概述
由于工作中不同的数据信息缓存在不同的redis的16个库中,当某个地方需要用到的时候,切换redis库不方便,下面讲解的即可简便操作,可直接集成于common包中
SpringBoot集成Redis | 使用注解动态切换Redis库
本人已将项目打包到github,有需要的可以直接去拿
项目地址-github:https://github.com/Linsider/redis (用的顺手别忘了点赞哦)
大家看完可以导入项目跑一跑,有疑问可以在评论区留言,看到即回复
一、目录结构
二、创建redis切换库所需注解、类
2.1 application.yml配置
# Tomcat
server:
tomcat:
uri-encoding: UTF-8
max-threads: 1000
min-spare-threads: 30
port: 8088
servlet:
context-path: /redis-demo
# mysql
spring:
http:
multipart:
max-file-size: 100MB
max-request-size: 100MB
enabled: true
redis:
database: 0
host: localhost
port: 6379
password: # 密码(默认为空)
timeout: 6000ms # 连接超时时长(毫秒)
jedis:
pool:
max-active: 1000 # 连接池最大连接数(使用负值表示没有限制)
max-wait: -1ms # 连接池最大阻塞等待时间(使用负值表示没有限制)
max-idle: 10 # 连接池中的最大空闲连接
min-idle: 5 # 连接池中的最小空闲连接
cache:
type: none
huangtuL:
redis:
open: false # 是否开启redis缓存 true开启 false关闭
logging:
level: debug
level.com.example: debug
path: logs/
file: huangtuL.log
2.2 创建自定义注解 RedisSelect
import java.lang.annotation.*;
/**
* author huangtuL
*/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface RedisSelect {
/**
* redis库
* @return
*/
int value() default 0;
}
2.3 Redis配置类 RedisConfig (下面的注解即可直接回去yml中的redis配置)
import com.example.redis.SelectableRedisTemplate;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration;
import org.springframework.boot.autoconfigure.data.redis.RedisProperties;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.data.redis.connection.RedisPassword;
import org.springframework.data.redis.connection.RedisStandaloneConfiguration;
import org.springframework.data.redis.connection.jedis.JedisClientConfiguration;
import org.springframework.data.redis.connection.jedis.JedisConnectionFactory;
import redis.clients.jedis.JedisPoolConfig;
import java.time.Duration;
/**
* Redis配置相关
* author huangtuL
*/
@Configuration
@AutoConfigureAfter(RedisAutoConfiguration.class)// 自动获取application.yml中的配置
@EnableConfigurationProperties(RedisProperties.class)
public class RedisConfig {
private RedisProperties properties;
public RedisConfig(RedisProperties properties){
this.properties = properties;
}
@Bean
@Primary
public JedisConnectionFactory jedisConnectionFactory(){
RedisStandaloneConfiguration config = new RedisStandaloneConfiguration();
config.setHostName(properties.getHost());
config.setPort(properties.getPort());
config.setPassword(RedisPassword.of(properties.getPassword()));
config.setDatabase(properties.getDatabase());
return new JedisConnectionFactory(config, getJedisClientConfiguration());
}
private JedisClientConfiguration getJedisClientConfiguration() {
JedisClientConfiguration.JedisClientConfigurationBuilder builder = JedisClientConfiguration.builder();
if (properties.isSsl()) {
builder.useSsl();
}
if (properties.getTimeout() != null) {
Duration timeout = properties.getTimeout();
builder.readTimeout(timeout).connectTimeout(timeout);
}
RedisProperties.Pool pool = properties.getJedis().getPool();
if (pool != null) {
builder.usePooling().poolConfig(jedisPoolConfig(pool));
}
return builder.build();
}
private JedisPoolConfig jedisPoolConfig(RedisProperties.Pool pool) {
JedisPoolConfig config = new JedisPoolConfig();
config.setMaxTotal(pool.getMaxActive());
config.setMaxIdle(pool.getMaxIdle());
config.setMinIdle(pool.getMinIdle());
if (pool.getMaxWait() != null) {
config.setMaxWaitMillis(pool.getMaxWait().toMillis());
}
return config;
}
@Bean(name = "redisTemplate")
@Primary
public SelectableRedisTemplate redisTemplate() {
SelectableRedisTemplate redisTemplate = new SelectableRedisTemplate();
redisTemplate.setConnectionFactory(jedisConnectionFactory());
return redisTemplate;
}
}
2.4 redis工具类 RedisUtils(这没啥说的)
import com.alibaba.fastjson.JSON;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
import java.util.concurrent.TimeUnit;
/**
* Redis工具类
*
* author huangtuL
*/
@Component
public class RedisUtils {
@Autowired
private StringRedisTemplate redisTemplate;
private ValueOperations<String, String> valueOperations;
@PostConstruct
public void init(){
this.valueOperations = redisTemplate.opsForValue();
}
/** 默认过期时长,单位:秒 */
public final static long DEFAULT_EXPIRE = 60 * 60 * 24;
/** 不设置过期时长 */
public final static long NOT_EXPIRE = -1;
public void set(String key, Object value, long expire){
valueOperations.set(key, toJson(value));
if(expire != NOT_EXPIRE){
redisTemplate.expire(key, expire, TimeUnit.SECONDS);
}
}
public void set(String key, Object value){
set(key, value, DEFAULT_EXPIRE);
}
public <T> T get(String key, Class<T> clazz, long expire) {
String value = valueOperations.get(key);
if(expire != NOT_EXPIRE){
redisTemplate.expire(key, expire, TimeUnit.SECONDS);
}
return value == null ? null : fromJson(value, clazz);
}
public <T> T get(String key, Class<T> clazz) {
return get(key, clazz, NOT_EXPIRE);
}
public String get(String key, long expire) {
String value = valueOperations.get(key);
if(expire != NOT_EXPIRE){
redisTemplate.expire(key, expire, TimeUnit.SECONDS);
}
return value;
}
public String get(String key) {
return get(key, NOT_EXPIRE);
}
public void delete(String key) {
redisTemplate.delete(key);
}
/**
* Object转成JSON数据
*/
private String toJson(Object object){
if(object instanceof Integer || object instanceof Long || object instanceof Float ||
object instanceof Double || object instanceof Boolean || object instanceof String){
return String.valueOf(object);
}
return JSON.toJSONString(object);
}
/**
* JSON数据,转成Object
*/
private <T> T fromJson(String json, Class<T> clazz){
return JSON.parseObject(json, clazz);
}
}
2.5 redis切换库支持类 RedisSelectSupport、SelectableRedisTemplate (切换连接在这)
/**
* author huangtuL
*/
public class RedisSelectSupport {
private static final ThreadLocal<Integer> SELECT_CONTEXT = new ThreadLocal<>();
public static void select(int db){
SELECT_CONTEXT.set(db);
}
public static Integer getSelect(){
return SELECT_CONTEXT.get();
}
}
import org.springframework.data.redis.connection.RedisConnection;
import org.springframework.data.redis.core.StringRedisTemplate;
/**
* author huangtuL
*/
public class SelectableRedisTemplate extends StringRedisTemplate {
@Override
protected RedisConnection createRedisConnectionProxy(RedisConnection pm) {
return super.createRedisConnectionProxy(pm);
}
@Override
protected RedisConnection preProcessConnection(RedisConnection connection, boolean existingConnection) {
Integer db;
if((db = RedisSelectSupport.getSelect()) != null){
connection.select(db);
}
return super.preProcessConnection(connection, existingConnection);
}
}
2.6 切面类 RedisAspect (主要在这)
import com.example.annotation.RedisSelect;
import com.example.exception.RRException;
import com.example.redis.RedisSelectSupport;
import com.example.redis.SelectableRedisTemplate;
import com.example.util.RedisUtils;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.stereotype.Component;
import java.lang.reflect.Method;
/**
* Redis切面处理类
*
* author huangtuL
*/
@Aspect
@Component
public class RedisAspect {
private Logger logger = LoggerFactory.getLogger(getClass());
//是否开启redis缓存 true开启 false关闭
@Value("${huangtuL.redis.open: false}")
private boolean open;
@Autowired
private RedisUtils redisUtils;
@Value("${spring.redis.database:0}")
private int defaultDataBase;
@Around("execution(* com.example.util.RedisUtils.*(..))")
public Object around(ProceedingJoinPoint point) throws Throwable {
Object result = null;
if(open){
try{
result = point.proceed();
}catch (Exception e){
logger.error("redis error", e);
throw new RRException("Redis服务异常");
}
}
return result;
}
@Around("@annotation(com.example.annotation.RedisSelect)")
@ConditionalOnBean(SelectableRedisTemplate.class)
public Object configRedis(ProceedingJoinPoint point) throws Throwable{
int db = defaultDataBase;
try {
MethodSignature signature = (MethodSignature) point.getSignature();
Method method = signature.getMethod();
RedisSelect config = method.getAnnotation(RedisSelect.class);
if(config != null){
db = config.value();
}
RedisSelectSupport.select(db);
return point.proceed();
} finally {
RedisSelectSupport.select(defaultDataBase);
logger.debug("redis reset {} to {}", db, defaultDataBase);
}
}
}
三、测试
3.1 测试类 TestRedisSelect
import com.example.annotation.RedisSelect;
import com.example.redis.RedisSelectSupport;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* 测试redis切换库
* author huangtuL
*/
@RestController
@RequestMapping("redis")
public class TestRedisSelect {
@Autowired
private StringRedisTemplate redisTemplate;
@RequestMapping("/one")
@RedisSelect(1) //选择db1库
public String selectOne(){
String one = redisTemplate.opsForValue().get("one");
return one;
}
@RequestMapping("/two")
@RedisSelect(2) //选择db2库
public String selectTwo(){
String two = redisTemplate.opsForValue().get("two");
return two;
}
/**
* 同一个方法中切换不同的redis库
* @return
*/
@RequestMapping("/three")
@RedisSelect(2) //选择db2库
public String selectThree(){
String two = redisTemplate.opsForValue().get("two");
System.out.println(two);
RedisSelectSupport.select(3);//此处切换到db3库
String three = redisTemplate.opsForValue().get("three");
System.out.println(three);
return three;
}
}
3.2 redis中写入测试数据
3.3 测试结果:(打印的 redis reset 表示从哪个库切换回默认的库)
第一个方法,从0切到1库:127.0.0.1:8088/redis-demo/redis/one
第二个方法,从0切到2库:127.0.0.1:8088/redis-demo/redis/two
第三个方法,从0切到2库,同一个方法中再切到3库:127.0.0.1:8088/redis-demo/redis/three
至此,演示完毕。大家看完可以导入项目跑一跑,有疑问可以在评论区留言,看到即回复
最后
以上就是顺心大象为你收集整理的SpringBoot集成Redis | 使用注解动态在方法上和方法中切换Redis库的全部内容,希望文章能够帮你解决SpringBoot集成Redis | 使用注解动态在方法上和方法中切换Redis库所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复