在Redis官网中提供了各种语言的客户端,地址:https://redis.io/resources/clients/
redis的java客户端 https://redis.io/resources/clients/#java
<dependency>
<groupId>redis.clientsgroupId>
<artifactId>jedisartifactId>
<version>5.0.0version>
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连接池代替Jedis的直连方式
public class JedisConnectionFactory {
private static final JedisPool jedisPool;
static {
JedisPoolConfig jedisPoolConfig = new JedisPoolConfig();
// 最大连接
jedisPoolConfig.setMaxTotal(8);
// 最大空闲连接
jedisPoolConfig.setMaxIdle(8);
// 最小空闲连接
jedisPoolConfig.setMinIdle(0);
// 设置最长等待时间, ms
jedisPoolConfig.setMaxWaitMillis(200);
jedisPool = new JedisPool(jedisPoolConfig, "192.168.150.101", 6379, 1000, "123321");
}
// 获取Jedis对象
public static Jedis getJedis(){ return jedisPool.getResource(); }
}
}
<dependency>
<groupId>io.lettucegroupId>
<artifactId>lettuce-coreartifactId>
<version>6.2.1.RELEASEversion>
dependency>
public class LettuceDemo
{
public static void main(String[] args)
{
//使用构建器 RedisURI.builder
RedisURI uri = RedisURI.builder()
.redis("192.168.111.181")
.withPort(6379)
.withAuthentication("default","111111")
.build();
//创建连接客户端
RedisClient client = RedisClient.create(uri);
StatefulRedisConnection conn = client.connect();
//操作命令api
RedisCommands<String,String> commands = conn.sync();
//keys
List<String> list = commands.keys("*");
for(String s : list) {
log.info("key:{}",s);
}
//String
commands.set("k1","1111");
String s1 = commands.get("k1");
System.out.println("String s ==="+s1);
//list
commands.lpush("myList2", "v1","v2","v3");
List<String> list2 = commands.lrange("myList2", 0, -1);
for(String s : list2) {
System.out.println("list ssss==="+s);
}
//set
commands.sadd("mySet2", "v1","v2","v3");
Set<String> set = commands.smembers("mySet2");
for(String s : set) {
System.out.println("set ssss==="+s);
}
//hash
Map<String,String> map = new HashMap<>();
map.put("k1","138xxxxxxxx");
map.put("k2","atguigu");
map.put("k3","zzyybs@126.com");//课后有问题请给我发邮件
commands.hmset("myHash2", map);
Map<String,String> retMap = commands.hgetall("myHash2");
for(String k : retMap.keySet()) {
System.out.println("hash k="+k+" , v=="+retMap.get(k));
}
//zset
commands.zadd("myZset2", 100.0,"s1",110.0,"s2",90.0,"s3");
List<String> list3 = commands.zrange("myZset2",0,10);
for(String s : list3) {
System.out.println("zset ssss==="+s);
}
//sort
SortArgs sortArgs = new SortArgs();
sortArgs.alpha();
sortArgs.desc();
List<String> list4 = commands.sort("myList2",sortArgs);
for(String s : list4) {
System.out.println("sort ssss==="+s);
}
//关闭
conn.close();
client.shutdown();
}
}
soringboot2.0之后默认使用的lettuce客户端连接redis服务器
SpringData是Spring中数据操作的模块,包含对各种数据库的集成,其中对Redis的集成模块就叫做SpringDataRedis,官网地址:https://spring.io/projects/spring-data-redis
提供了对不同Redis客户端的整合(Lettuce和Jedis)
SpringDataRedis中提供了RedisTemplate工具类,其中封装了各种对Redis的操作。并且将不同数据类型的操作API封装到了不同的类型中:
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-data-redisartifactId>
dependency>
<dependency>
<groupId>org.apache.commonsgroupId>
<artifactId>commons-pool2artifactId>
dependency>
# ========================redis单机=====================
spring.redis.database=0
# 修改为自己真实IP
spring.redis.host=192.168.111.185
spring.redis.port=6379
spring.redis.password=111111
spring.redis.lettuce.pool.max-active=8 #最大连接数
spring.redis.lettuce.pool.max-wait=100 #连接等待时间
spring.redis.lettuce.pool.max-idle=8#最大空闲连接
spring.redis.lettuce.pool.min-idle=0#最小空闲连接
@SpringBootTest
public class RedisTest {
@Autowired
private RedisTemplate redisTemplate;
@Test
void testString() {
// 插入一条string类型数据
redisTemplate.opsForValue().set("name", "李四");
// 读取一条string类型数据
Object name = redisTemplate.opsForValue().get("name");
System.out.println("name = " + name);
}
}
redisTemplate默认使用jdk序列化得到如下
缺点:占内存 不宜查看
我们可以自定义RedisTemplate的序列化方式,代码如下:
可以新建redisconfig配置类
@Bean
public RedisTemplate<String, Object> redisTemplate(LettuceConnectionFactory lettuceConnectionFactory)
{
RedisTemplate<String,Object> redisTemplate = new RedisTemplate<>();
redisTemplate.setConnectionFactory(lettuceConnectionFactory);
//设置key和hashkey序列化方式string
redisTemplate.setKeySerializer(new StringRedisSerializer());
redisTemplate.setHashKeySerializer(new StringRedisSerializer());
//设置value和hashvalue的序列化方式json,使用GenericJackson2JsonRedisSerializer替换默认序列化
redisTemplate.setValueSerializer(new GenericJackson2JsonRedisSerializer());
redisTemplate.setHashValueSerializer(new GenericJackson2JsonRedisSerializer());
redisTemplate.afterPropertiesSet();
return redisTemplate;
}
自定义redisTemplate可能带来的问题
将对象序列化存入redis中时
尽管JSON的序列化方式可以满足我们的需求,但依然存在一些问题,如图:
为了在反序列化时知道对象的类型,JSON序列化器会将类的class类型写入json结果中,存入Redis,会带来额外的内存开销。
Spring默认提供了一个StringRedisTemplate类,它的key和value的序列化方式默认就是String方式。省去了我们自定义RedisTemplate的过程:
@Autowired
private StringRedisTemplate stringRedisTemplate;
// JSON工具
private static final ObjectMapper mapper = new ObjectMapper();
@Test
void testStringTemplate() throws JsonProcessingException {
// 准备对象
User user = new User("虎哥", 18);
// 手动序列化
String json = mapper.writeValueAsString(user);
// 写入一条数据到redis
stringRedisTemplate.opsForValue().set("user:200", json);
// 读取数据
String val = stringRedisTemplate.opsForValue().get("user:200");
// 反序列化
User user1 = mapper.readValue(val, User.class);
}