Caffeine本地缓存应用实践

Caffeine本地缓存应用实践

1.1 概述

​ Caffeine是一种高性能的缓存库,内部使用ConcurrentHashMap实现,是基于Java 8的最佳缓存框架。基于 Google 的 Guava Cache,Caffeine 提供一个性能卓越的本地缓存实现 , 也是 SpringBoot 内置的本地缓存实现。

1.2 准备工作

在springboot工程中添加如下依赖

<dependency>
 <groupId>com.github.ben-manes.caffeine</groupId>
 <artifactId>caffeine</artifactId>
</dependency>

<dependency>
 <groupId>org.springframework.boot</groupId>
 <artifactId>spring-boot-starter-cache</artifactId>
</dependency>

1.3 应用分析及实践

第一步:定义常量信息(非必须的,只是将几个固定值写到一个类中,方便获取和统一)

package cn.tedu.cache;
/**
* 此类定义常量信息
*/
public class CacheConstants {
   /**
    * 默认过期时间(配置类中我使用的时间单位是秒,所以这里如 3*60 为3分钟)
    */
   public static final int DEFAULT_EXPIRES = 3 * 60;
   public static final int EXPIRES_5_MIN = 5 * 60;
   public static final int EXPIRES_10_MIN = 10 * 60;
   public static final String CACHE1 = "CACHE1";
   public static final String CACHE2 = "CACHE2";
}

第二步:创建枚举类(通过枚举定义一些固定实例),定义缓存相关信息

package cn.tedu.cache;

public enum CacheEnum {
   /**
    * 缓存1
    */
   CACHE1(CacheConstants.CACHE1, CacheConstants.EXPIRES_5_MIN),
   /**
    * 缓存2
    */
   CACHE2(CacheConstants.CACHE2, CacheConstants.EXPIRES_10_MIN),
   ;
   /**
    * 缓存名称
    */
   private final String name;
   /**
    * 过期时间
    */
   private final int expires;

   /**
    * 构造
    */
   CacheEnum(String name, int expires) {
       this.name = name;
       this.expires = expires;
   }

   public String getName() {
       return name;
   }

   public int getExpires() {
       return expires;
   }
}

第三步:定义缓存配置类

@EnableCaching //开启缓存
@Configuration
public class CacheConfig {
   /**
    * Caffeine配置说明:
    *   initialCapacity=[integer]: 初始的缓存空间大小
    *   maximumSize=[long]: 缓存的最大条数
    *   expireAfterWrite=[duration]: 最后一次写入后经过固定时间过期
    *   refreshAfterWrite=[duration]: 创建缓存或者最近一次更新缓存后经过固定的时间间隔,刷新缓存
    */
   @Bean
   public CacheManager cacheManager() {
       SimpleCacheManager cacheManager = new SimpleCacheManager();
       List<CaffeineCache> list = new ArrayList<>();
       //循环添加枚举类中自定义的缓存
       for (CacheEnum cacheEnum : CacheEnum.values()) {
           list.add(new CaffeineCache(cacheEnum.getName(),
                   Caffeine.newBuilder()
                           .initialCapacity(50)
                           .maximumSize(1000) //缓存的最大条数
                           .expireAfterWrite(cacheEnum.getExpires(), TimeUnit.SECONDS)
                           .build()));
       }
       cacheManager.setCaches(list);
       return cacheManager;
   }
}

第四步:AOP方式启动缓存应用

@RestController
@Api(tags = "2.分类处理类")
public class CategoryController {
   @Autowired
   private CategoryMapper categoryMapper;


   /**
    * 查询分类列表
    * @return
    */
   @GetMapping("/category/list")
   //添加缓存,value属性为添加到的缓存名字,sync表示异步
   @Cacheable(value = CacheConstants.CACHE2,sync = true)
   public List<Category> list(){
       System.out.println("===获取数据===");
       return categoryMapper.list();
   }

   /**
    * 创建新分类
    * @param category
    */
   @PostMapping("/category/insert")
   //清空缓存,value属性为添加到的缓存名字,allEntries = true表示清空所有
   @CacheEvict(value = CacheConstants.CACHE2, allEntries = true)
   public void doCreate(@RequestBody Category category){
         categoryMapper.insert(category);
   }

   /**
    * 基于id删除分类
    * @param id
    */
   @DeleteMapping("/category/delete/{id}")
   @CacheEvict(value = CacheConstants.CACHE2, allEntries = true)
   public void doDeleteById(@PathVariable("id") Integer id){
       categoryMapper.deleteById(id);
   }
}

第五步:启动服务,访问分类数据,检测缓存应用。

拦截器

2.1 背景

项目增加新的需求,要求系统登陆操作要有时间限制。

2.2 原理应用分析

拦截器 (Interceptor) 是一种动态拦截方法调用的机制,在SpringMVC中动态拦截控制器方法的执行 , 可以在目标方法执行之前,先进行业务检测,满足条件则放行,不满足条件则进行拦截,拦截器原理分析如下图所示:

image-20230321165157166

2.3 最终解决方案实现

第一步:拦截器定义,关键代码如下:

/**
 * Spring MVC中拦截器
 * @author Administrator
 */
public class TimeInterceptor implements HandlerInterceptor {
    /**
     * preHandle在控制层目标方法执行之前执行
     */
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
            throws Exception {
        System.out.println("preHandler()");
        //获取java中的日历对象
        Calendar c = Calendar.getInstance();
        c.set(Calendar.HOUR_OF_DAY, 6);
        c.set(Calendar.MINUTE, 0);
        c.set(Calendar.SECOND, 0);
        long start = c.getTimeInMillis();
        c.set(Calendar.HOUR_OF_DAY,14);
        long end = c.getTimeInMillis();
        long cTime = System.currentTimeMillis();
        if(cTime<start||cTime>end)
            throw new RuntimeException("不在访问时间之内");
        return true;
    }
}

第二步:拦截器配置,关键代码如下 :

@Configuration
public class SpringWebConfig implements WebMvcConfigurer {
    //配置spring mvc 拦截器
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new TimeInterceptor()).addPathPatterns("/user/login");
    }
}
Caffeine本地缓存适用于以下场景: 1. 提升应用性能:Caffeine本地缓存可以将频繁访问的数据缓存在内存中,以减少对底层数据源的访问次数,从而提高应用的性能和响应速度。 2. 降低系统负载:通过使用Caffeine本地缓存,可以避免频繁地从数据库或其他外部数据源中读取数据,减少了对外部系统的访问,从而降低了系统的负载。 3. 数据共享与共享状态管理:Caffeine本地缓存可以用于在应用内部共享数据,减少重复计算和查询的开销。同时,它也可以用于管理应用中的共享状态,确保多个线程或进程之间的数据一致性。 4. 缓存数据的有效期管理:Caffeine本地缓存提供了对缓存数据有效期的管理,可以根据需求设置缓存过期时间,以确保缓存数据的及时更新和一致性。 5. 缓解外部服务的压力:对于一些需要频繁调用外部服务的场景,可以使用Caffeine本地缓存来缓存外部服务的响应结果,减少对外部服务的调用次数,降低对外部服务的压力。 总之,Caffeine本地缓存适用于需要提升应用性能、降低系统负载、数据共享与共享状态管理、缓存数据有效期管理和缓解外部服务压力的场景。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* *3* [Caffeine一级缓存介绍和应用](https://blog.csdn.net/u011507134/article/details/127107322)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 100%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值