转自 https://my.oschina.net/sdlvzg/blog/1594834
EhCache 是一个纯Java的进程内缓存框架,具有快速、精干等特点,是Hibernate中默认的CacheProvider。
Ehcache是一种广泛使用的开源Java分布式缓存。主要面向通用缓存,Java EE和轻量级容器。它具有内存和磁盘存储,缓存加载器,缓存扩展,缓存异常处理程序,一个gzip缓存servlet过滤器,支持REST和SOAP api等特点。
本文档主要通过案例介绍一下,如何在SpringBoot中集中Ehcache,使用Ehcache。
使用的SpringBoot版本为1.5.9.RELEASE,Ehcache版本2.10.4,还使用MyBatis用于数据存取,并集成了mybatis-plus用于简化数据存取。
首先需要通过IDEA创建一个Maven项目。
一、代码
创建数据表,使用数据库为MySql
CREATE TABLE `tasklog` (
`id` varchar(32) NOT NULL DEFAULT '' COMMENT '主键',
`taskId` varchar(32) DEFAULT NULL COMMENT '任务ID',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
pom.xml
把项目的pom.xml修改为以下内容
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.lvgang</groupId>
<artifactId>springboot-ehcache</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>springboot-ehcache</name>
<description>Demo project for Spring Boot</description>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.9.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- spring-boot mybatis依赖-->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>1.3.1</version>
</dependency>
<!-- mysql 数据库驱动. -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<!-- mybatis-plus begin -->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatisplus-spring-boot-starter</artifactId>
<version>1.0.5</version>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus</artifactId>
<version>2.1.8</version>
</dependency>
<!-- Spring boot Cache-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-cache</artifactId>
</dependency>
<!-- Spring boot EhCache-->
<dependency>
<groupId>net.sf.ehcache</groupId>
<artifactId>ehcache</artifactId>
</dependency>
<!-- Spring boot单元测试. -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
application.properties
########################################################
###datasource
########################################################
spring.datasource.url = jdbc:mysql://xxx.xxx.xxx.xxx:3306/taskdb
spring.datasource.username = root
spring.datasource.password = xxxxxxx
spring.datasource.driverClassName = com.mysql.jdbc.Driver
spring.datasource.max-active=20
spring.datasource.max-idle=8
spring.datasource.min-idle=8
spring.datasource.initial-size=10
########################################################
###mybatis-plus
########################################################
mybatis-plus.mapper-locations=classpath:org/lvgang/springbootehcache/mapper/*Mapper.xml
########################################################
###log
########################################################
logging.level.org.lvgang.springbootehcache.mapper=debug
编写Bean
package org.lvgang.springbootehcache.bean;
import java.io.Serializable;
public class Tasklog implements Serializable{
public String id;
public String taskId;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getTaskId() {
return taskId;
}
public void setTaskId(String taskId) {
this.taskId = taskId;
}
@Override
public String toString() {
return "Tasklog{" +
"id='" + id + '\'' +
", taskId='" + taskId + '\'' +
'}';
}
}
编写Mapper
package org.lvgang.springbootehcache.mapper;
import com.baomidou.mybatisplus.mapper.BaseMapper;
import org.lvgang.springbootehcache.bean.Tasklog;
public interface TaskLogMapper extends BaseMapper<Tasklog> {
}
mapper继承了mybatisplus用于简化数据存储编码
编写Service
package org.lvgang.springbootehcache.service;
import net.sf.ehcache.Cache;
import net.sf.ehcache.Element;
import org.lvgang.springbootehcache.bean.Tasklog;
import org.lvgang.springbootehcache.mapper.TaskLogMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.CachePut;
import org.springframework.stereotype.Service;
import java.util.Map;
/**
* 测试服务层
*/
@Service
public class TaskLogService {
@Autowired private TaskLogMapper taskLogMapper;
@Autowired private net.sf.ehcache.CacheManager cacheManager;
/**
* 缓存的key
*/
public static final String CACHE_KEY = "taskLog";
/**
* 添加tasklog
* @param tasklog
* @return
*/
@CachePut(value = CACHE_KEY, key = "#tasklog.id")
public Tasklog create(Tasklog tasklog){
System.out.println("CREATE");
System.err.println (tasklog);
taskLogMapper.insert(tasklog);
return tasklog;
}
/**
* 根据ID获取Tasklog
* @param id
* @return
*/
@Cacheable(value = CACHE_KEY, key = "#id")
public Tasklog findById(String id){
System.out.println("FINDBYID");
System.out.println("ID:"+id);
return taskLogMapper.selectById(id);
}
/**
* 根据ID更新Tasklog
* @param tasklog
* @return
*/
@CachePut(value = CACHE_KEY, key = "#tasklog.id")
public Tasklog update(Tasklog tasklog){
System.out.println("UPDATE");
System.out.println (tasklog);
taskLogMapper.updateById(tasklog);
return tasklog;
}
/**
* 根据ID删除Tasklog
* @param id
*/
@CacheEvict(value = CACHE_KEY, key = "#id")
public void delete(String id){
System.out.println("DELETE");
System.out.println("ID:"+id);
taskLogMapper.deleteById(id);
}
public void getCache(){
System.out.println("GETCACHE");
Cache cache = cacheManager.getCache(CACHE_KEY);
Map<Object,Element> elements = cache.getAll(cache.getKeys());
if(elements!=null){
for (Map.Entry<Object, Element> entry : elements.entrySet()) {
System.out.println("key= " + entry.getValue().getObjectKey());
System.out.println("value= " + entry.getValue().getObjectValue());
}
}
}
// @Cacheable、@CachePut、@CacheEvict 注释介绍
// @Cacheable 的作用 主要针对方法配置,能够根据方法的请求参数对其结果进行缓存
// @CachePut 的作用 主要针对方法配置,能够根据方法的请求参数对其结果进行缓存,和 @Cacheable 不同的是,它每次都会触发真实方法的调用
// @CachEvict 的作用 主要针对方法配置,能够根据一定的条件对缓存进行清空
}
编写Controller
package org.lvgang.springbootehcache.controller;
import org.lvgang.springbootehcache.bean.Tasklog;
import org.lvgang.springbootehcache.service.TaskLogService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.UUID;
/**
* 测试控制层
*/
@RestController
@RequestMapping("/taskLog")
public class TaskLogController {
@Autowired
private TaskLogService taskLogService;
/**
* 根据ID查询
* @return
*/
@RequestMapping("/get")
public Tasklog getById(String id) {
return taskLogService.findById(id);
}
/**
* 添加数据
* @return
*/
@RequestMapping("/add")
public String add() {
Tasklog bean = new Tasklog();
bean.setId(UUID.randomUUID().toString().replace("-", ""));
bean.setTaskId(bean.getId());
taskLogService.create(bean);
return "插入成功";
}
/**
* 更新数据
* @return
*/
@RequestMapping("/update")
public String update(String id) {
Tasklog bean = new Tasklog();
bean.setId(id);
bean.setTaskId(UUID.randomUUID().toString().replace("-", ""));
bean = taskLogService.update(bean);
if (bean != null) {
return "更新成功";
} else {
return "更新失败";
}
}
/**
* 删除数据
* @return
*/
@RequestMapping("/romove")
public String romove(String id) {
taskLogService.delete(id);
return "删除成功";
}
/**
* 控制台输出缓存
* @param id
*/
@RequestMapping("/getCache")
public void getCache(String id) {
taskLogService.getCache();
}
}
SpringBoot Ehcache配置类
package org.lvgang.springbootehcache;
import net.sf.ehcache.config.CacheConfiguration;
import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.CachingConfigurer;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.cache.ehcache.EhCacheCacheManager;
import org.springframework.cache.interceptor.CacheErrorHandler;
import org.springframework.cache.interceptor.CacheResolver;
import org.springframework.cache.interceptor.KeyGenerator;
import org.springframework.cache.interceptor.SimpleKeyGenerator;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* EhCache配置文件,可以替代ehcache.xml 文件
*/
@Configuration
@EnableCaching
public class EhCacheConfiguration implements CachingConfigurer {
@Bean(destroyMethod="shutdown")
public net.sf.ehcache.CacheManager ehCacheManager() {
CacheConfiguration cacheConfiguration = new CacheConfiguration();
cacheConfiguration.setName("taskLog");
cacheConfiguration.setMemoryStoreEvictionPolicy("LRU");
cacheConfiguration.setMaxEntriesLocalHeap(1000);
net.sf.ehcache.config.Configuration config = new net.sf.ehcache.config.Configuration();
//可以创建多个cacheConfiguration,都添加到Config中
config.addCache(cacheConfiguration);
return net.sf.ehcache.CacheManager.newInstance(config);
}
@Bean
@Override
public CacheManager cacheManager() {
return new EhCacheCacheManager(ehCacheManager());
}
@Bean
@Override
public KeyGenerator keyGenerator() {
return new SimpleKeyGenerator();
}
@Override
public CacheResolver cacheResolver() { return null; }
@Override
public CacheErrorHandler errorHandler() {
return null;
}
}
SpringBoot 启动类
package org.lvgang.springbootehcache;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication // 等价于@Configuration,@EnableAutoConfiguration和@ComponentScan
@MapperScan("org.lvgang.springbootehcache.mapper") //mybatis mapper搜索路径
public class SpringbootEhcacheApplication {
public static void main(String[] args) {
SpringApplication.run(SpringbootEhcacheApplication.class, args);
}
}
二、测试
在执行以下测试时,必须先需要在数据库表中增加一条ID为9f829afb589542ffb4b7bff33345af2f的数据。
查询
在浏览器按顺序执行以下URL:
http://localhost:8080/taskLog/get?id=9f829afb589542ffb4b7bff33345af2f
http://localhost:8080/taskLog/get?id=9f829afb589542ffb4b7bff33345af2f
http://localhost:8080/taskLog/getCache
控制台输出:
FINDBYID
ID:9f829afb589542ffb4b7bff33345af2f
2018-01-17 23:20:30.493 DEBUG 6164 --- [nio-8080-exec-1] o.l.s.mapper.TaskLogMapper.selectById : ==> Preparing: SELECT id,taskId FROM tasklog WHERE id=?
2018-01-17 23:20:30.528 DEBUG 6164 --- [nio-8080-exec-1] o.l.s.mapper.TaskLogMapper.selectById : ==> Parameters: 9f829afb589542ffb4b7bff33345af2f(String)
2018-01-17 23:20:30.605 DEBUG 6164 --- [nio-8080-exec-1] o.l.s.mapper.TaskLogMapper.selectById : <== Total: 1
GETCACHE
key= 9f829afb589542ffb4b7bff33345af2f
value= Tasklog{id='9f829afb589542ffb4b7bff33345af2f', taskId='9f829afb589542ffb4b7bff33345af2f'}
添加
在浏览器按顺序执行以下URL:
http://localhost:8080/taskLog/add
http://localhost:8080/taskLog/getCache
控制台输出:
CREATE
Tasklog{id='e91f0a90531d4512a7665a52ca6cbbab', taskId='e91f0a90531d4512a7665a52ca6cbbab'}
2018-01-17 23:23:46.986 DEBUG 9808 --- [nio-8080-exec-3] o.l.s.mapper.TaskLogMapper.insert : ==> Preparing: INSERT INTO tasklog ( id, taskId ) VALUES ( ?, ? )
2018-01-17 23:23:47.030 DEBUG 9808 --- [nio-8080-exec-3] o.l.s.mapper.TaskLogMapper.insert : ==> Parameters: e91f0a90531d4512a7665a52ca6cbbab(String), e91f0a90531d4512a7665a52ca6cbbab(String)
2018-01-17 23:23:47.143 DEBUG 9808 --- [nio-8080-exec-3] o.l.s.mapper.TaskLogMapper.insert : <== Updates: 1
GETCACHE
key= e91f0a90531d4512a7665a52ca6cbbab
value= Tasklog{id='e91f0a90531d4512a7665a52ca6cbbab', taskId='e91f0a90531d4512a7665a52ca6cbbab'}
修改
在浏览器按顺序执行以下URL:
http://localhost:8080/taskLog/update?id=9f829afb589542ffb4b7bff33345af2f
http://localhost:8080/taskLog/getCache
控制台输出:
UPDATE
Tasklog{id='9f829afb589542ffb4b7bff33345af2f', taskId='c34c6e2ba06c46a3b267269dc871a0aa'}
2018-01-17 23:25:28.644 DEBUG 3856 --- [nio-8080-exec-1] o.l.s.mapper.TaskLogMapper.updateById : ==> Preparing: UPDATE tasklog SET taskId=? WHERE id=?
2018-01-17 23:25:28.675 DEBUG 3856 --- [nio-8080-exec-1] o.l.s.mapper.TaskLogMapper.updateById : ==> Parameters: c34c6e2ba06c46a3b267269dc871a0aa(String), 9f829afb589542ffb4b7bff33345af2f(String)
2018-01-17 23:25:28.784 DEBUG 3856 --- [nio-8080-exec-1] o.l.s.mapper.TaskLogMapper.updateById : <== Updates: 1
GETCACHE
key= 9f829afb589542ffb4b7bff33345af2f
value= Tasklog{id='9f829afb589542ffb4b7bff33345af2f', taskId='c34c6e2ba06c46a3b267269dc871a0aa'}
删除
http://localhost:8080/taskLog/get?id=9f829afb589542ffb4b7bff33345af2f
http://localhost:8080/taskLog/getCache
http://localhost:8080/taskLog/remove?id=9f829afb589542ffb4b7bff33345af2f
http://localhost:8080/taskLog/getCache
控制台输出:
FINDBYID
ID:9f829afb589542ffb4b7bff33345af2f
2018-01-17 23:27:39.535 DEBUG 9896 --- [nio-8080-exec-1] o.l.s.mapper.TaskLogMapper.selectById : ==> Preparing: SELECT id,taskId FROM tasklog WHERE id=?
2018-01-17 23:27:39.565 DEBUG 9896 --- [nio-8080-exec-1] o.l.s.mapper.TaskLogMapper.selectById : ==> Parameters: 9f829afb589542ffb4b7bff33345af2f(String)
2018-01-17 23:27:39.633 DEBUG 9896 --- [nio-8080-exec-1] o.l.s.mapper.TaskLogMapper.selectById : <== Total: 1
GETCACHE
key= 9f829afb589542ffb4b7bff33345af2f
value= Tasklog{id='9f829afb589542ffb4b7bff33345af2f', taskId='c34c6e2ba06c46a3b267269dc871a0aa'}
DELETE
ID:9f829afb589542ffb4b7bff33345af2f
2018-01-17 23:28:09.138 DEBUG 9896 --- [nio-8080-exec-5] o.l.s.mapper.TaskLogMapper.deleteById : ==> Preparing: DELETE FROM tasklog WHERE id=?
2018-01-17 23:28:09.138 DEBUG 9896 --- [nio-8080-exec-5] o.l.s.mapper.TaskLogMapper.deleteById : ==> Parameters: 9f829afb589542ffb4b7bff33345af2f(String)
2018-01-17 23:28:09.247 DEBUG 9896 --- [nio-8080-exec-5] o.l.s.mapper.TaskLogMapper.deleteById : <== Updates: 1
GETCACHE
三、修改为ehcache.xml配置文件
上面的例子使用了Java类配置ehcache,下面介绍如何更改为ehcache.xml配置文件
创建ehcache.xml配置文件
在resources文件夹中,创建ehcache.xml配置文件
<?xml version="1.0" encoding="UTF-8"?>
<ehcache>
<diskStore path="java.io.tmpdir"/>
<!--
name:缓存名称。
maxElementsInMemory:缓存最大个数。
eternal:对象是否永久有效,一但设置了,timeout将不起作用。
timeToIdleSeconds:设置对象在失效前的允许闲置时间(单位:秒)。仅当eternal=false对象不是永久有效时使用,可选属性,默认值是0,也就是可闲置时间无穷大。
timeToLiveSeconds:设置对象在失效前允许存活时间(单位:秒)。最大时间介于创建时间和失效时间之间。仅当eternal=false对象不是永久有效时使用,默认是0.,也就是对象存活时间无穷大。
overflowToDisk:当内存中对象数量达到maxElementsInMemory时,Ehcache将会对象写到磁盘中。
diskSpoolBufferSizeMB:这个参数设置DiskStore(磁盘缓存)的缓存区大小。默认是30MB。每个Cache都应该有自己的一个缓冲区。
maxElementsOnDisk:硬盘最大缓存个数。
diskPersistent:是否缓存虚拟机重启期数据 Whether the disk store persists between restarts of the Virtual Machine. The default value is false.
diskExpiryThreadIntervalSeconds:磁盘失效线程运行时间间隔,默认是120秒。
memoryStoreEvictionPolicy:当达到maxElementsInMemory限制时,Ehcache将会根据指定的策略去清理内存。默认策略是LRU(最近最少使用)。你可以设置为FIFO(先进先出)或是LFU(较少使用)。
clearOnFlush:内存数量最大时是否清除。
-->
<defaultCache
maxElementsInMemory="10000"
eternal="false"
timeToIdleSeconds="120"
timeToLiveSeconds="120"
overflowToDisk="true"
maxElementsOnDisk="10000000"
diskPersistent="false"
diskExpiryThreadIntervalSeconds="120"
memoryStoreEvictionPolicy="LRU"
/>
<cache name="taskLog" maxElementsInMemory="1000"/>
</ehcache>
配置ehcache配置文件位置
在application.properties增加以下内容,可以让springboot可以找到配置文件
########################################################
###ehcache
########################################################
spring.cache.ehcache.config=classpath:ehcache.xml
删除EhCacheConfiguration
把org.lvgang.springbootehcache包中的EhCacheConfiguration删除,因为使用了ehcache.xml配置文件,就不需要Java的EhCache配置文件
在SpringBoot的启动声明缓存启动
package org.lvgang.springbootehcache;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication // 等价于@Configuration,@EnableAutoConfiguration和@ComponentScan
@MapperScan("org.lvgang.springbootehcache.mapper") //mybatis mapper搜索路径
@EnableCaching //缓存启动
public class SpringbootEhcacheApplication {
public static void main(String[] args) {
SpringApplication.run(SpringbootEhcacheApplication.class, args);
}
}
通过四步可以实现由Java的EhCache配置文件更改为ehcache.xml配置文件在SpringBoot集中EhCache。