springCache配合redis做缓存

redis的优势

我们都知道redis可以作为缓存,是因为它具有

  1. 大内存作为缓存

  2. redis的缓存可以被持久化

  3. redis可以实现分布式缓存

  4. Redis可以处理每秒百万级的并发,是专业的缓存服务

  5. redis对缓存有过期时间机制

  6. Redis不仅仅支持简单的k/v类型的数据,同时还提供list,set,zset,hash等数据结构的存储。

什么是springCache

概述

Spring 3.1 引入了激动人心的基于凝视(annotation)的缓存(cache)技术,它本质上不是一个具体的缓存实现方案(比如EHCache 或者 OSCache),而是一个对缓存使用的抽象,通过在既有代码中加入少量它定义的各种 annotation,即能够达到缓存方法的返回对象的效果。

其特点总结例如以下:

  • 通过少量的配置 annotation 凝视就可以使得既有代码支持缓存

  • 支持开箱即用 Out-Of-The-Box,即不用安装和部署额外第三方组件就可以使用缓存

  • 支持 Spring Express Language,能使用对象的不论什么属性或者方法来定义缓存的 key 和 condition

  • 支持 AspectJ,并通过事实上现不论什么方法的缓存支持

  • 支持自己定义 key 和自己定义缓存管理者,具有相当的灵活性和扩展性

组成部分

图片

首先,我们可以知道 他有一个CachingConfigurer接口和 实现此接口的CachingConfigurerSupport实现类。

接口CachingConfigurer的方法:

  • CacheManager cacheManager() 返回缓存管理器bean,以用于注释驱动的缓存管理。默认的CacheResolver将使用此缓存管理器初始化。为了更精细地管理缓存,请考虑直接设置CacheResolver

  • CacheResolver cacheResolver() 以用于解析由注释驱动的缓存管理的常规缓存。这是指定要使用的CacheManager的替代方法,功能更强大

  • KeyGenerator keyGenerator() 返回密钥生成器bean,以用于注释驱动的缓存管理。实现必须明确声明

  • CacheErrorHandler errorHandler 返回CacheErrorHandler以处理与缓存相关的错误。默认情况下,使用SimpleCacheErrorHandler并简单地将异常返回给客户端

图片

我们可以设置redis作为缓存提供者

@Cacheable、@CachePut、@CacheEvict 注释介绍

@Cacheable 的作用 主要针对方法配置,能够根据方法的请求参数对其结果进行缓存

@Cacheable 主要的参数 value缓存的名称,在 spring 配置文件中定义,必须指定至少一个例如:

@Cacheable(value=”mycache”) 或者

@Cacheable(value={”cache1”,”cache2”}key缓存的 key,可以为空,如果指定要按照 SpEL 表达式编写,如果不指定,则缺省按照方法的所有参数进行组合例如:

@Cacheable(value=”testcache”,key=”#userName”)condition缓存的条件,可以为空,使用 SpEL 编写,返回 true 或者 false,只有为 true 才进行缓存例如:

@Cacheable(value=”testcache”,condition=”#userName.length()>2”)

@CachePut 的作用 主要针对方法配置,能够根据方法的请求参数对其结果进行缓存,和 @Cacheable 不同的是,它每次都会触发真实方法的调用

@CachePut 主要的参数 value缓存的名称,在 spring 配置文件中定义,必须指定至少一个例如:

@CachEvict 的作用 主要针对方法配置,能够根据一定的条件对缓存进行清空

@CacheEvict 主要的参数 value缓存的名称,在 spring 配置文件中定义,必须指定至少一个例如:

@CachEvict(value=”mycache”) 或者

@CachEvict(value={”cache1”,”cache2”}key缓存的 key,可以为空,如果指定要按照 SpEL 表达式编写,如果不指定,则缺省按照方法的所有参数进行组合例如:

@CachEvict(value=”testcache”,key=”#userName”)condition缓存的条件,可以为空,使用 SpEL 编写,返回 true 或者 false,只有为 true 才清空缓存例如:

@CachEvict(value=”testcache”,

condition=”#userName.length()>2”)allEntries是否清空所有缓存内容,缺省为 false,如果指定为 true,则方法调用后将立即清空所有缓存例如:

@CachEvict(value=”testcache”,allEntries=true)beforeInvocation是否在方法执行前就清空,缺省为 false,如果指定为 true,则在方法还没有执行的时候就清空缓存,缺省情况下,如果方法执行抛出异常,则不会清空缓存例如:

@CachEvict(value=”testcache”,beforeInvocation=true)

@CacheConfig:主要用于配置该类中会用到的一些共用的缓存配置

所有的@Cacheable()里面都有一个value=“xxx”的属性,这显然如果方法多了,写起来也是挺累的,如果可以一次性声明完 那就省事了, 所以,有了@CacheConfig这个配置,@CacheConfig is a class-level annotation that allows to share the cache names,如果你在你的方法写别的名字,那么依然以方法的名字为准。

@CacheConfig是一个类级别的注解。

/** * 测试服务层 */
@Service
@CacheConfig(value = "taskLog")
public class TaskLogService {
 
    @Autowired  private TaskLogMapper taskLogMapper;
    @Autowired  private net.sf.ehcache.CacheManager cacheManager;
 
    /** * 缓存的key */
    public static final String CACHE_KEY   = "taskLog";
 
    /** * 添加tasklog * @param tasklog * @return */
    @CachePut(key = "#tasklog.id")
    public Tasklog create(Tasklog tasklog){
        System.out.println("CREATE");
        System.err.println (tasklog);
        taskLogMapper.insert(tasklog);
        return tasklog;
    }
 
    /** * 根据ID获取Tasklog * @param id * @return */
    @Cacheable(key = "#id")
    public Tasklog findById(String id){
        System.out.println("FINDBYID");
        System.out.println("ID:"+id);
        return taskLogMapper.selectById(id);
    }
}

@Caching:配置于函数上,组合多个Cache注解使用。

有时候我们可能组合多个Cache注解使用;比如用户新增成功后,我们要添加id–>user;username—>user;email—>user的缓存;此时就需要@Caching组合多个注解标签了。

 @Caching(put = {
 @CachePut(value = "user", key = "#user.id"),
 @CachePut(value = "user", key = "#user.username"),
 @CachePut(value = "user", key = "#user.email")
 })
 public User save(User user) {
 }

demo 搭建

1. 配置缓存配置类

这里使用的spring-boot2.x版本

 @Configuration
 @EnableCaching
 class RedisCacheConfig extends CachingConfigurerSupport{
 
     /\*\*
      \* 自定义缓存key生成策略
      \*/
     @Override
     @Bean
     public KeyGenerator keyGenerator() {
         return new KeyGenerator() {
             @Override
             public Object generate(Object target, java.lang.reflect.Method method, Object... params) {
                 StringBuffer sb = new StringBuffer();
                 sb.append(target.getClass().getName());
                 sb.append(method.getName());
                 for (Object obj : params) {
                     sb.append(obj.toString());
                }
                 return sb.toString();
            }
        };
    }
 
 
         /\*\*
          \* 缓存管理器
          \*/
         @Bean
         public CacheManager cacheManager(RedisConnectionFactory redisConnectionFactory) {
             RedisCacheConfiguration redisCacheConfiguration = RedisCacheConfiguration.defaultCacheConfig()
                    .entryTtl(Duration.ofSeconds(30)); // 设置缓存有效期30s
             return RedisCacheManager
                    .builder(RedisCacheWriter.nonLockingRedisCacheWriter(redisConnectionFactory))
                    .cacheDefaults(redisCacheConfiguration).build();
        }
 
     @Bean
     public RedisTemplate<String, Object> redisTemplate(
             RedisConnectionFactory connectionFactory) {
         RedisTemplate<String, Object> redisTemplate = new RedisTemplate<String, Object>();
         redisTemplate.setConnectionFactory(connectionFactory);
         redisTemplate.setDefaultSerializer(new GenericJackson2JsonRedisSerializer());
         StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
         redisTemplate.setKeySerializer(stringRedisSerializer);
         redisTemplate.setHashKeySerializer(stringRedisSerializer);
         return redisTemplate;
    }
     
      /\* springboot 1.0 搭法
     @Bean
     public RedisTemplate<Object, Employee> empRedisTemplate(RedisConnectionFactory redisConnectionFactory) throws UnknownHostException {
         RedisTemplate<Object, Employee> template = new RedisTemplate();
         template.setConnectionFactory(redisConnectionFactory);
         Jackson2JsonRedisSerializer<Employee> serializer = new Jackson2JsonRedisSerializer<Employee>(Employee.class);
         template.setDefaultSerializer(serializer);
         return template;
     }
 
     @Bean
     public RedisCacheManager employeeCacheManager(RedisTemplate<Object,Employee> empRedisTemplate){
         RedisCacheManager cacheManager = new RedisCacheManager(empRedisTemplate);
         cacheManager.setTransactionAware(true);
 
         return cacheManager;
     }\*/
     
 }

2. service业务上 添加 对应注解

 @Service @Slf4j public class DeviceServiceImpl extends ServiceImpl<DeviceMapper, Device> implements IDeviceService {       /\*\*      \*新增      \* @param device 设备实体类      \* @return      \*/     @Override     @CachePut(cacheNames="device",key="#device.id")     public void insert(Device device){          save(device);    }      /\*\*      \* 删除      \* @param id 主键id      \* @return      \*/     @Override     @CacheEvict(cacheNames = "device",key = "id")     public boolean deleteById(Long id) {         return removeById(id);    }      /\*\*      \* 更新      \* @param device      \* @return      \*/     @Override     public Boolean updateDevice(Device device){         boolean update = updateById(device);         log.info("device update after : {}",device);         return update;    }      /\*\*      \* 查询全部设备      \*      \* @return      \*/     @Override     @Cacheable(cacheNames = "device",key = "'device-'+#root.targetClass.id")     public  List<Device> allDevices() {         List<Device> list = list();         return list;    }     }

3. 测试

 @RunWith(SpringRunner.class) //SpringBoot1.4版本之前用的是@SpringApplicationConfiguration(classes = Application.class) @SpringBootTest public class DeviceControllerTest {      @Autowired     private DeviceController deviceController;      @Test     public void devices() {         ResponseResult devices = deviceController.devices();         System.out.println("devices = " + devices);    }      @Test     public void saveDevice() {          deviceController.saveDevice();    }      @Test     public void deleteDevice() {          deviceController.deleteDevice(60L);    } }

4. redis 查询结果

图片

debug 模式 没有走 查询方法,说明只是把缓存的结果返回了

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值