SpringBoot中整合Redis(缓存篇)

实际开发中缓存处理是必须的,不可能我们每次客户端去请求一次服务器,服务器每次都要去数据库中进行查找,为什么要使用缓存?说到底是为了提高系统的运行速度。将用户频繁访问的内容存放在离用户最近,访问速度最快的地方,提高用户的响应速度,今天先来讲下在springboot中整合redis的详细步骤。

一、安装

redis下载地址:

https://redis.io/download

首先要在本地安装一个redis程序,安装过程十分简单(略过),安装完成后进入到redis文件夹中可以看到如下:

SpringBoot中整合Redis(缓存篇)

点击redis-server.exe开启redis服务,可以看到如下图所示即代表开启redis服务成功:

SpringBoot中整合Redis(缓存篇)

那么我们可以开启redis客户端进行测试:

SpringBoot中整合Redis(缓存篇)

二、整合到springboot

1、在项目中加入redis依赖,pom文件中添加如下:

<!-- 整合Redis缓存支持 -->  


        <dependency>  


            <groupId>org.springframework.boot</groupId>  


            <artifactId>spring-boot-starter-data-redis</artifactId>  

        </dependency> 

2、在application.yml中添加redis配置:

##默认密码为空  


redis:  


      host: 127.0.0.1  


      # Redis服务器连接端口  


      port: 6379  


      jedis:  


        pool:  


          #连接池最大连接数(使用负值表示没有限制)  


          max-active: 100  


          # 连接池中的最小空闲连接  


          max-idle: 10  


          # 连接池最大阻塞等待时间(使用负值表示没有限制)  


          max-wait: 100000  


      # 连接超时时间(毫秒)  


      timeout: 5000  


      #默认是索引为0的数据库  

      database: 0  

3、新建RedisConfiguration配置类,继承CachingConfigurerSupport,@EnableCaching开启注解

@Configuration  


@EnableCaching  


public class RedisConfiguration extends CachingConfigurerSupport {  


    /**  


     * 自定义生成key的规则  


     */  


    @Override  


    public KeyGenerator keyGenerator() {  


        return new KeyGenerator() {  


            @Override  


            public Object generate(Object o, Method method, Object... objects) {  


                //格式化缓存key字符串  


                StringBuilder sb = new StringBuilder();  


                //追加类名  


                sb.append(o.getClass().getName());  


                //追加方法名  


                sb.append(method.getName());  


                //遍历参数并且追加  


                for (Object obj : objects) {  


                    sb.append(obj.toString());  


                }  


                System.out.println("调用Redis缓存Key : " + sb.toString());  


                return sb.toString();  


            }  


        };  


    }   


    /**  


     * 采用RedisCacheManager作为缓存管理器  


     * @param connectionFactory  


     */  


    @Bean  


    public CacheManager cacheManager(RedisConnectionFactory connectionFactory) {  


        RedisCacheManager redisCacheManager = RedisCacheManager.create(connectionFactory);  


        return  redisCacheManager;  


    }  


    @Bean  


    public RedisTemplate<String, String> redisTemplate(RedisConnectionFactory factory) {  


        ////解决键、值序列化问题  


        StringRedisTemplate template = new StringRedisTemplate(factory);  


        Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);  

        ObjectMapper om = new ObjectMapper(); 

         om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);  


        om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);  


        jackson2JsonRedisSerializer.setObjectMapper(om);  


        template.setValueSerializer(jackson2JsonRedisSerializer);  


        template.afterPropertiesSet();  


        return template;  


    }  

} 

4、创建自定义的接口来定义需要的redis的功能

/**  


 * K 指以hash结构操作时 键类型  


 * T 为数据实体 应实现序列化接口,并定义serialVersionUID * RedisTemplate 提供了五种数据结构操作类型 hash / list / set / zset / value  


 * 方法命名格式为 数据操作类型 + 操作 如 hashPut 指以hash结构(也就是map)想key添加键值对   


 */  


public interface RedisHelper<HK, T> {  


    /**  


     * Hash结构 添加元素 * @param key key * @param hashKey hashKey * @param domain 元素  


     */  


    void hashPut(String key, HK hashKey, T domain);  


    /**  


     * Hash结构 获取指定key所有键值对 * @param key * @return  


     */  


    Map<HK, T> hashFindAll(String key);   


    /**  


     * Hash结构 获取单个元素 * @param key * @param hashKey * @return  


     */  


    T hashGet(String key, HK hashKey);  


    void hashRemove(String key, HK hashKey);  


    /**  


     * List结构 向尾部(Right)添加元素 * @param key * @param domain * @return  


     */  


    Long listPush(String key, T domain);  


    /**  


     * List结构 向头部(Left)添加元素 * @param key * @param domain * @return  


     */  


    Long listUnshift(String key, T domain);  


    /**  


     * List结构 获取所有元素 * @param key * @return  


     */  


    List<T> listFindAll(String key);  


    /**  


     * List结构 移除并获取数组第一个元素 * @param key * @return  


     */  


    T listLPop(String key);  


    /**  


     * 对象的实体类  


     * @param key  


     * @param domain  


     * @return  


     */  


    void valuePut(String key, T domain);  


    /**  


     * 获取对象实体类  


     * @param key  


     * @return  


     */  


    T getValue(String key);  


    void remove(String key);  


    /**  


     * 设置过期时间 * @param key 键 * @param timeout 时间 * @param timeUnit 时间单位  


     */  


    boolean expirse(String key, long timeout, TimeUnit timeUnit);  

} 

下面是创建RedisHelperImpl进行接口的实现

@Service("RedisHelper")  


public class RedisHelperImpl<HK, T> implements RedisHelper<HK, T> {  


    // 在构造器中获取redisTemplate实例, key(not hashKey) 默认使用String类型  


    private RedisTemplate<String, T> redisTemplate;  


    // 在构造器中通过redisTemplate的工厂方法实例化操作对象  


    private HashOperations<String, HK, T> hashOperations;  


    private ListOperations<String, T> listOperations;  


    private ZSetOperations<String, T> zSetOperations;  


    private SetOperations<String, T> setOperations;  


    private ValueOperations<String, T> valueOperations;  


    // IDEA虽然报错,但是依然可以注入成功, 实例化操作对象后就可以直接调用方法操作Redis数据库  


    @Autowired  


    public RedisHelperImpl(RedisTemplate<String, T> redisTemplate) {  


        this.redisTemplate = redisTemplate;  


        this.hashOperations = redisTemplate.opsForHash();  


        this.listOperations = redisTemplate.opsForList();  


        this.zSetOperations = redisTemplate.opsForZSet();  


        this.setOperations = redisTemplate.opsForSet();  


        this.valueOperations = redisTemplate.opsForValue();  


    }  


    @Override  


    public void hashPut(String key, HK hashKey, T domain) {  


        hashOperations.put(key, hashKey, domain);  


    }  


    @Override  


    public Map<HK, T> hashFindAll(String key) {  


        return hashOperations.entries(key);  


    }  


    @Override  


    public T hashGet(String key, HK hashKey) {  


        return hashOperations.get(key, hashKey);  


    }  


    @Override  


    public void hashRemove(String key, HK hashKey) {  


        hashOperations.delete(key, hashKey);  

    } 

    @Override  


    public Long listPush(String key, T domain) {  


        return listOperations.rightPush(key, domain);  


    }  


    @Override  


    public Long listUnshift(String key, T domain) {  


        return listOperations.leftPush(key, domain);  


    }  


    @Override  


    public List<T> listFindAll(String key) {  


        if (!redisTemplate.hasKey(key)) {  


            return null;  


        }  


        return listOperations.range(key, 0, listOperations.size(key));  


    }  


    @Override  


    public T listLPop(String key) {  


        return listOperations.leftPop(key);  


    }  


    @Override  


    public void valuePut(String key, T domain) {  


        valueOperations.set(key, domain);  


    }  


    @Override  


    public T getValue(String key) {  


        return valueOperations.get(key);  


    }  


    @Override  


    public void remove(String key) {  


        redisTemplate.delete(key);  


    }  


    @Override  


    public boolean expirse(String key, long timeout, TimeUnit timeUnit) {  


        return redisTemplate.expire(key, timeout, timeUnit);  


    }  

} 

三、测试

编写TestRedis类进行测试

@RunWith(SpringRunner.class)  


@SpringBootTest  


public class TestRedis {  


    @Autowired  


    private StringRedisTemplate stringRedisTemplate;  


    @Autowired  


    private RedisTemplate redisTemplate;  


    @Autowired  


    private RedisHelperImpl redisHelper;  


    @Test  


    public void test() throws Exception{  


//        基本写法  


//        stringRedisTemplate.opsForValue().set("aaa","111");  


//        Assert.assertEquals("111",stringRedisTemplate.opsForValue().get("aaa"));  


//        System.out.println(stringRedisTemplate.opsForValue().get("aaa"));  


        Author user=new Author();  


        user.setName("Alex");  


        user.setIntro_l("不会打篮球的程序不是好男人");  


        redisHelper.valuePut("aaa",user);  


        System.out.println(redisHelper.getValue("aaa"));  


    }  


    @Test  


    public void testObj() throws Exception {  


        Author user=new Author();  

        user.setName("Jerry"); 

         user.setIntro_l("不会打篮球的程序不是好男人!");  


        ValueOperations<String, Author> operations=redisTemplate.opsForValue();  


        operations.set("502", user);  


        Thread.sleep(500);  


        boolean exists=redisTemplate.hasKey("502");  


        if(exists){  


            System.out.println(redisTemplate.opsForValue().get("502"));  


        }else{  


            System.out.println("exists is false");  


        }  


        // Assert.assertEquals("aa", operations.get("com.neo.f").getUserName());  


    }  

} 

运行TestRedis测试类,结果如下:

SpringBoot中整合Redis(缓存篇)

注意:如果在RedisConfiguration中不配置redisTemplate(RedisConnectionFactory factory)注解,会造成键、值的一个序列化问题,有兴趣的可以去试一下。序列化:序列化框架的选型和比对

四、项目实战

首先需要在程序的入口处Application中添加@EnableCaching开启缓存的注解

@EnableCaching  //开启缓存  


@SpringBootApplication  


public class PoetryApplication {  


    public static void main(String[] args) {  


        SpringApplication.run(PoetryApplication.class, args);  


    }  

} 

上面的redis相关写法是我们自定义设置并获取的,那么我们经常要在访问接口的地方去使用redis进行缓存相关实体对象以及集合等,那么我们怎么实现呢?

比如我现在想在AuthorController中去缓存作者相关信息的缓存数据,该怎么办呢?如下:

相关推荐