springboot 2.x redis缓存
程序员文章站
2022-05-01 15:53:13
...
1.pom文件导入依赖,本项目持久层使用mybatis,springboot 版本2.1.8
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.8.RELEASE</version>
<relativePath /> <!-- lookup parent from repository -->
</parent>
<groupId>com.example</groupId>
<artifactId>rediscache2</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>rediscache2</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<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>
<!-- mysql -->
<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>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
<!--spring2.0集成redis所需common-pool2-->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-pool2</artifactId>
<version>2.4.2</version>
</dependency>
<!-- redis依赖,2.0以上使用这个依赖 -->
<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>
</dependencies>
2.application.yml配置文件
#Web服务
# address :可指定在某个IP上启动服务。空表示在所有IP上启动
# context-path :发布的路径
# session.timeout :超时时间,单位:秒
server:
address:
port: 8080
servlet:
context-path:
session:
timeout: 1800
spring:
#MySQL数据库
datasource:
url: jdbc:mysql://192.168.2.101:3306/redisTest?useUnicode=true&characterEncoding=UTF-8&allowMultiQueries=true&serverTimezone=GMT%2B8
username: root
password: root
driver-class-name: com.mysql.jdbc.Driver
#Mybatis配置
mybatis:
mapper-locations: classpath*:com/example/demo/mapper/*.xml
configuration:
log-impl: org.apache.ibatis.logging.log4j2.Log4j2Impl
# log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
logging.level.com.example.demo.dao: debug
spring.redis.database: 2
spring.redis.host: localhost
spring.redis.port: 6379
spring.redis.password:
# springboot2.x以上如此配置,由于2.x的客户端是lettuce
# 单位要带上
spring.redis.lettuce.pool.max-active: 8
spring.redis.lettuce.pool.min-idle: 0
spring.redis.lettuce.pool.max-idle: 8
spring.redis.lettuce.pool.max-wait: 10000ms
spring.redis.lettuce.shutdown-timeout: 100ms
3.RedisCacheConfig缓存配置文件
import java.time.Duration;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.cache.annotation.CachingConfigurerSupport;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.cache.interceptor.KeyGenerator;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.cache.RedisCacheConfiguration;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.RedisSerializationContext;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
@Configuration
@EnableCaching
public class RedisCacheConfig extends CachingConfigurerSupport {
private static final Logger logger = LoggerFactory.getLogger(RedisCacheConfig.class);
// 自定义key生成器
@Bean
public KeyGenerator keyGenerator(){
return (o, method, params) ->{
StringBuilder sb = new StringBuilder();
sb.append(o.getClass().getName()); // 类目
sb.append(method.getName()); // 方法名
for(Object param: params){
sb.append(param.toString()); // 参数名
}
return sb.toString();
};
}
// 配置缓存管理器
@Bean
public RedisCacheManager cacheManager(RedisConnectionFactory connectionFactory) {
RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig()
.entryTtl(Duration.ofSeconds(300)) // 60s缓存失效
// 设置key的序列化方式
.serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(keySerializer()))
// 设置value的序列化方式
.serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(valueSerializer()));
// 不缓存null值
// .disableCachingNullValues();
RedisCacheManager redisCacheManager = RedisCacheManager.builder(connectionFactory)
.cacheDefaults(config)
.transactionAware()
.build();
logger.info("自定义RedisCacheManager加载完成");
return redisCacheManager;
}
// key键序列化方式
private RedisSerializer<String> keySerializer() {
return new StringRedisSerializer();
}
// value值序列化方式
private GenericJackson2JsonRedisSerializer valueSerializer(){
return new GenericJackson2JsonRedisSerializer();
}
}
4.测试service代码
package com.example.demo;
import java.util.List;
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 com.example.demo.dao.FilmBaseMapper;
@Service
public class TestService {
@Autowired
private FilmBaseMapper filmBaseMapper;
//指定id作为redis的key,"film::9"为key
@Cacheable(cacheNames="film",key="#id")
public FilmBase getFilmById(int id) {
FilmBase film = filmBaseMapper.selectByPrimaryKey(id);
return film;
}
//方法全名为key,"films::com.example.demo.TestServicegetAll"为key
@Cacheable(cacheNames="films")
public List<FilmBase> getAll() {
List<FilmBase> selectAll = filmBaseMapper.selectAll();
return selectAll;
}
//方法必定执行一次,同时修改缓存 "film::9"为key
@CachePut(cacheNames = "film", key = "#filmBase.id")
public FilmBase updateFilm(FilmBase filmBase){
Integer i;
try {
i = filmBaseMapper.updateByPrimaryKey(filmBase);
return filmBase;
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return filmBase;
}
//删除cacheNames 为film和films开头的缓存,allEntries =false只删除指定 "film::9"或"films::9"为key的缓存,allEntries =true删除两种cacheNames 缓存
@CacheEvict(cacheNames = {"film","films"}, key ="#filmId",allEntries = false, beforeInvocation = true
)
public Integer delFilm(Integer filmId) {
return filmBaseMapper.deleteByPrimaryKey(filmId);
}
}
5.测试FilmBaseMapper.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="com.example.demo.dao.FilmBaseMapper">
<resultMap id="BaseResultMap" type="com.example.demo.FilmBase">
<id column="id" jdbcType="INTEGER" property="id" />
<result column="film_name" jdbcType="VARCHAR" property="filmName" />
<result column="user_id" jdbcType="INTEGER" property="userId" />
<result column="year" jdbcType="INTEGER" property="year" />
<result column="release_date" jdbcType="TIMESTAMP" property="releaseDate" />
<result column="note" jdbcType="VARCHAR" property="note" />
<result column="create_time" jdbcType="TIMESTAMP" property="createTime" />
</resultMap>
<delete id="deleteByPrimaryKey" parameterType="java.lang.Integer">
delete from film_base
where id = #{id,jdbcType=INTEGER}
</delete>
<insert id="insert" parameterType="com.example.demo.FilmBase">
<selectKey keyProperty="id" order="AFTER" resultType="java.lang.Integer">
SELECT LAST_INSERT_ID()
</selectKey>
insert into film_base (id, film_name, user_id,
year, release_date, note
)
values (#{id,jdbcType=INTEGER}, #{filmName,jdbcType=VARCHAR},
#{userId,jdbcType=INTEGER},
#{year,jdbcType=INTEGER}, #{releaseDate,jdbcType=TIMESTAMP}, #{note,jdbcType=VARCHAR}
)
</insert>
<update id="updateByPrimaryKey" parameterType="com.example.demo.FilmBase">
update film_base
set film_name = #{filmName,jdbcType=VARCHAR},
user_id = #{userId,jdbcType=INTEGER},
year = #{year,jdbcType=INTEGER},
release_date = #{releaseDate,jdbcType=TIMESTAMP},
note = #{note,jdbcType=VARCHAR}
where id = #{id,jdbcType=INTEGER}
</update>
<select id="selectByPrimaryKey" parameterType="java.lang.Integer"
resultMap="BaseResultMap">
select id, film_name, user_id, year, release_date, note
from film_base
where id = #{id,jdbcType=INTEGER}
</select>
<select id="selectByUserIdAndFilmName" resultMap="BaseResultMap">
select id, film_name, user_id, year, release_date, note
from film_base
where user_id = #{userId,jdbcType=INTEGER} and film_name =
#{filmName,jdbcType=VARCHAR}
</select>
<select id="selectByUserId" resultMap="BaseResultMap">
select id, film_name, user_id, year, release_date, note,create_time
from film_base
where user_id = #{userId,jdbcType=INTEGER}
</select>
<select id="selectAll" resultMap="BaseResultMap">
select id, film_name, user_id, year, release_date, note
from film_base
</select>
</mapper>
6.dao文件FilmBaseMapper
public interface FilmBaseMapper {
int deleteByPrimaryKey(Integer id);
int insert(FilmBase record);
FilmBase selectByPrimaryKey(Integer id);
List<FilmBase> selectAll();
Integer updateFilm(FilmBase filmBase);
Integer updateByPrimaryKey(FilmBase filmBase);
}
7.entity文件FilmBase
public class FilmBase implements Serializable {
private Integer id;
private String filmName;
private Integer userId;
private Integer year;
private Date releaseDate;
private String note;
private Date createTime;
private static final long serialVersionUID = 1L;
//省略getset
}
8.测试类
@RunWith(SpringRunner.class)
@SpringBootTest
public class DemoApplicationTests {
@Autowired
private TestService testService;
@Test
public void getAll() {
List<FilmBase> all = testService.getAll();
System.out.println(all.size());
for (FilmBase filmBase : all) {
System.out.println(filmBase.getFilmName());
}
}
@Test
public void getFilmById() {
try {
FilmBase all = testService.getFilmById(9);
System.out.println(all.getFilmName());
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
@Test
public void updateFilm() {
FilmBase fb =new FilmBase();
fb.setId(8);
fb.setFilmName("中国记账");
fb = testService.updateFilm(fb);
System.out.println(fb.getFilmName());
}
@Test
public void delFilm() {
int i = testService.delFilm(14);
System.out.println(i);
}
}
9.sql文件
SET FOREIGN_KEY_CHECKS=0;
-- ----------------------------
-- Table structure for `film_base`
-- ----------------------------
DROP TABLE IF EXISTS `film_base`;
CREATE TABLE `film_base` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`film_name` varchar(255) DEFAULT NULL COMMENT '电影名称',
`user_id` int(11) DEFAULT NULL COMMENT '用户id',
`year` int(11) DEFAULT NULL COMMENT '年份',
`release_date` datetime DEFAULT NULL COMMENT '发行日期',
`create_time` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '创建时间',
`note` varchar(255) DEFAULT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `filmName_user_unique` (`film_name`,`user_id`)
) ENGINE=InnoDB AUTO_INCREMENT=43 DEFAULT CHARSET=utf8;
-- ----------------------------
-- Records of film_base
-- ----------------------------
INSERT INTO `film_base` VALUES ('9', '建党伟业', '17', '2017', '2018-10-24 00:00:00', '2019-10-31 16:31:51', null);
INSERT INTO `film_base` VALUES ('20', '战狼', '4', '2017', '2017-12-12 00:00:00', '2019-10-31 19:18:47', null);
INSERT INTO `film_base` VALUES ('21', '哪吒', '4', '2018', '2019-10-01 00:00:00', '2019-10-31 19:57:58', null);
INSERT INTO `film_base` VALUES ('22', '齐天大圣', '2', '2017', '2019-10-07 00:00:00', '2019-10-31 20:13:25', null);
INSERT INTO `film_base` VALUES ('23', '神龙教', '17', '2017', '2018-09-04 00:00:00', '2019-10-31 20:53:23', null);
INSERT INTO `film_base` VALUES ('24', '太极张三丰', '17', '2018', '2019-02-01 00:00:00', '2019-10-31 21:08:57', null);
INSERT INTO `film_base` VALUES ('25', '战狼2', '4', '2017', '2017-12-12 00:00:00', '2019-10-31 21:11:33', null);
INSERT INTO `film_base` VALUES ('26', '战狼3', '4', '2017', '2017-12-12 00:00:00', '2019-10-31 21:11:41', null);
INSERT INTO `film_base` VALUES ('27', '上甘岭', '1', '1955', '1955-10-12 00:00:00', '2019-10-31 21:20:18', null);
INSERT INTO `film_base` VALUES ('28', '上甘岭2', '1', '1956', '1957-05-12 00:00:00', '2019-10-31 21:31:43', null);
INSERT INTO `film_base` VALUES ('29', '上甘岭4', '1', '1960', '1960-08-18 00:00:00', '2019-10-31 21:39:17', null);
INSERT INTO `film_base` VALUES ('30', '飒飒飒飒多所', '1', '2019', '2019-10-31 00:00:00', '2019-10-31 21:40:17', null);
INSERT INTO `film_base` VALUES ('31', '死亡骑士无', '1', '2018', '2018-10-31 00:00:00', '2019-10-31 21:41:45', null);
INSERT INTO `film_base` VALUES ('32', '读完读完群', '1', '2019', '2019-10-31 00:00:00', '2019-10-31 21:42:37', null);
INSERT INTO `film_base` VALUES ('33', '大萨达', '1', '2019', '2019-10-31 00:00:00', '2019-10-31 21:43:57', null);
INSERT INTO `film_base` VALUES ('34', '额滴神哒', '1', '2017', '2017-10-31 00:00:00', '2019-10-31 21:45:05', null);
INSERT INTO `film_base` VALUES ('35', '落花流水', '17', '2018', '2019-10-01 00:00:00', '2019-10-31 21:48:39', null);
INSERT INTO `film_base` VALUES ('36', '灵魂摆渡·黄泉', '4', null, null, '2019-11-01 09:30:29', null);
INSERT INTO `film_base` VALUES ('37', '死亡骑士', '1', '2016', '2016-11-15 00:00:00', '2019-11-01 10:12:34', null);
INSERT INTO `film_base` VALUES ('38', '死亡骑士1', '1', '2017', '2017-06-14 00:00:00', '2019-11-01 10:14:24', null);
INSERT INTO `film_base` VALUES ('39', 'test2', '2', '2019', '2019-11-19 00:00:00', '2019-11-01 10:31:16', null);
INSERT INTO `film_base` VALUES ('40', '九门提督', '4', '2019', '2019-11-13 00:00:00', '2019-11-01 10:33:34', null);
INSERT INTO `film_base` VALUES ('41', '唐山大地震', '17', '2017', '2017-07-03 00:00:00', '2019-11-01 10:44:59', null);
INSERT INTO `film_base` VALUES ('42', '超时空救援', '4', '2019', '2019-11-19 00:00:00', '2019-11-01 11:14:52', null);
10.测试方法,打印sql为走数据库,不打印为走缓存
a.执行getFilmById()方法,第一次走数据库
b.再次执行getFilmById()方法,第二次走缓存
c.执行getAll()方法,第一次走数据库
d.再次执行getAll()方法,第二次走缓存
e.redis数据库内容
f.执行delFilm()方法allEntries = false,指定id我传的9,将id为9的数据删除
g.执行delFilm()方法allEntries = true,指定id我传的20,将id为9的数据删除,同时删除film和films两个cacheNames缓存区域
h.补充。执行 getFilmById方法后,再执行updateFilm()方法,可以修改缓存和数据库
推荐阅读
-
浅谈SpringBoot集成Redis实现缓存处理(Spring AOP实现)
-
浅谈SpringCache与redis集成实现缓存解决方案
-
Java客户端利用Jedis操作redis缓存示例代码
-
SpringBoot缓存详解并整合Redis架构
-
详解springboot整合ehcache实现缓存机制
-
详解SpringBoot集成Redis来实现缓存技术方案
-
SpringBoot项目中使用redis缓存的方法步骤
-
redis与ssm整合方法(mybatis二级缓存)
-
SpringBoot+Mybatis项目使用Redis做Mybatis的二级缓存的方法
-
springboot+mybatis+redis 二级缓存问题实例详解