Redis安装
Redis 是完全开源免费的,遵守BSD协议,是一个高性能的key-value数据库。
Redis 与其他 key - value 缓存产品有以下三个特点:
- Redis支持数据的持久化,可以将内存中的数据保存在磁盘中,重启的时候可以再次加载进行使用。
- Redis不仅仅支持简单的key-value类型的数据,同时还提供list,set,zset,hash等数据结构的存储。
- Redis支持数据的备份,即master-slave模式的数据备份。
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.youkuaiyun.com/f641385712/article/details/84679456