springboot整合redis-sentinel支持Cache注解

一、前提

已经存在一个redis-sentinel集群,两个哨兵分别如下:

/home/redis-sentinel-cluster/sentinel-1.conf
port 26379

dir "/data"
sentinel monitor mymaster 172.16.1.11 16379 2
sentinel down-after-milliseconds mymaster 5000
sentinel failover-timeout mymaster 5000
sentinel parallel-syncs mymaster 1
/home/redis-sentinel-cluster/sentinel-2.conf
port 26380

dir "/data"
sentinel monitor mymaster 172.16.1.11 16379 2
sentinel down-after-milliseconds mymaster 5000
sentinel failover-timeout mymaster 5000
sentinel parallel-syncs mymaster 1

二、新建maven工程:redis-sentinel-demo最终完整工程如下:

springboot整合redis-sentinel支持Cache注解

pom.xml如下:

xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0modelVersion>

    <groupId>com.redis.sentinel.demogroupId>
    <artifactId>redis-sentinel-demoartifactId>
    <version>1.0-SNAPSHOTversion>

    <parent>
        <groupId>org.springframework.bootgroupId>
        <artifactId>spring-boot-starter-parentartifactId>
        <version>1.4.3.RELEASEversion>
        <relativePath/>
    parent>
    <properties>
        <project.build.sourceEncoding>UTF-8project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8project.reporting.outputEncoding>
        <java.version>1.7java.version>
    properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.bootgroupId>
            <artifactId>spring-boot-starter-webartifactId>
        dependency>

        <dependency>
            <groupId>org.springframework.bootgroupId>
            <artifactId>spring-boot-starter-data-redisartifactId>
        dependency>
    dependencies>

project>

1、application.yml

server:
  port: 8083
  context-path: /

spring:
  redis:
    sentinel:
      master: mymaster
      nodes: 172.16.1.11:26379,172.16.1.11:26380
    pool:
      max-active: 8
      max-idle: 8
      max-wait: -1
      min-idle: 0
    database: 0

2、新建redis的工具类RedisUtil

package com.redis.sentinel.demo.util;

import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.util.CollectionUtils;

import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;

/**
 * @author Administrator
 * @date 2019/03/19
 */
public class RedisUtil {

    private RedisTemplate redisTemplate;
    public void setRedisTemplate(RedisTemplate redisTemplate) {
        this.redisTemplate = redisTemplate;
    }
    //=============================common============================
    /**
     * 指定缓存失效时间
     * @param key 键
     * @param time 时间(秒)
     * @return
     */
    public boolean expire(String key,long time){
        try {
            if(time>0){
                redisTemplate.expire(key, time, TimeUnit.SECONDS);
            }
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 根据key 获取过期时间
     * @param key 键 不能为null
     * @return 时间(秒) 返回0代表为永久有效
     */
    public long getExpire(String key){
        return redisTemplate.getExpire(key, TimeUnit.SECONDS);
    }

    /**
     * 判断key是否存在
     * @param key 键
     * @return true 存在 false不存在
     */
    public boolean hasKey(String key){
        try {
            return redisTemplate.hasKey(key);
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 删除缓存
     * @param key 可以传一个值 或多个
     */
    @SuppressWarnings("unchecked")
    public void del(String... key){
        if(key!=null&&key.length>0){
            if(key.length==1){
                redisTemplate.delete(key[0]);
            }else{
                redisTemplate.delete(CollectionUtils.arrayToList(key));
            }
        }
    }

    //============================String=============================
    /**
     * 普通缓存获取
     * @param key 键
     * @return 值
     */
    public Object get(String key){
        return key==null?null:redisTemplate.opsForValue().get(key);
    }

    /**
     * 普通缓存放入
     * @param key 键
     * @param value 值
     * @return true成功 false失败
     */
    public boolean set(String key,Object value) {
        try {
            redisTemplate.opsForValue().set(key, value);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }

    }

    /**
     * 普通缓存放入并设置时间
     * @param key 键
     * @param value 值
     * @param time 时间(秒) time要大于0 如果time小于等于0 将设置无限期
     * @return true成功 false 失败
     */
    public boolean set(String key,Object value,long time){
        try {
            if(time>0){
                redisTemplate.opsForValue().set(key, value, time, TimeUnit.SECONDS);
            }else{
                set(key, value);
            }
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 递增
     * @param key 键
     * @param delta 要增加几(大于0)
     * @return
     */
    public long incr(String key, long delta){
        if(delta){
            throw new RuntimeException("递增因子必须大于0");
        }
        return redisTemplate.opsForValue().increment(key, delta);
    }

    /**
     * 递减
     * @param key 键
     * @param delta 要减少几(小于0)
     * @return
     */
    public long decr(String key, long delta){
        if(delta){
            throw new RuntimeException("递减因子必须大于0");
        }
        return redisTemplate.opsForValue().increment(key, -delta);
    }

    //================================Hash=================================
    /**
     * HashGet
     * @param key 键 不能为null
     * @param item 项 不能为null
     * @return 值
     */
    public Object hget(String key,String item){
        return redisTemplate.opsForHash().get(key, item);
    }

    /**
     * 获取hashKey对应的所有值
     * @param key 键
     * @return 对应的多个值
     */
    public Map hmget(String key){
        return redisTemplate.opsForHash().entries(key);
    }

    /**
     * HashSet
     * @param key 键
     * @param map 对应多个键值
     * @return true 成功 false 失败
     */
    public boolean hmset(String key, Map map){
        try {
            redisTemplate.opsForHash().putAll(key, map);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * HashSet 并设置时间
     * @param key 键
     * @param map 对应多个键值
     * @param time 时间(秒)
     * @return true成功 false失败
     */
    public boolean hmset(String key, Map map, long time){
        try {
            redisTemplate.opsForHash().putAll(key, map);
            if(time>0){
                expire(key, time);
            }
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 向一张hash表中放入数据,如果不存在将创建
     * @param key 键
     * @param item 项
     * @param value 值
     * @return true 成功 false失败
     */
    public boolean hset(String key,String item,Object value) {
        try {
            redisTemplate.opsForHash().put(key, item, value);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 向一张hash表中放入数据,如果不存在将创建
     * @param key 键
     * @param item 项
     * @param value 值
     * @param time 时间(秒)  注意:如果已存在的hash表有时间,这里将会替换原有的时间
     * @return true 成功 false失败
     */
    public boolean hset(String key,String item,Object value,long time) {
        try {
            redisTemplate.opsForHash().put(key, item, value);
            if(time>0){
                expire(key, time);
            }
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 删除hash表中的值
     * @param key 键 不能为null
     * @param item 项 可以使多个 不能为null
     */
    public void hdel(String key, Object... item){
        redisTemplate.opsForHash().delete(key,item);
    }

    /**
     * 判断hash表中是否有该项的值
     * @param key 键 不能为null
     * @param item 项 不能为null
     * @return true 存在 false不存在
     */
    public boolean hHasKey(String key, String item){
        return redisTemplate.opsForHash().hasKey(key, item);
    }

    /**
     * hash递增 如果不存在,就会创建一个 并把新增后的值返回
     * @param key 键
     * @param item 项
     * @param by 要增加几(大于0)
     * @return
     */
    public double hincr(String key, String item,double by){
        return redisTemplate.opsForHash().increment(key, item, by);
    }

    /**
     * hash递减
     * @param key 键
     * @param item 项
     * @param by 要减少记(小于0)
     * @return
     */
    public double hdecr(String key, String item,double by){
        return redisTemplate.opsForHash().increment(key, item,-by);
    }

    //============================set=============================
    /**
     * 根据key获取Set中的所有值
     * @param key 键
     * @return
     */
    public Set sGet(String key){
        try {
            return redisTemplate.opsForSet().members(key);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    /**
     * 根据value从一个set中查询,是否存在
     * @param key 键
     * @param value 值
     * @return true 存在 false不存在
     */
    public boolean sHasKey(String key,Object value){
        try {
            return redisTemplate.opsForSet().isMember(key, value);
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 将数据放入set缓存
     * @param key 键
     * @param values 值 可以是多个
     * @return 成功个数
     */
    public long sSet(String key, Object...values) {
        try {
            return redisTemplate.opsForSet().add(key, values);
        } catch (Exception e) {
            e.printStackTrace();
            return 0;
        }
    }

    /**
     * 将set数据放入缓存
     * @param key 键
     * @param time 时间(秒)
     * @param values 值 可以是多个
     * @return 成功个数
     */
    public long sSetAndTime(String key,long time,Object...values) {
        try {
            Long count = redisTemplate.opsForSet().add(key, values);
            if(time>0) expire(key, time);
            return count;
        } catch (Exception e) {
            e.printStackTrace();
            return 0;
        }
    }

    /**
     * 获取set缓存的长度
     * @param key 键
     * @return
     */
    public long sGetSetSize(String key){
        try {
            return redisTemplate.opsForSet().size(key);
        } catch (Exception e) {
            e.printStackTrace();
            return 0;
        }
    }

    /**
     * 移除值为value的
     * @param key 键
     * @param values 值 可以是多个
     * @return 移除的个数
     */
    public long setRemove(String key, Object ...values) {
        try {
            Long count = redisTemplate.opsForSet().remove(key, values);
            return count;
        } catch (Exception e) {
            e.printStackTrace();
            return 0;
        }
    }
    //===============================list=================================

    /**
     * 获取list缓存的内容
     * @param key 键
     * @param start 开始
     * @param end 结束  0 到 -1代表所有值
     * @return
     */
    public List lGet(String key, long start, long end){
        try {
            return redisTemplate.opsForList().range(key, start, end);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    /**
     * 获取list缓存的长度
     * @param key 键
     * @return
     */
    public long lGetListSize(String key){
        try {
            return redisTemplate.opsForList().size(key);
        } catch (Exception e) {
            e.printStackTrace();
            return 0;
        }
    }

    /**
     * 通过索引 获取list中的值
     * @param key 键
     * @param index 索引  index>=0时, 0 表头,1 第二个元素,依次类推;index@return
     */
    public Object lGetIndex(String key,long index){
        try {
            return redisTemplate.opsForList().index(key, index);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    /**
     * 将list放入缓存
     * @param key 键
     * @param value 值
     * @return
     */
    public boolean lSet(String key, Object value) {
        try {
            redisTemplate.opsForList().rightPush(key, value);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 将list放入缓存
     * @param key 键
     * @param value 值
     * @param time 时间(秒)
     * @return
     */
    public boolean lSet(String key, Object value, long time) {
        try {
            redisTemplate.opsForList().rightPush(key, value);
            if (time > 0) expire(key, time);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 将list放入缓存
     * @param key 键
     * @param value 值
     * @return
     */
    public boolean lSet(String key, List value) {
        try {
            redisTemplate.opsForList().rightPushAll(key, value);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 将list放入缓存
     * @param key 键
     * @param value 值
     * @param time 时间(秒)
     * @return
     */
    public boolean lSet(String key, List value, long time) {
        try {
            redisTemplate.opsForList().rightPushAll(key, value);
            if (time > 0) expire(key, time);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 根据索引修改list中的某条数据
     * @param key 键
     * @param index 索引
     * @param value 值
     * @return
     */
    public boolean lUpdateIndex(String key, long index,Object value) {
        try {
            redisTemplate.opsForList().set(key, index, value);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 用于移除键中指定的元素。接受3个参数,分别是缓存的键名,计数事件,要移除的值。计数事件可以传入的有三个值,分别是-1、0、1。
     -1代表从存储容器的最右边开始,删除一个与要移除的值匹配的数据;0代表删除所有与传入值匹配的数据;1代表从存储容器的最左边开始,删除一个与要移除的值匹配的数据。
     * @param key 键
     * @param count
     * @param value 值
     * @return 移除的个数
     */
    public void lRemove(String key,long count,Object value) {
        try {
            redisTemplate.opsForList().remove(key, count, value);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

3、新建RedisConfig(主要是设置实例化redisTemplate,并设置序列化,同时实例化RedisUtil)

package com.redis.sentinel.demo.config;

import com.redis.sentinel.demo.util.RedisUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CachingConfigurerSupport;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.JdkSerializationRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;

/**
 * @author Administrator
 * @date 2019/03/19
 */
@Configuration
@EnableCaching  //开启缓存,还要继承于CachingConfigurerSupport,主要是为了注解@Cacheable、@CacheEvict、@CachePut等的使用
public class RedisConfig extends CachingConfigurerSupport {
    /**
     * 注入 RedisConnectionFactory
     */
    @Autowired
    RedisConnectionFactory redisConnectionFactory;

    /**
     * 实例化 RedisTemplate 对象
     *
     * @return
     */
    @Bean
    public RedisTemplate functionDomainRedisTemplate() {
        RedisTemplate redisTemplate = new RedisTemplate<>();
        initDomainRedisTemplate(redisTemplate, redisConnectionFactory);
        return redisTemplate;
    }

    /**
     * 设置数据存入 redis 的序列化方式
     *
     * @param redisTemplate
     * @param factory
     */
    private void initDomainRedisTemplate(RedisTemplate redisTemplate, RedisConnectionFactory factory) {
        redisTemplate.setKeySerializer(new StringRedisSerializer());
        redisTemplate.setHashKeySerializer(new StringRedisSerializer());
        //只有设置jdk序列化,才能新类对象比如User进行存储
        redisTemplate.setHashValueSerializer(new JdkSerializationRedisSerializer());
        redisTemplate.setValueSerializer(new JdkSerializationRedisSerializer());
        redisTemplate.setConnectionFactory(factory);
    }

    /**
     * 实例化RedisUtil
     * @param redisTemplate
     * @return
     */
    @Bean
    public RedisUtil redisUtil(RedisTemplate redisTemplate) {
        RedisUtil redisUtil = new RedisUtil();
        redisUtil.setRedisTemplate(redisTemplate);
        return redisUtil;
    }
}

4、创建RedisTestController

package com.redis.sentinel.demo.controller;

import com.redis.sentinel.demo.model.User;
import com.redis.sentinel.demo.util.RedisUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * @author Administrator
 * @date 2019/03/19
 */
@RestController
@RequestMapping("/redis-sentinel")
public class RedisTestController {
    @Autowired
    private RedisUtil redisUtil;
    @RequestMapping(value = "/test",method = RequestMethod.POST)
    public void postTest(){
        testCommon();
        testHash();
        testSet();
        testList();
    }

    private void testCommon(){
        System.out.println("================================测试普通缓存==================");
        System.out.println("普通缓存,存入 key01 值为value01 到期时间为5秒");
        redisUtil.set("key01","value01",5);
        System.out.println("从redis获取key01的值:"+redisUtil.get("key01"));
        System.out.println("到期时间为:"+redisUtil.getExpire("key01"));
        try {
            Thread.sleep(5000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("6秒后从redis获取key01的值:"+redisUtil.get("key01"));
        System.out.println("key01是否存在:"+redisUtil.hasKey("key01"));
    }

    private void testHash(){
        System.out.println("================================测试Hash缓存==================");
        System.out.println("hash缓存,存入 key03 值为{\"name\":\"zhangsan\",\"sex\":\"man\"}");
        Map map = new HashMap<>();
        map.put("name","zhangsan");
        map.put("sex","man");
        redisUtil.hmset("key03",map);
        System.out.println("key03:"+redisUtil.hget("key03","name")+"  "+redisUtil.hget("key03","sex"));
        redisUtil.del("key03");
    }

    private void testSet(){
        System.out.println("================================测试Set缓存==================");
        System.out.println("Set缓存,将两个User放入缓存key04");
        redisUtil.sSet("key04",new User("name1","man"),new User("name2","femal"));
        Set users = redisUtil.sGet("key04");
        for(Object o:users){
            User user = (User)o;
            System.out.println(o.toString());
        }
        System.out.println("获取Set key04的长度:"+redisUtil.sGetSetSize("key04"));
        System.out.println("删除key04");
        redisUtil.del("key04");
        System.out.println("获取Set key04的长度:"+redisUtil.sGetSetSize("key04"));

    }

    private void testList(){
        System.out.println("================================测试List缓存==================");
        System.out.println("List缓存key05");
        redisUtil.lSet("key05", Arrays.asList("aa","bb","cc","dd","ee","ff","gg"));
        System.out.println("List缓存key06");
        redisUtil.lSet("key06","11");
        redisUtil.lSet("key06","22");
        redisUtil.lSet("key06","33");
        redisUtil.lSet("key06","44");
        redisUtil.lSet("key06","55");
        redisUtil.lSet("key06","66");
        redisUtil.lSet("key06","77");
        System.out.println("以上两种方式的缓存是有区别的,注意看下面的长度");
        System.out.println("输出key05的长度:"+redisUtil.lGetListSize("key05"));
        List list = redisUtil.lGet("key05",0,redisUtil.lGetListSize("key05"));
        System.out.println("输出key05的所有元素");
        for(Object str:list){
            System.out.println(str);
        }
        System.out.println("输出key06的长度:"+redisUtil.lGetListSize("key06"));
        List list1 = redisUtil.lGet("key06",0,redisUtil.lGetListSize("key06"));
        System.out.println("输出key06的所有元素");
        for(Object str:list1){
            System.out.println(str);
        }

        System.out.println("删除key06的的55");
        redisUtil.lRemove("key06",1,"55");
        List list2 = redisUtil.lGet("key06",0,redisUtil.lGetListSize("key06"));
        System.out.println("输出key06的长度:"+redisUtil.lGetListSize("key06"));
        System.out.println("输出key06的所有元素");
        for(Object str:list2){
            System.out.println(str);
        }

        redisUtil.del("key06");
        redisUtil.del("key05");

    }
}

5、创建springboot启动类

package com.redis.sentinel.demo;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

/**
 * @author Administrator
 * @date 2019/03/19
 */
@SpringBootApplication
public class Application {
    public static void main(String[] args){
        SpringApplication.run(Application.class, args);
    }
}

6、启动程序并用postman进行测试

springboot整合redis-sentinel支持Cache注解
================================测试普通缓存==================
普通缓存,存入 key01 值为value01 到期时间为5秒
从redis获取key01的值:value01
到期时间为:4
6秒后从redis获取key01的值:null
key01是否存在:false
================================测试Hash缓存==================
hash缓存,存入 key03 值为{"name":"zhangsan","sex":"man"}
key03:zhangsan  man
================================测试Set缓存==================
Set缓存,将两个User放入缓存key04
User{name='name2', sex='femal'}
User{name='name1', sex='man'}
获取Set key04的长度:2
删除key04
获取Set key04的长度:0
================================测试List缓存==================
List缓存key05
List缓存key06
以上两种方式的缓存是有区别的,注意看下面的长度
输出key05的长度:1
输出key05的所有元素
[aa, bb, cc, dd, ee, ff, gg]
输出key06的长度:7
输出key06的所有元素
11
22
33
44
55
66
77
删除key06的的55
输出key06的长度:6
输出key06的所有元素
11
22
33
44
66
77

三、使用Cache注解

1、@Cacheable

@Cacheable是用来声明方法是可缓存的。将结果存储到缓存中以便后续使用相同参数调用时不需执行实际的方法。直接从缓存中取值。最简单的格式需要制定缓存名称。主要用于查询。

参数 解释 示例 value 缓存的名称,必须指定至少一个

@Cacheable(value="users")@Cacheable(value={"users1","users2"}

key 缓存的 key,可以为空,如果指定要按照 SpEL 表达式编写,如果不指定,则缺省按照方法的所有参数进行组合

@Cacheable(value = "users", key = "#name")
@Cacheable(value = "users", key = "#p0")

condition 缓存的条件,可以为空,使用 SpEL 编写,返回 true 或者 false,只有为 true 才进行缓存

@Cacheable(value = "users",key = "#p0", condition = "#p0 != null")

2、@CachePut

如果缓存需要更新,且不干扰方法的执行,可以使用注解@CachePut。@CachePut标注的方法在执行前不会去检查缓存中是否存在之前执行过的结果,而是每次都会执行该方法,并将执行结果以键值对的形式存入指定的缓存中。

参数 解释 示例 value 缓存的名称,必须指定至少一个

@CachePut(value="users")@CachePut(value={"users1","users2"}

key 缓存的 key,可以为空,如果指定要按照 SpEL 表达式编写,如果不指定,则缺省按照方法的所有参数进行组合

@CachePut(value = "users", key = "#name")
@CachePut(value = "users", key = "#p0")

condition 缓存的条件,可以为空,使用 SpEL 编写,返回 true 或者 false,只有为 true 才进行缓存

@CachePut(value = "users",key = "#p0", condition = "#p0 != null")

3、@CacheEvict

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

参数 解释 示例 value 缓存的名称,必须指定至少一个

@CacheEvict(value="users")

key 缓存的 key,可以为空,如果指定要按照 SpEL 表达式编写,如果不指定,则缺省按照方法的所有参数进行组合

@CacheEvict(value = "users", key = "#name")
@CacheEvict(value = "users", key = "#p0")

condition 缓存的条件,可以为空,使用 SpEL 编写,返回 true 或者 false,只有为 true 才进行缓存

@CacheEvict(value = "users",key = "#p0", condition = "#p0 != null")

allEntries 缺省为 false,如果指定为 true,则方法调用后将立即清空所有缓存

@CacheEvict(value = "users",allEntries=true)

beforeInvocation 缺省为 false,如果指定为 true,则在方法还没有执行的时候就清空缓存,缺省情况下,如果方法执行抛出异常,则不会清空缓存

@CacheEvict(value = "users",beforeInvocation=true)

4、@Caching

有时候我们可能组合多个Cache注解使用

以上四个个注解的示例程序如下:

在上面的程中新建RedisCachableController

package com.redis.sentinel.demo.controller;

import com.redis.sentinel.demo.model.User;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.CachePut;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.cache.annotation.Caching;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import java.util.HashMap;
import java.util.Map;

/**
 * @author Administrator
 * @date 2019/03/21
 */
@RestController
@RequestMapping("/redis-sentinel-cache")
public class RedisCachableController {

    private Map userList = new HashMap<>();
    /**
     * 按key为user.name进行缓存
     * @param user
     * @return
     */
    @RequestMapping(value = "/add", method = RequestMethod.POST)
    @CachePut(value = "users", key = "#user.name")
    public User addUser(@RequestBody User user) {
        userList.put(user.getName(), user);
        return user;
    }

    /**
     * 组合多个Cache注解使用,按user.name和user.sex两个维度进行缓存
     * @param user
     * @return
     */
    @RequestMapping(value = "/add2", method = RequestMethod.POST)
    @Caching(put = {
            @CachePut(value = "users", key = "#user.name"),
            @CachePut(value = "users", key = "#user.sex")
    })
    public User addUser2(@RequestBody User user) {
        userList.put(user.getName(), user);
        return user;
    }

    /**
     * 先从缓存查数据,如果缓存没有,则到userList里面去拿。
     * @param name
     * @return
     */
    @RequestMapping(value = "/query", method = RequestMethod.GET)
    @Cacheable(value = "users", key = "#name", condition = "#name != null")
    public User queryUserByName(@RequestParam(value = "name") String name) {
        System.out.println("如果缓存没有,从map里面获取");
        User user = (User) userList.get(name);
        return user;
    }

    /**
     * 删除数据,从缓存中删除
     * @param name
     */
    @RequestMapping(value = "/del", method = RequestMethod.PUT)
    @CacheEvict(value = "users", key = "#name", condition = "#name != null")
    public void deleteUserByName(@RequestParam(value = "name") String name) {

    }
}

启动程序,用postman进行测试

1)执行add方法,将信息存入缓存

springboot整合redis-sentinel支持Cache注解

2)执行query方法,查看console

springboot整合redis-sentinel支持Cache注解

springboot整合redis-sentinel支持Cache注解

3)执行del方法,删除缓存

springboot整合redis-sentinel支持Cache注解

4)执行query方法,查看console

springboot整合redis-sentinel支持Cache注解

5、@CacheConfig

所有的@Cacheable()里面都有一个value=”xxx”的属性,这显然如果方法多了,写起来也是挺累的,如果可以一次性声明完 那就省事了, 所以,有了@CacheConfig这个配置,作用在类上面,可以将上面的Controller类进行改造

在上面的程中新建RedisCachableController1

package com.redis.sentinel.demo.controller;

import com.redis.sentinel.demo.model.User;
import org.springframework.cache.annotation.CacheConfig;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.CachePut;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.cache.annotation.Caching;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import java.util.HashMap;
import java.util.Map;

/**
 * @author Administrator
 * @date 2019/03/21
 */
@RestController
@RequestMapping("/redis-sentinel-cache2")
@CacheConfig(cacheNames = "users")
public class RedisCachableController1 {

    private Map userList = new HashMap<>();
    /**
     * 按key为user.name进行缓存
     * @param user
     * @return
     */
    @RequestMapping(value = "/add", method = RequestMethod.POST)
    @CachePut(key = "#user.name")
    public User addUser(@RequestBody User user) {
        userList.put(user.getName(), user);
        return user;
    }

    /**
     * 组合多个Cache注解使用,按user.name和user.sex两个维度进行缓存
     * @param user
     * @return
     */
    @RequestMapping(value = "/add2", method = RequestMethod.POST)
    @Caching(put = {
            @CachePut( key = "#user.name"),
            @CachePut( key = "#user.sex")
    })
    public User addUser2(@RequestBody User user) {
        userList.put(user.getName(), user);
        return user;
    }

    /**
     * 先从缓存查数据,如果缓存没有,则到userList里面去拿。
     * @param name
     * @return
     */
    @RequestMapping(value = "/query", method = RequestMethod.GET)
    @Cacheable( key = "#p0", condition = "#p0 != null")
    public User queryUserByName(@RequestParam(value = "name") String name) {
        System.out.println("如果缓存没有,从map里面获取");
        User user = (User) userList.get(name);
        return user;
    }

    /**
     * 删除数据,从缓存中删除
     * @param name
     */
    @RequestMapping(value = "/del", method = RequestMethod.PUT)
    @CacheEvict(key = "#name", condition = "#name != null")
    public void deleteUserByName(@RequestParam(value = "name") String name) {

    }
}

SpEL表达式

Spring Cache提供了一些供我们使用的SpEL上下文数据,下表直接摘自Spring官方文档:

名称位置描述示例 methodName root对象 当前被调用的方法名 root.methodName method root对象 当前被调用的方法 root.method.name target root对象 当前被调用的目标对象 root.target targetClass root对象 当前被调用的目标对象类 root.targetClass args root对象 当前被调用的方法的参数列表 root.args[0] caches root对象 当前方法调用使用的缓存列表(如@Cacheable(value={“cache1”, “cache2”})),则有两个cache root.caches[0].name argument name 执行上下文 当前被调用的方法的参数,如findById(Long id),我们可以通过#id拿到参数 user.id result 执行上下文 方法执行后的返回值(仅当方法执行之后的判断有效,如’unless’,’cache evict’的beforeInvocation=false) result

Original: https://www.cnblogs.com/boshen-hzb/p/10570389.html
Author: 波神
Title: springboot整合redis-sentinel支持Cache注解

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/529064/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

  • PHP PDF转图片

    Windows环境下 一、开启 Imagick 扩展 1、安装PHP扩展:Imagick,下载地址 https://pecl.php.net/package/imagick 注意和…

    Linux 2023年6月7日
    099
  • Shell 函数带中横线问题排查

    Shell 中编写的函数,如果函数名中带了中横线,在使用 /bin/sh 执行时会报错。 ➜ subprocess git:(master) ✗ cat kubectl.sh _k…

    Linux 2023年5月28日
    086
  • Twikoo私有化部署教程–迁移腾讯云

    备份数据 私有化部署 创建容器 导入数据 重新配置twikoo面板设置 引入前端CDN Nginx https反代http 作者:小牛呼噜噜 | https://xiaoniuhu…

    Linux 2023年6月6日
    0144
  • Makefile

    target … : prerequisites … command … … target可以是一个object file(目标文件),也可以是一个执行文件,还可以…

    Linux 2023年6月7日
    094
  • 4个实验,彻底搞懂TCP连接的断开

    前言 看到这个标题你可能会说,TCP 连接的建立与断开,这个我熟,不就是三次握手与四次挥手嘛。且慢,脑海中可以先尝试回答这几个问题: 四次挥手是谁发起的? 如果断电/断网了连接会断…

    Linux 2023年5月27日
    097
  • shell中的段落注释

    摘自: 感叹号可以用任意的串和字符替代,比如 注意!和BLOCK之前不能有空格,但是可以用Tab Original: https://www.cnblogs.com/LiuYanY…

    Linux 2023年5月28日
    086
  • Redis设置密码

    设置密码有两种方式。 运行cmd切换到redis根目录,先启动服务端 ><span class="hljs-selector-tag">red…

    Linux 2023年5月28日
    084
  • Docker学习笔记

    镜像下载、域名解析、时间同步请点击阿里云开源镜像站 Docker概述 Docker学习链接 官网链接:Home – Docker Docker与虚拟机比较 虚拟化技术 …

    Linux 2023年5月27日
    0103
  • Android的调用C++代码报错解决办法汇总

    汇总Android通过JNI调用C++代码遇到的错误 IDE:Android Studio BumBlebee | 2021.1.1 dlopen failed: library …

    Linux 2023年6月13日
    0107
  • 解决word插入新图片后原有图片题注的交叉引用错乱的问题

    引言 在日常工作和生活中,我们经常使用word来撰写文档、论文。为了更好地管理文档中的图片以及在正文中引用图片标题,需要借助题注来实现。通过题注,可以在正文中交叉引用图片,并为引用…

    Linux 2023年6月7日
    0144
  • Docker搭建Redis Cluster集群及扩容和收容

    上一篇文章讲解了Redis集群原理及搭建,由于工作中使用docker较多,本文主要讲解使用docker搭建集群及对集群的扩展收容。环境:Centos7.6Docker:20.10….

    Linux 2023年6月13日
    080
  • make

    make 背景 gcc 在编译一个包含多个源文件的工程时, gcc需要将每一个源文件都编译一遍,任何再链接起来形成一个可执行文件。实际上,用户很少对所有源文件都进行修改,这就会造成…

    Linux 2023年6月7日
    0104
  • LeetCode-329. 矩阵中的最长递增路径

    题目来源 329. 矩阵中的最长递增路径 题目详情 给定一个 m x n 整数矩阵 matrix ,找出其中 最长递增路径 的长度。 对于每个单元格,你可以往上,下,左,右四个方向…

    Linux 2023年6月7日
    074
  • .Net中Aspose组件调试技巧

    | 0.48分钟 | 774.4字符 | 1、引言&背景 2、水印或截断问题解决 3、即时调试的技巧 4、声明与参考资料 | SCscHero | 2022/6/4 PM2…

    Linux 2023年6月13日
    079
  • Python实现经典算法八皇后问题

    递归回溯解八皇后问题 遗传算法解八皇后问题 在8×8格的国际象棋上摆放八个皇后,使其不能互相攻击,即任意两个皇后都不能处于同一行、同一列或同一斜线上,问一共有多少种摆法。 分别用递…

    Linux 2023年6月7日
    0131
  • Docker私有仓库部署

    修改daemon.json 重启docker服务 镜像上传至私有仓库 标记此镜像为私有仓库的镜像 再次启动私服容器 Original: https://www.cnblogs.co…

    Linux 2023年6月8日
    073
亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球