记录传统SpringMVC项目集成Redis,总结一下遇到的坑和异常原因。
如果有疑问或者感觉哪里有问题欢迎指点,一起探讨。
一:选择合适的jar包
选择合适的jar包,而且如果spring和redis这两个jar包版本不对应的话运行中会报错。
以下是我使用的版本。
2.8.1
2.4.2
1.7.5.RELEASE
org.springframework.data
spring-data-redis
${spring.redis.version}
redis.clients
jedis
${jedis.version}
org.apache.commons
commons-pool2
${commons.pool2.version}
查看spring对应的redis信息可以去 Maven Repository 官方查询
选择版本点进去在页面下方可以看到对应的redis版本信息:
因为本人比较习惯使用spring低版本中的配置文件里的 JedisConnectionFactory 所以并没有选择使用高版本的 jar。
二:redis 配置文件信息:
<?xml version="1.0" encoding="UTF-8"?>
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.0.xsd">
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
classpath:config/*.properties
三:redis.properties 数据文件参数:
这里的参数是我们线上系统的使用参数,数值比较大,如果只是小系统使用可以设置的小一点,如果太小的话运行会报异常,按需调整就行。
#redis.master.ip=127.0.0.1
#redis.master.port=6379
#redis.master.password=123456
# JEDIS_BorrowPool:maxActive
redis.pool.maxActive=1024
# JEDIS_BorrowPool:maxIdle
redis.pool.maxIdle=200
# JEDIS_BorrowPool:maxTotal
redis.pool.maxTotal=200
# JEDIS_BorrowPool:maxWaitMillis
redis.pool.maxWaitMillis=7200
# JEDIS_BorrowPool:testOnBorrow
redis.pool.testOnBorrow=false
# JEDIS_BorrowPool:testOnReturn
redis.pool.testOnReturn=false
# JEDIS_Connection:timeout
redis.master.timeout=10000
四:RedisUtils工具类:
(其中指定 RedisSerializer 序列化,这个序列化程序序列化出的数据比较直观,不会乱码,在Redis Desktop Manager 软件上可以直接查看数据详情)。
package com.xxx.xxx.service.impl;
import com.xxx.xxx.xxx.utils.StringUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.dao.DataAccessException;
import org.springframework.data.redis.core.RedisConnectionUtils;
import org.springframework.data.redis.core.RedisOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.SessionCallback;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import redis.clients.jedis.Jedis;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.TimeUnit;
/**
* @author ShouSi
* @Title: Redis工具类Service,使用Spring整合,redisTemplate:事务操作,匿名内部类操作
* @date 2021/12/03 17:51
*/
public class RedisUtils {
private static final Logger logger = LogManager.getLogger(RedisUtils.class);
private static RedisTemplate redisTemplate;
public RedisUtils(RedisTemplate redisTemplate) {
RedisSerializer stringSerializer = new StringRedisSerializer();
redisTemplate.setKeySerializer(stringSerializer);
redisTemplate.setValueSerializer(stringSerializer);
redisTemplate.setHashKeySerializer(stringSerializer);
redisTemplate.setHashValueSerializer(stringSerializer);
this.redisTemplate = redisTemplate;
}
/**
* 获取所有key,支持正则表达式
* @param key
* @return Set key
*/
public static Set keys(String key) {
Set keys = null;
if(StringUtils.isBlank(key)){
key = "*";
}
try {
keys = redisTemplate.keys(key);
} catch (Exception e) {
logger.error("keys:获取所有key异常,key:{}", key,e);
} finally {
RedisConnectionUtils.unbindConnection(redisTemplate.getConnectionFactory());
}
return keys;
}
/**
* 向key指向的set集合中插入若干条数据
* @param key
* @param members
*/
public static void sadd(String key, String... members) {
//redis操作发生异常时要把异常捕获,不要响应正常的业务逻辑
try {
Long add = redisTemplate.boundSetOps(key).add(members);
} catch (Exception e) {
logger.error("sadd:向缓存中添加数据时出现异常,key:{} value:{}", key, members,e);
} finally {
RedisConnectionUtils.unbindConnection(redisTemplate.getConnectionFactory());
}
}
/**
* 从key指向的set集合中取出所有数据并删除此key指向的set集合
* @param key
* @return
*/
@SuppressWarnings("unchecked")
public static Set smembersAndDel(String key) {
Set set = null;
try {
Object o = redisTemplate.execute(new SessionCallback
为了方便使用,我这里专门做了一个Hask操作的key值参数类,这样可以使数据更好的按照指定的维度进行分类,比如店铺维度,后缀加MySql店铺表id,一个店铺一个Hash表。
五:RedisKeyAndField 类:
package com.xxx.xxx.domain.jedis;
/**
* @description: RedisKeyAndField
* @author: ShouSi
* @createDate: 2021/10/21
*/
public class RedisKeyAndField {
public static final String Order_Info_ = "Order_Info_"; // redis 订单 店铺维度 _后缀加店铺ID
public static final String OrderStock_Info_ = "OrderStock_Info_"; // redis 订单商品明细 店铺维度 _后缀加店铺ID
public static final String OrderGift_Info_ = "OrderGift_Info_"; // redis 订单赠品明细 店铺维度 _后缀加店铺ID
public static final String Shop_Info = "Shop_Info"; // redis 店铺
public static final String ShopCross_Info = "ShopCross_Info"; // redis 跨境店铺
public static final String Tenant_Info = "Tenant_Info"; // redis 租户
public static final String Goods_Info = "Goods_Info"; // redis 商品资料
public static final String Stock_Info = "Stock_Info"; // redis 库存
public static final String StockBatch_Info = "StockBatch_Info"; // redis 库存批次
public static final String Pretreat_Info_ = "Pretreat_Info"; // redis 预设置策略 货主维度 _后缀加tenantid
public static final String Paramset_Info = "Paramset_Info"; // redis 参数配置
public static final String Activity_Info_ = "Activity_Info_"; // redis 赠送策略 货主维度 _后缀加tenantid
public static final String StockPolicy1_ = "StockPolicy1_"; // redis 自动发货策略
public static final String StockPolicy2_ = "StockPolicy2_"; // redis 自动驳回策略
public static final String StockPolicy3_ = "StockPolicy3_"; // redis 自动合并策略
public static final String StockPolicy4_ = "StockPolicy4_"; // redis 自动拆分策略
}
注意:
店铺信息,账号信息这种不经常更改的信息如果要放到redis上,如果系统有修改或者新增的操作,要同步更新redis,并且在redis上尽量给这种数据一个过期时间,过期后在查询的时候如果没有数据,去数据库查,并且同步一份到redis。