点评项目(Redis中间件)第二部分Redis基础
Redis的java客户端
spring整合了前三种我们只需要学习spring整合的就行了。不过还是有企业使用老一套的原生的jedis。
jedis
操作
引入依赖
<dependency><groupId>redis.clients</groupId><artifactId>jedis</artifactId><version>3.7.0</version>
</dependency>
建立连接
private Jedis jedis;@BeforeEach
void setUp() {// 建立连接jedis = new Jedis("192.168.150.101", 6379);// 设置密码jedis.auth("123321");// 选择库jedis.select(0);
}
测试
@Test
void testString() {// 插入数据,方法名称就是 redis 命令名称,非常简单String result = jedis.set("name", "张三");System.out.println("result = " + result);// 获取数据String name = jedis.get("name");System.out.println("name = " + name);
}
释放
@AfterEach
void tearDown() {// 释放资源if (jedis != null) {jedis.close();}
}
jedis连接池
因为是jedis是单线程,所以一但出现多线程调用一个实例就会出现线程安全问题,而且频繁的创建和销毁对象实例是有很大的性能损耗,所以我们需要设置多个实例交给连接池来管理。
public class JedisConnectionFactory {private static final JedisPool jedisPool;static {JedisPoolConfig jedisPoolConfig = new JedisPoolConfig();// 最大连接jedisPoolConfig.setMaxTotal(8);// 最大空闲连接jedisPoolConfig.setMaxIdle(8);// 最小空闲连接jedisPoolConfig.setMinIdle(0);// 设置最长等待时间,msjedisPoolConfig.setMaxWaitMillis(200);jedisPool = new JedisPool(jedisPoolConfig, "192.168.150.101", 6379, 1000, "123321");}// 获取Jedis对象public static Jedis getJedis() {return jedisPool.getResource();}
}
这个代码里面有static代码块,这是一个静态代码块。它里面的代码会在类被加载到 JVM 时执行一次,并且只执行一次。它在任何对象创建之前,甚至在 main
方法执行之前就可能被执行。用来初始化 static
的 jedisPool
。当 JedisConnectionFactory
类第一次被使用(比如调用 getJedis()
方法)时,JVM 会加载这个类,并自动执行这个静态代码块,完成连接池的配置和创建。之后,这个创建好的 jedisPool
就可以被所有地方共享使用了。
这里提供一个简单、全局的入口点来获取 Jedis 连接。使用者不需要关心 JedisConnectionFactory
的内部细节,也不需要自己去创建这个工厂类的对象,直接调用 JedisConnectionFactory.getJedis()
就能得到一个连接。这是一种常见的“工厂模式”或“工具类”设计。
SpringDataRedis
操作
引入依赖
springboot里面引入了SpringDataRedis这个依赖不用手动导包。
连接池需要自己导入。
<!-- Redis依赖 -->
<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>
配置文件
spring:redis:host: 192.168.150.101port: 6379password: 123321lettuce:pool:max-active: 8 # 最大连接max-idle: 8 # 最大空闲连接min-idle: 0 # 最小空闲连接max-wait: 100 # 连接等待时间
spring默认连接池实现的是lettuce,如果要用jedis还需要自己手动导入依赖。
注入
@Autowired
private RedisTemplate<String, Object> redisTemplate;
测试
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;@SpringBootTest
public class RedisTest {@Autowiredprivate RedisTemplate<String, Object> redisTemplate;@Testvoid testString() {// 插入一条string类型数据redisTemplate.opsForValue().set("name", "李四");// 读取一条string类型数据Object name = redisTemplate.opsForValue().get("name");System.out.println("name = " + name);}
}
序列化
spring里面接受的是object对象,接受之后会用序列化器把对象序列化字节形式传递给底层的jedis。
改变序列化方式
序列化器的实现类有多个,我们选择专门处理字符串的就行。
一般,如果key是字符串,我们就是用字符串序列化,值如果是对象我们就使用json序列化。
操作
@Bean
public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory)throws UnknownHostException {// 创建 TemplateRedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();// 设置连接工厂redisTemplate.setConnectionFactory(redisConnectionFactory);// 设置序列化工具GenericJackson2JsonRedisSerializer jsonRedisSerializer = new GenericJackson2JsonRedisSerializer();// key 和 hashKey 采用 string 序列化redisTemplate.setKeySerializer(RedisSerializer.string());redisTemplate.setHashKeySerializer(RedisSerializer.string());// value 和 hashValue 采用 JSON 序列化redisTemplate.setValueSerializer(jsonRedisSerializer);redisTemplate.setHashValueSerializer(jsonRedisSerializer);return redisTemplate;
}
这个bean需要写在一个新的spring配置文件里面。
还需要额外引入jackson依赖,平常开发的话springmvc里面自带了。
类地址的自动填入问题
解决办法
@Autowired
private StringRedisTemplate stringRedisTemplate;
// JSON工具
private static final ObjectMapper mapper = new ObjectMapper();@Test
void testStringRedisTemplate() throws JsonProcessingException {// 准备对象User user = new User("虎哥", 18);// 手动序列化String json = mapper.writeValueAsString(user);// 写入一条数据到redisstringRedisTemplate.opsForValue().set("user:200", json);// 读取数据String val = stringRedisTemplate.opsForValue().get("user:200");// 反序列化User user1 = mapper.readValue(val, User.class);System.out.println("user1 = " + user1);
}