Spring对Redis的支持是通过Spring Data Redis来实现的。Spring Data Redis提供了RedisTemplate和StringRedisTemplate两个模板来进行数据操作,其中StringRedisTemplate只针对键值都是字符串类型的数据进行操作。 RedisTemplate和StringRedisTemplate模板提供的主要数据访问方法如下表:
方法 | 说明 |
---|---|
posForValue() | 操作只有简单属性的数据 |
opsForList() | 操作含有List的数据 |
opsForSet() | 操作含有Set的数据 |
opsForZSet() | 操作含有Zset(有序的Set)的数据 |
opsForHash() | 操作含有Hash的数据 |
当数据存储到Redis时,键和值都是通过Spring提供的Serializer序列化到数据的。RedisTemplate默认使用JdkSerializationRedisSerializer序列化,StringRedisTemplate默认使用StringRedisSerializer序列化。
Spring Boot对Redis的支持位于org.springframework.boot.autoconfigure.data.redis包下。 在RedisAutoConfiguration配置类中,默认配置了RedisTemplate和StringRedisTemplate,可以直接使用Redis存储数据。 在RedisProperties类中,可以使用以Spring.redis为前缀的属性在application.properties中配置Redis,主要属性默认配置如下:
spring.redis.database=0 #数据库名db0
spring.redis.host=localhost #服务器地址
spring.redis.port=6379 #连接端口号
spring.redis.max-idle=8 #连接池的最大连接数
spring.redis.min-idle=0 #连接池的最小连接数
spring.redis.max-active=8 #在给定时间连接池可以分配的最大连接数
spring.redis.max-wait=-1 #当池被耗尽时,抛出异常之前连接分配应阻塞的最大时间量
#(以毫秒为单位)使用负值表示无限期地阻止
在该Spring Boot应用ch6_9中,使用Redis的默认数据库连接。所以,不需要在application.properties文件中配置数据库连接信息。
创建名为com.ch.ch6_9.entity的包,并在改包中创建名为Student的实体类。该类必须实现序列化接口,这是因为使用Jackson做序列化需要一个空构造。 Student的代码如下:
package com.ch.ch6_9.entity;
import java.io.Serializable;
public class Student implements Serializable{
private static final long serialVersionUID = 1L;
private String sno;
private String sname;
private Integer sage;
public Student() {
super();
}
public Student(String sno, String sname, Integer sage) {
super();
this.sno = sno;
this.sname = sname;
this.sage = sage;
}
public String getSno() {
return sno;
}
public void setSno(String sno) {
this.sno = sno;
}
public String getSname() {
return sname;
}
public void setSname(String sname) {
this.sname = sname;
}
public Integer getSage() {
return sage;
}
public void setSage(Integer sage) {
this.sage = sage;
}
}
创建名为com.ch.ch6_9.repository的包,并在该包中创建名为StudentRepository的类,该类使用@Repository注解标注为数据访问层 StudentRepository的代码如下:
package com.ch.ch6_9.repository;
import java.util.List;
import javax.annotation.Resource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.stereotype.Repository;
import com.ch.ch6_9.entity.Student;
@Repository
public class StudentRepository {
@SuppressWarnings("unused")
@Autowired
private StringRedisTemplate stringRedisTemplate;
@SuppressWarnings("unused")
@Autowired
private RedisTemplate<Object, Object> redisTemplate;
/**
* 使用@Resource注解指定stringRedisTemplate,可注入基于字符串的简单属性操作方法
* ValueOperations<String, String> valueOpsStr = stringRedisTemplate.opsForValue();
*/
@Resource(name="stringRedisTemplate")
ValueOperations<String, String> valueOpsStr;
/**
* 使用@Resource注解指定redisTemplate,可注入基于对象的简单属性操作方法
* ValueOperations<Object, Object> valueOpsObject = redisTemplate.opsForValue();
*/
@Resource(name="redisTemplate")
ValueOperations<Object, Object> valueOpsObject;
/**
* 保存字符串到redis
*/
public void saveString(String key, String value) {
valueOpsStr.set(key, value);
}
/**
* 保存对象到redis
*/
public void saveStudent(Student stu) {
valueOpsObject.set(stu.getSno(), stu);
}
/**
* 保存List数据到redis
*/
public void saveMultiStudents(Object key, List<Student> stus) {
valueOpsObject.set(key, stus);
}
/**
* 从redis中获得字符串数据
*/
public String getString(String key) {
return valueOpsStr.get(key);
}
/**
* 从redis中获得对象数据
*/
public Object getObject(Object key) {
return valueOpsObject.get(key);
}
}
由于实例比较简单,我们直接在控制器层调用数据访问层。创建名为com.ch.ch6_9.controller的包,并在改包中创建控制器类TestRedisController
package com.ch.ch6_9.controller;
import java.util.ArrayList;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.ch.ch6_9.entity.Student;
import com.ch.ch6_9.repository.StudentRepository;
@RestController
public class TestRedisController {
@Autowired
private StudentRepository studentRepository;
@RequestMapping("/save")
public void save() {
studentRepository.saveString("uname", "陈恒");
Student s1 = new Student("111","陈恒1",77);
studentRepository.saveStudent(s1);
Student s2 = new Student("222","陈恒2",88);
Student s3 = new Student("333","陈恒3",99);
List<Student> stus = new ArrayList<Student>();
stus.add(s2);
stus.add(s3);
studentRepository.saveMultiStudents("mutilStus",stus);
}
@RequestMapping("/getUname")
@Cacheable(value = "myuname")
public String getUname(String key) {
System.out.println("测试缓存");
return studentRepository.getString(key);
}
@RequestMapping("/getStudent")
public Student getStudent(String key) {
return (Student)studentRepository.getObject(key);
}
@SuppressWarnings("unchecked")
@RequestMapping("/getMultiStus")
public List<Student> getMultiStus(String key) {
return (List<Student>)studentRepository.getObject(key);
}
}
我们知道REdisTemplate默认使用JdkSerializationRedisSerializer序列化数据,这对使用Redis Client查看数据很不直观,因为JdkSerializationRedisSerializer使用二进制形式存储数据。所以,在此我们将自己配置RedisTemplate,并定义Serializer。 修改后的配置类Ch69Application的代码如下:
package com.ch.ch6_9;
import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
@SpringBootApplication
public class Ch69Application {
public static void main(String[] args) {
SpringApplication.run(Ch69Application.class, args);
}
@Bean
public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory){
RedisTemplate<Object, Object> rTemplate = new RedisTemplate<Object, Object>();
rTemplate.setConnectionFactory(redisConnectionFactory);
@SuppressWarnings({ "unchecked", "rawtypes" })
Jackson2JsonRedisSerializer<Object> jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
ObjectMapper om = new ObjectMapper();
om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
jackson2JsonRedisSerializer.setObjectMapper(om);
//设置值的序列化采用Jackson2JsonRedisSerializer
rTemplate.setValueSerializer(jackson2JsonRedisSerializer);
//设置键的序列化采用StringRedisSerializer
rTemplate.setKeySerializer(new StringRedisSerializer());
return rTemplate;
}
}
首先,运行CH69Application主类。然后通过http://localhost:8080/save
测试存储数据。成功运行后,通过Redis Client查看数据,如下图所示:
通过http://localhost:8080/getUname?key=uname
查询key为uname的字符串值,如图:
通过http://localhost:8080/getStudent?key=111
查询key为111的Student对象值,如图所示:
通过http://localhost:8080/getMultiStus?key=mutilStus
查询key为mutilStus的list集合,如图所示: