新增redis缓存管理

This commit is contained in:
china-bin 2020-09-13 11:58:49 +08:00
parent b1d968d995
commit 51d61e06f4
18 changed files with 1167 additions and 26 deletions

View File

@ -1,5 +1,5 @@
## 平台简介
基于ruoyi开发的多站点管理cms每个站点独立后台管理员管理其各自的站点数据。在原代码生成功能基础上增添了符合多站点代码的生成。让多站点后台开发十分便捷。
基于ruoyi(4.4.0)开发的多站点管理cms每个站点独立后台管理员管理其各自的站点数据。在原代码生成功能基础上增添了符合多站点代码的生成。让多站点后台开发十分便捷。
@ -27,7 +27,7 @@
1. 多站点管理: 可以添站点,并且用户管理中为用户分配站点管理权限。
2. 资源管理:统一管理资源,保障资源不被重复使用。
3. 模板主题管理:可以针对不同站点设置不同的模板,
4. redis缓存管理
## 扩展代码生成
1. 新增站点id选择器与选择器类型。
@ -36,7 +36,8 @@
![模板](doc/img/2.png)
## 功能优化
1.
## 在线体验
- admin/admin123

View File

@ -218,6 +218,7 @@
<module>ruoyi-generator</module>
<module>ruoyi-common</module>
<module>ruoyi-cms</module>
<module>ruoyi-redis</module>
</modules>
<packaging>pom</packaging>

View File

@ -23,27 +23,9 @@
<body class="signin">
<div class="signinpanel">
<div class="row">
<div class="col-sm-7">
<div class="signin-info">
<div class="logopanel m-b">
<h1><img alt="[ 若依 ]" src="../static/ruoyi.png" th:src="@{/ruoyi.png}"></h1>
</div>
<div class="m-b"></div>
<h4>欢迎使用 <strong>若依 后台管理系统</strong></h4>
<ul class="m-b">
<li><i class="fa fa-arrow-circle-o-right m-r-xs"></i> SpringBoot</li>
<li><i class="fa fa-arrow-circle-o-right m-r-xs"></i> Mybatis</li>
<li><i class="fa fa-arrow-circle-o-right m-r-xs"></i> Shiro</li>
<li><i class="fa fa-arrow-circle-o-right m-r-xs"></i> Thymeleaf</li>
<li><i class="fa fa-arrow-circle-o-right m-r-xs"></i> Bootstrap</li>
</ul>
<strong th:if="${@config.getKey('sys.account.registerUser')}">还没有账号? <a th:href="@{/register}">立即注册&raquo;</a></strong>
</div>
</div>
<div class="col-sm-5">
<div class="col-sm-6">
<form id="signupForm" autocomplete="off">
<h4 class="no-margins">登录:</h4>
<p class="m-t-md">你若不离不弃,我必生死相依</p>
<h4 class="no-margins">登录</h4>
<input type="text" name="username" class="form-control uname" placeholder="用户名" value="admin" />
<input type="password" name="password" class="form-control pword" placeholder="密码" value="admin123" />
<div class="row m-t" th:if="${captchaEnabled==true}">
@ -65,7 +47,7 @@
</div>
<div class="signup-footer">
<div class="pull-left">
&copy; 2019 All Rights Reserved. RuoYi <br>
&copy; 2019 All Rights Reserved. RuoYi-cms <br>
</div>
</div>
</div>

View File

@ -27,6 +27,7 @@
</dependency>
</dependencies>

View File

@ -1,6 +1,9 @@
package com.ruoyi.common.utils;
import java.io.IOException;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
@ -161,4 +164,20 @@ public class ServletUtils
}
return flag;
}
public static Map<String, String> getMap(HttpServletRequest req) {
Map<String, String> map=new HashMap<String, String>();
Enumeration enu = req.getParameterNames();
while(enu.hasMoreElements()) {
String paramName = (String)enu.nextElement();
String[] paramValues = req.getParameterValues(paramName);
if (paramValues.length == 1) {
String paramValue = paramValues[0];
if (paramValue.length() != 0) {
map.put(paramName, paramValue);
}
}
}
return map;
}
}

View File

@ -102,7 +102,7 @@ public class StringUtils extends org.apache.commons.lang3.StringUtils
*/
public static boolean isEmpty(String str)
{
return isNull(str) || NULLSTR.equals(str.trim());
return isNull(str) || NULLSTR.equals(str.trim())||"null".equals(str);
}
/**
@ -405,4 +405,18 @@ public class StringUtils extends org.apache.commons.lang3.StringUtils
{
return (T) obj;
}
/**
* 如果target不为空返回target,否则返回一个默认值
* @param target
* @param defaultValue
* @return
*/
public static String assertNotNullOrEmpty(String target,String defaultValue){
if(isNotEmpty(target)){
return target;
}else{
return defaultValue;
}
}
}

View File

@ -87,7 +87,12 @@
<artifactId>ruoyi-system</artifactId>
</dependency>
<!-- redis模块-->
<dependency>
<groupId>com.ruoyi</groupId>
<artifactId>ruoyi-redis</artifactId>
<version>${ruoyi.version}</version>
</dependency>
</dependencies>

View File

@ -6,6 +6,7 @@ import java.util.Set;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.ruoyi.common.exception.SiteException;
import com.ruoyi.redis.util.RedisUtil;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;

31
ruoyi-redis/pom.xml Normal file
View File

@ -0,0 +1,31 @@
<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>ruoyi</artifactId>
<groupId>com.ruoyi</groupId>
<version>4.4.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>ruoyi-redis</artifactId>
<properties>
<jedis.version>2.7.3</jedis.version>
</properties>
<dependencies>
<!-- 通用工具-->
<dependency>
<groupId>com.ruoyi</groupId>
<artifactId>ruoyi-common</artifactId>
</dependency>
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>${jedis.version}</version>
</dependency>
</dependencies>
</project>

View File

@ -0,0 +1,33 @@
package com.ruoyi.redis.config;
import com.ruoyi.redis.util.InitRedisUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import javax.annotation.PostConstruct;
/**
* 读取代码生成相关配置
*
* @author wujiyue
*/
@Configuration
@PropertySource(value = { "classpath:redis.properties" })
public class RedisConfig {
protected final Logger log= LoggerFactory.getLogger(getClass());
@Value("${redis.address}")
protected String redisAddress;
@PostConstruct
public void initRedis(){
log.info(">>>>>>>redisAddress:"+redisAddress);
InitRedisUtil.init(redisAddress);
if(InitRedisUtil.initFlag){
log.info(">>>>>>>redis init success!");
}else{
log.warn(">>>>>>>redis init fail!");
}
}
}

View File

@ -0,0 +1,78 @@
package com.ruoyi.redis.controller;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.utils.ServletUtils;
import com.ruoyi.redis.service.RedisCacheMonitorService;
import com.ruoyi.redis.util.RedisUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import javax.servlet.http.HttpServletRequest;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
@Controller
@RequestMapping("/monitor/redis")
public class RedisCacheMonitorController extends BaseController {
@Autowired
RedisCacheMonitorService jedisUtilCacheService;
private String prefix = "monitor/redis";
/**
* 跳转页面
* @return
*/
@RequestMapping(value={"","/"})
public String index(){
return prefix+"/list";
}
@RequestMapping("/viewCacheInfoByKey")
public String viewCacheInfo(String key, Model model){
if(key.contains("$")){
key=key.replace("$","#") ;
}
Map<String,Object> info= jedisUtilCacheService.viewCacheInfoByKey(key);
model.addAttribute("info",info);
return prefix+"/viewInfo";
}
/**
* redis缓存信息列表
* @param req
* @return
*/
@ResponseBody
@RequestMapping("/list")
public Object list(HttpServletRequest req){
Map map= ServletUtils.getMap(req);
List<String> urls = new ArrayList<>();
urls.add("aaa");
urls.add("bbbb");
RedisUtil.setObjectValue("test", urls);
System.out.println(RedisUtil.getStringValue("test"));
return jedisUtilCacheService.listPg(map);
}
/**
* 清除缓存信息
* @param key
* @return
*/
@ResponseBody
@RequestMapping("/removeCacheByKey")
public Object removeCacheByKey(String key){
if(key.contains("$")){
key=key.replace("$","#") ;
}
return jedisUtilCacheService.removeCacheByKey(key);
}
}

View File

@ -0,0 +1,32 @@
package com.ruoyi.redis.runner;
import com.ruoyi.redis.util.RedisUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.CommandLineRunner;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
/**
* springboot 允许实现CommandLineRunner接口的类程序启动后run方法中做一些事情比如加载缓存.
*/
@Component
@Order(value = 2)
public class InitRedisCacheRunner implements CommandLineRunner {
protected final Logger log= LoggerFactory.getLogger(getClass());
@Override
public void run(String... args) throws Exception {
log.info("InitRedisCacheRunner加载缓存信息start>>>>>>>");
//可以从数据库加载配置信息到缓存
RedisUtil.setStringValue("test_key","test_value");
RedisUtil.setStringValue("test_user_key","test_user_value",18000);
for(int i=1;i<=20;i++){
RedisUtil.putDefaultInfo("key_"+i,"value"+i);
RedisUtil.putSysInfo("key_"+i,"value"+i);
RedisUtil.putUserInfo("key_",i+"","value"+i);
}
log.info("InitRedisCacheRunner加载缓存信息End<<<<<<<<");
}
}

View File

@ -0,0 +1,89 @@
package com.ruoyi.redis.service;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.redis.util.RedisUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@Service
public class RedisCacheMonitorService {
protected Logger logger = LoggerFactory.getLogger(getClass());
public Object removeCacheByKey(String key){
if(RedisUtil.exists(key)){
RedisUtil.del(key);
return AjaxResult.success("清除缓存成功!");
}
return AjaxResult.error("不存在key为["+key+"]的缓存!");
}
public Map<String,Object> viewCacheInfoByKey(String key){
Map<String,Object> res=new HashMap();
if(RedisUtil.exists(key)){
res.put("key",key);
String value= RedisUtil.getStringValue(key);
res.put("value",value);
}
return res;
}
/**
* 获取缓存分页信息
* @param map
* @return
*/
public Object listPg(Map<String, Object> map) {
try {
String keyContent = String.valueOf(map.get("keyContent"));
String page_str = (String) map.get("pageNum");//当前页
String limit_str = (String) map.get("pageSize");//每页几条数据
page_str = StringUtils.assertNotNullOrEmpty(page_str, "1");
limit_str = StringUtils.assertNotNullOrEmpty(limit_str, "10");
int page = Integer.parseInt(page_str);
int limit = Integer.parseInt(limit_str);
int start = page - 1;
if (page == 1 || page == 0) {
start = 0;
}
if (StringUtils.isEmpty(keyContent)) {
keyContent = "*";
} else {
keyContent = "*" + keyContent + "*";
}
List<String> keysList = RedisUtil.keys(keyContent);
int keysCount = keysList.size();
List<Map<String, Object>> mapList = new ArrayList<Map<String, Object>>();
Map<String, Object> temp = null;
for (int i = start * limit; i < keysCount && i < (start + 1) * limit; i++) {
temp = new HashMap<>();
String key = keysList.get(i);
String type = RedisUtil.type(key);
long ttl = RedisUtil.ttl(key);
temp.put("key", key);
temp.put("type", type);
temp.put("ttl", ttl);
mapList.add(temp);
}
TableDataInfo tableDataInfo=new TableDataInfo();
tableDataInfo.setTotal(keysCount);
tableDataInfo.setRows(mapList);
tableDataInfo.setCode(0);
tableDataInfo.setMsg("0");
return tableDataInfo;
}catch (Exception ex){
ex.printStackTrace();
return AjaxResult.error("获取缓存分页信息失败!");
}
}
}

View File

@ -0,0 +1,517 @@
package com.ruoyi.redis.util;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import redis.clients.jedis.*;
import java.io.*;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReentrantLock;
/**
* Redis client base on jedis
*
* @author wujiyue 2015-7-10 18:34:07
*/
public class InitRedisUtil {
private static Logger logger = LoggerFactory.getLogger(InitRedisUtil.class);
/**
* redis address, like "{ip}""{ip}:{port}""{redis/rediss}://域名:{password}@{ip}:{port:6379}/{db}"Multiple "," separated
*/
private static String address;
public static boolean initFlag=false;
public static void init(String address) {
InitRedisUtil.address = address;
getInstance();
}
// ------------------------ ShardedJedisPool ------------------------
/**
* 方式01: Redis单节点 + Jedis单例 : Redis单节点压力过重, Jedis单例存在并发瓶颈 不可用于线上
* new Jedis("127.0.0.1", 6379).get("cache_key");
* 方式02: Redis单节点 + JedisPool单节点连接池 Redis单节点压力过重负载和容灾比较差
* new JedisPool(new JedisPoolConfig(), "127.0.0.1", 6379, 10000).getResource().get("cache_key");
* 方式03: Redis分片(通过client端集群,一致性哈希方式实现) + Jedis多节点连接池 Redis集群,负载和容灾较好, ShardedJedisPool一致性哈希分片,读写均匀动态扩充
* new ShardedJedisPool(new JedisPoolConfig(), new LinkedList<JedisShardInfo>());
* 方式03: Redis集群
* new JedisCluster(jedisClusterNodes); // TODO
*/
private static ShardedJedisPool shardedJedisPool;
private static ReentrantLock INSTANCE_INIT_LOCL = new ReentrantLock(false);
/**
* 获取ShardedJedis实例
*
* @return
*/
private static ShardedJedis getInstance() {
if (shardedJedisPool == null) {
try {
if (INSTANCE_INIT_LOCL.tryLock(2, TimeUnit.SECONDS)) {
try {
if (shardedJedisPool == null) {
// JedisPoolConfig
JedisPoolConfig config = new JedisPoolConfig();
config.setMaxTotal(200);
config.setMaxIdle(50);
config.setMinIdle(8);
config.setMaxWaitMillis(10000); // 获取连接时的最大等待毫秒数(如果设置为阻塞时BlockWhenExhausted),如果超时就抛异常, 小于零:阻塞不确定的时间, 默认-1
config.setTestOnBorrow(true); // 在获取连接的时候检查有效性, 默认false
config.setTestOnReturn(false); // 调用returnObject方法时是否进行有效检查
config.setTestWhileIdle(true); // Idle时进行连接扫描
config.setTimeBetweenEvictionRunsMillis(30000); // 表示idle object evitor两次扫描之间要sleep的毫秒数
config.setNumTestsPerEvictionRun(10); // 表示idle object evitor每次扫描的最多的对象数
config.setMinEvictableIdleTimeMillis(60000); // 表示一个对象至少停留在idle状态的最短时间然后才能被idle object evitor扫描并驱逐这一项只有在timeBetweenEvictionRunsMillis大于0时才有意义
// JedisShardInfo List
List<JedisShardInfo> jedisShardInfos = new LinkedList<JedisShardInfo>();
String[] addressArr = address.split(",");
for (int i = 0; i < addressArr.length; i++) {
JedisShardInfo jedisShardInfo = new JedisShardInfo(addressArr[i]);
jedisShardInfos.add(jedisShardInfo);
}
shardedJedisPool = new ShardedJedisPool(config, jedisShardInfos);
logger.info(">>>>>>>>>>>RedisUtil.ShardedJedisPool init success.");
}
} finally {
INSTANCE_INIT_LOCL.unlock();
initFlag=true;
}
}
} catch (InterruptedException e) {
logger.error(e.getMessage(), e);
}
}
if (shardedJedisPool == null) {
initFlag=false;
throw new NullPointerException(">>>>>>>>>>> RedisUtil.ShardedJedisPool is null.");
}
ShardedJedis shardedJedis = shardedJedisPool.getResource();
return shardedJedis;
}
public static void close() throws IOException {
if(shardedJedisPool != null) {
shardedJedisPool.close();
}
}
// ------------------------ serialize and unserialize ------------------------
/**
* 将对象-->byte[] (由于jedis中不支持直接存储object所以转换成byte[]存入)
*
* @param object
* @return
*/
private static byte[] serialize(Object object) {
ObjectOutputStream oos = null;
ByteArrayOutputStream baos = null;
try {
// 序列化
baos = new ByteArrayOutputStream();
oos = new ObjectOutputStream(baos);
oos.writeObject(object);
byte[] bytes = baos.toByteArray();
return bytes;
} catch (Exception e) {
logger.error(e.getMessage(), e);
} finally {
try {
oos.close();
baos.close();
} catch (IOException e) {
logger.error(e.getMessage(), e);
}
}
return null;
}
/**
* 将byte[] -->Object
*
* @param bytes
* @return
*/
private static Object unserialize(byte[] bytes) {
ByteArrayInputStream bais = null;
try {
// 反序列化
bais = new ByteArrayInputStream(bytes);
ObjectInputStream ois = new ObjectInputStream(bais);
return ois.readObject();
} catch (Exception e) {
logger.error(e.getMessage(), e);
} finally {
try {
bais.close();
} catch (IOException e) {
logger.error(e.getMessage(), e);
}
}
return null;
}
// ------------------------ jedis util ------------------------
/**
* 存储简单的字符串或者是Object 因为jedis没有分装直接存储Object的方法所以在存储对象需斟酌下
* 存储对象的字段是不是非常多而且是不是每个字段都用到如果是的话那建议直接存储对象
* 否则建议用集合的方式存储因为redis可以针对集合进行日常的操作很方便而且还可以节省空间
*/
/**
* Set String
*
* @param key
* @param value
* @return
*/
public static String setStringValue(String key, String value) {
String result = null;
ShardedJedis client = getInstance();
try {
result = client.set(key, value);
} catch (Exception e) {
logger.error(e.getMessage(), e);
} finally {
if (client != null) {
client.close();
}
}
return result;
}
public static String type(String key) {
String result = null;
ShardedJedis client = getInstance();
try {
result = client.type(key);
} catch (Exception e) {
logger.error(e.getMessage(), e);
} finally {
if (client != null) {
client.close();
}
}
return result;
}
public static long ttl(String key) {
long result = 0L;
ShardedJedis client = getInstance();
try {
result = client.ttl(key);
} catch (Exception e) {
logger.error(e.getMessage(), e);
} finally {
if (client != null) {
client.close();
}
}
return result;
}
/**
* Set String
*
* @param key
* @param value
* @param seconds 存活时间,单位/
* @return
*/
public static String setStringValue(String key, String value, int seconds) {
String result = null;
ShardedJedis client = getInstance();
try {
result = client.setex(key, seconds, value);
} catch (Exception e) {
logger.error(e.getMessage(), e);
} finally {
if (client != null) {
client.close();
}
}
return result;
}
/**
* Set Object
*
* @param key
* @param obj
* @param seconds 存活时间,单位/
*/
public static String setObjectValue(String key, Object obj, int seconds) {
String result = null;
ShardedJedis client = getInstance();
try {
// result = client.setex(key.getBytes(), seconds, serialize(obj));
result = client.setex(key, seconds, JSON.toJSONString(obj));
} catch (Exception e) {
logger.error(e.getMessage(), e);
} finally {
if (client != null) {
client.close();
}
}
return result;
}
/**
* Set Object
*
* @param key
* @param obj
*/
public static String setObjectValue(String key, Object obj) {
String result = null;
ShardedJedis client = getInstance();
try {
result = client.set(key, JSON.toJSONString(obj));
} catch (Exception e) {
logger.error(e.getMessage(), e);
} finally {
if (client != null) {
client.close();
}
}
return result;
}
/**
* Get String
*
* @param key
* @return
*/
public static String getStringValue(String key) {
String value = null;
ShardedJedis client = getInstance();
try {
value = client.get(key);
} catch (Exception e) {
logger.error(e.getMessage(), e);
} finally {
if (client != null) {
client.close();
}
}
return value;
}
/**
* Get Object
*
* @param key
* @return
*/
public static Object getObjectValue(String key) {
Object obj = null;
ShardedJedis client = getInstance();
try {
byte[] bytes = client.get(key.getBytes());
if (bytes != null && bytes.length > 0) {
obj = unserialize(bytes);
}
} catch (Exception e) {
logger.error(e.getMessage(), e);
} finally {
if (client != null) {
client.close();
}
}
return obj;
}
public static Object getObjectValue(String key,Class cls) {
Object obj = null;
ShardedJedis client = getInstance();
try {
/* byte[] bytes = client.get(key.getBytes());
if (bytes != null && bytes.length > 0) {
obj = unserialize(bytes);
}*/
;
obj= JSONObject.parseObject(client.get(key), cls);
} catch (Exception e) {
logger.error(e.getMessage(), e);
} finally {
if (client != null) {
client.close();
}
}
return obj;
}
/**
* Delete key
*
* @param key
* @return Integer reply, specifically:
* an integer greater than 0 if one or more keys were removed
* 0 if none of the specified key existed
*/
public static Long del(String key) {
Long result = null;
ShardedJedis client = getInstance();
try {
result = client.del(key);
} catch (Exception e) {
logger.error(e.getMessage(), e);
} finally {
if (client != null) {
client.close();
}
}
return result;
}
/**
* incrBy i(+i)
*
* @param key
* @param i
* @return new value after incr
*/
public static Long incrBy(String key, int i) {
Long result = null;
ShardedJedis client = getInstance();
try {
result = client.incrBy(key, i);
} catch (Exception e) {
logger.error(e.getMessage(), e);
} finally {
if (client != null) {
client.close();
}
}
return result;
}
/**
* exists valid
*
* @param key
* @return Boolean reply, true if the key exists, otherwise false
*/
public static boolean exists(String key) {
Boolean result = null;
ShardedJedis client = getInstance();
try {
result = client.exists(key);
} catch (Exception e) {
logger.error(e.getMessage(), e);
} finally {
if (client != null) {
client.close();
}
}
return result;
}
/**
* expire reset
*
* @param key
* @param seconds 存活时间,单位/
* @return Integer reply, specifically:
* 1: the timeout was set.
* 0: the timeout was not set since the key already has an associated timeout (versions lt 2.1.3), or the key does not exist.
*/
public static long expire(String key, int seconds) {
Long result = null;
ShardedJedis client = getInstance();
try {
result = client.expire(key, seconds);
} catch (Exception e) {
logger.error(e.getMessage(), e);
} finally {
if (client != null) {
client.close();
}
}
return result;
}
/**
* expire at unixTime
*
* @param key
* @param unixTime
* @return
*/
public static long expireAt(String key, long unixTime) {
Long result = null;
ShardedJedis client = getInstance();
try {
result = client.expireAt(key, unixTime);
} catch (Exception e) {
logger.error(e.getMessage(), e);
} finally {
if (client != null) {
client.close();
}
}
return result;
}
/**
* 实现redis keys 模糊查询
* @author hq
* @param pattern
* @return
*/
public static List<String> keys(String pattern){
logger.info("开始模糊查询【{}】keys", pattern);
ShardedJedis shardedJedis= shardedJedisPool.getResource();
Collection<Jedis> allShards = shardedJedis.getAllShards();
List<String> keyList = new ArrayList<>();
for(Jedis jedis:allShards){
Set<String> keys = jedis.keys(pattern);
keyList.addAll(keys);
}
logger.info("已获取所有keys");
return keyList;
}
public static void main(String[] args) {
//String SsoRedisAddress = "redis://域名:password@127.0.0.1:6379/0";
String SsoRedisAddress = "redis://127.0.0.1:6379/0";
init(SsoRedisAddress);
ShardedJedis client = getInstance();
client.set("cnblog", "cnblog");
client.set("redis", "redis");
client.set("test", "test");
client.set("123456", "1234567");
Client client1 = client.getShard("cnblog").getClient();
Client client2 = client.getShard("redis").getClient();
Client client3 = client.getShard("test").getClient();
Client client4 = client.getShard("123456").getClient();
////打印key在哪个server中
System.out.println("cnblog in server:" + client1.getHost() + " and port is:" + client1.getPort());
System.out.println("redis in server:" + client2.getHost() + " and port is:" + client2.getPort());
System.out.println("test in server:" + client3.getHost() + " and port is:" + client3.getPort());
System.out.println("123456 in server:" + client4.getHost() + " and port is:" + client4.getPort());
List<String> keys=keys("*session*");
keys.forEach(s->{
System.out.println(s);
});
}
}

View File

@ -0,0 +1,214 @@
package com.ruoyi.redis.util;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import redis.clients.jedis.Client;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.ShardedJedis;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Set;
public class RedisUtil {
public static final String SYS_CACHE = "sysCache";
public static final String USER_CACHE = "userCache";
public static final String DEFAULT_CACHE = "defaultCache";
public static String getSysInfo(String key) {
return RedisUtil.getStringValue(SYS_CACHE+"_"+key);
}
public static String getDefaultInfo(String key) {
return RedisUtil.getStringValue(DEFAULT_CACHE+"_"+key);
}
public static String getUserInfo(String key,String yhid) {
return RedisUtil.getStringValue(USER_CACHE+"_"+key+"_"+yhid);
}
public static void putSysInfo(String key, Object value) {
RedisUtil.setStringValue(SYS_CACHE+"_"+key,JSON.toJSONString(value));
}
public static void putDefaultInfo(String key, Object value) {
RedisUtil.setStringValue(DEFAULT_CACHE+"_"+key,JSON.toJSONString(value));
}
public static void putUserInfo(String key,String yhid, Object value) {
RedisUtil.setStringValue(USER_CACHE+"_"+key+"_"+yhid,JSON.toJSONString(value));
}
public static void removeSysInfo(String key) {
RedisUtil.del(SYS_CACHE+"_"+key);
}
public static void removeDefaultInfo(String key) {
RedisUtil.del(DEFAULT_CACHE+"_"+key);
}
public static void removeUserInfo(String key,String yhid) {
RedisUtil.del(USER_CACHE+"_"+key+"_"+yhid);
}
public static void clearUserInfo(String yhid){
List<String> keys=RedisUtil.keys(USER_CACHE+"_*_"+yhid);
keys.forEach(s->{
RedisUtil.del(s);
});
}
public static void clearUserCache(){
List<String> keys=RedisUtil.keys(USER_CACHE+"_*");
keys.forEach(s->{
RedisUtil.del(s);
});
}
public static void clearSysCache(){
List<String> keys=RedisUtil.keys(SYS_CACHE+"_*");
keys.forEach(s->{
RedisUtil.del(s);
});
}
public static void clearDefaultCache(){
List<String> keys=RedisUtil.keys(DEFAULT_CACHE+"_*");
keys.forEach(s->{
RedisUtil.del(s);
});
}
//--------------------------------------------------
public static String setStringValue(String key, String value) {
return InitRedisUtil.setStringValue(key,value);
}
public static String type(String key) {
return InitRedisUtil.type(key);
}
public static long ttl(String key) {
return InitRedisUtil.ttl(key);
}
/**
* Set String
*
* @param key
* @param value
* @param seconds 存活时间,单位/
* @return
*/
public static String setStringValue(String key, String value, int seconds) {
return InitRedisUtil.setStringValue(key,value,seconds);
}
/**
* Set Object
* @param key
* @param obj
* @param seconds 存活时间,单位/
*/
public static String setObjectValue(String key, Object obj, int seconds) {
return InitRedisUtil.setObjectValue(key,obj,seconds);
}
/**
* Set Object
* @param key
* @param obj
*/
public static String setObjectValue(String key, Object obj) {
return InitRedisUtil.setObjectValue(key,obj);
}
/**
* Get String
*
* @param key
* @return
*/
public static String getStringValue(String key) {
return InitRedisUtil.getStringValue(key);
}
/**
* Get Object
*
* @param key
* @return
*/
public static Object getObjectValue(String key) {
return InitRedisUtil.getObjectValue(key);
}
public static Object getObjectValue(String key,Class cls) {
return InitRedisUtil.getObjectValue(key,cls);
}
/**
* Delete key
*
* @param key
* @return Integer reply, specifically:
* an integer greater than 0 if one or more keys were removed
* 0 if none of the specified key existed
*/
public static Long del(String key) {
return InitRedisUtil.del(key);
}
/**
* incrBy i(+i)
*
* @param key
* @param i
* @return new value after incr
*/
public static Long incrBy(String key, int i) {
return InitRedisUtil.incrBy(key,i);
}
/**
* exists valid
*
* @param key
* @return Boolean reply, true if the key exists, otherwise false
*/
public static boolean exists(String key) {
return InitRedisUtil.exists(key);
}
/**
* expire reset
* @param key
* @param seconds 存活时间,单位/
* @return Integer reply, specifically:
* 1: the timeout was set.
* 0: the timeout was not set since the key already has an associated timeout (versions lt 2.1.3), or the key does not exist.
*/
public static long expire(String key, int seconds) {
return InitRedisUtil.expireAt(key,seconds);
}
/**
* expire at unixTime
* @param key
* @param unixTime
* @return
*/
public static long expireAt(String key, long unixTime) {
return InitRedisUtil.expireAt(key,unixTime);
}
/**
* 实现redis keys 模糊查询
* @author hq
* @param pattern
* @return
*/
public static List<String> keys(String pattern){
return InitRedisUtil.keys(pattern);
}
public static void main(String[] args) {
List<String> urls = new ArrayList<>();
urls.add("aaa");
urls.add("bbbb");
RedisUtil.setObjectValue("test", urls, 3000);
System.out.println(RedisUtil.getStringValue("test"));
}
}

View File

@ -0,0 +1,6 @@
# redisÅäÖÃ
# "{ip}"
# "{ip}:{port}"
# "redis://{ip}:{port}/{db}"
# "redis://{user}:{password}@{ip}:{port}/{db}"
redis.address=redis://127.0.0.1:6379/0,redis://127.0.0.1:6379/1,redis://127.0.0.1:6379/2

View File

@ -0,0 +1,93 @@
<!DOCTYPE html>
<html lang="zh" xmlns:th="http://www.thymeleaf.org" xmlns:shiro="http://www.pollix.at/thymeleaf/shiro">
<head>
<th:block th:include="include :: header('redis缓存列表')" />
</head>
<body class="gray-bg">
<div class="container-div">
<div class="row">
<div class="col-sm-12 search-collapse">
<form id="config-form">
<div class="select-list">
<ul>
<!--<li>
类型:<select id="cachetype" name="cachetype" >
<option value="0" selected="selected">系统缓存</option>
<option value="1">用户缓存</option>
<option value="2">默认缓存</option>
</select>
</li>-->
<li>
键名:<input type="text" id="keyContent" name="keyContent"/>
</li>
<li>
<a class="btn btn-primary btn-rounded btn-sm" onclick="$.table.search()"><i class="fa fa-search"></i>&nbsp;搜索</a>
<a class="btn btn-warning btn-rounded btn-sm" onclick="$.form.reset()"><i class="fa fa-refresh"></i>&nbsp;重置</a>
</li>
</ul>
</div>
</form>
</div>
<div class="btn-group-sm" id="toolbar" role="group">
</div>
<div class="col-sm-12 select-table table-striped">
<table id="bootstrap-table" data-mobile-responsive="true" style="table-layout:fixed"></table>
</div>
</div>
</div>
<th:block th:include="include :: footer" />
<script th:inline="javascript">
var prefix = ctx + "monitor/redis";
$(function() {
var options = {
url: prefix + "/list",
createUrl: prefix + "/add",
modalName: "redis缓存",
columns: [{
checkbox: true
},
{field: 'key', title: 'KEY'},
/* {field: 'value', title: '值',
formatter: function(value, row, index) {
return $.table.tooltip(value);
}
},*/
{field: 'type', title: '类型',width:"100px"},
{field: 'ttl', title: 'TTL',width:"100px"},
{title: '操作', align: 'center', formatter: function(value, row, index) {
var actions = [];
actions.push('<a class="btn btn-success btn-xs" href="javascript:void(0)" onclick="viewInfo(\''+row.key+'\')"><i class="fa fa-edit"></i>查看</a> ');
actions.push('<a class="btn btn-danger btn-xs" href="javascript:void(0)" onclick="deleteCache(\''+row.key+'\')"><i class="fa fa-remove"></i>删除</a>');
return actions.join('');
}
}]
};
$.table.init(options);
});
var deleteCache=function(key){
var url=prefix+"/removeCacheByKey"
var data={key:key};
$.operate.submit(url, "post", "json", data);
}
function viewInfo(key){
var url=prefix+"/viewCacheInfoByKey?key="+key;
var options = {
title: "查看详细信息",
url: url,
skin: 'layui-layer-gray',
btn: ['关闭'],
yes: function (index, layero) {
layer.close(index);
}
};
$.modal.openOptions(options);
}
</script>
</body>
</html>

View File

@ -0,0 +1,24 @@
<!DOCTYPE html>
<html lang="zh" xmlns:th="http://www.thymeleaf.org" >
<head>
<th:block th:include="include :: header('查看缓存信息')" />
</head>
<body class="white-bg">
<div class="wrapper wrapper-content animated fadeInRight ibox-content">
<form class="form-horizontal m" id="form-config-edit">
<div class="form-group">
<label class="col-sm-3 control-label">KEY</label>
<div class="form-control-static" th:text="${info.key}">
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label">值:</label>
<div class="form-control-static" th:text="${info.value}">
</div>
</div>
</form>
</div>
<th:block th:include="include :: footer" />
</body>
</html>