spring boot cache 缓存实战

spring boot 集成了常用的cache实现

  • Generic
  • JCache (JSR-107) (EhCache 3, Hazelcast, Infinispan, and others)
  • EhCache 2.x
  • Hazelcast
  • Infinispan
  • Couchbase
  • Redis
  • Caffeine
  • Simple
    具体可看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
addressList = new ArrayList
(); 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 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 cacheMap = new ConcurrentHashMap();

    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 get(Object key, Class type) {
        logger.info("get cache1...");
        return (T) cacheMap.get(key + "");
    }

    @Override
    public  T get(Object key, Callable 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 缓存实战)