一、springboot缓存简介
在 Spring Boot中,通过@EnableCaching注解自动化配置合适的缓存管理器(CacheManager),Spring Boot根据下面的顺序去侦测缓存提供者:
* Generic
* JCache (JSR-107)
* EhCache 2.x
* Hazelcast
* Infinispan
* Redis
* Guava
* Simple
关于 Spring Boot 的缓存机制:
高速缓存抽象不提供实际存储,并且依赖于由org.springframework.cache.Cache和org.springframework.cache.CacheManager接口实现的抽象。 Spring Boot根据实现自动配置合适的CacheManager,只要缓存支持通过@EnableCaching注释启用即可。
二、实例
1、application.properyies
server.port=8850
#cache 多个用逗号分开
spring.cache.cache-names=userCache
spring.cache.jcache.config=classpath:ehcache.xml
# datasource
spring.datasource.name=ehcahcetest
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://127.0.0.1:3312/ehcahcetest
spring.datasource.username=root
spring.datasource.password=123456
# mybatis
mybatis.mapper-locations=classpath:mybatis/mapper/*.xml
mybatis.config-location=classpath:mybatis/mybatis-config.xml
#mybatis.type-aliases-package=
2、springboot启动类
1 @SpringBootApplication 2 @ComponentScan(basePackages="com.ehcache")//扫描组件 3 @EnableCaching 4 public class EhcacheTestApplication { 5 6 public static void main(String[] args) { 7 SpringApplication.run(EhcacheTestApplication.class, args); 8 } 9 }
3、加了缓存注解的service
1 @Service 2 public class UserService { 3 4 @Autowired 5 private UserDao userDao; 6 7 @CacheEvict(key="'user_'+#uid", value="userCache") 8 public void del(String uid) { 9 // TODO Auto-generated method stub 10 userDao.del(uid); 11 } 12 13 @CachePut(key="'user_'+#user.uid", value="userCache") 14 public void update(User user) { 15 userDao.update(user); 16 } 17 18 @Cacheable(key="'user_'+#uid",value="userCache") 19 public User getUserById(String uid){ 20 System.err.println("缓存里没有"+uid+",所以这边没有走缓存,从数据库拿数据"); 21 return userDao.findById(uid); 22 23 } 24 25 @CacheEvict(key="'user'",value="userCache") 26 public String save(User user) { 27 // TODO Auto-generated method stub 28 return userDao.save(user); 29 } 30 31 32 }
4、ehcache.xml
1 <?xml version="1.0" encoding="UTF-8"?> 2 <ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 3 xsi:noNamespaceSchemaLocation="http://ehcache.org/ehcache.xsd"> 4 <diskStore path="java.io.tmpdir" /> 5 6 <!-- 配置提供者 1、peerDiscovery,提供者方式,有两种方式:自动发现(automatic)、手动配置(manual) 2、rmiUrls,手动方式时提供者的地址,多个的话用|隔开 --> 7 <cacheManagerPeerProviderFactory 8 class="net.sf.ehcache.distribution.RMICacheManagerPeerProviderFactory" 9 properties="peerDiscovery=manual,rmiUrls=//127.0.0.1:40002/userCache" /> 10 <!-- <cacheManagerPeerProviderFactory 11 class="net.sf.ehcache.distribution.RMICacheManagerPeerProviderFactory" 12 properties="peerDiscovery=automatic, multicastGroupAddress=230.0.0.1, multicastGroupPort=4446,timeToLive=255"/> 13 --> 14 <!-- 配置监听器 1、hostName 主机地址 2、port 端口 3、socketTimeoutMillis socket子模块的超时时间,默认是2000ms --> 15 <cacheManagerPeerListenerFactory 16 class="net.sf.ehcache.distribution.RMICacheManagerPeerListenerFactory" 17 properties="hostName=127.0.0.1, port=40001, socketTimeoutMillis=2000" /> 18 <!-- <cacheManagerPeerListenerFactory 19 class="net.sf.ehcache.distribution.RMICacheManagerPeerListenerFactory"/> --> 20 21 22 <defaultCache eternal="false" maxElementsInMemory="1000" 23 overflowToDisk="false" diskPersistent="false" timeToIdleSeconds="0" 24 timeToLiveSeconds="600" memoryStoreEvictionPolicy="LRU" /> 25 26 <cache 27 name="userCache" 28 maxElementsInMemory="1000" 29 eternal="false" 30 timeToIdleSeconds="300" 31 timeToLiveSeconds="300" 32 overflowToDisk="false" 33 memoryStoreEvictionPolicy="LRU"> 34 35 36 <!-- 配置缓存事件监听器 replicateAsynchronously 操作是否异步,默认值为true. replicatePuts 添加操作是否同步到集群内的其他缓存,默认为true. 37 replicateUpdates 更新操作是否同步到集群内的其他缓存,默认为true. replicateUpdatesViaCopy 更新之后的对象是否复制到集群中的其他缓存(true); 38 replicateRemovals 删除操作是否同步到集群内的其他缓存,默认为true. --> 39 <cacheEventListenerFactory 40 class="net.sf.ehcache.distribution.RMICacheReplicatorFactory" 41 properties=" 42 replicateAsynchronously=true, 43 replicatePuts=true, 44 replicateUpdates=true, 45 replicateUpdatesViaCopy=true, 46 replicateRemovals=true " /> 47 48 49 <!-- 初始化缓存,以及自动设置 --> 50 <bootstrapCacheLoaderFactory 51 class="net.sf.ehcache.distribution.RMIBootstrapCacheLoaderFactory" 52 properties="bootstrapAsynchronously=true" /> 53 54 </cache> 55 56 </ehcache>
5、OperationController.java 测试类
1 package com.ehcache.controller; 2 3 import java.util.ArrayList; 4 import java.util.HashMap; 5 import java.util.List; 6 import java.util.Map; 7 8 import javax.servlet.http.HttpServletRequest; 9 10 import org.springframework.beans.factory.annotation.Autowired; 11 import org.springframework.cache.annotation.CachePut; 12 import org.springframework.cache.annotation.Cacheable; 13 import org.springframework.web.bind.annotation.RequestMapping; 14 import org.springframework.web.bind.annotation.RequestMethod; 15 import org.springframework.web.bind.annotation.RequestParam; 16 import org.springframework.web.bind.annotation.ResponseBody; 17 import org.springframework.web.bind.annotation.RestController; 18 19 import com.ehcache.entity.User; 20 import com.ehcache.factory.CacheManagerFactory; 21 import com.ehcache.factory.UserFactory; 22 import com.ehcache.service.UserService; 23 import com.google.gson.Gson; 24 25 import net.sf.ehcache.Element; 26 27 28 @RestController 29 @RequestMapping("/o") 30 public class OperationController { 31 32 @Autowired 33 private UserService userService; 34 35 Gson gson = new Gson(); 36 37 CacheManagerFactory cmf = CacheManagerFactory.getInstance(); 38 39 @RequestMapping(value = "/test", method = RequestMethod.GET) 40 public String test(HttpServletRequest request){ 41 42 // 保存一个新用户 43 String uid = userService.save(UserFactory.createUser()); 44 User user = userService.getUserById(uid); 45 user.setUsername("xiaoli"); 46 userService.update(user); 47 48 // 查询该用户 49 System.out.println(gson.toJson(user, User.class)); 50 /*System.out.println(); 51 // 再查询该用户 52 User user = userService.getUserById(uid); 53 System.out.println(gson.toJson(user, User.class)); 54 System.out.println(); 55 // 更新该用户 56 userService.update(user); 57 // 更新好了再查询该用户 58 System.out.println(gson.toJson(userService.getUserById(uid), User.class)); 59 System.out.println(); 60 // 删除该用户 61 userService.del(uid); 62 System.out.println(); 63 // 删除好了再查询该用户 64 System.out.println(gson.toJson(userService.getUserById(uid), User.class));*/ 65 66 67 // 再保存一个新用户 68 // String uid1 = userService.save(UserFactory.createUser()); 69 70 71 return uid; 72 } 73 74 75 @RequestMapping(value = "/test1", method = RequestMethod.GET) 76 public String test1(HttpServletRequest request,String key){ 77 78 String res = ""; 79 80 Element element = cmf.getElement("userCache", "map"); 81 if(element == null){ 82 Map<String, String> map = new HashMap<String, String>(); 83 map.put(key, key); 84 cmf.setElement("userCache", new Element("map", map)); 85 }else{ 86 Map<String, String> map = (Map<String, String>) element.getValue(); 87 res = map.get(key); 88 if(res == null){ 89 map.put(key, key); 90 // 多次测试发现,存在同名Element是,重复put的是无法复制的,因此当遇到两个节点同步不上的时候,先remove后put。 91 cmf.getCache("userCache").remove("map"); 92 cmf.setElement("userCache", new Element("map", map)); 93 res = "0;null"; 94 } 95 } 96 return res; 97 } 98 99 100 }