目录
🎈构建Spring项目
🎈SpringBoot 整合Redis
☑️ 添加依赖(pom.xml)
🎈Spring配置文件(application.properties)
🎈Jedis的测试及使用
🎈SpringBoot中使用RedisTemplate
☑️ 添加依赖(pom.xml)
🎈序列化操作
🎈构建Spring项目
文件--->新建--->项目---->Spring Initializr
💭创建时勾选NoSQL中的spring集成redis :Spring-data-redis 💭
❗❓Spring-data-redis是啥❗❓
Spring-data-redis是Spring大家族的一部分,提供了在srping应用中通过简单的连接池配置访问redis服务,对Reids底层开发包(Jedis, JRedis, and RJC)进行了高度封装。其中的RedisTemplate提供了redis各种操作、异常处理及序列化,支持发布订阅,并对spring 3.1 cache进行了实现。而且RedisTemplate还支持对象缓存操作。
🎈SpringBoot 整合Redis
☑️ 添加依赖(pom.xml)
Maven Repository: Search/Browse/Explore (mvnrepository.com)
☝️ ☝️ ☝️
⏩ 到网站寻找依赖
➡️ jedis ➡️ fastjson ➡️junit
⏩ 也可以直接复制我的代码哦 ~
⬇️⬇️⬇️
<!-- https://mvnrepository.com/artifact/redis.clients/jedis -->
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>3.8.0</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.alibaba/fastjson -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.76</version>
</dependency>
<!-- https://mvnrepository.com/artifact/junit/junit -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
🎈Spring配置文件(application.properties)
# 应用名称
spring.application.name=RedisTemplateTest
#Redis服务器IP地址
spring.redis.host=127.0.0.1
#Redis服务器端口号
spring.redis.port=6379
🎈Jedis的测试及使用
package com.ccit.redis;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Value;
import redis.clients.jedis.Jedis;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import java.util.Iterator;
import java.util.List;
@RunWith(SpringRunner.class)
@SpringBootTest
public class JedisTest {
@Value("${spring.redis.host}")
private String redis_host;
@Value("${spring.redis.port}")
private int redis_port;
private Jedis jedis = null;
@Before
public void testRun() {
try {
jedis = new Jedis(redis_host, redis_port);
System.out.println("连接成功");
System.out.println("服务器正在运行" + jedis.ping());
} catch (Exception e) {
e.printStackTrace();
System.out.println(e.getClass() + ":" + e.getMessage());
}
}
@Test
public void testString() {
try {
jedis.set("s1", "hello world");
System.out.println("s1:" + jedis.get("s1"));
} catch (Exception e) {
e.printStackTrace();
System.out.println(e.getClass() + ":" + e.getMessage());
}
}
@Test
public void testList() {
try {
jedis.lpush("books", "Java");
jedis.lpush("books", "Web");
jedis.rpush("books", "NoSQL");
System.out.println(jedis.lrange("books", 0, -1));
List<String> list = jedis.lrange("books", 0, -1);
Iterator<String> itList = list.iterator();
while (itList.hasNext()) {
System.out.println(itList.next());
}
} catch (Exception e) {
e.printStackTrace();
System.out.println(e.getClass() + ":" + e.getMessage());
}
}
@Test
public void testHash() {
}
@Test
public void testSet() {
}
@Test
public void testZset() {
}
}
🎈SpringBoot中使用RedisTemplate
⭐ 第一部分我们对Jedis的使用进行了介绍,而且封装了一个JedisPoolUtil工具类。可是这样还是很麻烦,难道每次我们使用的时候都得复制这个JedisUtill 连接池配置工具类到新项目中?而且Jedis还不支持缓存对象的操作。程序员从来不需要重复遭轮子,Spring框架已经帮我们封装好了这一切!
☑️ 添加依赖(pom.xml)
Maven Repository: Search/Browse/Explore (mvnrepository.com)
☝️ ☝️ ☝️
⏩ 到网站寻找依赖
➡️ jackson-databind
⏩ 也可以直接复制我的代码哦 ~
⬇️⬇️⬇️
<!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-databind -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.13.0</version>
</dependency>
⭐ Spring框架中的spring-data-redis模块对Jedis API的进行了高度封装,提供了在Spring应用中通过简单的连接池信息配置就可以访问Redis服务并进行相关缓存操作。SpringDataRedis相对于Jedis来说可以方便地更换Redis的Java客户端如多线程安全的Lettuce,比Jedis多了自动管理连接池的特性,不需要我们自己的JediPoolUtil封装工具类。
⭐它还默认提供了两个使用Redis的类StringRedisTemplate和RedisTemplate,其中RedisTemplate可以支持Redis没有的缓存对象的操作,而StringRedisTemplate用来存储字符串。(其实它们都是RedisTemplate<K, V>泛型接口的实现类,我们可以自定义模板然后@AutoWired注入IOC容器中使用)
package com.ccit.redis;
import com.alibaba.fastjson.JSON;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.redis.core.*;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.util.Assert;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;
@RunWith(SpringRunner.class)
@SpringBootTest
public class RedisTemplateTest {
@Autowired
private RedisTemplate<String, String> redisTemplate;
@Before
public void init() {
try {
System.out.println("初始化" + redisTemplate);
} catch (Exception e) {
e.printStackTrace();
}
}
@Test
public void testString() {
try {
//设置值
redisTemplate.opsForValue().set("s1", "hello world");
//获取值
System.out.println("s1:" + redisTemplate.opsForValue());
//设置值的同时设置超时时间
redisTemplate.opsForValue().set("s2", "ccit", 10, TimeUnit.SECONDS);
System.out.println("s2:" + redisTemplate.opsForValue().get("s2"));
//设置长度
int size = redisTemplate.opsForValue().size("s1").intValue();
System.out.println("s1 size:" + size);
//求子字符串
String subString = redisTemplate.opsForValue().get("s1", 0, 5);
System.out.println("s1 subString:" + subString);
//删除
boolean isDelete = redisTemplate.delete("s1");
System.out.println("isDelete:" + ((isDelete) ? "yes" : "no"));
} catch (Exception e) {
e.printStackTrace();
System.out.println(e.getClass() + ":" + e.getMessage());
}
}
@Test
public void testList() {
ListOperations<String, String> listOp = redisTemplate.opsForList();
listOp.leftPush("namelist", "mike"); // List 列表左侧插入一个元素
listOp.leftPush("namelist", "kim");
listOp.rightPush("namelist", "jimmy"); //往 List 列表右侧插入一个元素
listOp.rightPush("namelist", "chuck");
Long size = listOp.size("namelist"); //计算List列表大小
List namelist1 = listOp.range("namelist", 0, size); //遍历整个List列表
System.out.println("namelist1:" + JSON.toJSONString(namelist1));
List namelist = listOp.range("namelist", 0, -1); //遍历整个List列表,-1表示倒数第一个即最后一个
System.out.println("namelist:" + JSON.toJSONString(namelist));
Object name1 = listOp.leftPop("namelist", 200, TimeUnit.MILLISECONDS); //从 List 列表左侧取出第一个元素,并移除
System.out.println("is kim:" + name1.equals("kim"));
Object name2 = listOp.rightPop("namelist"); //从 List 右侧列表取出第一个元素,并移除
System.out.println("is chuck:" + name2.equals("chuck"));
}
@Test
public void testHash() {
try {
HashOperations<String,String,String> hashOp = redisTemplate.opsForHash();
hashOp.put("score", "Mike", "10"); //Hash 中新增元素。
hashOp.put("score", "Jimmy", "9");
hashOp.put("score", "Kim", "8");
Assert.isTrue(hashOp.hasKey("score", "Kim")); //判断指定 key 对应的 Hash 中是否存在指定的 map 键
String kim = hashOp.get("score", "Kim"); //获取指定 key 对应的 Hash 中指定键的值
Set<String> name = hashOp.keys("score"); //获取hash表所有的key集合
System.out.println(JSON.toJSONString(name));
List<String> score = hashOp.values("score"); //获取hash表所有的values集合
System.out.println(JSON.toJSONString(score));
Map<String, String> map = hashOp.entries("score"); //获取"score"对应的hash表Map
System.out.println(JSON.toJSONString(map));
hashOp.delete("score", "Mike"); //删除指定 key 对应 Hash 中指定键的键值对
//如果要删除整个hash表,要用redisTemplate.delete("score")方法,否则报错:Fields must not be empty
//hashOp.delete("score");
redisTemplate.delete("score"); //删除整个hash表
Map<String, String> map1 = hashOp.entries("score");
} catch (Exception e) {
e.printStackTrace();
}
}
@Test
public void testSet(){
try {
SetOperations<String,String>setOp=redisTemplate.opsForSet();
//向集合中添加元素,set元素具有唯一性
setOp.add("city", "changzhou", "beijing", "shanghai", "hongkong", "hongkong");
Long size = setOp.size("city");
System.out.println("city size:" + size);
//获取集合中的元素
Set city = setOp.members("city");
System.out.println(JSON.toJSONString(city));
//移除集合中的元素,可以一个或多个
setOp.remove("city", "paris");
//判断是否是集合中的元素
Boolean isMember = setOp.isMember("city", "hongkong");
System.out.println("hongkong is in city:" + isMember);
//移除并返回集合中的一个随机元素
String city1 = setOp.pop("city");
System.out.println(city1);
}catch (Exception e){
e.printStackTrace();
}
}
@Test
public void testZset(){
try {
ZSetOperations zSetOp=redisTemplate.opsForZSet();
//添加元素
zSetOp.add("zcity", "beijing", 100);
zSetOp.add("zcity", "shanghai", 95);
zSetOp.add("zcity", "guangzhou", 75);
zSetOp.add("zcity", "shenzhen", 85);
//获取变量指定区间的元素。0, -1表示全部
Set<String> zcity = zSetOp.range("zcity", 0, -1);
System.out.println(JSON.toJSONString(zcity));
//通过分数返回有序集合指定区间内的成员,其中有序集成员按分数值递增(从小到大)顺序排列
Set<String> byScore = zSetOp.rangeByScore("zcity", 85, 100);
System.out.println(JSON.toJSONString(byScore));
//获取有序集合的成员数
Long aLong = zSetOp.zCard("zcity");
System.out.println("zcity size: " + aLong);
}catch (Exception e){
e.printStackTrace();
}
}
}
⭐ SpringBoot 2.0已经使用Lettuce代替Jedis ⭐
🔮 其实,随着Spring Boot2.x的到来,支持的组件越来越丰富,也越来越成熟,其中对Redis的支持不仅仅是丰富了它的API,更是替换掉底层Jedis的依赖,取而代之换成了Lettuce高级Redis客户端,用于多线程安全同步,异步和响应使用。
🔮 Lettuce和Jedis的都是连接Redis Server的客户端程序。Jedis在实现上是直连redis server,多线程环境下非线程安全,除非使用连接池JedisPool,为每个Jedis实例增加物理连接。Lettuce基于Netty的连接实例(StatefulRedisConnection),可以在多个线程间并发访问,且线程安全,满足多线程环境下的并发访问,同时它是可伸缩的设计,一个连接实例不够的情况也可以按需增加连接实例。
🔮 为了多线程安全,以前是Jedis+JedisPool组合 ,现在在SpringBoot 2.0应用中直接使用Lettuce客户端的API封装RedisTemplate即可,只要配置好连接池属性,那么SpringBoot就能自动管理连接池。
🎈序列化操作
❗❓序列化是啥❗❓
Java序列化就是指把Java对象转换为字节序列的过程
Java反序列化就是指把字节序列恢复为Java对象的过程。
⬇️⬇️⬇️ 序列化和反序列化详解看下方链接
序列化和反序列化的详解_tree_ifconfig的博客_序列化和反序列化
⭐当我们的数据存储到 Redis 的时候,我们的键(key)和值(value)都是通过 Spring 提供的 Serializer 序列化到数据库的。
RedisTemplate 默认使用的是 JdkSerializationRedisSerializer,StringRedisTemplate 默认使用的是 StringRedisSerializer。
✅ 创建Java对象~
package com.ccit.redis.module;
public class Student {
private int id;
private String no;
private String name;
public Student() {
}
public Student(int id, String no, String name) {
this.id = id;
this.no = no;
this.name = name;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getNo() {
return no;
}
public void setNo(String no) {
this.no = no;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "Student{" +
"id=" + id +
", no='" + no + '\'' +
", name='" + name + '\'' +
'}';
}
}
✅序列化操作~
package com.ccit.redis;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.junit.Before;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.test.context.junit4.SpringRunner;
@RunWith(SpringRunner.class)
@SpringBootTest
public class RedisTemplateSerialize {
@Autowired
private RedisTemplate redisTemplate;
@Autowired(required = false)
private ObjectMapper objectMapper;
//定义日志
private Logger log = LoggerFactory.getLogger(RedisTemplateSerialize.class);
@Before
public void init() {
try {
System.out.println("初始化:" + redisTemplate);
} catch (Exception e) {
e.printStackTrace();
}
}
@Test
public void testString() {
String content="hello,world!";
String key="redis:template:string";
//Redis通用的操作组件
ValueOperations valueOperations=redisTemplate.opsForValue();
//将字符串信息写入缓存
log.info("写入缓存中的内容: {} ",content);
valueOperations.set(key,content);
//从缓存中读取内容
Object result=valueOperations.get(key);
log.info("读取出来的内容:{} ",result);
}
@Test
public void testList() {
}
}
✔️ 项目具体的结构看下方图片~
🎉写在最后
人之所以能,是相信能。