spring boot cache 緩存實(shí)戰(zhàn)

spring boot 集成了常用的cache實(shí)現(xiàn)

** 使用也極為簡單。基本2個(gè)注解 **

  • @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() { //模擬數(shù)據(jù)
        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個(gè)打印 取緩存數(shù)據(jù)
        logger.info("" + addressService.findAddress("10010"));
        logger.info("" + addressService.findAddress("10020"));
        logger.info("" + addressService.findAddress("10030"));
        

    }

}
  • 結(jié)果


    console1.png

配合redis

  • 默認(rèn)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緩存將失效,直接存儲(chǔ)到redis中

spring.cache.redis.time-to-live=8000

  • 結(jié)果


    redis-keys.png

    (測試時(shí),修改了幾次cache名)

自定義key

  • 默認(rèn)key是用 緩存名::參數(shù)值
  • 實(shí)現(xiàn) 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;
    }
  • 運(yùn)行后結(jié)果


    custom_key.png

    cus_key_list.png

如何自定義自己的cache

  • 可以通過系統(tǒng)源碼了解基本的

  • 基本的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);//如果有多個(gè) 需要通過 name獲取對(duì)應(yīng)的cache instance
        return myCustomCache; //直接返回,就一個(gè)Cache
    }

    @Override
    public Collection<String> getCacheNames() { //沒有用上
        System.out.println("getCacheNames");
        return Arrays.asList(new String[] {"my_cache1","my_cache2"});
    }

}

  • Cache實(shí)例
@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() {
    }

}

  • 運(yùn)行結(jié)果


    final.png

總結(jié)

  • 自定義大部分情況下用不上,自帶的基本夠用

  • 自定義還需要實(shí)現(xiàn)過期功能

  • 項(xiàng)目最終結(jié)構(gòu)


    final2.png

(有問題,歡迎指出)

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容