springboot整合redis做缓存管理详解

Redis安装

     Redis 是完全开源免费的,遵守BSD协议,是一个高性能的key-value数据库。

     Redis 与其他 key - value 缓存产品有以下三个特点:

  •        Redis支持数据的持久化,可以将内存中的数据保存在磁盘中,重启的时候可以再次加载进行使用。
  •        Redis不仅仅支持简单的key-value类型的数据,同时还提供list,set,zset,hash等数据结构的存储。
  •        Redis支持数据的备份,即master-slave模式的数据备份。

    redis安装传送门

pom.xml依赖

<dependencies>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>

		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
		</dependency>
		
		<dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>1.3.2</version>
        </dependency>
		
		<dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>
        
		<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
        </dependency>
		
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-cache</artifactId>
        </dependency>
        
        <dependency>        
		    <groupId>com.fasterxml.jackson.core</groupId>
		    <artifactId>jackson-annotations</artifactId>
		</dependency>
		
		<dependency>
		    <groupId>com.alibaba</groupId>
		    <artifactId>druid-spring-boot-starter</artifactId>
		    <version>1.1.10</version>
		</dependency>
			
		<dependency>
	        <groupId>org.springframework.boot</groupId>
	        <artifactId>spring-boot-devtools</artifactId>
	        <optional>true</optional>
	    </dependency>
	</dependencies>

application.yml配置

server:
  port: 8080
  
spring:
  datasource:
    type: com.alibaba.druid.pool.DruidDataSource
    driver-class-name: com.mysql.jdbc.Driver
    url: jdbc:mysql://localhost:3306/dycai?useUnicode=true&characterEncoding=utf8&allowPublicKeyRetrieval=true&useSSL=false
    username: root
    password: "088114"
  redis:
    host: localhost
    port: 6379
    password: 
    database: 0

mybatis:
  mapper-locations: classpath:mapper/*.xml

使用redis做缓存配置

配置部分主要是配置缓存管理器CacheManager 和RedisTemplate

Redis采用key-value存储的存储方式,对key和value需要序列化,常用四种序列化器StringRedisSerializer、JdkSerializationRedisSerializer、Jackson2JsonRedisSerializer、GenericJackson2JsonRedisSerializer的详细介绍如下:

1、StringRedisSerializer:

      优点:开发者友好,轻量级,效率也比较高
                 缺点:只能序列化String类型,如果key使用该序列化器,则key必须为String类型

2、jdkSerializationRedisSerializer:RestTemplate类默认的序列化方式,如果指定序列化器,则为它
                优点:反序列化时不需要提供类型信息(class)
                缺点:a、首先它要求存储的对象都必须实现java.io.Serializable接口,比较笨重
                          b、其次,他存储的为二进制数据,这对开发者是不友好的,无法直观查看数据
                          c、序列化后的结果非常庞大,是JSON格式的5倍左右,这样就会消耗redis服务器的大量内存。  

3、Jackson2JsonRedisSerializer:把一个对象以Json的形式存储,效率高且对调用者友好
                 优点:速度快,序列化后的字符串短小精悍,不需要存储对象实现java.io.Serializable接口
                 缺点:那就是此类的构造函数中有一个类型参数,必须提供要序列化对象的类型信息(.class对象),反序列化用到了该                              类型信息 

4、GenericJackson2JsonRedisSerializer:基本和上面的Jackson2JsonRedisSerializer功能差不多,使用方式也差不多,但不需要提供类型信息,推荐使用;

以上四种序列化方式如何配置见下面的代码片段,下面的代码片段采用的是StringRedisSerializer序列化key,GenericJackson2JsonRedisSerializer序列化value;

@Configuration
@EnableCaching
public class CacheConfig{
	/**
	 * 配置缓存管理器RedisCacheManager
	 * Redis采用key-value存储的存储方式,对key和value需要序列化
	 * Redis的序列化方式由StringRedisSerializer,JdkSerializationRedisSerializer,GenericJackson2JsonRedisSerializer,GenericJackson2JsonRedisSerializer等
	 * RedisCacheManager默认采用StringRedisSerializer序列化key,JdkSerializationRedisSerializer序列化value
	 * @param redisConnectionFactory
	 * @return
	 */
	@Bean
	public CacheManager cacheManager(RedisConnectionFactory redisConnectionFactory) {
//		StringRedisSerializer序列器:
//		优点:开发者友好,轻量级,效率也比较高
//		缺点:只能序列化String类型,如果key使用该序列化器,则key必须为String类型
		RedisSerializer<String> redisSerializer = new StringRedisSerializer();
		
//		jdkSerializationRedisSerializer序列化器:RestTemplate类默认的序列化方式,如果指定序列化器,则为它
//		优点:反序列化时不需要提供类型信息(class)
//		缺点:1、首先它要求存储的对象都必须实现java.io.Serializable接口,比较笨重
//			  2、其次,他存储的为二进制数据,这对开发者是不友好的
//			  3、序列化后的结果非常庞大,是JSON格式的5倍左右,这样就会消耗redis服务器的大量内存。		
//		ClassLoader loader = this.getClass().getClassLoader();
//		JdkSerializationRedisSerializer jdkSerializationRedisSerializer = new JdkSerializationRedisSerializer(loader);
		
//		Jackson2JsonRedisSerializer序列化器:把一个对象以Json的形式存储,效率高且对调用者友好
//		优点:速度快,序列化后的字符串短小精悍,不需要存储对象实现java.io.Serializable接口
//		缺点:那就是此类的构造函数中有一个类型参数,必须提供要序列化对象的类型信息(.class对象),反序列化用到了该类型信息
//		Jackson2JsonRedisSerializer<Object> jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer<>(Object.class);
//		ObjectMapper objectMapper = new ObjectMapper();
//		objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
		
//		GenericJackson2JsonRedisSerializer序列化器:基本和上面的Jackson2JsonRedisSerializer功能差不多,使用方式也差不多,
//		但不需要提供类型信息,推荐使用
		GenericJackson2JsonRedisSerializer genericJackson2JsonRedisSerializer = new GenericJackson2JsonRedisSerializer();
		RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig()
				.entryTtl(Duration.ofMinutes(10))	//设置失效时间
				.serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(redisSerializer))
				.serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(genericJackson2JsonRedisSerializer));
		
		RedisCacheManager redisCacheManager = RedisCacheManager.builder(redisConnectionFactory)
				.cacheDefaults(config)
				.build();
		
		return redisCacheManager;
	}
	
	@Bean
	public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory){
		RedisTemplate<String, Object> template = new RedisTemplate<>();
		template.setConnectionFactory(redisConnectionFactory);
		GenericJackson2JsonRedisSerializer genericJackson2JsonRedisSerializer = new GenericJackson2JsonRedisSerializer();		
		template.setKeySerializer(new StringRedisSerializer());
		template.setValueSerializer(genericJackson2JsonRedisSerializer);		
		template.setHashKeySerializer(new StringRedisSerializer());
		template.setHashValueSerializer(genericJackson2JsonRedisSerializer);
		template.afterPropertiesSet();
		return template;
	}
}

实列

代码结构如下

UserController.java

package cn.cai.microservice.controller;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;

import cn.cai.microservice.entiy.User;
import cn.cai.microservice.service.UserService;

@RestController
public class UserController {	
	private static final Logger log = LoggerFactory.getLogger(UserController.class);
	@Autowired
	private UserService userService;
	
	@PostMapping("/get/UserInfo/{userName}")
	public User getUserInfoByName(@PathVariable(value="userName") String userName) {
		long startTime = System.currentTimeMillis();
		User user =  userService.getUserInfoByName(userName);
		log.info("查询耗时:" + (System.currentTimeMillis() - startTime) + "ms");
		return user;
	}
	
	@PostMapping("/update/UserInfo")
	public void updateUserInfo(@RequestBody User user) {
		userService.updateUserInfo(user);
	}
	
	@PostMapping("/delete/userInfo/{userName}")
	public void deleteUserInfo(@PathVariable(value="userName") String userName) {
		userService.deleteUserInfo(userName);
	}
	
	@PostMapping("/insert/UserInfo")
	public void insertUserInfo(@RequestBody User user) {
		userService.insertUserInfo(user);
	}
	
}

UserDao.java

package cn.cai.microservice.dao;

import cn.cai.microservice.entiy.User;

public interface UserDao {
	User getUserInfoByName(String userName);
	
	void updateUserInfo(User user);
	
	void deleteUserInfo(String userName);
	
	void insertUserInfo(User user);
}

User.java

package cn.cai.microservice.entiy;

import java.io.Serializable;

//如果采用的是JdkSerializationRedisSerializer序列化器序列化value,则存储对象必须实现Serializable接口
//其他序列化器,可以不实现
public class User implements Serializable{

	private static final long serialVersionUID = 1L;
	private String userName;
	private String password;
	private String email;
	
	public String getUserName() {
		return userName;
	}
	public void setUserName(String userName) {
		this.userName = userName;
	}
	public String getPassword() {
		return password;
	}
	public void setPassword(String password) {
		this.password = password;
	}
	public String getEmail() {
		return email;
	}
	public void setEmail(String email) {
		this.email = email;
	}
	@Override
	public String toString() {
		return "User [userName=" + userName + ", password=" + password + ", email=" + email + "]";
	}
}

UserService.java

     Spring提供缓存注解@Cacheable、@CacheEvict、@CachePut

     @Cacheable:如果缓存之中能够查找到,就不执行该注解下面的方法,如果找不到,就执行方法,将方法的返回结果作为value防止到缓存中;

     @CachePut:不管缓存之中能否查找到,该注解下的方法都会被执行,且用返回结果作为value更新缓存

     @CachePut:删除指定key的缓存 

package cn.cai.microservice.service;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.CachePut;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;

import cn.cai.microservice.dao.UserDao;
import cn.cai.microservice.entiy.User;

@Service
public class UserService {
	private static final Logger log = LoggerFactory.getLogger(UserService.class);	
	@Autowired
	private UserDao userDao;	
	
//	注解@Cacheable:如果缓存之中能够查找到,就不执行该注解下面的方法;
//	如果找不到,就执行方法,将方法的返回结果作为value防止到缓存中;
	@Cacheable(value="userInfoCache", key="#userName")
	public User getUserInfoByName(String userName) {
		log.info("查询" + userName + "信息");
		User user = userDao.getUserInfoByName(userName);
		return user;
	}

//	注解@CachePut:不管缓存之中能否查找到,该注解下的方法都会被执行,且用返回结果作为value更新缓存
	@CachePut(value="userInfoCache", key="#user.userName")
	public User updateUserInfo(User user) {
		log.info("更新" + user.getUserName() + "信息");
		userDao.updateUserInfo(user);	
		return user;
	}

//	注解@CachePut:删除指定key的缓存 
	@CacheEvict(value="userInfoCache", key="#userName")
	public void deleteUserInfo(String userName) {
		log.info("删除" + userName + "信息");
		userDao.deleteUserInfo(userName);	
	}
	
	@CachePut(value="userInfoCache", key="#user.userName")
	public User insertUserInfo(User user) {
		userDao.insertUserInfo(user);
		return user;
	}
	
}

UserMapper.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >

<mapper namespace="cn.cai.microservice.dao.UserDao">

	<select id="getUserInfoByName" resultType="cn.cai.microservice.entiy.User">
		select * from userInfo where userName=#{userName}
	</select>
	
	<update id="updateUserInfo">
		update userInfo set
			password=#{password},
			email=#{email}
		where userName=#{userName} 
	</update>

	<delete id="deleteUserInfo">
		delete from userInfo where userName=#{userName}
	</delete>
	
	<insert id="insertUserInfo">
		insert into 
			userInfo(userName, password, email) values(#{userName}, #{password}, #{email})
	</insert>
</mapper>

SpringbootRedisCacheApplication.java

package cn.cai.microservice;

import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
@MapperScan({"cn.cai.microservice.dao"})
public class SpringbootRedisCacheApplication {

	public static void main(String[] args) {
		SpringApplication.run(SpringbootRedisCacheApplication.class, args);
	}

}

项目源码下载地址:https://github.com/xdouya/springboot-redis-cache

当时调试的时候遇到了很多坑,如有疑问,留言交流。

如果觉得有用,请记得给颗星星哦!

参考:https://www.runoob.com/redis/redis-intro.html

           https://blog.csdn.net/f641385712/article/details/84679456

 

 

  • 2
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值