美文网首页
spring boot cache 缓存实战

spring boot cache 缓存实战

作者: 不会飞的birds | 来源:发表于2018-08-03 14:03 被阅读0次

    spring boot 集成了常用的cache实现

    ** 使用也极为简单。基本2个注解 **

    • @EnableCaching
    • @Cacheable

    基本使用

    • 工具 Eclipse STS


      2.png
      3.png
      4.png

    代码编写

    @SpringBootApplication
    @EnableCaching
    public class SpringDemoCacheApplication {
    
        public static void main(String[] args) {
            SpringApplication.run(SpringDemoCacheApplication.class, args);
        }
    }
    
    public class Address implements java.io.Serializable {
    
        private static final long serialVersionUID = 5287789368637836326L;
    
        public Address() {
        }
    
        private String sno;
        private String country;
        private String state;
        
        public Address(String sno, String country, String state) {
            this.sno = sno;
            this.country = country;
            this.state = state;
        }
    
        @Override
        public String toString() {
            return sno + "," + country + "," + state;
        }
    
        public String getSno() {
            return sno;
        }
        public void setSno(String sno) {
            this.sno = sno;
        }
        public String getCountry() {
            return country;
        }
        public void setCountry(String country) {
            this.country = country;
        }
        public String getState() {
            return state;
        }
        public void setState(String state) {
            this.state = state;
        }
    }
    
    @Component
    public class AddressService {`
        
        private static final Logger logger = LoggerFactory.getLogger(AddressService.class);
        
        private List<Address> addressList = new ArrayList<Address>();
    
        public AddressService() {
            init();
        }
        
        
        private void init() { //模拟数据
            addressList.add(new Address("10010", "China", "NJ"));
            addressList.add(new Address("10020", "China", "BJ"));
            addressList.add(new Address("10030", "China", "HZ"));
        }
    
        @Cacheable(value = "birds_cache2")
        public Address findAddress(String sno) {
            logger.info("----find----" + sno); 
            for (Address address : addressList) {
                if (sno.equals(address.getSno())) {
                    return address;
                }
            }
            return null;
        }
    
    }
    
    @Component
    public class CacheRunner implements CommandLineRunner { //测试
        
        private static final Logger logger = LoggerFactory.getLogger(CacheRunner.class);
    
        @Autowired
        private AddressService addressService;
     
        public CacheRunner() {
        }
    
        @Override
        public void run(String... args) throws Exception {
            logger.info(addressService + "");
            logger.info("" + addressService.findAddress("10010"));
            logger.info("" + addressService.findAddress("10020"));
            logger.info("" + addressService.findAddress("10030"));
            //后面3个打印 取缓存数据
            logger.info("" + addressService.findAddress("10010"));
            logger.info("" + addressService.findAddress("10020"));
            logger.info("" + addressService.findAddress("10030"));
            
    
        }
    
    }
    
    • 结果


      console1.png

    配合redis

    • 默认application.properties 如果没有配置 则使用最简单的 concurrent maps
    • 配置redis
    spring.redis.host = 192.168.2.20
    spring.redis.port = 6379
    
    
    spring.cache.cache-names=birds_cache2,cache2
    spring.cache.caffeine.spec=maximumSize=500,expireAfterAccess=8s 
    #如果有redis上面的caffeine缓存将失效,直接存储到redis中
    
    spring.cache.redis.time-to-live=8000
    
    
    • 结果


      redis-keys.png

      (测试时,修改了几次cache名)

    自定义key

    • 默认key是用 缓存名::参数值
    • 实现 org.springframework.cache.interceptor.KeyGenerator
    @Configuration
    @Component("birds_key_gen")
    public class CustomCacheKey implements KeyGenerator {
        
        private static final Logger logger = LoggerFactory.getLogger(CustomCacheKey.class);
    
        public CustomCacheKey() {
        }
    
        @Override
        public Object generate(Object target, Method method, Object... params) {
            logger.info("call CustomCacheKey:" + target.getClass().getSimpleName() + " " + method.getName() + " " + params[0]);
            StringBuilder sb = new StringBuilder();
            sb.append(target.getClass().getSimpleName())
                .append("_")
                .append(method.getName())
                .append("_")
                .append(params[0]);
            return sb.toString();
        }
    
    }
    
    
    • 修改service方法
        @Cacheable(value = "birds_cache_cuskey",keyGenerator = "birds_key_gen")
        public Address findAddress(String sno) {
            logger.info("----find----" + sno); 
            for (Address address : addressList) {
                if (sno.equals(address.getSno())) {
                    return address;
                }
            }
            return null;
        }
    
    • 运行后结果


      custom_key.png
      cus_key_list.png

    如何自定义自己的cache

    • 可以通过系统源码了解基本的

    • 基本的cache组件配置


      key_key_list.png
    • 自定义CacheManager

    @Component
    public class MyCacheManager implements CacheManager {
        
        @Autowired
        private MyCustomCache myCustomCache;
    
        public MyCacheManager() {
        }
    
        @Override
        public Cache getCache(String name) {
            System.err.println("====cache name====" + name);//如果有多个 需要通过 name获取对应的cache instance
            return myCustomCache; //直接返回,就一个Cache
        }
    
        @Override
        public Collection<String> getCacheNames() { //没有用上
            System.out.println("getCacheNames");
            return Arrays.asList(new String[] {"my_cache1","my_cache2"});
        }
    
    }
    
    
    • Cache实例
    @Component
    public class MyCustomCache implements Cache {
        
        private static final Logger logger = LoggerFactory.getLogger(MyCustomCache.class);
        static final ConcurrentHashMap<String, Object> cacheMap = new ConcurrentHashMap<String, Object>();
    
        public MyCustomCache() {
            logger.info("init cache...."); 
        }
    
        @Override
        public String getName() {
            return "";
        }
    
        @Override
        public Object getNativeCache() {
            return cacheMap;
        }
    
        @Override
        public ValueWrapper get(Object key) {
            Object obj = cacheMap.get(key + "");
            if (obj != null) {
                logger.info("hit cache:" + key);
                return new SimpleValueWrapper(obj);
            }
            return null;
        }
    
        @Override
        public <T> T get(Object key, Class<T> type) {
            logger.info("get cache1...");
            return (T) cacheMap.get(key + "");
        }
    
        @Override
        public <T> T get(Object key, Callable<T> valueLoader) {
            logger.info("get cache2...");
            return (T) cacheMap.get(key + "");
        }
    
        @Override
        public void put(Object key, Object value) {
            logger.info("put cache2...");
            cacheMap.put(key + "", value);
        }
    
        @Override
        public ValueWrapper putIfAbsent(Object key, Object value) {
            logger.info("putIfAbsent...");
            return null;
        }
    
        @Override
        public void evict(Object key) {
            cacheMap.remove(key);
        }
    
        @Override
        public void clear() {
        }
    
    }
    
    
    • 运行结果


      final.png

    总结

    • 自定义大部分情况下用不上,自带的基本够用

    • 自定义还需要实现过期功能

    • 项目最终结构


      final2.png

    (有问题,欢迎指出)

    相关文章

      网友评论

          本文标题:spring boot cache 缓存实战

          本文链接:https://www.haomeiwen.com/subject/qfmyvftx.html