在springboot1.x中默认使用Jedis,而在springboot2.x中默认使用lettuce。
Jedis在实现上是直连的redis server,在多线程环境下是非线程安全的,这个时候只有使用连接池,为每个Jedis实例增加物理连接;
Lettuce的连接是基于Netty的,连接实例(StatefulRedisConnection)可以在多个线程间并发访问,因为StatefulRedisConnection是线程安全的,所以一个连接实例就可以满足多线程环境下的并发访问;
一、默认使用lettuce (推荐使用)
1. pom.xml中引入jar包
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-pool2</artifactId>
</dependency>
2. application.properties配置redis
spring.redis.host=127.0.0.1
spring.redis.port=6379
spring.redis.password=123
spring.redis.lettuce.pool.max-active=500
spring.redis.lettuce.pool.max-idle=300
spring.redis.lettuce.pool.max-wait=1000
spring.redis.lettuce.pool.min-idle=0
spring.redis.database=8
3.注册redis序列化
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration;
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;
import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
@Configuration
@AutoConfigureAfter(RedisAutoConfiguration.class)
public class RedisCacheConfig {
@Bean
public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory, RedisSerializer<Object> redisSerializer) {
RedisTemplate<String, Object> template = new RedisTemplate<>();
template.setConnectionFactory(redisConnectionFactory);
//RedisTemplate对象需要指明Key序列化方式,如果声明StringRedisTemplate对象则不需要
template.setKeySerializer(StringRedisSerializer.UTF_8);
template.setValueSerializer(redisSerializer);
template.setHashKeySerializer(StringRedisSerializer.UTF_8);
template.setHashValueSerializer(redisSerializer);
//template.setEnableTransactionSupport(true);//是否启用事务
template.afterPropertiesSet();
return template;
}
/**
* 自定义redis序列化的机制
*
* @return
*/
@Bean
public RedisSerializer<Object> redisSerializer() {
ObjectMapper objectMapper = new ObjectMapper();
//反序列化时候遇到不匹配的属性并不抛出异常
objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
//序列化时候遇到空对象不抛出异常
objectMapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);
//反序列化的时候如果是无效子类型,不抛出异常
objectMapper.configure(DeserializationFeature.FAIL_ON_INVALID_SUBTYPE, false);
//指定DATE序列化格式,默认时间戳
objectMapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"));
//不使用默认的dateTime进行序列化,
objectMapper.configure(SerializationFeature.WRITE_DATE_KEYS_AS_TIMESTAMPS, false);
//使用JSR310提供的序列化类,里面包含了大量的JDK8时间序列化类
JavaTimeModule javaTimeModule = new JavaTimeModule();
javaTimeModule.addSerializer(LocalDateTime.class,new LocalDateTimeSerializer(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSS")));
javaTimeModule.addDeserializer(LocalDateTime.class,new LocalDateTimeDeserializer(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSS")));
objectMapper.registerModule(javaTimeModule);
//指定序列化输入的类型@class JsonTypeInfo.As.PROPERTY-表示以对象属性的形式 WRAPPER_ARRAY-表示以数组的形式
objectMapper.activateDefaultTyping(LaissezFaireSubTypeValidator.instance, ObjectMapper.DefaultTyping.NON_FINAL, JsonTypeInfo.As.PROPERTY);
//配置null值的序列化器
GenericJackson2JsonRedisSerializer.registerNullValueSerializer(objectMapper, null);
return new GenericJackson2JsonRedisSerializer(objectMapper);
}
}
4. 使用RedisTemplate
import com.kevin.core.result.ApiResult;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.Map;
/**
* @author kevin
* @create 2020/8/7 14:42
*/
@ApiResult
@RestController
public class TestController {
@Autowired
private RedisTemplate redisTemplate;
@GetMapping(value="/test",produces= MediaType.APPLICATION_JSON_VALUE)
public Object test(){
Map<String, Object> user=new HashMap<>();
user.put("id", 1);
user.put("name","kevin");
user.put("createTime", LocalDateTime.now());
redisTemplate.opsForValue().set("user:"+user.get("id"), user);
return redisTemplate.opsForValue().get("user:"+user.get("id"));
}
}
5. 测试
二、继续使用jedis
因为一些历史遗留问题,比如老代码中使用了jedis不想调整,想继续使用jedis,只需调整一下配置即可。
1. pom.xml引入jar包(排除lettuce,引入jedis)
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
<exclusions>
<exclusion>
<groupId>io.lettuce</groupId>
<artifactId>lettuce-core</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
</dependency>
2. application.properties配置jedis
spring.redis.host=127.0.0.1
spring.redis.port=6379
spring.redis.password=123
spring.redis.jedis.pool.max-active=500
spring.redis.jedis.pool.max-idle=300
spring.redis.jedis.pool.max-wait=1000
spring.redis.jedis.pool.min-idle=0
spring.redis.database=8