From cba2e9fba9f7fee2d54d454318e95f9d2fd0adc0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=83=91=E6=9D=B0?= Date: Sat, 22 Sep 2018 13:14:45 +0800 Subject: [PATCH] =?UTF-8?q?=E6=96=B0=E5=A2=9ERedis=E7=BB=88=E7=AB=AF?= =?UTF-8?q?=E7=AE=A1=E7=90=86=EF=BC=8C=E4=BF=AE=E5=A4=8D=E8=8F=9C=E5=8D=95?= =?UTF-8?q?=E7=AE=A1=E7=90=86=E5=88=A0=E9=99=A4=E5=A4=B1=E8=B4=A5=E7=9A=84?= =?UTF-8?q?BUG?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.MD | 20 +- pom.xml | 3 +- sql/aurora.sql | 16 +- .../app/rest/system/RedisController.java | 157 +++++++ .../me/aurora/config/redis/RedisConfig.java | 16 + .../java/me/aurora/domain/ResponseEntity.java | 7 + .../java/me/aurora/domain/UserOnline.java | 7 +- .../java/me/aurora/service/RedisService.java | 79 ++++ .../aurora/service/impl/MenuServiceImpl.java | 13 +- .../aurora/service/impl/RedisServiceImpl.java | 81 ++++ src/main/resources/sql/aurora.sql | 33 +- .../resources/static/js/redis/terminal.js | 382 ++++++++++++++++++ src/main/resources/templates/index.html | 3 + .../templates/system/redis/terminal.html | 25 ++ 14 files changed, 792 insertions(+), 50 deletions(-) create mode 100644 src/main/java/me/aurora/app/rest/system/RedisController.java create mode 100644 src/main/java/me/aurora/service/RedisService.java create mode 100644 src/main/java/me/aurora/service/impl/RedisServiceImpl.java create mode 100644 src/main/resources/static/js/redis/terminal.js create mode 100644 src/main/resources/templates/system/redis/terminal.html diff --git a/README.MD b/README.MD index 963a555..1ce8cd8 100644 --- a/README.MD +++ b/README.MD @@ -26,15 +26,15 @@ Aurora是一个简单高效的后台管理系统。项目基础框架采用全 │ ├─角色管理 │ └─权限管理 ├─系统监控 -│ ├─在线用户(开发中) +│ ├─Redis终端 +│ ├─在线用户 │ └─系统日志 -│─网络资源(开发中) -│ ├─ 开发中 -│ │ ├─散文 -│ │ ├─绘画 -│ │ └─语文 -│ ├─天气查询 -│ └─每日一文 +│─网络资源 +│ ├─天气查询(开发中) +│ └─图床管理 +│─第三方工具(开发中) +│ │-支付宝支付 +│ └─云储存 └─任务调度(开发中) ├─定时任务 └─调度日志 @@ -122,6 +122,10 @@ Aurora是一个简单高效的后台管理系统。项目基础框架采用全 ![](https://i.imgur.com/G3MmlGy.png) +- Redis终端 + +![](https://i.imgur.com/TvKl5SH.png) + - sql日志打印使用log4jdbc+logback,效果如下 ![](https://i.imgur.com/R1xsFXk.jpg) diff --git a/pom.xml b/pom.xml index fa82a23..c2c7a28 100644 --- a/pom.xml +++ b/pom.xml @@ -126,7 +126,8 @@ org.springframework.boot spring-boot-starter-tomcat - provided + + compile diff --git a/sql/aurora.sql b/sql/aurora.sql index b4a568f..d01f84c 100644 --- a/sql/aurora.sql +++ b/sql/aurora.sql @@ -11,7 +11,7 @@ Target Server Version : 50559 File Encoding : 65001 - Date: 21/09/2018 16:47:46 + Date: 22/09/2018 13:06:32 */ SET NAMES utf8mb4; @@ -34,7 +34,7 @@ CREATE TABLE `zj_menu` ( `level_number` int(11) NOT NULL, PRIMARY KEY (`id`) USING BTREE, UNIQUE INDEX `UK_cbhg0bi3f1emxkhqqtvca9btx`(`soft`) USING BTREE -) ENGINE = InnoDB AUTO_INCREMENT = 15 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Compact; +) ENGINE = InnoDB AUTO_INCREMENT = 17 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Compact; -- ---------------------------- -- Records of zj_menu @@ -43,16 +43,17 @@ INSERT INTO `zj_menu` VALUES (1, 'layui-icon-unlink', 0, 1, '异常页', 40, '', INSERT INTO `zj_menu` VALUES (2, 'layui-icon-tree', 1, 2, '403', 41, '/exception/403', '2018-08-29 11:40:17', '2018-09-20 11:36:24', 0); INSERT INTO `zj_menu` VALUES (3, 'layui-icon-tree', 1, 2, '404', 42, '/exception/404', '2018-08-29 11:40:17', '2018-09-20 11:36:32', 0); INSERT INTO `zj_menu` VALUES (4, 'layui-icon-tree', 1, 2, '500', 43, '/exception/500', '2018-08-29 11:40:17', '2018-09-20 11:36:40', 0); -INSERT INTO `zj_menu` VALUES (5, 'layui-icon-chart', 0, 1, '系统监控', 10, '', '2018-08-29 11:40:17', '2018-09-21 16:09:38', 2); +INSERT INTO `zj_menu` VALUES (5, 'layui-icon-chart', 0, 1, '系统监控', 10, '', '2018-08-29 11:40:17', '2018-09-22 11:18:21', 4); INSERT INTO `zj_menu` VALUES (6, 'layui-icon-tree', 7, 2, '用户管理', 2, '/user/index', '2018-08-29 11:40:17', '2018-09-04 07:40:25', 0); INSERT INTO `zj_menu` VALUES (7, 'layui-icon-util', 0, 1, '系统管理', 1, '', '2018-08-29 11:40:17', '2018-09-20 19:02:05', 4); INSERT INTO `zj_menu` VALUES (8, 'layui-icon-tree', 7, 2, '菜单管理', 6, '/menu/index', '2018-08-29 11:40:17', '2018-09-04 07:40:25', 0); -INSERT INTO `zj_menu` VALUES (9, 'layui-icon-tree', 5, 2, '日志管理', 11, '/sysLog/index', '2018-08-29 11:40:17', '2018-09-04 07:40:25', 0); +INSERT INTO `zj_menu` VALUES (9, 'layui-icon-tree', 5, 2, '系统日志', 11, '/sysLog/index', '2018-08-29 11:40:17', '2018-09-22 10:17:02', 0); INSERT INTO `zj_menu` VALUES (10, 'layui-icon-tree', 7, 2, '权限管理', 4, '/permission/index', '2018-08-29 11:40:17', '2018-09-04 07:40:25', 0); INSERT INTO `zj_menu` VALUES (11, 'layui-icon-tree', 7, 2, '角色管理', 3, '/role/index', '2018-08-29 11:40:17', '2018-09-04 07:40:25', 0); INSERT INTO `zj_menu` VALUES (12, 'layui-icon-website', 0, 1, '网络资源', 30, '', '2018-09-20 11:35:56', '2018-09-20 11:40:53', 1); INSERT INTO `zj_menu` VALUES (13, 'layui-icon-tree', 12, 2, '图床管理', 31, '/picture/index', '2018-09-20 11:40:53', '2018-09-20 11:40:53', 0); -INSERT INTO `zj_menu` VALUES (14, 'layui-icon-tree', 5, 2, '在线用户管理', 12, '/online/index', '2018-09-21 16:09:38', '2018-09-21 16:09:38', 0); +INSERT INTO `zj_menu` VALUES (14, 'layui-icon-tree', 5, 2, '在线用户', 12, '/online/index', '2018-09-21 16:09:38', '2018-09-22 10:17:09', 0); +INSERT INTO `zj_menu` VALUES (16, 'layui-icon-tree', 5, 2, 'Redis终端', 14, '/redis/terminal', '2018-09-22 11:18:21', '2018-09-22 11:37:28', 0); -- ---------------------------- -- Table structure for zj_menus_roles @@ -84,6 +85,7 @@ INSERT INTO `zj_menus_roles` VALUES (11, 1); INSERT INTO `zj_menus_roles` VALUES (12, 1); INSERT INTO `zj_menus_roles` VALUES (13, 1); INSERT INTO `zj_menus_roles` VALUES (14, 1); +INSERT INTO `zj_menus_roles` VALUES (16, 1); INSERT INTO `zj_menus_roles` VALUES (1, 2); INSERT INTO `zj_menus_roles` VALUES (2, 2); INSERT INTO `zj_menus_roles` VALUES (3, 2); @@ -233,12 +235,12 @@ CREATE TABLE `zj_user` ( `username` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, PRIMARY KEY (`id`) USING BTREE, UNIQUE INDEX `UK_kpubos9gc2cvtkb0thktkbkes`(`email`) USING BTREE -) ENGINE = InnoDB AUTO_INCREMENT = 9 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Compact; +) ENGINE = InnoDB AUTO_INCREMENT = 2 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Compact; -- ---------------------------- -- Records of zj_user -- ---------------------------- -INSERT INTO `zj_user` VALUES (1, 'https://www.zhengjie.me/images/avatar.jpg', '2018-08-23 09:11:56', 'zhengjie@tom.com', 1, '2018-09-21 16:26:05', '65a674ce6632479005ea7a9071234cfb', 'aurora'); +INSERT INTO `zj_user` VALUES (1, 'https://www.zhengjie.me/images/avatar.jpg', '2018-08-23 09:11:56', 'zhengjie@tom.com', 1, '2018-09-22 13:00:04', '65a674ce6632479005ea7a9071234cfb', 'aurora'); -- ---------------------------- -- Table structure for zj_user_pictures diff --git a/src/main/java/me/aurora/app/rest/system/RedisController.java b/src/main/java/me/aurora/app/rest/system/RedisController.java new file mode 100644 index 0000000..ec3566f --- /dev/null +++ b/src/main/java/me/aurora/app/rest/system/RedisController.java @@ -0,0 +1,157 @@ +package me.aurora.app.rest.system; + +import me.aurora.annotation.Log; +import me.aurora.domain.ResponseEntity; +import me.aurora.service.RedisService; +import org.apache.shiro.authz.annotation.Logical; +import org.apache.shiro.authz.annotation.RequiresPermissions; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.ui.Model; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.servlet.ModelAndView; +import java.util.Set; + +/** + * @author 郑杰 + * @date 2018/09/22 10:48:11 + */ +@RestController +@RequestMapping("redis") +public class RedisController { + + private static final String INTEGER_PREFIX = "(integer)"; + + @Autowired + private RedisService redisService; + + @GetMapping("terminal") + @RequiresPermissions (value={"admin", "redis:all","redis:terminal"}, logical= Logical.OR) + public ModelAndView redisTerminal(Model model) { + String osName = System.getProperty("os.name"); + model.addAttribute("osName", osName); + return new ModelAndView("/system/redis/terminal"); + } + + @Log("执行Redis keys命令") + @RequestMapping("keys") + public ResponseEntity keys(String arg) { + try { + Set set = this.redisService.getKeys(arg); + return ResponseEntity.ok(set); + } catch (Exception e) { + return ResponseEntity.error(e.getMessage()); + } + } + + @Log("执行Redis get命令") + @GetMapping("get") + public ResponseEntity get(String arg) { + try { + String result = this.redisService.get(arg); + return ResponseEntity.ok(result == null ? "" : result); + } catch (Exception e) { + return ResponseEntity.error(e.getMessage()); + } + } + + @Log("执行Redis set命令") + @GetMapping("set") + public ResponseEntity set(String arg) { + try { + String[] args = arg.split(","); + if (args.length == 1){ + return ResponseEntity.error("(error) ERR wrong number of arguments for 'set' command"); + } else if(args.length != 2){ + return ResponseEntity.error("(error) ERR syntax error"); + } + String result = this.redisService.set(args[0], args[1]); + return ResponseEntity.ok(result); + } catch (Exception e) { + return ResponseEntity.error(e.getMessage()); + } + } + + @Log("执行Redis del命令") + @GetMapping("del") + public ResponseEntity del(String arg) { + try { + String[] args = arg.split(","); + Long result = this.redisService.del(args); + return ResponseEntity.ok(INTEGER_PREFIX + result); + } catch (Exception e) { + return ResponseEntity.error(e.getMessage()); + } + } + + @Log("执行Redis exists命令") + @GetMapping("exists") + public ResponseEntity exists(String arg) { + try { + int count = 0; + String[] arr = arg.split(","); + for (String key : arr) { + if (this.redisService.exists(key)){ + count++; + } + } + return ResponseEntity.ok(INTEGER_PREFIX + count); + } catch (Exception e) { + return ResponseEntity.error(e.getMessage()); + } + } + + @Log("执行Redis pttl命令") + @GetMapping("pttl") + public ResponseEntity pttl(String arg) { + try { + return ResponseEntity.ok(INTEGER_PREFIX + this.redisService.pttl(arg)); + } catch (Exception e) { + return ResponseEntity.error(e.getMessage()); + } + } + + @Log("执行Redis pexpire命令") + @GetMapping("pexpire") + public ResponseEntity pexpire(String arg) { + try { + String[] arr = arg.split(","); + if (arr.length != 2 || !isValidLong(arr[1])) { + return ResponseEntity.error("(error) ERR wrong number of arguments for 'pexpire' command"); + } + return ResponseEntity.ok(INTEGER_PREFIX + this.redisService.pexpire(arr[0], Long.valueOf(arr[1]))); + } catch (Exception e) { + return ResponseEntity.error(e.getMessage()); + } + } + + @Log("执行flushdb命令") + @GetMapping("flushdb") + public ResponseEntity flushdb() { + try { + return ResponseEntity.ok(INTEGER_PREFIX + this.redisService.flushdb()); + } catch (Exception e) { + return ResponseEntity.error(e.getMessage()); + } + } + + @Log("执行flushall命令") + @GetMapping("flushall") + public ResponseEntity flushall() { + try { + return ResponseEntity.ok(INTEGER_PREFIX + this.redisService.flushall()); + } catch (Exception e) { + return ResponseEntity.error(e.getMessage()); + } + } + + private static boolean isValidLong(String str) { + try { + Long.parseLong(str); + return true; + } catch (NumberFormatException e) { + return false; + } + } +} diff --git a/src/main/java/me/aurora/config/redis/RedisConfig.java b/src/main/java/me/aurora/config/redis/RedisConfig.java index 1283472..d48affb 100644 --- a/src/main/java/me/aurora/config/redis/RedisConfig.java +++ b/src/main/java/me/aurora/config/redis/RedisConfig.java @@ -3,6 +3,7 @@ package me.aurora.config.redis; import afu.org.checkerframework.checker.oigj.qual.O; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.serializer.SerializerFeature; +import org.apache.commons.lang3.StringUtils; import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.cache.CacheManager; @@ -21,6 +22,9 @@ import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSeriali import org.springframework.data.redis.serializer.RedisSerializer; import org.springframework.data.redis.serializer.SerializationException; import org.springframework.data.redis.serializer.StringRedisSerializer; +import redis.clients.jedis.JedisPool; +import redis.clients.jedis.JedisPoolConfig; + import java.io.Serializable; import java.lang.reflect.Method; import java.nio.charset.Charset; @@ -67,6 +71,18 @@ public class RedisConfig extends CachingConfigurerSupport { return new JedisConnectionFactory(redisStandaloneConfiguration, jedisClientConfiguration.build()); } + @Bean + public JedisPool redisPoolFactory() { + JedisPoolConfig jedisPoolConfig = new JedisPoolConfig(); + jedisPoolConfig.setMaxIdle(maxIdle); + jedisPoolConfig.setMaxWaitMillis(Long.parseLong(maxWaitMillis.replace("ms",""))); + if (StringUtils.isNotBlank(password)) { + return new JedisPool(jedisPoolConfig, host, port, Integer.parseInt(timeout.replace("ms","")), password); + } else { + return new JedisPool(jedisPoolConfig, host, port, Integer.parseInt(timeout.replace("ms",""))); + } + } + /** * 序列化 * @param redisConnectionFactory diff --git a/src/main/java/me/aurora/domain/ResponseEntity.java b/src/main/java/me/aurora/domain/ResponseEntity.java index 3887018..0c5509a 100644 --- a/src/main/java/me/aurora/domain/ResponseEntity.java +++ b/src/main/java/me/aurora/domain/ResponseEntity.java @@ -29,6 +29,13 @@ public class ResponseEntity extends HashMap{ return responseEntity; } + public static ResponseEntity ok(Object msg) { + ResponseEntity responseBo = new ResponseEntity(); + responseBo.put("code", 0); + responseBo.put("msg", msg); + return responseBo; + } + public static ResponseEntity ok(String msg) { ResponseEntity responseEntity = new ResponseEntity(); responseEntity.put("msg", msg); diff --git a/src/main/java/me/aurora/domain/UserOnline.java b/src/main/java/me/aurora/domain/UserOnline.java index 4ca69b5..24d8c97 100644 --- a/src/main/java/me/aurora/domain/UserOnline.java +++ b/src/main/java/me/aurora/domain/UserOnline.java @@ -1,8 +1,6 @@ package me.aurora.domain; -import lombok.Getter; -import lombok.Setter; - +import lombok.Data; import javax.persistence.*; import java.io.Serializable; import java.util.Date; @@ -12,8 +10,7 @@ import java.util.Date; * @author 郑杰 * @date 2018/09/21 15:38:06 */ -@Getter -@Setter +@Data public class UserOnline implements Serializable{ /** diff --git a/src/main/java/me/aurora/service/RedisService.java b/src/main/java/me/aurora/service/RedisService.java new file mode 100644 index 0000000..ae4b5c9 --- /dev/null +++ b/src/main/java/me/aurora/service/RedisService.java @@ -0,0 +1,79 @@ +package me.aurora.service; + +import java.util.Set; + +/** + * @author 郑杰 + * @date 2018/09/22 10:42:52 + */ +public interface RedisService { + + /** + * 获取 key + * @param pattern 正则 + * @return Set + */ + Set getKeys(String pattern); + + /** + * get命令 + * + * @param key key + * @return String + */ + String get(String key); + + /** + * set命令 + * + * @param key key + * @param value value + * @return String + */ + String set(String key, String value); + + /** + * del命令 + * + * @param key key + * @return Long + */ + Long del(String... key); + + /** + * exists命令 + * + * @param key key + * @return Boolean + */ + Boolean exists(String key); + + /** + * pttl命令 + * + * @param key key + * @return Long + */ + Long pttl(String key); + + /** + * pexpire命令 + * + * @param key key + * @param milliscends 毫秒 + * @return Long + */ + Long pexpire(String key, Long milliscends); + + /** + * flushdb 命令 + * @return + */ + String flushdb(); + + /** + * flushall 命令 + * @return + */ + String flushall(); +} diff --git a/src/main/java/me/aurora/service/impl/MenuServiceImpl.java b/src/main/java/me/aurora/service/impl/MenuServiceImpl.java index 5343171..f583c57 100644 --- a/src/main/java/me/aurora/service/impl/MenuServiceImpl.java +++ b/src/main/java/me/aurora/service/impl/MenuServiceImpl.java @@ -19,6 +19,7 @@ import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; import org.springframework.stereotype.Service; import java.util.*; +import java.util.stream.Collectors; /** * @author 郑杰 @@ -100,12 +101,14 @@ public class MenuServiceImpl implements MenuService { @Override public void delete(Menu menu) { - List menus = menuRepo.findByPid(menu.getPid()); - if(menus !=null && menus.size()!=0){ - menuRepo.deleteAll(menus); + if(menu.getLevelNum() == 0){ + menuRepo.delete(menu); + } else { + Set menus = menuRepo.findByPid(menu.getPid()).stream().collect(Collectors.toSet()); + if(menus !=null && menus.size()!=0){ + menuRepo.deleteAll(menus); + } } - menuRepo.delete(menu); - } @Override diff --git a/src/main/java/me/aurora/service/impl/RedisServiceImpl.java b/src/main/java/me/aurora/service/impl/RedisServiceImpl.java new file mode 100644 index 0000000..9ecd296 --- /dev/null +++ b/src/main/java/me/aurora/service/impl/RedisServiceImpl.java @@ -0,0 +1,81 @@ +package me.aurora.service.impl; + +import me.aurora.service.RedisService; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import redis.clients.jedis.Jedis; +import redis.clients.jedis.JedisPool; +import java.util.*; +import java.util.function.Function; + +/** + * Redis 工具类,只封装了几个常用的 redis 命令, + * 可根据实际需要按类似的方式扩展即可。 + * @author 郑杰 + * @date 2018/09/22 10:42:52 + */ +@Service("redisService") +@SuppressWarnings("unchecked") +public class RedisServiceImpl implements RedisService { + + private Logger log = LoggerFactory.getLogger(this.getClass()); + + @Autowired + JedisPool jedisPool; + + + /** + * 处理jedis请求 + * @param f 处理逻辑,通过lambda行为参数化 + * @return 处理结果 + */ + private Object excuteByJedis(Function f) { + try (Jedis jedis = jedisPool.getResource()) { + return f.apply(jedis); + } catch (Exception e) { + log.error(e.getMessage()); + return null; + } + } + + @Override + public Set getKeys(String pattern) { + return (Set) this.excuteByJedis(j -> j.keys(pattern)); + } + + @Override + public String get(String key) { + return (String) this.excuteByJedis(j -> j.get(key)); + } + + @Override + public String set(String key, String value) { + return (String) this.excuteByJedis(j -> j.set(key, value)); + } + + @Override + public Long del(String... key) { + return (Long) this.excuteByJedis(j -> j.del(key)); + } + + @Override + public Boolean exists(String key) { + return (Boolean) this.excuteByJedis(j -> j.exists(key)); + } + + @Override + public Long pttl(String key) { + return (Long) this.excuteByJedis(j -> j.pttl(key)); + } + + @Override + public Long pexpire(String key, Long milliseconds) { return (Long) this.excuteByJedis(j -> j.pexpire(key, milliseconds)); } + + @Override + public String flushdb() { return (String) this.excuteByJedis(j -> j.flushDB()); } + + @Override + public String flushall() { return (String) this.excuteByJedis(j -> j.flushAll()); } +} diff --git a/src/main/resources/sql/aurora.sql b/src/main/resources/sql/aurora.sql index c4d09fc..d01f84c 100644 --- a/src/main/resources/sql/aurora.sql +++ b/src/main/resources/sql/aurora.sql @@ -11,7 +11,7 @@ Target Server Version : 50559 File Encoding : 65001 - Date: 21/09/2018 16:47:46 + Date: 22/09/2018 13:06:32 */ SET NAMES utf8mb4; @@ -34,7 +34,7 @@ CREATE TABLE `zj_menu` ( `level_number` int(11) NOT NULL, PRIMARY KEY (`id`) USING BTREE, UNIQUE INDEX `UK_cbhg0bi3f1emxkhqqtvca9btx`(`soft`) USING BTREE -) ENGINE = InnoDB AUTO_INCREMENT = 15 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Compact; +) ENGINE = InnoDB AUTO_INCREMENT = 17 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Compact; -- ---------------------------- -- Records of zj_menu @@ -43,16 +43,17 @@ INSERT INTO `zj_menu` VALUES (1, 'layui-icon-unlink', 0, 1, '异常页', 40, '', INSERT INTO `zj_menu` VALUES (2, 'layui-icon-tree', 1, 2, '403', 41, '/exception/403', '2018-08-29 11:40:17', '2018-09-20 11:36:24', 0); INSERT INTO `zj_menu` VALUES (3, 'layui-icon-tree', 1, 2, '404', 42, '/exception/404', '2018-08-29 11:40:17', '2018-09-20 11:36:32', 0); INSERT INTO `zj_menu` VALUES (4, 'layui-icon-tree', 1, 2, '500', 43, '/exception/500', '2018-08-29 11:40:17', '2018-09-20 11:36:40', 0); -INSERT INTO `zj_menu` VALUES (5, 'layui-icon-chart', 0, 1, '系统监控', 10, '', '2018-08-29 11:40:17', '2018-09-21 16:09:38', 2); +INSERT INTO `zj_menu` VALUES (5, 'layui-icon-chart', 0, 1, '系统监控', 10, '', '2018-08-29 11:40:17', '2018-09-22 11:18:21', 4); INSERT INTO `zj_menu` VALUES (6, 'layui-icon-tree', 7, 2, '用户管理', 2, '/user/index', '2018-08-29 11:40:17', '2018-09-04 07:40:25', 0); INSERT INTO `zj_menu` VALUES (7, 'layui-icon-util', 0, 1, '系统管理', 1, '', '2018-08-29 11:40:17', '2018-09-20 19:02:05', 4); INSERT INTO `zj_menu` VALUES (8, 'layui-icon-tree', 7, 2, '菜单管理', 6, '/menu/index', '2018-08-29 11:40:17', '2018-09-04 07:40:25', 0); -INSERT INTO `zj_menu` VALUES (9, 'layui-icon-tree', 5, 2, '日志管理', 11, '/sysLog/index', '2018-08-29 11:40:17', '2018-09-04 07:40:25', 0); +INSERT INTO `zj_menu` VALUES (9, 'layui-icon-tree', 5, 2, '系统日志', 11, '/sysLog/index', '2018-08-29 11:40:17', '2018-09-22 10:17:02', 0); INSERT INTO `zj_menu` VALUES (10, 'layui-icon-tree', 7, 2, '权限管理', 4, '/permission/index', '2018-08-29 11:40:17', '2018-09-04 07:40:25', 0); INSERT INTO `zj_menu` VALUES (11, 'layui-icon-tree', 7, 2, '角色管理', 3, '/role/index', '2018-08-29 11:40:17', '2018-09-04 07:40:25', 0); INSERT INTO `zj_menu` VALUES (12, 'layui-icon-website', 0, 1, '网络资源', 30, '', '2018-09-20 11:35:56', '2018-09-20 11:40:53', 1); INSERT INTO `zj_menu` VALUES (13, 'layui-icon-tree', 12, 2, '图床管理', 31, '/picture/index', '2018-09-20 11:40:53', '2018-09-20 11:40:53', 0); -INSERT INTO `zj_menu` VALUES (14, 'layui-icon-tree', 5, 2, '在线用户管理', 12, '/online/index', '2018-09-21 16:09:38', '2018-09-21 16:09:38', 0); +INSERT INTO `zj_menu` VALUES (14, 'layui-icon-tree', 5, 2, '在线用户', 12, '/online/index', '2018-09-21 16:09:38', '2018-09-22 10:17:09', 0); +INSERT INTO `zj_menu` VALUES (16, 'layui-icon-tree', 5, 2, 'Redis终端', 14, '/redis/terminal', '2018-09-22 11:18:21', '2018-09-22 11:37:28', 0); -- ---------------------------- -- Table structure for zj_menus_roles @@ -84,6 +85,7 @@ INSERT INTO `zj_menus_roles` VALUES (11, 1); INSERT INTO `zj_menus_roles` VALUES (12, 1); INSERT INTO `zj_menus_roles` VALUES (13, 1); INSERT INTO `zj_menus_roles` VALUES (14, 1); +INSERT INTO `zj_menus_roles` VALUES (16, 1); INSERT INTO `zj_menus_roles` VALUES (1, 2); INSERT INTO `zj_menus_roles` VALUES (2, 2); INSERT INTO `zj_menus_roles` VALUES (3, 2); @@ -218,23 +220,6 @@ INSERT INTO `zj_role` VALUES (1, '2018-08-23 09:13:54', '超级管理员', NULL, INSERT INTO `zj_role` VALUES (2, '2018-08-27 19:31:03', '普通用户', '', '2018-09-01 08:31:08'); INSERT INTO `zj_role` VALUES (3, '2018-09-03 15:17:31', '测试', '1', '2018-09-20 17:28:03'); --- ---------------------------- --- Table structure for zj_syslog --- ---------------------------- -DROP TABLE IF EXISTS `zj_syslog`; -CREATE TABLE `zj_syslog` ( - `id` bigint(20) NOT NULL AUTO_INCREMENT, - `createTime` datetime NULL DEFAULT NULL, - `ip` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, - `location` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, - `method` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, - `operation` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, - `params` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, - `time` int(11) NULL DEFAULT NULL, - `username` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, - PRIMARY KEY (`id`) USING BTREE -) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Compact; - -- ---------------------------- -- Table structure for zj_user -- ---------------------------- @@ -250,12 +235,12 @@ CREATE TABLE `zj_user` ( `username` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, PRIMARY KEY (`id`) USING BTREE, UNIQUE INDEX `UK_kpubos9gc2cvtkb0thktkbkes`(`email`) USING BTREE -) ENGINE = InnoDB AUTO_INCREMENT = 9 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Compact; +) ENGINE = InnoDB AUTO_INCREMENT = 2 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Compact; -- ---------------------------- -- Records of zj_user -- ---------------------------- -INSERT INTO `zj_user` VALUES (1, 'https://www.zhengjie.me/images/avatar.jpg', '2018-08-23 09:11:56', 'zhengjie@tom.com', 1, '2018-09-21 16:26:05', '65a674ce6632479005ea7a9071234cfb', 'aurora'); +INSERT INTO `zj_user` VALUES (1, 'https://www.zhengjie.me/images/avatar.jpg', '2018-08-23 09:11:56', 'zhengjie@tom.com', 1, '2018-09-22 13:00:04', '65a674ce6632479005ea7a9071234cfb', 'aurora'); -- ---------------------------- -- Table structure for zj_user_pictures diff --git a/src/main/resources/static/js/redis/terminal.js b/src/main/resources/static/js/redis/terminal.js new file mode 100644 index 0000000..73485ec --- /dev/null +++ b/src/main/resources/static/js/redis/terminal.js @@ -0,0 +1,382 @@ +var $MB_Redis_Bash = function () { + $(document).ready(function () { + var title = $(".title"); + var terminal = $(".terminal"); + var prompt = "➜"; + var path = "~"; + var commandHistory = []; + var historyIndex = 0; + var command = ""; + + title.text(userName + "@" + osName + ": ~ (redis-cli)"); + var date = new Date().toString(); + date = date.substr(0, date.indexOf("GMT") - 1); + printf("Last login: " + date + " on aurora, type `help` for help\n"); + displayPrompt(); + + var commands = [{ + name: "clear", + function: clear + }, { + name: "help", + function: help + }, { + name: "echo", + function: echo + }, { + name: "keys", + function: keys + }, { + name: "get", + function: get + }, { + name: "exists", + function: exists + }, { + name: "pttl", + function: pttl + }, { + name: "pexpire", + function: pexpire + }, { + name: "set", + function: set + }, { + name: "del", + function: del + }, { + name: "flushdb", + function: flushdb + }, { + name: "flushall", + function: flushall + }]; + + // system command + + function clear() { + terminal.text(""); + printc(); + } + + function echo(args) { + var str = args.join(""); + printf(str + "\n"); + printc(); + } + + function erase(n) { + command = command.slice(0, -n); + terminal.html(terminal.html().slice(0, -n)); + } + + function clearCommand() { + if (command.length > 0) { + erase(command.length); + } + } + + // redis command + function keys(args) { + args = args.join(""); + if (!hasArgs(args)) { + errorArgs('keys'); + } else $.get("/redis/keys", { + 'arg': args + }, function (r) { + console.log(r); + var data = r.msg; + if (r.code === 0) { + if (data.length) { + for (var i = 0; i < data.length; i++) { + printf('"' + data[i] + '"\n'); + } + } else { + printf("(empty list or set)\n"); + } + } else { + printf(data + "\n"); + } + printc(); + }); + } + + function get(args) { + args = args.join(""); + if (!hasArgs(args)) { + errorArgs('get'); + } else $.get("/redis/get", { + 'arg': args + }, function (r) { + var data = r.msg; + if (r.code === 0 && data !== '') { + printf(data + "\n"); + } else { + printf("(nil)\n"); + } + printc(); + }); + } + + function set(args) { + if (!hasArgs(args.join(""))) { + errorArgs('set'); + } else $.get("/redis/set", { + 'arg': args.join(",") + }, function (r) { + printf(r.msg + "\n"); + printc(); + }); + } + + function del(args) { + if (!hasArgs(args.join(""))) { + errorArgs('set'); + } else $.get("/redis/del", { + 'arg': args.join(",") + }, function (r) { + printf(r.msg + "\n"); + printc(); + }); + } + + function exists(args) { + if (!hasArgs(args.join(""))) { + errorArgs('exists'); + } else { + $.get("/redis/exists", {arg: args.join(",")}, function (r) { + var data = r.msg; + printf(data + "\n"); + printc(); + }); + } + } + + function pttl(args) { + args = args.join(""); + if (!hasArgs(args)) { + errorArgs('pttl'); + } else { + $.get("/redis/pttl", {arg: args}, function (r) { + var data = r.msg; + printf(data + "\n"); + printc(); + }); + } + } + + function flushdb(args) { + $.get("/redis/flushdb",{},function (r) { + var data = r.msg; + printf(data + "\n"); + printc(); + }); + } + + function flushall(args) { + $.get("/redis/flushall",{},function (r) { + var data = r.msg; + printf(data + "\n"); + printc(); + }); + } + + function pexpire(args) { + if (!hasArgs(args.join(""))) { + errorArgs('pexpire'); + } else { + $.get("/redis/pexpire", {arg: args.join(",")}, function (r) { + var data = r.msg; + printf(data + "\n"); + printc(); + }); + } + } + + function help(arg) { + arg = arg.join(" "); + if (hasArgs(arg)) { + switch (arg) { + case "keys": { + printf(" KEYS pattern\n"); + printf(" summary: Find all keys matching the given pattern.\n"); + printf(" since: 1.0.0\n"); + printf(" group: generic\n"); + break; + } + + case "get": { + printf(" GET key\n"); + printf(" summary: Get the value of a key\n"); + printf(" since: 1.0.0\n"); + printf(" group: string\n"); + break; + } + case "set": { + printf(" DEL key [key ...]\n"); + printf(" summary: Delete a key\n"); + printf(" since: 1.0.0\n"); + printf(" group: generic\n"); + break; + } + case "del": { + printf(" SET key value\n"); + printf(" summary: Set the string value of a key\n"); + printf(" since: 1.0.0\n"); + printf(" group: string\n"); + break; + } + case "exists": { + printf(" EXISTS key [key ...]\n"); + printf(" summary: Determine if a key exists\n"); + printf(" since: 1.0.0\n"); + printf(" group: generic\n"); + break; + } + case "pttl": { + printf(" PTTL key\n"); + printf(" summary: Get the time to live for a key in milliseconds\n"); + printf(" since: 2.6.0\n"); + printf(" group: generic\n"); + break; + } + case "pexpire": { + printf(" PEXPIRE key milliseconds\n"); + printf(" summary: Set a key's time to live in milliseconds\n"); + printf(" since: 2.6.0\n"); + printf(" group: generic\n"); + break; + } + default: { + printf(" no more messages about command `" + arg + "`\n"); + } + } + } else { + printf(" Redis bash with SpringBoot by MrBird, version v0.0.1 - Snapshot \n"); + printf(" These shell commands are defined internally. Type `help` to see this list.\n"); + printf(" Type `help name` to find out more about the command `name`.\n"); + printf(" -------------------------------- \n"); + printf(" | system command | \n"); + printf(" -------------------------------- \n"); + printf(" clear help echo\n"); + printf(" -------------------------------- \n"); + printf(" | redis command | \n"); + printf(" -------------------------------- \n"); + printf(" keys get set \n"); + printf(" del exists pttl\n"); + printf(" -------------------------------- \n"); + printf(" | redis wipe cache | \n"); + printf(" -------------------------------- \n"); + printf(" flushall flushdb\n"); + } + printc(); + } + + + function processCommand() { + var isValid = false; + var args = command.split(" "); + var cmd = args[0]; + args.shift(); + for (var i = 0; i < commands.length; i++) { + if (cmd === commands[i].name) { + commands[i].function(args); + isValid = true; + break; + } + } + if (!isValid) { + printf("redis: command not found: `" + command + "`, type `help` for help.\n"); + printc(); + } + commandHistory.push(command); + historyIndex = commandHistory.length; + command = ""; + } + + function displayPrompt() { + printf('' + prompt + " "); + printf('' + path + " "); + } + + + function appendCommand(str) { + terminal.append(str); + command += str; + } + + $(document).keydown(function (e) { + e = e || window.event; + var keyCode = typeof e.which === "number" ? e.which : e.keyCode; + if (keyCode === 8 && e.target.tagName !== "INPUT" && e.target.tagName !== "TEXTAREA") { + e.preventDefault(); + if (command !== "") { + erase(1); + } + } + if (keyCode === 38 || keyCode === 40) { + if (keyCode === 38) { + historyIndex--; + if (historyIndex < 0) { + historyIndex++; + } + } else if (keyCode === 40) { + historyIndex++; + if (historyIndex > commandHistory.length - 1) { + historyIndex--; + } + } + var cmd = commandHistory[historyIndex]; + if (cmd !== undefined) { + clearCommand(); + appendCommand(cmd); + } + } + }); + $(document).keypress(function (e) { + e = e || window.event; + var keyCode = typeof e.which === "number" ? e.which : e.keyCode; + switch (keyCode) { + case 13: { + printf("\n"); + processCommand(); + break; + } + + default: { + appendCommand(String.fromCharCode(keyCode)); + } + } + }); + + function scroll(o) { + o = o[0]; + o.scrollTop = o.scrollHeight; + } + + function printf(msg) { + terminal.append(msg); + } + + function printc() { + displayPrompt(); + historyIndex++; + scroll(terminal); + } + + function hasArgs(arg) { + try { + if (arg.length === 0) return 0; + else return 1; + } catch (e) { + return 0; + } + } + + function errorArgs(args) { + printf("(error) ERR wrong number of arguments for '" + args + "' command\n"); + printc(); + } + + }); +}($); \ No newline at end of file diff --git a/src/main/resources/templates/index.html b/src/main/resources/templates/index.html index 0942050..ab9f2ff 100644 --- a/src/main/resources/templates/index.html +++ b/src/main/resources/templates/index.html @@ -144,6 +144,9 @@ base: 'js/' }).use('index'); + \ No newline at end of file diff --git a/src/main/resources/templates/system/redis/terminal.html b/src/main/resources/templates/system/redis/terminal.html new file mode 100644 index 0000000..ec84355 --- /dev/null +++ b/src/main/resources/templates/system/redis/terminal.html @@ -0,0 +1,25 @@ + +
+
+
+
+
+
+
+ + + +
+ +
+
+
+
+
+
+ +