文章目录

  • 前文
  • 简介
  • SpringBoot 整合 Redis
  • 添加依赖
  • 配置 Redis
  • 创建实体类
  • @RedisAutoConfiguration
  • 编写控制器代码
  • RedisTemplate 与 StringRedisTemplate 操作
  • RedisTemplate
  • StringRedisTemplate
  • 自定义一个 RedisTemplate


前文

Redis 的下载安装
Redis 的简单实用

简介

Redis 的 Java 客户端有很多种,例如 Jedis、JRedis、Spring Data Redis 等,SpringBoot 借助于 Spring Data Redis 为 Redis 提供了开箱即用的自动化配置,开发者只需要添加相关的依赖并配置 Redis 连接信息即可

SpringBoot 整合 Redis

SpringBoot 操作数据:spring-data、jpa、jdbc、mongodb、redis

SpringData 也是和 SpringBoot 齐名的项目

说明

在 SpringBoot 2.x 之后,原来使用 jedis 被替换成了 lettuce

  • jedis:采用直连的放是,多个线程操作的话,是不安全的,如果想要避免不安全的,使用 jedis pool 连接池!BIO
  • lettuce:采用 Netty,实例可以在多线程中进行共享,不存在线程不安全情况!可以减少线程数量了,更像 NIO 模式

添加依赖

<dependencies>

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

	<dependency>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-test</artifactId>
		<scope>test</scope>
		<exclusions>
			<exclusion>
				<groupId>org.junit.vintage</groupId>
				<artifactId>junit-vintage-engine</artifactId>
			</exclusion>
		</exclusions>
	</dependency>
</dependencies>

配置 Redis

spring.redis.database=0
# Redis 的实例地址
spring.redis.host=127.0.0.1
# Redis 的默认端口号
spring.redis.port=6379
# Redis 的登录密码
spring.redis.password=
# Redis 连接池的最大连接数
spring.redis.jedis.pool.max-active=8
# Redis 连接池中的最大空闲连接数
spring.redis.jedis.pool.max-idle=8
# 表示连接池的最大阻塞等待时间,默认为 -1,表示没有限制
spring.redis.jedis.pool.max-wait=-1ms
# 表示连接池的最小空闲连接数
spring.redis.jedis.pool.min-idle=0

在设置密码的时候如果是不知道 Redis 的密码的可以这样做:
启动 redis 的客户端程序,输入以下命令

config get requirepass   # 获取密码

springboot 集成redis redis重连问题 redis springboot整合_Redis


如果要设置新的密码,输入以下命令

config set requirepass 你要设置的密码 # 设置密码

然后再次输入获取密码的命令时可能会报以下的错误

(error) NOAUTH Authentication required.

只要输入 auth 你设置的密码 就可以了

创建实体类

package com.example.demo.entity;

import java.io.Serializable;

public class User implements Serializable {

    private Integer id;

    private String name;

    private String info;

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getInfo() {
        return info;
    }

    public void setInfo(String info) {
        this.info = info;
    }

    @Override
    public String toString() {
        return "User{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", info='" + info + '\'' +
                '}';
    }
}

@RedisAutoConfiguration

SpringBoot 的自动配置类中提供了 RedisAutoConfiguration 注解进行 Redis 的自动装配,源码如下:

@Configuration(
    proxyBeanMethods = false
)
@ConditionalOnClass({RedisOperations.class})
@EnableConfigurationProperties({RedisProperties.class})
@Import({LettuceConnectionConfiguration.class, JedisConnectionConfiguration.class})
public class RedisAutoConfiguration {
    public RedisAutoConfiguration() {
    }

    @Bean
    @ConditionalOnMissingBean(name = {"redisTemplate"}) // 我们可以自定义一个 RedisTemplate 来替换这个默认的
    public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) throws UnknownHostException {
    	// 默认的 RedisTemplate 没有过多的设置,redis 对象都是需要序列化的
    	// 两个泛型都是 Object 类型,Object 类型我们使用需要强制转换<String, Object>
        RedisTemplate<Object, Object> template = new RedisTemplate();
        template.setConnectionFactory(redisConnectionFactory);
        return template;
    }

    @Bean
    @ConditionalOnMissingBean  // 由于 String 是 redis 中最常用的类型,所以说单独提出来一个 bean
    public StringRedisTemplate stringRedisTemplate(RedisConnectionFactory redisConnectionFactory) throws UnknownHostException {
        StringRedisTemplate template = new StringRedisTemplate();
        template.setConnectionFactory(redisConnectionFactory);
        return template;
    }
}

从 @RedisAutoConfiguration 注解的源码可以知道,该注解定义了两个 Bean:

  • RedisTemplate
  • StringRedisTemplate

而且 application.properties 中的配置信息会被注入到 RedisProperties 中,如果开发者自己没有提供 RedisTemplate 或者 StringRedisTemplate 实例,则 SpringBoot 默认会提供这两个实例,RedisTemplate 和 StringRedisTemplate 实例则提供了 Redis 的基本操作方法

编写控制器代码

RedisTemplate 与 StringRedisTemplate 操作

RedisTemplate

package com.example.demo.controller;

import com.example.demo.entity.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class UserController {

    @Autowired
    private RedisTemplate redisTemplate;

    @GetMapping("test")
    public void test() {
    	// opsForValue 操作字符串 类似 String
    	// opsForList 操作 list 类似 list
    	// opsForSet 操作 set 类似 set
    	// opsForHash 操作 hash 类似 hash
    	// opsForZset 操作 zset 类似 zset
        ValueOperations opsForValue = redisTemplate.opsForValue();
        User setUser = new User();
        setUser.setId(1);
        setUser.setName("John");
        setUser.setInfo("我爱打篮球");
        opsForValue.set("user",setUser);
        User getUser = (User) opsForValue.get("user");
        System.out.println(getUser);
    }
}

在浏览器中访问 http://localhost:8080/test,控制台显示如下:

springboot 集成redis redis重连问题 redis springboot整合_redis_02

StringRedisTemplate

package com.example.demo.controller;

import com.example.demo.entity.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class UserController {

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    @GetMapping("test")
    public void test() {
        ValueOperations<String,String> opsForValue = stringRedisTemplate.opsForValue();
        opsForValue.set("name","lisa");
        String name = opsForValue.get("name");
        System.out.println(name);
    }
}

在浏览器中访问 http://localhost:8080/test,控制台显示如下:

springboot 集成redis redis重连问题 redis springboot整合_spring_03

  • StringRedisTemplate 是 RedisTemplate 的子类,StringRedisTemplate 中的 key 和 value 都是字符串,采用的序列化的方案是 StringRedisSerializer,而 RedisTemplate 则可以用来操作对象,RedisTemplate 采用的序列化方案是 JdkSerializationRedisSerializer,无论是 StringRedisTemplate 还是 RedisTemplate,操作 Redis 的方法都是一样的
  • StringRedisTemplate 和 RedisTemplate 都是通过 opsForValue、opsForZSet 或者 opsForSet 等方法首先获取一个操作对象,再使用该操作对象完成数据的读写

自定义一个 RedisTemplate

代码中会使用到 fastjson,所以我们需要引入 fastjson 的依赖

<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>fastjson</artifactId>
    <version>1.2.73</version>
</dependency>
package com.java;

import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.jsontype.impl.LaissezFaireSubTypeValidator;
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.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;

/**
 * @author Woo_home
 * @create by 2020/8/6  11:04
 */

@Configuration
public class RedisConfig {

    /**
     * 自定义 RedisTemplate
     * @param factory
     * @return
     */
    @Bean
    public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {
        // 我们为了自己开发方便,一般直接使用 <String, Object>
        RedisTemplate<String, Object> template = new RedisTemplate<>();
        template.setConnectionFactory(factory);

        // JSON 序列化配置
        Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
        ObjectMapper om = new ObjectMapper();
        om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        om.activateDefaultTyping(LaissezFaireSubTypeValidator.instance, ObjectMapper.DefaultTyping.NON_FINAL);
        jackson2JsonRedisSerializer.setObjectMapper(om);
        // String 的序列化
        StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();

        // key 采用 String 的序列化方式
        template.setKeySerializer(stringRedisSerializer);
        // hash 的 key 也采用 String 的序列化方式
        template.setHashKeySerializer(stringRedisSerializer);
        // value 序列化方式采用 jackson
        template.setValueSerializer(jackson2JsonRedisSerializer);
        // hash 的 value 序列化方式采用 jackson
        template.setHashValueSerializer(jackson2JsonRedisSerializer);
        template.afterPropertiesSet();

        return template;
    }
}

注意:

使用该版本的 fastjson 时,ObjectMapper 中的 enableDefaultTyping 方法都已经弃用了

springboot 集成redis redis重连问题 redis springboot整合_spring_04


所以建议使用 activateDefaultTyping 来替代 enableDefaultTyping 方法