mirror of
				https://gitee.com/hhyykk/ipms-sjy.git
				synced 2025-10-30 09:48:43 +08:00 
			
		
		
		
	!211 Redis 监控添加缓存列表
Merge pull request !211 from 圆梦巨人/feature/cache-list
This commit is contained in:
		| @@ -4,21 +4,25 @@ import cn.iocoder.yudao.framework.common.pojo.CommonResult; | |||||||
| import cn.iocoder.yudao.framework.redis.core.RedisKeyDefine; | import cn.iocoder.yudao.framework.redis.core.RedisKeyDefine; | ||||||
| import cn.iocoder.yudao.framework.redis.core.RedisKeyRegistry; | import cn.iocoder.yudao.framework.redis.core.RedisKeyRegistry; | ||||||
| import cn.iocoder.yudao.module.infra.controller.admin.redis.vo.RedisKeyRespVO; | import cn.iocoder.yudao.module.infra.controller.admin.redis.vo.RedisKeyRespVO; | ||||||
|  | import cn.iocoder.yudao.module.infra.controller.admin.redis.vo.RedisKeyValueRespVO; | ||||||
| import cn.iocoder.yudao.module.infra.controller.admin.redis.vo.RedisMonitorRespVO; | import cn.iocoder.yudao.module.infra.controller.admin.redis.vo.RedisMonitorRespVO; | ||||||
| import cn.iocoder.yudao.module.infra.convert.redis.RedisConvert; | import cn.iocoder.yudao.module.infra.convert.redis.RedisConvert; | ||||||
| import io.swagger.annotations.Api; | import io.swagger.annotations.Api; | ||||||
| import io.swagger.annotations.ApiOperation; | import io.swagger.annotations.ApiOperation; | ||||||
| import org.springframework.data.redis.connection.RedisServerCommands; | import org.springframework.data.redis.connection.RedisServerCommands; | ||||||
|  | import org.springframework.data.redis.core.Cursor; | ||||||
| import org.springframework.data.redis.core.RedisCallback; | import org.springframework.data.redis.core.RedisCallback; | ||||||
|  | import org.springframework.data.redis.core.ScanOptions; | ||||||
| import org.springframework.data.redis.core.StringRedisTemplate; | import org.springframework.data.redis.core.StringRedisTemplate; | ||||||
| import org.springframework.security.access.prepost.PreAuthorize; | import org.springframework.security.access.prepost.PreAuthorize; | ||||||
| import org.springframework.web.bind.annotation.GetMapping; | import org.springframework.web.bind.annotation.*; | ||||||
| import org.springframework.web.bind.annotation.RequestMapping; |  | ||||||
| import org.springframework.web.bind.annotation.RestController; |  | ||||||
|  |  | ||||||
| import javax.annotation.Resource; | import javax.annotation.Resource; | ||||||
|  | import java.nio.charset.StandardCharsets; | ||||||
|  | import java.util.HashSet; | ||||||
| import java.util.List; | import java.util.List; | ||||||
| import java.util.Properties; | import java.util.Properties; | ||||||
|  | import java.util.Set; | ||||||
|  |  | ||||||
| import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; | import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; | ||||||
|  |  | ||||||
| @@ -45,11 +49,68 @@ public class RedisController { | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     @GetMapping("/get-key-list") |     @GetMapping("/get-key-list") | ||||||
|     @ApiOperation("获得 Redis Key 列表") |     @ApiOperation("获得 Redis Key 模板列表") | ||||||
|     @PreAuthorize("@ss.hasPermission('infra:redis:get-key-list')") |     @PreAuthorize("@ss.hasPermission('infra:redis:get-key-list')") | ||||||
|     public CommonResult<List<RedisKeyRespVO>> getKeyList() { |     public CommonResult<List<RedisKeyRespVO>> getKeyList() { | ||||||
|         List<RedisKeyDefine> keyDefines = RedisKeyRegistry.list(); |         List<RedisKeyDefine> keyDefines = RedisKeyRegistry.list(); | ||||||
|         return success(RedisConvert.INSTANCE.convertList(keyDefines)); |         return success(RedisConvert.INSTANCE.convertList(keyDefines)); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     @GetMapping("/get-key-Defines") | ||||||
|  |     @ApiOperation("获得 Redis keys 键名列表") | ||||||
|  |     @PreAuthorize("@ss.hasPermission('infra:redis:get-key-list')") | ||||||
|  |     public CommonResult<Set<String>> getKeyDefines(@RequestParam("keyDefine") String keyDefine) { | ||||||
|  |         Set<String> keys = new HashSet<>(); | ||||||
|  |          stringRedisTemplate.execute((RedisCallback<Set<String>>) connection -> { | ||||||
|  |             try (Cursor<byte[]> cursor = connection.scan(ScanOptions.scanOptions() | ||||||
|  |                     .match(keyDefine + "*") | ||||||
|  |                     .count(Integer.MAX_VALUE).build())) { | ||||||
|  |                 while (cursor.hasNext()) { | ||||||
|  |                     keys.add(new String(cursor.next(), StandardCharsets.UTF_8)); | ||||||
|  |                 } | ||||||
|  |             } catch (Exception e) { | ||||||
|  |                 throw new RuntimeException(e); | ||||||
|  |             } | ||||||
|  |             return keys; | ||||||
|  |         }); | ||||||
|  |         return success(keys); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     @DeleteMapping("/delete-key-defines") | ||||||
|  |     @ApiOperation("删除 Redis Key 根据模板") | ||||||
|  |     @PreAuthorize("@ss.hasPermission('infra:redis:get-key-list')") | ||||||
|  |     public CommonResult<Boolean> deleteKeyDefines(@RequestParam("keyDefine") String keyDefine) { | ||||||
|  |         Set<String> keys = stringRedisTemplate.keys(keyDefine + "*"); | ||||||
|  |         if(keys != null && keys.isEmpty()){ | ||||||
|  |              stringRedisTemplate.delete(keys); | ||||||
|  |         } | ||||||
|  |         return success(Boolean.TRUE); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     @GetMapping("/get-key-value") | ||||||
|  |     @ApiOperation("获得 Redis key 内容") | ||||||
|  |     @PreAuthorize("@ss.hasPermission('infra:redis:get-key-list')") | ||||||
|  |     public CommonResult<RedisKeyValueRespVO> getKeyValue(@RequestParam("keyDefine") String keyDefine, @RequestParam("cacheKey") String cacheKey) { | ||||||
|  |         String cacheValue = stringRedisTemplate.opsForValue().get(cacheKey); | ||||||
|  |         return success(RedisKeyValueRespVO.of(keyDefine, cacheKey, cacheValue)); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     @DeleteMapping("/delete-key-value") | ||||||
|  |     @ApiOperation("删除 Redis Key 根据key") | ||||||
|  |     @PreAuthorize("@ss.hasPermission('infra:redis:get-key-list')") | ||||||
|  |     public CommonResult<Boolean> deleteKeyValue(@RequestParam("cacheKey") String cacheKey) { | ||||||
|  |         stringRedisTemplate.delete(cacheKey); | ||||||
|  |         return success(Boolean.TRUE); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     @DeleteMapping("/delete-cache-all") | ||||||
|  |     @ApiOperation(value="删除 所有缓存", notes="不使用该接口") | ||||||
|  |     @PreAuthorize("@ss.hasPermission('infra:redis:get-key-list')") | ||||||
|  |     public CommonResult<Boolean> deleteCacheAll() { | ||||||
|  |         return success(stringRedisTemplate.execute((RedisCallback<Boolean>) connection -> { | ||||||
|  |             connection.flushAll(); | ||||||
|  |             return Boolean.TRUE; | ||||||
|  |         })); | ||||||
|  |     } | ||||||
|  |  | ||||||
| } | } | ||||||
|   | |||||||
| @@ -0,0 +1,34 @@ | |||||||
|  | package cn.iocoder.yudao.module.infra.controller.admin.redis.vo; | ||||||
|  |  | ||||||
|  | import io.swagger.annotations.ApiModel; | ||||||
|  | import io.swagger.annotations.ApiModelProperty; | ||||||
|  | import lombok.AllArgsConstructor; | ||||||
|  | import lombok.Builder; | ||||||
|  | import lombok.Data; | ||||||
|  | import org.apache.commons.lang3.StringUtils; | ||||||
|  |  | ||||||
|  | @ApiModel("管理后台 - Redis Key Value onse VO") | ||||||
|  | @Data | ||||||
|  | @Builder | ||||||
|  | @AllArgsConstructor | ||||||
|  | public class RedisKeyValueRespVO { | ||||||
|  |  | ||||||
|  |     @ApiModelProperty(value = "oauth2_access_token:%s", required = true, example = "String") | ||||||
|  |     private String keyTemplate; | ||||||
|  |  | ||||||
|  |     @ApiModelProperty(value = "c5f6990767804a928f4bb96ca249febf", required = true, example = "String") | ||||||
|  |     private String key; | ||||||
|  |  | ||||||
|  |     @ApiModelProperty(required = true, example = "String") | ||||||
|  |     private String value; | ||||||
|  |  | ||||||
|  |     public static RedisKeyValueRespVO of(String keyTemplate, String key, String value){ | ||||||
|  |         return RedisKeyValueRespVO.builder() | ||||||
|  |                 .keyTemplate(StringUtils.replace(keyTemplate, ":", "")) | ||||||
|  |                 .key(StringUtils.replace(key, keyTemplate, "")) | ||||||
|  |                 .value(value) | ||||||
|  |                 .build(); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |  | ||||||
|  | } | ||||||
| @@ -8,10 +8,35 @@ export function getCache() { | |||||||
|   }) |   }) | ||||||
| } | } | ||||||
|  |  | ||||||
| // TODO | // 获取模块 | ||||||
| export function getKeyList() { | export function getKeyList() { | ||||||
|   return request({ |   return request({ | ||||||
|     url: '/infra/redis/get-key-list', |     url: '/infra/redis/get-key-list', | ||||||
|     method: 'get' |     method: 'get' | ||||||
|   }) |   }) | ||||||
| } | } | ||||||
|  |  | ||||||
|  | // 获取键名列表 | ||||||
|  | export function getKeyDefines(keyDefine) { | ||||||
|  |   return request({ | ||||||
|  |     url: '/infra/redis/get-key-Defines?keyDefine=' + keyDefine, | ||||||
|  |     method: 'get' | ||||||
|  |   }) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // 获取缓存内容 | ||||||
|  | export function getKeyValue(keyDefine, key) { | ||||||
|  |   return request({ | ||||||
|  |     url: '/infra/redis/get-key-value?keyDefine=' + keyDefine + "&cacheKey=" + key, | ||||||
|  |     method: 'get' | ||||||
|  |   }) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // 根据键名删除缓存 | ||||||
|  | export function deleteKeyValue(key) { | ||||||
|  |   return request({ | ||||||
|  |     url: '/infra/redis/delete-key-value?cacheKey=' + key, | ||||||
|  |     method: 'delete' | ||||||
|  |   }) | ||||||
|  | } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -70,29 +70,130 @@ | |||||||
|       v-loading="keyListLoad" |       v-loading="keyListLoad" | ||||||
|       :data="keyList" |       :data="keyList" | ||||||
|       row-key="id" |       row-key="id" | ||||||
|  |       @row-click="openCacheInfo" | ||||||
|     > |     > | ||||||
|       <el-table-column prop="keyTemplate" label="Key 模板" width="200" /> |       <el-table-column prop="keyTemplate" label="Key 模板" width="200" /> | ||||||
|       <el-table-column prop="keyType" label="Key 类型" width="100" /> |       <el-table-column prop="keyType" label="Key 类型" width="100" /> | ||||||
|       <el-table-column prop="valueType" label="Value 类型" /> |       <el-table-column prop="valueType" label="Value 类型" /> | ||||||
|       <el-table-column prop="timeoutType" label="超时时间" width="200"> |       <el-table-column prop="timeoutType" label="超时时间" width="200"> | ||||||
|         <template slot-scope="scope"> |         <template slot-scope="scope"> | ||||||
|           <dict-tag :type="DICT_TYPE.INFRA_REDIS_TIMEOUT_TYPE" :value="scope.row.timeoutType" /> |           <dict-tag | ||||||
|           <span v-if="scope.row.timeout > 0">({{ scope.row.timeout / 1000 }} 秒)</span> |             :type="DICT_TYPE.INFRA_REDIS_TIMEOUT_TYPE" | ||||||
|  |             :value="scope.row.timeoutType" | ||||||
|  |           /> | ||||||
|  |           <span v-if="scope.row.timeout > 0" | ||||||
|  |             >({{ scope.row.timeout / 1000 }} 秒)</span | ||||||
|  |           > | ||||||
|         </template> |         </template> | ||||||
|       </el-table-column> |       </el-table-column> | ||||||
|       <el-table-column prop="memo" label="备注" /> |       <el-table-column prop="memo" label="备注" /> | ||||||
|     </el-table> |     </el-table> | ||||||
|   </div> |  | ||||||
|  |  | ||||||
|  |     <!-- 缓存模块信息框 --> | ||||||
|  |     <el-dialog | ||||||
|  |       :title="keyTemplate + '模块'" | ||||||
|  |       :visible.sync="open" | ||||||
|  |       width="60vw" | ||||||
|  |       append-to-body | ||||||
|  |     > | ||||||
|  |       <el-row :gutter="10"> | ||||||
|  |         <el-col :span="10" class="card-box"> | ||||||
|  |           <el-card style="height: 70vh"> | ||||||
|  |             <div slot="header"> | ||||||
|  |               <span>键名列表</span> | ||||||
|  |               <el-button | ||||||
|  |                 style="float: right; padding: 3px 0" | ||||||
|  |                 type="text" | ||||||
|  |                 icon="el-icon-refresh-right" | ||||||
|  |                 @click="refreshCacheKeys" | ||||||
|  |               ></el-button> | ||||||
|  |             </div> | ||||||
|  |             <el-table | ||||||
|  |                 :data="cachekeys" | ||||||
|  |                 style="width: 100%" | ||||||
|  |                 @row-click="handleCacheValue" | ||||||
|  |             > | ||||||
|  |               <el-table-column | ||||||
|  |                 label="序号" | ||||||
|  |                 width="60" | ||||||
|  |                 type="index" | ||||||
|  |               ></el-table-column> | ||||||
|  |               <el-table-column | ||||||
|  |                 label="缓存键名" | ||||||
|  |                 align="center" | ||||||
|  |                 :show-overflow-tooltip="true" | ||||||
|  |                 :formatter="keyFormatter" | ||||||
|  |               > | ||||||
|  |               </el-table-column> | ||||||
|  |               <el-table-column | ||||||
|  |                 label="操作" | ||||||
|  |                 width="60" | ||||||
|  |                 align="center" | ||||||
|  |                 class-name="small-padding fixed-width" | ||||||
|  |               > | ||||||
|  |                 <template slot-scope="scope"> | ||||||
|  |                   <el-button | ||||||
|  |                     size="mini" | ||||||
|  |                     type="text" | ||||||
|  |                     icon="el-icon-delete" | ||||||
|  |                     @click="handleClearCacheKey(scope.row)" | ||||||
|  |                   ></el-button> | ||||||
|  |                 </template> | ||||||
|  |               </el-table-column> | ||||||
|  |             </el-table> | ||||||
|  |           </el-card> | ||||||
|  |         </el-col> | ||||||
|  |  | ||||||
|  |         <el-col :span="14"> | ||||||
|  |           <el-card :bordered="false" style="height: 70vh"> | ||||||
|  |             <div slot="header"> | ||||||
|  |               <span>缓存内容</span> | ||||||
|  |               <!-- <el-button | ||||||
|  |                 style="float: right; padding: 3px 0" | ||||||
|  |                 type="text" | ||||||
|  |                 icon="el-icon-refresh-right" | ||||||
|  |                 @click="handleClearCacheAll()" | ||||||
|  |                 >清理全部</el-button> | ||||||
|  |                 --> | ||||||
|  |             </div> | ||||||
|  |           <el-form :model="cacheForm"> | ||||||
|  |             <el-row :gutter="32"> | ||||||
|  |               <el-col :offset="1" :span="22"> | ||||||
|  |                 <el-form-item label="缓存名称:" prop="keyTemplate"> | ||||||
|  |                   <el-input v-model="cacheForm.keyTemplate" :readOnly="true" /> | ||||||
|  |                 </el-form-item> | ||||||
|  |               </el-col> | ||||||
|  |               <el-col :offset="1" :span="22"> | ||||||
|  |                 <el-form-item label="缓存键名:" prop="key"> | ||||||
|  |                   <el-input v-model="cacheForm.key" :readOnly="true" /> | ||||||
|  |                 </el-form-item> | ||||||
|  |                 </el-col> | ||||||
|  |                 <el-col :offset="1" :span="22"> | ||||||
|  |                   <el-form-item label="缓存内容:" prop="value"> | ||||||
|  |                     <el-input | ||||||
|  |                       v-model="cacheForm.value" | ||||||
|  |                       type="textarea" | ||||||
|  |                       :rows="12" | ||||||
|  |                       :readOnly="true" | ||||||
|  |                     /> | ||||||
|  |                   </el-form-item> | ||||||
|  |                 </el-col> | ||||||
|  |               </el-row> | ||||||
|  |             </el-form> | ||||||
|  |           </el-card> | ||||||
|  |         </el-col> | ||||||
|  |       </el-row> | ||||||
|  |     </el-dialog> | ||||||
|  |   </div> | ||||||
| </template> | </template> | ||||||
|  |  | ||||||
| <script> | <script> | ||||||
| import { getCache, getKeyList } from "@/api/infra/redis"; | import { getCache, getKeyList, getKeyDefines, getKeyValue, deleteKeyValue } from "@/api/infra/redis"; | ||||||
| import echarts from "echarts"; | import echarts from "echarts"; | ||||||
|  |  | ||||||
| export default { | export default { | ||||||
|   name: "Server", |   name: "Server", | ||||||
|   data() { |   data () { | ||||||
|     return { |     return { | ||||||
|       // 统计命令信息 |       // 统计命令信息 | ||||||
|       commandstats: null, |       commandstats: null, | ||||||
| @@ -103,15 +204,20 @@ export default { | |||||||
|       // key 列表 |       // key 列表 | ||||||
|       keyListLoad: true, |       keyListLoad: true, | ||||||
|       keyList: [], |       keyList: [], | ||||||
|  |       // 模块弹出框 | ||||||
|  |       open: false, | ||||||
|  |       keyTemplate: "", | ||||||
|  |       cachekeys: [], | ||||||
|  |       cacheForm: {} | ||||||
|     }; |     }; | ||||||
|   }, |   }, | ||||||
|   created() { |   created () { | ||||||
|     this.getList(); |     this.getList(); | ||||||
|     this.openLoading(); |     this.openLoading(); | ||||||
|   }, |   }, | ||||||
|   methods: { |   methods: { | ||||||
|     /** 查缓存询信息 */ |     /** 查缓存询信息 */ | ||||||
|     getList() { |     getList () { | ||||||
|       // 查询 Redis 监控信息 |       // 查询 Redis 监控信息 | ||||||
|       getCache().then((response) => { |       getCache().then((response) => { | ||||||
|         this.cache = response.data; |         this.cache = response.data; | ||||||
| @@ -174,10 +280,55 @@ export default { | |||||||
|         this.keyListLoad = false; |         this.keyListLoad = false; | ||||||
|       }); |       }); | ||||||
|     }, |     }, | ||||||
|  |  | ||||||
|     // 打开加载层 |     // 打开加载层 | ||||||
|     openLoading() { |     openLoading () { | ||||||
|       this.$modal.loading("正在加载缓存监控数据,请稍后!"); |       this.$modal.loading("正在加载缓存监控数据,请稍后!"); | ||||||
|     }, |     }, | ||||||
|  |  | ||||||
|  |     // 打开缓存弹窗 | ||||||
|  |     openCacheInfo (e) { | ||||||
|  |       this.open = true; | ||||||
|  |       let keyDefine = e.keyTemplate.substring(0, e.keyTemplate.length - 2); | ||||||
|  |       this.keyTemplate = keyDefine; | ||||||
|  |       // 加载键名列表 | ||||||
|  |       this.handleCacheKeys(keyDefine); | ||||||
|  |     }, | ||||||
|  |  | ||||||
|  |     /** 键名前缀去除 */ | ||||||
|  |     keyFormatter (cacheKey) { | ||||||
|  |       return cacheKey.replace(this.keyTemplate, ""); | ||||||
|  |     }, | ||||||
|  |  | ||||||
|  |     // 获取键名列表 | ||||||
|  |     handleCacheKeys (keyDefine){ | ||||||
|  |       const cacheName = keyDefine !== undefined ? keyDefine : this.keyTemplate; | ||||||
|  |       getKeyDefines(cacheName).then(response => { | ||||||
|  |         this.cachekeys = response.data | ||||||
|  |         this.cacheForm = {} | ||||||
|  |       }) | ||||||
|  |     }, | ||||||
|  |  | ||||||
|  |     // 获取缓存值 | ||||||
|  |     handleCacheValue (e){ | ||||||
|  |       getKeyValue(this.keyTemplate, e).then(response => { | ||||||
|  |         this.cacheForm = response.data | ||||||
|  |       }) | ||||||
|  |     }, | ||||||
|  |  | ||||||
|  |     // 刷新键名列表 | ||||||
|  |     refreshCacheKeys(){ | ||||||
|  |       this.$modal.msgSuccess("刷新键名列表成功"); | ||||||
|  |       this.handleCacheKeys(); | ||||||
|  |     }, | ||||||
|  |  | ||||||
|  |     // 删除缓存 | ||||||
|  |     handleClearCacheKey(key){ | ||||||
|  |       deleteKeyValue(key).then(response =>{ | ||||||
|  |         this.$modal.msgSuccess("清理缓存键名[" + key + "]成功"); | ||||||
|  |         this.handleCacheKeys(); | ||||||
|  |       }) | ||||||
|  |     }, | ||||||
|   }, |   }, | ||||||
| }; | }; | ||||||
| </script> | </script> | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 芋道源码
					芋道源码