文章目录
前言
首先确保在服务器或虚拟机中安装配置好了redis,确保服务器或虚拟机上的redis能够被远程调用。
如果没有,见:https://blog.csdn.net/weixin_45773632/article/details/123656061
SpringBoot整合redis
说明
在
springBoot 2.x
之后,原来使用的Jedis
被替换为了lettuce
-
jedis: 采用的是直连,多个线程操作的话,是不安全的,如果向要避免不安全的情况出现,使用jedis pool连接池!更像 BIO 模式
-
lettuce: 采用netty,实例可以在多个线程中进行共享,不存在线程不安全的情况!可以减少线程开销,更像NIO模式
依赖导入
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
查看配置文件
找到redis相关的自动配置类:
跳转到RedisAutoConfiguration:
跳转到RedisProperties:
RedisAutoConfiguration 源码分析
@Configuration(proxyBeanMethods = false)
@ConditionalOnClass(RedisOperations.class)
@EnableConfigurationProperties(RedisProperties.class)
@Import({ LettuceConnectionConfiguration.class, JedisConnectionConfiguration.class })
public class RedisAutoConfiguration {
@Bean
@ConditionalOnMissingBean(name = "redisTemplate")
@ConditionalOnSingleCandidate(RedisConnectionFactory.class)
public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
RedisTemplate<Object, Object> template = new RedisTemplate<>();
template.setConnectionFactory(redisConnectionFactory);
return template;
}
@Bean
@ConditionalOnMissingBean
@ConditionalOnSingleCandidate(RedisConnectionFactory.class)
public StringRedisTemplate stringRedisTemplate(RedisConnectionFactory redisConnectionFactory) {
StringRedisTemplate template = new StringRedisTemplate();
template.setConnectionFactory(redisConnectionFactory);
return template;
}
}
整合测试
-
启动一个单机的redis
注意:如果redis是安装在服务器上,需要将·bind 127.0.0.1
注释,并且将protected mode
设置为no。参考:https://blog.csdn.net/bababuzaijia/article/details/88872754 -
编写配置文件
spring:
#redis基础配置
redis:
#redis的地址
host: 127.0.0.1
port: 6379
- 测试类
@RunWith(SpringRunner.class)
@SpringBootTest
public class RedisTemplateTest {
@Resource
private RedisTemplate redisTemplate;
@Test
public void contextLoads() {
redisTemplate.opsForValue().set("testKey","xxxxxx");
System.out.println(redisTemplate.opsForValue().get("testKey"));
}
}
注意:@RunWith(SpringRunner.class)
必加,否则报空指针,原文见https://blog.csdn.net/weixin_42236404/article/details/88969718
注意:这里mykey对应的值是英文,如果是中文的话会出现问题。需要自定义Redistemplate
注意:如果set的值是一个对象的话,则这个对象的类必须被序列化,否则就会报错。
RedisTemplate 源码分析
/**
* Constructs a new <code>RedisTemplate</code> instance.
*/
public RedisTemplate() {}
/*
* (non-Javadoc)
* @see org.springframework.data.redis.core.RedisAccessor#afterPropertiesSet()
*/
@Override
public void afterPropertiesSet() {
super.afterPropertiesSet();
boolean defaultUsed = false;
if (defaultSerializer == null) {
defaultSerializer = new JdkSerializationRedisSerializer(
classLoader != null ? classLoader : this.getClass().getClassLoader());
}
if (enableDefaultSerializer) {
if (keySerializer == null) {
keySerializer = defaultSerializer;
defaultUsed = true;
}
if (valueSerializer == null) {
valueSerializer = defaultSerializer;
defaultUsed = true;
}
if (hashKeySerializer == null) {
hashKeySerializer = defaultSerializer;
defaultUsed = true;
}
if (hashValueSerializer == null) {
hashValueSerializer = defaultSerializer;
defaultUsed = true;
}
}
if (enableDefaultSerializer && defaultUsed) {
Assert.notNull(defaultSerializer, "default serializer null and not all serializers initialized");
}
if (scriptExecutor == null) {
this.scriptExecutor = new DefaultScriptExecutor<>(this);
}
initialized = true;
}
- RedisTemplate 中有四个值,代表不同键和值的序列化方式
@SuppressWarnings("rawtypes") private @Nullable RedisSerializer keySerializer = null;
@SuppressWarnings("rawtypes") private @Nullable RedisSerializer valueSerializer = null;
@SuppressWarnings("rawtypes") private @Nullable RedisSerializer hashKeySerializer = null;
@SuppressWarnings("rawtypes") private @Nullable RedisSerializer hashValueSerializer = null;
- RedisTemplate中只有一个无参构造函数,导入依赖后,默认会向容器中注入一个RedisTemplate
- RedisTemplate默认使用 JdkSerializationRedisSerializer 来序列化
if (defaultSerializer == null) {
defaultSerializer = new JdkSerializationRedisSerializer(
classLoader != null ? classLoader : this.getClass().getClassLoader());
}
自定义RedisTemplate
RedisConfig
@Configuration
public class RedisConfig {
@Bean
public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {
RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
redisTemplate.setConnectionFactory(factory);
//使用Jackson 提供的json序列化器
Jackson2JsonRedisSerializer<Object> jsonRedisSerializer = new Jackson2JsonRedisSerializer<>(Object.class);
ObjectMapper om = new ObjectMapper();
om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
jsonRedisSerializer.setObjectMapper(om);
//String 的序列化
StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
//key采用字符串序列化
redisTemplate.setKeySerializer(stringRedisSerializer);
redisTemplate.setHashKeySerializer(stringRedisSerializer);
//value的序列化方式采用jackson
redisTemplate.setValueSerializer(jsonRedisSerializer);
redisTemplate.setHashValueSerializer(jsonRedisSerializer);
//该方法尽量还是调用一下
redisTemplate.afterPropertiesSet();
return redisTemplate;
}
}
测试
@RunWith(SpringRunner.class)
@SpringBootTest
public class RedisTemplateTest {
@Resource
private RedisTemplate redisTemplate;
@Test
public void contextLoads1() {
User user = new User();
redisTemplate.opsForValue().set("mykey1",user);
System.out.println(redisTemplate.opsForValue().get("mykey1"));
}
}
拓展 (通过Jedis操作redis)
(1) 导入依赖
<!-- https://mvnrepository.com/artifact/redis.clients/jedis -->
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>3.8.0</version>
</dependency>
(2) 测试连接
public class TestPing {
public static void main(String[] args) {
Jedis jedis = new Jedis("121.4.91.181", 6379);
jedis.auth("afajy487nf34fa.sdfa");
System.out.println(jedis.ping());
}
}