添加依赖
首先在pom.xml添加必要依赖
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-cacheartifactId>
dependency>
<dependency>
<groupId>net.sf.ehcachegroupId>
<artifactId>ehcacheartifactId>
dependency>
添加依赖时会提示net.sf.ehcache已经集成在springboot里边,但是不加程序又提示找不到net.sf.ehcache.CacheManager的class文件。该问题需要朋友们解决一下。
开启缓存
在Spring Boot环境下,使用缓存技术只需在项目中导入相关缓存技术的依赖包,并在配置类上使用@EnableCaching开启缓存即可。
在启动类添加注解@EnableCaching
@SpringBootApplication
@EnableCaching
public class MyTestApplication {
private static Logger log=LoggerFactory.getLogger(MyTestApplication .class);
public static void main(String[] args) {
SpringApplication.run(MyTestApplication .class, args);
log.info("服务启动成功");
}
}
新建数据库表
CREATE TABLE `paraconfig` (
`paraId` int(11) NOT NULL AUTO_INCREMENT COMMENT '参数id',
`paraName` varchar(20) NOT NULL COMMENT '参数名称',
`paraCode` varchar(50) NOT NULL COMMENT '参数值',
`paraDesc` varchar(100) DEFAULT NULL COMMENT '参数描述',
`status` enum('有效','无效') NOT NULL COMMENT '参数状态',
PRIMARY KEY (`paraId`),
UNIQUE KEY `paraName` (`paraName`) USING BTREE,
KEY `paraStatus` (`status`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8
新建实体类
import java.io.Serializable;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
@Entity
public class Paraconfig implements Serializable{
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue
private Integer paraid;
private String paraname;
private String paracode;
private String paradesc;
private String status;
public Integer getParaid() {
return paraid;
}
public void setParaid(Integer paraid) {
this.paraid = paraid;
}
public String getParaname() {
return paraname;
}
public void setParaname(String paraname) {
this.paraname = paraname;
}
public String getParacode() {
return paracode;
}
public void setParacode(String paracode) {
this.paracode = paracode;
}
public String getParadesc() {
return paradesc;
}
public void setParadesc(String paradesc) {
this.paradesc = paradesc;
}
public String getStatus() {
return status;
}
public void setStatus(String status) {
this.status = status;
}
@Override
public String toString() {
return "Paraconfig [paraid=" + paraid + ", paraname=" + paraname + ", paracode=" + paracode + ", paradesc="
+ paradesc + ", status=" + status + "]";
}
}
新建dao查询数据库接口
import java.util.List;
import org.springframework.data.jpa.repository.JpaRepository;
import com.xx.model.Paraconfig;
public interface IParaConfigDao extends JpaRepository<Paraconfig,Integer>{
public Paraconfig findByParaid(Integer id);
public Paraconfig findByParaname(String name);
public List findByStatus(String status);
}
新建数据库操作服务及实现
import java.util.List;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.CachePut;
import org.springframework.cache.annotation.Cacheable;
import com.xx.model.Paraconfig;
public interface IParaConfigService {
@CacheEvict(value = "SystemCache")
public int deletePara(int id);
@CachePut(value = "SystemCache", key = "#para.paraid")
public Paraconfig addPara(Paraconfig para);
@Cacheable(value = "SystemCache", key = "#id")
public Paraconfig findOne(int id);
@Cacheable(value = "SystemCache", key = "#name")
public Paraconfig findByName(String name);
@Cacheable(value = "SystemCache")
public List findAll();
@Cacheable(value = "SystemCache")
public List findByStatus(String status);
@CachePut(value = "SystemCache", key = "#para.paraid")
public Paraconfig updataPara(Paraconfig para);
}
import java.util.List;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.xx.DatabaseSservice.paraConfig.IParaConfigService;
import com.xx.dao.IParaConfigDao;
import com.xx.model.Paraconfig;
@Service
public class ParaConfigServiceImpl implements IParaConfigService{
private Logger log=LoggerFactory.getLogger(ParaConfigServiceImpl.class);
@Autowired
private IParaConfigDao dao;
@Override
public int deletePara(int id) {
log.info("o==||======>删除系统参数入参ID="+id);
int result=0;
try{
dao.deleteById(id);
result=0;
}catch(Exception e){
e.printStackTrace();
result=-1;
log.info("删除系统参数异常");
}
return result;
}
@Override
public Paraconfig addPara(Paraconfig para) {
log.info("o==||=====>新增系统参数入参:"+para.toString());
return doExecute("addPara",null,para);
}
@Override
public Paraconfig findOne(int id) {
log.info("o==||=====>id查找系统参数入参:id="+id);
return doExecute("findOne",String.valueOf(id),null);
}
@Override
public Paraconfig findByName(String name) {
log.info("o==||=====>name查找系统参数入参:name="+name);
return doExecute("findByName",name,null);
}
@Override
public List findAll() {
log.info("o==||=====>查找All系统参数");
return doExecutePage("findAll",null);
}
@Override
public List findByStatus(String status) {
log.info("o==||=====>status查找系统参数:status="+status);
return doExecutePage("findByStatus",status);
}
@Override
public Paraconfig updataPara(Paraconfig para) {
log.info("o==||=====>更新系统参数入参:"+para.toString());
return doExecute("updataPara",null,para);
}
public Paraconfig doExecute(String type,String arg,Paraconfig req){
Paraconfig resp=new Paraconfig();
try{
switch(type){
case "addPara" : ;
case "updataPara" : resp=dao.save(req);break;
case "findOne" : resp=dao.findByParaid(Integer.valueOf(arg));break;
case "findByName" : resp=dao.findByParaname(arg);break;
}
}catch(Exception e){
e.printStackTrace();
String Emsg = null;
switch(type){
case "addPara" : Emsg="新增系统参数异常";break;
case "updataPara" : Emsg="更新系统参数异常";break;
case "findOne" : Emsg="根据ID查找系统参数异常";break;
case "findByName" : Emsg="根据name查找系统参数异常";break;
}
log.info(Emsg+e.getMessage());
}finally{
log.info("查找系统参数返回:"+(resp==null?null:resp.toString()));
}
return resp;
}
public List doExecutePage(String type,String arg){
List resp = null;
try{
switch(type){
case "findAll" : resp=dao.findAll();break;
case "findByStatus" : resp=dao.findByStatus(arg);break;
}
}catch(Exception e){
e.printStackTrace();
}finally{
log.info("查找系统参数返回:"+(resp==null?null:resp.toString()));
}
return resp;
}
}
新建测试controller
@PostMapping("/testCachefindOne")
public void testCachefindOne(){
Paraconfig para=null;
try{
para=paraConfigService.findOne(1);
}catch(Exception e){
e.printStackTrace();
log.info("异常:"+e.getMessage());
}
}
测试
使用postman请求。查看控制执行数据库操作日志。
第一次请求缓存没有则有日志打印,第二次请求缓存有数据则不会打印日志。
测试没有问题说明缓存自动存储已经没问题了,接下来就是怎么取缓存及添加自定义的缓存了。
添加ehcache配置文件
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="http://ehcache.org/ehcache.xsd"
updateCheck="false">
<diskStore path="java.io.tmpdir/Tmp_EhCache" />
<defaultCache
eternal="false"
maxElementsInMemory="1000"
overflowToDisk="false"
diskPersistent="false"
timeToIdleSeconds="0"
timeToLiveSeconds="100"
memoryStoreEvictionPolicy="LRU" />
<cache
name="SystemCache"
eternal="false"
maxElementsInMemory="100"
overflowToDisk="false"
diskPersistent="false"
timeToIdleSeconds="0"
timeToLiveSeconds="30"
memoryStoreEvictionPolicy="LRU" />
ehcache>
配置文件详解
(1).diskStore: 为缓存路径,ehcache分为内存和磁盘两级,此属性定义磁盘的缓存位置。参数解释如下:
user.home – 用户主目录
user.dir – 用户当前工作目录
java.io.tmpdir – 默认临时文件路径
(2).defaultCache:默认缓存策略,当ehcache找不到定义的缓存时,则使用这个缓存策略。只能定义一个。
(3).cache:自定缓存策略,为自定义的缓存策略。参数解释如下:
cache元素的属性:
name:缓存名称
maxElementsInMemory:内存中最大缓存对象数
maxElementsOnDisk:硬盘中最大缓存对象数,若是0表示无穷大
eternal:true表示对象永不过期,此时会忽略timeToIdleSeconds和timeToLiveSeconds属性,默认为false
overflowToDisk:true表示当内存缓存的对象数目达到了maxElementsInMemory界限后,会把溢出的对象写到硬盘缓存中。注意:如果缓存的对象要写入到硬盘中的话,则该对象必须实现了Serializable接口才行。
diskSpoolBufferSizeMB:磁盘缓存区大小,默认为30MB。每个Cache都应该有自己的一个缓存区。
diskPersistent:是否缓存虚拟机重启期数据
diskExpiryThreadIntervalSeconds:磁盘失效线程运行时间间隔,默认为120秒
timeToIdleSeconds: 设定允许对象处于空闲状态的最长时间,以秒为单位。当对象自从最近一次被访问后,如果处于空闲状态的时间超过了timeToIdleSeconds属性值,这个对象就会过期,EHCache将把它从缓存中清空。只有当eternal属性为false,该属性才有效。如果该属性值为0,则表示对象可以无限期地处于空闲状态
timeToLiveSeconds:设定对象允许存在于缓存中的最长时间,以秒为单位。当对象自从被存放到缓存中后,如果处于缓存中的时间超过了 timeToLiveSeconds属性值,这个对象就会过期,EHCache将把它从缓存中清除。只有当eternal属性为false,该属性才有效。如果该属性值为0,则表示对象可以无限期地存在于缓存中。timeToLiveSeconds必须大于timeToIdleSeconds属性,才有意义
memoryStoreEvictionPolicy:当达到maxElementsInMemory限制时,Ehcache将会根据指定的策略去清理内存。可选策略有:LRU(最近最少使用,默认策略)、FIFO(先进先出)、LFU(最少访问次数)。
将配置文件放在src/main/resources下(或其他路径,需要配置路径)。
新建ApplicationContextUtils实现ApplicationContextAware接口
import org.springframework.beans.BeansException;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;
@Component
@EnableAutoConfiguration
public class ApplicationContextUtils implements ApplicationContextAware{
public static ApplicationContext applicationContext=null;//可写成单利模式,这里为了方便
@Override
public void setApplicationContext(ApplicationContext arg0) throws BeansException {
applicationContext=arg0;
System.out.println("设置ApplicationContext成功!");
}
}
缓存自定义存取
@PostMapping("/testCachefindOne")
public void testCachefindOne(){
Paraconfig para=null;
try{
para=paraConfigService.findOne(1);
EhCacheCacheManager cacheCacheManager=ApplicationContextUtils.applicationContext.getBean(EhCacheCacheManager.class);
//获取Cache
Cache cache=cacheCacheManager.getCache("SystemCache");
cache.put("Hello-key", "Hello-value");
System.out.println("缓存名:"+cache.getName());
System.out.println("缓存Hello-key:"+cache.get("Hello-key", String.class));
System.out.println("缓存SYSDATE:"+cache.get("SYSDATE",Paraconfig.class));
}catch(Exception e){
e.printStackTrace();
log.info("异常:"+e.getMessage());
}
}
小结:
1.@CachePut表示缓存新添加的数据或者更新的数据到缓存中,两个参数value表示缓存的名称为SystemCache,key表示缓存的key为#id 的数据,#id为方法参数 。
2.@CacheEvict表示从缓存SystemCache中删除key为id的数据
3.@Cacheable表示添加数据到缓存中,缓存名称为SystemCache,缓存key为#para.paraid的数据。
注意: @CachePut总会执行SQL操作,其主要用在更新或插入数据时。
@Cacheable主要用在查询数据库时,缓存有则不查数据库。