前面我们就搭建测试好了redis环境,接下来我们就来整合redis来做缓存,我们需要引入redis的starter,
这个starter我们直接去官方文档去搜索就行了,我们来找到所有的starter跟redis有关的,这一块有一个starters,
https://docs.spring.io/spring-boot/docs/1.5.22.RELEASE/reference/html/using-boot-build-systems.html
#using-boot-starter
在这里看redis,redis就是跟数据访问的,数据访问这里有非常多的starter,这里有一个
spring-boot-starter-data-redis
Starter for using Redis key-value data store with Spring Data Redis and the Jedis client
我们就用它,我们先引入这个场景启动器,我们在这引入
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
把它引入进来以后呢,我们redis相应的场景就引入进来了,他引入了哪些呢,点击来,我们可以来看一下,
这里主要引入了jedis客户端
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
</dependency>
接下来我们就来配置好redis,先用springboot测试,第三步配置redis,配置redis非常的简单,我们只要指定spring.redis.host,
指定一下redis的主机地址
spring.redis.host=10.40.8.152
就是这个地址,我们就来到这个测试类里面
spring.redis.host=localhost # Redis server host.
spring.redis.password= # Login password of the redis server.
spring.redis.port=6379 # Redis server port.
当我们引入了redis场景以后,我们RedisAutoConfiguration,就不起作用了,由于我们引入了redis,
@Configuration
@ConditionalOnClass({ JedisConnection.class, RedisOperations.class, Jedis.class })
@EnableConfigurationProperties(RedisProperties.class)
public class RedisAutoConfiguration {
包括有了Jedis,我们redis的自动配置就起效了,这个自动配置做了什么,我们来往下看,他给我们配了有两个东西,
@Bean给容器中加组件,
* Standard Redis configuration.
*/
@Configuration
protected static class RedisConfiguration {
@Bean
@ConditionalOnMissingBean(name = "redisTemplate")
public RedisTemplate<Object, Object> redisTemplate(
RedisConnectionFactory redisConnectionFactory)
throws UnknownHostException {
RedisTemplate<Object, Object> template = new RedisTemplate<Object, Object>();
template.setConnectionFactory(redisConnectionFactory);
return template;
}
@Bean
@ConditionalOnMissingBean(StringRedisTemplate.class)
public StringRedisTemplate stringRedisTemplate(
RedisConnectionFactory redisConnectionFactory)
throws UnknownHostException {
StringRedisTemplate template = new StringRedisTemplate();
template.setConnectionFactory(redisConnectionFactory);
return template;
}
}
加了一个RedisTemplate<Object, Object>,还有一个是StringRedisTemplate,相当于两个RedisTemplate的东西,
他就是用来操作redis的,就跟大家学的JdbcTemplate一样,来操作数据库的,这就是用来简化操作redis的两个
template,我们把这两个复制过来,如果要用,我们只需要自动注入就行了,还有一个就直接叫RedisTemplate,
为什么会有两个呢,RedisTemplate<Object, Object>两个Object代表键值,键值都是对象的,由于我们经常跟连接
字符串操作比较多,来专门操作字符串的,StringRedisTemplate,这个就是操作字符串的,redis操作的基本几种类型,
String(字符串),就和我们刚才在命令行操作的一样,还有操作list,这个就是我们的列表,包括我们还操作过一个叫set,
集合,包括里面还有一个常见的数据类型,hash,这是一个散列,包括还有一个叫Zset,这是一个有序集合,这是Redis常见的
5大数据类型,这些template都能操作,我们先用StringRedisTemplate来演示,这里有一个方法,opsForValue,这个就是用来操作
字符串的,。来简化操作字符串的,stringRedisTemplate.opsForHash()操作我们Hash的,还有一个
stringRedisTemplate.opsForList(),这是来操作列表的,这是来操作列表类型数据的,stringRedisTemplate.opsForSet()
这个是来操作集合的,其他的不用讲了,其实都是一样,所以太会有对应的这几个,我就把这些都复制过来了,这个template其实
跟stringRedisTemplate一模一样,他们都有这些操作,操作一些常用的数据,他跟他的不同我们以前说过,这些k-v都是对象的,
我们用stringRedisTemplate来做一个例子,来操作字符串,操作字符串我们怎么操作,这里有append,相当于redis命令里边,
只要有这些命令,你基本上都能够点出来,比如我们测试刚才的追加命令,比如我们的key就叫message,这个message的值就叫hello,
刚才我们把redis数据库给清空了,什么都没有,我们相当于给redis中保存了一个数据,我们发现redis里msg hello也已经有了,
我想把这个数据读出来,读我们就来写一个get,我们要按照这个key来读数据,append是追加字符串的,这里有一个set,给某一个key
设置某一个值,我们发现有报错,默认的序列化需要一个可序列化的类,但是我们Employee这个类是不可以序列化的,那我先把它
给序列化一下,然后我再来运行,我们发现这里有数据,
\xAC\xED\x00\x05t\x00\x06emp-01
emp-01前面一大堆是什么呢,其实这都是序列化的结果,默认如果保存对象,使用jdk序列化机制,序列化的数据保存在redis里,
我们还是习惯以json的方式保存,有两种办法,将数据以JSON的方式保存,我们自己 把数据转换来,自己讲对象转为JSON,
这种我们就不说了,大家都会转,用市面上的JSON转换工具,其实redisTemplate它有默认的序列化规则,RedisTemplate里边,
private RedisSerializer keySerializer = null;
private RedisSerializer valueSerializer = null;
private RedisSerializer hashKeySerializer = null;
private RedisSerializer hashValueSerializer = null;
private RedisSerializer<String> stringSerializer = new StringRedisSerializer();
有keySerializer的序列化器,这些值的序列化器,我们来变一下规则就行了,
@Bean
@ConditionalOnMissingBean(name = "redisTemplate")
public RedisTemplate<Object, Object> redisTemplate(
RedisConnectionFactory redisConnectionFactory)
throws UnknownHostException {
RedisTemplate<Object, Object> template = new RedisTemplate<Object, Object>();
template.setConnectionFactory(redisConnectionFactory);
return template;
}
他就直接new了一个RedisTemplate,把redis的连接工厂放过来,把这个template返回,默认情况下我们看他的序列号器用的
是什么,用的就是JdkSerializationRedisSerializer
if (defaultSerializer == null) {
defaultSerializer = new JdkSerializationRedisSerializer(
classLoader != null ? classLoader : this.getClass().getClassLoader());
}
我们来切换成JSON的序列号器引用
我来写一个MyRedisConfig,@Configuration,跟他的写法是一样的,我这里来放一个专门来序列化employee的,我们来
放一个序列号器,只要我们导了JACKSON,我们就会有Jackson2JsonRedisSerializer,我们把它给拿过来,只不过他new的
时候要传入一个泛型,我们就是来转换Employee的,这个是我们这个序列化器,让我们这个template来使用这个序列化器,
你都可以来写相应的RedisTemplate,我们在测试类的时候就自动注入这个
@Autowired
RedisTemplate<Object,Employee> empRedisTemplate;
package com.learn.entities;
import java.io.Serializable;
public class Employee implements Serializable {
private Integer id;
private String name;
private String gender;
private String title;
private String email;
private double salary;
private Integer deptId;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getGender() {
return gender;
}
public void setGender(String gender) {
this.gender = gender;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public double getSalary() {
return salary;
}
public void setSalary(double salary) {
this.salary = salary;
}
public Integer getDeptId() {
return deptId;
}
public void setDeptId(Integer deptId) {
this.deptId = deptId;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "Employee [id=" + id + ", name=" + name + ", gender=" + gender + ", title=" + title + ", email=" + email
+ ", salary=" + salary + ", deptId=" + deptId + "]";
}
}
package com.learn.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import com.learn.entities.Employee;
@Configuration
public class MyRedisConfig {
@Bean
public RedisTemplate<Object,Employee> empRedisTemplate(RedisConnectionFactory redisConnectionFactory){
RedisTemplate<Object,Employee> template = new RedisTemplate<Object,Employee>();
template.setConnectionFactory(redisConnectionFactory);
Jackson2JsonRedisSerializer<Employee> ser = new Jackson2JsonRedisSerializer<Employee>(Employee.class);
template.setDefaultSerializer(ser);
return template;
}
}
package com.learn.springboot;
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.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.test.context.junit4.SpringRunner;
import com.learn.entities.Employee;
import com.learn.mapper.EmployeeMapper;
/**
* SpringBoot单元测试
*
* 可以在测试期间很方便的类似编码一样进行自动注入等容器的功能
*/
@RunWith(SpringRunner.class)
@SpringBootTest
public class SpringBoot01CacheApplicationTests {
// 操作k-v都是对象的
@Autowired
StringRedisTemplate stringRedisTemplate;
// 操作字符串的 k-v都是字符串的
@Autowired
RedisTemplate<Object,Object> redisTemplate;
@Autowired
EmployeeMapper employeeMapper;
@Autowired
RedisTemplate<Object,Employee> empRedisTemplate;
/**
* Redis常见的五大数据类型
* String(字符串),List(列表),Set(集合),Hash(散列),ZSet(有序集合)
* stringRedisTemplate.opsForValue[String(字符串)]
* stringRedisTemplate.opsForHash()[Hash(散列)]
* stringRedisTemplate.opsForList()[List(列表)]
* stringRedisTemplate.opsForSet()[Set(集合)]
* stringRedisTemplate.opsForZSet()[ZSet(有序集合)]
*/
@Test
public void test01() {
// 给redis中保存一个数据
// stringRedisTemplate.opsForValue().append("msg", "hello");
// String msg = stringRedisTemplate.opsForValue().get("msg");
// System.out.println(msg);
// stringRedisTemplate.opsForList().leftPush("mylist", "1");
// stringRedisTemplate.opsForList().leftPush("mylist", "2");
}
// 测试保存对象
@Test
public void test02() {
Employee emp = employeeMapper.getEmpById(1);
// 默认如果保存对象,使用jdk序列号机制,序列化后的数据保存到redis中
// redisTemplate.opsForValue().set("emp-01", emp);
// 1.将数据以json的方式保存
// (1)自己将对象转为json
// (2)redisTemplate默认的序列号规则
empRedisTemplate.opsForValue().set("emp-01", emp);
}
}