Commit 40954e4e4661449bda0108141294ab8691091183

Authored by luowenfeng
1 parent 15ee097a

feature(Redis监控): 添加缓存列表

yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/redis/RedisController.java
@@ -5,6 +5,7 @@ import cn.iocoder.yudao.framework.redis.core.RedisKeyDefine; @@ -5,6 +5,7 @@ import cn.iocoder.yudao.framework.redis.core.RedisKeyDefine;
5 import cn.iocoder.yudao.framework.redis.core.RedisKeyRegistry; 5 import cn.iocoder.yudao.framework.redis.core.RedisKeyRegistry;
6 import cn.iocoder.yudao.module.infra.controller.admin.redis.vo.RedisKeyRespVO; 6 import cn.iocoder.yudao.module.infra.controller.admin.redis.vo.RedisKeyRespVO;
7 import cn.iocoder.yudao.module.infra.controller.admin.redis.vo.RedisMonitorRespVO; 7 import cn.iocoder.yudao.module.infra.controller.admin.redis.vo.RedisMonitorRespVO;
  8 +import cn.iocoder.yudao.module.infra.controller.admin.redis.vo.RedisValuesRespVO;
8 import cn.iocoder.yudao.module.infra.convert.redis.RedisConvert; 9 import cn.iocoder.yudao.module.infra.convert.redis.RedisConvert;
9 import io.swagger.annotations.Api; 10 import io.swagger.annotations.Api;
10 import io.swagger.annotations.ApiOperation; 11 import io.swagger.annotations.ApiOperation;
@@ -12,13 +13,10 @@ import org.springframework.data.redis.connection.RedisServerCommands; @@ -12,13 +13,10 @@ import org.springframework.data.redis.connection.RedisServerCommands;
12 import org.springframework.data.redis.core.RedisCallback; 13 import org.springframework.data.redis.core.RedisCallback;
13 import org.springframework.data.redis.core.StringRedisTemplate; 14 import org.springframework.data.redis.core.StringRedisTemplate;
14 import org.springframework.security.access.prepost.PreAuthorize; 15 import org.springframework.security.access.prepost.PreAuthorize;
15 -import org.springframework.web.bind.annotation.GetMapping;  
16 -import org.springframework.web.bind.annotation.RequestMapping;  
17 -import org.springframework.web.bind.annotation.RestController; 16 +import org.springframework.web.bind.annotation.*;
18 17
19 import javax.annotation.Resource; 18 import javax.annotation.Resource;
20 -import java.util.List;  
21 -import java.util.Properties; 19 +import java.util.*;
22 20
23 import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; 21 import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
24 22
@@ -52,4 +50,42 @@ public class RedisController { @@ -52,4 +50,42 @@ public class RedisController {
52 return success(RedisConvert.INSTANCE.convertList(keyDefines)); 50 return success(RedisConvert.INSTANCE.convertList(keyDefines));
53 } 51 }
54 52
  53 + @GetMapping("/get-key/{keyDefine}")
  54 + @ApiOperation("获得 Redis Key")
  55 +// @PreAuthorize("@ss.hasPermission('infra:redis:get-key-list')")
  56 + public CommonResult<Set<String>> getKeyDefineKeys(@PathVariable("keyDefine") String keyDefine) {
  57 + Set<String> Keys = stringRedisTemplate.keys(keyDefine + "*");
  58 + return success(Keys);
  59 + }
  60 +
  61 + @DeleteMapping("/clear-key/{keyDefine}")
  62 + @ApiOperation("获得 Redis Key")
  63 +// @PreAuthorize("@ss.hasPermission('infra:redis:get-key-list')")
  64 + public CommonResult<Boolean> clearKeyDefineKeys(@PathVariable("keyDefine") String keyDefine) {
  65 + stringRedisTemplate.delete(Objects.requireNonNull(stringRedisTemplate.keys(keyDefine + "*")));
  66 + return success(Boolean.TRUE);
  67 + }
  68 +
  69 +// @PreAuthorize("@ss.hasPermi('monitor:cache:list')")
  70 + @GetMapping("/get-key/{cacheName}/{cacheKey}")
  71 + public CommonResult<RedisValuesRespVO> getKeyValue(@PathVariable("cacheName") String cacheName, @PathVariable("cacheKey") String cacheKey) {
  72 + String cacheValue = stringRedisTemplate.opsForValue().get(cacheKey);
  73 + return success(new RedisValuesRespVO(cacheName, cacheKey, cacheValue));
  74 + }
  75 +
  76 +// @PreAuthorize("@ss.hasPermi('monitor:cache:list')")
  77 + @DeleteMapping("/clearCacheKey/{cacheKey}")
  78 + public CommonResult<Boolean> clearCacheKey(@PathVariable String cacheKey) {
  79 + stringRedisTemplate.delete(cacheKey);
  80 + return success(Boolean.TRUE);
  81 + }
  82 +
  83 +// @PreAuthorize("@ss.hasPermi('monitor:cache:list')")
  84 + @DeleteMapping("/clearCacheAll")
  85 + public CommonResult<Boolean> clearCacheAll() {
  86 + Collection<String> cacheKeys = stringRedisTemplate.keys("*");
  87 + stringRedisTemplate.delete(cacheKeys);
  88 + return success(Boolean.TRUE);
  89 + }
  90 +
55 } 91 }
yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/redis/vo/RedisValuesRespVO.java 0 → 100644
  1 +package cn.iocoder.yudao.module.infra.controller.admin.redis.vo;
  2 +
  3 +import io.swagger.annotations.ApiModel;
  4 +import io.swagger.annotations.ApiModelProperty;
  5 +import lombok.Builder;
  6 +import lombok.Data;
  7 +import org.apache.commons.lang3.StringUtils;
  8 +
  9 +@ApiModel("管理后台 - Redis Key Value onse VO")
  10 +@Data
  11 +@Builder
  12 +public class RedisValuesRespVO {
  13 +
  14 + @ApiModelProperty(value = "oauth2_access_token:%s", required = true, example = "String")
  15 + private String keyTemplate;
  16 +
  17 + @ApiModelProperty(value = "c5f6990767804a928f4bb96ca249febf", required = true, example = "String")
  18 + private String key;
  19 +
  20 + @ApiModelProperty(required = true, example = "String")
  21 + private String value;
  22 +
  23 + public RedisValuesRespVO(String keyTemplate, String key, String value){
  24 + this.keyTemplate = StringUtils.replace(keyTemplate, ":", "");
  25 + this.key = StringUtils.replace(key, keyTemplate, "");
  26 + this.value = value;
  27 + }
  28 +
  29 +
  30 +}
yudao-ui-admin/src/api/infra/redis.js
@@ -8,10 +8,35 @@ export function getCache() { @@ -8,10 +8,35 @@ export function getCache() {
8 }) 8 })
9 } 9 }
10 10
11 -// TODO 11 +// 获取模块
12 export function getKeyList() { 12 export function getKeyList() {
13 return request({ 13 return request({
14 url: '/infra/redis/get-key-list', 14 url: '/infra/redis/get-key-list',
15 method: 'get' 15 method: 'get'
16 }) 16 })
17 } 17 }
  18 +
  19 +// 获取键名列表
  20 +export function getKeyDefineKeys(keyDefine) {
  21 + return request({
  22 + url: '/infra/redis/get-key/' + keyDefine,
  23 + method: 'get'
  24 + })
  25 +}
  26 +
  27 +// 获取缓存内容
  28 +export function getKeyValue(keyDefine, key) {
  29 + return request({
  30 + url: '/infra/redis/get-key/' + keyDefine + "/" + key,
  31 + method: 'get'
  32 + })
  33 +}
  34 +
  35 +// 根据键名删除缓存
  36 +export function clearCacheKey(key) {
  37 + return request({
  38 + url: '/infra/redis/clearCacheKey/' + key,
  39 + method: 'delete'
  40 + })
  41 +}
  42 +
yudao-ui-admin/src/views/infra/redis/index.vue
@@ -67,32 +67,133 @@ @@ -67,32 +67,133 @@
67 </el-row> 67 </el-row>
68 68
69 <el-table 69 <el-table
70 - v-loading="keyListLoad"  
71 - :data="keyList"  
72 - row-key="id" 70 + v-loading="keyListLoad"
  71 + :data="keyList"
  72 + row-key="id"
  73 + @row-click="openCacheInfo"
73 > 74 >
74 <el-table-column prop="keyTemplate" label="Key 模板" width="200" /> 75 <el-table-column prop="keyTemplate" label="Key 模板" width="200" />
75 <el-table-column prop="keyType" label="Key 类型" width="100" /> 76 <el-table-column prop="keyType" label="Key 类型" width="100" />
76 <el-table-column prop="valueType" label="Value 类型" /> 77 <el-table-column prop="valueType" label="Value 类型" />
77 <el-table-column prop="timeoutType" label="超时时间" width="200"> 78 <el-table-column prop="timeoutType" label="超时时间" width="200">
78 <template slot-scope="scope"> 79 <template slot-scope="scope">
79 - <dict-tag :type="DICT_TYPE.INFRA_REDIS_TIMEOUT_TYPE" :value="scope.row.timeoutType" />  
80 - <span v-if="scope.row.timeout > 0">({{ scope.row.timeout / 1000 }} 秒)</span> 80 + <dict-tag
  81 + :type="DICT_TYPE.INFRA_REDIS_TIMEOUT_TYPE"
  82 + :value="scope.row.timeoutType"
  83 + />
  84 + <span v-if="scope.row.timeout > 0"
  85 + >({{ scope.row.timeout / 1000 }} 秒)</span
  86 + >
81 </template> 87 </template>
82 </el-table-column> 88 </el-table-column>
83 <el-table-column prop="memo" label="备注" /> 89 <el-table-column prop="memo" label="备注" />
84 </el-table> 90 </el-table>
85 - </div>  
86 91
  92 + <!-- 缓存模块信息框 -->
  93 + <el-dialog
  94 + :title="keyTemplate + '模块'"
  95 + :visible.sync="open"
  96 + width="50vw"
  97 + append-to-body
  98 + >
  99 + <el-row :gutter="10">
  100 + <el-col :span="10" class="card-box">
  101 + <el-card style="height: 70vh">
  102 + <div slot="header">
  103 + <span>键名列表</span>
  104 + <el-button
  105 + style="float: right; padding: 3px 0"
  106 + type="text"
  107 + icon="el-icon-refresh-right"
  108 + @click="refreshCacheKeys"
  109 + ></el-button>
  110 + </div>
  111 + <el-table
  112 + :data="cachekeys"
  113 + style="width: 100%"
  114 + @row-click="handleCacheValue"
  115 + >
  116 + <el-table-column
  117 + label="序号"
  118 + width="60"
  119 + type="index"
  120 + ></el-table-column>
  121 + <el-table-column
  122 + label="缓存键名"
  123 + align="center"
  124 + :show-overflow-tooltip="true"
  125 + :formatter="keyFormatter"
  126 + >
  127 + </el-table-column>
  128 + <el-table-column
  129 + label="操作"
  130 + width="60"
  131 + align="center"
  132 + class-name="small-padding fixed-width"
  133 + >
  134 + <template slot-scope="scope">
  135 + <el-button
  136 + size="mini"
  137 + type="text"
  138 + icon="el-icon-delete"
  139 + @click="handleClearCacheKey(scope.row)"
  140 + ></el-button>
  141 + </template>
  142 + </el-table-column>
  143 + </el-table>
  144 + </el-card>
  145 + </el-col>
  146 +
  147 + <el-col :span="14">
  148 + <el-card :bordered="false" style="height: 70vh">
  149 + <div slot="header">
  150 + <span>缓存内容</span>
  151 + <!-- <el-button
  152 + style="float: right; padding: 3px 0"
  153 + type="text"
  154 + icon="el-icon-refresh-right"
  155 + @click="handleClearCacheAll()"
  156 + >清理全部</el-button>
  157 + -->
  158 + </div>
  159 + <el-form :model="cacheForm">
  160 + <el-row :gutter="32">
  161 + <el-col :offset="1" :span="22">
  162 + <el-form-item label="缓存名称:" prop="keyTemplate">
  163 + <el-input v-model="cacheForm.keyTemplate" :readOnly="true" />
  164 + </el-form-item>
  165 + </el-col>
  166 + <el-col :offset="1" :span="22">
  167 + <el-form-item label="缓存键名:" prop="key">
  168 + <el-input v-model="cacheForm.key" :readOnly="true" />
  169 + </el-form-item>
  170 + </el-col>
  171 + <el-col :offset="1" :span="22">
  172 + <el-form-item label="缓存内容:" prop="value">
  173 + <el-input
  174 + v-model="cacheForm.value"
  175 + type="textarea"
  176 + :rows="12"
  177 + :readOnly="true"
  178 + />
  179 + </el-form-item>
  180 + </el-col>
  181 + </el-row>
  182 + </el-form>
  183 + </el-card>
  184 + </el-col>
  185 + </el-row>
  186 + </el-dialog>
  187 + </div>
87 </template> 188 </template>
88 189
89 <script> 190 <script>
90 -import { getCache, getKeyList } from "@/api/infra/redis"; 191 +import { getCache, getKeyList, getKeyDefineKeys, getKeyValue, clearCacheKey } from "@/api/infra/redis";
91 import echarts from "echarts"; 192 import echarts from "echarts";
92 193
93 export default { 194 export default {
94 name: "Server", 195 name: "Server",
95 - data() { 196 + data () {
96 return { 197 return {
97 // 统计命令信息 198 // 统计命令信息
98 commandstats: null, 199 commandstats: null,
@@ -103,15 +204,20 @@ export default { @@ -103,15 +204,20 @@ export default {
103 // key 列表 204 // key 列表
104 keyListLoad: true, 205 keyListLoad: true,
105 keyList: [], 206 keyList: [],
  207 + // 模块弹出框
  208 + open: false,
  209 + keyTemplate: "",
  210 + cachekeys: [],
  211 + cacheForm: {}
106 }; 212 };
107 }, 213 },
108 - created() { 214 + created () {
109 this.getList(); 215 this.getList();
110 this.openLoading(); 216 this.openLoading();
111 }, 217 },
112 methods: { 218 methods: {
113 /** 查缓存询信息 */ 219 /** 查缓存询信息 */
114 - getList() { 220 + getList () {
115 // 查询 Redis 监控信息 221 // 查询 Redis 监控信息
116 getCache().then((response) => { 222 getCache().then((response) => {
117 this.cache = response.data; 223 this.cache = response.data;
@@ -174,10 +280,55 @@ export default { @@ -174,10 +280,55 @@ export default {
174 this.keyListLoad = false; 280 this.keyListLoad = false;
175 }); 281 });
176 }, 282 },
  283 +
177 // 打开加载层 284 // 打开加载层
178 - openLoading() { 285 + openLoading () {
179 this.$modal.loading("正在加载缓存监控数据,请稍后!"); 286 this.$modal.loading("正在加载缓存监控数据,请稍后!");
180 }, 287 },
  288 +
  289 + // 打开缓存弹窗
  290 + openCacheInfo (e) {
  291 + this.open = true;
  292 + let keyDefine = e.keyTemplate.substring(0, e.keyTemplate.length - 2);
  293 + this.keyTemplate = keyDefine;
  294 + // 加载键名列表
  295 + this.handleCacheKeys(keyDefine);
  296 + },
  297 +
  298 + /** 键名前缀去除 */
  299 + keyFormatter (cacheKey) {
  300 + return cacheKey.replace(this.keyTemplate, "");
  301 + },
  302 +
  303 + // 获取键名列表
  304 + handleCacheKeys (keyDefine){
  305 + const cacheName = keyDefine !== undefined ? keyDefine : this.keyTemplate;
  306 + getKeyDefineKeys(cacheName).then(response => {
  307 + this.cachekeys = response.data
  308 + this.cacheForm = {}
  309 + })
  310 + },
  311 +
  312 + // 获取缓存值
  313 + handleCacheValue (e){
  314 + getKeyValue(this.keyTemplate, e).then(response => {
  315 + this.cacheForm = response.data
  316 + })
  317 + },
  318 +
  319 + // 刷新键名列表
  320 + refreshCacheKeys(){
  321 + this.$modal.msgSuccess("刷新键名列表成功");
  322 + this.handleCacheKeys();
  323 + },
  324 +
  325 + // 删除缓存
  326 + handleClearCacheKey(key){
  327 + clearCacheKey(key).then(response =>{
  328 + this.$modal.msgSuccess("清理缓存键名[" + key + "]成功");
  329 + this.handleCacheKeys();
  330 + })
  331 + },
181 }, 332 },
182 }; 333 };
183 </script> 334 </script>