java中SpringCache+Redis实现分布式缓存的功能

 

 

SpringCache介绍

对于缓存声明,Spring的缓存提供了一组java注解:

  1. @Cacheable:触发缓存写入。
  2. @CacheEvict:触发缓存清除。
  3. @CachePut:更新缓存(不会影响到方法的运行)。
  4. @Caching:重新组合要应用于方法的多个缓存操作。
  5. @CacheConfig:设置类级别上共享的一些常见缓存设置。

集成SpringCache 

1.导入依赖

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

 2.在启动类打上@EnableCaching注解开启Cache

//缓存服务
@SpringBootApplication
@EnableCaching
public class CacheApplication {

    public static void main(String[] args) {
        SpringApplication.run(CacheApplication.class) ;
    }
}

3.配置redis

@Configuration
public class CacheConfig extends CachingConfigurerSupport {

    @Resource
    private RedisConnectionFactory factory;

    /**
     * 自定义生成redis-key , 类名.方法名
     * @return
     */
    @Override
    @Bean
    public KeyGenerator keyGenerator() {
        return (o, method, objects) -> {
            StringBuilder sb = new StringBuilder();
            sb.append(o.getClass().getName()).append(".");
            sb.append(method.getName()).append(".");
            for (Object obj : objects) {
                sb.append(obj.toString());
            }
            return sb.toString();
        };
    }

    @Bean
    public RedisTemplate<Object, Object> redisTemplate() {
        RedisTemplate<Object, Object> redisTemplate = new RedisTemplate<>();
        redisTemplate.setConnectionFactory(factory);
        //JSON格式序列化
        GenericJackson2JsonRedisSerializer genericJackson2JsonRedisSerializer = new GenericJackson2JsonRedisSerializer();
         //key的序列化
        redisTemplate.setKeySerializer(genericJackson2JsonRedisSerializer);
        //value的序列化
        redisTemplate.setValueSerializer(genericJackson2JsonRedisSerializer);
        //hash结构key的虚拟化

        redisTemplate.setHashKeySerializer(new StringRedisSerializer());
        //hash结构value的虚拟化
        redisTemplate.setHashValueSerializer(genericJackson2JsonRedisSerializer);
        return redisTemplate;
    }

    @Bean
    @Override
    public CacheResolver cacheResolver() {
        return new SimpleCacheResolver(cacheManager());
    }

    @Bean
    @Override
    public CacheErrorHandler errorHandler() {
        // 用于捕获从Cache中进行CRUD时的异常的回调处理器。
        return new SimpleCacheErrorHandler();
    }
    //缓存管理器
    @Bean
    @Override
    public CacheManager cacheManager() {
        RedisCacheConfiguration cacheConfiguration = defaultCacheConfig()
                        .disableCachingNullValues() //不允许空值
                        .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(new GenericJackson2JsonRedisSerializer()));//值使用JSON虚拟化

        return RedisCacheManager.builder(factory).cacheDefaults(cacheConfiguration).build();

    }
} 

 4.yml中的配置

spring:
  application:
    name: cache-server
  redis:
    database: 0
    host: 127.0.0.1
    port: 6379
    password: 
    jedis:
      pool:
        max-wait: 2000ms
        min-idle: 2
        max-idle: 8

主要注解的使用: 

@Cacheable注解

@Cacheable可以用来进行缓存的写入,将结果存储在缓存中,以便于在后续调用的时候可以直接返回缓存中的值,而不必再执行实际的方法。 最简单的使用方式,注解名称=缓存名称

@Cacheable(cacheNames="books",key="’book1’")
public Book findBook(ISBN isbn) {...}

 一个方法可以对应多个缓存名称,如下: 

@Cacheable(cacheNames={"books", "isbns"},key="’book1’")
public Book findBook(ISBN isbn) {...} 

@Cacheable的缓存名称是可以配置动态参数的,比如选择传入的参数,如下:

@Cacheable(cacheNames="books", key="#isbn") //参数值作为Key
public Book findBook(ISBN isbn, boolean checkWarehouse, boolean includeUsed)
   
@Cacheable(cacheNames="books", key="#isbn.rawNumber")
public Book findBook(ISBN isbn, boolean checkWarehouse, boolean includeUsed)

@Cacheable还可以设置根据条件判断是否需要缓存 

condition:取决于给定的参数是否满足条件
unless:取决于返回值是否满足条件
以下是一个简单的例子:

@Cacheable(cacheNames="book", condition="#name.length() < 32") 
public Book findBook(String name)
    
@Cacheable(cacheNames="book",condition="#name.length()<32", unless="#result.hardback") 
public Book findBook(String name) 

 @Cacheable还可设置:keyGenerator(指定key自动生成方法),cacheManager(指定使用的缓存管理),cacheResolver(指定使用缓存的解析器)等,这些参数比较适合全局设置。

@CachePut注解

@CachePut:当需要更新缓存而不干扰方法的运行时 ,可以使用该注解。也就是说,始终执行该方法,并将结果放入缓存(已经有缓存就更新缓存),注解参数与@Cacheable相同。

@CachePut(cacheNames="book", key="#isbn")
public Book updateBook(ISBN isbn, BookDescriptor descriptor) 

建议不要对同一方法同时使用@CachePut和@Cacheable注解,因为它们具有不同的行为。

@CacheEvict注解

@CacheEvict:删除缓存的注解,这对删除旧的数据和无用的数据是非常有用的。这里还多了一个参数(allEntries),设置allEntries=true时,可以对整个条目进行批量删除。

@CacheEvict(cacheNames="books") 
public void loadBooks(InputStream batch)
   
//对cacheNames进行批量删除
@CacheEvict(cacheNames="books", allEntries=true) 
public void loadBooks(InputStream batch) 

@Caching注解

@Caching:在使用缓存的时候,有可能会同时进行更新和删除,会出现同时使用多个注解的情况.而@Caching可以实现。

@Caching(evict = { @CacheEvict("primary"), @CacheEvict(cacheNames="secondary", key="#p0") })
public Book importBooks(String deposit, Date date) 

@CacheConfig注解

@CacheConfig:缓存提供了许多的注解选项,但是有一些公用的操作,我们可以使用@CacheConfig在类上进行全局设置。

@CacheConfig(cacheName="books") 
public class BookRepositoryImpl implements BookRepository {
    
@Cacheable
public Book findBook(ISBN isbn) {...}

} 

Redis缓存案例

实体类:实现Serializable 可序列化

public class MyUser implements Serializable {
    private Long id;
    private String username;
    public MyUser() {
    }
    public MyUser(Long id, String username) {
        this.id = id;
        this.username = username;
    }
    public Long getId() {
        return id;
    }
    public void setId(Long id) {
        this.id = id;
    }
    public String getUsername() {
        return username;
    }
    public void setUsername(String username) {
        this.username = username;
    }
}

缓存业务类:

/**
 * 统一设置cacheNames,方法上可以不用设置了
 */
@CacheConfig(cacheNames = "users")
@Service
public class RedisServiceImpl implements RedisService {

    /**
     * 把cacheNames和key组合编程Redis的key存储,如: “users::user1”
     * @Cacheable(cacheNames = {"users"}, key = "'user1'")
     * 从参数中取值作为key ,如: “users::1”
     */
    @Cacheable(cacheNames = "users",key = "#id")
    public MyUser findUser(Long id) {
        System.out.println("没有命中缓存...");
        return new MyUser(id,"Maske");
    }

    /**
     * 把方法返回结果作为缓存的修改内容,匹配  “users::1” 缓存
     * 不建议把 @CachePut 和  @Cacheable 作用于同一个方法,功能冲突会出Bug
     */
    @CachePut(cacheNames = {"users"}, key = "#id")
    public MyUser updateUser(Long id) {
        System.out.println("修改User...");
        return new MyUser(id,"Buffett");
    }

    /**
     * 对cacheNames进行批量删除
     * @CacheEvict(cacheNames="users", key = "#id") ,删除 "users::#id"
     * 对cacheNames进行批量删除 ,如: "users::2" , "users::1"都会被删除
     */
    @CacheEvict(cacheNames="users", key = "#id",allEntries=true)
    public void deleteUser(Long id) {
        System.out.println("删除User...");
    }
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

不会理财的程序员不是好摄影师

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值