SpringBoot整合Redis以及Redis的序列化

一、搭建基本环境

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', '李四', '[email protected]', '1', '1');
INSERT INTO `employee` VALUES ('2', '张三', '[email protected]', '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();
    }
}

在这里插入图片描述

发布了7 篇原创文章 · 获赞 0 · 访问量 156

猜你喜欢

转载自blog.csdn.net/a3562323/article/details/104207072
今日推荐