龙空技术网

阿里面试官:Spring Boot中如何使用cache缓存?

马士兵老师 3084

前言:

目前姐妹们对“csscache”大约比较关怀,各位老铁们都想要了解一些“csscache”的相关文章。那么小编也在网络上收集了一些关于“csscache””的相关资讯,希望姐妹们能喜欢,兄弟们一起来学习一下吧!

前言

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

  工程结构代码编写

  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=10010spring.application.name=springboot-cachespring.cache.type=ehcachespring.cache.ehcache.config=classpath:/ehcache.xml

  ehcache.xml

<?xml version="1.0" encoding="UTF-8"?><ehcache xmlns:xsi="; xsi:noNamespaceSchemaLocation="; 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")@Datapublic 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;    }}
效果演示

  李四

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

  

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

  王五

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

  

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

  

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

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

  

  首次调用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

原文链接:

标签: #csscache