二级缓存
@CacheNamespace(implementation = MybatisEhcacheCache.class)
一、导入依赖
<!-- 缓存开始 -->
<!-- 开启二级缓存 -->
<dependency>
<groupId>org.mybatis.caches</groupId>
<artifactId>mybatis-ehcache</artifactId>
<version>1.1.0</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-pool2</artifactId>
</dependency>
<!-- 缓存完结 -->
残缺的 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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.3.4.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.xxtsoft</groupId>
<artifactId>call-center</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>call-center</name>
<description> 信讯通呼叫核心标准版 </description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<!-- thymeleaf 模版引擎 begin -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
<groupId>org.thymeleaf.extras</groupId>
<artifactId>thymeleaf-extras-springsecurity5</artifactId>
</dependency>
<!-- thymeleaf 模版引擎 end -->
<!-- spring-boot-starter begin -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<!-- spring-boot-starter end -->
<!-- web begin -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- end begin -->
<!-- devtools begin -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
</dependency>
<!-- devtools end -->
<!-- 数据库驱动 begin -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<!-- 数据库驱动 end -->
<!-- 用传统的 xml 或 properties 配置,就须要应用 spring-boot-configuration-processor begin -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
<!-- end -->
<!-- lombok begin -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<!-- lombok end -->
<!-- 测试 starter -->
<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>
<!-- 测试 starter 完结 -->
<!-- 平安 开始 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<!-- 平安 完结 -->
<!-- 数据校验 begin-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
<!-- 数据校验 end-->
<!-- mybatis 开始 -->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.4.0</version>
</dependency>
<!-- 代码生成器 -->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-generator</artifactId>
<version>3.4.0</version>
</dependency>
<!-- 引入 freemarker 包 作为代码生成器引擎 -->
<dependency>
<groupId>org.freemarker</groupId>
<artifactId>freemarker</artifactId>
<version>2.3.30</version>
</dependency>
<!-- mybatis 完结 -->
<!-- hutool 工具包 begin -->
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.4.4</version>
</dependency>
<!-- hutool 工具包 end -->
<!-- json 依赖 开始 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.73</version>
</dependency>
<!-- json 依赖 完结 -->
<!-- swagger 开始 -->
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>2.9.2</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>2.9.2</version>
</dependency>
<!-- swagger 完结 -->
<!-- apache 开始 -->
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>4.1.1</version>
<exclusions>
<exclusion>
<artifactId>poi-ooxml-schemas</artifactId>
<groupId>org.apache.poi</groupId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml-schemas</artifactId>
<version>3.17</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.apache.commons/commons-lang3 -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.11</version>
</dependency>
<!-- apache 完结 -->
<!-- junit 测试开始 -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>
<!-- junit 测试 完结 -->
<!-- web jar 开始 -->
<dependency>
<groupId>org.webjars</groupId>
<artifactId>webjars-locator</artifactId>
<version>0.34</version>
</dependency>
<dependency>
<groupId>org.webjars</groupId>
<artifactId>jquery</artifactId>
<version>2.1.4</version>
</dependency>
<dependency>
<groupId>org.webjars</groupId>
<artifactId>bootstrap</artifactId>
<version>3.3.6</version>
<exclusions>
<exclusion>
<artifactId>jquery</artifactId>
<groupId>org.webjars</groupId>
</exclusion>
</exclusions>
</dependency>
<!-- <dependency>-->
<!-- <groupId>org.webjars.bowergithub.dreamerlxb</groupId>-->
<!-- <artifactId>jquery-easyui</artifactId>-->
<!-- <version>1.9.0</version>-->
<!-- </dependency>-->
<dependency>
<groupId>org.webjars</groupId>
<artifactId>font-awesome</artifactId>
<version>4.4.0</version>
</dependency>
<dependency>
<groupId>org.webjars.npm</groupId>
<artifactId>animate.css</artifactId>
<version>4.1.1</version>
</dependency>
<dependency>
<groupId>org.webjars.bower</groupId>
<artifactId>bootstrap-table</artifactId>
<version>1.14.1</version>
</dependency>
<dependency>
<groupId>org.webjars</groupId>
<artifactId>zTree</artifactId>
<version>3.5.18</version>
<exclusions>
<exclusion>
<artifactId>jquery</artifactId>
<groupId>org.webjars</groupId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.webjars.npm</groupId>
<artifactId>bootstrap-select</artifactId>
<version>1.13.14</version>
</dependency>
<dependency>
<groupId>org.webjars.bower</groupId>
<artifactId>metisMenu</artifactId>
<version>1.1.3</version>
<exclusions>
<exclusion>
<groupId>org.webjars.bower</groupId>
<artifactId>bootstrap</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.webjars</groupId>
<artifactId>jQuery-slimScroll</artifactId>
<version>1.3.1</version>
<exclusions>
<exclusion>
<artifactId>jquery</artifactId>
<groupId>org.webjars</groupId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.webjars</groupId>
<artifactId>pace</artifactId>
<version>1.0.2</version>
</dependency>
<dependency>
<groupId>org.webjars</groupId>
<artifactId>jquery-cookie</artifactId>
<version>1.4.1</version>
<exclusions>
<exclusion>
<artifactId>jquery</artifactId>
<groupId>org.webjars</groupId>
</exclusion>
</exclusions>
</dependency>
<!-- 缓存开始 -->
<!-- 开启二级缓存 -->
<dependency>
<groupId>org.mybatis.caches</groupId>
<artifactId>mybatis-ehcache</artifactId>
<version>1.1.0</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-pool2</artifactId>
</dependency>
<!-- 缓存完结 -->
<dependency>
<groupId>org.webjars.bower</groupId>
<artifactId>jquery.serializeJSON</artifactId>
<version>2.6.1</version>
</dependency>
<dependency>
<groupId>org.webjars</groupId>
<artifactId>echarts</artifactId>
<version>2.1.10</version>
</dependency>
<dependency>
<groupId>org.webjars</groupId>
<artifactId>layui</artifactId>
<version>2.5.6</version>
</dependency>
<dependency>
<groupId>org.webjars.bowergithub.sentsin</groupId>
<artifactId>layer</artifactId>
<version>3.1.1</version>
</dependency>
<dependency>
<groupId>org.webjars</groupId>
<artifactId>vue</artifactId>
<version>2.6.11</version>
</dependency>
<dependency>
<groupId>org.webjars.npm</groupId>
<artifactId>axios</artifactId>
<version>0.20.0</version>
</dependency>
<dependency>
<groupId>org.webjars.npm</groupId>
<artifactId>element-ui</artifactId>
<version>2.14.0</version>
</dependency>
<!-- web jar 完结 -->
</dependencies>
<build>
<plugins>
<plugin>
<!-- 热部署配置 -->
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.12.4</version>
<configuration>
<argLine>-Xmx1024m</argLine>
</configuration>
</plugin>
</plugins>
</build>
</project>
二、设置配置文件 application.yml
# 连贯数据库
spring:
datasource:
driverClassName: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://192.168.6.250:3306/call_center?sserverTimezone=GMT%2B8&useUnicode=true&characterEncoding=utf-8
# url: jdbc:mysql://10.8.0.142:3306/call_center?serverTimezone=UTC&useUnicode=true&characterEncoding=utf-8
username: root
password: XXT123456.
devtools:
restart:
# spring boot devtools 热部署后拜访报 404 问题
# https://www.jianshu.com/p/9337fd517291
poll-interval: 3000ms
quiet-period: 2999ms
# 配置 redis 缓存
redis:
# host: 10.8.0.142
host: 192.168.6.250
port: 6379
password: XXT123456.
database: 1
timeout: 2000ms
# 连贯超时工夫(毫秒)默认是 2000ms
lettuce:
pool:
max-active: 200
# 连接池最大连接数(应用负值示意没有限度)max-wait: -1ms
# 连接池最大阻塞等待时间(应用负值示意没有限度)max-idle: 100
# 连接池中的最大闲暇连贯
min-idle: 50
# 连接池中的最小闲暇连贯
shutdown-timeout: 100ms
# MyBatis plus 显示 SQL 语句
mybatis-plus:
configuration:
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
# 应用缓存
cache-enabled: true
# ===================================================================
# 日志配置 从低到高
# log.trace("trace");
# log.debug("debug");
# log.info("info");
# log.warn("warn");
# log.error("error");
# ===================================================================
logging:
# 对 com.xxtsoft 下的文件开启 trace 级别的日志
level:
com:
xxtsoft: trace
server:
port: 8081
servlet:
context-path: /call
三、创立 RedisUtil
封装 RedisTemplateRedisTemplate
package com.xxtsoft.util.redis;
import cn.hutool.core.collection.ListUtil;
import cn.hutool.core.lang.Validator;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;
/**
* redis 工具类
*
* @author yang
*/
@Component
public class RedisUtil {
@Autowired
private RedisTemplate<String, Object> redisTemplate;
@Autowired
private StringRedisTemplate stringRedisTemplate;
/**
* 指定缓存生效工夫
*
* @param key 键
* @param time 工夫(秒)
* @return boolean
*/
public boolean expire(String key, long time) {
try {if (time > 0) {redisTemplate.expire(key, time, TimeUnit.SECONDS);
}
return true;
} catch (Exception e) {e.printStackTrace();
return false;
}
}
/**
* 依据 key 获取过期工夫
*
* @param key 键 不能为 null
* @return 工夫(秒) 返回 0 代表为永恒无效
*/
public Long getExpire(String key) {final Long expire = redisTemplate.getExpire(key, TimeUnit.SECONDS);
assert expire != null;
return expire;
}
/**
* 判断 key 是否存在
*
* @param key 键
* @return true 存在 false 不存在
*/
public Boolean hasKey(String key) {
try {final Boolean aBoolean = redisTemplate.hasKey(key);
assert aBoolean != null;
return aBoolean;
} catch (Exception e) {e.printStackTrace();
return false;
}
}
/**
* 删除缓存
*
* @param key 能够传一个值 或多个
*/
public void del(String... key) {if (Validator.isNotNull(key) && Validator.isTrue(key.length > 0)) {if (key.length == 1) {redisTemplate.delete(key[0]);
} else {redisTemplate.delete(ListUtil.toList(key));
}
}
}
// ============================String=============================
/**
* 一般缓存获取
*
* @param key 键
* @return 值
*/
public Object get(String key) {return key == null ? null : redisTemplate.opsForValue().get(key);
}
/**
* 一般缓存放入
*
* @param key 键
* @param value 值
* @return true 胜利 false 失败
*/
public Boolean set(String key, Object value) {
try {redisTemplate.opsForValue().set(key, value);
return true;
} catch (Exception e) {e.printStackTrace();
return false;
}
}
/**
* 一般缓存放入并设置工夫
*
* @param key 键
* @param value 值
* @param time 工夫(秒) time 要大于 0 如果 time 小于等于 0 将设置无限期
* @return true 胜利 false 失败
*/
public boolean set(String key, Object value, long time) {
try {if (time > 0) {redisTemplate.opsForValue().set(key, value, time, TimeUnit.SECONDS);
} else {set(key, value);
}
return true;
} catch (Exception e) {e.printStackTrace();
return false;
}
}
/**
* 递增
*
* @param key 键
* @param delta 要减少几(大于 0)
* @return long
*/
public Long incr(String key, long delta) {if (delta < 0) {throw new RuntimeException("递增因子必须大于 0");
}
return redisTemplate.opsForValue().increment(key, delta);
}
/**
* 递加
*
* @param key 键
* @param delta 要缩小几(大于 0)
* @return long
*/
public Long decr(String key, long delta) {if (delta < 0) {throw new RuntimeException("递加因子必须大于 0");
}
return redisTemplate.opsForValue().increment(key, -delta);
}
// ================================Map=================================
/**
* HashGet
*
* @param key 键 不能为 null
* @param item 项 不能为 null
* @return 值
*/
public Object hget(String key, String item) {return redisTemplate.opsForHash().get(key, item);
}
/**
* 获取 hashKey 对应的所有键值
*
* @param key 键
* @return 对应的多个键值
*/
public Map<Object, Object> hmget(String key) {return redisTemplate.opsForHash().entries(key);
}
/**
* HashSet
*
* @param key 键
* @param map 对应多个键值
* @return true 胜利 false 失败
*/
public boolean hmset(String key, Map<String, Object> map) {
try {redisTemplate.opsForHash().putAll(key, map);
return true;
} catch (Exception e) {e.printStackTrace();
return false;
}
}
/**
* HashSet 并设置工夫
*
* @param key 键
* @param map 对应多个键值
* @param time 工夫(秒)
* @return true 胜利 false 失败
*/
public boolean hmset(String key, Map<String, Object> map, long time) {
try {redisTemplate.opsForHash().putAll(key, map);
if (time > 0) {expire(key, time);
}
return true;
} catch (Exception e) {e.printStackTrace();
return false;
}
}
/**
* 向一张 hash 表中放入数据, 如果不存在将创立
*
* @param key 键
* @param item 项
* @param value 值
* @return true 胜利 false 失败
*/
public boolean hset(String key, String item, Object value) {
try {redisTemplate.opsForHash().put(key, item, value);
return true;
} catch (Exception e) {e.printStackTrace();
return false;
}
}
/**
* 向一张 hash 表中放入数据, 如果不存在将创立
*
* @param key 键
* @param item 项
* @param value 值
* @param time 工夫(秒) 留神: 如果已存在的 hash 表有工夫, 这里将会替换原有的工夫
* @return true 胜利 false 失败
*/
public boolean hset(String key, String item, Object value, long time) {
try {redisTemplate.opsForHash().put(key, item, value);
if (time > 0) {expire(key, time);
}
return true;
} catch (Exception e) {e.printStackTrace();
return false;
}
}
/**
* 删除 hash 表中的值
*
* @param key 键 不能为 null
* @param item 项 能够使多个 不能为 null
*/
public Object hdel(String key, Object... item) {return redisTemplate.opsForHash().delete(key, item);
}
/**
* 判断 hash 表中是否有该项的值
*
* @param key 键 不能为 null
* @param item 项 不能为 null
* @return true 存在 false 不存在
*/
public boolean hHasKey(String key, String item) {return redisTemplate.opsForHash().hasKey(key, item);
}
/**
* hash 递增 如果不存在, 就会创立一个 并把新增后的值返回
*
* @param key 键
* @param item 项
* @param by 要减少几(大于 0)
* @return 新增后的值
*/
public Double hincr(String key, String item, double by) {return redisTemplate.opsForHash().increment(key, item, by);
}
/**
* hash 递加
*
* @param key 键
* @param item 项
* @param by 要缩小记(小于 0)
* @return 新减后的值
*/
public double hdecr(String key, String item, double by) {return redisTemplate.opsForHash().increment(key, item, -by);
}
/**
* hash 键数量
*
* @param key key
* @return int
*/
public int hsize(String key) {return redisTemplate.opsForHash().size(key).intValue();}
// ============================set=============================
/**
* 依据 key 获取 Set 中的所有值
*
* @param key 键
* @return 所有值
*/
public Set<Object> sGet(String key) {
try {return redisTemplate.opsForSet().members(key);
} catch (Exception e) {e.printStackTrace();
return null;
}
}
/**
* 依据 value 从一个 set 中查问, 是否存在
*
* @param key 键
* @param value 值
* @return true 存在 false 不存在
*/
public boolean sHasKey(String key, Object value) {
try {final Boolean member = redisTemplate.opsForSet().isMember(key, value);
assert member != null;
return member;
} catch (Exception e) {e.printStackTrace();
return false;
}
}
/**
* 将数据放入 set 缓存
*
* @param key 键
* @param values 值 能够是多个
* @return 胜利个数
*/
public long sSet(String key, Object... values) {
try {final Long add = redisTemplate.opsForSet().add(key, values);
assert add != null;
return add;
} catch (Exception e) {e.printStackTrace();
return 0;
}
}
/**
* 将 set 数据放入缓存
*
* @param key 键
* @param time 工夫(秒)
* @param values 值 能够是多个
* @return 胜利个数
*/
public Long sSetAndTime(String key, long time, Object... values) {
try {Long count = redisTemplate.opsForSet().add(key, values);
if (time > 0) {expire(key, time);
}
return count;
} catch (Exception e) {e.printStackTrace();
return 0L;
}
}
/**
* 获取 set 缓存的长度
*
* @param key 键
* @return set 缓存的长度
*/
public long sGetSetSize(String key) {
try {final Long size = redisTemplate.opsForSet().size(key);
assert size != null;
return size;
} catch (Exception e) {e.printStackTrace();
return 0;
}
}
/**
* 移除值为 value 的
*
* @param key 键
* @param values 值 能够是多个
* @return 移除的个数
*/
public long setRemove(String key, Object... values) {
try {Long count = redisTemplate.opsForSet().remove(key, values);
assert count != null;
return count;
} catch (Exception e) {e.printStackTrace();
return 0;
}
}
// ===============================list=================================
/**
* 获取 list 缓存的内容
*
* @param key 键
* @param start 开始
* @param end 完结 0 到 - 1 代表所有值
* @return 缓存的内容
*/
public List<Object> lGet(String key, long start, long end) {
try {return redisTemplate.opsForList().range(key, start, end);
} catch (Exception e) {e.printStackTrace();
return null;
}
}
/**
* 获取 list 缓存的长度
*
* @param key 键
* @return 缓存的长度
*/
public long lGetListSize(String key) {
try {final Long size = redisTemplate.opsForList().size(key);
assert size != null;
return size;
} catch (Exception e) {e.printStackTrace();
return 0;
}
}
/**
* 通过索引 获取 list 中的值
*
* @param key 键
* @param index 索引 index>= 0 时,0 表头,1 第二个元素,顺次类推;index<0 时,-1,表尾,- 2 倒数第二个元素,顺次类推
* @return list 中的值
*/
public Object lGetIndex(String key, long index) {
try {return redisTemplate.opsForList().index(key, index);
} catch (Exception e) {e.printStackTrace();
return null;
}
}
/**
* 将 list 放入缓存
*
* @param key 键
* @param value 值
* @return 是否胜利
*/
public boolean lSet(String key, Object value) {
try {redisTemplate.opsForList().rightPush(key, value);
return true;
} catch (Exception e) {e.printStackTrace();
return false;
}
}
/**
* 将 list 放入缓存
*
* @param key 键
* @param value 值
* @param time 工夫(秒)
* @return boolean
*/
public boolean lSet(String key, Object value, long time) {
try {redisTemplate.opsForList().rightPush(key, value);
if (time > 0) {expire(key, time);
}
return true;
} catch (Exception e) {e.printStackTrace();
return false;
}
}
/**
* 将 list 放入缓存
*
* @param key 键
* @param value 值
* @return boolean
*/
public boolean lSet(String key, List<Object> value) {
try {redisTemplate.opsForList().rightPushAll(key, value);
return true;
} catch (Exception e) {e.printStackTrace();
return false;
}
}
/**
* 将 list 放入缓存
*
* @param key 键
* @param value 值
* @param time 工夫(秒)
* @return boolean
*/
public boolean lSet(String key, List<Object> value, long time) {
try {redisTemplate.opsForList().rightPushAll(key, value);
if (time > 0) {expire(key, time);
}
return true;
} catch (Exception e) {e.printStackTrace();
return false;
}
}
/**
* 依据索引批改 list 中的某条数据
*
* @param key 键
* @param index 索引
* @param value 值
* @return boolean
*/
public boolean lUpdateIndex(String key, long index, Object value) {
try {redisTemplate.opsForList().set(key, index, value);
return true;
} catch (Exception e) {e.printStackTrace();
return false;
}
}
/**
* 移除 N 个值为 value
*
* @param key 键
* @param count 移除多少个
* @param value 值
* @return 移除的个数
*/
public long lRemove(String key, long count, Object value) {
try {Long remove = redisTemplate.opsForList().remove(key, count, value);
assert remove != null;
return remove;
} catch (Exception e) {e.printStackTrace();
return 0;
}
}
// ===============================sorted set 有序汇合 =================================
/**
* 增加一个元素
*
* @param key 键
* @param value 值
* @param score 分值
*/
public void zAdd(String key, Object value, double score) {redisTemplate.opsForZSet().add(key, value, score);
}
/**
* 返回有序集中,成员的分数值
*
* @param key 键
* @param value 值
* @return 成员的分数值
*/
public double zScore(String key, Object value) {Double d = redisTemplate.opsForZSet().score(key, value);
d = d == null ? 0L : d;
return d;
}
/**
* 判断 value 在 zset 中的排名
*
* @param key 键
* @param value 值
* @return 排名
*/
public Long zRank(String key, Object value) {Long index = redisTemplate.opsForZSet().rank(key, value);
index = index == null ? 0L : index;
return index;
}
/**
* 查问 汇合中 指定程序 的 值 和 score
* <p>
*(start=0 & end = -1)示意获取全副的汇合内容
*
* @param key 键
* @param start 开始
* @param end 完结
* @return 全副的汇合内容
*/
public Set<Object> zRangeWithScore(String key, long start, long end) {return redisTemplate.opsForZSet().rangeByScore(key, start, end);
}
}
四、SpringContextUtils
:保护 Spring 中的实例
能够应用 hutool 的 Spring 工具 – SpringUtil 来替换
package com.xxtsoft.util.spring;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.servlet.http.HttpServletRequest;
import java.util.Objects;
/**
* Spring 工具类
*
* @author yang
*/
@Component
public class SpringContextUtils implements ApplicationContextAware {
/**
* 上下文对象实例
*/
private static ApplicationContext applicationContext;
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {SpringContextUtils.applicationContext = applicationContext;}
/**
* 获取 applicationContext
*
* @return 获取 applicationContext
*/
public static ApplicationContext getApplicationContext() {return applicationContext;}
/**
* 获取 HttpServletRequest
*/
public static HttpServletRequest getHttpServletRequest() {return ((ServletRequestAttributes) Objects.requireNonNull(RequestContextHolder.getRequestAttributes())).getRequest();}
public static String getDomain() {HttpServletRequest request = getHttpServletRequest();
StringBuffer url = request.getRequestURL();
return url.delete(url.length() - request.getRequestURI().length(), url.length()).toString();}
public static String getOrigin() {HttpServletRequest request = getHttpServletRequest();
return request.getHeader("Origin");
}
/**
* 通过 name 获取 Bean.
*
* @param name name
* @return Bean
*/
public static Object getBean(String name) {return getApplicationContext().getBean(name);
}
/**
* 通过 class 获取 Bean.
*
* @param clazz 类
* @param <T> 类型
* @return bean
*/
public static <T> T getBean(Class<T> clazz) {return getApplicationContext().getBean(clazz);
}
/**
* 通过 name, 以及 Clazz 返回指定的 Bean
*
* @param name 名字
* @param clazz 类
* @param <T> 类型
* @return bean
*/
public static <T> T getBean(String name, Class<T> clazz) {return getApplicationContext().getBean(name, clazz);
}
}
五、RedisConfig
:配置Redis
的 RedisTemplate
和 CacheManager
并载入 Spring IOC
容器
package com.xxtsoft.config;
import com.fasterxml.jackson.annotation.JsonAutoDetect.Visibility;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.ObjectMapper.DefaultTyping;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.CachingConfigurerSupport;
import org.springframework.cache.annotation.EnableCaching;
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.cache.RedisCacheWriter;
import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.*;
import javax.annotation.Resource;
import java.time.Duration;
import static java.util.Collections.singletonMap;
/**
* redis 配置类
*
* @author yang
*/
@Configuration
@EnableCaching
public class RedisConfig extends CachingConfigurerSupport {
@Resource
private LettuceConnectionFactory lettuceConnectionFactory;
/**
* RedisTemplate 配置
*
* @param lettuceConnectionFactory lettuceConnectionFactory
* @return RedisTemplate
*/
@Bean
public RedisTemplate<String, Object> redisTemplate(LettuceConnectionFactory lettuceConnectionFactory) {
// 设置序列化
Jackson2JsonRedisSerializer<Object> jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer<Object>(Object.class);
ObjectMapper om = new ObjectMapper();
om.setVisibility(PropertyAccessor.ALL, Visibility.ANY);
om.enableDefaultTyping(DefaultTyping.NON_FINAL);
// 解决 jackson2 无奈反序列化 LocalDateTime 的问题
om.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
om.registerModule(new JavaTimeModule());
jackson2JsonRedisSerializer.setObjectMapper(om);
// 配置 redisTemplate
RedisTemplate<String, Object> redisTemplate = new RedisTemplate<String, Object>();
redisTemplate.setConnectionFactory(lettuceConnectionFactory);
RedisSerializer<?> stringSerializer = new StringRedisSerializer();
// key 序列化
redisTemplate.setKeySerializer(stringSerializer);
// value 序列化
redisTemplate.setValueSerializer(jackson2JsonRedisSerializer);
// Hash key 序列化
redisTemplate.setHashKeySerializer(stringSerializer);
// Hash value 序列化
redisTemplate.setHashValueSerializer(jackson2JsonRedisSerializer);
redisTemplate.afterPropertiesSet();
return redisTemplate;
}
/**
* 缓存配置管理器
*
* @param factory factory
* @return CacheManager
*/
@Bean
public CacheManager cacheManager(LettuceConnectionFactory factory) {
// 配置序列化(缓存默认有效期 6 小时)RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig().entryTtl(Duration.ofHours(6));
RedisCacheConfiguration redisCacheConfiguration = config.serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(new StringRedisSerializer()))
.serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(new GenericJackson2JsonRedisSerializer()));
/* 自定义配置 test:demo 的超时工夫为 5 分钟 */
return RedisCacheManager
.builder(RedisCacheWriter.lockingRedisCacheWriter(factory))
.cacheDefaults(redisCacheConfiguration)
.withInitialCacheConfigurations(singletonMap("test:demo", RedisCacheConfiguration.defaultCacheConfig().entryTtl(Duration.ofMinutes(5)).disableCachingNullValues()))
.transactionAware()
.build();}
}
六、创立 MybatisRedisCache
实现 org.apache.ibatis.cache.Cache
package com.xxtsoft.config;
import cn.hutool.extra.spring.SpringUtil;
import com.xxtsoft.util.redis.RedisUtil;
import lombok.Setter;
import org.apache.ibatis.cache.Cache;
import org.springframework.stereotype.Component;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
/**
* 缓存实现类
*
* @author 杨磊
*/
@Component
public class MybatisRedisCache implements Cache {
private RedisUtil redisUtil;
private RedisUtil getRedis() {return SpringUtil.getBean(RedisUtil.class);
}
private final ReadWriteLock readWriteLock = new ReentrantReadWriteLock();
/**
* 缓存刷新工夫(秒)*/
@Setter
private long flushInterval = 0L;
private String id;
public MybatisRedisCache() {}
public MybatisRedisCache(final String id) {if (id == null) {throw new IllegalArgumentException("Cache instances require an ID");
}
this.id = id;
}
@Override
public String getId() {return this.id;}
@Override
public void putObject(Object o, Object o1) {getRedis().hset(getId(), o.toString(), o1);
if (flushInterval > 0L) {getRedis().expire(getId(), flushInterval);
}
}
@Override
public Object getObject(Object o) {return getRedis().hget(getId(), o.toString());
}
@Override
public Object removeObject(Object o) {return getRedis().hdel(getId(), o);
}
@Override
public void clear() {getRedis().del(getId());
}
@Override
public int getSize() {return getRedis().hsize(getId());
}
@Override
public ReadWriteLock getReadWriteLock() {return readWriteLock;}
}
七、增加 缓存注解
Mybatis 反对两种形式增加缓存注解,以下计划 二选一 即可:
- 增加缓存注解
@CacheNamespace
在代码中为每个 mapper 增加缓存注解,申明 implementation 或 eviction 的值为 MybatisRedisCache
@CacheNamespace(implementation = MybatisRedisCache.class,eviction=MybatisRedisCache.class)
public interface UserMapper extends BaseMapper<User> {}
- 在对应的 mapper.xml 中将原有正文批改为链接式申明,以保障 xml 文件里的缓存可能失常
<cache-ref namespace="com.w.mapper.UserMapper"></cache-ref>
本篇文章由一文多发平台 ArtiPub 主动公布