SpringBoot集成cache缓存的实现

前言

  日常开发中,缓存是解决数据库压力的一种方案,通常用于频繁查询的数据,例如新闻中的热点新闻,本文记录springboot中使用cache缓存。

  官方文档介绍:https://docs.spring.io/spring-boot/docs/2.1.0.RELEASE/reference/htmlsingle/#boot-features-caching-provider-generic

工程结构

代码编写

  pom引入依赖,引入cache缓存,数据库使用mysql,ORM框架用jpa

<!--添加springdata-cache依赖 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-cache</artifactId>
        </dependency>

        <!-- 引入ehcache支持 -->
        <dependency>
            <groupId>net.sf.ehcache</groupId>
            <artifactId>ehcache</artifactId>
        </dependency>

        <!--添加springdata-jpa依赖 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>

        <!--添加MySQL驱动依赖 -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>

  配置文件

server.port=10010
spring.application.name=springboot-cache

spring.cache.type=ehcache
spring.cache.ehcache.config=classpath:/ehcache.xml

  ehcache.xml

<?xml version="1.0" encoding="UTF-8"?>
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="http://ehcache.org/ehcache.xsd" updateCheck="false">

    <!-- 磁盘缓存位置 -->
    <diskStore path="java.io.tmpdir"/>

    <!-- maxEntriesLocalHeap:堆内存中最大缓存对象数,0没有限制 -->
    <!-- maxElementsInMemory: 在内存中缓存的element的最大数目。-->
    <!-- eternal:elements是否永久有效,如果为true,timeouts将被忽略,element将永不过期 -->
    <!-- timeToIdleSeconds:发呆秒数,发呆期间未访问缓存立即过期,当eternal为false时,这个属性才有效,0为不限制 -->
    <!-- timeToLiveSeconds:总存活秒数,当eternal为false时,这个属性才有效,0为不限制 -->
    <!-- overflowToDisk: 如果内存中数据超过内存限制,是否要缓存到磁盘上 -->
    <!-- statistics:是否收集统计信息。如果需要监控缓存使用情况,应该打开这个选项。默认为关闭(统计会影响性能)。设置statistics="true"开启统计 -->

    <!--
        默认缓存
        无过期时间,但 600 秒内无人访问缓存立即过期
    -->
    <defaultCache
            maxElementsInMemory="1000"
            eternal="false"
            timeToIdleSeconds="600"
            timeToLiveSeconds="0"
            overflowToDisk="false">
    </defaultCache>

    <!--
        xx业务缓存
        在有效的 120 秒内,如果连续 60 秒未访问缓存,则缓存失效。
        就算有访问,也只会存活 120 秒。
    -->
    <cache name="myCache"
           maxElementsInMemory="1000"
           eternal="false"
           timeToIdleSeconds="120"
           timeToLiveSeconds="0"
           overflowToDisk="false">
    </cache>
</ehcache>

  先写一个套tb_user表的CRUD代码

@RestController
@RequestMapping("/tbUser/")
public class TbUserController {
    @Autowired
    private TbUserService tbUserService;

    //方便测试暂时改成GetMapping
    @GetMapping("list")
//    @PostMapping("list")
    public List<TbUser> list(TbUser entityVo) {
        return tbUserService.list(entityVo);
    }

    @GetMapping("get/{id}")
    public TbUser get(@PathVariable("id")Integer id) {
        return tbUserService.get(id);
    }

    //方便测试暂时改成GetMapping
    @GetMapping("save")
//    @PostMapping("save")
    public TbUser save(TbUser entityVo) {
        return tbUserService.save(entityVo);
    }

    @GetMapping("delete/{id}")
    public Integer delete( @PathVariable("id") Integer id) {
        return tbUserService.delete(id);
    }
}

  opjo实体类要实现序列化

@Entity
@Table(name = "tb_user")
@Data
public class TbUser implements Serializable {
    @Id
    @GeneratedValue(strategy= GenerationType.IDENTITY)
    private Integer id;//表id

    private String username;//用户名

    private String password;//密码

    private Date created;//创建时间

    private Integer descriptionId;//关联详情id
}

  serviceImpl中,使用注解来开启缓存

@Service
@Transactional
@CacheConfig(cacheNames = {"myCache"})
public class TbUserServiceImpl implements TbUserService{

    @PersistenceContext
    private EntityManager em;

    @Autowired
    private TbUserRepository tbUserRepository;

    //@Cacheable缓存数据:key为userList,value为返回值List<TbUser>
    @Cacheable(key = "'userList'")
    @Override
    public List<TbUser> list(TbUser entityVo) {
        System.out.println("获取list用户列表缓存数据,"+new Date());
        return tbUserRepository.findAll(Example.of(entityVo));
    }

    //@Cacheable缓存数据:key为参数id,value为返回值TbUser
    @Cacheable(key = "#id")
    @Override
    public TbUser get(Integer id) {
        System.out.println("获取数据缓存,key:"+id);
        Optional<TbUser> optionalE = tbUserRepository.findById(id);
        if (!optionalE.isPresent()) {
            throw new RuntimeException("ID不存在!");
        }
        return optionalE.get();
    }

    //@CachePut缓存新增的或更新的数据到缓存,其中缓存的名称为people,数据的key是person的id
    @CachePut(key = "#entityVo.id")
    // @CacheEvict从缓存中删除key为参数userList的数据
    @CacheEvict(key = "'userList'")
    @Override
    public TbUser save(TbUser entityVo) {
        System.out.println("新增/更新缓存,key:"+entityVo.getId());
        //entityVo传啥存啥,会全部更新
        return tbUserRepository.save(entityVo);
    }

    //清空所有缓存
    @CacheEvict(allEntries=true)
    @Override
    public Integer delete(Integer id) {
        System.out.println("清空所有缓存");
        tbUserRepository.deleteById(id);
        return id;
    }
}

  效果演示

  http://localhost:10010/tbUser/save?id=2&username=李四

  调用save方法,key为2,value为当前tbUser对象的数据被缓存下来

  http://localhost:10010/tbUser/get/2

  当我们调用get方法时,直接获取缓存数据,控制台啥也不打印,连serviceImpl的get方法都不进去(可以打断点调试)

  http://localhost:10010/tbUser/save?id=2&username=王五

  当我们再次调用save方法更新username时,缓存数据也被更新

  http://localhost:10010/tbUser/get/2

  再次调用get接口,直接返回缓存数据,后台也是方法都不进去,啥也不打印

  http://localhost:10010/tbUser/delete/2

  调用delete接口,删除数据,同时删除缓存

  再次调用get接口,发现缓存数据被清除,查询数据库

  http://localhost:10010/tbUser/list

  首次调用list接口,key为userList的,value为用户集合数据被缓存下来,再次调用直接返回缓存数据

  当调用save接口,数据更新,删除key为userList的缓存,再次调用list时,重新查库并设置缓存

  我们配置了缓存发呆时间,当120秒内未使用该缓存,立即过期,一直用就会一直存在

  我们先同时访问两个接口list、get,list接口2分钟后再次访问,get接口不能超过2分钟是不是访问一下,结果如预期

  PS:原先使用了这个jar包,有报错

 <dependency>
      <groupId>org.ehcache</groupId>
      <artifactId>ehcache</artifactId>
      <version>3.8.1</version>
    </dependency> 

  后面改成用上面“代码编写”里pom中引的jnet.sf.ehcache下面的ar

后记

  缓存除了能缓解数据库压力,还能做用户登录状态控制,例如:用户登录成功后cookie中保存颁发的token令牌设置永不过期,缓存存活时间也设置永不过期,发呆时间设置1天,这样只有用户在1天内有访问缓存接口,那他就可以一直保留登录状态,直至有其他业务将token或者缓存清掉。

  springboot使用cache缓存暂时先记录到这,后续有空再进行补充。

代码开源

  代码已经开源、托管到我的GitHub、码云:

  GitHub:https://github.com/huanzi-qch/springBoot

  码云:https://gitee.com/huanzi-qch/springBoot

到此这篇关于SpringBoot集成cache缓存的实现的文章就介绍到这了,更多相关SpringBoot cache缓存内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

时间: 2021-06-10

springboot使用GuavaCache做简单缓存处理的方法

问题背景 实际项目碰到一个上游服务商接口有10秒的查询限制(同个账号). 项目中有一个需求是要实时统计一些数据,一个应用下可能有多个相同的账号.由于服务商接口的限制,当批量查询时,可能出现同一个账号第一次查询有数据,但第二次查询无数据的情况. 解决方案 基于以上问题,提出用缓存的过期时间来解决. 这时,可用Redis和Guava Cache来解决: 当批量查询时,同一个账号第一次查询有数据则缓存并设置过期时间10s, 后续查询时直接从缓存中取,没有再从服务商查询. 最终采用Guava Cache

Springboot使用cache缓存过程代码实例

1.pom.xml <!-- Ehcache 坐标 --> <dependency> <groupId>net.sf.ehcache</groupId> <artifactId>ehcache</artifactId> </dependency> 2.ehcache.xml <?xml version="1.0" encoding="UTF-8"?> <ehcach

Springboot整合GuavaCache缓存过程解析

这篇文章主要介绍了springboot整合GuavaCache缓存过程解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 Guava Cache是一种本地缓存机制,之所以叫本地缓存,是因为它不会把缓存数据放到外部文件或者其他服务器上,而是存放到了应用内存中. Guava Cache的优点是:简单.强大.轻量级. GuavaCache适用场景: 1.某些接口或者键值会被查询多次以上: 2.愿意使用或牺牲一些内存空间来提升访问或者计算速度: 3.缓

SpringBoot中Shiro缓存使用Redis、Ehcache的方法

SpringBoot 中配置redis作为session 缓存器. 让shiro引用 本文是建立在你是使用这shiro基础之上的补充内容 第一种:Redis缓存,将数据存储到redis 并且开启session存入redis中. 引入pom <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifac

springboot集成spring cache缓存示例代码

本文介绍如何在springboot中使用默认的spring cache, 声明式缓存 Spring 定义 CacheManager 和 Cache 接口用来统一不同的缓存技术.例如 JCache. EhCache. Hazelcast. Guava. Redis 等.在使用 Spring 集成 Cache 的时候,我们需要注册实现的 CacheManager 的 Bean. Spring Boot 为我们自动配置了 JcacheCacheConfiguration. EhCacheCacheCo

详解springboot整合ehcache实现缓存机制

EhCache 是一个纯Java的进程内缓存框架,具有快速.精干等特点,是Hibernate中默认的CacheProvider. ehcache提供了多种缓存策略,主要分为内存和磁盘两级,所以无需担心容量问题. spring-boot是一个快速的集成框架,其设计目的是用来简化新Spring应用的初始搭建以及开发过程.该框架使用了特定的方式来进行配置,从而使开发人员不再需要定义样板化的配置. 由于spring-boot无需任何样板化的配置文件,所以spring-boot集成一些其他框架时会有略微的

SpringBoot2 整合Ehcache组件,轻量级缓存管理的原理解析

本文源码:GitHub·点这里 || GitEE·点这里 一.Ehcache缓存简介 1.基础简介 EhCache是一个纯Java的进程内缓存框架,具有快速.上手简单等特点,是Hibernate中默认的缓存提供方. 2.Hibernate缓存 Hibernate三级缓存机制简介: 一级缓存:基于Session级别分配一块缓存空间,缓存访问的对象信息.Session关闭后会自动清除缓存. 二级缓存:是SessionFactory对象缓存,可以被创建出的多个 Session 对象共享,二级缓存默认是

详解SpringBoot缓存的实例代码(EhCache 2.x 篇)

本篇介绍了SpringBoot 缓存(EhCache 2.x 篇),分享给大家,具体如下: SpringBoot 缓存 在 spring Boot中,通过@EnableCaching注解自动化配置合适的缓存管理器(CacheManager),Spring Boot根据下面的顺序去侦测缓存提供者: Generic JCache (JSR-107) EhCache 2.x Hazelcast Infinispan Redis Guava Simple 关于 Spring Boot 的缓存机制: 高速

详解vuex 渐进式教程实例代码

vuex 渐进式教程,从入门级带你慢慢深入使用vuex. Vuex 是什么? Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式.它采用集中式存储管理应用的所有组件的状态, 并以相应 的规则保证状态以一种可预测的方式发生变化. vuex官网: vuex.vuejs.org/zh/guide/ 安装 安装vue-cli: cnpm install -g vue-cli vue init webpack vuex 安装vuex cnpm i vuex --save 1.初级使用方法 //

详解Springboot整合Dubbo之代码集成和发布

本文介绍了Springboot整合Dubbo之代码集成和发布,分享给大家,具体如下: 1. boot-dubbo-api相关 打开boot-dubbo-api项目,正在src/main/java下创建一个包,并创建你需要dubbo暴露的接口TestService.java,并创建一个实体类用于测试User.java.如下图所示: 创建文件和包结构 User.java package com.boot.domain; import lombok.Data; import java.io.Seria

IE 条件注释详解总结(附实例代码)

顾名思义,有条件注释使你能够根据条件(比如浏览器版本)显示代码块.尽管是非标准的,但是有条件注释对于其他所有浏览器作为常规注释出现,因此本质上是无害的.有条件注释在Windows上的IE5中首次出现,并且得到了Widnows浏览器所有后续版本的支持. IE的有条件注释及其有效,而且非常容易记住.主要的缺点是这些注释需要放在HTML页面中,而不是放在CSS中.这样,当你不需要这些东西,或者有所更改的时候,就需要维护很多的地方. 让我们据几个例子来看看吧-- 只有IE才能识别 因为只有IE5以上的版

SpringBoot Tomcat启动实例代码详解

废话不多了,具体内容如下所示: Application configuration class: @SpringBootApplication public class ServletInitializer extends SpringBootServletInitializer { @Override protected SpringApplicationBuilder configure(SpringApplicationBuilder application) { return appli

详解SpringBoot的三种缓存技术(Spring Cache、Layering Cache 框架、Alibaba JetCache 框架)

引言 ​前两天在写一个实时数据处理的项目,项目要求是 1s 要处理掉 1k 的数据,这时候显然光靠查数据库是不行的,技术选型的时候老大跟我提了一下使用 Layering-Cache 这个开源项目来做缓存框架. ​之间问了一下身边的小伙伴,似乎对这块了解不多.一般也就用用 Redis 来缓存,应该是很少用多级缓存框架来专门性的管理缓存吧. ​趁着这个机会,我多了解了一些关于 SpringBoot 中缓存的相关技术,于是有了这篇文章! 在项目性能需求比较高时,就不能单单依赖数据库访问来获取数据了,必

详解springboot+aop+Lua分布式限流的最佳实践

一.什么是限流?为什么要限流? 不知道大家有没有做过帝都的地铁,就是进地铁站都要排队的那种,为什么要这样摆长龙转圈圈?答案就是为了限流!因为一趟地铁的运力是有限的,一下挤进去太多人会造成站台的拥挤.列车的超载,存在一定的安全隐患.同理,我们的程序也是一样,它处理请求的能力也是有限的,一旦请求多到超出它的处理极限就会崩溃.为了不出现最坏的崩溃情况,只能耽误一下大家进站的时间. 限流是保证系统高可用的重要手段!!! 由于互联网公司的流量巨大,系统上线会做一个流量峰值的评估,尤其是像各种秒杀促销活动,

详解SpringBoot 应用如何提高服务吞吐量

意外和明天不知道哪个先来.没有危机是最大的危机,满足现状是最大的陷阱. 背景 生产环境偶尔会有一些慢请求导致系统性能下降,吞吐量下降,下面介绍几种优化建议. 方案 1.undertow替换tomcat 电子商务类型网站大多都是短请求,一般响应时间都在100ms,这时可以将web容器从tomcat替换为undertow,下面介绍下步骤: 1.增加pom配置 <dependency> <groupid> org.springframework.boot </groupid>

详解SpringBoot Redis自适应配置(Cluster Standalone Sentinel)

核心代码段 提供一个JedisConnectionFactory  根据配置来判断 单点 集群 还是哨兵 @Bean @ConditionalOnMissingBean public JedisConnectionFactory jedisConnectionFactory() { JedisConnectionFactory factory = null; String[] split = node.split(","); Set<HostAndPort> nodes =