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);
}