pom.xml
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-cache</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.session</groupId>
<artifactId>spring-session-data-redis</artifactId>
</dependency>
application.yml
spring:
redis:
database: xxx
host: xxx
port: 6379
password: xxxx # 密码(默认为空)
timeout: 6000 # 连接超时时长(毫秒)
pool:
max-active: 1000 # 连接池最大连接数(使用负值表示没有限制)
max-wait: -1 # 连接池最大阻塞等待时间(使用负值表示没有限制)
max-idle: 10 # 连接池中的最大空闲连接
min-idle: 5 # 连接池中的最小空闲连接
RedisConfig.java
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.*;
import org.springframework.data.redis.serializer.JdkSerializationRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
/**
* SpringDataRedis配置
*
* Redis的Value支持5种类型:
* String字符串, List双向链表, Hash键值对,
* Set无序集合, Sorted Set有序集合
*/
@Configuration
public class RedisConfig{
@Autowired
private RedisConnectionFactory factory;
@Bean(name = "redisTemplateCustomize")
public RedisTemplate<String, Object> redisTemplate() {
RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
redisTemplate.setKeySerializer(new StringRedisSerializer());
redisTemplate.setHashKeySerializer(new StringRedisSerializer());
redisTemplate.setHashValueSerializer(new StringRedisSerializer());
redisTemplate.setValueSerializer(new JdkSerializationRedisSerializer());
redisTemplate.setConnectionFactory(factory);
return redisTemplate;
}
// value是Hash键值对类型
@Bean
public HashOperations<String, String, Object> hashOperations(RedisTemplate<String, Object> redisTemplate) {
return redisTemplate.opsForHash();
}
// value是String字符串类型
@Bean
public ValueOperations<String, String> valueOperations(RedisTemplate<String, String> redisTemplate) {
return redisTemplate.opsForValue();
}
// value是List双向链表类型
@Bean
public ListOperations<String, Object> listOperations(RedisTemplate<String, Object> redisTemplate) {
return redisTemplate.opsForList();
}
// value是Set无序集合类型
@Bean
public SetOperations<String, Object> setOperations(RedisTemplate<String, Object> redisTemplate) {
return redisTemplate.opsForSet();
}
// value是Sorted Set有序集合类型
@Bean
public ZSetOperations<String, Object> zSetOperations(RedisTemplate<String, Object> redisTemplate) {
return redisTemplate.opsForZSet();
}
}
CacheConfig.java
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.CachingConfigurerSupport;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
/**
* SpringCache配置
*/
@Configuration
public class CacheConfig extends CachingConfigurerSupport {
@Autowired
RedisTemplate redisTemplate;
@Bean
@ConditionalOnClass(RedisTemplate.class)
@Override
public CacheManager cacheManager() {
redisTemplate.setKeySerializer(new Jackson2JsonRedisSerializer<String>(String.class));
RedisCacheManager cacheManager = new RedisCacheManager(redisTemplate);
cacheManager.setUsePrefix(true);
cacheManager.setDefaultExpiration(50000);
return cacheManager;
}
}
RedisUtils.java
import cn.jiguang.common.utils.StringUtils;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.serializer.SerializerFeature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.stereotype.Component;
import java.util.Set;
import java.util.concurrent.TimeUnit;
/**
* Redis工具类
*/
@Component
public class RedisUtils {
public static final Logger log = LoggerFactory.getLogger(RedisUtils.class);
// @Autowired
// @Qualifier("redisTemplateCustomize")
// private RedisTemplate redisTemplate;
@Autowired
private ValueOperations<String, String> valueOperations;
// @Resource(name="redisTemplate")
// private HashOperations<String, String, Object> hashOperations;
// @Resource(name="redisTemplate")
// private ListOperations<String, Object> listOperations;
// @Resource(name="redisTemplate")
// private SetOperations<String, Object> setOperations;
// @Resource(name="redisTemplate")
// private ZSetOperations<String, Object> zSetOperations;
/** 默认过期时长,单位:秒 */
public final static long DEFAULT_EXPIRE = 60 * 60 * 24L;
/** 过期时长,2H */
public final static long EXPIRE_TWO_HOUR = 60 * 60 * 2L;
/** 不设置过期时长 */
public final static long NOT_EXPIRE = -1;
/**
* 获取key对应的value值
*/
public String get(String key) {
return valueOperations.get(key);
//return get(key, NOT_EXPIRE);
}
/**
* 获取key对应的value值, 并把value转为指定类型
*/
public <T> T get(String key, Class<T> clazz) {
return get(key, clazz, NOT_EXPIRE);
}
public <T> T get(String key, Class<T> clazz, long expire) {
String value = valueOperations.get(key);
if(expire != NOT_EXPIRE){
valueOperations.getOperations().expire(key, expire, TimeUnit.SECONDS);
}
return value == null ? null : fromJson(value, clazz);
}
public String get(String key, long expire) {
String value = valueOperations.get(key);
if(expire != NOT_EXPIRE){
valueOperations.getOperations().expire(key, expire, TimeUnit.SECONDS);
}
return value;
}
/**
* 往redis插入数据
*/
public void set(String key, Object value){
set(key, value, DEFAULT_EXPIRE);
}
/**
* 设置key的过期时间
*/
public void set(String key, Object value, long expire){
String strdata=toJson(value);
valueOperations.set(key, strdata);
if(expire != NOT_EXPIRE){
valueOperations.getOperations().expire(key, expire, TimeUnit.SECONDS);
}
}
/**
* 删除指定数据
*/
public void delete(String key) {
valueOperations.getOperations().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, SerializerFeature.WriteDateUseDateFormat);
}
/**
* JSON数据,转成Object
*/
private <T> T fromJson(String json, Class<T> clazz){
return JSON.parseObject(json, clazz);
}
public void deleteAllKeys(String key) {
Set<String> keys = valueOperations.getOperations().keys(key);
valueOperations.getOperations().delete(keys);
}
/**
* 加锁
* @param key
* @param value 当前时间+超时时间
* @return
*/
public boolean lock(String key, String value) {
if(valueOperations.setIfAbsent(key, value)) {
return true;
}
//currentValue=A 这两个线程的value都是B 其中一个线程拿到锁
String currentValue = valueOperations.get(key);
//如果锁过期
if (!StringUtils.isEmpty(currentValue)
&& Long.parseLong(currentValue) < System.currentTimeMillis()) {
//获取上一个锁的时间
String oldValue = valueOperations.getAndSet(key, value);
return !StringUtils.isEmpty(oldValue) && oldValue.equals(currentValue);
}
return false;
}
/**
* 解锁
* @param key
* @param value
*/
public void unlock(String key, String value) {
try {
String currentValue = valueOperations.get(key);
if (!StringUtils.isEmpty(currentValue) && currentValue.equals(value)) {
valueOperations.getOperations().delete(key);
}
}catch (Exception e) {
log.error("【redis分布式锁】解锁异常, {}", e);
}
}
}
RedisKeys.java
/**
* Redis所有Keys
*/
public class RedisKeys {
public static String getSysConfigKey(String key){
return "sys:config:" + key;
}
public static String getShiroSessionKey(String key){
return "sessionid:" + key;
}
public static String getViewCountKey(String key) {return "viewCountKey:"+key;}
// 自己自定义添加...
}
RedisShiroSessionDAO.java
import com.yymt.common.utils.RedisKeys;
import org.apache.shiro.session.Session;
import org.apache.shiro.session.mgt.eis.EnterpriseCacheSessionDAO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import java.io.Serializable;
import java.util.concurrent.TimeUnit;
/**
* shiro session dao
*/
@Component
public class RedisShiroSessionDAO extends EnterpriseCacheSessionDAO {
@Autowired
private RedisTemplate redisTemplate;
//创建session
@Override
protected Serializable doCreate(Session session) {
Serializable sessionId = super.doCreate(session);
final String key = RedisKeys.getShiroSessionKey(sessionId.toString());
setShiroSession(key, session);
return sessionId;
}
//获取session
@Override
protected Session doReadSession(Serializable sessionId) {
Session session = super.doReadSession(sessionId);
if (session == null) {
final String key = RedisKeys.getShiroSessionKey(sessionId.toString());
session = getShiroSession(key);
}
return session;
}
//更新session
@Override
protected void doUpdate(Session session) {
super.doUpdate(session);
final String key = RedisKeys.getShiroSessionKey(session.getId().toString());
setShiroSession(key, session);
}
//删除session
@Override
protected void doDelete(Session session) {
super.doDelete(session);
final String key = RedisKeys.getShiroSessionKey(session.getId().toString());
redisTemplate.delete(key);
}
private Session getShiroSession(String key) {
return (Session) redisTemplate.opsForValue().get(key);
}
private void setShiroSession(String key, Session session) {
redisTemplate.opsForValue().set(key, session);
//60分钟过期
redisTemplate.expire(key, 60, TimeUnit.MINUTES);
}
}
Demo1 (换脸次数每天最多30次)
@Autowired
RedisUtils redisUtils;
private void ifLimitCount(long userId) {
String date = DateUtil.dateConvert(new Date(), "yyyy-MM-dd");
String redisKey = date + ":" + userId;
Integer count = ConvertUtil.parseInt(redisUtils.get(redisKey));
if (count >= 30) {
throw new RRException("你已超过今日换脸次数,请明日再试!");
} else {
redisUtils.set(redisKey, count + 1, 60 * 60 * 24);
}
}
Demo2 ( RedisUtils.get(key, class)使用案例 )
@PostMapping("/hot")
@ApiOperation("热门搜索")
// @Cacheable(cacheNames = "hotsearch")
public R hot() {
String strkey= RedisKeys.getViewCountKey(parmas.toString());
R ret=redisUtils.get(strkey,R.class);
if(ret==null){
List<Map<String, Object>> list = scenicService.queryHotSearchRank();
ret=R.ok().put("data", list);
redisUtils.set(strkey,ret,60*2);
}
return ret;
}
public R getWxLiveInfo(Map<String,Object> parmas){
String strKey= RedisKeys.getLiveInfoKey(parmas.toString());
String strdata= redisUtils.get(strKey, String.class);
try {
if(strdata==null){
// 业务逻辑 ...
}
}catch(Exception e){
return R.error("获取数据异常");
}
return R.ok().put("data", strdata);
}
CREATE TABLE `sys_config` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`key` varchar(50) DEFAULT NULL COMMENT 'key',
`value` varchar(2000) DEFAULT NULL COMMENT 'value',
`status` tinyint(4) DEFAULT '1' COMMENT '状态 0:隐藏 1:显示',
`remark` varchar(500) DEFAULT NULL COMMENT '备注',
`del_flag` tinyint(1) DEFAULT NULL COMMENT '是否删除1-是,0-否',
PRIMARY KEY (`id`) USING BTREE,
UNIQUE KEY `key` (`key`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8 COMMENT='系统管理-系统配置信息表';
SysConfigRedis.java
import com.yymt.common.utils.RedisKeys;
import com.yymt.common.utils.RedisUtils;
import com.yymt.entity.sys.SysConfigEntity;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
/**
* 系统配置Redis
*/
@Component
public class SysConfigRedis {
@Autowired
private RedisUtils redisUtils;
public void saveOrUpdate(SysConfigEntity config) {
if(config == null){
return ;
}
String key = RedisKeys.getSysConfigKey(config.getKey());
redisUtils.set(key, config);
}
public void delete(String configKey) {
String key = RedisKeys.getSysConfigKey(configKey);
redisUtils.delete(key);
}
public SysConfigEntity get(String configKey){
String key = RedisKeys.getSysConfigKey(configKey);
return redisUtils.get(key, SysConfigEntity.class);
}
}
SysConfigServiceImpl.java
import com.baomidou.mybatisplus.service.impl.ServiceImpl;
import com.yymt.dao.sys.SysConfigDao;
import com.yymt.entity.sys.SysConfigEntity;
import com.yymt.modules.redis.SysConfigRedis;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@Service("sysConfigService")
public class SysConfigServiceImpl extends ServiceImpl<SysConfigDao, SysConfigEntity>{
@Autowired
private SysConfigRedis sysConfigRedis;
public void save(SysConfigEntity config) {
this.insert(config);
sysConfigRedis.saveOrUpdate(config);
}
@Transactional(rollbackFor = Exception.class)
public void update(SysConfigEntity config) {
this.updateById(config);
sysConfigRedis.saveOrUpdate(config);
}
@Transactional(rollbackFor = Exception.class)
public void updateValueByKey(String key, String value) {
baseMapper.updateValueByKey(key, value);
sysConfigRedis.delete(key);
}
}