springboot之redis缓存探索
Redis(Remote Dictionary Server ),即远程字典服务,是一个开源的使用ANSI C语言编写、支持网络、可基于内存亦可持久化的日志型、Key-Value数据库,并提供多种语言的API。
好了,其它的就不介绍了
@Cacheable
此注解表明在进入方法之前,Spring 会先去缓存服务器中査找对应 key 的缓存值,如果找到缓存值,那么 Spring 将不会再调用方法,而是将缓存值读出,返回给调用者;如果没有找到缓存值,那么 Spring 就会执行你的方法,将最后的结果通过 key 保存到缓存服务器中
第一次执行时redis是没有缓存的 Cacheable去redis里面查找对应的key是找不到的,便会往下执行方法
而我去数据库删除一条数据后,再去执行这个注解标识的方法
可以看到,如果有往下执行方法我的数据必定是两条数据,然后数据与我数据库数据不对应,说明取了redis里面的缓存,并没有执行方法,控制台也没有调用日志
@CachePut
主要针对方法配置,能够根据方法的返回值对其结果进行缓存,和 @Cacheable 不同的是,它每次都会触发真实方法的调用,在其他地方写的是根据方法的请求参数对其结果进行缓存,实际是按方法返回值进行缓存的
这里一般都用做更新缓存
这里第一次执行缓存
可以看到它缓存的内容为实际该方法的返回对象
如果我还以之前的id去提交数据
可以看到该注解每次都会真实调用标识的方法
@CachEvict
主要针对方法配置,能够根据一定的条件对缓存进行清空
以上为我实验之前缓存的数据
我调用CachEvict标识的方法后该缓存redis里面就找不到了
@CacheConfig
所有的@CacheXXXX()里面都有一个value=“xxx”的属性时可以一次性声明,如果你在你的方法写别的名字,那么依然以方法的名字为准。
@CacheConfig(cacheNames="redisCache")
可以看到我使用了CacheConfig后,我保存了一个key=2的一条学信息,统一使用CacheConfig标识的value
@Caching
在缓存的应用场景中 通常我们缓存某一个数据更新了,可能也会影响到其它位置的缓存,需要一个联动更新
@GetMapping("/testCaching/{id}")
@ApiOperation(value = "联动更新缓存",notes = "统一value标识")
@Caching(cacheable = @Cacheable(cacheNames = "testCaching",key = "#id"),evict = @CacheEvict(cacheNames = "redisCache",key = "#id"))
public Student testCaching(@PathVariable("id") String id){
return studentService.getById(id);
}
我这一步想要缓存 testCaching::key 然后失效 redisCache::key
我调用这个联动更新缓存的方法后
可以看到redisCache这个缓存消失了,出现了testCaching,说明实验成功了
这是个分组注解,它能够同时应用于其他缓存的注解
参数 | 解释 |
---|---|
value | 缓存的名称,在 spring 配置文件中定义,必须指定至少一个。就是个自己取的名字,通过它指明了第一次调用这个方法时返回将被存在内存的哪里。 |
key | 缓存的 key,可选。如果指定要按照 SpEL 表达式编写,如果不指定,则缺省按照方法的所有参数进行组合 |
condition | 缓存的限定条件,满足就缓存,不满足就不缓存 |
allEntries | 是否清空所有缓存内容,缺省为 false,如果指定为 true,则方法调用后将立即清空所有缓存 |
beforeInvocation | 是否在方法执行前就清空,缺省为 false,如果指定为 true,则在方法还没有执行的时候就清空缓存,缺省情况下,如果方法执行抛出异常,则不会清空缓存 |
好了上代码吧
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.zkb</groupId>
<artifactId>springboot-redis</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>springboot-redis</name>
<description>springboot-redis</description>
<properties>
<java.version>1.8</java.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<spring-boot.version>2.3.7.RELEASE</spring-boot.version>
<swagger-ui.version>1.5.22</swagger-ui.version>
<springfox.version>2.9.2</springfox.version>
<swagger-bootstrap-ui.version>1.9.1</swagger-bootstrap-ui.version>
<fastjson.version>1.2.47</fastjson.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.4.2</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>${springfox.version}</version>
<exclusions>
<exclusion>
<groupId>io.swagger</groupId>
<artifactId>swagger-annotations</artifactId>
</exclusion>
<exclusion>
<groupId>io.swagger</groupId>
<artifactId>swagger-models</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>io.swagger</groupId>
<artifactId>swagger-annotations</artifactId>
<version>${swagger-ui.version}</version>
</dependency>
<dependency>
<groupId>io.swagger</groupId>
<artifactId>swagger-models</artifactId>
<version>${swagger-ui.version}</version>
</dependency>
<!-- https://mvnrepository.com/artifact/io.springfox/springfox-swagger-ui -->
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>${springfox.version}</version>
</dependency>
<dependency>
<groupId>com.github.xiaoymin</groupId>
<artifactId>swagger-bootstrap-ui</artifactId>
<version>${swagger-bootstrap-ui.version}</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>${fastjson.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>${spring-boot.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
<encoding>UTF-8</encoding>
</configuration>
</plugin>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>2.3.7.RELEASE</version>
<configuration>
<mainClass>com.zkb.SpringbootRedisApplication</mainClass>
</configuration>
<executions>
<execution>
<id>repackage</id>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
server:
port: 8081
spring:
application:
name: springboot-redis
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
name: defaultDataSource
url: jdbc:mysql://${MYSQL_HOST:zkbplus-mysql}:${MYSQL_PORT:3306}/${MYSQL_DB:test_demo1}?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=Asia/Shanghai&autoReconnect=true&failOverReadOnly=false&zeroDateTimeBehavior=convertToNull
username: root
password: zkb.com
type: com.zaxxer.hikari.HikariDataSource
jackson:
date-format: yyyy-MM-dd HH:mm:ss
time-zone: GMT+8
redis:
host: zkbplus-redis
port: 6379
password: zkb123456
database: 3
logging:
level:
com:
fs: debug
mybatis-plus:
configuration:
map-underscore-to-camel-case: true
auto-mapping-behavior: full
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
mapper-locations: classpath:mapping/*.xml
global-config:
# 逻辑删除配置
db-config:
# 删除前
logic-not-delete-value: 0
# 删除后
logic-delete-value: 1
<?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="com.zkb.mapper.StudentMapper">
<!-- 通用查询映射结果 -->
<resultMap id="BaseResultMap" type="com.zkb.entity.Student">
<id column="id" property="id" />
<result column="name" property="name" />
<result column="age" property="age" />
</resultMap>
</mapper>
package com.zkb.conf;
import org.springframework.boot.autoconfigure.cache.CacheProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.cache.RedisCacheConfiguration;
import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.RedisSerializationContext;
@Configuration
public class RedisConfig {
@Bean
public RedisCacheConfiguration redisCacheConfiguration(CacheProperties cacheProperties) {
CacheProperties.Redis redisProperties = cacheProperties.getRedis();
RedisCacheConfiguration config = RedisCacheConfiguration
.defaultCacheConfig();
config = config.serializeValuesWith(RedisSerializationContext.SerializationPair
.fromSerializer(new GenericJackson2JsonRedisSerializer()));
if (redisProperties.getTimeToLive() != null) {
config = config.entryTtl(redisProperties.getTimeToLive());
}
if (redisProperties.getKeyPrefix() != null) {
config = config.prefixKeysWith(redisProperties.getKeyPrefix());
}
if (!redisProperties.isCacheNullValues()) {
config = config.disableCachingNullValues();
}
if (!redisProperties.isUseKeyPrefix()) {
config = config.disableKeyPrefix();
}
return config;
}
}
package com.zkb.conf;
import io.swagger.annotations.ApiOperation;
import io.swagger.models.auth.In;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.service.ApiKey;
import springfox.documentation.service.Contact;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;
import java.util.Arrays;
import java.util.List;
@Configuration
@EnableSwagger2
public class SwaggerConfig {
@Bean
public Docket createRestApi1() {
return new Docket(DocumentationType.SWAGGER_2).enable(true).apiInfo(apiInfo()).select()
.apis(RequestHandlerSelectors.withMethodAnnotation(ApiOperation.class))
.apis(RequestHandlerSelectors.basePackage("com.zkb.controller"))
.paths(PathSelectors.any()).build().securitySchemes(apiKeyList()).groupName("系统接口");
}
private ApiInfo apiInfo() {
return new ApiInfoBuilder()
.title("系统接口文档")
.description("这是系统接口文档说明")
.contact(new Contact("h2", "", ""))
.version("1.0")
.build();
}
private List<ApiKey> apiKeyList() {
return Arrays.asList(new ApiKey("登录token", "token", In.HEADER.name()),
new ApiKey("设备类型(android,ios,pc)---必填", "deviceType", In.HEADER.name()));
}
}
package com.zkb.constant;
public class CacheTimes {
public static final String D1 = "cache_1d";
}
package com.zkb.controller;
import com.zkb.constant.CacheTimes;
import com.zkb.entity.Student;
import com.zkb.service.StudentService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.*;
import org.springframework.web.bind.annotation.*;
import java.util.List;
@RequestMapping("/test")
@RestController
@Api(value = "Student", tags = "Student")
@CacheConfig(cacheNames="redisCache")
public class TestController {
@Autowired
StudentService studentService;
@GetMapping("list")
@ApiOperation(value = "获取列表")
@Cacheable(value = CacheTimes.D1)
public List<Student> getList(){
return studentService.list();
}
@PostMapping("save")
@ApiOperation(value = "保存")
@CachePut("students")
public String save(Student student){
studentService.save(student);
return "success";
}
@GetMapping("/getStudentById/{id}")
@ApiOperation(value = "根据id获取学生信息")
@Cacheable(value = CacheTimes.D1,key = "#id")
public Student getStudentById(@PathVariable("id") String id){
return studentService.getById(id);
}
@GetMapping("/deleteById/{id}")
@ApiOperation(value = "根据id删除学生信息")
@CacheEvict(value = CacheTimes.D1,key = "#id")
public void deleteById(@PathVariable("id") String id){
studentService.removeById(id);
}
@GetMapping("/getStuById/{id}")
@ApiOperation(value = "根据id获取学生信息", notes = "统一value标识")
@Cacheable(key = "#id")
public Student getStuById(@PathVariable("id") String id){
return studentService.getById(id);
}
@GetMapping("/delStuById/{id}")
@ApiOperation(value = "根据id删除学生信息",notes = "统一value标识")
@CacheEvict(key = "#id")
public void delStuById(@PathVariable("id") String id){
studentService.removeById(id);
}
@GetMapping("/testCaching/{id}")
@ApiOperation(value = "联动更新缓存",notes = "统一value标识")
@Caching(cacheable = @Cacheable(cacheNames = "testCaching",key = "#id"),evict = @CacheEvict(cacheNames = "redisCache",key = "#id"))
public Student testCaching(@PathVariable("id") String id){
return studentService.getById(id);
}
}
package com.zkb.entity;
import com.baomidou.mybatisplus.annotation.TableName;
import com.baomidou.mybatisplus.extension.activerecord.Model;
import lombok.Data;
import lombok.EqualsAndHashCode;
@Data
@EqualsAndHashCode(callSuper = false)
@TableName("student")
public class Student extends Model<Student> {
private Integer id;
private String name;
private Integer age;
}
package com.zkb.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.zkb.entity.Student;
public interface StudentMapper extends BaseMapper<Student> {
}
package com.zkb.service.impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.zkb.entity.Student;
import com.zkb.mapper.StudentMapper;
import com.zkb.service.StudentService;
import org.springframework.stereotype.Service;
@Service
public class StudentServiceImpl extends ServiceImpl<StudentMapper, Student> implements StudentService {
}
package com.zkb.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.zkb.entity.Student;
public interface StudentService extends IService<Student> {
}
package com.zkb;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cache.annotation.EnableCaching;
import springfox.documentation.swagger2.annotations.EnableSwagger2;
@SpringBootApplication
@EnableCaching // 允许使用注解进行缓存
@MapperScan(basePackages = "com.zkb.mapper")
@EnableSwagger2
public class SpringbootRedisApplication {
public static void main(String[] args) {
SpringApplication.run(SpringbootRedisApplication.class, args);
}
}
例子:https://download.csdn.net/download/qq_14926283/86608542