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 5 import cn.iocoder.yudao.framework.redis.core.RedisKeyRegistry;
6 6 import cn.iocoder.yudao.module.infra.controller.admin.redis.vo.RedisKeyRespVO;
7 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 9 import cn.iocoder.yudao.module.infra.convert.redis.RedisConvert;
9 10 import io.swagger.annotations.Api;
10 11 import io.swagger.annotations.ApiOperation;
... ... @@ -12,13 +13,10 @@ import org.springframework.data.redis.connection.RedisServerCommands;
12 13 import org.springframework.data.redis.core.RedisCallback;
13 14 import org.springframework.data.redis.core.StringRedisTemplate;
14 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 18 import javax.annotation.Resource;
20   -import java.util.List;
21   -import java.util.Properties;
  19 +import java.util.*;
22 20  
23 21 import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
24 22  
... ... @@ -52,4 +50,42 @@ public class RedisController {
52 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 8 })
9 9 }
10 10  
11   -// TODO
  11 +// 获取模块
12 12 export function getKeyList() {
13 13 return request({
14 14 url: '/infra/redis/get-key-list',
15 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 67 </el-row>
68 68  
69 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 75 <el-table-column prop="keyTemplate" label="Key 模板" width="200" />
75 76 <el-table-column prop="keyType" label="Key 类型" width="100" />
76 77 <el-table-column prop="valueType" label="Value 类型" />
77 78 <el-table-column prop="timeoutType" label="超时时间" width="200">
78 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 87 </template>
82 88 </el-table-column>
83 89 <el-table-column prop="memo" label="备注" />
84 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 188 </template>
88 189  
89 190 <script>
90   -import { getCache, getKeyList } from "@/api/infra/redis";
  191 +import { getCache, getKeyList, getKeyDefineKeys, getKeyValue, clearCacheKey } from "@/api/infra/redis";
91 192 import echarts from "echarts";
92 193  
93 194 export default {
94 195 name: "Server",
95   - data() {
  196 + data () {
96 197 return {
97 198 // 统计命令信息
98 199 commandstats: null,
... ... @@ -103,15 +204,20 @@ export default {
103 204 // key 列表
104 205 keyListLoad: true,
105 206 keyList: [],
  207 + // 模块弹出框
  208 + open: false,
  209 + keyTemplate: "",
  210 + cachekeys: [],
  211 + cacheForm: {}
106 212 };
107 213 },
108   - created() {
  214 + created () {
109 215 this.getList();
110 216 this.openLoading();
111 217 },
112 218 methods: {
113 219 /** 查缓存询信息 */
114   - getList() {
  220 + getList () {
115 221 // 查询 Redis 监控信息
116 222 getCache().then((response) => {
117 223 this.cache = response.data;
... ... @@ -174,10 +280,55 @@ export default {
174 280 this.keyListLoad = false;
175 281 });
176 282 },
  283 +
177 284 // 打开加载层
178   - openLoading() {
  285 + openLoading () {
179 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 334 </script>
... ...