SpringBoot整合Redis(单机版)

一:环境搭建.

      1.1 SpringBoot的环境是 1.5.10.RELEASE.

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

    1.2 已配置好开启Server服务的Redis一台.

   1.3 查看所有的key,发现是空的.(keys * 通配)

   1.4 IDEA下推荐一款插件,Redis的客户端工具.Iedis.

   下载链接:Iedis 提取码(9sjd).安装方式就是加载硬盘里面的插件,然后重新启动IDEA即可.

效果如下.

这里在命令行添加一个String类型的key看一下效果吧.

 

二:Redis的配置.

     2.1 由于前文我们源码分析了Data-Redis,对配置比较了解, 配置RestTemplate.这里使用RedisTemplate.StringRedisTemplate继承了RedisTemplate。

   2.2 application.properties添加连接信息.

#配置Redis
spring.redis.database=0
spring.redis.host=Redis IP
spring.redis.port=6379
spring.redis.password=123456
#最大连接数
spring.redis.pool.max-active=8
#最大阻塞时间,负值表示没有限制
spring.redis.pool.max-wait=-1
#最小空闲连接数
spring.redis.pool.min-idle=0
#最大空闲连接数
spring.redis.pool.max-idle=8
#连接超时时间(毫秒)
spring.redis.timeout=10000

 2.3 Java注解配置RedisTemplate.

       RedisCacheConfig(注意导包的正确性)配置泛型类型<Object, Object>

import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.connection.jedis.JedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import redis.clients.jedis.JedisPoolConfig;
/**
 * author: 
 * date: 
 * time: 
 * description: 配置Redis缓存
 */
@Configuration
public class RedisCacheConfig {
   @Value("${spring.redis.database}")
   private int database;
   @Value("${spring.redis.host}")
   private String host;
   @Value("${spring.redis.port}")
   private int port;
   @Value("${spring.redis.password}")
   private String password;
   @Value("${spring.redis.pool.max-active}")
   private int maxActive;
   @Value("${spring.redis.pool.max-idle}")
   private int maxIdle;
   @Value("${spring.redis.pool.min-idle}")
   private int minIdle;
   @Value("${spring.redis.pool.max-wait}")
   private int maxWait;

   /** 配置JedisConnectionFactory*/
   @Bean
   public JedisConnectionFactory jedisConnectionFactory(){
       JedisConnectionFactory factory=new JedisConnectionFactory();
       factory.setDatabase(database);
       factory.setHostName(host);
       factory.setPassword(password);
       factory.setPort(port);
       JedisPoolConfig jedisPoolConfig=new JedisPoolConfig();
       jedisPoolConfig.setMaxTotal(maxActive);
       jedisPoolConfig.setMaxIdle(maxIdle);
       jedisPoolConfig.setMinIdle(minIdle);
       jedisPoolConfig.setMaxWaitMillis(maxWait);
       factory.setPoolConfig(jedisPoolConfig);
       return factory;
   }
   /** SpringBoot自定义配置RedisTemplate*/
   @Bean
   @SuppressWarnings({"rawtypes", "unchecked"})
   public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
       RedisTemplate<Object, Object> template=new RedisTemplate<>();
       template.setConnectionFactory(redisConnectionFactory);
       // 使用Jackson2JsonRedisSerialize 替换默认序列化
       Jackson2JsonRedisSerializer jackson2JsonRedisSerializer=new Jackson2JsonRedisSerializer(Object.class);
       ObjectMapper mapper=new ObjectMapper();
       mapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
       mapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
       jackson2JsonRedisSerializer.setObjectMapper(mapper);
       // 设置value的序列化规则和 key的序列化规则
       template.setValueSerializer(jackson2JsonRedisSerializer);
       template.setKeySerializer(new StringRedisSerializer());
       template.setHashKeySerializer(new StringRedisSerializer());
       template.afterPropertiesSet();
       return  template;
   }
}

2.4                        方式一:使用Jedis提供的Java客户端API方法操作Redis.

     RedisController如下.

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.*;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
 * author: 
 * date: 
 * time: 
 * description:Redis的五种数据类型操作
 */
@RestController
@RequestMapping("/redis")
public class RedisController {
    @Autowired
    private RedisTemplate<Object, Object> redisTemplate;

    @RequestMapping("/value")
    public Object redis(){
        redisTemplate.opsForValue().set("name", "tomcat");
        ValueOperations<Object, Object> value=redisTemplate.opsForValue();
        Object name=value.get("name").toString();
        // 输出value
        System.out.println("获取的值:"+name);
        return name;
    }

    @RequestMapping("/list")
    public List<Object> list(){
        ListOperations<Object, Object> list=redisTemplate.opsForList();
        list.leftPush("s-list", "Chinese");
        list.leftPush("s-list", "Math");
        list.leftPush("s-list", "English");
        // 输出list
        System.out.println(list.range("s-list",0,2));
        List<Object> resultList=list.range("s-list",0,2);
        return resultList;
    }

    @RequestMapping("/set")
    public Set<Object> set(){
        SetOperations<Object, Object> set = redisTemplate.opsForSet();
        set.add("p-set", "ps");
        set.add("p-set", "27");
        set.add("p-set", "180cm");
        // 输出set
        System.out.println(set.members("p-set"));
        Set<Object> resultSet=set.members("p-set");
        return resultSet;
    }

   @RequestMapping("/zset")
   public Set<Object> zset(){
       ZSetOperations<Object, Object> zset=redisTemplate.opsForZSet();
       zset.add("z-set", "ps", 0);
       zset.add("z-set", "27", 1);
       zset.add("z-set", "180cm",2);
       // 输出zset
       System.out.println(zset.range("z-set",0, 2));
       Set<Object> resultZSet=zset.range("z-set",0, 2);
       return resultZSet;
   }

   @RequestMapping("/hash")
    public Map<Object,Object> hash(){
        HashOperations<Object, Object, Object> hash=redisTemplate.opsForHash();
        Map<Object, Object> map=new HashMap();
        map.put("name", "lucy");
        map.put("age", 22);
        map.put("address", "重庆市");
        hash.putAll("map",map);
        // 输出map
        System.out.println(hash.entries("map"));
        Map<Object, Object> resultMap=hash.entries("map");
        return resultMap;
   }
}

 浏览器测试如下:

  String类型的.

② List类型的.

③ Set类型的.

④:ZSet类型的.

⑤:Hash类型.

IDEA的Redis插件查看一下吧.

删除所有的key.del key(后面跟多个key,返回成功删除的个数).

                                               方式二:声明式注解操作

启动类添加@EnableCaching,开启声明式注解.

首先来看一下Spring对缓存的支持.

Spring定义了CacheManager和Cahce接口来统一不同的缓存技术,例如,单体版的缓存服务,分布式的缓存服务等,良好的可扩展性

CacheManager是Spring框架提供的各种缓存技术抽象接口.

Cahce接口包含缓存的各种操作(增加,删除,获取缓存).

CacheManager接口位置如下.

CacheManager.使用Spring缓存必不可少的.

getCache():获取指定的名称的缓存对象.

getCacheNames():返回Cache的集合.

SpringBoot为我们自动配置了多个CacheManager.不同我们自己配置CacheManagerle 那我们可以就 嘿嘿了.

SpringBoot默认是以spring.cache为前缀的属性配置缓存的.SpringBoot会自动根据spring.cahce的类型判断使用的缓存类型.

声明式缓存注解.

①:Cacheable

在方法执行前Spring先查看缓存中是否有数据,如果有数据,则直接返回缓存中的数据,如果没有数据,调用方法并将方法返回值放进缓存中.

②:CachePut

无论怎样,直接将方法的返回值放进缓存中.

③:CacheEvict

将一条或多条数据从缓存中删除.

④:Caching

可以通过@Caching注解将多个注解策略放在一个方法上.

配置RedisCacheManager.

@Bean
public CacheManager cacheManager(RedisTemplate<Object, Object> redisTemplate){
     RedisCacheManager cacheManager=new RedisCacheManager(redisTemplate);
     return cacheManager;
}

Service层使用缓存.

缓存对象集合中,缓存是以key-value形式保存的。当不指定缓存的key时,SpringBoot会使用SimpleKeyGenerator生成key。

由于key如果自己不指定默认就是方法的方法的所有参数组合.由于配置了Remplate的Key的规则是StringRedisSerializer.不能是Integer的入口参数,否则报类型不匹配的错误的.这里的key是使用的SpringEL获取的id值.如果不是能够获取的值就报如下错误的.

例如这样的写法 key="user-#id";

// key为id,value是方法的返回值
@Cacheable(value="UserCache",key="#id")
public User getUserById(String id) {
     System.out.println("开始查询");
        System.out.println("为id="+id+"的数据做了缓存!");
        Integer userId=Integer.valueOf(id);
        User user= userMapper.getUserById(Integer.valueOf(id));
        System.out.println("结束查询");
        return user;
    }

Controller层

@RestController
@RequestMapping("/annot/redis")
public class AnnotRedisController {
    
    @Autowired
    private UserService userService;

    @RequestMapping("/search/{id}")
    public User getUser(@PathVariable("id") String id){
        User user=null;
        if(id!=null){
            user=userService.getUserById(id);
        }
        return user;
 }

浏览器访问测试.@Cacheable

这个时候清空控制台,多次请求观察.发现控制台没有输出Service的开始查询执行的方法,是走了Redis缓存的.

这个时候查询一下缓存吧.

使用@CacheEvict从缓存XXX中删除key为id的数据.

Service层

 @Override
 @CacheEvict(value="UserCache")
    public int delete(String id) {
        System.out.println("删除了id="+id+"的数据缓存!");
        return userMapper.delete(Integer.valueOf(id));
 }

Controller层

    @RequestMapping("/delete/{id}")
    public String deleteUser(@PathVariable("id") String id){
        if(id!=null){
            userService.delete(id);
            return "Delete Success";
        }
        return "Delete Fail";
    }

浏览器测试一下吧.

查看删除效果.

@CachePut:是缓存新增或者是更新后的数据到缓存.测试一下吧.所以和@Cacheable的属性要一样的.缓存属性名和key要一致.

更新的是value值.

由于使用id的这种方式极容易出现重复的.冲突的.(使用是的参数名拼成的缓存key),如果两个方法的参数是一样的,但是里面的执行逻辑不同,这样我们执行第二个方法不就命中第一个方法的缓存了吗.

解决的方法就是我们自己制定key ,或者是实现一个KeyGenerator,在注解中指定KeyGenerator.在注解中指定KeyGenerator即可.但是如果这样的情况很多,每一个都要指定key、KeyGenerator很麻烦。

Spring框架提供:继承CachingConfigurerSupport并重写keyGenerator()。

  RedisCacheConfig继承CacingConfigurerSupport.

    @Bean
    public KeyGenerator userKeyGenerator() {
        return new KeyGenerator(){
            @Override
            public Object generate(Object target, Method method, Object... params) {
                StringBuilder builder=new StringBuilder();
                builder.append(target).append("-").append(method).append("-");
                for(Object obj:params){
        builder.append("-").append(obj);
             }
                return builder.toString();
             }
        };
                }

这样的缓存key就是包名+方法名+参数名了.只有三者都相同参会冲突的.

首先是访问id=4的用户,将数据由数据库查询出来存放至缓存里面.

至此完成了基于API方法调用和注解的两种方式整合了Redis.

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

大道之简

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

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

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

打赏作者

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

抵扣说明:

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

余额充值