由浅入深学习springboot中使用redis

springboot缓存有些方法

springboot配置升高简单化

自然上边包车型地铁配备只是为着打探原理的哈,实际上大家采用会更轻易点。我们重写了RedisConfig

图片 1图片 2

@Configuration
@EnableCaching//开启缓存
public class RedisConfig extends CachingConfigurerSupport {

    @Bean
    public KeyGenerator keyGenerator() {
        return new KeyGenerator() {
            @Override
            public Object generate(Object target, Method method, Object... params) {
                StringBuilder sb = new StringBuilder();
                sb.append(target.getClass().getName());
                sb.append(method.getName());
                for (Object obj : params) {
                    sb.append(obj.toString());
                }
                return sb.toString();
            }
        };
    }    
    /**
     * 申明缓存管理器,会创建一个切面(aspect)并触发Spring缓存注解的切点(pointcut)
     * 根据类或者方法所使用的注解以及缓存的状态,这个切面会从缓存中获取数据,将数据添加到缓存之中或者从缓存中移除某个值

     * @return
     */
    @Bean
    public RedisCacheManager cacheManager(RedisTemplate redisTemplate) {
        return new RedisCacheManager(redisTemplate);
    }


    @Bean
    @Primary
    public RedisTemplate redisTemplate(RedisConnectionFactory factory) {
        // 创建一个模板类
        RedisTemplate<String, Object> template = new RedisTemplate<String, Object>();
        // 将刚才的redis连接工厂设置到模板类中
        template.setConnectionFactory(factory);
        // 设置key的序列化器
        template.setKeySerializer(new StringRedisSerializer());
        // 设置value的序列化器
        //使用Jackson 2,将对象序列化为JSON
        Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
        //json转对象类,不设置默认的会将json转成hashmap
        ObjectMapper om = new ObjectMapper();
        om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
        jackson2JsonRedisSerializer.setObjectMapper(om);
        template.setValueSerializer(jackson2JsonRedisSerializer);

        return template;
    }

}

View Code

然后在resources下的application.properties下配置

图片 3图片 4

# REDIS (RedisProperties)
# Redis数据库索引(默认为0)
spring.redis.database=0  
# Redis服务器地址
spring.redis.host=127.0.0.1
# Redis服务器连接端口
spring.redis.port=6379  
# Redis服务器连接密码(默认为空)
spring.redis.password=
# 连接池最大连接数(使用负值表示没有限制)
spring.redis.pool.max-active=8  
# 连接池最大阻塞等待时间(使用负值表示没有限制)
spring.redis.pool.max-wait=-1  
# 连接池中的最大空闲连接
spring.redis.pool.max-idle=8  
# 连接池中的最小空闲连接
spring.redis.pool.min-idle=0  
# 连接超时时间(毫秒)
spring.redis.timeout=0

View Code

我们开掘大家并不曾注册RedisConnectionFactory,那是因为spring默许帮大家读取application.properties文件同一时间注册了贰个factorybean

keyGenerator方法帮大家报了名了叁个key的成形准绳,就不要大家写spel表达式了,依据反射的原理读取类名+方法名+参数。然而大家有的时候仍旧须要组合spel的。

接下来在controller上助长@Cacheable(“cachename”),之后就能够在redis观望保存了并且key的值是keyGenerator生成的名字

 

 

 条件化缓存

通过为艺术增添Spring的缓存申明,Spring就能够围绕着那个办法创建叁个缓存切面。可是,在多少场景下大家恐怕希望将缓存功用关闭。

@Cacheable和@CachePut提供了两脾个性用以达成条件化缓存:unless和condition,那多个属性都接受贰个SpEL表明式。固然unless属性的SpEL表明式总计结
果为true,那么缓存方法再次来到的多少就不会安置缓存中。与之类似,要是condition属性的SpEL表明式总括结果为false,那么对于这么些法子缓存就能够被禁止使用掉

表面上来看,unless和condition属性做的是大同小异的事体。可是,这里有一点点一线的差别。

unless属性只好阻止将对象放进缓存,不过在那几个措施调用的时候,如故会去缓存中实行查找,假诺找到了非凡的值,就能够回到找到的值。

与之分化,纵然condition的表达式总结结果为false,那么在这一个措施调用的进度中,缓存是被剥夺的。便是说,不会去缓存举行检索,同不常间再次来到值也不会放进缓存中。

 

    @RequestMapping("/getPrud2")
    @CachePut(value ="prudCache",unless="#result.desc.contains('nocache')")
    public Pruduct getPrud2(@RequestParam(required=true)String id){
        System.out.println("如果走到这里说明,说明缓存没有生效!");
        Pruduct p = new Pruduct(Integer.parseInt(id), "name_nocache"+id, "nocache");
        return p;
    }

 

地点的代码中,假使回到的靶子desc中富含nocache字符串,则不进行缓存。

 

redis连接工厂类 

首先步,必要加上springboot的redis jar包

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

接下来大家写三个配备类,成立了八个redis连接的厂子的spring
bean。(Redis连接工厂会转换到Redis数据库服务器的连天)

@Configuration
public class RedisConfig {
    @Bean
    public RedisConnectionFactory redisCF(){
        //如果什么参数都不设置,默认连接本地6379端口
        JedisConnectionFactory factory = new JedisConnectionFactory();
        factory.setPort(6379);
        factory.setHostName("localhost");
        return factory;
    }
}

单元测量试验,看看这么些工厂方法的利用

@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest(classes = Application.class)
public class RedisTest {

    @Autowired
    RedisConnectionFactory factory;

    @Test
    public void testRedis(){
        //得到一个连接
        RedisConnection conn = factory.getConnection();
        conn.set("hello".getBytes(), "world".getBytes());
        System.out.println(new String(conn.get("hello".getBytes())));
    }

}

输出结果
:world,表明已经打响收获到连年,并且往redis到手丰盛数据, 

加上缓存

接下去大家在controller层的措施内丰硕注脚,然后运营我们的品类。

    @RequestMapping("/getPrud")
    @Cacheable("prudCache")
    public Pruduct getPrud(@RequestParam(required=true)String id){
        System.out.println("如果第二次没有走到这里说明缓存被添加了");
        return pruductDao.getPrud(Integer.parseInt(id));
    }

意识打字与印刷的这段话只被打字与印刷二次,表明在走到这几个方法的时候接触了三个断面,並且查找再次回到缓存中的数据。

自然@Cacheable注明也能够放置这些dao层的艺术里面,但是此地会报贰个错,Integer不能够转成String,因为咱们dao层方法的参数类型是int,而RedisTemplate的key类型是String,这里是要注意的。

打开redis的客商端开掘redis对应的key便是我们的参数1,今年就能出标题,比如说笔者在另外要缓存的措施的参数也是1,就能够再一次。后边我们会将自定义这么些key的值。

除了这一个之外@Cacheable加多缓存外,springboot还为大家带了了其余几个申明

图片 5

template(模版)

不过大家开掘每回加多的key和value都以byte数组类型(使用很艰苦),于是spring为大家带来了redis
template(模版)

Spring Data Redis提供了三个模板:
  RedisTemplate
  StringRedisTemplate

第一大家先创立贰个RedisTemplate模板类,类型的key是String类型,value是Object类型(倘诺key和value都以String类型,提出使用StringRedisTemplate)

    @Bean
    public RedisTemplate redisTemplate(RedisConnectionFactory factory){
        //创建一个模板类
        RedisTemplate<String, Object> template = new RedisTemplate<String, Object>();
        //将刚才的redis连接工厂设置到模板类中
        template.setConnectionFactory(factory);
        return template;
    }

单元测量试验

    @Autowired    
    RedisTemplate<String, Object> template;

    @Test
    public void testRedisTemplate(){
        template.opsForValue().set("key1", "value1");
        System.out.println(template.opsForValue().get("key1"));
    }

获取结果输出value1,是否很有益于了呢。

 借使是操作集结呢,也很便利的哈。

    @Test
    public void testRedisTemplateList(){

        Pruduct prud  = new Pruduct(1, "洗发水", "100ml");
        Pruduct prud2  = new Pruduct(2, "洗面奶", "200ml");
        //依次从尾部添加元素
        template.opsForList().rightPush("pruduct", prud);
        template.opsForList().rightPush("pruduct", prud);
        //查询索引0到商品总数-1索引(也就是查出所有的商品)
        List<Object> prodList = template.opsForList().range("pruduct", 0,template.opsForList().size("pruduct")-1);
        for(Object obj:prodList){
            System.out.println((Pruduct)obj);
        }
        System.out.println("产品数量:"+template.opsForList().size("pruduct"));

    }

 


redis连接工厂类 

首先步,供给加上springboot的redis jar包

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

接下来大家写贰个配备类,创设了一个redis连接的厂子的spring
bean。(Redis连接工厂会调换到Redis数据库服务器的连日)

@Configuration
public class RedisConfig {
    @Bean
    public RedisConnectionFactory redisCF(){
        //如果什么参数都不设置,默认连接本地6379端口
        JedisConnectionFactory factory = new JedisConnectionFactory();
        factory.setPort(6379);
        factory.setHostName("localhost");
        return factory;
    }
}

单元测验,看看这么些工厂方法的应用

@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest(classes = Application.class)
public class RedisTest {

    @Autowired
    RedisConnectionFactory factory;

    @Test
    public void testRedis(){
        //得到一个连接
        RedisConnection conn = factory.getConnection();
        conn.set("hello".getBytes(), "world".getBytes());
        System.out.println(new String(conn.get("hello".getBytes())));
    }

}

输出结果 :world,表达已经打响博获得连年,並且往redis收获充足数据, 

自定义key

@Cacheable和@CachePut都有八个名称为key属性,那特性格可以替换暗中同意的key,它是因此三个表明式(Spel表明式,spring提供的,相当粗略)总括获得的。

举例下边包车型大巴就是将重回对象的id当做key来囤积(可是Pruduct的id是int类型,所以须求将数字转化成String类型)

    @RequestMapping("/savePrud")
    @CachePut(value="prudsaveCache",key="#result.id +''")
    public Pruduct savePrud(Pruduct prud){
        return prud;
    }

别的除了#result是意味着函数的重回值,spring还为我们带来了其他的部分元数据 

图片 6

自定义key

@Cacheable和@CachePut都有二个名叫key属性,那本性情能够替换暗中认可的key,它是经过一个表明式(Spel表达式,spring提供的,相当的粗略)总计获得的。

比方说下边包车型客车就是将赶回对象的id充任key来囤积(可是Pruduct的id是int类型,所以供给将数字转化成String类型)

    @RequestMapping("/savePrud")
    @CachePut(value="prudsaveCache",key="#result.id +''")
    public Pruduct savePrud(Pruduct prud){
        return prud;
    }

别的除了#result是表示函数的重返值,spring还为大家带来了其余的有的元数据 

图片 7

 条件化缓存

透过为艺术增加Spring的缓存评释,Spring就可以围绕着这几个方法成立三个缓存切面。可是,在有一点点场景下大家只怕希望将缓存成效关闭。

@Cacheable和@CachePut提供了多个本性用以完结条件化缓存:unless和condition,那多个属性都接受二个SpEL表明式。假若unless属性的SpEL表明式总计结
果为true,那么缓存方法重临的数额就不会安置缓存中。与之类似,如若condition属性的SpEL表达式总计结果为false,那么对于这一个格局缓存就能够被禁用掉

外部上来看,unless和condition属性做的是同样的事务。然则,这里有几许细小的异样。

unless属性只好阻止将对象放进缓存,不过在那么些法子调用的时候,依然会去缓存中开展查找,要是找到了相当的值,就能回到找到的值。

与之分化,假使condition的表达式总括结果为false,那么在这一个法子调用的经过中,缓存是被剥夺的。正是说,不会去缓存举行检索,同不常间重回值也不会放进缓存中。

 

    @RequestMapping("/getPrud2")
    @CachePut(value ="prudCache",unless="#result.desc.contains('nocache')")
    public Pruduct getPrud2(@RequestParam(required=true)String id){
        System.out.println("如果走到这里说明,说明缓存没有生效!");
        Pruduct p = new Pruduct(Integer.parseInt(id), "name_nocache"+id, "nocache");
        return p;
    }

 

地方的代码中,假诺回到的靶子desc中满含nocache字符串,则不实行缓存。

 

剔除缓存

在delete的时候用@CacheEvict清楚这条缓存。

    @RequestMapping("/deletePrud")
    @CacheEvict("pruddeleteCache")
    public String deletePrud(@RequestParam(required=true)String id){
        return "SUCCESS";
    }

@CachePut将那一个法子的归来值放到缓存,借使我们放三个Pruduct对象,他会将那几个指标作为key,这明明不是大家想要的。那个时候就供给自定义大家的key。

增加缓存

接下去大家在controller层的不二秘籍内拉长注脚,然后运维大家的花色。

    @RequestMapping("/getPrud")
    @Cacheable("prudCache")
    public Pruduct getPrud(@RequestParam(required=true)String id){
        System.out.println("如果第二次没有走到这里说明缓存被添加了");
        return pruductDao.getPrud(Integer.parseInt(id));
    }

开掘打印的这段话只被打印叁次,表明在走到那些形式的时候接触了一个断面,并且查找再次回到缓存中的数据。

当然@Cacheable表明也得以松开那几个dao层的不二秘技里面,但是这里会报叁个错,Integer不大概转成String,因为我们dao层方法的参数类型是int,而RedisTemplate的key类型是String,这里是要留意的。

开发redis的客商端发掘redis对应的key就是大家的参数1,那个时候就能够出标题,例如说作者在其余要缓存的艺术的参数也是1,就可以再也。后边我们会将自定义这几个key的值。

而外@Cacheable加多缓存外,springboot还为我们带了了其余多少个申明

图片 8

template(模版)

可是大家发现每一回增多的key和value都以byte数组类型(使用很艰难),于是spring为大家带来了redis
template(模版)

Spring Data Redis提供了三个模板:
  RedisTemplate
  StringRedisTemplate

首先大家先创立一个RedisTemplate模板类,类型的key是String类型,value是Object类型(即便key和value都以String类型,提议选取StringRedisTemplate)

    @Bean
    public RedisTemplate redisTemplate(RedisConnectionFactory factory){
        //创建一个模板类
        RedisTemplate<String, Object> template = new RedisTemplate<String, Object>();
        //将刚才的redis连接工厂设置到模板类中
        template.setConnectionFactory(factory);
        return template;
    }

单元测量试验

    @Autowired    
    RedisTemplate<String, Object> template;

    @Test
    public void testRedisTemplate(){
        template.opsForValue().set("key1", "value1");
        System.out.println(template.opsForValue().get("key1"));
    }

获得结果输出value1,是否很方便了啊。

 假诺是操作集结呢,也很有利的哈。

    @Test
    public void testRedisTemplateList(){

        Pruduct prud  = new Pruduct(1, "洗发水", "100ml");
        Pruduct prud2  = new Pruduct(2, "洗面奶", "200ml");
        //依次从尾部添加元素
        template.opsForList().rightPush("pruduct", prud);
        template.opsForList().rightPush("pruduct", prud);
        //查询索引0到商品总数-1索引(也就是查出所有的商品)
        List<Object> prodList = template.opsForList().range("pruduct", 0,template.opsForList().size("pruduct")-1);
        for(Object obj:prodList){
            System.out.println((Pruduct)obj);
        }
        System.out.println("产品数量:"+template.opsForList().size("pruduct"));

    }

 


注脚缓存管理器

在少数时候,我们或然有如此的必要,客户登陆的时候,大家会从数据库中读取客户具有的权能,部门等新闻。并且每一遍刷新页面都要求判别该客户有未有那一个权力,如若不停的从数据库中读而且计算,

是充裕耗品质的,所以我们那一年将要动用了springboot为大家带来的缓存管理器

 

率先在大家的RedisConfig这一个类上加上@EnableCaching这些证明。

本条注解会被spring发掘,何况会创设贰个断面(aspect)
并触发Spring缓存注解的切点(pointcut) 。
根据所运用的声明以及缓存的情况, 这一个切面会从缓存中获取数据,
将数据增长到缓存之中或许从缓存中移除有个别值。

 

接下去大家须要说美赞臣(Meadjohnson)个缓存管理器的bean,那几个意义正是@EnableCaching那些切面在疯长缓存或然去除缓存的时候会调用那些缓存管理器的不二秘诀

/**
     * 申明缓存管理器,会创建一个切面(aspect)并触发Spring缓存注解的切点(pointcut)
     * 根据类或者方法所使用的注解以及缓存的状态,这个切面会从缓存中获取数据,将数据添加到缓存之中或者从缓存中移除某个值

     * @return
     */
    @Bean
    public RedisCacheManager cacheManager(RedisTemplate redisTemplate) {
        return new RedisCacheManager(redisTemplate);
    }

 当然,缓存处理器除了RedisCacheManager还应该有一点另外的。举个例子

  1. SimpleCacheManager
  2. NoOpCacheManager
  3. ConcurrentMapCacheManager
  4. CompositeCacheManager
  5. EhCacheCacheManager

ConcurrentMapCacheManager,这些差不离的缓存管理器使用java.util.concurrent.ConcurrentHashMap作为其缓存存款和储蓄。它特别轻易,因而对于开采、测试或基础的选择来说,那是贰个很准确的选拔.

发表评论

电子邮件地址不会被公开。 必填项已用*标注