您的位置:首页 > 数据库 > Redis

SpringBoot整合Redis以及Redis的序列化

2020-03-10 00:06 639 查看

一、搭建基本环境

1、导入数据库文件 创建department和employee表

SET FOREIGN_KEY_CHECKS=0;
DROP TABLE IF EXISTS `department`;
CREATE TABLE `department` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`departmentName` varchar(255) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
DROP TABLE IF EXISTS `employee`;
CREATE TABLE `employee` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`lastName` varchar(255) DEFAULT NULL,
`email` varchar(255) DEFAULT NULL,
`gender` int(2) DEFAULT NULL,
`d_id` int(11) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;
INSERT INTO `employee` VALUES ('1', '李四', 'lisi@111.com', '1', '1');
INSERT INTO `employee` VALUES ('2', '张三', '123@123.com', '1', '1');

2、创建javabean封装数据

Department .java

package com.wzw.cache.bean;
public class Department {

private Integer id;
private String departmentName;

public Department() {
super();
// TODO Auto-generated constructor stub
}
public Department(Integer id, String departmentName) {
super();
this.id = id;
this.departmentName = departmentName;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getDepartmentName() {
return departmentName;
}
public void setDepartmentName(String departmentName) {
this.departmentName = departmentName;
}
@Override
public String toString() {
return "Department [id=" + id + ", departmentName=" + departmentName + "]";
}
}

Employee .java

package com.wzw.cache.bean;
import java.io.Serializable;
public class Employee implements Serializable {

private Integer id;
private String lastName;
private String email;
private Integer gender; //性别 1男  0女
private Integer dId;

public Employee() {
super();
}

public Employee(Integer id, String lastName, String email, Integer gender, Integer dId) {
super();
this.id = id;
this.lastName = lastName;
this.email = email;
this.gender = gender;
this.dId = dId;
}

public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public Integer getGender() {
return gender;
}
public void setGender(Integer gender) {
this.gender = gender;
}
public Integer getdId() {
return dId;
}
public void setdId(Integer dId) {
this.dId = dId;
}
@Override
public String toString() {
return "Employee [id=" + id + ", lastName=" + lastName + ", email=" + email + ", gender=" + gender + ", dId="
+ dId + "]";
}
}

3、整合Mybatis操作数据库

1)POM中导入需要的依赖,配置数据源信息

pom文件

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-cache</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.1.1</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
<groupId>com.microsoft.sqlserver</groupId>
<artifactId>mssql-jdbc</artifactId>
<scope>runtime</scope>
</dependency>

properties配置文件

spring.datasource.url=jdbc:mysql://localhost:3306/spring_cache?serverTimezone=UTC	//不加serverTimezone=UTC的话,运行时会时区报错
spring.datasource.username=root
spring.datasource.password=root

2)使用注解版的Mybatis

在SpringBoot启动类加上@MapperScan,指定需要扫描的mapper接口所在的包

二、给需要缓存的类加上注解

1、开启基于注解的缓存@EnableCaching

SpringBoot启动类加上开启注解@EnableCaching

2、标注缓存注解

@Cacheable

/**
* 将方法的运行结果进行缓存,以后再有相同的数据就直接从缓存中取,不再调用方法
*  CacheManager管理多个Cache组件,对缓存的CRUD操作在Cache组件中,每一个缓存组件有自己唯一的名字
*  @Cacheable的几个属性
*      value/cacheNames:指定缓存组件的名称,将方法的返回结果放在哪个缓存中,是数组的方式,可以指定多个缓存
*      key:缓存数据使用的Key,可以用它来指定,key默认是使用方法参数的值,value它的值就是方法的返回值
*          编写SpEL:#id:参数id的值     #root.args[0]:第0个参数的值
*          key = "#root.methodName+'['+#id+']'"————key的值就是getEmp[2]
*      keyGenerator:key的生成器,可以自己指定key的生成器的组件Id
*              keyGenerator/key:二选一使用
*      cacheManager:指定缓存管理器,或者cacheResolver指定缓存解析器
*              cacheManagercacheResolver/二选一
*      condition:指定符合条件的情况下才缓存  condition = "#id>0":#id大于0才缓存
*      unless:否定缓存;当unless指定条件为true,方法的返回值就不会被缓存;可以获取到结果进行判断
*              unless="#result==null"
*      sync:是否使用异步模式
* @param id
* @return
*/
@Cacheable(cacheNames = "emp"/*,keyGenerator = "myKeyGenerator",condition = "#a0>1",unless = "#a0==2"*/)
public Employee getEmp(Integer id){
System.out.println("查询"+id+"号员工");
return employeeMapper.getEmpById(id);
}

@CachePut

/**
* @CachePut :既调用方法又更新缓存,修改了数据库某个数据,同时更新缓存
*      1、先调用目标方法,
*      2、将目标方法的结果缓存起来
*  测试:
*      1、查询1号员工,结果会存在缓存中
*      2、更新1号员工
*      3、结果没更新
*          因为之前1号员工的key保存的是1,而更新1号员工时,默认的key是employee对象
*      4、指定更新的员工的key
*          key = "#employee.id",可以从传入的参数的属性取值
*          key = "#result.id",这个方法返回了值,也可以从返回值的属性取值
* @param employee
* @return
*/
@CachePut(value = "emp",key = "#employee.id")
public Employee updateEmp(Employee employee){
System.out.println("调update方法:"+employee);
employeeMapper.updateEmployee(employee);
return employee;
}

@CacheEvict

/**
* @CacheEvict 缓存清除
*      allEntries = true:清除emp这个缓存中所有缓存
*      beforeInvocation = false:缓存的清除是否在方法之前执行,默认是在方法执行之后执行,如果出现异常,缓存就不会清除
*      beforeInvocation = true:代表清除缓存在方法之前运行,无论是否出现异常,缓存都清除
* @param id
*/
@CacheEvict(value = "emp",allEntries = true)
public void deleteEmp(Integer id){
System.out.println("删除员工:"+id);
employeeMapper.deleteEmpById(id);
}

三、整合Redis作为缓存

1、安装Redis

引入redis的starter

最开始的POM已经引入过了

3、配置redis

这里就配置redis的ip地址即可

spring.redis.host=192.168.43.223

4、测试缓存

编写Mapper接口

package com.wzw.cache.mapper;

@Repository
public interface EmployeeMapper {

@Select("select * from employee where id=#{id}")
public Employee getEmpById(Integer id);

@Update("update employee set lastName=#{lastName},email=#{email},gender=#{gender},d_id=#{dId} where id=#{id}")
public void updateEmployee(Employee employee);

@Delete("delete from employee where id=#{id}")
public void deleteEmpById(Integer id);

@Options(useGeneratedKeys = true,keyProperty = "id")
@Insert("insert into employee(lastName,email,gender,d_id) values(#{lastName},#{email},#{gender},#{dId})")
public void insertUser(Employee employee);

@Select("select * from employee where lastName=#{lastName}")
Employee getEmpByLastName(String lastName);
}

  引入redis的starter,CacheManager就会变为RedisCacheManager,直接保存在Redis中。

package com.wzw.cache;

import com.wzw.cache.bean.Employee;
import com.wzw.cache.mapper.EmployeeMapper;
import org.junit.jupiter.api.Test;
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;

@SpringBootTest
class Springboot01CacheApplicationTests {

@Autowired
EmployeeMapper employeeMapper;

@Autowired
RedisTemplate redisTemplate;    //操作k-v都是对象的

@Autowired
StringRedisTemplate stringRedisTemplate;  //因为操作字符串的比较多,所以单独列出来一个StringRedisTemplate操作k-v都是字符串的

@Autowired
RedisTemplate<Object, Employee> empRedisTemplate;

/**
* redis常见的五大数据类型
*  String(字符串)
*      stringRedisTemplate.opsForValue()
*  List(列表)
*      stringRedisTemplate.opsForList()
*  Set(集合)
*      stringRedisTemplate.opsForSet()
*  Hash(散列)
*      stringRedisTemplate.opsForHash()
*  ZSet(有序集合)
*      stringRedisTemplate.opsForZSet()
*/
@Test
void testRedis(){
//	    stringRedisTemplate.opsForValue().append("key1","value1");
//        System.out.println(stringRedisTemplate.opsForValue().get("key1"));
stringRedisTemplate.opsForList().leftPushAll("mylist","1","2","3","4");
//        System.out.println(stringRedisTemplate.opsForList().range("mylist",0,-1));
}

//测试保存对象
@Test
void tetRedisObject(){
//默认如果保存对象,使用Jdk序列化机制,序列化后的数据保存到redis中
//	    redisTemplate.opsForValue().set("emp1",employeeMapper.getEmpById(1));
/**
* 1.将数据以json方式保存,
*      (1)自己将对象转成json
*      (2)redisTemplate默认的序列化规则,改变默认的序列化规则
*/
empRedisTemplate.opsForValue().set("emp1",employeeMapper.getEmpById(1));
System.out.println(empRedisTemplate.opsForValue().get("emp1"));

}

}

  默认保存数据k-v都是Object,利用序列化保存,在Redis Desktop中查看到的是序列化后的结果

  默认创建的RedisCacheManager操作Redis的时候使用的是RedisTemplate<Object,Objet>
想要直接在Redis中查看到对象,如下所示,需要编写配置类

编写配置类

@Configuration
public class MyRedisConfig extends CachingConfigurerSupport {
/**
* 配置序列化,作为一个对象存在Redis中,而不是jdk的序列化机制
*
* @param redisConnectionFactory
* @return
* @throws UnknownHostException
*/
@Bean
public RedisTemplate<Object, Employee> empRedisTemplate(RedisConnectionFactory redisConnectionFactory
) throws UnknownHostException {
RedisTemplate<Object, Employee> template = new RedisTemplate<Object, Employee>();
template.setConnectionFactory(redisConnectionFactory);
//        Jackson2JsonRedisSerializer<Employee> ser = new Jackson2JsonRedisSerializer<Employee>(Employee.class);
GenericJackson2JsonRedisSerializer ser = new GenericJackson2JsonRedisSerializer();
template.setDefaultSerializer(ser);
return template;
}

以上是测试的时候通过注入RedisTemplate就能改变默认的jdk序列化,作为一个对象存在Redis中,网页访问需要自定义配置类

自定义配置类

@Configuration
public class MyRedisConfig extends CachingConfigurerSupport {

/**
* 配置序列化,作为一个对象存在Redis中,而不是jdk的序列化机制
*
* @param redisConnectionFactory
* @return
* @throws UnknownHostException
*/
@Bean
public RedisTemplate<Object, Employee> empRedisTemplate(RedisConnectionFactory redisConnectionFactory
) throws UnknownHostException {
RedisTemplate<Object, Employee> template = new RedisTemplate<Object, Employee>();
template.setConnectionFactory(redisConnectionFactory);
//        Jackson2JsonRedisSerializer<Employee> ser = new Jackson2JsonRedisSerializer<Employee>(Employee.class);
GenericJackson2JsonRedisSerializer ser = new GenericJackson2JsonRedisSerializer();
template.setDefaultSerializer(ser);
return template;
}

/*
springboot2.0已经废弃
@Bean
public RedisCacheManager employeeCacheManager(RedisTemplate<Object, Employee> empRedisTemplate){
RedisCacheManager cacheManager=new RedisCacheManager(empRedisTemplate);
cacheManager.setUsePrefix(true);

}*/
//过期时间1天
private Duration timeToLive = Duration.ofDays(1);

@Bean
public RedisCacheManager cacheManager(RedisConnectionFactory connectionFactory) {
//默认1
RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig()
.entryTtl(this.timeToLive)
.serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(keySerializer()))
.serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(valueSerializer()))
.disableCachingNullValues();
RedisCacheManager redisCacheManager = RedisCacheManager.builder(connectionFactory)
.cacheDefaults(config)
.transactionAware()
.build();
//        log.debug("自定义RedisCacheManager加载完成");
return redisCacheManager;
}

private RedisSerializer<String> keySerializer() {
return new StringRedisSerializer();
}

private RedisSerializer<Object> valueSerializer() {
return new GenericJackson2JsonRedisSerializer();
}
}

  • 点赞
  • 收藏
  • 分享
  • 文章举报
WuWuII 发布了23 篇原创文章 · 获赞 0 · 访问量 680 私信 关注
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: