前面我们就搭建测试好了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);
	}
}