分布式缓存Ehcache整合

        EhCache是一个比较成熟的Java缓存框架,最早从hibernate发展而来,是进程中的缓存 系统,它提供了用内存,磁盘文件存储,以及分布式存储方式等多种灵活的cache管理方案,快速简单。
       Spring Boot对Ehcache的使用提供支持,所以在Spring Boot中只需简单配置即可使用Ehcache实现数据缓存处理。
一、Spring Cache相关注解说明

        SpringBoot缓存实现内部使用SpringCache实现缓存控制,这里集成Ehcache实际上是对SpringCache抽象的其中-种实现,这里在使用Ehcache实现缓存控制时相关注解说明如下:

1、@CacheConfig

用于标注在类上,可以存放该类中所有缓存的公有属性,比如设置缓存的名字。

@CacheConfig( cacheNames ="users")
public interface UserService {.....}

       配置了该数据访问对象中返回的内容将存储于名为users的缓存对象中,我们也可以不使用该注解,直接通过@Cacheable自己配置缓存集的名字来定义。

2、 @Cacheable

        应用到读取数据的方法.上,即可缓存的方法,如查找方法,先从缓存中读取,如果没有再调用相应方法获取数据,然后把数
据添加到缓存中。
该注解主要有下面几个参数:
value、 cacheNames :两个等同的参数( cacheNames为Spring4新增,作为value的别名),用于指定缓存存储的集合名。由于Spring 4中新增了@CacheConfig,因此在Spring了中原本必须有的value属性,也成为非必需项了。
key:缓存对象存储在Map集合中的key值,非必需,缺省按照函数的所有参数组合作为key值,若自己配置需使用SpEL表达式,比如: @Cacheable(key = “#p0”) :使用函数第一个 参数作为缓存的key值,更多关于SpEL表达式的详细内容可参考官方文档。
●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接口来实现自己的缓存解析器,并用该参数指定。


@Cacheable(value = “user" ,key=“#id")
User selectUserById(final Integer id);

3、@CachePut

       应用到写数据的方法上,如新增/修改方法,调用方法时会自动把相应的数据放入缓存,@CachePut 的参数与@Cacheable类似,示例如下:

@CachePut(value = "user", key = " #user.id")
public User save(User user) {
	users. add(user);
	return user;
}

4、@CacheEvict

应用到移除数据的方法上,如删除方法,调用方法时会从缓存中移除相应的数据,示例如下:

@CacheEvict(value = "user", key = "#id")
void delete(final Integer id);

除了同@Cacheable一样的参数之外, @CacheEvict 还有下面两个参数:
       ●allEntries :非必需,默认为false。当为true时,会移除所有数据
       ●beforelnvocation :非必需,默认为false, 会在调用方法之后移除数据。当为true时,会在调用方法之前移除数据。

5、@Caching

组合多个Cache注解使用。示例:

@Caching(
	put={
		@CachePut(value = "user", key = "#user .id" ),
		@Cacheput(value = "user", key = "#user . username"),
		@Cachefut(value = "user", key = "#user.age")
	}

将id -> user ; username -> user ; age -> user进行缓存。

二、配置环境
1、pom.xml依赖添加
<!-- Ehcache-->
	<dependency>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-cache</artifactId>
	</dependency>
	<dependency>
		<groupId>net.sf.ehcache</groupId>
		<artifactId>ehcache</artifactId>
	</dependency>

2、ehcache.xml文件添加

src/main/resources目录下添加ehcache.xml文件,内容如下:

<ehcache name= "mycache">
<!--
如果不使用磁盘存储,只需要将diskStore注释掉即可;
如果使用,需要在ehcache.xml文件中的ehcahce元素下的定义一个diskStore元素并指定其path属性.
-->
<diskStore path="C:\java\cache"/>
<!--
	name :缓存名称。
	maxElementsInMemory :缓存最大数目
	maxElementsOnDisk :硬盘最大缓存个数。
	eternal:对象是否永久有效,-但设置了,timeout将不起作用。
	overflowToDisk :是否保存到磁盘,当系统宕机时
	timeToIdleSeconds :设置对象在失效前的允许闲置时间(单位:秒)。
		仅当eternal=false对象不是永久有效时使用,可选属性,默认值是0,表示可闲置时间无穷大。
	timeToliveSeconds:设置射象在失效前允许存活时间(单位:秒)。
		最大时间介于创建时间和失效时间之间。
		仅当eternal=false对象不是永久有效时使用,默认是0,也就是对象存活时间无穷大。
	diskPersistent:是否缓存虚拟机重启期数据
		Whether the disk store persists between restarts of the Virtual Machine.
	The default value is false.
		diskSpoolBufferSizeMB:这个参数设置DiskStore (磁盘缓存)的缓存区大小。
			默认是30MB。每个Cache都应该有自己的一个缓冲区。
		diskExpiryThreadIntervalSeconds:磁盘失效线程运行时间间隔,默认是120秒。
		memoryStoreEvictionPolicy:当达到maxElements InMemory限制时,会根据指定的策略去清理内存
			默认策略是LRU (最近最少使用)。你可以设置为FIFO (先进先出)或是LFU (较少使用)。
		clearonFlush:内存数量最大时是否清除。
		memoryStoreEvictionPolicy:
			可选策略有:
				LRU (最近最少使用,默认策略)
					Least Recently Used,最近最少使用的。
				FIFO (先进先出)
					First in First out, 这个是大家最熟的,先进先出。
				LFU(汇最少访问次数)
					Less Frequently Used, 就是例子中使用的策略,就是一直以来最少 被使用的。
					缓存的元素有一个时间戳,当缓存容量满了,而又需要腾出地方来缓存新的元素的时候,那么现有缓存元素中时间戳离当前时间最远的元素将被清出缓存。
-->


		<defaultCache
			maxElementsInMemory="10000"
			eternal="false"
			timeToIdleSeconds="120"
			timeToLiveSeconds="120"
			maxElementsOnDisk= "10000000"
			diskExpiryThreadIntervalSeconds="120"
			memoryStoreEvictionPolicy="LRU">
		</defaultCache>
		<cache
			name="users "
			eternal="false"
			maxElementsInMemory="100"
			overflowToDisk="false"
			diskPersistent="false"
			timeToIdleSeconds="0"
			timeToLiveSeconds="300"
			memoryStoreEvictionPolicy= "LRU"/>
		</ehcache>

3、application.yml缓存配置
spring:
	datasource:
		type: com.mchange.V2.c3p0.ComboPooledDataSource
		driver-class-name: com.mysql.cj.jdbc.Driver
		url: jdbc :mysql://127.0.0.1:3306/dai_pao?useUnicode=true&characterEncoding=utf8&serverTimezone=GMT%2B8
		username: root
		password: 123456
	devtools:
		restart :
			enabled: true
			#设置重启的目录,添加目录的文件需要restart
			additional-paths: src/main/java
			#解决项目自动重新编译后接口报404的问题
			poll-interval: 3000
			quiet-period: 1000
		## Ehcache缓存配置
	cache:
		ehcache:
			config: classpath: ehcache.xml

4、启动缓存

在Starter启动入口类中,添加@EnableCaching注解,启动缓存

@SpringBootApplication 
@EnableCaching
@MapperScan("com.xxx.dao")
public class Starter {
	public static void main(String[] args) {
		SpringAppl ication.run(Starter.class);
	}
}

三、缓存实现

这里以UserService的方法为例:

1、用户详情查询缓存

//通过用户ID查询用户信息,添加到缓存
    @GetMapping("user/ids/{user_id}")
    @Cacheable(value="users",key = "#user_id")
    public MyUser queryUserByIds(@PathVariable String user_id){
        return userService.queryUserByIds(user_id);
    }
    

       

2、用户列表查询缓存
@Cacheable(value = "users",key="#userQuery.userName+'-'+#userQuery.pageNum+'-'+#userQuery.pageSize")
public PageInfo<User> queryUserByParams(UserQuery userQuery){
 	PageHelper.startPage(userQuery.getPageNum(),userQuery.getPageSize());
 	return new PageInfo<User>(userMapper.selectByParams(userQuery));
}
3、⽤户更新 & 删除缓存
@CacheEvict(value = "users",key="#user.id")
public void updateUser(User user) {
 	AssertUtil.isTrue(StringUtils.isBlank(user.getUserName()), "⽤户名不能为空!");
 	AssertUtil.isTrue(StringUtils.isBlank(user.getUserPwd()),"⽤户密码不能为空!");
 	User temp = userMapper.queryUserByUserName(user.getUserName());
 	AssertUtil.isTrue(null != temp && !(temp.getId().equals(user.getId())), "该⽤户已存在!");
 	AssertUtil.isTrue(userMapper.update(user)<1,"⽤户记录添加失败!");
}


@CacheEvict(value = "users",allEntries=true)
public void deleteUser(Integer userId){
 	AssertUtil.isTrue(null == userId || null == userMapper.queryById(userId),"待删除记录不存在!");
 	AssertUtil.isTrue(userMapper.delete(userId)<1,"⽤户删除失败!");
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
本实例的环境 eclipse + maven + spring + ehcache + junit EhCache 是一个纯Java的进程内缓存框架,具有快速、精干等特点,是Hibernate中默认的CacheProvider。Ehcache是一种广泛使用的开 源Java分布式缓存。主要面向通用缓存,Java EE和轻量级容器。它具有内存和磁盘存储,缓存加载器,缓存扩展,缓存异常处理程序,一个gzip缓存servlet过滤器,支持REST和SOAP api等特点。 优点: 1. 快速 2. 简单 3. 多种缓存策略 4. 缓存数据有两级:内存和磁盘,因此无需担心容量问题 5. 缓存数据会在虚拟机重启的过程中写入磁盘 6. 可以通过RMI、可插入API等方式进行分布式缓存 7. 具有缓存缓存管理器的侦听接口 8. 支持多缓存管理器实例,以及一个实例的多个缓存区域 9. 提供Hibernate的缓存实现 缺点: 1. 使用磁盘Cache的时候非常占用磁盘空间:这是因为DiskCache的算法简单,该算法简单也导致Cache的效率非常高。它只是对元素直接追加存储。因此搜索元素的时候非常的快。如果使用DiskCache的,在很频繁的应用中,很快磁盘会满。 2. 不能保证数据的安全:当突然kill掉java的时候,可能会产生冲突,EhCache的解决方法是如果文件冲突了,则重建cache。这对于Cache 数据需要保存的时候可能不利。当然,Cache只是简单的加速,而不能保证数据的安全。如果想保证数据的存储安全,可以使用Bekeley DB Java Edition版本。这是个嵌入式数据库。可以确保存储安全和空间的利用率。 EhCache分布式缓存有传统的RMI,1.5版的JGroups,1.6版的JMS。分布式缓存主要解决集群环境中不同的服务器间的数据的同步问题。 使用Spring的AOP进行整合,可以灵活的对方法的返回结果对象进行缓存

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值