纵有疾风起
人生不言弃

SpringBoot使用Redis做缓存结合自带注解


配置Spring Cache

<dependency>    <groupId>org.springframework.boot</groupId>    <artifactId>spring-boot-starter-data-redis</artifactId></dependency><dependency>    <groupId>com.github.ulisesbocchio</groupId>    <artifactId>jasypt-spring-boot-starter</artifactId>    <version>1.16</version></dependency><dependency>    <groupId>com.fasterxml.jackson.core</groupId>    <artifactId>jackson-databind</artifactId>    <version>2.10.3</version></dependency>
spring:  cache:    type: redis    ### 配置Redis    # Redis数据库索引(默认为0)    redis:      database: 0      # Redis服务器地址      host: mmren.edu.redis.server      # Redis服务器连接端口      port: 6379      # Redis服务器连接密码(默认为空)      password: ENC(bIx3PYzFf0CcZ+6CdAGHruIaTgY1/CyB)      # 配置连接池      jedis:        pool:          # 连接池最大连接数(使用负值表示没有限制)          max-active: 8          # 连接池最大阻塞等待时间(使用负值表示没有限制)          max-wait: -1          # 连接池中的最大空闲连接          max-idle: 500          # 连接池中的最小空闲连接          min-idle: 0      # 连接超时时间(毫秒)      timeout: 2000      lettuce:        shutdown-timeout: 0jasypt:  encryptor:    password: gerrymmrenedu # 设置根密码

缓存配置类

@EnableCaching@Configurationpublic class RedisCacheConfig extends CachingConfigurerSupport {    @Bean    public CacheManager cacheManager(RedisConnectionFactory factory) {        // 创建Redis序列化对象        RedisSerializer<String> redisSerializer = new StringRedisSerializer();        // 使用Jackson的序列化对象        Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);        //解决查询缓存转换异常的问题        ObjectMapper om = new ObjectMapper();        om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);        om.activateDefaultTyping(om.getPolymorphicTypeValidator(), ObjectMapper.DefaultTyping.NON_FINAL);        jackson2JsonRedisSerializer.setObjectMapper(om);        // 配置序列化(解决乱码的问题)        RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig()                // 7 天缓存过期                .entryTtl(Duration.ofDays(7))                .serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(redisSerializer))                .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(jackson2JsonRedisSerializer))                .disableCachingNullValues();        RedisCacheManager cacheManager = RedisCacheManager.builder(factory)                .cacheDefaults(config)                .build();        return cacheManager;    }}

创建实体

public class Book implements Serializable {    private static final long serialVersionUID = 2629983876059197650L;        private String id;    private String name; // 书名    private Integer price; // 价格    private Date update; //     public Book(String id, String name, Integer price, Date update) {        super();        this.id = id;        this.name = name;        this.price = price;        this.update = update;    }    public String getName() {        return name;    }    public void setName(String name) {        this.name = name;    }    public Integer getPrice() {        return price;    }    public void setPrice(Integer price) {        this.price = price;    }    public String getId() {        return id;    }    public void setId(String id) {        this.id = id;    }    public Date getUpdate() {        return update;    }    public void setUpdate(Date update) {        this.update = update;    }}--------------------------------public class BookQry {    private String id;    private String name; // 书名    public String getId() {        return id;    }    public void setId(String id) {        this.id = id;    }    public String getName() {        return name;    }    public void setName(String name) {        this.name = name;    }        @Override    public String toString(){        return JSON.toJSONString(this);    }}

数据初始化类

public abstract class AbstractService {    protected static Map<String, Book> repositoryBook = new HashMap<>();    public AbstractService() {        super();    }        @PostConstruct    public void init() {        // 1        Book book1 = new Book("1001", "牧码人", 11, new Date());        repositoryBook.put(book1.getId(), book1);        // 2        Book book2 = new Book("1002", "张三", 43, new Date());        repositoryBook.put(book2.getId(), book2);        // 3        Book book3 = new Book("1003", "Gerry", 5433, new Date());        repositoryBook.put(book3.getId(), book3);        // 4        Book book4 = new Book("1004", "教育", 54, new Date());        repositoryBook.put(book4.getId(), book4);    }}

自定义缓存key生成类

@Componentpublic class MyKeyGenerator implements KeyGenerator {    @Override    public Object generate(Object target, Method method, Object... params) {        System.out.println("自定义缓存,使用第一参数作为缓存key. params = " + Arrays.toString(params));        // 仅仅用于测试,实际不可能这么写        return params[0] + "0";    }}

Spring缓存的基本用法

@Componentpublic class BookService extends AbstractService {    private static final Logger logger = LoggerFactory.getLogger(BookService.class);        // ==================== @Cacheable ========================    /**     * cacheNames 设置缓存的值      *     key:指定缓存的key,这是指参数id值。 key可以使用spEl表达式     * @param id     * @return     */    @Cacheable(cacheNames="book1", key="#id")    public Book queryBookCacheable(String id){        logger.info("queryBookCacheable,id={}",id);        return repositoryBook.get(id);    }        /**     * 这里使用另一个缓存存储缓存     *      * @param id     * @return     */    @Cacheable(cacheNames="book2", key="#id")    public Book queryBookCacheable_2(String id){        logger.info("queryBookCacheable_2,id={}",id);        return repositoryBook.get(id);    }        /**     * 缓存的key也可以指定对象的成员变量     * @param qry     * @return     */    @Cacheable(cacheNames="book1", key="#qry.id")    public Book queryBookCacheableByBookQry(BookQry qry){        logger.info("queryBookCacheableByBookQry,qry={}",qry);        String id = qry.getId();        Assert.notNull(id, "id can't be null!");        String name = qry.getName();        Book book = null;        if(id != null){            book = repositoryBook.get(id);            if(book != null && !(name != null && book.getName().equals(name))){                book = null;            }        }        return book;    }        /**     * 以上我们使用默认的keyGenerator,对应spring的SimpleKeyGenerator      *     如果你的使用很复杂,我们也可以自定义myKeyGenerator的生成key     *      *  key和keyGenerator是互斥,如果同时制定会出异常     *     The key and keyGenerator parameters are mutually exclusive and an operation specifying both will result in an exception.     *      * @param id     * @return     */    @Cacheable(cacheNames="book3",  keyGenerator="myKeyGenerator")    public Book queryBookCacheableUseMyKeyGenerator(String id){        logger.info("queryBookCacheableUseMyKeyGenerator,id={}",id);        return repositoryBook.get(id);    }        /***     * 如果设置sync=true,     *     如果缓存中没有数据,多个线程同时访问这个方法,则只有一个方法会执行到方法,其它方法需要等待     *     如果缓存中已经有数据,则多个线程可以同时从缓存中获取数据     * @param id     * @return     */    @Cacheable(cacheNames="book3", sync=true)    public Book queryBookCacheableWithSync(String id) {        logger.info("begin ... queryBookCacheableByBookQry,id={}",id);        try {            Thread.sleep(1000 * 2);        } catch (InterruptedException e) {        }        logger.info("end ... queryBookCacheableByBookQry,id={}",id);        return repositoryBook.get(id);    }        /**     * 条件缓存:     * 只有满足condition的请求才可以进行缓存,如果不满足条件,则跟方法没有@Cacheable注解的方法一样     *     如下面只有id < 3才进行缓存     *      */    @Cacheable(cacheNames="book11", condition="T(java.lang.Integer).parseInt(#id) < 3 ")    public Book queryBookCacheableWithCondition(String id) {        logger.info("queryBookCacheableByBookQry,id={}",id);        return repositoryBook.get(id);    }        /**     * 条件缓存:     * 对不满足unless的记录,才进行缓存     *     "unless expressions" are evaluated after the method has been called     *     如下面:只对不满足返回 'T(java.lang.Integer).parseInt(#result.id) <3 ' 的记录进行缓存     * @param id     * @return     */    @Cacheable(cacheNames="book22", unless = "T(java.lang.Integer).parseInt(#result.id) <3 ")    public Book queryBookCacheableWithUnless(String id) {        logger.info("queryBookCacheableByBookQry,id={}",id);        return repositoryBook.get(id);    }            // ==================== @CacheEvict ========================    /**     * allEntries = true: 清空book1里的所有缓存     */    @CacheEvict(cacheNames="book1", allEntries=true)    public void clearBook1All(){        logger.info("clearAll");    }    /**     * 对符合key条件的记录从缓存中book1移除     */    @CacheEvict(cacheNames="book1", key="#id")    public void updateBook(String id, String name){        logger.info("updateBook");        Book book = repositoryBook.get(id);        if(book != null){            book.setName(name);            book.setUpdate(new Date());        }    }        // ==================== @CachePut ========================    /**     * 每次执行都会执行方法,无论缓存里是否有值,同时使用新的返回值的替换缓存中的值     *     这里不同于@Cacheable:@Cacheable如果缓存没有值,从则执行方法并缓存数据,如果缓存有值,则从缓存中获取值     * @param id     * @return     */    @CachePut(cacheNames="book1", key="#id")    public Book queryBookCachePut(String id){        logger.info("queryBookCachePut,id={}",id);        return repositoryBook.get(id);    }    }

@CacheConfig配置定义

/** * @CacheConfig: 类级别的注解 *     如果我们在此注解中定义cacheNames,则此类中的所有方法上@Cacheable的cacheNames默认都是此值。当然    * @Cacheable也可以重定义cacheNames的值 * */@Component@CacheConfig(cacheNames="booksAll") public class BookService2 extends AbstractService {    private static final Logger logger = LoggerFactory.getLogger(BookService2.class);        /**     * 此方法的@Cacheable没有定义cacheNames,则使用类上的注解@CacheConfig里的值 cacheNames     * @param id     * @return     */    @Cacheable(key="#id")    public Book queryBookCacheable(String id){        logger.info("queryBookCacheable,id={}",id);        return repositoryBook.get(id);    }    /**     * 此方法的@Cacheable有定义cacheNames,则使用此值覆盖类注解@CacheConfig里的值cacheNames     *      * @param id     * @return     */    @Cacheable(cacheNames="books_custom", key="#id")    public Book queryBookCacheable2(String id){        logger.info("queryBookCacheable2,id={}",id);        return repositoryBook.get(id);    }}

编写测试用例

public class RedisCacheTests  extends  ApplicationTests{    @Autowired    private BookService bookService;    @Test    public void testCache1() throws Exception {        Book book = bookService.queryBookCacheable("1001");        convertToString(book);    }    @Test    public void testCache2() throws Exception {        Book book = bookService.queryBookCacheable_2("1001");        convertToString(book);    }    @Test    public void testCache3() throws Exception {        BookQry qry = new BookQry();        qry.setId("1004");        qry.setName("教育");        Book book = bookService.queryBookCacheableByBookQry(qry);        convertToString(book);    }    @Test    public void testCache4() throws Exception {        Book book = bookService.queryBookCacheableUseMyKeyGenerator("1003");        convertToString(book);    }    @Test    public void testCache5() throws Exception {        Book book = bookService.queryBookCachePut("1003");        convertToString(book);    }    public void convertToString(Object object) {        String jsonString = JSON.toJSONString(object, true);        System.out.println(jsonString);    }}

 

文章转载于:https://www.cnblogs.com/lm970585581/p/12810024.html

原著是一个有趣的人,若有侵权,请通知删除

未经允许不得转载:起风网 » SpringBoot使用Redis做缓存结合自带注解

分享到: 生成海报
avatar

评论 抢沙发

评论前必须登录!

立即登录   注册

切换注册

登录

忘记密码 ?

切换登录

注册

我们将发送一封验证邮件至你的邮箱, 请正确填写以完成账号注册和激活