 
EhCache 是一个比较成的Java缓存框架,最早从 hibernate 发展而来,是进程中的缓存系统,它提供了内存、磁盘文件存储,以及分布式存储方案等多种灵活的cache管理方案。
Sprging boot 对 Ehcache 的使用提供支持,所以在 spring boot 中只需要简单配置即可使用Ehcache实现数据缓存处理。
相关注解
@CacheConfig
用于标注在类上,可以存放该类中所有缓存的公有属性,比如设置缓存的名字
| 12
 3
 4
 5
 
 | @CacheConfig(cacheName = "users")
 public interface UserService(
 
 )
 
 | 
配置了该数据访问对象中返回的内容将存储于名为 users 的缓存对象中,我们也可以不使用该注解,直接通过 @cacheable 自己配置缓存集的名字来定要。
@Cacheable
应用到读取数据的方法上,即可缓存的方法,如查找方法,先从缓存中读取,如果没有再调用相应方法获取数据,然后把数据添加到缓存中。该注解主要有下面借个参数。
- value、cacheNames:两个等同的参数(cacheNames为 spring4新增,作为value的别名),用于指定缓存存储的集合名。由于spring4中新增了@CacheConfig,因此在spring3中原本必须有的value属性,也成了非必需项了。
- key:缓存对象存储在 Map 集合中的 key 值,非必需,缺省按照函数的所有参数组合作为key值,若自己配置需要使用 SpEl 表达式,比如 @Cacheable(key = "#p0")使用函数的第一个参数作为缓存的key值。
- condition:缓存对象的条件,非必需,也需要使用SpEl表达式,只有满足表达式条件的内容才会被缓存,比如:@Cacheable(key = "#p0", condition = "#p0.length() < 3"),表示只有当第一个参数的长度小于3的时候才会被缓存。
- unless:另外一个缓存条件参数,非必需,也需要使用SpEL表达式。它不同于 condition 参数的地方在于它的判断时机,该条件是在函数被调用之后才做判断,所以它可以通过对 result 进行判断。
- keyGenerator:用于指定 key 生成器,非必需。若需要指定一个自定义的 key 生成器,我们需要去实现 org.springframework.cache.interceptor.KeyGenerator接口,并使用该参数来指定。需要注意的是,该参数与key是互斥的。
- cacheManager:用于指定使用哪个缓存管理器,非必需。只有当有多个时才需要使用。
- cacheResolver:用于指定使用哪个缓存解析器,非必需。需要通过 org.springframework.cache.interceptor.CacheResolver接口来实现自己的缓存解析器,并用该参数指定。
@CachePut
应用到写数据的方法上,如 新增/修改方法(此放必须返回需要写到缓存中的数据),调用方法时会自动把相应的数据放入缓存,@CachePut的参数与@Cacheable类似。
| 12
 3
 4
 
 | @CachePut(value="users", key = "#user.id")public User add(User user) {
 
 }
 
 | 
@CacheEvict
应用到删除数据的方法上,如删除方法,调用方法时会从缓存中移除相应的数据
| 12
 
 | @cacheEvict(value = "uses", key="#id")void delete(final Integer id);
 
 | 
除了同@Cacheable一样的参数之外,@CacheEvict还有下面两个参数:
- allEntries:非必需,默认是false。当为 true 时,会移除所有数据。
- beforeInvocation:非必需,默认为false,会在调用方法之后移除数据。当为true时,会在调用方法之前移除数据。
@Caching
组合多个 Cache 注解使用,如
| 12
 3
 4
 5
 6
 7
 
 | @Caching(put = {
 @CachePut(value="user", key="#user.id")
 @CachePut(value="user", key="#user.username")
 @CachePut(value="user", key="#user.age")
 }
 )
 
 | 
环境配置
添加依赖
- ehcache
- spring-boot-starter-cache
pom.xml| 12
 3
 4
 5
 6
 7
 8
 
 | <dependency><groupId>net.sf.ehcache</groupId>
 <artifactId>ehcache</artifactId>
 </dependency>
 <dependency>
 <groupId>org.springframework.boot</groupId>
 <artifactId>spring-boot-starter-cache</artifactId>
 </dependency>
 
 | 
 
缓存配置
src/main/resources 目录下添加文件 ehcache.xml ,内容如下
ehcache.xml| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 
 | <ehcache name="mycache">
 
 
 
 <diskStore path="c:\java\cache" />
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 <defaultCache
 maxElementsInMemory="10000"
 eternal="false"
 timeToIdleSeconds="120"
 timeToLiveSeconds="120"
 maxElementsOnDisk="10000000"
 diskExpiryThreadIntervalSeconds="120"
 memoryStoreEvictionPolicy="LRU" />
 
 
 <cache
 name="users"
 eternal="false"
 maxElementsInMemory="100"
 overflowToDisk="false"
 diskPersistent="false"
 timeToIdleSeconds="0"
 timeToLiveSeconds="300"
 memoryStoreEvictionPolicy="LRU"/>
 </ehcache>
 
 | 
 
springboot 缓存配置
application.yml| 12
 3
 4
 5
 6
 7
 8
 9
 
 | 
 
 spring:
 
 cache:
 encache:
 config: classpath:ehcache.xml
 
 
 | 
 
启动缓存
在项目的入口类中,添加 @EnableCaching 注解,启动缓存
| 12
 3
 4
 5
 6
 
 | @SpringBootApplication@EnableCaching
 @MapperScan("com.xxx.dao")
 public calss Starter{
 SpringApplicatin.run(Starter.class);
 }
 
 | 
使用缓存
bean对象实现序列化
目标缓存对象需要实现序列化,如实体类
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 
 | package org.example.po;
 
 import lombok.Data;
 import org.hibernate.validator.constraints.Length;
 
 import javax.validation.constraints.NotBlank;
 import java.io.Serializable;
 
 
 
 
 @Data
 public class User implements Serializable {
 private Integer userId;
 
 @NotBlank(message = "用户名不能为空")
 private String userName;
 
 @NotBlank(message = "密码不能为空")
 @Length(min =6, max = 10, message="密码长度至少6位但不超过10位")
 private String userPwd;
 }
 
 | 
使用注解缓存实现
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
 100
 101
 102
 103
 104
 105
 106
 107
 108
 109
 110
 111
 112
 113
 
 | package org.example.service;
 import com.github.pagehelper.PageHelper;
 import com.github.pagehelper.PageInfo;
 import org.apache.commons.lang3.StringUtils;
 import org.example.dao.UserMapper;
 import org.example.po.User;
 import org.example.query.UserQuery;
 import org.example.util.AssertUtil;
 import org.springframework.cache.annotation.CacheEvict;
 import org.springframework.cache.annotation.CachePut;
 import org.springframework.cache.annotation.Cacheable;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Propagation;
 import org.springframework.transaction.annotation.Transactional;
 
 import javax.annotation.Resource;
 import java.util.List;
 import java.util.Map;
 
 
 
 
 @Service
 public class UserService {
 @Resource
 private UserMapper userMapper;
 
 
 
 
 
 
 public User findUserByName(String userName){
 
 return this.userMapper.findUserByName(userName);
 }
 
 
 
 
 
 
 @Cacheable(value="users", key = "#userId")
 public User findUserById(Integer userId){
 return this.userMapper.findUserById(userId);
 }
 
 
 
 
 
 
 @Cacheable(value="users", key="#userQuery.userName + '-' + #userQuery.pageNum + '-' + #userQuery.pageSize")
 public PageInfo<User> findUserByParam(UserQuery userQuery){
 
 PageHelper.startPage(userQuery.getPageNum(), userQuery.getPageSize());
 
 List<User> userList = this.userMapper.findUserByParam(userQuery);
 
 return new PageInfo<User>(userList);
 }
 
 
 
 
 
 
 @CachePut(value = "users", key = "#user.userId")
 public User addUser(User user) {
 
 AssertUtil.isTrue(user == null, "用户信息不能为空");
 AssertUtil.isTrue(StringUtils.isBlank(user.getUserName()),"用户姓名不能为空");
 AssertUtil.isTrue(StringUtils.isBlank(user.getUserPwd()),"密码不能为空");
 AssertUtil.isTrue(this.findUserByName(user.getUserName()) != null, "用户名不能重复");
 
 
 AssertUtil.isTrue(this.userMapper.addUser(user) < 1, "添加用户失败");
 
 return user;
 }
 
 
 
 
 
 @Transactional(propagation = Propagation.REQUIRED)
 @CachePut(value = "users", key = "#user.userId")
 public User updateUser(User user){
 
 AssertUtil.isTrue(user == null, "用户信息不能为空");
 AssertUtil.isTrue(user.getUserId() == null,"用户数据异常");
 AssertUtil.isTrue(StringUtils.isBlank(user.getUserName()),"用户姓名不能为空");
 AssertUtil.isTrue(StringUtils.isBlank(user.getUserPwd()),"密码不能为空");
 User checkUser = this.userMapper.findUserByName(user.getUserName());
 AssertUtil.isTrue(checkUser != null && !checkUser.getUserId().equals(user.getUserId()), "用户名已存在");
 
 
 
 AssertUtil.isTrue(this.userMapper.updateUser(user) < 1, "修改用户失败");
 return user;
 }
 
 
 
 
 
 @CacheEvict(value = "users", key = "#userId")
 public void deleteUserById(Integer userId){
 AssertUtil.isTrue( userId == null ||this.userMapper.findUserById(userId) == null, "用户不存在");
 AssertUtil.isTrue(this.userMapper.deleteUserById(userId) < 1, "删除用户失败");
 }
 }
 
 |