在实际项目中,用到缓存的地方很多,缓存有多种实现方式,当下比较火的如Redis。今天我要讲的是另一种缓存 Ehcache。随着Redis的火热程度不断加深,Ehcache慢慢没落,但是还是有用到的地方。接下来直接进入代码实战
在pom文件引入两个坐标。分别是springboot的缓存和ehcache的缓存
<!-- Spring Boot 缓存支持启动器 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-cache</artifactId>
</dependency>
<!-- Ehcache 坐标 -->
<dependency>
<groupId>net.sf.ehcache</groupId>
<artifactId>ehcache</artifactId>
<version>2.9.1</version>
</dependency>
编写实体类
@Data
public class Dept implements Serializable {
private Long deptNo;
private String deptName;
}
编写dao
public interface DeptMapper {
List<Dept> list();
Integer updateDept(Long deptNo);
}
编写mapper.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.zhao.dao.DeptMapper">
<resultMap id="BaseResultMap" type="com.zhao.entity.Dept">
<id property="deptNo" column="deptno"/>
<result column="dname" property="deptName"/>
</resultMap>
<delete id="updateDept" parameterType="Long">
delete from dept WHERE deptno = #{deptNo}
</delete>
<select id="list" resultMap="BaseResultMap">
SELECT
deptno,
dname
FROM
dept
</select>
</mapper>
编写service
public interface DeptService {
List<Dept> list();
Integer updateDept(Long deptNo);
}
编写serviceImpl
@Service
public class DeptServiceImpl implements DeptService {
@Autowired
private DeptMapper deptMapper;
@Override
public List<Dept> list() {
return deptMapper.list();
}
@Override
public Integer updateDept(Long deptNo) {
return deptMapper.updateDept(deptNo);
}
}
编写controller
@RestController
public class DeptController {
@Autowired
private DeptService deptService;
@Autowired
private CacheManager cacheManager;
@GetMapping("/list")
public List<Dept> list(){
return deptService.list();
}
@RequestMapping("/removeCache")
public void removeCache(){
cacheManager.getCache("deptCache").clear();
}
@PostMapping("/update/{deptNo}")
public Integer update(@PathVariable("deptNo") String deptNo){
return deptService.updateDept(Long.parseLong(deptNo));
}
}
接下来开始引入Ehcache的注解
在dao上添加注解
@CacheConfig 表示这个接口要做成缓存
@Cacheable(cacheNames =“deptCache” )
查询的缓存注解 Cacheable 缓存的名字 deptCache
@CacheEvict(cacheNames =“deptCache”,allEntries = true,beforeInvocation = true)
新增,修改,删除用的缓存注解 CacheEvict
allEntries:true。表示 新增修改删除的时候,清除所有的缓存
beforeInvocation :true 表示 新增修改删除的时候,是否清除缓存
@CacheConfig
public interface DeptMapper {
@Cacheable(cacheNames ="deptCache" )
List<Dept> list();
@CacheEvict(cacheNames ="deptCache",allEntries = true,beforeInvocation = true)
Integer updateDept(Long deptNo);
}
启动类上添加注解
@EnableCaching 加这个注解 说明缓存开启了
@SpringBootApplication
@MapperScan("com.zhao.dao")
@EnableCaching
public class SpringbootEhcacheApplication {
public static void main(String[] args) {
SpringApplication.run(SpringbootEhcacheApplication.class, args);
}
下面最重要的两步 ehcache.xml和application.yaml文件的编写
name=“deptCache” 要和接口上的cacheName相同,不然会提示找不到
<?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"/>
<!-- <defaultCache-->
<!-- eternal="false" -->
<!-- maxElementsInMemory="900"<!–缓存的最大数目–>-->
<!-- overflowToDisk="false" <!–内存不足时,是否启用磁盘缓存,如果为true则表示启动磁盘来存储,如果为false则表示不启动磁盘–>-->
<!-- diskPersistent="false"-->
<!-- timeToIdleSeconds="0" <!–当缓存的内容闲置多少时间销毁–>-->
<!-- timeToLiveSeconds="60" <!–当缓存存活多少时间销毁(单位是秒,如果我们想设置2分钟的缓存存活时间,那么这个值我们需要设置120)–>-->
<!-- memoryStoreEvictionPolicy="LRU" /> <!–自动销毁策略–>-->
<!-- 这里的 users 缓存空间是为了下面的 demo 做准备 -->
<cache
name="deptCache"
eternal="false"
maxElementsInMemory="200"
overflowToDisk="false"
diskPersistent="false"
timeToIdleSeconds="0"
timeToLiveSeconds="120"
memoryStoreEvictionPolicy="LRU" />
</ehcache>
<!--<diskStore>==========当内存缓存中对象数量超过maxElementsInMemory时,将缓存对象写到磁盘缓存中(需对象实现序列化接口) -->
<!--<diskStore path="">==用来配置磁盘缓存使用的物理路径,Ehcache磁盘缓存使用的文件后缀名是*.data和*.index -->
<!--name=================缓存名称,cache的唯一标识(ehcache会把这个cache放到HashMap里) -->
<!--maxElementsOnDisk====磁盘缓存中最多可以存放的元素数量,0表示无穷大 -->
<!--maxElementsInMemory==内存缓存中最多可以存放的元素数量,若放入Cache中的元素超过这个数值,则有以下两种情况 -->
<!--1)若overflowToDisk=true,则会将Cache中多出的元素放入磁盘文件中 -->
<!--2)若overflowToDisk=false,则根据memoryStoreEvictionPolicy策略替换Cache中原有的元素 -->
<!--eternal==============缓存中对象是否永久有效,即是否永驻内存,true时将忽略timeToIdleSeconds和timeToLiveSeconds -->
<!--timeToIdleSeconds====缓存数据在失效前的允许闲置时间(单位:秒),仅当eternal=false时使用,默认值是0表示可闲置时间无穷大,此为可选属性 -->
<!--即访问这个cache中元素的最大间隔时间,若超过这个时间没有访问此Cache中的某个元素,那么此元素将被从Cache中清除 -->
<!--timeToLiveSeconds====缓存数据在失效前的允许存活时间(单位:秒),仅当eternal=false时使用,默认值是0表示可存活时间无穷大 -->
<!--即Cache中的某元素从创建到清楚的生存时间,也就是说从创建开始计时,当超过这个时间时,此元素将从Cache中清除 -->
<!--overflowToDisk=======内存不足时,是否启用磁盘缓存(即内存中对象数量达到maxElementsInMemory时,Ehcache会将对象写到磁盘中) -->
<!--会根据标签中path值查找对应的属性值,写入磁盘的文件会放在path文件夹下,文件的名称是cache的名称,后缀名是data -->
<!--diskPersistent=======是否持久化磁盘缓存,当这个属性的值为true时,系统在初始化时会在磁盘中查找文件名为cache名称,后缀名为index的文件 -->
<!--这个文件中存放了已经持久化在磁盘中的cache的index,找到后会把cache加载到内存 -->
<!--要想把cache真正持久化到磁盘,写程序时注意执行net.sf.ehcache.Cache.put(Element element)后要调用flush()方法 -->
<!--diskExpiryThreadIntervalSeconds==磁盘缓存的清理线程运行间隔,默认是120秒 -->
<!--diskSpoolBufferSizeMB============设置DiskStore(磁盘缓存)的缓存区大小,默认是30MB -->
<!--memoryStoreEvictionPolicy========内存存储与释放策略,即达到maxElementsInMemory限制时,Ehcache会根据指定策略清理内存 -->
<!--共有三种策略,分别为LRU(Least Recently Used 最近最少使用)、LFU(Less Frequently Used最不常用的)、FIFO(first in first out先进先出) -->
application.yaml
cache:
type: ehcache
ehcache:
config: classpath:ehcache.xml
到此为止,代码编写完毕,要用的话,照着修改即可