spring cache(三)demo

一、入门demo

1、pom
<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><groupId>org.example</groupId><artifactId>plus-cache-demo</artifactId><version>1.0-SNAPSHOT</version><properties><maven.compiler.source>17</maven.compiler.source><maven.compiler.target>17</maven.compiler.target><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding></properties><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>3.2.4</version><relativePath/></parent><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><!--尽量不要同时导入mybatis 和 mybatis_plus,避免版本差异--><dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-spring-boot3-starter</artifactId><version>3.5.5</version></dependency><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>8.0.13</version></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId></dependency><!--cache-->
<!--        <dependency>-->
<!--            <groupId>org.springframework.boot</groupId>-->
<!--            <artifactId>spring-boot-starter-data-redis</artifactId>-->
<!--        </dependency>-->
<!--        <dependency>-->
<!--            <groupId>org.springframework.boot</groupId>-->
<!--            <artifactId>spring-boot-starter-data-redis-reactive</artifactId>-->
<!--        </dependency>--><!--        <dependency>-->
<!--            <groupId>org.springframework.boot</groupId>-->
<!--            <artifactId>spring-boot-starter-cache</artifactId>-->
<!--        </dependency>--><!--spring-boot-starter-data-redis--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId></dependency><!--spring cache--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-cache</artifactId></dependency><dependency><groupId>org.apache.commons</groupId><artifactId>commons-pool2</artifactId></dependency></dependencies>
</project>
2、配置文件
server.port=1111
server.servlet.context-path=/plusDemo
#mysql
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3308/demo?useUnicode=true&characterEncoding=utf-8&useSSL=false
spring.datasource.username=root
spring.datasource.password=wtyy
#mybatis
mybatis.mapper-locations=classpath*:mapper/*Mapper.xml
#打印日志
mybatis-plus.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl#redis
spring.data.redis.host=127.0.0.1
spring.data.redis.port=6379
spring.data.redis.password=
spring.data.redis.lettuce.pool.max-active=8
spring.data.redis.lettuce.pool.max-wait=-1
spring.data.redis.lettuce.pool.max-idle=8
spring.data.redis.lettuce.pool.min-idle=0
spring.data.redis.lettuce.pool.enabled=true
spring.data.redis.lettuce.pool.time-between-eviction-runs=30s
#cache
#类型指定redis
spring.cache.type=redis
#一个小时,以毫秒为单位
spring.cache.redis.time-to-live=3600000
#给缓存的建都起一个前缀。  如果指定了前缀就用我们指定的,如果没有就默认使用缓存的名字作为前缀,一般不指定
#spring.cache.redis.key-prefix=CACHE_
#指定是否使用前缀
spring.cache.redis.use-key-prefix=true
#是否缓存空值,防止缓存穿透
spring.cache.redis.cache-null-values=true
3、config
package com.pluscache.demo.config;import org.springframework.boot.autoconfigure.data.redis.RedisProperties;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.context.annotation.Configuration;@Configuration
@EnableCaching
@EnableConfigurationProperties(RedisProperties.class)//开启属性绑定配置的功能
public class MyCacheConfig {
}
4、controller
package com.pluscache.demo.controller;import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.pluscache.demo.dto.ParamDTO;
import com.pluscache.demo.dto.UserDTO;
import com.pluscache.demo.service.ParamService;
import com.pluscache.demo.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;import java.util.List;@RestController
@RequestMapping("/param")
public class ParamController {@Autowiredprivate ParamService paramService;@RequestMapping("/listParams")public List<ParamDTO> listParams() {return paramService.listParams();}@RequestMapping("/addParam")public void addParam(ParamDTO paramDTO) {paramService.addParam(paramDTO);}@RequestMapping("/listParamsByKey")public List<ParamDTO> listParamsByKey(String key) {return paramService.listParamsByKey(key);}@RequestMapping("/deleteById")public void deleteById(String key) {paramService.deleteByKey(key);}}
5、service
package com.pluscache.demo.service.impl;import com.pluscache.demo.dto.ParamDTO;
import com.pluscache.demo.repository.ParamRepository;
import com.pluscache.demo.service.ParamService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;import java.util.List;@Service("paramService")
public class ParamServiceImpl implements ParamService {@Autowiredprivate ParamRepository paramRepository;@Overridepublic List<ParamDTO> listParams() {return paramRepository.listParams();}@Overridepublic void addParam(ParamDTO paramDTO) {paramRepository.addParam(paramDTO);}@Overridepublic List<ParamDTO> listParamsByKey(String key) {return paramRepository.listParamsByKey(key);}@Overridepublic void deleteByKey(String key) {paramRepository.deleteByKey(key);}
}
6、dao
package com.pluscache.demo.repository;import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.pluscache.demo.constant.DbConstant;
import com.pluscache.demo.dto.ParamDTO;
import com.pluscache.demo.dto.UserDTO;
import com.pluscache.demo.mapper.ParamMapper;
import com.pluscache.demo.mapper.UserMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheConfig;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Repository;import java.util.List;@Repository
@CacheConfig(cacheNames = {DbConstant.TABLE_PARAM_NAME_KEY_FORMAT})
@Slf4j
public class ParamRepository {@Autowiredprivate ParamMapper paramMapper;//1、无参@Cacheable(key = "#root.methodName")public List<ParamDTO> listParams() {log.info("listParams无参start");LambdaQueryWrapper<ParamDTO> queryWrapper = new LambdaQueryWrapper<>();return paramMapper.selectList(queryWrapper);}@CacheEvict(key = "#root.methodName")public void addParam(ParamDTO paramDTO) {paramMapper.insert(paramDTO);}//2、单参@Cacheable(key = "{#p0}")public List<ParamDTO> listParamsByKey(String key) {log.info("listParamsByKey有参start");LambdaQueryWrapper<ParamDTO> queryWrapper = new LambdaQueryWrapper<>();queryWrapper.eq(ParamDTO::getParamKey,key);return paramMapper.selectList(queryWrapper);}@CacheEvict(key = "{#p0}",beforeInvocation = true)public void deleteByKey(String key) {LambdaQueryWrapper<ParamDTO> queryWrapper = new LambdaQueryWrapper<>();queryWrapper.eq(ParamDTO::getParamKey,key);paramMapper.delete(queryWrapper);//int a = 1/0;}
}
package com.pluscache.demo.mapper;import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.pluscache.demo.dto.ParamDTO;
import com.pluscache.demo.dto.UserDTO;
import org.apache.ibatis.annotations.Param;import java.util.List;public interface ParamMapper extends BaseMapper<ParamDTO> {void batchDeleteByKey(@Param("keys") List<String> keys);
}
 7、dto与常量
package com.pluscache.demo.dto;import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;import java.io.Serializable;@Data
@TableName("t_param")
public class ParamDTO implements Serializable {private Integer id;private String paramKey;private String paramValue;
}
package com.pluscache.demo.constant;public class DbConstant {public static final String TABLE_PARAM_NAME_KEY_FORMAT = "cache:t_param:";
}
8、测试:
8.1、无参

①  第一次访问localhost:1111/plusDemo/param/listParams控制台输出:

2024-04-25T17:14:33.330+08:00  INFO 36136 --- [nio-1111-exec-2] com.zaxxer.hikari.HikariDataSource       : HikariPool-1 - Start completed.
JDBC Connection [HikariProxyConnection@644769222 wrapping com.mysql.cj.jdbc.ConnectionImpl@5ee5b9f5] will not be managed by Spring
==>  Preparing: SELECT id,param_key,param_value FROM t_param
==> Parameters: 
<==    Columns: id, param_key, param_value
<==        Row: 1, a, a_1
<==        Row: 2, a, a_2
<==      Total: 2
Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@14369ce6]

查看redis:

②  再次访问,返回数据和第一次一样,但是控制台无输出,断点可以看到在serveimImpl直接返回了,并没有进入ParamRepository。

8.2、单参
(1)缓存与删除缓存

 访问localhost:1111/plusDemo/param/listParamsByKey?key=a

 第一次走db查询,后面不走db查询。查看redis:

key为t_param:::a:

value为:

访问localhost:1111/plusDemo/param/deleteById?key=a 刷新redis可以看到缓存已经被删除了

这时再访问listParamsByKey发现又走db层了

(2)删除缓存加入异常
 @CacheEvict(key = "{#p0}",beforeInvocation = true)public void deleteByKey(String key) {LambdaQueryWrapper<ParamDTO> queryWrapper = new LambdaQueryWrapper<>();queryWrapper.eq(ParamDTO::getParamKey,key);paramMapper.delete(queryWrapper);int a = 1/0;}

访问localhost:1111/plusDemo/param/listParamsByKey?key=a后再访问localhost:1111/plusDemo/param/deleteById?key=a可以看到缓存已经清除了,重新走db查询

如果没有写beforeInvocation = true,仍然走缓存查询,验证beforeInvocation决定了缓存和db的先后顺序。

二、自定义KeyConstructor

对上面的demo进行改造:

① 在前面也提到了,Repository的CUD接口应该接收(集合)对象;

②  如果Repository中有多种组合key的缓存,CUD接口在@CacheEvict注解中维护key比较麻烦,所以我们可以把key组合提到自定义KeyConstructor中。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/840651.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

ACL组网实验(华为)

思科设备参考&#xff1a;ACL组网实验&#xff08;思科&#xff09; 更多内容参考&#xff1a;华为ACL配置&#xff08;基本ACL高级ACL综合应用&#xff09; 技术简介 ACL&#xff08;Access Control List&#xff09;技术是一种基于包过滤的流控制技术&#xff0c;主要用于…

ML307R OpenCPU UART使用

一、串口使用流程图 二、串口相关函数介绍 三、实现串口收发 一、串口使用流程图 OneMO ML307R模组提供了2路UART给开发者用于通讯开发&#xff0c;以及1路DBG UART用于log的打印。UART Demo示例可以在SDK&#xff1a;examples\uart\src\cm_demo_uart.c中查看。 串口使用流…

Vue3实战笔记(42)—Vue + ECharts:流量数据可视化的强大组合

文章目录 前言vue3使用echarts标准demo&#xff1a;总结 前言 在前端开发中&#xff0c;数据可视化已经成为了一个不可或缺的部分。Vue.js作为一个轻量级且易于上手的渐进式JavaScript框架&#xff0c;与ECharts这个强大的数据可视化库的结合&#xff0c;使得在Vue应用中构建交…

java继承(构造器)使用细节3

那么我们怎么来选择用父类的 有参构造器 和无参构造器泥&#xff1f; 就可以不写 或只写super() 并且如像爸爸的爸爸还有爸爸&#xff0c;还有构造。所以会一直调用到爷爷的构造。 细节2 直接继承指的是儿子和爸爸&#xff0c;爸爸和爷爷

Python 渗透测试:Redis 数据库 弱密码测试.(6379端口)

什么是 Redis 数据库 Redis (Remote Dictionary Server) 是一个开源的、内存中的数据结构存储系统&#xff0c;它可以用作数据库、缓存和消息中间件。它支持多种类型的数据结构,如字符串(strings)、哈希(hashes)、列表(lists)、集合(sets)、有序集合(sorted sets)等&#xff0…

View function mapping is overwriting an existing endpoint function: home_page

这个错误是因为在你的 Flask 应用中,你定义了两个或多个视图函数,它们使用了相同的 endpoint 名称。Flask 不允许多个视图函数使用相同的 endpoint 名称,因为这会导致冲突。 通常,这个错误会出现在以下几种情况下: 你在不同的路由装饰器中使用了相同的 endpoint 名称。你…

Xilinx(AMD) FPGA通过ICAP原语读取芯片IDCODE实现方法

1 概述 Xilinx每种型号的FPGA芯片都有一个唯一的IDCODE与之对应&#xff0c;同一型号不同封装的IDCODE是相同的。IDCODE的获取方法包括JTAG、ICAP原语、AXI_HWICAP IP核等。获取IDCODE常用于根据芯片型号改变代码的功能&#xff0c;或者对代码进行授权保护&#xff0c;只能在指…

Java使用apache.poi生成excel插入word中

加油&#xff0c;新时代打工人&#xff01; 工作需求&#xff0c;上个文章我们生成好的word&#xff0c;这次将生成好的excel表格数据&#xff0c;插入word中。需要准备好excle数据&#xff0c;然后插入到word中。 最后个需要&#xff0c;就是把这些生成好的word文档转成pdf进行…

EyeMock下载与使用教程

视频眼神修复直视镜头的AI具有极高的灵活性和适应性。它可以根据不同的拍摄环境和主播需求进行个性化设置&#xff0c;确保最佳的视觉呈现效果。在直播互动中&#xff0c;主播可能因为分神或疲劳而失去与观众的直视&#xff0c;这款工具能够迅速识别并修复这一问题&#xff0c;…

机器学习(七) ----------聚类(K-means)

目录 1 核心思想 2 K-means算法 2.1 算法概述 2.2 算法步骤 2.3 数学原理 2.4 ‘肘’方法确定K值 2.4.1 原理 2.4.2 步骤 2.4.3 代码实现 2.5 聚类评估方法 2.5.1 SC轮廓系数&#xff08;Silhouette Coefficient&#xff09; 计算方法 解读 注意事项 2.5.2 Cal…

刷代码随想录有感(77):回溯算法——含有重复元素的全排列

题干&#xff1a; 代码&#xff1a; class Solution { public:vector<int> tmp;vector<vector<int>> res;void backtracking(vector<int> nums, vector<int> used){if(tmp.size() nums.size()){res.push_back(tmp);return;}sort(nums.begin(),…

对安卓手机上损坏的 SD 卡进行故障排除:恢复提示和修复

概括 如果您总是在旅途中&#xff0c;那么您很可能每天都在使用 SD 卡。这些微小但功能强大的闪存已经变得和手机的内部存储一样有用。它们可以存储数据并移动您想要的任何数据类型&#xff0c;因为它们在 Android 设备上添加了额外的存储空间。不幸的是&#xff0c;他们可能会…

四天学会JS高阶(学好vue的关键)——深入面向对象(理论+实战)(第三天)

***本章面试使用居多* 理论篇**一、编程思想 1.1 面向过程 JS 前端居多 按照步骤 性能高 适合跟硬件关系很紧密 没有面向对象易维护易复用易扩展 1.2 面向对象 java典型 按照功能&#xff0c;把事务分别成一个个对象&#xff0c;对象之间分工合作 比较灵活 适合多人合作的…

python绘制多级饼图(分层饼图)

python绘制多级饼图&#xff08;分层饼图&#xff09; 介绍效果代码 介绍 多级饼图展示了数据的层次结构&#xff0c;其中每个级别表示数据的一个层次。我们可以使用matplotlib绘制多级饼图。 效果 代码 import matplotlib.pyplot as plt# 示例数据 outer_labels [Category…

css卡片横线100%宽度

所需样式: 横线不用border, 用单独一个div, 这样就不会影响父组件的padding <div class"pumpDetailView"><div class"pump_title_name"><span>{{ pumpInfo.pointname }}</span><divclass"point_state":style"…

html 字体设置 (web端字体设置)

windows自带的字体是有版权的&#xff0c;包括微软雅黑&#xff08;方正&#xff09;、宋体&#xff08;中易&#xff09;、黑体&#xff08;中易&#xff09;等 版权算是个大坑&#xff0c;所谓为了避免版权问题&#xff0c;全部使用开源字体即可 我这里选择的是思源宋体&…

nodejs 与 npm 版本对应关系

官方地址&#xff1a;https://nodejs.org/en/about/previous-releases

C++容器之无序多集(std::unordered_multiset)

目录 1 概述2 使用实例3 接口使用3.1 construct3.2 assigns3.3 iterators3.4 capacity3.5 find3.6 count3.7 equal_range3.8 emplace3.9 emplace_hint3.10 insert3.11 erase3.12 clear3.13 swap3.14 bucket_count3.15 max_bucket_count3.16 bucket_size3.17 bucket3.18 load_fa…

全栈式数据统计:SqlAlchemy怎样连接MsSql Server获取视图列表

1.源代码 #-----------获取数据库视图列表----------------------------- # -------密码含特殊字符使用 from urllib.parse import quote_plus as urlquotefrom sqlalchemy import create_engine, MetaData, inspect# 替换为你的数据库连接字符串 DRIVER "ODBC Driver 1…

【新】snapd申请Let‘s Encrypt免费SSL证书、自动化续签证书

简介 之前写过一篇certbot申请SSL证书的文章&#xff1a;SSL证书申请&#xff0c;写得比较详细&#xff0c;但是最近发现使用snapd会更方便。 使用机器&#xff1a;Ubuntu 20.04 简单步骤 1、首先安装必要软件 sudo apt install snapd sudo apt install certbot sudo apt …