[
  {
    "path": "README-EN.md",
    "content": "### Jin Xia Nian Hua\n\n```\nHello,Welcome to boot...SpringBoot The version number of the:v2.0.7.RELEASE Project producer:LuKe(walker)\n\nIt's not easy to develop,I hope you can keep the copyright declaration for a while。Pencil lead💗💗💗\n```\n\n<h1><a href=\"#\">hacker-walker</a></h1>\n\n🇨🇳[简体中文](./README.md) | 🇺🇸English | [更新日志](https://github.com/java-aodeng/hope-plus/commits/master)\n\n[![author](https://img.shields.io/badge/author-walker-blue.svg)](https://wuxf.cn)\n[![JDK](https://img.shields.io/badge/JDK-1.8-orange.svg)](https://github.com/hacker-walker/hacker-walker)\n[![license](https://img.shields.io/badge/license-GPL--3.0-red.svg)](https://github.com/hacker-walker/hacker-walker/releases/tag/3.0)\n[![QQ群](https://img.shields.io/badge/chat-walkerQQ%E7%BE%A4-yellow.svg)](https://jq.qq.com/?_wv=1027&k=5mjexzD)\n<a href=\"https://github.com/hacker-walker/hacker-walker\"><img alt=\"star\" src=\"https://img.shields.io/github/stars/hacker-walker/hacker-walker.svg?label=Stars&style=social\"/></a>\n[![star](https://gitee.com/walker-cloud/hacker-walker/badge/star.svg?theme=dark)](https://gitee.com/walker-cloud/hacker-walker/stargazers)\n[![released version](https://img.shields.io/badge/release-3.0-green.svg)](https://github.com/hacker-walker/hacker-walker/releases)  \n\nWechat Public Number:Jin Xia Nian Hua\n\n![file](https://images.gitee.com/uploads/images/2019/0610/161454_710bf233_2127888.png)\n\n### brief introduction\n   **Project address：https://gitee.com/walker-cloud/hacker-walker**\n```\n     In 2019, I wish everyone who works hard a reward\nOn the road of life, tears are on the left, laughter is on the right, and flowers of life are on both sides.\nThrough the four seasons of life, we experienced the baptism of tears, witnessed the moment of laughter, appreciated the rise of the morning sun, gazed at the blooming of flower stamens.\nOn the way of life, we harvest the inexhaustible gift of the God of life, and set out with her gifts and blessings. All the way, because of the harvest, we have never been cold, we have never been lonely.\n\nNetease Mailbox Communication: a18627830855@163.com   | QQ Communication: 1722009230   | wx Communication: 18627830855   | QQ-Group Communication：741413607\n\n```\n### Account number\n```\n1.Logon test:\n     Visit URL: http://localhost:8888/success\n     If you are not logged in, you will jump directly to the login page: http://localhost:8888/dr\n2.Login account description:\n     Login account shows that there is no server database, and SQL statement will be placed later\n     Account Name：admin\n     Password：abc123\n     Verification code (this is not done yet, it will be put on later)\n3.After successful login, it will jump to the relevant success page\n4.User Information Display (after login)\n     URL: http://localhost:8888/qdst\n\nBackend API management：localhost:8888/swagger-ui.html\n```\n### Modular Partitioning\n| Modular   | Interpretation   |\n| -- | -- |\n| hacker-db | DatabaseSql |\n| hacker-service-channel-manage  |  Background management module,Mapper,Service etc |\n| hacker-framework-common  | Various forcing configurations for iso-frameworks   |\n| hacker-framework-model  |  Database Core Entity Class  |\n| hacker-govern-gateway(center)  |  gateway  |\n| hacker-framework-util  |  Tool class  |\n\n### Instructions\n```\n1.Use command pull substitution code：\n    git clone https://gitee.com/walker-cloud/Hacker-walker.git \n2.Create a database：jinnian(jin nian)， character set：utf8;（Note: All you need to do is create a database）\n3.IDEA is the best way to import this project\n4.Warehouse Configuration\n    open Settings option——》Choice Build Tools The following Maven tab——》Configure your own warehouse under Maven home direcdtory\n5.Modify configuration\n    A.open application.properties，Configure database connection\n          datasource:\n              url: Your database address\n              username: Your database username\n              password: Your database password\n6.Running Project (Background Management Module)\n    a.Direct operation hacker.channel.manage App in Directory\n    b.Browser access：http://127.0.0.1:8888\n```\n### Thank\n- hacker-walker The birth of the project is inseparable from the following (take open source, use open source)：\n- Spring Boot：Core Framework\n- Apache Shiro：Permission Framework\n- Thymeleaf：template engine\n- MyBatis-plus：Be used for Java Of MyBatis SQL Mapper frame\n- alibaba/druid：Database connection pool\n- alibaba/fastjson：Fast JSON parser/generator for Java\n- Lombok：Make the code more concise\n- swagger：Swagger（Swagger）The most popular API expression tool in the world。\n- Html5：Front-end page\n\n### Framework demonstration\n```\nAt present, it is still in perfect development, and will be put here to show the effect, please laugh!\n```\n```\nLogin interface\n```\n![Login interface](https://images.gitee.com/uploads/images/2019/0610/180431_93d56664_2127888.png)\n```\nBackground management interface\n```\n![Background management interface](https://images.gitee.com/uploads/images/2019/0613/111333_0edb6d4e_2127888.png)\n![1](https://i.loli.net/2019/07/03/5d1c94263e68624395.png)\n![2](https://i.loli.net/2019/07/03/5d1c943d8714f56661.png)\n![3](https://i.loli.net/2019/07/03/5d1c9443c143583430.png)\n### Friendship Links\n\n- Author: Low-key Panda  Blog：http://ilovey.live （Reading ten thousand books, traveling ten thousand miles, making a lot of money）Wechat Public Number: Low-key Panda  \n- Author:walker Blog：https://wuxf.cn (Unknown Partners in Australia) Wechat Public Number：jin xia nian hua\n\n### Last\nhttp://doc.zengrong.net/smart-questions/cn.html   \nIn order to prevent the world from being destroyed, in order to love and justice, it is recommended to look at the wisdom of asking questions.\n\n## You thumb up encouragement is the motivation for us to move forward\n![cartridge](https://i.loli.net/2019/07/13/5d29c699493f847597.png)"
  },
  {
    "path": "README.md",
    "content": " \n### 堇夏年华        \n    \n\n```\nHello,Welcome to boot...SpringBoot的版本号:v2.0.7.RELEASE 项目制作人:LuKe(walker)\n\n    开发不易，希望您可以保留一下版权声明。 笔芯💗💗💗\n```\n<h1><a href=\"#\">hacker-walker</a></h1>\n\n🇨🇳简体中文 | 🇺🇸[English](./README-EN.md) | [更新日志](https://gitee.com/walker-cloud/hacker-walker)\n\n[![author](https://img.shields.io/badge/author-walker-blue.svg)](https://wuxf.cn)\n[![JDK](https://img.shields.io/badge/JDK-1.8-orange.svg)](https://github.com/hacker-walker/hacker-walker)\n[![license](https://img.shields.io/badge/license-GPL--3.0-red.svg)](https://github.com/hacker-walker/hacker-walker/releases/tag/3.0)\n[![QQ群](https://img.shields.io/badge/chat-walkerQQ%E7%BE%A4-yellow.svg)](https://jq.qq.com/?_wv=1027&k=5mjexzD)\n<a href=\"https://github.com/hacker-walker/hacker-walker\"><img alt=\"star\" src=\"https://img.shields.io/github/stars/hacker-walker/hacker-walker.svg?label=Stars&style=social\"/></a>\n[![star](https://gitee.com/walker-cloud/hacker-walker/badge/star.svg?theme=dark)](https://gitee.com/walker-cloud/hacker-walker/stargazers)\n[![发行版本](https://img.shields.io/badge/release-3.0-green.svg)](https://github.com/hacker-walker/hacker-walker/releases)  \n\n微信公众号:堇夏年华\n\n![file](https://images.gitee.com/uploads/images/2019/0610/161454_710bf233_2127888.png)\n\n\n### 简介\n   **项目地址：https://gitee.com/walker-cloud/hacker-walker** \n\n       2019年，祝每一个努力的人都有所收获 \n\n       人生路上，泪水在左，欢笑在右，生命的鲜花铺满两旁。\n       走过生命的四季，我们经历了泪水的洗礼，见证了欢笑的时刻，欣赏着朝阳的升起，凝视着花蕊的绽放。\n       人生途中，我们收获着生命之神不尽的惠赠，满揣着她的礼物与祝福启程。一路走来，因为收获，我们不曾寒冷，我们从未孤独。\n   \n    网易邮箱 交流: a18627830855@163.com   | QQ 交流: 1722009230   | wx 交流: 18627830855   | QQ群 交流：741413607\n\n### 账号\n    \n```\n1.登录测试:\n     访问URL: http://localhost:8888/success\n     如果未登录会直接跳到登录页: http://localhost:8888/dr\n2.登录账号说明:\n     此处没有放服务器数据库,后面会放sql语句\n     账户名：admin\n     密码：abc123\n     验证码(这个还没做，后面会放上去)\n3.登录成功后会跳转到相关的成功页面\n4.用户信息显示(登陆后)\n     URL: http://localhost:8888/qdst\n\n后端API管理：localhost:8888/swagger-ui.html\n```\n\n### 模块划分\n| 模块   | 释义   |\n| -- | -- |\n| hacker-db | 数据库sql |\n| hacker-service-channel-manage  |  后台管理模块,Mapper,Service等 |\n| hacker-framework-common  | 框架的各种牛逼配置   |\n| hacker-framework-model  |  数据库核心实体类  |\n| hacker-govern-gateway(center)  |  网关  |\n| hacker-framework-util  |  工具类  |\n\n### 使用说明 \n```\n1.使用命令拉取代码：\n    git clone https://gitee.com/walker-cloud/Hacker-walker.git \n2.创建数据库：jinnian(堇年)， 字符集：utf8;（注意：只需要你创建数据库即可）\n3.最好使用IDEA导入该项目\n4.仓库配置\n    打开Settings选项——》选择Build Tools下面的Maven选项卡——》在Maven home direcdtory下配置自己的仓库\n5.修改配置\n    A.打开application.properties，配置数据库连接\n          datasource:\n              url: 你的数据库地址\n              username: 你的数据库用户名\n              password: 你的数据库密码\n6.运行项目(后台管理模块)\n    a.直接运行hacker.channel.manage目录下的App\n    b.浏览器访问：http://127.0.0.1:8888\n```\n\n### 感谢\n- hacker-walker的诞生离不开下面这些项目（取之开源，用之开源）：\n- Spring Boot：核心框架\n- Apache Shiro：权限框架\n- Thymeleaf：模板引擎\n- MyBatis-plus：用于Java的MyBatis SQL Mapper框架\n- alibaba/druid：数据库连接池\n- alibaba/fastjson：用于Java的快速JSON解析器/生成器\n- Lombok：让代码更简洁\n- swagger：Swagger（丝袜哥）是世界上最流行的 API 表达工具。\n- Html5：前端页面\n\n\n### 框架演示\n\n```\n  目前还在完善开发，后面会放到这里展示效果，请笑纳！\n```\n```\n登陆界面\n```\n![登陆界面](https://images.gitee.com/uploads/images/2019/0610/180431_93d56664_2127888.png)\n```\n后台管理界面\n```\n![后台界面](https://images.gitee.com/uploads/images/2019/0613/111333_0edb6d4e_2127888.png)\n![1](https://i.loli.net/2019/07/03/5d1c94263e68624395.png)\n![2](https://i.loli.net/2019/07/03/5d1c943d8714f56661.png)\n![3](https://i.loli.net/2019/07/03/5d1c9443c143583430.png)\n### 友情链接\n\n- 作者:低调小熊猫 博客：http://ilovey.live （读万卷书，行万里路，赚很多钱）微信公众号：低调小熊猫   \n- 作者:walker 博客：https://wuxf.cn (澳大利亚不知名企业合伙人) 微信公众号：堇夏年华\n\n### Last\n    为了防止世界被毁灭，为了爱情和正义，建议大家看看提出问题的智慧。\nhttp://doc.zengrong.net/smart-questions/cn.html\n\n    In order to prevent the world from being destroyed, in order to love and justice, it is recommended to look at the wisdom of asking questions.\n\n## 你的点赞鼓励，是我前进的动力\n![笔芯](https://i.loli.net/2019/07/13/5d29c699493f847597.png)\n"
  },
  {
    "path": "hacker-db/walker.sql",
    "content": "/*\r\nSQLyog Ultimate v8.32 \r\nMySQL - 8.0.15 : Database - jinnian\r\n*********************************************************************\r\n*/\r\r\n\r\n/*!40101 SET NAMES utf8 */;\r\n\r\n/*!40101 SET SQL_MODE=''*/;\r\n\r\n/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;\r\n/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;\r\n/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;\r\n/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;\r\nCREATE DATABASE /*!32312 IF NOT EXISTS*/`jinnian` /*!40100 DEFAULT CHARACTER SET utf8 */;\r\n\r\nUSE `jinnian`;\r\n\r\n/*Table structure for table `tb_admin` */\r\n\r\nDROP TABLE IF EXISTS `tb_admin`;\r\n\r\nCREATE TABLE `tb_admin` (\r\n  `id` int(32) unsigned NOT NULL AUTO_INCREMENT COMMENT 'id',\r\n  `username` varchar(64) NOT NULL,\r\n  `password` varchar(122) NOT NULL,\r\n  `phone` varchar(64) DEFAULT NULL,\r\n  `status` int(1) NOT NULL DEFAULT '1' COMMENT '状态 成功:1 失败:0',\r\n  `is_readonly` int(2) NOT NULL DEFAULT '1' COMMENT '是否只允许读操作 0:否 1:是',\r\n  `last_login_ip` varchar(64) NOT NULL DEFAULT '' COMMENT '登陆IP',\r\n  `last_login_token` varchar(64) DEFAULT NULL COMMENT '登陆的token',\r\n  `login_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '登陆时间',\r\n  `created_at` timestamp NULL DEFAULT NULL COMMENT '创建时间',\r\n  `updated_at` timestamp NULL DEFAULT NULL COMMENT '修改时间',\r\n  PRIMARY KEY (`id`)\r\n) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8;\r\n\r\n/*Data for the table `tb_admin` */\r\n\r\ninsert  into `tb_admin`(`id`,`username`,`password`,`phone`,`status`,`is_readonly`,`last_login_ip`,`last_login_token`,`login_at`,`created_at`,`updated_at`) values (1,'admin','9feb61735eae35a19c709cdcda699f80e087bc3f0e1049768fbb457a0d38702b','admin',1,1,'172.20.10.2','d55f2b281e2d4fd38835ceafd4a39566','2019-08-02 15:38:37','2019-05-26 10:14:15','2019-05-26 10:14:15');\r\n\r\n/*Table structure for table `tb_admin_role` */\r\n\r\nDROP TABLE IF EXISTS `tb_admin_role`;\r\n\r\nCREATE TABLE `tb_admin_role` (\r\n  `role_id` int(10) unsigned NOT NULL,\r\n  `admin_id` int(10) unsigned NOT NULL,\r\n  PRIMARY KEY (`role_id`,`admin_id`)\r\n) ENGINE=InnoDB DEFAULT CHARSET=utf8;\r\n\r\n/*Data for the table `tb_admin_role` */\r\n\r\ninsert  into `tb_admin_role`(`role_id`,`admin_id`) values (1,1),(1,2),(2,1);\r\n\r\n/*Table structure for table `tb_pay` */\r\n\r\nDROP TABLE IF EXISTS `tb_pay`;\r\n\r\nCREATE TABLE `tb_pay` (\r\n  `tradeNo` int(64) unsigned NOT NULL AUTO_INCREMENT COMMENT '用户订单号',\r\n  `userId` int(64) NOT NULL,\r\n  `adminId` int(32) NOT NULL,\r\n  `payTime` timestamp NULL DEFAULT CURRENT_TIMESTAMP COMMENT '支付时间',\r\n  `payStatus` int(2) NOT NULL DEFAULT '1' COMMENT '支付状态',\r\n  `payType` int(2) NOT NULL DEFAULT '1' COMMENT '支付方式',\r\n  `gmtCreate` timestamp NULL DEFAULT CURRENT_TIMESTAMP,\r\n  `merchantOutOrderNo` varchar(64) DEFAULT NULL COMMENT '商家支付订单号',\r\n  PRIMARY KEY (`tradeNo`)\r\n) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8;\r\n\r\n/*Data for the table `tb_pay` */\r\n\r\ninsert  into `tb_pay`(`tradeNo`,`userId`,`adminId`,`payTime`,`payStatus`,`payType`,`gmtCreate`,`merchantOutOrderNo`) values (1,1,1,'2019-08-02 16:02:15',1,1,'2019-08-02 16:02:15','121');\r\n\r\n/*Table structure for table `tb_permission` */\r\n\r\nDROP TABLE IF EXISTS `tb_permission`;\r\n\r\nCREATE TABLE `tb_permission` (\r\n  `id` int(32) unsigned NOT NULL AUTO_INCREMENT,\r\n  `name` varchar(64) DEFAULT NULL COMMENT '权限对应的唯一ID',\r\n  `index_name` varchar(64) NOT NULL DEFAULT '' COMMENT '前端路由',\r\n  `parent_id` int(32) NOT NULL DEFAULT '0' COMMENT '父类id 根节点为0',\r\n  `display_name` varchar(64) NOT NULL COMMENT '权限展示名',\r\n  `is_show` int(2) NOT NULL DEFAULT '1' COMMENT '是否展示在菜单栏',\r\n  `status` int(2) NOT NULL DEFAULT '1' COMMENT '状态 禁用:0 未禁用:1',\r\n  `created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',\r\n  `updated_at` timestamp NULL DEFAULT NULL COMMENT '修改时间',\r\n  PRIMARY KEY (`id`)\r\n) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8;\r\n\r\n/*Data for the table `tb_permission` */\r\n\r\ninsert  into `tb_permission`(`id`,`name`,`index_name`,`parent_id`,`display_name`,`is_show`,`status`,`created_at`,`updated_at`) values (1,'sytem.admin.list','/system/admin/list',0,'管理员列表',1,1,'2019-05-24 16:21:28','2019-05-24 16:21:28');\r\n\r\n/*Table structure for table `tb_role` */\r\n\r\nDROP TABLE IF EXISTS `tb_role`;\r\n\r\nCREATE TABLE `tb_role` (\r\n  `id` int(32) unsigned NOT NULL AUTO_INCREMENT COMMENT 'id',\r\n  `display_name` varchar(64) NOT NULL COMMENT '角色展示名',\r\n  `level` int(2) NOT NULL DEFAULT '0' COMMENT '角色等级',\r\n  `created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',\r\n  `updated_at` timestamp NULL DEFAULT NULL COMMENT '修改时间',\r\n  PRIMARY KEY (`id`)\r\n) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;\r\n\r\n/*Data for the table `tb_role` */\r\n\r\ninsert  into `tb_role`(`id`,`display_name`,`level`,`created_at`,`updated_at`) values (1,'超级管理员',1,'2019-05-26 10:14:15','2019-05-26 10:14:15'),(2,'管理员',0,'2019-06-25 12:42:12','2019-06-26 10:12:18');\r\n\r\n/*Table structure for table `tb_role_permission` */\r\n\r\nDROP TABLE IF EXISTS `tb_role_permission`;\r\n\r\nCREATE TABLE `tb_role_permission` (\r\n  `permission_id` int(10) unsigned NOT NULL,\r\n  `role_id` int(10) unsigned NOT NULL,\r\n  PRIMARY KEY (`permission_id`,`role_id`)\r\n) ENGINE=InnoDB DEFAULT CHARSET=utf8;\r\n\r\n/*Data for the table `tb_role_permission` */\r\n\r\ninsert  into `tb_role_permission`(`permission_id`,`role_id`) values (1,1),(1,2),(2,1);\r\n\r\n/*!40101 SET SQL_MODE=@OLD_SQL_MODE */;\r\n/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;\r\n/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */;\r\n/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;\r\n"
  },
  {
    "path": "hacker-framework-common/.gitignore",
    "content": "HELP.md\n/target/\n!.mvn/wrapper/maven-wrapper.jar\n\n### STS ###\n.apt_generated\n.classpath\n.factorypath\n.project\n.settings\n.springBeans\n.sts4-cache\n\n### IntelliJ IDEA ###\n.idea\n*.iws\n*.iml\n*.ipr\n\n### NetBeans ###\n/nbproject/private/\n/nbbuild/\n/dist/\n/nbdist/\n/.nb-gradle/\n/build/\n\n### VS Code ###\n.vscode/\n"
  },
  {
    "path": "hacker-framework-common/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n         xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n    <modelVersion>4.0.0</modelVersion>\n\n\n    <!--父类-->\n    <parent>\n        <groupId>Hacker.walker</groupId>\n        <artifactId>Hacker-walker-cloud</artifactId>\n        <version>1.0-SNAPSHOT</version>\n        <relativePath>../pom.xml</relativePath>\n    </parent>\n\n    <!--子类-->\n    <artifactId>Hacker-framework-common</artifactId>\n\n    <dependencies>\n\n        <!--util-->\n        <dependency>\n            <groupId>Hacker.walker</groupId>\n            <artifactId>Hacker-framework-util</artifactId>\n            <version>1.0-SNAPSHOT</version>\n            <scope>compile</scope>\n        </dependency>\n        <!--util-->\n\n        <!--model-->\n        <dependency>\n            <groupId>Hacker.walker</groupId>\n            <artifactId>Hacker-framework-model</artifactId>\n            <version>1.0-SNAPSHOT</version>\n            <scope>compile</scope>\n        </dependency>\n        <!--model-->\n\n    </dependencies>\n\n</project>\n"
  },
  {
    "path": "hacker-framework-common/src/main/java/hacker/framework/common/annotation/Constants.java",
    "content": "package hacker.framework.common.annotation;\n\n/**\n *\n * @Description: J X N H\n * @EnglishName LuKe\n * @authod LiuQi\n * @date 2019/6/3 11:37\n */\npublic class Constants {\n    public static final Short STATUS_ENABLE = 1;\n\n    public static final Short STATUS_DISABLE = 0;\n\n    public static final Integer PRIV_SUPER = 999;\n\n    public static final String AUTH_USER = \"AUTH_USER\";\n\n    public static final Integer PAGE_DEF_START = 1;\n\n    public static final Integer PAGE_DEF_SIZE = 10;\n\n    public static final String CUSTOMER_ROLE_NAME = \"超级管理员\";\n\n    public static final String CUSTOMER_ROLE_DESC = \"管理所有权限,该权限组无法删除!\";\n\n    public static final Integer CUSTOMER_DEF_STATUS = 0;\n}\n"
  },
  {
    "path": "hacker-framework-common/src/main/java/hacker/framework/common/annotation/DistributedLock.java",
    "content": "package hacker.framework.common.annotation;\n\nimport java.lang.annotation.ElementType;\nimport java.lang.annotation.Retention;\nimport java.lang.annotation.RetentionPolicy;\nimport java.lang.annotation.Target;\n\n/**\n * @Description: J X N H\n * @EnglishName LuKe\n * @authod LiuQi\n * @date 2019/6/3 12:37\n */\n@Retention(RetentionPolicy.RUNTIME)\n@Target(ElementType.METHOD)\npublic @interface DistributedLock {\n\n    /**\n     * 当前锁的：自动过期时间  （单位：秒）默认值：1s\n     *\n     * @return\n     */\n    long value() default 1;\n}\n"
  },
  {
    "path": "hacker-framework-common/src/main/java/hacker/framework/common/annotation/Limiter.java",
    "content": "package hacker.framework.common.annotation;\n\n\nimport java.lang.annotation.ElementType;\nimport java.lang.annotation.Retention;\nimport java.lang.annotation.RetentionPolicy;\nimport java.lang.annotation.Target;\n\n/**\n * 用户级别限流\n *\n * @Description: J X N H\n * @EnglishName LuKe\n * @authod LiuQi\n * @date 2019/6/3 12:37\n */\n@Retention(RetentionPolicy.RUNTIME)\n@Target(ElementType.METHOD)\npublic @interface Limiter {\n\n\n    /**\n     * 限流次数，配合expire使用      默认：1次/s\n     *\n     * @return\n     */\n    int value() default 1;\n\n    /**\n     * 限流时间跨度 （单位：秒）      默认：1s\n     *\n     * @return\n     */\n    int expire() default 1;\n}\n"
  },
  {
    "path": "hacker-framework-common/src/main/java/hacker/framework/common/annotation/ResponseCode.java",
    "content": "package hacker.framework.common.annotation;\n\n/**\n *\n * @Description: J X N H\n * @EnglishName LuKe\n * @authod LiuQi\n * @date 2019/6/3 12:34\n */\npublic enum ResponseCode {\n    SUCCESS(\"0\", \"OK\"),\n    ERROR(\"1\", \"数据异常!\");\n\n    private String status;\n\n    private String message;\n\n    ResponseCode(String status, String message) {\n        this.status = status;\n        this.message = message;\n    }\n\n    public String getStatus() {\n        return status;\n    }\n\n    public void setStatus(String status) {\n        this.status = status;\n    }\n\n    public String getMessage() {\n        return message;\n    }\n\n    public void setMessage(String message) {\n        this.message = message;\n    }\n}\n"
  },
  {
    "path": "hacker-framework-common/src/main/java/hacker/framework/common/aspect/DistributedLockAspect.java",
    "content": "package hacker.framework.common.aspect;\n\nimport hacker.framework.common.annotation.DistributedLock;\nimport org.apache.commons.lang3.ArrayUtils;\nimport org.aspectj.lang.ProceedingJoinPoint;\nimport org.aspectj.lang.annotation.Around;\nimport org.aspectj.lang.annotation.Aspect;\nimport org.aspectj.lang.reflect.MethodSignature;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Component;\n\nimport java.io.Serializable;\nimport java.lang.reflect.Method;\nimport java.util.Random;\n\n/**\n * 分布式🔐\n *\n * @Description: J X N H\n * @EnglishName LuKe\n * @authod LiuQi\n * @date 2019/6/3 11:58\n */\n@Aspect\n@Component\npublic class DistributedLockAspect {\n\n    private static final Logger logger = LoggerFactory.getLogger(DistributedLockAspect.class);\n\n    /**\n     * 🔐KEY前缀\n     */\n    private static final String LOCK_KEY_PREFIX = \"lock:key:\";\n\n    @Autowired\n    private LockUtils lockUtils;\n\n    //当前锁的：自动过期时间\n    @Around(value = \"@annotation(hacker.framework.common.annotation.DistributedLock)\")\n    public Object around(ProceedingJoinPoint point) throws Throwable {\n\n        MethodSignature methodSignature = (MethodSignature) point.getSignature();\n        Method method = methodSignature.getMethod();\n\n        DistributedLock annotation = method.getAnnotation(DistributedLock.class);\n\n        // timeOut\n        long timeOut = annotation.value();\n\n\n        // key\n        // sessionId\n        Serializable sessionId = null;   // TODO SessionUtils.getSessionId();\n        // methodName\n        String fullMethodName = getFullMethodName(method);\n        // hashCode\n        int fullMethodNameHashCode = fullMethodName.hashCode();\n        // prefix + methodName + sessionId + hashCode\n        String key = LOCK_KEY_PREFIX + method.getName() + \":\" + sessionId + \":\" + fullMethodNameHashCode;\n\n\n        // randomVal     生成一个随机数：作为当前🔐的val\n        long randomNum = new Random().nextInt(1000000000);\n        String val = System.currentTimeMillis() + String.valueOf(randomNum);\n\n\n        try {\n\n            // 获取锁\n            boolean getLock = lockUtils.lock(key, val, timeOut);\n            logger.debug(getLock ? \"获取锁成功！KEY：\" + key + \" , VAL：\" + val : \"获取锁失败！KEY：\" + key + \" , VAL：\" + val);\n\n            // 获m取到锁\n            if (getLock) {\n\n                // 执行原方法\n                Object result = point.proceed();\n\n                return result;\n            }\n\n        } catch (Exception ex) {\n\n            throw ex;\n\n        } finally {\n\n            // 释放锁\n            boolean releaseLock = lockUtils.releaseLock(key, val);\n            logger.debug(releaseLock ? \"释放锁成功！KEY：\" + key + \" , VAL：\" + val : \"释放锁失败！KEY：\" + key + \" , VAL：\" + val);\n        }\n\n        return null;\n    }\n\n    /**\n     * method的全方法名\n     *\n     * @param method\n     * @return\n     */\n    private static String getFullMethodName(Method method) {\n\n        String fullMethodName = \"\";\n\n        String clazzName = method.getDeclaringClass().getName();\n        String methodName = method.getName();\n\n        fullMethodName += clazzName;\n        fullMethodName += methodName;\n\n        Class<?>[] parameterTypes = method.getParameterTypes();\n\n        if (ArrayUtils.isNotEmpty(parameterTypes)) {\n\n            for (int i = 0; i < parameterTypes.length; i++) {\n\n                fullMethodName += parameterTypes[i].getName();\n            }\n        }\n\n        return fullMethodName;\n    }\n\n}\n"
  },
  {
    "path": "hacker-framework-common/src/main/java/hacker/framework/common/aspect/GlobalExceptionHandler.java",
    "content": "package hacker.framework.common.aspect;\n\nimport com.alibaba.fastjson.JSONPathException;\nimport hacker.framework.common.exception.JxnhException;\nimport hacker.framework.common.request.ResultBean;\nimport lombok.extern.slf4j.Slf4j;\nimport org.apache.commons.lang3.StringUtils;\nimport org.springframework.http.HttpStatus;\nimport org.springframework.jdbc.BadSqlGrammarException;\nimport org.springframework.web.bind.MethodArgumentNotValidException;\nimport org.springframework.web.bind.MissingServletRequestParameterException;\nimport org.springframework.web.bind.annotation.ControllerAdvice;\nimport org.springframework.web.bind.annotation.ExceptionHandler;\nimport org.springframework.web.bind.annotation.ResponseBody;\nimport org.springframework.web.bind.annotation.ResponseStatus;\n\nimport javax.websocket.DecodeException;\n\n\n/**\n * 统一异常处理\n *\n * @Description: J X N H\n * @EnglishName LuKe\n * @authod LiuQi\n * @date 2019/6/3 12:12\n */\n@Slf4j\n@ControllerAdvice\npublic class GlobalExceptionHandler {\n\n    @ExceptionHandler(Exception.class)\n    @ResponseStatus(value = HttpStatus.OK)\n    @ResponseBody\n    public ResultBean<Object> exceptionHandler(Throwable e) {\n\n        return doGlobalExceptionHandler(e);\n    }\n\n    /**\n     * 执行异常处理\n     *\n     * @param e\n     * @return\n     */\n    public static ResultBean<Object> doGlobalExceptionHandler(Throwable e) {\n\n        log.error(e.getMessage(), e);\n\n        if (e instanceof JxnhException) {\n            Integer code = ((JxnhException) e).getCode();\n            String msg = ((JxnhException) e).getMsg();\n            if (null == code) {\n                return ResultBean.ofError(msg);\n            } else {\n                return ResultBean.ofError(code, msg);\n            }\n        } else if (e instanceof MissingServletRequestParameterException) {\n            String parameterName = ((MissingServletRequestParameterException) e).getParameterName();\n            return ResultBean.ofError(parameterName + \"不能为空\");\n        } else if (e instanceof MethodArgumentNotValidException) {\n            return ResultBean.ofError(\"表单必录数据填写不完整\");\n        } else if (e instanceof DecodeException) {\n            return ResultBean.ofError(e.getMessage());\n        } else if (e instanceof IllegalArgumentException) {\n            return ResultBean.ofError(e.getMessage());\n        } else if (e instanceof NullPointerException) {\n            return ResultBean.ofError(e.getMessage());\n        } else if (e instanceof NumberFormatException) {\n            return ResultBean.ofError(\"参数类型转换异常\");\n        }else if (e instanceof JSONPathException) {\n            return ResultBean.ofError(\"类型转换异常\");\n        } else if (e instanceof BadSqlGrammarException) {\n            return ResultBean.ofError(\"出错啦,请稍后再试!\");\n        } else if (e instanceof RuntimeException) {\n            return ResultBean.ofError(\"出错啦,请稍后再试!\");\n        } else if (e instanceof Exception) {\n            return ResultBean.ofError(\"出错啦,请稍后再试!\");\n        } else {\n            String errorMsg = e.toString() == null ? e.getMessage() : e.toString();\n            return ResultBean.ofError(StringUtils.isBlank(errorMsg) ? \"未知错误\" : errorMsg);\n        }\n    }\n\n}\n"
  },
  {
    "path": "hacker-framework-common/src/main/java/hacker/framework/common/aspect/GlobalLogHandler.java",
    "content": "package hacker.framework.common.aspect;\n\nimport com.alibaba.fastjson.JSON;\nimport lombok.extern.slf4j.Slf4j;\nimport org.apache.commons.lang3.StringUtils;\nimport org.aspectj.lang.ProceedingJoinPoint;\nimport org.aspectj.lang.annotation.Around;\nimport org.aspectj.lang.annotation.Aspect;\nimport org.springframework.stereotype.Component;\nimport org.springframework.util.CollectionUtils;\nimport org.springframework.web.context.request.RequestContextHolder;\nimport org.springframework.web.context.request.ServletRequestAttributes;\n\nimport javax.servlet.http.HttpServletRequest;\nimport javax.servlet.http.HttpServletResponse;\nimport java.io.IOException;\nimport java.util.Arrays;\nimport java.util.List;\nimport java.util.stream.Collectors;\n\n/**\n * 统一日志处理\n *\n * @Description: J X N H\n * @EnglishName LuKe\n * @authod LiuQi\n * @date 2019/6/3 11:58\n */\n@Aspect\n@Component\n@Slf4j\npublic class GlobalLogHandler {\n\n\n    //加载包路径\n    @Around(value = \"execution(* hacker.*.manage.controller..*.*(..))\")\n    public Object doAround(ProceedingJoinPoint pjp) throws Throwable {\n\n        long startTime = System.currentTimeMillis();\n\n        // 日志记录   ------》有的方法里会出项BUG----->这里执行一次，方法里还会执行一次，第一次有值，第二次报空了\n//        log(pjp);\n\n        // exec   反射\n        Object result = pjp.proceed();\n\n        // 统计时间\n        long totalTime = System.currentTimeMillis() - startTime;\n        log.info(\"totalTime : {}s\", new Double(totalTime) / 1000);\n\n        return result;\n    }\n\n    /**\n     * 记录日志\n     * @param pjp\n     */\n    private void log(ProceedingJoinPoint pjp) {\n\n        Object[] args = pjp.getArgs();\n\n        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.currentRequestAttributes()).getRequest();\n\n        List<Object> argList = Arrays.stream(args)\n                .filter(arg -> !(arg instanceof HttpServletRequest) && !(arg instanceof HttpServletResponse))\n                .collect(Collectors.toList());\n\n        if (CollectionUtils.isEmpty(argList)) {\n            log.info(Arrays.asList(request.getServletPath(), getIpAddress(request)).stream().collect(Collectors.joining(\" \")));\n        } else {\n            log.info(Arrays.asList(request.getServletPath(), getIpAddress(request), JSON.toJSONString(argList)).stream().collect(Collectors.joining(\" \")));\n        }\n\n    }\n\n\n\n\n    /**\n     * 获取请求主机IP地址,如果通过代理进来，则透过防火墙获取真实IP地址\n     *\n     * @param request\n     * @return\n     * @throws IOException\n     */\n    public static String getIpAddress(HttpServletRequest request) {\n\n\n\n\n        String ip = request.getHeader(\"X-Forwarded-For\");\n\n\n\n        if (ipIsBlank(ip)) {\n            ip = request.getHeader(\"Proxy-Client-IP\");\n\n            if (ipIsBlank(ip)) {\n                ip = request.getHeader(\"WL-Proxy-Client-IP\");\n\n                if (ipIsBlank(ip)) {\n                    ip = request.getHeader(\"HTTP_CLIENT_IP\");\n\n                    if (ipIsBlank(ip)) {\n                        ip = request.getHeader(\"HTTP_X_FORWARDED_FOR\");\n\n                        if (ipIsBlank(ip)) {\n                            ip = request.getRemoteAddr();\n                        }\n                    }\n                }\n            }\n\n        } else if (ip.length() > 15) {\n\n\n            // 经过多层代理后会有多个代理，取第一个ip地址就可以了\n            String[] ips = ip.split(\"\\\\,\");\n\n            for (int index = 0; index < ips.length; index++) {\n\n                String strIp = ips[index];\n\n                if (!(\"unknown\".equalsIgnoreCase(strIp))) {\n                    ip = strIp;\n                    break;\n                }\n            }\n        }\n\n        return ip;\n    }\n\n    private static boolean ipIsBlank(String ip) {\n\n        boolean ipIsBank = StringUtils.isBlank(ip) || \"unknown\".equalsIgnoreCase(ip);\n\n        return ipIsBank;\n    }\n\n}\n"
  },
  {
    "path": "hacker-framework-common/src/main/java/hacker/framework/common/aspect/GlobalVariable.java",
    "content": "package hacker.framework.common.aspect;\n\nimport lombok.Data;\nimport org.springframework.beans.factory.annotation.Value;\nimport org.springframework.stereotype.Component;\n\n\n/**\n * 全局变量相关配置信息\n *\n * @Description: J X N H\n * @EnglishName LuKe\n * @authod LiuQi\n * @date 2019/6/3 11:44\n */\n@Component\n@Data\npublic class GlobalVariable {\n\n\n    /**\n     * 消息校验token\n     */\n    @Value(\"${token}\")\n    private String token;\n\n    /**\n     * secret\n     */\n    @Value(\"${secret}\")\n    private String secret;\n\n}\n"
  },
  {
    "path": "hacker-framework-common/src/main/java/hacker/framework/common/aspect/LimiterAspect.java",
    "content": "package hacker.framework.common.aspect;\n\nimport com.alibaba.fastjson.JSON;\nimport com.google.common.collect.Lists;\nimport hacker.framework.common.annotation.Limiter;\nimport org.aspectj.lang.ProceedingJoinPoint;\nimport org.aspectj.lang.annotation.Around;\nimport org.aspectj.lang.annotation.Aspect;\nimport org.aspectj.lang.reflect.MethodSignature;\nimport org.springframework.core.io.ClassPathResource;\nimport org.springframework.data.redis.core.StringRedisTemplate;\nimport org.springframework.data.redis.core.script.DefaultRedisScript;\nimport org.springframework.scripting.support.ResourceScriptSource;\nimport org.springframework.stereotype.Component;\nimport org.springframework.web.context.request.RequestContextHolder;\nimport org.springframework.web.context.request.ServletRequestAttributes;\n\nimport javax.annotation.Resource;\nimport javax.servlet.http.HttpServletRequest;\nimport java.lang.reflect.Method;\n\n@Aspect\n@Component\npublic class LimiterAspect {\n\n    /**\n     * LIMIT-KEY 前缀\n     */\n    private static final String LIMIT_KEY_PREFIX = \"limit:key:\";\n\n    @Resource\n    private StringRedisTemplate stringRedisTemplate;\n\n\n    /**\n     * @param point\n     */\n    @Around(\"@annotation(hacker.framework.common.annotation.Limiter)\")\n    public Object around(ProceedingJoinPoint point) throws Throwable {\n\n        // requestPath\n        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.currentRequestAttributes()).getRequest();\n        String route = request.getServletPath();\n\n        MethodSignature methodSignature = (MethodSignature) point.getSignature();\n        Method method = methodSignature.getMethod();\n        Limiter limiter = method.getAnnotation(Limiter.class);\n\n        int limit = limiter.value();\n        int expire = limiter.expire();\n\n        // 唯一：登录用户SessionId + 参数\n        String sessionId = null; // todo SecurityUtils.getSubject().getSession().getId().toString();\n        String user = sessionId + \":\" + JSON.toJSONString(point.getArgs());\n        String userHash = String.valueOf(user.hashCode());\n\n        //判断登陆次数\n        if (!doLimiter(route, userHash, limit, expire)) {\n            throw new RuntimeException(\"操作太过频繁，请勿重复点击！\");\n        }\n\n        return point.proceed();\n    }\n\n    /**\n     * 限流Redis-lua实现\n     *\n     * @param route\n     * @param userHash\n     * @param limit\n     * @param expire\n     * @return\n     */\n    private boolean doLimiter(String route, String userHash, Integer limit, int expire) {\n\n        final String key = LIMIT_KEY_PREFIX + route + \":\" + userHash;\n\n        DefaultRedisScript<Long> redisScript = new DefaultRedisScript<>();\n        redisScript.setScriptSource(new ResourceScriptSource(new ClassPathResource(\"lua/rateLimit.lua\")));\n        redisScript.setResultType(Long.class);\n\n        Object result = stringRedisTemplate.execute(redisScript, Lists.newArrayList(key),\n                String.valueOf(limit), String.valueOf(expire));\n\n        if ((long) result == 1) {\n            return true;\n        }\n        return false;\n    }\n\n}\n"
  },
  {
    "path": "hacker-framework-common/src/main/java/hacker/framework/common/aspect/LockUtils.java",
    "content": "package hacker.framework.common.aspect;\n\nimport com.google.common.collect.Lists;\nimport org.springframework.core.io.ClassPathResource;\nimport org.springframework.data.redis.core.StringRedisTemplate;\nimport org.springframework.data.redis.core.script.DefaultRedisScript;\nimport org.springframework.scripting.support.ResourceScriptSource;\nimport org.springframework.stereotype.Component;\n\nimport javax.annotation.Resource;\n\n/**\n * @Description: J X N H\n * @EnglishName LuKe\n * @authod LiuQi\n * @date 2019/6/3 12:37\n */\n@Component\npublic class LockUtils {\n\n    @Resource\n    private StringRedisTemplate stringRedisTemplate;\n\n\n    /**\n     * 获取🔐\n     * @param key\n     * @param randomVal\n     * @param timeOut   单位：秒\n     */\n    public boolean lock(String key, String randomVal, Long timeOut) {\n\n        DefaultRedisScript<Long> redisScript = new DefaultRedisScript<>();\n        redisScript.setScriptSource(new ResourceScriptSource(new ClassPathResource(\"lua/distributedLock.lua\")));\n        redisScript.setResultType(Long.class);\n\n        Object result = stringRedisTemplate.execute(redisScript, Lists.newArrayList(key), randomVal, String.valueOf(timeOut));\n\n        if ((long) result == 1) {\n            return true;\n        }\n        return false;\n    }\n\n    /**\n     * 释放🔐\n     *\n     * @param key\n     * @param val\n     * @return\n     */\n    public boolean releaseLock(String key, String val) {\n\n        Class<Long> clazz = Long.class;\n        DefaultRedisScript<Long> redisScript = new DefaultRedisScript<>();\n        redisScript.setScriptSource(new ResourceScriptSource(new ClassPathResource(\"lua/releaseLock.lua\")));\n        redisScript.setResultType(clazz);\n\n        Object result = stringRedisTemplate.execute(redisScript, Lists.newArrayList(key), val);\n\n        if ((long) result == 1) {\n            return true;\n        }\n        return false;\n    }\n}\n"
  },
  {
    "path": "hacker-framework-common/src/main/java/hacker/framework/common/aspect/SqlTimeInterceptor.java",
    "content": "package hacker.framework.common.aspect;\n\nimport org.apache.ibatis.executor.Executor;\nimport org.apache.ibatis.mapping.BoundSql;\nimport org.apache.ibatis.mapping.MappedStatement;\nimport org.apache.ibatis.mapping.ParameterMapping;\nimport org.apache.ibatis.plugin.*;\nimport org.apache.ibatis.reflection.MetaObject;\nimport org.apache.ibatis.session.Configuration;\nimport org.apache.ibatis.session.ResultHandler;\nimport org.apache.ibatis.session.RowBounds;\nimport org.apache.ibatis.type.TypeHandlerRegistry;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\nimport java.text.DateFormat;\nimport java.util.Date;\nimport java.util.List;\nimport java.util.Locale;\nimport java.util.Properties;\n\n/**\n * Sql逆向工程\n * SqlTimeInterceptor\n */\n@Intercepts({@Signature(type = Executor.class, method = \"update\", args = {MappedStatement.class, Object.class}),\n        @Signature(type = Executor.class, method = \"query\", args = {MappedStatement.class, Object.class,\n                RowBounds.class, ResultHandler.class})})\npublic class SqlTimeInterceptor implements Interceptor {\n\n    @SuppressWarnings(\"unused\")\n    private Properties properties;\n    private static Logger log = LoggerFactory.getLogger(SqlTimeInterceptor.class);\n\n    @Override\n    public Object intercept(Invocation invocation) throws Throwable {\n        MappedStatement mappedStatement = (MappedStatement) invocation.getArgs()[0];\n        Object parameter = null;\n        if (invocation.getArgs().length > 1) {\n            parameter = invocation.getArgs()[1];\n        }\n        String sqlId = mappedStatement.getId();\n        BoundSql boundSql = mappedStatement.getBoundSql(parameter);\n        Configuration configuration = mappedStatement.getConfiguration();\n        Object returnValue = null;\n        long start = System.currentTimeMillis();\n        returnValue = invocation.proceed();\n        long end = System.currentTimeMillis();\n        long time = (end - start);\n        // 大于time秒，则打印SQL  -> 记录慢SQL用\n        if (time > 2000) {\n            String sql = getSql(configuration, boundSql, sqlId, time);\n            log.info(sql);\n        }\n        return returnValue;\n    }\n\n    public static String getSql(Configuration configuration, BoundSql boundSql, String sqlId, long time) {\n        String sql = showSql(configuration, boundSql);\n        StringBuilder str = new StringBuilder(100);\n        str.append(sqlId);\n        str.append(\":\");\n        str.append(sql);\n        str.append(\": 执行耗时\");\n        str.append(time);\n        str.append(\"ms\");\n        return str.toString();\n    }\n\n    private static String getParameterValue(Object obj) {\n        String value = null;\n        if (obj instanceof String) {\n            value = \"'\" + obj.toString() + \"'\";\n        } else if (obj instanceof Date) {\n            DateFormat formatter = DateFormat.getDateTimeInstance(DateFormat.DEFAULT, DateFormat.DEFAULT, Locale.CHINA);\n            value = \"'\" + formatter.format(new Date()) + \"'\";\n        } else {\n            if (obj != null) {\n                value = obj.toString();\n            } else {\n                value = \"\";\n            }\n\n        }\n        return value;\n    }\n\n    public static String showSql(Configuration configuration, BoundSql boundSql) {\n        Object parameterObject = boundSql.getParameterObject();\n        List<ParameterMapping> parameterMappings = boundSql.getParameterMappings();\n        String sql = boundSql.getSql().replaceAll(\"[\\\\s]+\", \" \");\n        if (parameterMappings.size() > 0 && parameterObject != null) {\n            TypeHandlerRegistry typeHandlerRegistry = configuration.getTypeHandlerRegistry();\n            if (typeHandlerRegistry.hasTypeHandler(parameterObject.getClass())) {\n                sql = sql.replaceFirst(\"\\\\?\", getParameterValue(parameterObject));\n\n            } else {\n                MetaObject metaObject = configuration.newMetaObject(parameterObject);\n                for (ParameterMapping parameterMapping : parameterMappings) {\n                    String propertyName = parameterMapping.getProperty();\n                    if (metaObject.hasGetter(propertyName)) {\n                        Object obj = metaObject.getValue(propertyName);\n                        sql = sql.replaceFirst(\"\\\\?\", getParameterValue(obj));\n                    } else if (boundSql.hasAdditionalParameter(propertyName)) {\n                        Object obj = boundSql.getAdditionalParameter(propertyName);\n                        sql = sql.replaceFirst(\"\\\\?\", getParameterValue(obj));\n                    }\n                }\n            }\n        }\n        return sql;\n    }\n\n    @Override\n    public Object plugin(Object target) {\n        return Plugin.wrap(target, this);\n    }\n\n    @Override\n    public void setProperties(Properties properties0) {\n        this.properties = properties0;\n    }\n}\n"
  },
  {
    "path": "hacker-framework-common/src/main/java/hacker/framework/common/consts/CommonConst.java",
    "content": "/**\n * MIT License\n * Copyright (c) 2018 yadong.zhang\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\npackage hacker.framework.common.consts;\n\n/**\n * walker公用常量类\n *\n * @Description: J X N H\n * @EnglishName LuKe\n * @authod LiuQi(walker)\n * @date 2019/6/15 23:25\n */\npublic class CommonConst {\n    /***\n     *uuid盐,hope专用\n     */\n    public static final String ZYD_SECURITY_KEY = \"929123f8f17944e8b0a531045453e1f1\";\n    /***\n     *程序错误状态码\n     */\n    public static final int DEFAULT_ERROR_CODE = 500;\n    /***\n     * 程序成功状态码\n     */\n    public static final int DEFAULT_SUCCESS_CODE = 200;\n\n    /***\n     * session key\n     */\n    public static final String USER_SESSION_KEY = \"user_session_key\";\n}\n"
  },
  {
    "path": "hacker-framework-common/src/main/java/hacker/framework/common/enums/BaseExceptionEnum.java",
    "content": "package hacker.framework.common.enums;\n\n\n\n/**\n * code\n * @Description: J X N H\n * @EnglishName LuKe\n * @authod LiuQi\n * @date 2019/6/3 11:45\n */\npublic enum BaseExceptionEnum {\n\n    NOT_LOGIN(10001, \"操作会话已失效，请重新登录！\"),\n    NOT_PERMISSION(10002, \"您无该权限\"),\n\n    //目前就用到成功和失败\n    EC00000200(200, \"success\"),\n    EC00000500(500, \"系统异常\"),\n    EC00000404(404, \"该接口不存在\"),\n\n    EC00000000(100000, \"无法加载切点对象\"),\n    EC00000001(100001, \"链接点参数为空\"),\n    EC00000002(100002, \"类或对象访问权限限制\"),\n    EC00000003(100003, \"I/O异常\"),\n    EC00000004(100004, \"obj to json 失败\"),\n    EC00000005(100005, \"不支持字符编码\"),\n    EC00000006(100006, \"没有此算法\"),\n    EC00000007(100007, \"缺少算法配置参数\"),\n    EC00000008(100008, \"读取私钥失败\"),\n    EC00000009(100009, \"加载私钥失败\"),\n    EC00000010(100010, \"密文数据已损坏\"),\n    EC00000011(100011, \"私钥长度非法\"),\n    EC00000012(100012, \"私钥非法\"),\n    EC00000013(100013, \"读取公钥失败\"),\n    EC00000014(100014, \"加载公钥失败\"),\n    EC00000015(100015, \"明文数据已损坏\"),\n    EC00000016(100016, \"公钥非法\"),\n    EC00000017(100017, \"公钥长度非法\"),\n    EC00000018(100018, \"签名失败\"),\n    EC00000019(100019, \"验签失败\"),\n\n\n    EL00000000(200000, \"数据报为空\"),\n    EL00000001(200001, \"转换数据报返回为空\"),\n    EL00000002(200002, \"目标名称为空\"),\n    EL00000003(200003, \"调用API失败\"),\n    EL00000004(200004, \"参数名不能为空\"),\n    EL00000005(200005, \"参数不能为空\"),\n    EA00000001(200001, \"签名认证失败\");\n\n    private int code;\n\n    private String message;\n\n    BaseExceptionEnum(int code, String message) {\n        this.code = code;\n        this.message = message;\n    }\n\n    public int getCode() {\n        return code;\n    }\n\n    public void setCode(int code) {\n        this.code = code;\n    }\n\n    public String getMessage() {\n        return message;\n    }\n\n    public void setMessage(String message) {\n        this.message = message;\n    }\n}\n"
  },
  {
    "path": "hacker-framework-common/src/main/java/hacker/framework/common/exception/AppException.java",
    "content": "package hacker.framework.common.exception;\n\n/**\n * @description 自定义异常类\n *\n * @Description: J X N H\n * @EnglishName LuKe\n * @authod LiuQi\n * @date 2019/6/3 12:34\n */\npublic class AppException extends Exception {\n\n    public AppException() {\n        super();\n    }\n\n    public AppException(String message) {\n        super(message);\n    }\n\n    public AppException(String message, Throwable cause) {\n        super(message, cause);\n    }\n\n    public AppException(Throwable cause) {\n        super(cause);\n    }\n}\n"
  },
  {
    "path": "hacker-framework-common/src/main/java/hacker/framework/common/exception/JxnhException.java",
    "content": "package hacker.framework.common.exception;\n\n\nimport hacker.framework.common.enums.BaseExceptionEnum;\n\n/**\n * 自定义堇夏年华异常\n *\n * @Description: J X N H\n * @EnglishName LuKe\n * @authod LiuQi\n * @date 2019/6/3 14:58\n */\npublic class JxnhException extends RuntimeException {\n\n    private int code;\n\n    private String msg;\n\n\n    public JxnhException() {\n        super();\n    }\n\n    public JxnhException(Throwable cause) {\n        super(cause);\n    }\n\n    public JxnhException(String msg) {\n        super(msg);\n        this.msg = msg;\n    }\n\n    public JxnhException(int code, String msg) {\n        super(msg);\n        this.code = code;\n        this.msg = msg;\n    }\n\n    public JxnhException(BaseExceptionEnum exEnum) {\n        this.code = exEnum.getCode();\n        this.msg = exEnum.getMessage();\n    }\n\n    public int getCode() {\n        return code;\n    }\n\n    public String getMsg() {\n        return msg;\n    }\n\n}\n"
  },
  {
    "path": "hacker-framework-common/src/main/java/hacker/framework/common/object/BaseConditionVo.java",
    "content": "package hacker.framework.common.object;\n\nimport lombok.Data;\nimport lombok.EqualsAndHashCode;\nimport org.springframework.format.annotation.DateTimeFormat;\n\nimport java.util.Date;\n\n/**\n * 基础转换 其实分页工具会自动计算，只需要num和size即可\n *\n * @Description: J X N H\n * @EnglishName LuKe\n * @authod LiuQi(walker)\n * @date 2019/6/15 23:15\n */\n@Data\n@EqualsAndHashCode(callSuper = false)\npublic class BaseConditionVo {\n\n    public final static int DEFAULT_PAGE_SIZE = 10;\n    private int pageNum = 1;\n    private int pageSize = 0;\n    private int pageStart = 0;\n    private String orderField;\n    private String orderDirection;\n    private String keywords;\n    @DateTimeFormat(pattern = \"yyyy-MM-dd HH:mm:ss\")\n    private Date startDate;\n    @DateTimeFormat(pattern = \"yyyy-MM-dd HH:mm:ss\")\n    private Date endDate;\n\n    public int getPageSize() {\n        return pageSize > 0 ? pageSize : DEFAULT_PAGE_SIZE;\n    }\n\n    public int getPageStart() {\n        return pageNum > 0 ? (pageNum - 1) * pageSize : 0;\n    }\n}\n"
  },
  {
    "path": "hacker-framework-common/src/main/java/hacker/framework/common/object/PageResultVo.java",
    "content": "package hacker.framework.common.object;\n\nimport lombok.Data;\nimport lombok.EqualsAndHashCode;\n\nimport java.util.List;\n\n/**\n * 用于bootstrap table返回json格式\n *\n * @Description: J X N H\n * @EnglishName LuKe\n * @authod LiuQi(walker)\n * @date 2019/6/15 23:15\n */\n@Data\n@EqualsAndHashCode(callSuper = false)\npublic class PageResultVo {\n    private Long total;\n    private List rows;\n\n    public PageResultVo(Long total, List rows) {\n        this.total = total;\n        this.rows = rows;\n    }\n\n    public PageResultVo() {\n    }\n}\n"
  },
  {
    "path": "hacker-framework-common/src/main/java/hacker/framework/common/object/ResponseVo.java",
    "content": "package hacker.framework.common.object;\n\nimport com.alibaba.fastjson.JSONObject;\nimport com.alibaba.fastjson.serializer.SerializerFeature;\nimport hacker.framework.common.enums.BaseExceptionEnum;\nimport lombok.Data;\nimport lombok.EqualsAndHashCode;\n\nimport java.util.Collection;\nimport java.util.List;\n\n/**\n * 使用阿里的fastjson\n *\n * @Description: J X N H\n * @EnglishName LuKe\n * @authod LiuQi(walker)\n * @date 2019/6/15 23:15\n */\n@Data\n@EqualsAndHashCode(callSuper = false)\npublic class ResponseVo<T> {\n    private Integer status;\n    private String message;\n    private T data;\n\n    public ResponseVo(Integer status, String message, T data) {\n        this.status = status;\n        this.message = message;\n        this.data = data;\n    }\n\n    public ResponseVo(BaseExceptionEnum status, T data) {\n        this(status.getCode(), status.getMessage(), data);\n    }\n\n    public String toJson() {\n        T t = this.getData();\n        if (t instanceof List || t instanceof Collection) {\n            return JSONObject.toJSONString(this, SerializerFeature.WriteNullListAsEmpty);\n        } else {\n            return JSONObject.toJSONString(this, SerializerFeature.WriteMapNullValue);\n        }\n    }\n}\n"
  },
  {
    "path": "hacker-framework-common/src/main/java/hacker/framework/common/object/ResultUtil.java",
    "content": "package hacker.framework.common.object;\n\nimport hacker.framework.common.consts.CommonConst;\nimport hacker.framework.common.enums.BaseExceptionEnum;\nimport org.springframework.web.servlet.ModelAndView;\n\nimport java.util.Map;\n\n/**\n * 接口返回工具\n * @Description: J X N H\n * @EnglishName LuKe\n * @authod LiuQi(walker)\n * @date 2019/6/15 23:15\n */\npublic class ResultUtil {\n    /**\n     * ModelAndView\n     **/\n    public static ModelAndView view(String view) {\n        return new ModelAndView(view);\n    }\n\n    public static ModelAndView view(String view, Map<String, Object> model) {\n        return new ModelAndView(view, model);\n    }\n\n    public static ModelAndView redirect(String view) {\n        return new ModelAndView(\"redirect:\" + view);\n    }\n\n    /**\n     * vo\n     **/\n    public static ResponseVo vo(int code, String message, Object data) {\n        return new ResponseVo<>(code, message, data);\n    }\n\n\n    /**\n     * error\n     **/\n    public static ResponseVo error(int code, String message) {\n        return vo(code, message, null);\n    }\n\n    public static ResponseVo error(BaseExceptionEnum statusEnum) {\n        return vo(statusEnum.getCode(), statusEnum.getMessage(), null);\n    }\n\n    public static ResponseVo error(String message) {\n        return vo(CommonConst.DEFAULT_ERROR_CODE, message, null);\n    }\n\n    /**\n     * success\n     **/\n    public static ResponseVo success(String message, Object data) {\n        return vo(CommonConst.DEFAULT_SUCCESS_CODE, message, data);\n    }\n\n    public static ResponseVo success(String message) {\n        return success(message, null);\n    }\n\n    public static ResponseVo success(BaseExceptionEnum statusEnum) {\n        return vo(statusEnum.getCode(), statusEnum.getMessage(), null);\n    }\n\n}\n"
  },
  {
    "path": "hacker-framework-common/src/main/java/hacker/framework/common/request/BaseCode.java",
    "content": "package hacker.framework.common.request;\n\nimport lombok.Getter;\n\n/**\n * 基础返回码\n * @Description: J X N H\n * @EnglishName LuKe\n * @authod LiuQi\n * @date 2019/6/3 14:39\n */\n@Getter\npublic enum BaseCode {\n    /**\n     * 成功\n     */\n    SUCCESS(\"200\"),\n    /**\n     * 异常失败\n     */\n    FAIL(\"500\");\n\n    BaseCode(String code) {\n        this.code = code;\n    }\n\n    private String code;\n\n    public static void main(String[] args) {\n        System.out.println(BaseCode.SUCCESS.getCode());\n    }\n}\n"
  },
  {
    "path": "hacker-framework-common/src/main/java/hacker/framework/common/request/BaseResult.java",
    "content": "package hacker.framework.common.request;\n\nimport lombok.Getter;\nimport lombok.Setter;\n\n/**\n * @description 基础支持类\n *\n * @Description: J X N H\n * @EnglishName LuKe\n * @authod LiuQi\n * @date 2019/6/3 14:36\n */\n@Getter\n@Setter\npublic class BaseResult {\n    String code;\n    String msg;\n    Object data;\n\n    public BaseResult() {\n    }\n\n    public BaseResult(String code, String msg, Object data) {\n        this.code = code;\n        this.msg = msg;\n        this.data = data;\n    }\n}\n"
  },
  {
    "path": "hacker-framework-common/src/main/java/hacker/framework/common/request/ResultBean.java",
    "content": "package hacker.framework.common.request;\n\nimport com.fasterxml.jackson.annotation.JsonInclude;\nimport hacker.framework.common.enums.BaseExceptionEnum;\n\nimport java.io.Serializable;\nimport java.util.Collection;\n\n\n/**\n * @Description: J X N H\n * @EnglishName LuKe\n * @authod LiuQi\n * @date 2019/6/3 12:34\n */\npublic class ResultBean<T> implements Serializable {\n\n    private static final long serialVersionUID = -2361820086956983473L;\n\n    /**\n     * 数据明细\n     */\n    private T data;\n\n    private T data1;\n\n\n    private Boolean success;\n\n    private int code;\n\n    private String msg;\n\n    public static long getSerialVersionUID() {\n        return serialVersionUID;\n    }\n\n    public T getData() {\n        return data;\n    }\n\n    public void setData(T data) {\n        this.data = data;\n    }\n\n    public T getData1() {\n        return data1;\n    }\n\n    public void setData1(T data1) {\n        this.data1 = data1;\n    }\n\n\n    public Boolean getSuccess() {\n        return success;\n    }\n\n    public void setSuccess(Boolean success) {\n        this.success = success;\n    }\n\n    public int getCode() {\n        return code;\n    }\n\n    public void setCode(int code) {\n        this.code = code;\n    }\n\n    public String getMsg() {\n        return msg;\n    }\n\n    public void setMsg(String msg) {\n        this.msg = msg;\n    }\n\n    public Integer getTotalNum() {\n        return totalNum;\n    }\n\n    public void setTotalNum(Integer totalNum) {\n        this.totalNum = totalNum;\n    }\n\n    public Integer getPageIndex() {\n        return pageIndex;\n    }\n\n    public void setPageIndex(Integer pageIndex) {\n        this.pageIndex = pageIndex;\n    }\n\n    public Integer getPageSize() {\n        return pageSize;\n    }\n\n    public void setPageSize(Integer pageSize) {\n        this.pageSize = pageSize;\n    }\n\n    public Integer getTotalPage() {\n        return totalPage;\n    }\n\n    public void setTotalPage(Integer totalPage) {\n        this.totalPage = totalPage;\n    }\n\n    /**\n     * 为null时,不参与序列化\n     */\n    @JsonInclude(JsonInclude.Include.NON_NULL)\n    private Integer totalNum;\n\n    @JsonInclude(JsonInclude.Include.NON_NULL)\n    private Integer pageIndex;\n\n    @JsonInclude(JsonInclude.Include.NON_NULL)\n    private Integer pageSize;\n\n    @JsonInclude(JsonInclude.Include.NON_NULL)\n    private Integer totalPage;\n\n    public static <T> ResultBean<T> ofSuccess() {\n        return of(null, true, BaseExceptionEnum.EC00000200);\n    }\n\n    public static <T> ResultBean<T> ofSuccess(T data) {\n        return of(data, true, BaseExceptionEnum.EC00000200);\n    }\n\n    public static <T> ResultBean<T> ofSuccess(T data, String msg) {\n        return of(data, true, BaseExceptionEnum.EC00000200.getCode(), msg);\n    }\n\n    public static <T> ResultBean<T> ofSuccess(T data, T date1, String msg) {\n        return of(data, date1, true, BaseExceptionEnum.EC00000200.getCode(), msg);\n    }\n\n\n    public static <T> ResultBean<T> ofSuccess(T data, BaseExceptionEnum baseExceptionEnum) {\n        return of(data, true, baseExceptionEnum);\n    }\n\n    public static <T> ResultBean<T> ofSuccess(T data, Integer totalNum, Integer pageIndex, Integer pageSize) {\n        return of(data, true, BaseExceptionEnum.EC00000200, totalNum, pageIndex, pageSize);\n    }\n\n    public static <T> ResultBean<T> ofSuccess(T data, Integer totalNum, Integer pageIndex, Integer pageSize, String msg) {\n        return of(data, true, BaseExceptionEnum.EC00000200, totalNum, pageIndex, pageSize, msg);\n    }\n\n    public static <T> ResultBean<T> of(T data, boolean success, BaseExceptionEnum baseExceptionEnum,\n                                       Integer totalNum, Integer pageIndex, Integer pageSize) {\n        return of(data, success, baseExceptionEnum, totalNum, pageIndex, pageSize, null);\n    }\n\n    public static <T> ResultBean of(T data, boolean success, BaseExceptionEnum baseExceptionEnum) {\n        if (null != baseExceptionEnum) {\n            return of(data, success, baseExceptionEnum.getCode(), baseExceptionEnum.getMessage());\n        } else {\n            return of(data, success, null, null);\n        }\n    }\n\n    public static <T> ResultBean of(T data, boolean success, Integer code, String msg) {\n        ResultBean resultBean = new ResultBean<>();\n        resultBean.setData(data);\n        resultBean.setSuccess(success);\n        resultBean.setCode(code);\n        resultBean.setMsg(msg);\n        if (data instanceof Collection) {\n            resultBean.setTotalNum(((Collection) data).size());\n        }\n        return resultBean;\n    }\n\n\n    public static <T> ResultBean of(T data, T data1, boolean success, Integer code, String msg) {\n        ResultBean resultBean = new ResultBean<>();\n        resultBean.setData(data);\n        resultBean.setData1(data1);\n        resultBean.setSuccess(success);\n        resultBean.setCode(code);\n        resultBean.setMsg(msg);\n        if (data instanceof Collection) {\n            resultBean.setTotalNum(((Collection) data).size());\n        }\n        return resultBean;\n    }\n\n    public static <T> ResultBean<T> of(T data, boolean success, BaseExceptionEnum baseExceptionEnum,\n                                       Integer totalNum, Integer pageIndex, Integer pageSize, String msg) {\n\n        ResultBean resultBean = new ResultBean();\n        resultBean.setData(data);\n        resultBean.setSuccess(success);\n        if (null != baseExceptionEnum) {\n            resultBean.setCode(baseExceptionEnum.getCode());\n            resultBean.setMsg(baseExceptionEnum.getMessage());\n        }\n        if (data instanceof Collection && null == totalNum) {\n            resultBean.setTotalNum(((Collection) data).size());\n        }\n        resultBean.setTotalNum(totalNum);\n        resultBean.setPageIndex(pageIndex);\n        resultBean.setPageSize(pageSize);\n        resultBean.setTotalPage((null == pageSize || pageSize == 0) ? null : (totalNum % pageSize == 0 ? totalNum / pageSize : (totalNum / pageSize + 1)));\n        resultBean.setMsg(msg);\n        return resultBean;\n    }\n\n\n    public static ResultBean ofError(BaseExceptionEnum baseExceptionEnum) {\n        return ofError(baseExceptionEnum.getCode(), baseExceptionEnum.getMessage());\n    }\n\n    public static ResultBean ofError(String msg) {\n        return ofError(BaseExceptionEnum.EC00000500.getCode(), msg);\n    }\n\n    public static ResultBean ofError(int code, String msg) {\n        ResultBean resultBean = new ResultBean();\n        resultBean.setSuccess(false);\n        resultBean.setCode(code);\n        resultBean.setMsg(msg);\n        resultBean.setData(null);\n        return resultBean;\n    }\n\n\n}"
  },
  {
    "path": "hacker-framework-common/src/main/java/hacker/framework/common/request/ResultInfo.java",
    "content": "package hacker.framework.common.request;\n\nimport javafx.scene.control.Pagination;\nimport lombok.Data;\n\nimport java.io.Serializable;\n\n\n/**\n * 返回结果封装\n *\n * @Description: J X N H\n * @EnglishName LuKe\n * @authod LiuQi\n * @date 2019/6/3 11:44\n */\n@Data\npublic class ResultInfo implements Serializable {\n\n\n    private String status;\n\n    private String message;\n\n    private Object data;\n\n    private Pagination pagination;    //标记页码数\n\n    private String code;\n\n\n}"
  },
  {
    "path": "hacker-framework-common/src/main/java/hacker/framework/common/request/ResultInfoUtil.java",
    "content": "package hacker.framework.common.request;\n\nimport hacker.framework.common.annotation.ResponseCode;\nimport hacker.framework.common.request.ResultInfo;\n\n/**\n * 返回结果封装结果\n *\n * @Description: J X N H\n * @EnglishName LuKe\n * @authod LiuQi\n * @date 2019/6/3 11:54\n */\npublic class ResultInfoUtil {\n\n\t/**\n\t * 提供给部分不需要出參的接口\n\t *\n\t * @return\n\t */\n\tpublic static ResultInfo success() {\n\t\treturn success(ResponseCode.SUCCESS);\n\t}\n\n\t/**\n\t * 返回成功的结果\n\t *\n\t * @param data\n\t * @return\n\t */\n\tpublic static ResultInfo success(Object data) {\n\t\treturn success(ResponseCode.SUCCESS, data);\n\t}\n\n\n\tpublic static ResultInfo error(String status, String message) {\n\t\tResultInfo result = new ResultInfo();\n\t\tresult.setStatus(status);\n\t\tresult.setMessage(message);\n\t\tresult.setData(null);\n\t\treturn result;\n\t}\n\n\n\t/**\n\t * 返回成功的结果\n\t *\n\t * @param object\n\t * @return\n\t */\n\tpublic static ResultInfo success(ResponseCode message, Object object) {\n\t\tResultInfo resultInfo = new ResultInfo();\n\t\tresultInfo.setStatus(message.getStatus());\n\t\tresultInfo.setMessage(message.getMessage());\n\t\tresultInfo.setData(object);\n\t\treturn resultInfo;\n\t}\n\n\n\tpublic static ResultInfo error() {\n\n\t\treturn error(ResponseCode.ERROR);\n\t}\n\n\tpublic static ResultInfo error(Object data) {\n\t\treturn error(ResponseCode.ERROR, data);\n\t}\n\tpublic static ResultInfo error(ResponseCode message, Object object) {\n\t\tResultInfo resultInfo = new ResultInfo();\n\t\tresultInfo.setStatus(message.getStatus());\n\t\tresultInfo.setMessage(message.getMessage());\n\t\tresultInfo.setData(object);\n\t\treturn resultInfo;\n\t}\n\n}"
  },
  {
    "path": "hacker-framework-model/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n         xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n    <modelVersion>4.0.0</modelVersion>\n\n    <!--父类-->\n    <parent>\n        <groupId>Hacker.walker</groupId>\n        <artifactId>Hacker-walker-cloud</artifactId>\n        <version>1.0-SNAPSHOT</version>\n        <relativePath>../pom.xml</relativePath>\n    </parent>\n\n    <!--子类-->\n    <artifactId>Hacker-framework-model</artifactId>\n\n\n    <dependencies>\n\n    </dependencies>\n\n    <build>\n        <plugins>\n            <plugin>\n                <groupId>org.apache.maven.plugins</groupId>\n                <artifactId>maven-compiler-plugin</artifactId>\n                <configuration>\n                    <source>8</source>\n                    <target>8</target>\n                </configuration>\n            </plugin>\n        </plugins>\n    </build>\n</project>\n"
  },
  {
    "path": "hacker-framework-model/src/main/java/hacker/framework/model/Cto/AdminRoles.java",
    "content": "package hacker.framework.model.Cto;\n\nimport lombok.Getter;\nimport lombok.Setter;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\n/**\n * 添加角色----》封装了管理员id和所分配的角色id集合\n *\n * @Description: J X N H\n * @EnglishName LuKe\n * @authod LiuQi\n * @date 2019/6/3 15:35\n */\n@Getter\n@Setter\npublic class AdminRoles{\n    Integer uid;\n    Integer role;\n    List<Integer> roles;\n\n    public AdminRoles() {\n    }\n\n    public AdminRoles(Integer uid, List<Integer> roles) {\n        this.uid = uid;\n        this.roles = roles;\n    }\n\n    public AdminRoles(Integer uid, Integer role) {\n        this.uid = uid;\n        this.role = role;\n    }\n\n    public List<AdminRoles> getResult(){\n        List<AdminRoles> adminRoles = new ArrayList<>(12);\n        roles.forEach( ro ->{\n            adminRoles.add(new AdminRoles(uid,ro));\n        });\n        return adminRoles;\n    }\n\n\n}\n"
  },
  {
    "path": "hacker-framework-model/src/main/java/hacker/framework/model/Cto/RolePermissions.java",
    "content": "package hacker.framework.model.Cto;\n\nimport lombok.Getter;\nimport lombok.Setter;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\n/**\n * 封装roleid和permissionid,用来给角色赋权\n *\n * @Description: J X N H\n * @EnglishName LuKe\n * @authod LiuQi\n * @date 2019/6/3 15:26\n */\n@Getter\n@Setter\npublic class RolePermissions {\n\n\n    Integer rid;\n    Integer pid;\n    List<Integer> pids;\n\n    public RolePermissions() {\n    }\n\n    public RolePermissions(Integer rid, List<Integer> pids) {\n        this.rid = rid;\n        this.pids = pids;\n    }\n\n    public RolePermissions(Integer rid, Integer pid) {\n        this.rid = rid;\n        this.pid = pid;\n    }\n\n    public List<RolePermissions> getObj() {\n        List<RolePermissions> list = new ArrayList<>(12);\n        pids.forEach(pid -> {\n            list.add(new RolePermissions(this.rid, pid));\n        });\n        return list;\n    }\n\n}\n"
  },
  {
    "path": "hacker-framework-model/src/main/java/hacker/framework/model/entity/Admin.java",
    "content": "package hacker.framework.model.entity;\n\nimport com.baomidou.mybatisplus.annotation.IdType;\nimport com.baomidou.mybatisplus.annotation.TableField;\nimport com.baomidou.mybatisplus.annotation.TableId;\nimport com.baomidou.mybatisplus.annotation.TableName;\nimport lombok.Data;\n\nimport java.io.Serializable;\nimport java.util.Date;\nimport java.util.List;\n\n/**\n * 管理员表\n * @Description: J X N H\n * @EnglishName LuKe\n * @authod LiuQi\n * @date 2019/6/3 15:19\n */\n\n@Data\n@TableName(\"tb_admin\")\npublic class Admin implements Serializable {\n\n    @TableId(type = IdType.AUTO)\n    private Integer id;\n\n    private String phone;\n    private String username;\n    private String nickname;\n    private String password;\n    private Integer status;\n    //是否只允许读操作 0否 1是\n    private Integer is_readonly;\n    private String last_login_token;\n    private String last_login_ip;\n    private Date login_at;\n    private Date created_at;\n    private Date updated_at;\n\n    //角色和权限\n    @TableField(exist = false)\n    private List<Role> roles;\n    @TableField(exist = false)\n    private List<Permission> permissions;\n\n\n    @Override\n    public String toString() {\n        return \"Admin{\" +\n                \"id=\" + id +\n                \", phone='\" + phone + '\\'' +\n                \", username='\" + username + '\\'' +\n                \", nickname='\" + nickname + '\\'' +\n                \", password='\" + password + '\\'' +\n                \", status=\" + status +\n                \", is_readonly=\" + is_readonly +\n                \", last_login_token='\" + last_login_token + '\\'' +\n                \", last_login_ip='\" + last_login_ip + '\\'' +\n                \", login_at=\" + login_at +\n                \", created_at=\" + created_at +\n                \", updated_at=\" + updated_at +\n                \", roles=\" + roles +\n                \", permissions=\" + permissions +\n                '}';\n    }\n}\n\n"
  },
  {
    "path": "hacker-framework-model/src/main/java/hacker/framework/model/entity/Pay.java",
    "content": "package hacker.framework.model.entity;\n\nimport com.baomidou.mybatisplus.annotation.TableName;\nimport lombok.Data;\n\nimport java.math.BigDecimal;\nimport java.util.Date;\n\n/**\n * @Description: J X N H\n * @EnglishName LuKe\n * @authod LiuQi(walker)\n * @date 2019/6/4 13:45\n */\n@Data\n@TableName(\"tb_pay\")\npublic class Pay {\n\n    private Long tradeNo;  //用户订单号\n\n    private Integer userId;\n\n    private Integer adminId;\n\n    private Date payTime;\n\n    private BigDecimal payAmount;\n\n    private Integer payStatus;\n\n    private Integer payType;\n\n    private Date gmtCreate;\n\n    private String merchantOutOrderNo; //商家支付订单号\n\n    @Override\n    public String toString() {\n        return \"Pay{\" +\n                \"tradeNo=\" + tradeNo +\n                \", userId=\" + userId +\n                \", adminId=\" + adminId +\n                \", payTime=\" + payTime +\n                \", payAmount=\" + payAmount +\n                \", payStatus=\" + payStatus +\n                \", payType=\" + payType +\n                \", gmtCreate=\" + gmtCreate +\n                \", merchantOutOrderNo='\" + merchantOutOrderNo + '\\'' +\n                '}';\n    }\n}\n"
  },
  {
    "path": "hacker-framework-model/src/main/java/hacker/framework/model/entity/Permission.java",
    "content": "package hacker.framework.model.entity;\n\nimport com.baomidou.mybatisplus.annotation.IdType;\nimport com.baomidou.mybatisplus.annotation.TableId;\nimport com.baomidou.mybatisplus.annotation.TableName;\nimport lombok.Data;\n\nimport java.io.Serializable;\nimport java.util.Date;\n\n/**\n * 权限表\n * @Description: J X N H\n * @EnglishName LuKe\n * @authod LiuQi\n * @date 2019/6/3 15:17\n */\n\n@Data\n@TableName(\"tb_permission\")\npublic class Permission implements Serializable {\n\n    @TableId(type = IdType.AUTO)\n    private Integer id;\n\n    private String name;        //权限唯一ID\n    private Integer parent_id;  //父类ID,根节点为0\n    private String index_name;\n    private String display_name;//权限展示名\n    private Integer is_show;    //是否展示在菜单栏\n    private Integer status;     //状态 1：正常 0：禁用\n    private Date created_at;\n    private Date updated_at;\n\n\n    @Override\n    public String toString() {\n        return \"Permission{\" +\n                \"id=\" + id +\n                \", name='\" + name + '\\'' +\n                \", index_name='\" + index_name + '\\'' +\n                \", parent_id=\" + parent_id +\n                \", display_name='\" + display_name + '\\'' +\n                \", is_show=\" + is_show +\n                \", status=\" + status +\n                \", created_at=\" + created_at +\n                \", updated_at=\" + updated_at +\n                '}';\n    }\n}\n"
  },
  {
    "path": "hacker-framework-model/src/main/java/hacker/framework/model/entity/Role.java",
    "content": "package hacker.framework.model.entity;\n\nimport com.baomidou.mybatisplus.annotation.IdType;\nimport com.baomidou.mybatisplus.annotation.TableId;\nimport com.baomidou.mybatisplus.annotation.TableName;\nimport lombok.Data;\n\nimport java.io.Serializable;\nimport java.util.Date;\n\n/**\n * 角色表\n * @Description: J X N H\n * @EnglishName LuKe\n * @authod LiuQi\n * @date 2019/6/3 15:14\n */\n\n@Data\n@TableName(\"tb_role\")\npublic class Role implements Serializable {\n\n    @TableId(type = IdType.AUTO)\n    private Integer id;\n\n    private String display_name;//角色展示名\n    private Integer level;      //角色等级\n    private Date created_at;\n    private Date updated_at;\n\n    @Override\n    public String toString() {\n        return \"Role{\" +\n                \"id=\" + id +\n                \", display_name='\" + display_name + '\\'' +\n                \", level=\" + level +\n                \", created_at=\" + created_at +\n                \", updated_at=\" + updated_at +\n                '}';\n    }\n}\n"
  },
  {
    "path": "hacker-framework-model/src/main/resources/application.properties",
    "content": "\n"
  },
  {
    "path": "hacker-framework-util/.gitignore",
    "content": "HELP.md\n/target/\n!.mvn/wrapper/maven-wrapper.jar\n\n### STS ###\n.apt_generated\n.classpath\n.factorypath\n.project\n.settings\n.springBeans\n.sts4-cache\n\n### IntelliJ IDEA ###\n.idea\n*.iws\n*.iml\n*.ipr\n\n### NetBeans ###\n/nbproject/private/\n/nbbuild/\n/dist/\n/nbdist/\n/.nb-gradle/\n/build/\n\n### VS Code ###\n.vscode/\n"
  },
  {
    "path": "hacker-framework-util/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n         xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n    <modelVersion>4.0.0</modelVersion>\n\n    <!--父类-->\n    <parent>\n        <groupId>Hacker.walker</groupId>\n        <artifactId>Hacker-walker-cloud</artifactId>\n        <version>1.0-SNAPSHOT</version>\n        <relativePath>../pom.xml</relativePath>\n    </parent>\n\n    <!--子类-->\n    <artifactId>Hacker-framework-util</artifactId>\n\n    <dependencies>\n\n    </dependencies>\n\n    <build>\n        <plugins>\n            <plugin>\n                <groupId>org.apache.maven.plugins</groupId>\n                <artifactId>maven-compiler-plugin</artifactId>\n                <configuration>\n                    <source>8</source>\n                    <target>8</target>\n                </configuration>\n            </plugin>\n        </plugins>\n    </build>\n\n</project>\n"
  },
  {
    "path": "hacker-framework-util/src/main/java/hacker/framework/util/ApplicationContextUtil.java",
    "content": "package hacker.framework.util;\n\nimport org.springframework.beans.BeansException;\nimport org.springframework.context.ApplicationContext;\nimport org.springframework.context.ApplicationContextAware;\nimport org.springframework.stereotype.Component;\n\n/**\n * @Description: J X N H\n * @EnglishName LuKe\n * @authod LiuQi\n * @date 2019/6/3 14:28\n * @description 获取spring 容器\n */\n@Component\npublic class ApplicationContextUtil implements ApplicationContextAware {\n\n    private ApplicationContext applicationContext;\n\n    @Override\n    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {\n\n        this.applicationContext = applicationContext;\n    }\n\n    public ApplicationContext getApplicationContext(){\n        return applicationContext;\n    }\n\n    private ApplicationContextUtil() { }\n}\n"
  },
  {
    "path": "hacker-framework-util/src/main/java/hacker/framework/util/CommontUtil.java",
    "content": "package hacker.framework.util;\n\nimport javax.servlet.http.HttpServletRequest;\nimport java.sql.Timestamp;\nimport java.time.LocalDateTime;\nimport java.util.UUID;\n\n/**\n *\n * @Description: J X N H\n * @EnglishName LuKe\n * @authod LiuQi\n * @date 2019/6/3 16:58\n * @description 通用工具\n */\npublic class CommontUtil {\n    private final static String UNKNOWN = \"unknown\";\n    /**\n     * 获取ip\n     * @param request\n     * @return\n     */\n    public static String getIpAddress(HttpServletRequest request) {\n        String split = \",\";\n        String ip = request.getHeader(\"x-forwarded-for\");\n        if (ip == null || ip.length() == 0 || UNKNOWN.equalsIgnoreCase(ip)) {\n            ip = request.getHeader(\"Proxy-Client-IP\");\n        }\n        if (ip == null || ip.length() == 0 || UNKNOWN.equalsIgnoreCase(ip)) {\n            ip = request.getHeader(\"WL-Proxy-Client-IP\");\n        }\n        if (ip == null || ip.length() == 0 || UNKNOWN.equalsIgnoreCase(ip)) {\n            ip = request.getRemoteAddr();\n        }\n        if (ip.contains(split)) {\n            return ip.split(split)[0];\n        } else {\n            return ip;\n        }\n    }\n\n    /**\n     * 返回uuid\n     * @return uuid\n     */\n    public static String getUUID(){\n        return UUID.randomUUID().toString().replace(\"-\",\"\");\n    }\n\n    /**\n     * 返回当前时间的Timestamp格式\n     * @return Timestamp\n     */\n    public static Timestamp getTimeStampTime(){\n        LocalDateTime time = LocalDateTime.now();\n        Timestamp timestamp = Timestamp.valueOf(time);\n        return timestamp;\n    }\n}\n"
  },
  {
    "path": "hacker-framework-util/src/main/java/hacker/framework/util/FileUtil.java",
    "content": "package hacker.framework.util;\n\n/**\n *\n * @Description: J X N H\n * @EnglishName LuKe\n * @authod LiuQi\n * @date 2019/6/10 9:50\n */\n\npublic class FileUtil {\n\n    // 图片允许的后缀扩展名-----》格式\n    public static String[] IMAGE_FILE_EXTD = new String[] { \"png\", \"bmp\", \"jpg\", \"jpeg\",\"pdf\" };\n\n    public static boolean isFileAllowed(String fileName) {\n        for (String ext : IMAGE_FILE_EXTD) {\n            if (ext.equals(fileName)) {\n                return true;\n            }\n        }\n        return false;\n    }\n}\n"
  },
  {
    "path": "hacker-framework-util/src/main/java/hacker/framework/util/LuKeIp.java",
    "content": "package hacker.framework.util;\n\nimport javax.servlet.http.HttpServletRequest;\nimport java.net.InetAddress;\nimport java.net.UnknownHostException;\n\n/**\n * 获取IP的工具类\n *\n * @Description: J X N H\n * @EnglishName LuKe\n * @authod LiuQi\n * @date 2019/6/3 16:37\n */\npublic class LuKeIp {\n\n    /**\n     * 获取用户IP地址\n     */\n    public static String getIpAddress(HttpServletRequest request) {\n        String[] ipHeaders = {\"x-forwarded-for\", \"Proxy-Client-IP\", \"WL-Proxy-Client-IP\", \"HTTP_CLIENT_IP\", \"HTTP_X_FORWARDED_FOR\"};\n        String[] localhostIp = {\"127.0.0.1\", \"0:0:0:0:0:0:0:1\"};\n        String ip = request.getRemoteAddr();\n        for (String header : ipHeaders) {\n            if (ip != null && ip.length() != 0 && !\"unknown\".equalsIgnoreCase(ip)) break;\n            ip = request.getHeader(header);\n        }\n        for (String local : localhostIp) {\n            if (ip != null && ip.equals(local)) {\n                try {\n                    ip = InetAddress.getLocalHost().getHostAddress();\n                } catch (UnknownHostException ignored) {\n\n                }\n                break;\n            }\n        }\n        if (ip != null && ip.length() > 15 && ip.contains(\",\")) {\n            ip = ip.substring(0, ip.indexOf(','));\n        }\n        return ip;\n    }\n}\n"
  },
  {
    "path": "hacker-framework-util/src/main/java/hacker/framework/util/MD5Util.java",
    "content": "package hacker.framework.util;\n\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\nimport java.security.MessageDigest;\nimport java.security.NoSuchAlgorithmException;\n\n/**\n * @Description: J X N H\n * @EnglishName LuKe\n * @authod LiuQi\n * @date 2019/6/3 17:42\n */\npublic class MD5Util {\n    private static final Logger logger = LoggerFactory.getLogger( MD5Util.class );\n\n    /**\n     * MDB加密方法\n     * @param s\n     * @return\n     */\n    public static final String to_32_MD5(String s) {\n        if(StringUtil.isEmpty(s)){\n            throw new RuntimeException(\"被加密字段不能为空\");\n        }\n\n        char hexDigits[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};\n        byte[] strTemp = s.getBytes();\n        MessageDigest mdTemp = null;\n        try {\n            mdTemp = MessageDigest.getInstance(\"MD5\");\n        } catch (NoSuchAlgorithmException e) {\n            logger.error(\"数据加密发生异常 {}\",e.getMessage());\n            return null;\n        }\n        mdTemp.update(strTemp);\n        byte[] md = mdTemp.digest();\n        int j = md.length;\n        char str[] = new char[j * 2];\n        int k = 0;\n        for (int i = 0; i < j; i++) {\n            byte byte0 = md[i];\n            str[k++] = hexDigits[byte0 >>> 4 & 0xf];\n            str[k++] = hexDigits[byte0 & 0xf];\n        }\n        return new String(str).toUpperCase();\n    }\n\n    /**\n     * 16位MD5串\n     * @param s\n     * @return\n     */\n    public static final String to_16_MD5(String s){\n        if(StringUtil.isEmpty(s)){\n            throw new RuntimeException(\"被加密字段不能为空\");\n        }\n        String md5Str = to_32_MD5(s);\n        md5Str = md5Str.substring(8, 24);\n        return md5Str.toUpperCase();\n    }\n\n    /**\n     * 将32位的md5字符串截断成16位\n     * @param s\n     * @return\n     */\n    public static final String md5To16(String s){\n        if(StringUtil.isEmpty(s)){\n            throw new RuntimeException(\"加密字段不能为空\");\n        }\n        String md5Str = s.substring(8, 24);\n        return md5Str.toUpperCase();\n    }\n}\n"
  },
  {
    "path": "hacker-framework-util/src/main/java/hacker/framework/util/OrderUtil.java",
    "content": "package hacker.framework.util;\n\nimport java.text.DateFormat;\nimport java.text.SimpleDateFormat;\nimport java.util.Date;\nimport java.util.Random;\n\n/**\n * * 订单编码码生成器，生成32位数字编码，\n * * @生成规则 1位单号类型+17位时间戳+14位(用户id加密&随机数)\n */\npublic class OrderUtil {\n    /**\n     * 订单类别头\n     */\n    private static final String ORDER_CODE = \"1\";\n    /**\n     * 退货类别头\n     */\n\n    private static final String RETURN_ORDER = \"2\";\n    /**\n     * 退款类别头\n     */\n\n    private static final String REFUND_ORDER = \"3\";\n    /**\n     * 未付款重新支付别头\n     */\n    private static final String AGAIN_ORDER = \"4\";\n\n    /**\n     * 随即编码\n     */\n    private static final int[] r = new int[]{7, 9, 6, 2, 8, 1, 3, 0, 5, 4};\n\n    /**\n     * 用户id和随机数总长度\n     */\n    private static final int maxLength = 14;\n\n    /**\n     * 更具id进行加密+加随机数组成固定长度编码\n     */\n    private static String toCode(Integer id) {\n        String idStr = id.toString();\n        StringBuilder idsbs = new StringBuilder();\n        for (int i = idStr.length() - 1; i >= 0; i--) {\n            idsbs.append(r[idStr.charAt(i) - '0']);\n        }\n        return idsbs.append(getRandom(maxLength - idStr.length())).toString();\n    }\n\n    /**\n     * 生成时间戳\n     */\n    private static String getDateTime() {\n        DateFormat sdf = new SimpleDateFormat(\"yyyyMMddHHmmssSSS\");\n        return sdf.format(new Date());\n    }\n\n    /**\n     * 生成固定长度随机码\n     *\n     * @param\n     */\n    private static long getRandom(long n) {\n        long min = 1, max = 9;\n        for (int i = 1; i < n; i++) {\n            min *= 10;\n            max *= 10;\n        }\n        long rangeLong = (((long) (new Random().nextDouble() * (max - min)))) + min;\n        return rangeLong;\n    }\n\n    /**\n     * 生成不带类别标头的编码\n     *\n     * @param userId\n     */\n    private static synchronized String getCode(Integer userId) {\n        userId = userId == null ? 10000 : userId;\n        return getDateTime() + toCode(userId);\n    }\n\n    /**\n     * 生成订单单号编码\n     *\n     * @param userId\n     */\n    public static String getOrderCode(Integer userId) {\n        return ORDER_CODE + getCode(userId);\n    }\n\n    /**\n     * 生成退货单号编码\n     *\n     * @param userId\n     */\n    public static String getReturnCode(Integer userId) {\n        return RETURN_ORDER + getCode(userId);\n    }\n\n    /**\n     * 生成退款单号编码\n     *\n     * @param userId\n     */\n    public static String getRefundCode(Integer userId) {\n        return REFUND_ORDER + getCode(userId);\n    }\n\n    /**\n     * 未付款重新支付\n     *\n     * @param userId\n     */\n    public static String getAgainCode(Integer userId) {\n        return AGAIN_ORDER + getCode(userId);\n    }\n\n}"
  },
  {
    "path": "hacker-framework-util/src/main/java/hacker/framework/util/SHA256.java",
    "content": "package hacker.framework.util;\n\n\nimport org.apache.commons.codec.binary.Hex;\nimport java.io.UnsupportedEncodingException;\nimport java.security.MessageDigest;\nimport java.security.NoSuchAlgorithmException;\n\n/**\n * @Description: J X N H\n * @EnglishName LuKe\n * @authod LiuQi\n * @date 2019/6/3 15:42\n */\npublic class SHA256 {\nprivate static final String CHARSET_NAME = \"UTF-8\";\n\n    /**\n     * SHA256加密\n     * @param str 明文\n     * @return  密文\n     */\n    public static String SHA256Encode(String str){\n        MessageDigest messageDigest;\n        String encodeStr = \"\";\n        try {\n            messageDigest = MessageDigest.getInstance(\"SHA-256\");\n            byte[] hash = messageDigest.digest(str.getBytes(CHARSET_NAME));\n            encodeStr = Hex.encodeHexString(hash);\n        } catch (NoSuchAlgorithmException e) {\n            e.printStackTrace();\n        } catch (UnsupportedEncodingException e) {\n            e.printStackTrace();\n        }\n        return encodeStr;\n    }\n\n    public static void main(String[] args) {\n        //对自己的密码加密-----》》64位以上\n        String name = SHA256Encode(\"abc123\"+\"Jhuiabn9_DhiebFIJ==jel%$dafe4fs@deaerf_\");\n        //cpu核心数\n        int i = Runtime.getRuntime().availableProcessors();\n        System.out.println(name);\n    }\n}\n"
  },
  {
    "path": "hacker-framework-util/src/main/java/hacker/framework/util/Snowflake.java",
    "content": "package hacker.framework.util;\n\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\nimport java.text.SimpleDateFormat;\nimport java.util.Date;\nimport java.util.concurrent.atomic.AtomicLong;\n\n/**\n * java edition of Twitter <b>Snowflake</b>, a network service for generating\n * unique ID numbers at high scale with some simple guarantees.\n *\n * https://github.com/twitter/snowflake\n */\npublic class Snowflake {\n\n    private static Logger log = LoggerFactory.getLogger(Snowflake.class);\n//    private static Logger\n\t/*\n\t * bits allocations for timeStamp, datacenterId, workerId and sequence\n\t */\n\n    private final long unusedBits = 1L;\n    /**\n     * 'time stamp' here is defined as the number of millisecond that have\n     * elapsed since the {@link #epoch} given by users on {@link Snowflake}\n     * instance initialization\n     */\n    private final long timestampBits = 41L;\n    private final long datacenterIdBits = 5L;\n    private final long workerIdBits = 5L;\n    private final long sequenceBits = 12L;\n\n    /*\n     * max values of timeStamp, workerId, datacenterId and sequence\n     */\n    private final long maxDatacenterId = -1L ^ (-1L << datacenterIdBits); // 2^5-1\n    private final long maxWorkerId = -1L ^ (-1L << workerIdBits); // 2^5-1\n    private final long maxSequence = -1L ^ (-1L << sequenceBits); // 2^12-1\n\n    /**\n     * left shift bits of timeStamp, workerId and datacenterId\n     */\n    private final long timestampShift = sequenceBits + datacenterIdBits + workerIdBits;\n    private final long datacenterIdShift = sequenceBits + workerIdBits;\n    private final long workerIdShift = sequenceBits;\n\n\t/*\n\t * object status variables\n\t */\n\n    /**\n     * reference material of 'time stamp' is '2018-12-14'. its value can't be\n     * modified after initialization.\n     */\n    private final long epoch = 1451606400000L;\n\n    /**\n     * data center number the process running on, its value can't be modified\n     * after initialization.\n     * <p>\n     * max: 2^5-1 range: [0,31]\n     */\n    private final long datacenterId;\n\n    /**\n     * machine or process number, its value can't be modified after\n     * initialization.\n     * <p>\n     * max: 2^5-1 range: [0,31]\n     *\n     */\n    private final long workerId;\n\n    /**\n     * the unique and incrementing sequence number scoped in only one\n     * period/unit (here is ONE millisecond). its value will be increased by 1\n     * in the same specified period and then reset to 0 for next period.\n     * <p>\n     * max: 2^12-1 range: [0,4095]\n     */\n    private long sequence = 0L;\n\n    /** the time stamp last snowflake ID generated */\n    private long lastTimestamp = -1L;\n\n    /**\n     * generate an unique and incrementing id\n     *\n     * @return id\n     */\n    public synchronized long nextId() {\n        long currTimestamp = timestampGen();\n\n        if (currTimestamp < lastTimestamp) {\n            throw new IllegalStateException(\n                    String.format(\"Clock moved backwards. Refusing to generate id for %d milliseconds\",\n                            lastTimestamp - currTimestamp));\n        }\n\n        if (currTimestamp == lastTimestamp) {\n            sequence = (sequence + 1) & maxSequence;\n            if (sequence == 0) { // overflow: greater than max sequence\n                currTimestamp = waitNextMillis(currTimestamp);\n            }\n\n        } else { // reset to 0 for next period/millisecond\n            sequence = 0L;\n        }\n\n        // track and memo the time stamp last snowflake ID generated\n        lastTimestamp = currTimestamp;\n\n        return ((currTimestamp - epoch) << timestampShift) | //\n                (datacenterId << datacenterIdShift) | //\n                (workerId << workerIdShift) | // new line for nice looking\n                sequence;\n    }\n\n    /**\n     * @param datacenterId\n     *            data center number the process running on, value range: [0,31]\n     * @param workerId\n     *            machine or process number, value range: [0,31]\n     */\n    public Snowflake(long datacenterId, long workerId) {\n        if (datacenterId > maxDatacenterId || datacenterId < 0) {\n            throw new IllegalArgumentException(\n                    String.format(\"datacenter Id can't be greater than %d or less than 0\", maxDatacenterId));\n        }\n        if (workerId > maxWorkerId || workerId < 0) {\n            throw new IllegalArgumentException(\n                    String.format(\"worker Id can't be greater than %d or less than 0\", maxWorkerId));\n        }\n\n        this.datacenterId = datacenterId;\n        this.workerId = workerId;\n    }\n\n    /**\n     * track the amount of calling {@link #waitNextMillis(long)} method\n     */\n    private final AtomicLong waitCount = new AtomicLong(0);\n\n    /**\n     * @return the amount of calling {@link #waitNextMillis(long)} method\n     */\n    public long getWaitCount() {\n        return waitCount.get();\n    }\n\n    /**\n     * running loop blocking until next millisecond\n     *\n     * @param\tcurrTimestamp\tcurrent time stamp\n     * @return current time stamp in millisecond\n     */\n    protected long waitNextMillis(long currTimestamp) {\n        waitCount.incrementAndGet();\n        while (currTimestamp <= lastTimestamp) {\n            currTimestamp = timestampGen();\n        }\n        return currTimestamp;\n    }\n\n    /**\n     * get current time stamp\n     *\n     * @return current time stamp in millisecond\n     */\n    protected long timestampGen() {\n        return System.currentTimeMillis();\n    }\n\n    /**\n     * show settings of Snowflake\n     */\n    @Override\n    public String toString() {\n        return \"Snowflake Settings [timestampBits=\" + timestampBits + \", datacenterIdBits=\" + datacenterIdBits\n                + \", workerIdBits=\" + workerIdBits + \", sequenceBits=\" + sequenceBits + \", epoch=\" + epoch\n                + \", datacenterId=\" + datacenterId + \", workerId=\" + workerId + \"]\";\n    }\n\n    public long getEpoch() {\n        return this.epoch;\n    }\n\n    /**\n     * extract time stamp, datacenterId, workerId and sequence number\n     * information from the given id\n     *\n     * @param id\n     *            a snowflake id generated by this object\n     * @return an array containing time stamp, datacenterId, workerId and\n     *         sequence number\n     */\n    public long[] parseId(long id) {\n        long[] arr = new long[5];\n        arr[4] = ((id & diode(unusedBits, timestampBits)) >> timestampShift);\n        arr[0] = arr[4] + epoch;\n        arr[1] = (id & diode(unusedBits + timestampBits, datacenterIdBits)) >> datacenterIdShift;\n        arr[2] = (id & diode(unusedBits + timestampBits + datacenterIdBits, workerIdBits)) >> workerIdShift;\n        arr[3] = (id & diode(unusedBits + timestampBits + datacenterIdBits + workerIdBits, sequenceBits));\n        return arr;\n    }\n\n    /**\n     * extract and display time stamp, datacenterId, workerId and sequence\n     * number information from the given id in humanization format\n     *\n     * @param id snowflake id in Long format\n     * @return snowflake id in String format\n     */\n    public String formatId(long id) {\n        long[] arr = parseId(id);\n        String tmf = new SimpleDateFormat(\"yyyy-MM-dd HH:mm:ss.SSS\").format(new Date(arr[0]));\n        return String.format(\"%s, #%d, @(%d,%d)\", tmf, arr[3], arr[1], arr[2]);\n    }\n\n    /**\n     * a diode is a long value whose left and right margin are ZERO, while\n     * middle bits are ONE in binary string layout. it looks like a diode in\n     * shape.\n     *\n     * @param offset\n     *            left margin position\n     * @param length\n     *            offset+length is right margin position\n     * @return a long value\n     */\n    private long diode(long offset, long length) {\n        int lb = (int) (64 - offset);\n        int rb = (int) (64 - (offset + length));\n        return (-1L << lb) ^ (-1L << rb);\n    }\n\n    public static void main(String[] args) {\n        Snowflake idWorker = new Snowflake(1, 2);\n        Snowflake idWorker2 = new Snowflake(1, 3);\n        for(int i=0;i<10;i++){\n            long l = idWorker.nextId();\n            long l2 = idWorker2.nextId();\n            System.out.println(l);\n            System.out.println(l2);\n        }\n\n    }\n}\n\n"
  },
  {
    "path": "hacker-framework-util/src/main/java/hacker/framework/util/SnowflakeIdWorker.java",
    "content": "package hacker.framework.util;\n\n/**\n * Twitter_Snowflake<br>\n * SnowFlake的结构如下(每部分用-分开):<br>\n * 0 - 0000000000 0000000000 0000000000 0000000000 0 - 00000 - 00000 - 000000000000 <br>\n * 1位标识，由于long基本类型在Java中是带符号的，最高位是符号位，正数是0，负数是1，所以id一般是正数，最高位是0<br>\n * 41位时间截(毫秒级)，注意，41位时间截不是存储当前时间的时间截，而是存储时间截的差值（当前时间截 - 开始时间截)\n * 得到的值），这里的的开始时间截，一般是我们的id生成器开始使用的时间，由我们程序来指定的（如下下面程序IdWorker类的startTime属性）。41位的时间截，可以使用69年，年T = (1L << 41) / (1000L * 60 * 60 * 24 * 365) = 69<br>\n * 10位的数据机器位，可以部署在1024个节点，包括5位datacenterId和5位workerId<br>\n * 12位序列，毫秒内的计数，12位的计数顺序号支持每个节点每毫秒(同一机器，同一时间截)产生4096个ID序号<br>\n * 加起来刚好64位，为一个Long型。<br>\n * SnowFlake的优点是，整体上按照时间自增排序，并且整个分布式系统内不会产生ID碰撞(由数据中心ID和机器ID作区分)，并且效率较高，经测试，SnowFlake每秒能够产生26万ID左右。\n */\npublic class SnowflakeIdWorker {\n\n    // ==============================Fields===========================================\n    /** 开始时间截 (2018-12-14) */\n    private final long twepoch = 1420041600000L;\n\n    /** 机器id所占的位数 */\n    private final long workerIdBits = 5L;\n\n    /** 数据标识id所占的位数 */\n    private final long datacenterIdBits = 5L;\n\n    /** 支持的最大机器id，结果是31 (这个移位算法可以很快的计算出几位二进制数所能表示的最大十进制数) */\n    private final long maxWorkerId = -1L ^ (-1L << workerIdBits);\n\n    /** 支持的最大数据标识id，结果是31 */\n    private final long maxDatacenterId = -1L ^ (-1L << datacenterIdBits);\n\n    /** 序列在id中占的位数 */\n    private final long sequenceBits = 12L;\n\n    /** 机器ID向左移12位 */\n    private final long workerIdShift = sequenceBits;\n\n    /** 数据标识id向左移17位(12+5) */\n    private final long datacenterIdShift = sequenceBits + workerIdBits;\n\n    /** 时间截向左移22位(5+5+12) */\n    private final long timestampLeftShift = sequenceBits + workerIdBits + datacenterIdBits;\n\n    /** 生成序列的掩码，这里为4095 (0b111111111111=0xfff=4095) */\n    private final long sequenceMask = -1L ^ (-1L << sequenceBits);\n\n    /** 工作机器ID(0~31) */\n    private long workerId;\n\n    /** 数据中心ID(0~31) */\n    private long datacenterId;\n\n    /** 毫秒内序列(0~4095) */\n    private long sequence = 0L;\n\n    /** 上次生成ID的时间截 */\n    private long lastTimestamp = -1L;\n\n    //==============================Constructors=====================================\n    /**\n     * 构造函数\n     * @param workerId 工作ID (0~31)\n     * @param datacenterId 数据中心ID (0~31)\n     */\n    public SnowflakeIdWorker(long workerId, long datacenterId) {\n        if (workerId > maxWorkerId || workerId < 0) {\n            throw new IllegalArgumentException(String.format(\"worker Id can't be greater than %d or less than 0\", maxWorkerId));\n        }\n        if (datacenterId > maxDatacenterId || datacenterId < 0) {\n            throw new IllegalArgumentException(String.format(\"datacenter Id can't be greater than %d or less than 0\", maxDatacenterId));\n        }\n        this.workerId = workerId;\n        this.datacenterId = datacenterId;\n    }\n\n    // ==============================Methods==========================================\n    /**\n     * 获得下一个ID (该方法是线程安全的)\n     * @return SnowflakeId\n     */\n    public synchronized long nextId() {\n        long timestamp = timeGen();\n\n        //如果当前时间小于上一次ID生成的时间戳，说明系统时钟回退过这个时候应当抛出异常\n        if (timestamp < lastTimestamp) {\n            throw new RuntimeException(\n                    String.format(\"Clock moved backwards.  Refusing to generate id for %d milliseconds\", lastTimestamp - timestamp));\n        }\n\n        //如果是同一时间生成的，则进行毫秒内序列\n        if (lastTimestamp == timestamp) {\n            sequence = (sequence + 1) & sequenceMask;\n            //毫秒内序列溢出\n            if (sequence == 0) {\n                //阻塞到下一个毫秒,获得新的时间戳\n                timestamp = tilNextMillis(lastTimestamp);\n            }\n        }\n        //时间戳改变，毫秒内序列重置\n        else {\n            sequence = 0L;\n        }\n\n        //上次生成ID的时间截\n        lastTimestamp = timestamp;\n\n        //移位并通过或运算拼到一起组成64位的ID\n        return ((timestamp - twepoch) << timestampLeftShift) //\n                | (datacenterId << datacenterIdShift) //\n                | (workerId << workerIdShift) //\n                | sequence;\n    }\n\n    /**\n     * 阻塞到下一个毫秒，直到获得新的时间戳\n     * @param lastTimestamp 上次生成ID的时间截\n     * @return 当前时间戳\n     */\n    protected long tilNextMillis(long lastTimestamp) {\n        long timestamp = timeGen();\n        while (timestamp <= lastTimestamp) {\n            timestamp = timeGen();\n        }\n        return timestamp;\n    }\n\n    /**\n     * 返回以毫秒为单位的当前时间\n     * @return 当前时间(毫秒)\n     */\n    protected long timeGen() {\n        return System.currentTimeMillis();\n    }\n\n\n\n    //==============================Test=============================================\n    /** 测试 */\n    public static void main(String[] args) {\n//        System.out.println(Long.toBinaryString(5));\n        SnowflakeIdWorker idWorker = new SnowflakeIdWorker(1, 1);\n        for (int i = 0; i < 1000; i++) {\n            long id = idWorker.nextId();\n            System.out.println(Long.toBinaryString(id));\n            System.out.println(id);\n        }\n    }\n}\n"
  },
  {
    "path": "hacker-framework-util/src/main/java/hacker/framework/util/SslUtils.java",
    "content": "package hacker.framework.util;\n\nimport javax.net.ssl.*;\nimport java.security.cert.CertificateException;\nimport java.security.cert.X509Certificate;\n\n/**\n * Ssl安全证书\n */\npublic class SslUtils {\n\n\n    private static void trustAllHttpsCertificates() throws Exception {\n        TrustManager[] trustAllCerts = new TrustManager[1];\n        TrustManager tm = new miTM();\n        trustAllCerts[0] = tm;\n        SSLContext sc = SSLContext.getInstance(\"SSL\");\n        sc.init(null, trustAllCerts, null);\n        HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());\n    }\n\n    static class miTM implements TrustManager,X509TrustManager {\n        @Override\n        public X509Certificate[] getAcceptedIssuers() {\n            return null;\n        }\n\n        public boolean isServerTrusted(X509Certificate[] certs) {\n            return true;\n        }\n\n        public boolean isClientTrusted(X509Certificate[] certs) {\n            return true;\n        }\n\n        @Override\n        public void checkServerTrusted(X509Certificate[] certs, String authType)\n                throws CertificateException {\n            return;\n        }\n\n        @Override\n        public void checkClientTrusted(X509Certificate[] certs, String authType)\n                throws CertificateException {\n            return;\n        }\n    }\n    /**\n     * 忽略HTTPS请求的SSL证书，必须在openConnection之前调用\n     * @throws Exception\n     */\n    public static void ignoreSsl() throws Exception{\n        HostnameVerifier hv = new HostnameVerifier() {\n            @Override\n            public boolean verify(String urlHostName, SSLSession session) {\n                return true;\n            }\n        };\n\n        trustAllHttpsCertificates();\n        HttpsURLConnection.setDefaultHostnameVerifier(hv);\n\n    }\n}\n"
  },
  {
    "path": "hacker-framework-util/src/main/java/hacker/framework/util/StringUtil.java",
    "content": "package hacker.framework.util;\n\nimport org.apache.commons.lang3.StringUtils;\n\nimport java.util.UUID;\n\npublic class StringUtil {\n    /**\n     * 字符串去掉前后空格后是否为空字符串\n     * @param source\n     * @return\n     */\n    public static final boolean isEmpty(String source){\n\n        return StringUtils.isEmpty(StringUtils.trimToEmpty(source));\n    }\n\n    /**\n     * 字符串去掉前后空格后是否不为空字符串\n     * @param source\n     * @return\n     */\n    public static final boolean isNotEmpty(String source){\n        return StringUtils.isNotEmpty(StringUtils.trimToEmpty(source));\n    }\n\n    /**\n     * 字符串去掉前后空格后是否为空\n     * @param source\n     * @return\n     */\n    public static final boolean isNull(String source){\n        return StringUtils.isBlank(StringUtils.trimToNull(source));\n    }\n\n    /**\n     * 字符串去掉前后空格后是否不为空\n     * @param source\n     * @return\n     */\n    public static final boolean isNotNull(String source){\n        return StringUtils.isNotBlank(StringUtils.trimToNull(source));\n    }\n\n    /**\n     * 获取去除间隔符号的UUID字符串\n     * @return\n     */\n    public static final String getKey(){\n        String uuidStr = UUID.randomUUID().toString();\n        return uuidStr.replace(\"-\", \"\");\n    }\n\n    public static String toUnicodeEx(String str){\n        String result=\"\";\n        for (int i = 0; i < str.length(); i++){\n            int chr1 = (char) str.charAt(i);\n            if(chr1>=19968&&chr1<=171941){//\\u4e00-\\u9fa5\n                result+=\"\\\\\\\\\\\\\\\\\\\\u\" + Integer.toHexString(chr1);\n            }else{\n                if(chr1<255) {\n                    result += \"\\\\\\\\\\\\\\\\\\\\u\" + String.format(\"%04x\", chr1);\n                }else {\n                    result += str.charAt(i);\n                }\n            }\n        }\n        return result;\n    }\n}\n"
  },
  {
    "path": "hacker-framework-util/src/main/java/hacker/framework/util/TestUtil.java",
    "content": "package hacker.framework.util;\n\nimport org.apache.commons.lang3.StringUtils;\n\nimport java.io.BufferedReader;\nimport java.io.IOException;\nimport java.io.InputStreamReader;\nimport java.io.PrintWriter;\nimport java.math.BigDecimal;\nimport java.net.HttpURLConnection;\nimport java.net.URL;\nimport java.net.URLConnection;\nimport java.net.URLEncoder;\nimport java.security.MessageDigest;\nimport java.text.ParseException;\nimport java.text.SimpleDateFormat;\nimport java.util.*;\n\n\npublic class TestUtil {\n\n\n    /**\n     *double类型数乘以100\n     */\n    public static Double doubleRide100(double d) {\n        BigDecimal bg = new BigDecimal(d * 100);\n        double doubleValue = bg.setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue();\n        return doubleValue;\n    }\n\n    /**\n     *\n     * 方法用途: 对所有传入参数按照字段名的 ASCII 码从小到大排序（字典序），并且生成url参数串<br>\n     * 实现步骤: <br>\n     *\n     * @param paraMap\n     *            要排序的Map对象\n     * @param urlEncode\n     *            是否需要URLENCODE\n     * @param keyToLower\n     *            是否需要将Key转换为全小写 true:key转化成小写，false:不转化\n     * @return\n     */\n    public static String formatUrlMap(Map<String, String> paraMap, boolean urlEncode, boolean keyToLower) {\n        String buff = \"\";\n        Map<String, String> tmpMap = paraMap;\n        try {\n            List<Map.Entry<String, String>> infoIds = new ArrayList<Map.Entry<String, String>>(tmpMap.entrySet());\n            // 对所有传入参数按照字段名的 ASCII 码从小到大排序（字典序）\n            Collections.sort(infoIds, new Comparator<Map.Entry<String, String>>() {\n\n                @Override\n                public int compare(Map.Entry<String, String> o1, Map.Entry<String, String> o2) {\n                    return (o1.getKey()).toString().compareTo(o2.getKey());\n                }\n            });\n            // 构造URL 键值对的格式\n            StringBuilder buf = new StringBuilder();\n            for (Map.Entry<String, String> item : infoIds) {\n                if (StringUtils.isNotBlank(item.getKey())) {\n                    String key = item.getKey();\n                    String val = item.getValue();\n                    if (urlEncode) {\n                        val = URLEncoder.encode(val, \"utf-8\");\n                    }\n                    if (keyToLower) {\n                        buf.append(key.toLowerCase() + \"=\" + val);\n                    } else {\n                        buf.append(key + \"=\" + val);\n                    }\n                    buf.append(\"&\");\n                }\n\n            }\n            buff = buf.toString();\n            if (buff.isEmpty() == false) {\n                buff = buff.substring(0, buff.length() - 1);\n            }\n        } catch (Exception e) {\n            return null;\n        }\n        return buff;\n    }\n\n    /**\n     * 对字符串md5加密\n     *\n     * @param str\n     * @return\n     */\n    public static String getMD5(String str){\n        MessageDigest md5 = null;\n        try{\n            md5 = MessageDigest.getInstance(\"MD5\");\n        }catch (Exception e){\n            System.out.println(e.toString());\n            e.printStackTrace();\n            return \"\";\n        }\n        char[] charArray = str.toCharArray();\n        byte[] byteArray = new byte[charArray.length];\n        for (int i = 0; i < charArray.length; i++) {\n            byteArray[i] = (byte) charArray[i];\n        }\n        byte[] md5Bytes = md5.digest(byteArray);\n        StringBuffer hexValue = new StringBuffer();\n        for (int i = 0; i < md5Bytes.length; i++){\n            int val = ((int) md5Bytes[i]) & 0xff;\n            if (val < 16) {\n                hexValue.append(\"0\");\n            }\n            hexValue.append(Integer.toHexString(val));\n        }\n        return hexValue.toString();\n    }\n\n    /**\n     * 接口调用 GET\n     */\n    public static String sendGet(String GET_URL) {\n        String s=null;\n        try {\n            URL url = new URL(GET_URL);    // 把字符串转换为URL请求地址\n            HttpURLConnection connection = (HttpURLConnection) url.openConnection();// 打开连接\n            connection.connect();// 连接会话\n            // 获取输入流\n            BufferedReader br = new BufferedReader(new InputStreamReader(connection.getInputStream()));\n            String line;\n            StringBuilder sb = new StringBuilder();\n            while ((line = br.readLine()) != null) {// 循环读取流\n                sb.append(line);\n            }\n            br.close();// 关闭流\n            connection.disconnect();// 断开连接\n            System.out.println(\"接口调用 GET:\"+sb.toString());\n            s=sb.toString();\n            return s;\n        } catch (Exception e) {\n            e.printStackTrace();\n            System.out.println(\"失败!\");\n        }\n        return null;\n    }\n\n    /**\n     * 向指定 URL 发送POST方法的请求\n     *\n     * @param url\n     *            发送请求的 URL\n     * @param param\n     *            请求参数，请求参数应该是 name1=value1&name2=value2 的形式。\n     * @param charset\n     *             发送和接收的格式\n     * @return 所代表远程资源的响应结果\n     */\n    public static String sendPost(String url, String param,String charset) {\n        PrintWriter out = null;\n        BufferedReader in = null;\n        String result = \"\";\n        String line;\n        StringBuffer sb=new StringBuffer();\n        try {\n            URL realUrl = new URL(url);\n            //如果是https请求,忽略SSL证书\n            if(\"https\".equalsIgnoreCase(realUrl.getProtocol())){\n                SslUtils.ignoreSsl();\n            }\n            // 打开和URL之间的连接\n            URLConnection conn = realUrl.openConnection();\n            // 设置通用的请求属性 设置请求格式\n            conn.setRequestProperty(\"contentType\", charset);\n            conn.setRequestProperty(\"content-type\", \"application/x-www-form-urlencoded\");\n            //设置超时时间\n            conn.setConnectTimeout( 60000);\n            conn.setReadTimeout( 60000);\n            // 发送POST请求必须设置如下两行\n            conn.setDoOutput(true);\n            conn.setDoInput(true);\n            // 获取URLConnection对象对应的输出流\n            out = new PrintWriter(conn.getOutputStream());\n            // 发送请求参数\n            out.print(param);\n            // flush输出流的缓冲\n            out.flush();\n            // 定义BufferedReader输入流来读取URL的响应    设置接收格式\n            in = new BufferedReader(new InputStreamReader(conn.getInputStream(),charset));\n            while ((line = in.readLine()) != null) {\n                sb.append(line);\n            }\n            result=sb.toString();\n        } catch (Exception e) {\n            System.out.println(\"发送 POST请求出现异常!\"+e);\n            e.printStackTrace();\n        }\n        //使用finally块来关闭输出流、输入流\n        finally{\n            try{\n                if(out!=null){\n                    out.close();\n                }\n                if(in!=null){\n                    in.close();\n                }\n            }\n            catch(IOException ex){\n                ex.printStackTrace();\n            }\n        }\n        return result;\n    }\n\n    /**\n     * 获取现在时间\n     * @author haixin\n     * @return 返回时间类型 yyyy-MM-dd HH:mm:ss\n     * @throws ParseException\n     */\n    public static Date getNowDate() throws ParseException {\n        SimpleDateFormat sd = new SimpleDateFormat(\"yyyy-MM-dd HH:mm:ss\");\n        String dateTime=sd.format(new Date());\n        Date date=sd.parse(dateTime);\n        return date;\n    }\n\n    /**\n     * 生成两位随机数\n     * @author haixin\n     * @return 返回int类型 10-99\n     */\n    public static int random() {\n        int max=99;\n        int min=10;\n        Random random = new Random();\n        int s = random.nextInt(max)%(max-min+1) + min;\n        return s;\n    }\n\n    /**\n     * 不够位数的在前面补0，保留num的长度位数字\n     * @param code\n     * @return\n     */\n    private static String autoGenericCode(String code, int num) {\n        String result = \"\";\n        // 保留num的位数\n        // 0 代表前面补充0\n        // num 代表长度为4\n        // d 代表参数为正数型\n        result = String.format(\"%0\" + num + \"d\", Integer.parseInt(code));\n\n        return result;\n    }\n\n    /**\n     * @author haixin.hu\n     * @param str：name1=value1&name2=value2类型字符串\n     * @return 返回类型：Map数组\n     * */\n    @SuppressWarnings(\"rawtypes\")\n    public static Map StrToMap(String str){\n        String[] strs = str.split(\"&\");\n        Map<String, String> m = new HashMap<String, String>();\n        for(String s:strs){\n            String[] ms = s.split(\"=\");\n            m.put(ms[0], ms[1]);\n        }\n        return m;\n    }\n}\n"
  },
  {
    "path": "hacker-framework-util/src/main/java/hacker/framework/util/TokenProccessor.java",
    "content": "package hacker.framework.util;\n\n\nimport sun.misc.BASE64Encoder;\n\nimport java.security.MessageDigest;\nimport java.security.NoSuchAlgorithmException;\nimport java.util.Random;\n\n/**\n * 生成Token的工具类\n * @Description: J X N H\n * @EnglishName LuKe\n * @authod LiuQi\n * @date 2019/6/3 16:37\n */\npublic class TokenProccessor {\n\n    private TokenProccessor(){};\n    private static final TokenProccessor instance = new TokenProccessor();\n\n    public static TokenProccessor getInstance() {\n        return instance;\n    }\n\n    /**\n     * 生成Token\n     * @return\n     */\n    public String makeToken() {\n        String token = (System.currentTimeMillis() + new Random().nextInt(999999999)) + \"\";\n        try {\n            MessageDigest md = MessageDigest.getInstance(\"md5\");\n            byte md5[] =  md.digest(token.getBytes());\n            BASE64Encoder encoder = new BASE64Encoder();\n            return encoder.encode(md5);\n        } catch (NoSuchAlgorithmException e) {\n            // TODO Auto-generated catch block\n            e.printStackTrace();\n        }\n        return null;\n    }\n}\n"
  },
  {
    "path": "hacker-framework-util/src/main/resources/application.properties",
    "content": "\n"
  },
  {
    "path": "hacker-govern-center/.gitignore",
    "content": "HELP.md\n/target/\n!.mvn/wrapper/maven-wrapper.jar\n\n### STS ###\n.apt_generated\n.classpath\n.factorypath\n.project\n.settings\n.springBeans\n.sts4-cache\n\n### IntelliJ IDEA ###\n.idea\n*.iws\n*.iml\n*.ipr\n\n### NetBeans ###\n/nbproject/private/\n/nbbuild/\n/dist/\n/nbdist/\n/.nb-gradle/\n/build/\n\n### VS Code ###\n.vscode/\n"
  },
  {
    "path": "hacker-govern-center/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n         xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n    <modelVersion>4.0.0</modelVersion>\n\n\n    <parent>\n        <groupId>Hacker.walker</groupId>\n        <artifactId>Hacker-walker-cloud</artifactId>\n        <version>1.0-SNAPSHOT</version>\n        <relativePath>../pom.xml</relativePath>\n    </parent>\n\n    <!--子类-->\n    <artifactId>Hacker-govern-center</artifactId>\n\n\n    <dependencies>\n        <!-- eureka-server -->\n        <dependency>\n            <groupId>org.springframework.cloud</groupId>\n            <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>\n            <version>2.0.2.RELEASE</version>\n            <exclusions>\n                <exclusion>\n                    <groupId>org.springframework.boot</groupId>\n                    <artifactId>spring-boot-starter-logging</artifactId>\n                </exclusion>\n            </exclusions>\n        </dependency>\n        <!-- eureka-server -->\n\n\n    </dependencies>\n\n    <build>\n        <finalName>Hacker-govern-center</finalName>\n        <plugins>\n            <plugin>\n                <groupId>org.springframework.boot</groupId>\n                <artifactId>spring-boot-maven-plugin</artifactId>\n            </plugin>\n        </plugins>\n    </build>\n\n</project>\n"
  },
  {
    "path": "hacker-govern-center/src/main/java/hacker/framework/center/EurekaApplication.java",
    "content": "package hacker.framework.center;\n\nimport org.springframework.boot.SpringApplication;\nimport org.springframework.boot.autoconfigure.SpringBootApplication;\nimport org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;\n\n@EnableEurekaServer  // 标识此工程是一个EurekaServer\n@SpringBootApplication\npublic class EurekaApplication {\n\n    public static void main(String[] args) {\n        SpringApplication.run(EurekaApplication.class, args);\n\n        System.out.println(\"标识此工程是一个EurekaServer\");\n    }\n\n}\n"
  },
  {
    "path": "hacker-govern-center/src/main/resources/application.properties",
    "content": "#spring.profiles.active=dev\n#server.port=8101\n#spring.application.name=Hacker-govern-model\n"
  },
  {
    "path": "hacker-govern-center/src/main/resources/application.yml",
    "content": "server:\n  port: ${PORT:50101} #服务端口\nspring:\n#  profiles: dev\n  application:\n    name: Hacker-govern-model # 指定服务名\n\neureka:\n  client:\n    registerWithEureka: true    # 服务注册，是否将自己注册到Eureka服务中\n    fetchRegistry: true         # 服务发现，是否从Eureka中获取注册信息\n    serviceUrl:                 # Eureka客户端与Eureka服务端的交互地址，高可用状态配置对方的地址，单机状态配置自己（如果不配置则默认本机8761端口）\n      defaultZone: ${EUREKA_SERVER:http://127.0.0.1:${server.port}/eureka/}\n  server:\n    enable-self-preservation: false       # 是否开启自我保护模式\n    eviction-interval-timer-in-ms: 60000  # 服务注册表清理间隔（单位毫秒，默认是60*1000）\n  instance:\n    hostname: ${EUREKA_DOMAIN:127.0.0.1}"
  },
  {
    "path": "hacker-govern-gateway/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n         xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n    <modelVersion>4.0.0</modelVersion>\n\n\n    <!--父类-->\n    <parent>\n        <groupId>Hacker.walker</groupId>\n        <artifactId>Hacker-walker-cloud</artifactId>\n        <version>1.0-SNAPSHOT</version>\n        <relativePath>../pom.xml</relativePath>\n    </parent>\n    <!--父类-->\n\n    <!--子类-->\n    <artifactId>Hacker-govern-gateway</artifactId>\n    <!--子类-->\n\n\n    <dependencies>\n        <!--cloud 网关api-->\n        <dependency>\n            <groupId>org.springframework.cloud</groupId>\n            <artifactId>spring-cloud-netflix-zuul</artifactId>\n            <version>2.1.1.RELEASE</version>\n        </dependency>\n        <!--cloud 网关api-->\n\n    </dependencies>\n\n    <build>\n        <finalName>Hacker-govern-gateway</finalName>\n        <plugins>\n            <plugin>\n                <groupId>org.springframework.boot</groupId>\n                <artifactId>spring-boot-maven-plugin</artifactId>\n            </plugin>\n        </plugins>\n    </build>\n</project>\n"
  },
  {
    "path": "hacker-govern-gateway/src/main/java/hacker/govern/gateway/ZuulAppApplication.java",
    "content": "package hacker.govern.gateway;\n\n        import org.springframework.boot.SpringApplication;\n        import org.springframework.boot.autoconfigure.SpringBootApplication;\n        import org.springframework.cloud.netflix.zuul.EnableZuulProxy;\n\n@SpringBootApplication\n@EnableZuulProxy  // 此工程是一个zuul网关\n\npublic class ZuulAppApplication {\n\n    public static void main(String[] args) {\n        SpringApplication.run(ZuulAppApplication.class, args);\n\n        System.out.println(\"此工程是一个zuul网关\");\n    }\n\n}\n"
  },
  {
    "path": "hacker-govern-gateway/src/main/resources/application.properties",
    "content": "\nserver.servlet.context-path=/api\nspring.application.name=Hacker-govern-gateway\n"
  },
  {
    "path": "hacker-govern-gateway/src/main/resources/application.yml",
    "content": "#spring:\n#  profiles: dev\n\nserver:\n  port: 50201\n  servlet:\n    context-path: /api\n\nspring:\n  application:\n    name: Hacker-govern-gateway\n\n  redis:\n    host: 127.0.0.1\n    port: 6379\n    password: 123456\n    timeout: 3000\n    lettuce:\n      pool:\n        max-active: 200\n        max-idle: 50\n        min-idle: 24\n        max-wait: 2000\n\nzuul:\n  routes:\n    Hacker-api-business-web:\n      path: /business/**\n      serviceId: Hacker-api-business-web  # 指定服务ID(名称)，网关会从eureka中获取该服务名称下的服务实例的地址\n      # url: http://www.baidu.com         # 也可指定url，此url也可以是外网地址   （例子：将请求转发到http://www.baidu.com/business）\n      strip-prefix: false                 # true：代理转发时去掉前缀，false:代理转发时不去掉前缀\n      sensitiveHeaders:                   # 默认zuul会屏蔽cookie，cookie不会传到下游服务，这里设置为空则取消默认的黑名单，如果设置了具体的头信息则不会传到下游服务\n      # ignoredHeaders:                   # 默认为空表示不过虑任何头\n    Hacker-api-business-app:\n      path: /business/app/**\n      serviceId: Hacker-api-business-app\n      strip-prefix: false\n      sensitiveHeaders:\n    Hacker-api-business-alipay-shenghuohao:\n      path: /business/alipay/shenghuohao/**\n      serviceId: Hacker-api-business-alipay-shenghuohao\n      strip-prefix: false\n      sensitiveHeaders:\n\neureka:\n  client:\n    registerWithEureka: true  # 服务注册开关\n    fetchRegistry: true       # 服务发现开关\n    serviceUrl:               # Eureka客户端与Eureka服务端进行交互的地址，多个中间用逗号分隔\n      defaultZone: ${EUREKA_SERVER:http://localhost:50101/eureka/,http://localhost:50102/eureka/}\n  instance:\n    prefer-ip-address:  true  # 将自己的ip地址注册到Eureka服务中\n    ip-address: 127.0.0.1\n    instance-id: ${spring.application.name}:${server.port} # 指定实例id\n\nribbon:\n  MaxAutoRetries: 2                # 最大重试次数，当Eureka中可以找到服务，但是服务连不上时将会重试，如果eureka中找不到服务则直接走断路器\n  MaxAutoRetriesNextServer: 3      # 切换实例的重试次数\n  OkToRetryOnAllOperations: false  # 对所有操作请求都进行重试，如果是get则可以，如果是post，put等操作没有实现幂等的情况下是很危险的,所以设置为false\n  ConnectTimeout: 5000             # 请求连接的超时时间\n  ReadTimeout: 6000                # 请求处理的超时时间"
  },
  {
    "path": "hacker-service-channel-manage/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n         xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n    <modelVersion>4.0.0</modelVersion>\n\n    <!--父类-->\n    <parent>\n        <groupId>Hacker.walker</groupId>\n        <artifactId>Hacker-walker-cloud</artifactId>\n        <version>1.0-SNAPSHOT</version>\n        <relativePath>../pom.xml</relativePath>\n    </parent>\n    <!--父类-->\n\n    <!--子类-->\n    <artifactId>Hacker-service-channel-manage</artifactId>\n    <!--子类-->\n\n        <dependencies>\n\n            <!--common-->\n            <dependency>\n                <groupId>Hacker.walker</groupId>\n                <artifactId>Hacker-framework-common</artifactId>\n                <version>1.0-SNAPSHOT</version>\n                <scope>compile</scope>\n            </dependency>\n            <!--common-->\n\n            <!--model-->\n            <dependency>\n                <groupId>Hacker.walker</groupId>\n                <artifactId>Hacker-framework-model</artifactId>\n                <version>1.0-SNAPSHOT</version>\n                <scope>compile</scope>\n            </dependency>\n            <!--model-->\n\n            <!--util-->\n            <dependency>\n                <groupId>Hacker.walker</groupId>\n                <artifactId>Hacker-framework-util</artifactId>\n                <version>1.0-SNAPSHOT</version>\n                <scope>compile</scope>\n            </dependency>\n            <!--util-->\n        </dependencies>\n\n    <build>\n        <finalName>Hacker-service-channel-manage</finalName>\n        <plugins>\n            <plugin>\n                <groupId>org.springframework.boot</groupId>\n                <artifactId>spring-boot-maven-plugin</artifactId>\n            </plugin>\n        </plugins>\n    </build>\n\n</project>\n"
  },
  {
    "path": "hacker-service-channel-manage/src/main/java/hacker/channel/manage/App.java",
    "content": "package hacker.channel.manage;\n\nimport com.baomidou.mybatisplus.extension.spring.MybatisSqlSessionFactoryBean;\nimport org.apache.ibatis.session.SqlSessionFactory;\nimport org.mybatis.spring.annotation.MapperScan;\nimport org.springframework.beans.BeansException;\nimport org.springframework.boot.SpringApplication;\nimport org.springframework.boot.autoconfigure.SpringBootApplication;\nimport org.springframework.boot.autoconfigure.domain.EntityScan;\nimport org.springframework.context.ApplicationContext;\nimport org.springframework.context.ApplicationContextAware;\nimport org.springframework.context.annotation.Bean;\nimport org.springframework.context.annotation.ComponentScan;\nimport org.springframework.context.annotation.ComponentScans;\nimport org.springframework.scheduling.annotation.EnableScheduling;\nimport org.springframework.web.bind.annotation.RequestMapping;\n\nimport javax.sql.DataSource;\n\n\n@SpringBootApplication\n// 扫描common、util下的所有类\n@EnableScheduling\n@ComponentScans(@ComponentScan(\"hacker.framework\"))\n// 扫描实体类\n@EntityScan(\"hacker.framework.model\")\n//扫描接口\n@MapperScan(\"hacker.channel.manage.mapper\")\n//dao\n@RequestMapping(value = \"/\")\npublic class App implements ApplicationContextAware {\n\n    public static void main(String[] args) {\n\n        SpringApplication.run(App.class, args);\n\n        System.out.println(\"walker开源作品 个人博客:https://www.wuxf.cn 微信公众号:堇夏年华\");\n        System.out.println(\"2019年，祝每一个努力的人都有所收获\");\n    }\n\n    //applicationContext\n    private ApplicationContext applicationContext;\n    @Override\n    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {\n        this.applicationContext = applicationContext;\n    }\n\n    //加载dataSource\n    @Bean\n    public SqlSessionFactory sqlSessionFactory() throws Exception {\n        MybatisSqlSessionFactoryBean sessionFactoryBean = new MybatisSqlSessionFactoryBean();\n        sessionFactoryBean.setDataSource((DataSource) applicationContext.getBean(\"dataSource\"));\n        return sessionFactoryBean.getObject();\n    }\n\n}\n"
  },
  {
    "path": "hacker-service-channel-manage/src/main/java/hacker/channel/manage/config/AppInterceptor.java",
    "content": "package hacker.channel.manage.config;\n\nimport lombok.extern.slf4j.Slf4j;\nimport org.apache.shiro.SecurityUtils;\nimport org.apache.shiro.subject.Subject;\nimport org.springframework.web.servlet.HandlerInterceptor;\nimport org.springframework.web.servlet.ModelAndView;\n\nimport javax.servlet.http.HttpServletRequest;\nimport javax.servlet.http.HttpServletResponse;\n\n\n/**\n * @Description 拦截器\n * @Description: J X N H\n * @EnglishName LuKe\n * @authod LiuQi\n * @date 2019/6/3 11:44\n */\n@Slf4j\npublic class AppInterceptor implements HandlerInterceptor {\n\n    @Override\n    public boolean preHandle(HttpServletRequest request, HttpServletResponse response,\n                             Object handler) throws Exception {\n        String url = request.getRequestURL().toString();\n        log.info(\"=== request url: \"+url);\n\n        Subject subject = SecurityUtils.getSubject();\n        Object principal = subject.getPrincipal();\n        if (null == principal){\n            response.sendRedirect(\"/templates/dr\");\n            log.info(\"=拦截=重定向=\");\n            return false;\n        }\n        log.info(\"拦截器放行\");\n        return true;\n    }\n\n    @Override\n    public void postHandle(HttpServletRequest request, HttpServletResponse response,\n                           Object handler, ModelAndView modelAndView) throws Exception {\n        System.out.println(\"拦截器执行后\");\n    }\n\n    @Override\n    public void afterCompletion(HttpServletRequest request, HttpServletResponse response,\n                                Object handler, Exception ex) throws Exception {\n        System.out.println(\"完成\");\n    }\n}\n"
  },
  {
    "path": "hacker-service-channel-manage/src/main/java/hacker/channel/manage/config/AuthInterceptor.java",
    "content": "package hacker.channel.manage.config;\n\n\nimport hacker.framework.common.annotation.Constants;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\nimport org.springframework.stereotype.Component;\nimport org.springframework.web.servlet.HandlerInterceptor;\n\nimport javax.servlet.http.HttpServletRequest;\nimport javax.servlet.http.HttpServletResponse;\n\n/**\n * @Description: J X N H\n * @EnglishName LuKe\n * @authod LiuQi\n * @date 2019/6/3 11:44\n */\n@Component\npublic class AuthInterceptor implements HandlerInterceptor {\n    Logger logger = LoggerFactory.getLogger( AuthInterceptor.class );\n\n    @Override\n    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {\n        logger.info( \"AuthInterceptor preHandler {}\", request.getRequestURI() );\n\n        Object obj = request.getSession().getAttribute(Constants.AUTH_USER);\n\n        if ( null == obj ) {\n            response.setStatus( 401 );\n            return false;\n        }\n\n        // 操作权限验证TODO???\n\n        return true;\n    }\n}\n"
  },
  {
    "path": "hacker-service-channel-manage/src/main/java/hacker/channel/manage/config/CorsConfig.java",
    "content": "package hacker.channel.manage.config;\n\nimport org.springframework.boot.web.servlet.FilterRegistrationBean;\nimport org.springframework.context.annotation.Bean;\nimport org.springframework.context.annotation.Configuration;\nimport org.springframework.web.cors.CorsConfiguration;\nimport org.springframework.web.cors.UrlBasedCorsConfigurationSource;\nimport org.springframework.web.filter.CorsFilter;\n\n/**\n * 跨域配置\n * @Description: J X N H\n * @EnglishName LuKe\n * @authod LiuQi\n * @date 2019/6/3 11:44\n */\n@Configuration\npublic class CorsConfig {\n\n    @Bean\n    public FilterRegistrationBean corsFilter() {\n\n        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();\n        CorsConfiguration config = new CorsConfiguration();\n        config.setAllowCredentials(true);\n        // 设置你要允许的网站域名，如果全允许则设为 *\n        config.addAllowedOrigin(\"*\");\n        // 如果要限制 HEADER 或 METHOD 请自行更改\n        config.addAllowedHeader(\"*\");\n        config.addAllowedMethod(\"*\");\n        source.registerCorsConfiguration(\"/**\", config);\n        FilterRegistrationBean bean = new FilterRegistrationBean(new CorsFilter(source));\n        // 这个顺序很重要，为避免麻烦请设置在最前\n        bean.setOrder(0);\n        return bean;\n    }\n}"
  },
  {
    "path": "hacker-service-channel-manage/src/main/java/hacker/channel/manage/config/MvcConfig.java",
    "content": "package hacker.channel.manage.config;\n\n\nimport org.springframework.context.annotation.Configuration;\nimport org.springframework.web.servlet.config.annotation.InterceptorRegistry;\nimport org.springframework.web.servlet.config.annotation.ViewControllerRegistry;\nimport org.springframework.web.servlet.config.annotation.WebMvcConfigurer;\n\n\n/**\n * @description 拦截器注册配置\n * @Description: J X N H\n * @EnglishName LuKe\n * @authod LiuQi\n * @date 2019/6/3 11:44\n */\n@Configuration\npublic class MvcConfig implements WebMvcConfigurer {\n\n    /**\n     * 视图跳转集中配置\n     * @param registry\n     */\n    @Override\n    public void addViewControllers(ViewControllerRegistry registry) {\n        registry.addViewController(\"/dr\").setViewName(\"dr\");\n    }\n\n    /**\n     * 配置拦截器\n     * @param registry\n     */\n    @Override\n    public void addInterceptors(InterceptorRegistry registry) {\n        registry.addInterceptor(new AppInterceptor())\n                //放行\n                .addPathPatterns(\"/**\")\n                .excludePathPatterns(\"/api/login\")\n                .excludePathPatterns(\"/error\")\n                .excludePathPatterns(\"/dr\")\n                .excludePathPatterns(\"/**\")\n                .excludePathPatterns(\"/swagger-resources/**\", \"/webjars/**\", \"/v2/**\", \"/swagger-ui.html/**\")\n                .excludePathPatterns(\"/static/**\");\n    }\n\n}\n"
  },
  {
    "path": "hacker-service-channel-manage/src/main/java/hacker/channel/manage/config/ShiroConfig.java",
    "content": "package hacker.channel.manage.config;\n\nimport org.apache.shiro.cache.ehcache.EhCacheManager;\nimport org.apache.shiro.mgt.SecurityManager;\nimport org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;\nimport org.apache.shiro.spring.web.ShiroFilterFactoryBean;\nimport org.apache.shiro.web.mgt.DefaultWebSecurityManager;\nimport org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.context.annotation.Bean;\nimport org.springframework.context.annotation.Configuration;\n\nimport java.util.LinkedHashMap;\nimport java.util.Map;\n\n/**\n * @description shiro的Java配置\n * @Description: J X N H\n * @EnglishName LuKe\n * @authod LiuQi\n * @date 2019/6/3 16:44\n */\n@Configuration\npublic class ShiroConfig {\n\n    @Autowired\n    private ShiroRealm shiroRealm;\n\n    @Bean\n    public ShiroFilterFactoryBean shirFilter(SecurityManager securityManager) {\n        ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();\n        shiroFilterFactoryBean.setSecurityManager(securityManager);\n        //拦截器.\n        Map<String,String> filterChainDefinitionMap = new LinkedHashMap<String,String>();\n        //登陆url，未登陆也会重定向到此\n        shiroFilterFactoryBean.setLoginUrl(\"/dr\");\n        //api/login/dr.html\n        //配置退出，Shiro已经实现\n        filterChainDefinitionMap.put(\"/logout\", \"logout\");\n        //过滤链定义，从上向下顺序执行，一般将/**放在最为下边\n        //authc:所有url都必须认证通过才可以访问; anon:所有url都都可以匿名访问\n        filterChainDefinitionMap.put(\"/static/**\", \"anon\");\n        filterChainDefinitionMap.put(\"/api/login\", \"anon\");\n\n        filterChainDefinitionMap.put(\"/**\", \"authc\");\n\n        //未授权界面;\n        shiroFilterFactoryBean.setUnauthorizedUrl(\"/403\");\n        shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);\n        return shiroFilterFactoryBean;\n    }\n\n    /**\n     * 安全管理器\n     * @return SecurityManager\n     */\n    @Bean\n    public SecurityManager securityManager(){\n        DefaultWebSecurityManager securityManager =  new DefaultWebSecurityManager();\n        securityManager.setRealm(shiroRealm);\n        securityManager.setCacheManager(ehCacheManager());\n        return securityManager;\n    }\n    /**\n     * 缓存管理器\n     * @return EhCacheManager\n     */\n    @Bean\n    public EhCacheManager ehCacheManager(){\n        EhCacheManager ehCacheManager = new EhCacheManager();\n        //缓存\n        ehCacheManager.setCacheManagerConfigFile(\"classpath:ehcache.xml\");\n        return ehCacheManager;\n    }\n\n    //************************************* 以下是对shiro注解的支持  *****************************************//\n\n    @Bean\n    public DefaultAdvisorAutoProxyCreator advisorAutoProxyCreator(){\n        DefaultAdvisorAutoProxyCreator advisorAutoProxyCreator = new DefaultAdvisorAutoProxyCreator();\n        advisorAutoProxyCreator.setProxyTargetClass(true);\n        return advisorAutoProxyCreator;\n    }\n\n    @Bean\n    public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager){\n        AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor\n                = new AuthorizationAttributeSourceAdvisor();\n        authorizationAttributeSourceAdvisor.setSecurityManager(securityManager);\n        return authorizationAttributeSourceAdvisor;\n    }\n}\n"
  },
  {
    "path": "hacker-service-channel-manage/src/main/java/hacker/channel/manage/config/ShiroRealm.java",
    "content": "package hacker.channel.manage.config;\n\nimport hacker.channel.manage.service.AdminService;\nimport hacker.channel.manage.service.PermissionService;\nimport hacker.channel.manage.service.RoleService;\nimport hacker.framework.model.entity.Admin;\nimport hacker.framework.model.entity.Permission;\nimport hacker.framework.model.entity.Role;\nimport org.apache.shiro.SecurityUtils;\nimport org.apache.shiro.authc.AuthenticationException;\nimport org.apache.shiro.authc.AuthenticationInfo;\nimport org.apache.shiro.authc.AuthenticationToken;\nimport org.apache.shiro.authc.SimpleAuthenticationInfo;\nimport org.apache.shiro.authz.AuthorizationInfo;\nimport org.apache.shiro.authz.SimpleAuthorizationInfo;\nimport org.apache.shiro.realm.AuthorizingRealm;\nimport org.apache.shiro.subject.PrincipalCollection;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Component;\n\nimport java.util.List;\n\n/**\n * @description shiro授权，认证 realm,shiro需要自己处理异常\n * @Description: J X N H\n * @EnglishName LuKe\n * @authod LiuQi\n * @date 2019/6/3 11:44\n */\n@Component\npublic class ShiroRealm extends AuthorizingRealm {\n\n    @Autowired\n    private AdminService adminService;\n\n    @Autowired\n    private RoleService roleService;\n\n    @Autowired\n    private PermissionService permissionService;\n    /**\n     * 授权\n     * @param principalCollection\n     * @return\n     */\n    @Override\n    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {\n        SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();\n        //获取当前登陆用户后查询该用户角色和权限并赋值\n        Admin user = (Admin) SecurityUtils.getSubject().getPrincipal();\n        List<Role> roles = roleService.queryRolesUser(user);\n        List<Permission> permissions = permissionService.queryByUser(user);\n        user.setRoles(roles);\n        user.setPermissions(permissions);\n\n        roles.forEach( role ->info.addRole(role.getDisplay_name()));\n        permissions.forEach(permission -> info.addStringPermission(permission.getName()));\n        return info;\n    }\n\n    /**\n     * 登陆\n     * @param authenticationToken\n     * @return\n     * @throws AuthenticationException\n     */\n    @Override\n    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken)\n            throws AuthenticationException {\n        if (authenticationToken.getPrincipal() == null) {\n            return null;\n        }\n        //获取用户信息\n        String username = authenticationToken.getPrincipal().toString();\n        Admin user = null;\n        try {\n            //调用查询的方法查询用户名\n            user = adminService.findByName(username);\n        } catch (Exception e) {\n            e.printStackTrace();\n        }\n        if (user == null) {\n            //这里返回后会报出对应异常\n            return null;\n        } else {\n            //这里验证authenticationToken和simpleAuthenticationInfo的信息\n            String password = user.getPassword();\n            SimpleAuthenticationInfo simpleAuthenticationInfo =\n                    //shiro自动检验密码\n                    //user，密码，唯一权限id\n            new SimpleAuthenticationInfo(user, password, getName());\n            return simpleAuthenticationInfo;\n        }\n    }\n\n}\n"
  },
  {
    "path": "hacker-service-channel-manage/src/main/java/hacker/channel/manage/config/Swagger2Configuration.java",
    "content": "package hacker.channel.manage.config;\n\nimport org.springframework.context.annotation.Bean;\nimport org.springframework.context.annotation.Configuration;\nimport springfox.documentation.builders.ApiInfoBuilder;\nimport springfox.documentation.builders.PathSelectors;\nimport springfox.documentation.builders.RequestHandlerSelectors;\nimport springfox.documentation.service.ApiInfo;\nimport springfox.documentation.spi.DocumentationType;\nimport springfox.documentation.spring.web.plugins.Docket;\nimport springfox.documentation.swagger2.annotations.EnableSwagger2;\n\n/**\n * Api文档\n * @Description: J X N H\n * @EnglishName LuKe\n * @authod LiuQi(walker)\n * @date 2019/6/9 15:44\n */\n@Configuration\n@EnableSwagger2\npublic class Swagger2Configuration {\n\n    @Bean\n    public Docket createRestApi() {\n\n        return new Docket(DocumentationType.SWAGGER_2)\n                .apiInfo(apiInfo())\n                .select()\n                .apis(RequestHandlerSelectors.basePackage(\"hacker\"))//看自己定义，可以肆意妄为\n                .paths(PathSelectors.any())\n                .build();\n    }\n\n    private ApiInfo apiInfo() {\n\n        return new ApiInfoBuilder()\n                .title(\"API文档\")\n                .description(\"API文档\")\n                .termsOfServiceUrl(\"https://www.wuxf.cn\")\n                .version(\"1.0\")\n                .build();\n    }\n\n}\n"
  },
  {
    "path": "hacker-service-channel-manage/src/main/java/hacker/channel/manage/config/WebSocketConfig.java",
    "content": "package hacker.channel.manage.config;\n\nimport org.springframework.context.annotation.Bean;\nimport org.springframework.context.annotation.Configuration;\nimport org.yeauty.standard.ServerEndpointExporter;\n\n\n/**\n * @description 开启websocket支持\n * @Description: J X N H\n * @EnglishName LuKe\n * @authod LiuQi\n * @date 2019/6/3 15:44\n */\n@Configuration\npublic class WebSocketConfig {\n\n    @Bean\n    public ServerEndpointExporter serverEndpointExporter(){\n\n        return new ServerEndpointExporter();\n    }\n}\n"
  },
  {
    "path": "hacker-service-channel-manage/src/main/java/hacker/channel/manage/config/WebSocketServer.java",
    "content": "package hacker.channel.manage.config;\n\n\nimport lombok.extern.slf4j.Slf4j;\nimport org.springframework.stereotype.Component;\nimport org.yeauty.annotation.*;\nimport org.yeauty.pojo.Session;\n\n\nimport java.util.ArrayList;\nimport java.util.List;\n\n/**\n * @description websocket服务\n * @Description: J X N H\n * @EnglishName LuKe\n * @authod LiuQi\n * @date 2019/6/3 15:34\n */\n@Slf4j\n@Component\n@ServerEndpoint(prefix = \"netty-websocket\")\npublic class WebSocketServer {\n\n    /**\n     * 打开链接\n     * @param session\n     */\n    @OnOpen\n    public void onOpen(Session session) {\n        this.session = session;\n        addSession();\n        //TODO 打开链接后要做什么\n        //在线数加1\n        addOnlineCount();\n        log.info(\"open\");\n        this.session.sendText(\"打开链接\");\n    }\n\n    /**\n     * 连接关闭调用的方法\n     */\n    @OnClose\n    public void onClose() {\n        //TODO 关闭链接后要做什么\n        log.info(\"close\");\n    }\n\n    /**\n     * 接受到消息\n     * @param message\n     * @param session\n     */\n    @OnMessage\n    public void onMessage(String message, Session session) {\n        //TODO 接受消息的逻辑\n        System.out.println(\"收到消息：\"+message);\n        sendMessage(message);\n    }\n\n    /**\n     * 服务端主动发送消息\n     * @param message 消息体\n     */\n    public void sendMessage(String message) {\n        this.session.sendText(message);\n    }\n\n    /**\n     * 发生错误\n     * @param session\n     * @param e\n     */\n    @OnError\n    public void onError(Session session, Throwable e) {\n        log.error(\"websocket错误\", e);\n        e.printStackTrace();\n    }\n\n    /**\n     * 连接数+1\n     * @return\n     */\n    public int addOnlineCount(){\n        return WebSocketServer.count++;\n    }\n\n    /**\n     * 添加session到容器\n     */\n    public void addSession(){\n        WebSocketServer.sessions.add(this.session);\n    }\n\n    private static volatile int count = 0;\n    private static volatile List<Session> sessions = new ArrayList<>(10);\n    private Session session = null;\n}\n"
  },
  {
    "path": "hacker-service-channel-manage/src/main/java/hacker/channel/manage/controller/AdminController.java",
    "content": "package hacker.channel.manage.controller;\n\nimport org.apache.shiro.SecurityUtils;\nimport hacker.channel.manage.service.AdminService;\nimport hacker.framework.common.request.BaseCode;\nimport hacker.framework.common.request.BaseResult;\nimport hacker.framework.model.Cto.AdminRoles;\nimport hacker.framework.model.entity.Admin;\nimport hacker.framework.util.SHA256;\nimport io.swagger.annotations.ApiOperation;\nimport lombok.extern.slf4j.Slf4j;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.beans.factory.annotation.Value;\nimport org.springframework.util.Assert;\nimport org.springframework.web.bind.annotation.*;\n\n\n/**\n * 管理员界面\n *\n * @Description: J X N H\n * @EnglishName LuKe\n * @author  LiuQi(walker)\n * @date 2019/6/3 16:17\n */\n@Slf4j\n@RestController\n@RequestMapping(\"/api\")\n@CrossOrigin(methods = {RequestMethod.GET, RequestMethod.POST, RequestMethod.PUT, RequestMethod.DELETE}, origins = \"*\")\npublic class AdminController {\n\n    @Autowired\n    private AdminService adminService;\n\n    //slat\n    @Value(\"${salt}\")\n    private String slat;\n\n    /**\n     * 新建管理用户\n     *\n     * @param user 要新建的用户\n     * @return 返回信息\n     */\n    @PostMapping(\"/addUser\")\n    @ApiOperation(value = \"新建管理用户\")\n    public BaseResult createAdminUser(@RequestBody Admin user) {\n        //接收前端传过来的参数\n        System.out.println(user);\n        //接收的参数不能为空\n        Admin loginUser = (Admin) SecurityUtils.getSubject().getPrincipal();\n        Assert.notNull(user.getUsername(), \"用户名不可为空\");\n        Assert.notNull(user.getPassword(), \"密码不可为空\");\n\n        //对密码进行加密\n        user.setPassword(SHA256.SHA256Encode(user.getPassword() + slat));\n        int us = adminService.createNewAdmin(user);\n        if (us == -1) {\n            return new BaseResult(\"-1\", \"用户名重复\", 0);\n        } else {\n\n            log.info(\"用户(id=\" + loginUser.getId() + \") 新建用户（   name：\" + user.getUsername() + \")\");\n            return new BaseResult(BaseCode.SUCCESS.getCode(), \"新建成功\", 1);\n        }\n    }\n\n    /**\n     * 根据id删除管理员用户\n     *\n     * @param id id\n     * @return 删除信息\n     */\n    @PostMapping(\"/deleteById\")\n    @ApiOperation(value = \"根据id删除管理员用户\")\n    public BaseResult deleteById(Integer id) {\n        //接收前端传过来的id\n        System.out.println(id);\n        Admin loginUser = (Admin) SecurityUtils.getSubject().getPrincipal();\n        try {\n            //调用删除的方法\n            adminService.deleteById(id);\n            log.info(\"当前登陆用户(id:\" + loginUser.getId() + \" ,name:\" + loginUser.getUsername() + \") 删除了当前id=\" + id + \"的管理员\");\n            return new BaseResult(BaseCode.SUCCESS.getCode(), \"删除成功\", 1);\n        } catch (Exception e) {\n            e.printStackTrace();\n            log.error(\"删除管理员用户失败\", e);\n            return new BaseResult(BaseCode.FAIL.getCode(), \"删除管理员用户失败\", 0);\n        }\n    }\n\n\n    /**\n     * 为管理员分配角色\n     *\n     * @param adminRoles 用户id和分配的角色id\n     */\n    @PostMapping(\"/allotRole\")\n    @ApiOperation(value = \"添加管理员对应的角色\")\n    public BaseResult setRoles(@RequestBody AdminRoles adminRoles) {\n        //这里封装了uid和rid在getObj方法中，前端传uid和roles-----》对应的多个role\n        try {\n            adminService.setRoles(adminRoles);\n            log.info(\" 添加管理员对应的=\" + adminRoles + \"角色\");\n            return new BaseResult(BaseCode.SUCCESS.getCode(), \"分配成功\", 1);\n        } catch (Exception e) {\n            e.printStackTrace();\n            log.error(\"分配角色时异常\", e);\n            return new BaseResult(BaseCode.FAIL.getCode(), \"分配失败\", 0);\n        }\n    }\n\n\n}\n\n"
  },
  {
    "path": "hacker-service-channel-manage/src/main/java/hacker/channel/manage/controller/ErrorController.java",
    "content": "package hacker.channel.manage.controller;\n\nimport hacker.framework.common.object.ResultUtil;\nimport io.swagger.annotations.Api;\nimport io.swagger.annotations.ApiOperation;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\nimport org.springframework.http.HttpStatus;\nimport org.springframework.stereotype.Controller;\nimport org.springframework.ui.Model;\nimport org.springframework.web.bind.annotation.RequestMapping;\nimport org.springframework.web.servlet.ModelAndView;\n\nimport javax.servlet.http.HttpServletResponse;\n\n/**\n * @Description: J X N H\n * @EnglishName LuKe\n * @authod LiuQi(walker)\n * @date 2019/6/15 23:15\n */\n@Api(value = \"错误\", description = \"错误页面处理\")\n@Controller\npublic class ErrorController {\n    private static final Logger log = LoggerFactory.getLogger(LoginController.class);\n\n    /***\n     * 错误页面\n     * @param model\n     * @return\n     */\n    @ApiOperation(\n            value = \"错误页面\",\n            notes = \"错误页面\",\n            produces = \"application/json, application/xml\",\n            consumes = \"application/json, application/xml\")\n    @RequestMapping(\"/error1\")\n    public ModelAndView error1(Model model, HttpServletResponse response) {\n\n        log.info(\"错误页面\");\n        response.setStatus(HttpStatus.FORBIDDEN.value());\n\n        return ResultUtil.view(\"templates/error/010.html\");\n    }\n}\n"
  },
  {
    "path": "hacker-service-channel-manage/src/main/java/hacker/channel/manage/controller/LiuStaticTest.java",
    "content": "package hacker.channel.manage.controller;\n\n/**\n * @Description: J X N H\n * @EnglishName LuKe\n * @authod LiuQi(walker)\n * @date 2019/6/4 18:26\n */\npublic class LiuStaticTest {\n\n        public static void main(String[] args) {\n\n            //测试一下输出顺序和a、b的值\n            staticFunction();\n        }\n\n        //静态初始化过程中有对象初始化----会中断静态初始化\n        //非静态的代码块也属于成员是放在堆中的，new 对象就是初始化堆中的内容 代码块 又会比构造先执行  所以就先2了-----个人理解\n\n        //静态变量\n        static LiuStaticTest st = new LiuStaticTest();\n\n        int a = 10;\n        static int b = 11;\n\n        //静态代码块\n        static {\n            System.out.println(\"1\");\n            System.out.println(\"静态代码块\");\n            System.out.println(\"-----------------------\");\n        }\n\n        //代码块\n        {\n            System.out.println(\"2\");\n            System.out.println(\"代码块\");\n            System.out.println(\"-----------------------\");\n        }\n\n        //构造方法\n        LiuStaticTest() {\n            System.out.println(\"3\");\n            System.out.println(\"a=\" + a + \",\" + \"b=\" + b);\n            System.out.println(\"构造方法\");\n            System.out.println(\"-----------------------\");\n        }\n\n        public static void staticFunction() {\n            System.out.println(\"4\");\n\n            System.out.println(\"静态变量放在最前面,静态初始化过程中有对象初始化,会中断静态初始化,执行结果是2、3 a=10,b=0、1、4\");\n            System.out.println(\"静态变量放在静态方法后面，不会被初始化，代码块 又会比构造先执行，执行结果就是1、2、3 a=10,b=11、4\");\n        }\n\n\n}\n"
  },
  {
    "path": "hacker-service-channel-manage/src/main/java/hacker/channel/manage/controller/LoginController.java",
    "content": "package hacker.channel.manage.controller;\n\nimport hacker.channel.manage.service.AdminService;\nimport hacker.framework.common.request.BaseResult;\nimport hacker.framework.common.request.ResultBean;\nimport hacker.framework.model.entity.Admin;\nimport hacker.framework.util.SHA256;\nimport io.swagger.annotations.Api;\nimport io.swagger.annotations.ApiOperation;\nimport lombok.extern.slf4j.Slf4j;\nimport org.apache.shiro.SecurityUtils;\nimport org.apache.shiro.authc.AuthenticationToken;\nimport org.apache.shiro.authc.UsernamePasswordToken;\nimport org.apache.shiro.subject.Subject;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.beans.factory.annotation.Value;\nimport org.springframework.web.bind.annotation.*;\n\nimport javax.servlet.http.HttpServletRequest;\nimport javax.servlet.http.HttpSession;\n\n\n/**\n * admin用户登陆界面\n * @Description: J X N H\n * @EnglishName LuKe\n * @author LiuQi(walker)\n * @date 2019/6/3 14:14\n */\n@Slf4j\n@RestController\n@RequestMapping(\"/api\")\n@Api(value = \"页面入口\", description = \"页面入口管理\")\n@CrossOrigin(methods = { RequestMethod.GET, RequestMethod.POST,RequestMethod.PUT,RequestMethod.DELETE }, origins = \"*\")\npublic class LoginController {\n\n    @Autowired\n    private AdminService adminService;\n\n\n    //slat\n    @Value(\"${salt}\")\n    private String slat;\n\n\n    /***\n     * 首页\n     * @return\n     */\n    @ApiOperation(value = \"首页\", notes = \"首页\")\n    @GetMapping(value = {\"/\", \"/templates/dr\", \"/dr\"})\n    public String dr() {\n        return \"templates/dr\";\n    }\n\n\n    /**\n     * 登陆\n     * @param username 用户名\n     * @param password 密码\n     * @return 返回状态\n     */\n    @PostMapping(\"/login\")\n    @ApiOperation(value = \"用户登录\")\n    public BaseResult login(String username, String password, HttpServletRequest request, HttpSession httpSession ){\n\n        //接收前端传过来的信息\n        System.out.println(\"登陆的用户名为：\" +username);\n        System.out.println(\"登陆的密码为：\" +password);\n\n        //密码加盐sha256加密-----》看个人习惯\n        password = SHA256.SHA256Encode(password + slat);\n        //subject\n        Subject subject = SecurityUtils.getSubject();\n        //token\n        AuthenticationToken authenticationToken = new UsernamePasswordToken(username, password);\n        //返回信息\n        try {\n            //通过token和用户名去执行登陆操作\n            subject.login(authenticationToken);\n            //登陆成功后------》修改用户状态-------》修改成功后、存了登陆的token、IP、登陆时间\n            Admin user = (Admin) subject.getPrincipal();\n            adminService.updateUserStatus(user, request);\n\n            //用户userId\n            Integer userId = user.getId();\n            //获取用户登陆的sessionId,目前没有传给前端,看后期需不需要\n            httpSession.setAttribute(\"user_id\", userId);\n            System.out.println(\"用户的user_sessionId为:\" + httpSession.getId());\n            System.out.println(\"用户的userId为：\" + userId);\n\n            return new BaseResult(\"200\",\"登陆成功\",userId);\n        }catch (Exception e){\n            e.printStackTrace();\n            log.error(\"登陆失败\",e);\n            return new BaseResult(\"500\",\"登陆失败，用户名或密码错误\",0);\n        }\n    }\n\n\n    @GetMapping(\"/logout\")\n    @ApiOperation(value = \"用户退出\")\n    public BaseResult logout(){\n        Subject subject = SecurityUtils.getSubject();\n        try {\n            subject.logout();\n            return new BaseResult(\"200\",\"退出成功\",1);\n        }catch (Exception e){\n            e.printStackTrace();\n            log.error(\"登陆失败\",e);\n            return new BaseResult(\"500\",\"退出失败\",0);\n        }\n    }\n\n\n\n    /**\n     * 用户名查询\n     * @param username 用户名\n     * @return 查询返回结果\n     */\n    @GetMapping(\"/findByName\")\n    @ApiOperation(value = \"用户名查询\")\n    public ResultBean findByName(String username){\n\n        //接收前端传过来的信息\n        System.out.println(username);\n        //调用查询的方法\n        Admin us = adminService.findByName(username);\n        //判断是否存在\n        if (us != null){\n            return ResultBean.ofError(0,\"用户名已存在\");\n        }else {\n            return ResultBean.ofSuccess(1,\"用户名可用\");\n        }\n\n    }\n}"
  },
  {
    "path": "hacker-service-channel-manage/src/main/java/hacker/channel/manage/controller/NotifyController.java",
    "content": "package hacker.channel.manage.controller;\n\nimport hacker.channel.manage.mapper.PayMapper;\nimport hacker.framework.model.entity.Pay;\nimport hacker.framework.util.TestUtil;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.beans.factory.annotation.Value;\nimport org.springframework.web.bind.annotation.RequestMapping;\nimport org.springframework.web.bind.annotation.ResponseBody;\nimport org.springframework.web.bind.annotation.RestController;\n\nimport javax.servlet.http.HttpServletRequest;\nimport javax.servlet.http.HttpServletResponse;\nimport java.util.Date;\nimport java.util.HashMap;\nimport java.util.Map;\n\n/**\n * 支付回调\n * @Description: J X N H\n * @EnglishName LuKe\n * @author LiuQi(walker)\n * @date 2019/6/9 19:14\n */\n@RestController\n@RequestMapping(\"/api/notify\")\npublic class NotifyController {\n\n    //日志\n    private static final Logger log = LoggerFactory.getLogger(PayAliController.class);\n\n    //配置\n    @Value(\"${merid}\")\n    private String merid;// 分配的商户号\n    @Value(\"${key}\")\n    private String key;// 商户号对应的密钥\n    @Value(\"${notifyUrl}\")\n    private String notifyUrl;// 用于接收回调通知的地址\n    @Value(\"${noncestr}\")\n    private String noncestr;//随机参数\n\n    @Autowired\n    private PayMapper payMapper;\n\n    /***\n     * 支付回调 更新订单支付状态\n     * @param request\n     * @param response\n     * @return\n     */\n    @ResponseBody\n    @RequestMapping(\"/callback\")\n    public String callback(HttpServletRequest request, HttpServletResponse response) {\n        //订单号1\n        String merchantOutOrderNo = request.getParameter(\"merchantOutOrderNo\");\n        //商户号\n        String merid = request.getParameter(\"merid\");\n        //订单详情\n        String msg = request.getParameter(\"msg\");\n        //随机字符串，和商户下单时传的一致\n        String noncestr = request.getParameter(\"noncestr\");\n        //平台订单号\n        String orderNo = request.getParameter(\"orderNo\");\n        //支付结果\n        String payResult = request.getParameter(\"payResult\");\n        //签名\n        String sign = request.getParameter(\"sign\");\n        //和下单时所填id字段一致，下单时未传则为空\n        String id = request.getParameter(\"id\");\n        //支付宝订单号 支付宝渠道才会有\n        String aliNo = request.getParameter(\"aliNo\");\n\n        //拼接签名参数\n        Map<String, String> signParamMap = new HashMap<String, String>();\n        signParamMap.put(\"merchantOutOrderNo\", merchantOutOrderNo);\n        signParamMap.put(\"merid\", merid);\n        signParamMap.put(\"msg\", msg);\n        signParamMap.put(\"noncestr\", noncestr);\n        signParamMap.put(\"orderNo\", orderNo);\n        signParamMap.put(\"payResult\", payResult);\n        //转换为key=value模式\n        String signParam = TestUtil.formatUrlMap(signParamMap, false, false);\n        //生成签名\n        String signLocal = TestUtil.getMD5(signParam + \"&key=\" + key);\n        //对比签名\n        if (signLocal.equals(sign)) {\n            //更新订单支付状态 订单返回结果,1 为成功,0为失败，3为处理中\n            Pay payLogDO = new Pay();\n\n            if (\"1\".equals(payResult)) {\n                payLogDO.setPayTime(new Date());\n                payLogDO.setPayStatus(1);//支付状态：1-成功；2-失败；3-等待支付\n                payLogDO.setMerchantOutOrderNo(merchantOutOrderNo);\n                payMapper.updateOrderStatus(payLogDO);\n            }\n            if (\"0\".equals(payResult)) {\n                payLogDO.setPayTime(new Date());\n                payLogDO.setPayStatus(2);//支付状态：1-成功；2-失败；3-等待支付\n                payLogDO.setMerchantOutOrderNo(merchantOutOrderNo);\n                payMapper.updateOrderStatus(payLogDO);\n            }\n            if (\"3\".equals(payResult)) {\n                payLogDO.setPayTime(new Date());\n                payLogDO.setPayStatus(3);//支付状态：1-成功；2-失败；3-等待支付\n                payLogDO.setMerchantOutOrderNo(merchantOutOrderNo);\n                payMapper.updateOrderStatus(payLogDO);\n            }\n            log.info(\"验签成功\");\n            return \"success\";\n        } else {\n            /*PayLogDO payLogDO=new PayLogDO();\n            payLogDO.setPayTime(new Date());\n            payLogDO.setPayStatus(2);//支付状态：1-成功；2-失败；3-等待支付\n            payLogDO.setMerchantOutOrderNo(merchantOutOrderNo);\n            payLogDOMapper.updateOrderStatus(payLogDO);*/\n            log.info(\"验签失败\");\n            return \"faild\";\n        }\n    }\n}\n"
  },
  {
    "path": "hacker-service-channel-manage/src/main/java/hacker/channel/manage/controller/PayAliController.java",
    "content": "package hacker.channel.manage.controller;\n\nimport hacker.channel.manage.service.PayService;\nimport hacker.framework.common.request.ResultBean;\nimport hacker.framework.model.entity.Pay;\nimport io.swagger.annotations.ApiOperation;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.web.bind.annotation.*;\n\n/**\n * @Description: J X N H\n * @EnglishName LuKe\n * @author LiuQi(walker)\n * @date 2019/6/4 16:47\n * 支付宝支付\n */\n@RestController\n@RequestMapping(\"/admin/pay\")\n@CrossOrigin(methods = {RequestMethod.GET, RequestMethod.POST, RequestMethod.PUT, RequestMethod.DELETE}, origins = \"*\")\npublic class PayAliController {\n\n    //日志\n    private static final Logger log= LoggerFactory.getLogger(PayAliController.class);\n\n    @Autowired\n    private PayService payService;\n\n    /***\n     * 支付宝订单支付\n     * @param pay  payAmount channelId 订单信息：用户id，支付金额，账户id\n     * @return 返回url和状态\n     */\n    @PostMapping(value = \"/pay\",consumes = \"application/json\")\n    @ApiOperation(value = \"提交支付宝支付\", notes = \"true:提交成功,false:提交失败\")\n    public ResultBean<String> Pay(@RequestBody Pay pay){\n\n        String url = payService.Pay(pay);\n\n        log.info(\"url-[{}]\",url);\n\n        ResultBean<String> resultBean = new ResultBean<>();\n        resultBean.setData(url);\n        resultBean.setCode(200);\n        resultBean.setSuccess(true);\n        resultBean.setMsg(\"支付宝支付\");\n        return resultBean;\n    }\n\n    /**\n     * 根据ID去查询支付状态\n     */\n    @GetMapping(\"/findOne\")\n    @ApiOperation(value = \"跟住ID去查询支付状态\")\n    public ResultBean findById(Long tradeNo){\n\n        return ResultBean.ofSuccess(payService.findById(tradeNo));\n    }\n\n}\n"
  },
  {
    "path": "hacker-service-channel-manage/src/main/java/hacker/channel/manage/controller/PayQuickController.java",
    "content": "package hacker.channel.manage.controller;\n\nimport hacker.channel.manage.mapper.PayMapper;\nimport hacker.framework.common.request.ResultBean;\nimport hacker.framework.model.entity.Pay;\nimport hacker.framework.util.SnowflakeIdWorker;\nimport hacker.framework.util.TestUtil;\nimport io.swagger.annotations.ApiOperation;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.beans.factory.annotation.Value;\nimport org.springframework.http.MediaType;\nimport org.springframework.web.bind.annotation.*;\n\nimport java.text.SimpleDateFormat;\nimport java.util.Date;\nimport java.util.HashMap;\nimport java.util.Map;\n\n/**\n * @Description: J X N H\n * @EnglishName LuKe\n * @authod LiuQi(walker)\n * @date 2019/6/4 17:17\n * @Description: 快捷支付\n * @Version 1.0\n **/\n@RestController\n@RequestMapping(\"/admin/quick\")\n@CrossOrigin(methods = {RequestMethod.GET, RequestMethod.POST, RequestMethod.PUT, RequestMethod.DELETE}, origins = \"*\")\npublic class PayQuickController {\n\n    private static final Logger log= LoggerFactory.getLogger(PayAliController.class);\n\n    @Value(\"${merid}\")\n    private String merid;// 分配的商户号\n    @Value(\"${key}\")\n    private String key;// 商户号对应的密钥\n    @Value(\"${notifyUrl}\")\n    private String notifyUrl;// 用于接收回调通知的地\n    @Value(\"${noncestr}\")\n    private String noncestr;//随机参数\n    @Value(\"${returnUrl}\")\n    private String returnUrl;//支付完成跳转页面\n    @Value(\"${subMerchantName}\")\n    private String subMerchantName;//二级商户名称\n\n    @Autowired\n    private PayMapper payMapper;\n\n    /***\n     *\n     * @param pay 订单信息： 用户id，支付金额，账号id\n     * @return\n     */\n//    @RequestMapping(value = \"/payLog\",method = RequestMethod.POST,produces = \"application/json\")\n    @PostMapping(value = \"/payLog\",consumes = MediaType.APPLICATION_JSON_UTF8_VALUE)\n    @ApiOperation(value = \"提交银联快捷支付\", notes = \"true:提交成功,false:提交失败\")\n    public ResultBean<String> Pay(@RequestBody Pay pay){\n        //第三方接口 -------》换成自己的调用的第三方即可\n        String wxurl=\"https://alipay.3c-buy.com/api/createQuickOrder\";\n\n        Map<String, String> paramMap = new HashMap<String, String>();\n\n        //产生支付单号\n        SnowflakeIdWorker idWorker0 = new SnowflakeIdWorker(0, 0);\n        String merchantOutOrderNo = idWorker0.nextId()+\"\";\n        //订单时间\n        SimpleDateFormat sdf = new SimpleDateFormat(\"yyyyMMddHHmmss\");\n        String orderTime = sdf.format(new Date());\n\n        paramMap.put(\"merchantOutOrderNo\",merchantOutOrderNo);\n        paramMap.put(\"merid\",merid);\n        paramMap.put(\"noncestr\",noncestr);\n        paramMap.put(\"notifyUrl\", notifyUrl);\n        paramMap.put(\"orderMoney\",pay.getPayAmount().toString());\n        paramMap.put(\"orderTime\",orderTime);\n\n        //添加订单信息\n        Pay insertPayLogDO=new Pay();\n        insertPayLogDO.setUserId(pay.getUserId());\n        insertPayLogDO.setAdminId(pay.getAdminId());//账户id\n        insertPayLogDO.setPayAmount(pay.getPayAmount()); //金额\n        insertPayLogDO.setPayStatus(3);//支付状态：1-成功；2-失败；3-等待支付\n        insertPayLogDO.setPayType(3);//支付方式：1-支付宝；2-微信；3-银联\n        insertPayLogDO.setGmtCreate(new Date());\n        insertPayLogDO.setMerchantOutOrderNo(merchantOutOrderNo); //编号\n\n        payMapper.insertSelective(insertPayLogDO);\n\n        String StringA= TestUtil.formatUrlMap(paramMap,false, false);//待签名串\n        String sign=TestUtil.getMD5(StringA+\"&key=\"+key);//签名\n\n        //对参数按照key=value的格式,参照参数名ASCII码排序,并对value做utf-8的encode编码后得到字符串 param\n        String param = TestUtil.formatUrlMap(paramMap, true, false);\n\n        //#二级商户名称 银联页面显示的商户名称，不填则默认，请保证该名称已在一麻袋后台的二级商户名称中添加，并通过白名单审核，否则会报“二级商户名称不合法”\n        String url = wxurl + \"?\" + param + \"&sign=\" + sign + \"&id=\" + pay.getUserId()+\"&returnUrl=\"+returnUrl;//+\"&subMerchantName=\"+subMerchantName;\n\n        log.info(\"url-[{}]\",url);\n\n        ResultBean<String> resultBean = new ResultBean<>();\n        resultBean.setData(url);\n        resultBean.setCode(200);\n        resultBean.setSuccess(true);\n        resultBean.setMsg(\"银联快捷支付\");\n        return resultBean;\n    }\n}\n"
  },
  {
    "path": "hacker-service-channel-manage/src/main/java/hacker/channel/manage/controller/PayWxController.java",
    "content": "package hacker.channel.manage.controller;\n\nimport hacker.channel.manage.mapper.PayMapper;\nimport hacker.framework.common.request.ResultBean;\nimport hacker.framework.model.entity.Pay;\nimport hacker.framework.util.SnowflakeIdWorker;\nimport hacker.framework.util.TestUtil;\nimport io.swagger.annotations.ApiOperation;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.beans.factory.annotation.Value;\nimport org.springframework.http.MediaType;\nimport org.springframework.web.bind.annotation.*;\n\nimport java.text.SimpleDateFormat;\nimport java.util.Date;\nimport java.util.HashMap;\nimport java.util.Map;\n\n/**\n * @Description: J X N H\n * @EnglishName LuKe\n * @authod LiuQi(walker)\n * @date 2019/5/15 10:47\n * 微信支付\n **/\n@RestController\n@RequestMapping(\"/admin/wx\")\n@CrossOrigin(methods = {RequestMethod.GET, RequestMethod.POST, RequestMethod.PUT, RequestMethod.DELETE}, origins = \"*\")\npublic class PayWxController {\n\n    private static final Logger log= LoggerFactory.getLogger(PayAliController.class);\n\n    @Value(\"${merid}\")\n    private String merid;// 分配的商户号\n    @Value(\"${key}\")\n    private String key;// 商户号对应的密钥\n    @Value(\"${notifyUrl}\")\n    private String notifyUrl;// 用于接收回调通知的地\n    @Value(\"${noncestr}\")\n    private String noncestr;//随机参数\n\n    @Autowired\n    private PayMapper payMapper;\n\n    /***\n     *\n     * @param paylogDo 订单信息： 用户id，支付金额，账号id\n     * @param //address 加密经纬度\n     * @return\n     */\n    /*@RequestMapping(value = \"/payLog\",method = RequestMethod.POST,produces = \"application/json\")*/\n    @PostMapping(value = \"/payLog\",consumes = MediaType.APPLICATION_JSON_UTF8_VALUE)\n    @ApiOperation(value = \"提交微信支付\", notes = \"true:提交成功,false:提交失败\")\n    public ResultBean<String> Pay(@RequestBody Pay paylogDo){\n        //第三方接口-----换成自己的调用的第三方即可\n        String wxurl=\"https://alipay.3c-buy.com/api/createWxOrder\";\n\n        Map<String, String> paramMap = new HashMap<String, String>();\n\n        //产生支付单号\n        SnowflakeIdWorker idWorker0 = new SnowflakeIdWorker(0, 0);\n        String merchantOutOrderNo = idWorker0.nextId()+\"\";\n        //订单时间\n        SimpleDateFormat sdf = new SimpleDateFormat(\"yyyyMMddHHmmss\");\n        String orderTime = sdf.format(new Date());\n\n        //商户\n        paramMap.put(\"merchantOutOrderNo\",merchantOutOrderNo);\n        paramMap.put(\"merid\",merid);\n        paramMap.put(\"noncestr\",noncestr);\n        paramMap.put(\"notifyUrl\", notifyUrl);\n        paramMap.put(\"orderMoney\",paylogDo.getPayAmount().toString());\n        paramMap.put(\"orderTime\",orderTime);\n\n        //添加订单信息\n        Pay insertPayLogDO=new Pay();\n        insertPayLogDO.setUserId(paylogDo.getUserId());\n        insertPayLogDO.setAdminId(paylogDo.getAdminId());//账户id\n        insertPayLogDO.setPayAmount(paylogDo.getPayAmount()); //金额\n        insertPayLogDO.setPayStatus(3);//支付状态：1-成功；2-失败；3-等待支付\n        insertPayLogDO.setPayType(2);//支付方式：1-支付宝；2-微信；3-银联\n        insertPayLogDO.setGmtCreate(new Date());\n        insertPayLogDO.setMerchantOutOrderNo(merchantOutOrderNo); //编号\n\n        payMapper.insertSelective(insertPayLogDO);\n\n        String StringA= TestUtil.formatUrlMap(paramMap,false, false);//待签名串\n        String sign=TestUtil.getMD5(StringA+\"&key=\"+key);//签名\n\n\n        //对参数按照key=value的格式,参照参数名ASCII码排序,并对value做utf-8的encode编码后得到字符串 param\n        String param = TestUtil.formatUrlMap(paramMap, true, false);\n\n        String url = wxurl + \"?\" + param + \"&sign=\" + sign + \"&id=\" + paylogDo.getUserId();\n\n        log.info(\"url-[{}]\",url);\n\n        //返回信息\n        ResultBean<String> resultBean = new ResultBean<>();\n        resultBean.setData(url);\n        resultBean.setCode(200);\n        resultBean.setSuccess(true);\n        resultBean.setMsg(\"微信支付\");\n        return resultBean;\n    }\n}\n"
  },
  {
    "path": "hacker-service-channel-manage/src/main/java/hacker/channel/manage/controller/QiniuController.java",
    "content": "package hacker.channel.manage.controller;\n\nimport hacker.channel.manage.service.QiniuService;\nimport hacker.framework.common.request.ResultInfo;\nimport io.swagger.annotations.ApiOperation;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.web.bind.annotation.*;\nimport org.springframework.web.multipart.MultipartFile;\n\nimport javax.servlet.http.HttpServletRequest;\n\n\n/**\n * 七牛云\n *\n * @Description: J X N H\n * @EnglishName LuKe\n * @authod LiuQi\n * @date 2019/6/10 9:54\n */\n@RestController\n@CrossOrigin(methods = { RequestMethod.GET, RequestMethod.POST,RequestMethod.PUT,RequestMethod.DELETE }, origins = \"*\")\npublic class QiniuController {\n\t\n\t@Autowired\n\tprivate QiniuService qiniuService;\n\n\t@RequestMapping(value = \"/upload\", method = RequestMethod.POST)\n\t@ResponseBody\n\t@ApiOperation(value = \"图片上传操作\")\n\tpublic ResultInfo uploadImage(@RequestParam(\"file\") MultipartFile file, HttpServletRequest request) {\n\n\t\t//文件上传到七牛云\n\n\t\tResultInfo res = new ResultInfo();\n\n\t\tif(file.isEmpty()) {\n\t\t\tres.setMessage(\"文件不存在\");\n\t\t\treturn res;\n\t\t}\n\t\ttry {\n\t\t\tString url=qiniuService.saveImage(file);\n\t\t\tres.setStatus(\"0\");\n\t\t\tres.setMessage(\"文件上传成功\");\n\t\t\tres.setData(url);\n\t\t\treturn res;\n\t\t} catch (Exception e) {\n\t\t\te.printStackTrace();\n\t\t\tres.setMessage(\"文件上传失败\");\n\t\t\treturn res;\n\t\t}\n\t}\n}"
  },
  {
    "path": "hacker-service-channel-manage/src/main/java/hacker/channel/manage/controller/RoleController.java",
    "content": "package hacker.channel.manage.controller;\n\nimport hacker.channel.manage.service.RoleService;\nimport hacker.framework.common.request.BaseCode;\nimport hacker.framework.common.request.BaseResult;\nimport hacker.framework.model.Cto.RolePermissions;\nimport hacker.framework.model.entity.Role;\nimport hacker.framework.util.CommontUtil;\nimport io.swagger.annotations.ApiOperation;\nimport lombok.extern.slf4j.Slf4j;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.web.bind.annotation.*;\n\nimport java.util.List;\nimport java.util.Map;\n\n/**\n * 角色controller\n * @Description: J X N H\n * @EnglishName LuKe\n * @authod LiuQi(walker)\n * @date 2019/6/3 14:14\n */\n@Slf4j\n@RestController\n@RequestMapping(\"/api\")\n@CrossOrigin(methods = {RequestMethod.GET, RequestMethod.POST, RequestMethod.PUT, RequestMethod.DELETE}, origins = \"*\")\npublic class RoleController {\n\n    @Autowired\n    private RoleService roleService;\n\n\n    @PostMapping(\"/addRole\")\n    @ApiOperation(value = \"增加角色\")\n    public BaseResult createRole(@RequestBody Role role) {\n\n        //创建时获取当前创建时间\n        role.setCreated_at(CommontUtil.getTimeStampTime());\n        try {\n            roleService.add(role);\n            return new BaseResult(BaseCode.SUCCESS.getCode(), \"增加角色成功\", 1);\n        } catch (Exception e) {\n            e.printStackTrace();\n            log.error(\"增加角色异常\", e);\n            return new BaseResult(BaseCode.FAIL.getCode(), \"增加角色异常\", 0);\n        }\n    }\n\n\n    @PostMapping(\"/deleteRoleById\")\n    @ApiOperation(value = \"根据角色id删除角色\")\n    public BaseResult deleteById(Integer id) {\n        try {\n            roleService.deleteById(id);\n            log.info(\"删除角色成功\");\n            return new BaseResult(BaseCode.SUCCESS.getCode(), \"删除角色成功\", 1);\n        } catch (Exception e) {\n            e.printStackTrace();\n            log.error(\"删除角色异常\", e);\n            return new BaseResult(BaseCode.FAIL.getCode(), \"删除角色异常\", 0);\n        }\n    }\n\n\n    @PostMapping(\"/updateRole\")\n    @ApiOperation(value = \"根据id去修改角色\")\n    public BaseResult updateRole(@RequestBody Role role) {\n        //修改成功时获取当前修改时间\n        role.setUpdated_at(CommontUtil.getTimeStampTime());\n        try {\n            roleService.updateRole(role);\n            log.info(\"修改角色成功\");\n            return new BaseResult(BaseCode.SUCCESS.getCode(), \"修改角色成功\", 1);\n        } catch (Exception e) {\n            e.printStackTrace();\n            log.error(\"修改角色异常\", e);\n            return new BaseResult(BaseCode.FAIL.getCode(), \"修改角色异常\", 0);\n        }\n    }\n\n\n    @GetMapping(\"/listPermission\")\n    @ApiOperation(value = \"根据角色id查询该角色下的权限列表\")\n    public BaseResult queryPermissionRole(Integer id){\n        //前端传来的参数\n        System.out.println(id);\n        try {\n            List<Map<String, Object>> result = roleService.queryPermissionRole(id);\n            log.info(\"查询完成\");\n            return new BaseResult(BaseCode.SUCCESS.getCode(), \"查询完成\", result);\n        } catch (Exception e) {\n            e.printStackTrace();\n            log.error(\"查询角色权限异常\", e);\n            return new BaseResult(BaseCode.FAIL.getCode(), \"查询角色权限异常\", 0);\n        }\n    }\n\n\n    @PostMapping(\"/allotPermission\")\n    @ApiOperation(value = \"给某角色分配权限\")\n    public BaseResult allotPermission(@RequestBody RolePermissions rolePermissions) {\n        //这里封装了rid和Pid在getObj方法中，前端传rid和pids-----》对应的多个pid\n        try {\n            roleService.allotRolePermissions(rolePermissions);\n            log.info(\"分配权限成功\");\n            return new BaseResult(BaseCode.SUCCESS.getCode(),\"分配权限成功\",1);\n        } catch (Exception e) {\n            e.printStackTrace();\n            log.error(\"分配权限异常\",e);\n            return new BaseResult(BaseCode.FAIL.getCode(), \"分配权限异常\", 0);\n        }\n    }\n\n}\n"
  },
  {
    "path": "hacker-service-channel-manage/src/main/java/hacker/channel/manage/mapper/AdminMapper.java",
    "content": "package hacker.channel.manage.mapper;\n\nimport com.baomidou.mybatisplus.core.mapper.BaseMapper;\nimport hacker.framework.model.Cto.AdminRoles;\nimport hacker.framework.model.entity.Admin;\nimport org.apache.ibatis.annotations.Mapper;\nimport org.apache.ibatis.annotations.Select;\nimport org.springframework.stereotype.Repository;\n\nimport java.util.List;\n\n/**\n * @Description: J X N H\n * @EnglishName LuKe\n * @authod LiuQi\n * @date 2019/6/3 17:34\n */\n@Repository\n@Mapper\npublic interface AdminMapper extends BaseMapper<Admin> {\n\n    //通过用户名查询\n    Admin findByName(String username);\n\n    //修改用户状态\n    int updateUserStatus(Admin user);\n\n    //删除账户角色\n    void deleteAdminRole(Integer id);\n\n    //调用了封装的obj方法\n    void setRoles(List<AdminRoles> obj);\n}\n"
  },
  {
    "path": "hacker-service-channel-manage/src/main/java/hacker/channel/manage/mapper/PayMapper.java",
    "content": "package hacker.channel.manage.mapper;\n\nimport hacker.framework.model.entity.Pay;\nimport org.apache.ibatis.annotations.Mapper;\nimport org.springframework.stereotype.Repository;\n\nimport java.util.List;\n\n\n/**\n * 支付\n * @Description: J X N H\n * @EnglishName LuKe\n * @authod LiuQi(walker)\n * @date 2019/6/4 13:41\n */\n@Mapper\n@Repository\npublic interface PayMapper {\n\n    //跟住id查询支付状态\n    Pay selectByPrimaryKey(Long key);\n\n    //保存\n    int insertSelective(Pay record);\n\n    //String Pay(String id, String orderMoney);\n\n    //修改订单状态\n    int updateOrderStatus(Pay record);\n}\n"
  },
  {
    "path": "hacker-service-channel-manage/src/main/java/hacker/channel/manage/mapper/PermissionMapper.java",
    "content": "package hacker.channel.manage.mapper;\n\nimport com.baomidou.mybatisplus.core.mapper.BaseMapper;\nimport hacker.framework.model.entity.Admin;\nimport hacker.framework.model.entity.Permission;\nimport org.apache.ibatis.annotations.Mapper;\nimport org.apache.ibatis.annotations.Param;\nimport org.apache.ibatis.annotations.ResultType;\nimport org.apache.ibatis.annotations.Select;\nimport org.springframework.stereotype.Repository;\n\nimport java.util.List;\nimport java.util.Map;\n\n/**\n * 权限\n * @Description: J X N H\n * @EnglishName LuKe\n * @authod LiuQi\n * @date 2019/6/3 16:34\n */\n@Mapper\n@Repository\npublic interface PermissionMapper extends BaseMapper<Permission> {\n\n    //查询用户id的权限\n    @Select({\"select p.* from sun_permission p \" ,\n            \"join tb_role_permission rp on rp.permission_id = p.id \" ,\n            \"join tb_role r on r.id = rp.role_id \" ,\n            \"join tb_admin_role ar on ar.role_id = r.id \" ,\n            \"join tb_admin u on u.id = ar.admin_id \" ,\n            \"where u.id = #{user.id} and p.status = 1\"})\n    List<Permission> queryByUser(@Param(\"user\") Admin user);\n\n\n    //根据角色id查询该角色对应的所有权限\n    @Select({\"select p.id, p.name,p.index_name, p.parent_id pid, p.display_name sName, p.is_show isShow \",\n            \"from tb_permission p \",\n            \"join tb_role_permission rp on p.id = rp.permission_id \",\n            \"join tb_role r on r.id = rp.role_id \",\n            \"where r.id = #{id} and p.status = 1 \",\n            \"order by pid\"})\n    @ResultType(Map.class)\n    List<Map> queryByRole(Integer id);\n\n}\n"
  },
  {
    "path": "hacker-service-channel-manage/src/main/java/hacker/channel/manage/mapper/RoleMapper.java",
    "content": "package hacker.channel.manage.mapper;\n\nimport com.baomidou.mybatisplus.core.mapper.BaseMapper;\nimport hacker.framework.model.Cto.RolePermissions;\nimport hacker.framework.model.entity.Admin;\nimport hacker.framework.model.entity.Role;\nimport org.apache.ibatis.annotations.Mapper;\nimport org.springframework.stereotype.Repository;\n\nimport java.util.List;\n\n/**\n * 角色\n * @Description: J X N H\n * @EnglishName LuKe\n * @authod LiuQi\n * @date 2019/6/3 16:14\n */\n@Mapper\n@Repository\npublic interface RoleMapper extends BaseMapper<Role> {\n\n    //查询用户的角色\n    List<Role> queryRolesUser(Admin user);\n\n    //删除角色对应的权限\n    void deleteRolePermission(Integer id);\n\n    //删除账号角色\n    void deleteAdminRole(Integer id);\n\n    //调用了封装的obj方法\n    void allotPermission(List<RolePermissions> obj);\n\n}\n"
  },
  {
    "path": "hacker-service-channel-manage/src/main/java/hacker/channel/manage/service/AdminService.java",
    "content": "package hacker.channel.manage.service;\n\n\nimport hacker.framework.model.Cto.AdminRoles;\nimport hacker.framework.model.entity.Admin;\n\nimport javax.servlet.http.HttpServletRequest;\n\n/**\n * @Description: J X N H\n * @EnglishName LuKe\n * @authod LiuQi\n * @date 2019/6/3 15:34\n */\npublic interface AdminService {\n\n    /**\n     * 通过用户名查询\n     * @param username 用户名\n     * @return 管理员用户\n     */\n    Admin findByName(String username);\n\n    /**\n     * 新建管理员用户\n     * @param user 用户参数\n     * @return\n     */\n    int createNewAdmin(Admin user);\n\n    /**\n     * 修改用户状态\n     * @param user\n     * @return\n     */\n    int updateUserStatus(Admin user, HttpServletRequest request);\n\n    /**\n     * 根据id删除管理员\n     * @param id id\n     * @return\n     */\n    void deleteById(Integer id);\n\n\n    /**\n     * 为管理员分配角色\n     * @param adminRoles 在实体类封装了管理员id和所分配的角色id集合\n     */\n    void setRoles(AdminRoles adminRoles);\n\n}\n\n"
  },
  {
    "path": "hacker-service-channel-manage/src/main/java/hacker/channel/manage/service/PayService.java",
    "content": "package hacker.channel.manage.service;\n\nimport hacker.framework.model.entity.Pay;\n\n/**\n * 支付\n * @Description: J X N H\n * @EnglishName LuKe\n * @authod LiuQi(walker)\n * @date 2019/6/4 13:39\n */\npublic interface PayService {\n\n\n    /**\n     * 支付\n     * @param\n     * @param pay\n     * @return\n     */\n    String Pay(Pay pay);\n\n\n    /**\n     * 跟住用户id查询支付状态\n     * @param tradeNo\n     * @return\n     */\n    Pay findById(Long tradeNo);\n}\n"
  },
  {
    "path": "hacker-service-channel-manage/src/main/java/hacker/channel/manage/service/PermissionService.java",
    "content": "package hacker.channel.manage.service;\n\n\nimport hacker.framework.model.entity.Admin;\nimport hacker.framework.model.entity.Permission;\n\nimport java.util.List;\n\n/**\n * 权限\n * @Description: J X N H\n * @EnglishName LuKe\n * @authod LiuQi\n * @date 2019/6/3 15:14\n */\npublic interface PermissionService {\n\n    /**\n     * 查询用户的权限\n     * @param user 用户\n     * @return 权限\n     */\n    List<Permission> queryByUser(Admin user);\n}\n"
  },
  {
    "path": "hacker-service-channel-manage/src/main/java/hacker/channel/manage/service/QiniuService.java",
    "content": "package hacker.channel.manage.service;\n\nimport org.springframework.web.multipart.MultipartFile;\n\nimport java.io.IOException;\n\n/**\n * 七牛云\n *\n * @Description: J X N H\n * @EnglishName LuKe\n * @authod LiuQi\n * @date 2019/6/10 9:44\n */\npublic interface QiniuService {\n\n\tString saveImage(MultipartFile file) throws IOException;\n\n}\n"
  },
  {
    "path": "hacker-service-channel-manage/src/main/java/hacker/channel/manage/service/RoleService.java",
    "content": "package hacker.channel.manage.service;\n\nimport hacker.framework.model.Cto.RolePermissions;\nimport hacker.framework.model.entity.Admin;\nimport hacker.framework.model.entity.Role;\n\nimport java.util.List;\nimport java.util.Map;\n\n/**\n * 角色\n * @Description: J X N H\n * @EnglishName LuKe\n * @authod LiuQi\n * @date 2019/6/3 14:14\n */\npublic interface RoleService {\n\n    /**\n     * 查询用户的角色\n     * @param user 用户\n     * @return 角色\n     */\n    List<Role> queryRolesUser(Admin user);\n\n    /**\n     * 增加角色\n     * @param role 角色\n     */\n    void add(Role role);\n\n    /**\n     * 根据id删除角色\n     * @param id id\n     */\n    void deleteById(Integer id);\n\n    /**\n     * 根据id修改角色\n     * @param role role\n     */\n    void updateRole(Role role);\n\n    /**\n     * 根据角色id查询权限\n     * @param id 角色id\n     */\n    List<Map<String, Object>> queryPermissionRole(Integer id);\n\n    /**\n     * 给某角色分配权限\n     * @param rolePermissions 参数封装\n     */\n    void allotRolePermissions(RolePermissions rolePermissions);\n\n}\n"
  },
  {
    "path": "hacker-service-channel-manage/src/main/java/hacker/channel/manage/service/impl/AdminServiceImpl.java",
    "content": "package hacker.channel.manage.service.impl;\n\nimport hacker.channel.manage.mapper.AdminMapper;\nimport hacker.channel.manage.service.AdminService;\nimport hacker.framework.model.Cto.AdminRoles;\nimport hacker.framework.model.entity.Admin;\nimport hacker.framework.util.CommontUtil;\nimport hacker.framework.util.LuKeIp;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Service;\n\nimport javax.servlet.http.HttpServletRequest;\nimport java.sql.Timestamp;\nimport java.util.HashMap;\nimport java.util.List;\nimport java.util.Map;\n\n/**\n * @Description: J X N H\n * @EnglishName LuKe\n * @authod LiuQi\n * @date 2019/6/3 15:34\n */\n@Service\npublic class AdminServiceImpl implements AdminService {\n\n    @Autowired\n    private AdminMapper adminMapper;\n\n\n    //查询用户名\n    @Override\n    public Admin findByName(String username) {\n\n        return adminMapper.findByName(username);\n    }\n\n    //新建管理员用户\n    @Override\n    public int createNewAdmin(Admin user) {\n        //map\n        Map<String, Object> map = new HashMap<>(1);\n        //username\n        map.put(\"username\",user.getUsername());\n        //查询\n        List<Admin> admins = adminMapper.selectByMap(map);\n        //如果已存在该用户名的用户，新建失败\n        if (null != admins && admins.size() > 0) {\n            return -1;\n        } else {\n            //添加创建时间\n            user.setCreated_at(CommontUtil.getTimeStampTime());\n\n            //执行添加操作\n            System.out.println(user.getUsername());\n            //同步手机号和用户名，保持一致\n            user.setPhone(user.getUsername());\n            //调用添加方法\n            return adminMapper.insert(user);\n        }\n    }\n\n    //修改用户状态\n    @Override\n    public int updateUserStatus(Admin user, HttpServletRequest request) {\n        //CommontUtil获取IP的格式是 0:0:0:0:0:0:0:1\n        Timestamp timestamp = CommontUtil.getTimeStampTime();\n        user.setLogin_at(timestamp);\n        //获取登陆ip----》必须要调用自己的工具类,用java获取ip地址会出现问题,获取的ip将是 0:0:0:0:0:0:0:1---->调用工具类获取当前的登陆IP\n        String ip = LuKeIp.getIpAddress(request);\n        user.setLast_login_ip(ip);\n        //token\n        user.setLast_login_token(CommontUtil.getUUID());\n        return adminMapper.updateUserStatus(user);\n    }\n\n    //根据id删除管理员操作\n    @Override\n    public void deleteById(Integer id) {\n        //删除主键id\n        adminMapper.deleteById(id);\n        //删除账号角色\n        adminMapper.deleteAdminRole(id);\n    }\n\n    //为管理员分配角色\n    @Override\n    public void setRoles(AdminRoles adminRoles) {\n\n        List<AdminRoles> obj = adminRoles.getResult();\n        //给管理员分配角色时，先删除该管理员对应的所有角色，重新分配角色\n        adminMapper.deleteAdminRole(adminRoles.getUid());\n        //为管理员分配角色\n        adminMapper.setRoles(obj);\n    }\n\n\n}\n"
  },
  {
    "path": "hacker-service-channel-manage/src/main/java/hacker/channel/manage/service/impl/PayServiceImpl.java",
    "content": "package hacker.channel.manage.service.impl;\n\nimport hacker.channel.manage.mapper.PayMapper;\nimport hacker.channel.manage.service.PayService;\nimport hacker.framework.model.entity.Pay;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.beans.factory.annotation.Value;\nimport org.springframework.stereotype.Service;\nimport hacker.framework.util.SnowflakeIdWorker;\nimport hacker.framework.util.TestUtil;\nimport java.text.SimpleDateFormat;\nimport java.util.Date;\nimport java.util.HashMap;\nimport java.util.Map;\n\n/**\n * 支付\n * @Description: J X N H\n * @EnglishName LuKe\n * @authod LiuQi(walker)\n * @date 2019/6/4 13:40\n */\n@Service\npublic class PayServiceImpl implements PayService {\n\n    //配置\n    @Value(\"${merid}\")\n    private String merid;// 分配的商户号\n    @Value(\"${key}\")\n    private String key;// 商户号对应的密钥\n    @Value(\"${notifyUrl}\")\n    private String notifyUrl;// 用于接收回调通知的地\n    @Value(\"${noncestr}\")\n    private String noncestr;//随机参数\n\n    @Autowired\n    private PayMapper payMapper;\n\n    /**\n     * 支付\n     * @author liuqi\n     * @param pay\n     * @return\n     */\n    @Override\n    public String Pay(Pay pay) {\n        Map<String, String> paraMap = new HashMap<String, String>();\n\n        //产生支付单号\n        SnowflakeIdWorker idWorker0 = new SnowflakeIdWorker(0, 0);\n        String merchantOutOrderNo = idWorker0.nextId()+\"\";\n        //订单时间---格式yyyyMMddHHmmss\n        SimpleDateFormat sdf = new SimpleDateFormat(\"yyyyMMddHHmmss\");\n        String orderTime = sdf.format(new Date());\n\n        paraMap.put(\"merchantOutOrderNo\", merchantOutOrderNo);\n        paraMap.put(\"merid\", merid);\n        paraMap.put(\"noncestr\", noncestr);\n        paraMap.put(\"orderMoney\", pay.getPayAmount().toString());\n        paraMap.put(\"orderTime\", orderTime);\n        paraMap.put(\"notifyUrl\", notifyUrl);\n\n        //添加订单信息\n        Pay insertPay=new Pay();\n        insertPay.setUserId(pay.getUserId());\n        insertPay.setAdminId(pay.getAdminId()); //账号id\n        insertPay.setPayAmount(pay.getPayAmount()); //金额\n        insertPay.setPayStatus(3);//支付状态：1-成功；2-失败；3-等待支付\n        insertPay.setPayType(1);//支付方式：1-支付宝；2-微信；3-银联\n        insertPay.setGmtCreate(new Date());\n        insertPay.setMerchantOutOrderNo(merchantOutOrderNo); //订单编号\n\n        //调用添加的方法\n        payMapper.insertSelective(insertPay);\n\n        //对参数按照 key=value 的格式，并参照参数名 ASCII 码排序后得到字符串 stringA\n        String stringA = TestUtil.formatUrlMap(paraMap, false, false);\n        //在stringA最后拼接上key得到stringsignTemp字符串,并对stringsignTemp进行MD5运算，得到sign值\n        String stringsignTemp = stringA + \"&key=\" + key;\n        String sign = TestUtil.getMD5(stringsignTemp);\n        //对参数按照key=value的格式,参照参数名ASCII码排序,并对value做utf-8的encode编码后得到字符串 param\n        String param = TestUtil.formatUrlMap(paraMap, true, false);\n\n        String payUrl = \"https://alipay.3c-buy.com/api/createOrder\";//这是H5调支付宝的路径\n\n        //将此URL送至APP前端页面或手机浏览器打开，即可自动调起支付宝(需要安装)发起支付\n        String url = payUrl + \"?\" + param + \"&sign=\" + sign + \"&id=\" + pay.getUserId();\n        return url;\n    }\n\n\n    /**\n     * 跟住用户id查询支付状态\n     * @param tradeNo\n     * @return\n     */\n    @Override\n    public Pay findById(Long tradeNo){\n\n        //商户订单号\n        return payMapper.selectByPrimaryKey(tradeNo);\n    }\n\n\n}\n"
  },
  {
    "path": "hacker-service-channel-manage/src/main/java/hacker/channel/manage/service/impl/PermissionServiceImpl.java",
    "content": "package hacker.channel.manage.service.impl;\n\n\nimport hacker.channel.manage.mapper.PermissionMapper;\nimport hacker.channel.manage.service.PermissionService;\nimport hacker.framework.model.entity.Admin;\nimport hacker.framework.model.entity.Permission;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Service;\n\nimport java.util.List;\n\n/**\n * 权限\n * @Description: J X N H\n * @EnglishName LuKe\n * @authod LiuQi\n * @date 2019/6/3 15:44\n */\n@Service\npublic class PermissionServiceImpl implements PermissionService {\n\n    @Autowired\n    private PermissionMapper permissionMapper;\n\n    //查询用户的权限\n    @Override\n    public List<Permission> queryByUser(Admin user) {\n\n        return permissionMapper.queryByUser(user);\n    }\n}\n"
  },
  {
    "path": "hacker-service-channel-manage/src/main/java/hacker/channel/manage/service/impl/QiniuServiceImpl.java",
    "content": "package hacker.channel.manage.service.impl;\n\nimport com.alibaba.fastjson.JSONObject;\nimport com.qiniu.common.QiniuException;\nimport com.qiniu.common.Zone;\nimport com.qiniu.http.Response;\nimport com.qiniu.storage.Configuration;\nimport com.qiniu.storage.UploadManager;\nimport com.qiniu.util.Auth;\nimport hacker.channel.manage.service.QiniuService;\nimport hacker.framework.util.FileUtil;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\nimport org.springframework.stereotype.Service;\nimport org.springframework.web.multipart.MultipartFile;\n\nimport java.io.IOException;\nimport java.util.UUID;\n\n/**\n * 七牛云\n *\n * @Description: J X N H\n * @EnglishName LuKe\n * @authod LiuQi\n * @date 2019/6/10 9:44\n */\n@Service\npublic class QiniuServiceImpl implements QiniuService {\n\n    private static final Logger logger = LoggerFactory.getLogger(QiniuServiceImpl.class);\n\n    //设置好账号的ACCESS_KEY和SECRET_KEY\n    //这里我就不放真实的账号了\n    String ACCESS_KEY = \"XPzvjptibbtEy3eZHjra-RVcTIMTsdhVO\";\n    String SECRET_KEY = \"sKKfdLMhBJW9WjGesF71WztrX-VjaEt84\";\n\n    // 要上传的空间\n    String bucketname = \"wechat\";\n\n    // 密钥配置\n    Auth auth = Auth.create(ACCESS_KEY, SECRET_KEY);\n    // 构造一个带指定Zone对象的配置类,不同的七云牛存储区域调用不同的zone\n    Configuration cfg = new Configuration(Zone.zone0());\n    // ...其他参数参考类注释\n    UploadManager uploadManager = new UploadManager(cfg);\n\n    // 测试域名，只有30天有效期-----》自己去调\n    private static String QINIU_IMAGE_DOMAIN = \"http://t.wechat.mengpark.cn/\";\n\n    // 简单上传，使用默认策略，只需要设置上传的空间名就可以了\n    public String getUpToken() {\n\n        return auth.uploadToken(bucketname);\n    }\n\n    public String saveImage(MultipartFile file) throws IOException {\n        try {\n            int dotPos = file.getOriginalFilename().lastIndexOf(\".\");\n            if (dotPos < 0) {\n                return null;\n            }\n            String fileExt = file.getOriginalFilename().substring(dotPos + 1).toLowerCase();\n            // 判断是否是合法的文件后缀\n            if (!FileUtil.isFileAllowed(fileExt)) {\n                return null;\n            }\n\n            String fileName = UUID.randomUUID().toString().replaceAll(\"-\", \"\") + \".\" + fileExt;\n            // 调用put方法上传\n            Response res = uploadManager.put(file.getBytes(), fileName, getUpToken());\n            // 打印返回的信息\n            if (res.isOK() && res.isJson()) {\n                // 返回这张存储照片的地址\n                return QINIU_IMAGE_DOMAIN + JSONObject.parseObject(res.bodyString()).get(\"key\");\n\n            } else {\n                logger.error(\"七牛云异常1\"+ res.bodyString());\n                return null;\n            }\n        } catch (QiniuException e) {\n            // 请求失败时打印的异常的信息\n            logger.error(\"七牛云异常2\" + e.getMessage());\n            return null;\n        }\n    }\n}"
  },
  {
    "path": "hacker-service-channel-manage/src/main/java/hacker/channel/manage/service/impl/RoleServiceImpl.java",
    "content": "package hacker.channel.manage.service.impl;\n\nimport com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;\nimport hacker.channel.manage.mapper.PermissionMapper;\nimport hacker.channel.manage.mapper.RoleMapper;\nimport hacker.channel.manage.service.RoleService;\nimport hacker.framework.model.Cto.RolePermissions;\nimport hacker.framework.model.entity.Admin;\nimport hacker.framework.model.entity.Role;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Service;\n\nimport java.util.ArrayList;\nimport java.util.HashMap;\nimport java.util.List;\nimport java.util.Map;\n\n/**\n * 角色\n * @Description: J X N H\n * @EnglishName LuKe\n * @authod LiuQi\n * @date 2019/6/3 15:24\n */\n@Service\npublic class RoleServiceImpl implements RoleService {\n\n    @Autowired\n    private RoleMapper roleMapper;\n\n    @Autowired\n    private PermissionMapper permissionMapper;\n\n    //查询用户的角色\n    @Override\n    public List<Role> queryRolesUser(Admin user) {\n\n        return roleMapper.queryRolesUser(user);\n    }\n\n    //增加角色\n    @Override\n    public void add(Role role) {\n\n        roleMapper.insert(role);\n    }\n\n    //根据id删除角色\n    @Override\n    public void deleteById(Integer id) {\n\n        //要删除角色，先删除角色<---->权限关系，角色<---->用户关系\n        roleMapper.deleteRolePermission(id);\n        roleMapper.deleteAdminRole(id);\n        roleMapper.deleteById(id);\n    }\n\n    //根据id修改角色\n    @Override\n    public void updateRole(Role role) {\n\n        roleMapper.updateById(role);\n    }\n\n    //根据角色id查询权限\n    @Override\n    public List<Map<String, Object>> queryPermissionRole(Integer id) {\n        //存放该角色所拥有的权限id\n        List<Long> ids = new ArrayList<>(12);\n        //存放一级权限的id和在result中的索引值\n        Map<String, Object> keys = new HashMap<>(16);\n        //总的返回值\n        List<Map<String, Object>> result = new ArrayList<>(12);\n        //根据角色id查询该角色对应的所有权限--->map\n        List<Map> maps = permissionMapper.queryByRole(id);\n        QueryWrapper wrapper = new QueryWrapper();\n        wrapper.eq(\"status\", 1);  //------------>对应数据库权限的状态，查询为禁用的数据\n        //根据 Wrapper 条件，查询全部\n        List<Map<String, Object>> maps1 = permissionMapper.selectMaps(wrapper);\n        //将该角色有的权限id拿出来\n        maps.forEach(map -> {\n            Long pid = (Long) map.get(\"id\");\n            ids.add(pid);\n        });\n        //遍历所有的权限，取出一级，如果是该角色有的，做上私人标记-----------》有对应的权限会带上标记\n        maps1.forEach(map -> {\n            Long pid = (Long) map.get(\"id\");\n            if (ids.contains(pid)) {\n                map.put(\"selected\", 1);\n            }\n            Integer parentId = (Integer) map.get(\"parentId\");  //----------》父类id等于0，就是最高权限---->一级权限\n            //筛选出一级权限\n            if (0 == parentId) {\n                //将一级权限先放入返回值中\n                result.add(map);\n                //一级权限id和索引放入map\n                keys.put(pid.toString(), result.size() - 1);\n            }\n        });\n        //遍历二级，组装到一级下-----------》没有对应的权限不会带上标记，但是也会全部显示出来\n        maps1\n                .stream()\n                //过滤掉一级\n                .filter(map -> (Integer) map.get(\"parentId\") != 0)\n                .forEach(map -> {\n                    Integer parentId = (Integer) map.get(\"parentId\");\n                    Integer i = (Integer) keys.get(parentId.toString());\n                    Map<String, Object> parent = result.get(i);\n                    //根据二级权限的父节点id进行组装\n                    List<Map<String, Object>> children =\n                            (List<Map<String, Object>>) parent.get(\"children\");\n                    if (null == children) {\n                        children = new ArrayList<>();\n                        parent.put(\"children\", children);\n                    }\n                    children.add(map);\n                });\n        return result;\n    }\n\n    //给某角色分配权限\n    @Override\n    public void allotRolePermissions(RolePermissions rolePermissions) {\n\n        //给角色分配权限时，先删除该角色的所有权限，重新分配权限\n        roleMapper.deleteRolePermission(rolePermissions.getRid());\n        //给某角色分配权限\n        roleMapper.allotPermission(rolePermissions.getObj());\n    }\n\n}\n"
  },
  {
    "path": "hacker-service-channel-manage/src/main/resources/application.properties",
    "content": "## server 端口\nserver.port=8888\nserver.host=localhost\nserver.tomcat.uri-encoding=UTF-8\n\n## mybatis-plus 开启sql显示\nmybatis-plus.configuration.log-impl=org.apache.ibatis.logging.slf4j.Slf4jImpl\n\n#数据库-----》ＪＸＮＨ------》这里没有换成我服务器的数据库，后面会用脚本代替\nspring.datasource.url=jdbc:mysql://localhost:3306/jinnian?serverTimezone=Asia/Shanghai\nspring.datasource.username=root\nspring.datasource.password=123\nspring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver\nspring.datasource.max-idle=10\nspring.datasource.max-wait=10000\nspring.datasource.min-idle=5\nspring.datasource.initial-size=5\n\n#mapperXml------------->同一目录不用加\n#mybatis.mapper-locations=classpath:mapper/*.xml\n#mybatis.config-location=classpath:mybatis-config.xml\n\n#日志生成-----》用的spring boot默认log back日志------》默认生成到本地\n#debug=false\n#log.path=C:/logs/jn\n#logging.config=classpath:logback.xml\n\n# Date Convert\nspring.jackson.date-format=yyyy-MM-dd hh:mm:ss\nspring.jackson.time-zone=GMT+8\n\n## 文件上传支持\nspring.servlet.multipart.enabled=true\n## 最大文件大小\nspring.servlet.multipart.max-file-size=10MB\n\n#全局变量信息,密钥\ntoken=dy$UpUp\nsecret=5087D91C818EE6E9\n\n## 密码加密所用盐\nsalt=Jhuiabn9_DhiebFIJ==jel%$dafe4fs@deaerf_\n\n## netty websocket 配置\n#netty-websocket.host=0.0.0.0\nnetty-websocket.path=/websocket\nnetty-websocket.port=80\n\n\n## thymeleaf模板引擎\nspring.thymeleaf.cache=false\nspring.thymeleaf.encoding=utf-8\n\n\n#支付参数 回调本地内网穿透测试\n#分配的商户号---请输入自己的或者公司提供的商户号，我这里是不可用的\nmerid=2088912840264143962\n#商户号对应的密钥 ------》输入自己对应的\nkey=if1Q15rGf2rOMYGmsiUkKRzbKb0s9zw6Jt\n#用于接收回调通知的地址 alipay.3c-buy.com替换为自己的地址\nnotifyUrl=http://www.wuxf.cn:8888/api/channel/notify/callback\n#随机参数\nnoncestr=jxnh\n#支付完成跳转页面 https://github.com/Liu777替换为自己要跳转的地址\nreturnUrl=\n#二级商户名称 银联页面显示的商户名称，不填则默认。（请保证该名称已在一麻袋后台的二级商户名称中添加，并通过白名单审核，否则会报“二级商户名称不合法”）\nsubMerchantName="
  },
  {
    "path": "hacker-service-channel-manage/src/main/resources/banner.txt",
    "content": "${AnsiColor.YELLOW}Hello,Welcome to boot...${AnsiColor.RED}Sprin${AnsiColor.BRIGHT_YELLOW}gBoot的${AnsiColor.BRIGHT_GREEN}版本号:${AnsiColor.RED}${AnsiColor.MAGENTA} ${spring-boot.formatted-version} 项目制作人:LuKe（walker） 博客网站:https://www.wuxf.cn  ${AnsiColor.BRIGHT_YELLOW}\n\n\n                                                       __    __    ______   .______    _______\n                                                      |  |  |  |  /  __  \\  |   _  \\  |   ____|${AnsiColor.YELLOW}\n                                                      |  |__|  | |  |  |  | |  |_)  | |  |__   ${AnsiColor.BRIGHT_GREEN}\n                                                      |   __   | |  |  |  | |   ___/  |   __|  ${AnsiColor.BRIGHT_CYAN}\n                                                      |  |  |  | |  `--'  | |  |      |  |____ ${AnsiColor.BLUE}\n                                                      |__|  |__|  \\______/  | _|      |_______|${AnsiColor.MAGENTA}\n\n\n${AnsiColor.MAGENTA}2019年，祝每一个努力的人都有所收获。人生路上，泪水在左，欢笑在右，生命的鲜花铺满两旁。\n走过生命的四季，我们经历了泪水的洗礼，见证了欢笑的时刻，欣赏着朝阳的升起，凝视着花蕊的绽放。\n人生途中，我们收获着生命之神不尽的惠赠，满揣着她的礼物与祝福启程。一路走来，因为收获，我们不曾寒冷，我们从未孤独。\n${AnsiColor.DEFAULT}"
  },
  {
    "path": "hacker-service-channel-manage/src/main/resources/ehcache.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<ehcache name=\"es\">\n\n    <diskStore path=\"java.io.tmpdir\"/>\n\n    <!--\n       name:缓存名称。\n       maxElementsInMemory:缓存最大数目\n       maxElementsOnDisk：硬盘最大缓存个数。\n       eternal:对象是否永久有效，一但设置了，timeout将不起作用。\n       overflowToDisk:是否保存到磁盘，当系统当机时\n       timeToIdleSeconds:设置对象在失效前的允许闲置时间（单位：秒）。\n                            仅当eternal=false对象不是永久有效时使用，可选属性，默认值是0，也就是可闲置时间无穷大。\n       timeToLiveSeconds:设置对象在失效前允许存活时间（单位：秒）。最大时间介于创建时间和失效时间之间。\n                            仅当eternal=false对象不是永久有效时使用，默认是0.，也就是对象存活时间无穷大。\n       diskPersistent：是否缓存虚拟机重启期数据 The default value is false.\n       diskSpoolBufferSizeMB：这个参数设置DiskStore（磁盘缓存）的缓存区大小。默认是30MB。每个Cache都应该有自己的一个缓冲区。\n       diskExpiryThreadIntervalSeconds：磁盘失效线程运行时间间隔，默认是120秒。\n       memoryStoreEvictionPolicy：当达到maxElementsInMemory限制时，Ehcache将会根据指定的策略去清理内存。\n                                    默认策略是LRU（最近最少使用）。你可以设置为FIFO（先进先出）或是LFU（较少使用）。\n        clearOnFlush：内存数量最大时是否清除。\n        memoryStoreEvictionPolicy:\n            Ehcache的三种清空策略;\n            FIFO，first in first out，这个是大家最熟的，先进先出。\n            LFU， Less Frequently Used，就是上面例子中使用的策略，直白一点就是讲一直以来最少被使用的。\n                                        如上面所讲，缓存的元素有一个hit属性，hit值最小的将会被清出缓存。\n            LRU，Least Recently Used，最近最少使用的，缓存的元素有一个时间戳，当缓存容量满了，\n                                        而又需要腾出地方来缓存新的元素的时候，那么现有缓存元素中时间戳离当前时间最远的\n                                        元素将被清出缓存。\n    -->\n    <defaultCache\n            maxElementsInMemory=\"10000\"\n            eternal=\"false\"\n            timeToIdleSeconds=\"120\"\n            timeToLiveSeconds=\"120\"\n            overflowToDisk=\"false\"\n            diskPersistent=\"false\"\n            diskExpiryThreadIntervalSeconds=\"120\"\n    />\n\n\n</ehcache>"
  },
  {
    "path": "hacker-service-channel-manage/src/main/resources/hacker/channel/manage/mapper/AdminMapper.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE mapper PUBLIC \"-//mybatis.org//DTD Mapper 3.0//EN\" \"http://mybatis.org/dtd/mybatis-3-mapper.dtd\">\n<mapper namespace=\"hacker.channel.manage.mapper.AdminMapper\">\n    <resultMap id=\"BaseResultMap\" type=\"hacker.framework.model.entity.Admin\">\n        <result column=\"id\" jdbcType=\"INTEGER\" property=\"id\"/>\n        <result column=\"phone\" jdbcType=\"VARCHAR\" property=\"phone\"/>\n        <result column=\"nickname\" jdbcType=\"VARCHAR\" property=\"nickname\"/>\n        <result column=\"username\" jdbcType=\"VARCHAR\" property=\"username\"/>\n        <result column=\"password\" jdbcType=\"VARCHAR\" property=\"password\"/>\n        <result column=\"status\" jdbcType=\"INTEGER\" property=\"status\"/>\n        <result column=\"is_readonly\" jdbcType=\"INTEGER\" property=\"is_readonly\"/>\n        <result column=\"last_login_token\" jdbcType=\"VARCHAR\" property=\"last_login_token\"/>\n        <result column=\"last_login_ip\" jdbcType=\"VARCHAR\" property=\"last_login_ip\"/>\n        <result column=\"login_at\" jdbcType=\"TIMESTAMP\" property=\"login_at\"/>\n        <result column=\"created_at\" jdbcType=\"TIMESTAMP\" property=\"created_at\"/>\n        <result column=\"updated_at\" jdbcType=\"TIMESTAMP\" property=\"updated_at\"/>\n    </resultMap>\n\n    <!--查询用户名-->\n    <select id=\"findByName\" parameterType=\"hacker.framework.model.entity.Admin\" resultMap=\"BaseResultMap\">\n\n     SELECT * FROM tb_admin WHERE username =#{username} AND STATUS = 1\n    </select>\n\n    <!--通过id修改用户的状态-->\n    <update id=\"updateUserStatus\" parameterType=\"hacker.framework.model.entity.Admin\">\n\n      UPDATE tb_admin SET last_login_ip = #{last_login_ip},\n              last_login_token = #{last_login_token},\n              login_at = #{login_at} WHERE id = #{id}\n        </update>\n\n    <!--通过id删除当前管理员-->\n    <delete id=\"deleteAdminRole\" parameterType=\"hacker.framework.model.entity.Admin\">\n\n        delete from tb_admin_role where admin_id = #{id}\n    </delete>\n\n    <!--批量插入,分配用户角色-->\n    <insert id=\"setRoles\" parameterType=\"hacker.framework.model.Cto.AdminRoles\">\n\n        INSERT INTO tb_admin_role (admin_id, role_id) VALUES\n        <foreach collection='list' item='item' separator=','>\n            (#{item.uid},#{item.role})\n        </foreach>\n    </insert>\n</mapper>"
  },
  {
    "path": "hacker-service-channel-manage/src/main/resources/hacker/channel/manage/mapper/PayMapper.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE mapper PUBLIC \"-//mybatis.org//DTD Mapper 3.0//EN\" \"http://mybatis.org/dtd/mybatis-3-mapper.dtd\">\n<mapper namespace=\"hacker.channel.manage.mapper.PayMapper\">\n    <resultMap id=\"BaseResultMap\" type=\"hacker.framework.model.entity.Pay\">\n        <id column=\"tradeNo\" jdbcType=\"BIGINT\" property=\"tradeNo\"/>\n        <result column=\"userId\" jdbcType=\"INTEGER\" property=\"userId\"/>\n        <result column=\"adminId\" jdbcType=\"INTEGER\" property=\"adminId\"/>\n        <result column=\"payTime\" jdbcType=\"TIMESTAMP\" property=\"payTime\"/>\n        <result column=\"payAmount\" jdbcType=\"DECIMAL\" property=\"payAmount\"/>\n        <result column=\"payStatus\" jdbcType=\"INTEGER\" property=\"payStatus\"/>\n        <result column=\"payType\" jdbcType=\"INTEGER\" property=\"payType\"/>\n        <result column=\"gmtCreate\" jdbcType=\"TIMESTAMP\" property=\"gmtCreate\"/>\n    </resultMap>\n    <!--添加-->\n    <insert id=\"insertSelective\" parameterType=\"hacker.framework.model.entity.Pay\">\n        insert into tb_pay\n        <trim prefix=\"(\" suffix=\")\" suffixOverrides=\",\">\n            <if test=\"tradeNo != null\">\n                tradeNo,\n            </if>\n            <if test=\"userId != null\">\n                userId,\n            </if>\n            <if test=\"adminId != null\">\n                adminId,\n            </if>\n            <if test=\"payTime != null\">\n                payTime,\n            </if>\n            <if test=\"payAmount != null\">\n                payAmount,\n            </if>\n            <if test=\"payStatus != null\">\n                payStatus,\n            </if>\n            <if test=\"payType != null\">\n                payType,\n            </if>\n            <if test=\"gmtCreate != null\">\n                gmtCreate,\n            </if>\n            <if test=\"merchantOutOrderNo != null\">\n                merchantOutOrderNo,\n            </if>\n        </trim>\n        <trim prefix=\"values (\" suffix=\")\" suffixOverrides=\",\">\n            <if test=\"tradeNo != null\">\n                #{tradeNo,jdbcType=BIGINT},\n            </if>\n            <if test=\"userId != null\">\n                #{userId,jdbcType=INTEGER},\n            </if>\n            <if test=\"adminId != null\">\n                #{adminId,jdbcType=INTEGER},\n            </if>\n            <if test=\"payTime != null\">\n                #{payTime,jdbcType=TIMESTAMP},\n            </if>\n            <if test=\"payAmount != null\">\n                #{payAmount,jdbcType=DECIMAL},\n            </if>\n            <if test=\"payStatus != null\">\n                #{payStatus,jdbcType=INTEGER},\n            </if>\n            <if test=\"payType != null\">\n                #{payType,jdbcType=INTEGER},\n            </if>\n            <if test=\"gmtCreate != null\">\n                #{gmtCreate,jdbcType=TIMESTAMP},\n            </if>\n            <if test=\"merchantOutOrderNo != null\">\n                #{merchantOutOrderNo,jdbcType=VARCHAR},\n            </if>\n        </trim>\n    </insert>\n\n    <!--跟住id查询支付状态-->\n    <select id=\"selectByPrimaryKey\" parameterType=\"java.lang.Long\" resultMap=\"BaseResultMap\">\n        select\n        *\n        from tb_pay\n        where tradeNo = #{tradeNo,jdbcType=BIGINT}\n    </select>\n\n    <!--修改订单状态-->\n    <update id=\"updateOrderStatus\" parameterType=\"hacker.framework.model.entity.Pay\">\n        update tb_paylog\n        <set>\n            <if test=\"userId != null\">\n                userId = #{userId,jdbcType=INTEGER},\n            </if>\n            <if test=\"adminId != null\">\n                adminId = #{adminId,jdbcType=INTEGER},\n            </if>\n            <if test=\"payTime != null\">\n                payTime = #{payTime,jdbcType=TIMESTAMP},\n            </if>\n            <if test=\"payAmount != null\">\n                payAmount = #{payAmount,jdbcType=DECIMAL},\n            </if>\n            <if test=\"payStatus != null\">\n                payStatus = #{payStatus,jdbcType=INTEGER},\n            </if>\n            <if test=\"payType != null\">\n                payType = #{payType,jdbcType=INTEGER},\n            </if>\n            <if test=\"gmtCreate != null\">\n                gmtCreate = #{gmtCreate,jdbcType=TIMESTAMP},\n            </if>\n        </set>\n        where merchantOutOrderNo = #{merchantOutOrderNo,jdbcType=BIGINT}\n    </update>\n</mapper>"
  },
  {
    "path": "hacker-service-channel-manage/src/main/resources/hacker/channel/manage/mapper/RoleMapper.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE mapper PUBLIC \"-//mybatis.org//DTD Mapper 3.0//EN\" \"http://mybatis.org/dtd/mybatis-3-mapper.dtd\">\n<mapper namespace=\"hacker.channel.manage.mapper.RoleMapper\">\n    <resultMap id=\"BaseResultMap\" type=\"hacker.framework.model.entity.Role\">\n        <result column=\"id\" jdbcType=\"INTEGER\" property=\"id\"/>\n        <result column=\"display_name\" jdbcType=\"VARCHAR\" property=\"display_name\"/>\n        <result column=\"level\" jdbcType=\"INTEGER\" property=\"level\"/>\n        <result column=\"created_at\" jdbcType=\"TIMESTAMP\" property=\"created_at\"/>\n        <result column=\"updated_at\" jdbcType=\"TIMESTAMP\" property=\"updated_at\"/>\n    </resultMap>\n\n\n    <!--查询用户的角色-->\n    <select id=\"queryRolesUser\" parameterType=\"hacker.framework.model.entity.Role\" resultMap=\"BaseResultMap\">\n\n     SELECT r.id, r.display_name  FROM tb_role r JOIN tb_admin_role ur ON r.id = ur.role_id WHERE ur.admin_id = #{id}\n    </select>\n\n    <!--删除角色-权限关系-->\n    <delete id=\"deleteRolePermission\" parameterType=\"hacker.framework.model.entity.Role\">\n\n    delete from tb_role_permission where role_id = #{id}\n    </delete>\n\n    <!--删除用户-角色关系-->\n    <delete id=\"deleteAdminRole\" parameterType=\"hacker.framework.model.entity.Role\">\n\n    delete from tb_admin_role where role_id = #{id}\n    </delete>\n\n    <!--给角色分配权限-->\n    <insert id=\"allotPermission\" parameterType=\"hacker.framework.model.Cto.RolePermissions\">\n\n        insert into tb_role_permission (permission_id, role_id) values\n        <foreach collection='list' item='item' separator=','>\n            (#{item.pid},#{item.rid})\n        </foreach>\n    </insert>\n\n</mapper>"
  },
  {
    "path": "hacker-service-channel-manage/src/main/resources/logback.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<configuration debug=\"false\" scan=\"true\" scanPeriod=\"1 seconds\">\n\n    <contextName>logback</contextName>\n    <property name=\"log.path\" value=\"/data/applogs/xxl-sso/xxl-sso-server.log\"/>\n\n    <appender name=\"console\" class=\"ch.qos.logback.core.ConsoleAppender\">\n\n        <!--去除所有的日志信息-->\n       <filter class=\"ch.qos.logback.classic.filter.ThresholdFilter\" >\n            <level>WARN</level>\n        </filter>\n\n        <encoder>\n            <pattern>%d{HH:mm:ss.SSS} %contextName [%thread] %-5level %logger{36} - %msg%n</pattern>\n        </encoder>\n    </appender>\n\n    <appender name=\"file\" class=\"ch.qos.logback.core.rolling.RollingFileAppender\">\n        <file>${log.path}</file>\n        <rollingPolicy class=\"ch.qos.logback.core.rolling.TimeBasedRollingPolicy\">\n            <fileNamePattern>${log.path}.%d{yyyy-MM-dd}.zip</fileNamePattern>\n        </rollingPolicy>\n        <encoder>\n            <pattern>%date %level [%thread] %logger{36} [%file : %line] %msg%n\n            </pattern>\n        </encoder>\n    </appender>\n\n    <root level=\"info\">\n        <appender-ref ref=\"console\"/>\n        <appender-ref ref=\"file\"/>\n    </root>\n\n</configuration>"
  },
  {
    "path": "hacker-service-channel-manage/src/main/resources/static/css/htshouye.css",
    "content": "* {\n\t\t\t\tpadding: 0;\n\t\t\t\tmargin: 0;\n\t\t\t}\n\t\t\ta {\n\t\t\t\ttext-decoration: none;\n\t\t\t}\n\t\t\tli{\n\t\t\t\tlist-style: none;\n\t\t\t}\n\t\t\tinput::-webkit-input-placeholder {\n\t\t\t\ttext-indent: 10px;\n\t\t\t}\n\t\t\tinput{\n\t\t\t\ttext-indent: 10px;\n\t\t\t}\n\t\t\thtml,\n\t\t\tbody {\n\t\t\t\twidth: 100%;\n\t\t\t\theight: 100%;\n\t\t\t}\n\t\t\t.boxMax {\n\t\t\t\twidth: 100%;\n\t\t\t\theight: 100%;\n\t\t\t\tbox-sizing: border-box;\n\t\t\t\tposition: relative;\n\t\t\t\tpadding-top: 47px;\n\t\t\t\tmin-height: 715px;\n\t\t\t\tmin-width: 1250px;\n\t\t\t}\n\t\t\t.title {\n\t\t\t\twidth: 100%;\n\t\t\t\theight: 47px;\n\t\t\t\tbackground-color: #0F0930;\n\t\t\t\tline-height: 47px;\n\t\t\t\tposition: fixed;\n\t\t\t\ttop: 0;\n\t\t\t\tleft: 0;\n\t\t\t\tz-index: 799;\n\t\t\t}\n\t\t\t.title>a {\n\t\t\t\tmargin-left: 20px;\n\t\t\t\tcolor: rgb(180, 188, 200);\n\t\t\t}\n\t\t\t.titleRight {\n\t\t\t\twidth: 120px;\n\t\t\t\theight: 47px;\n\t\t\t\tline-height: 47px;\n\t\t\t\tfloat: right;\n\t\t\t\tmargin-right: 20px;\n\t\t\t\tcursor: pointer;\n\t\t\t}\n\t\t\t.titleRight:hover {\n\t\t\t\tbackground-color: rgb(63, 79, 98);\n\t\t\t}\n\t\t\t.titleRight>img {\n\t\t\t\tborder-radius: 50%;\n\t\t\t\tvertical-align: middle;\n\t\t\t\tmargin-left: 10px;\n\t\t\t}\n\t\t\t.titleRight>span {\n\t\t\t\tdisplay: inline-block;\n\t\t\t\twidth: 58px;\n\t\t\t\theight: 100%;\n\t\t\t\tline-height: 47px;\n\t\t\t\tcolor: rgb(180, 188, 200);\n\t\t\t\tfont-size: 14px;\n\t\t\t\tmargin-left: 5px;\n\t\t\t}\n\t\t\t.arrowUp:after {\n\t\t\t\tcontent: '';\n\t\t\t\tdisplay: inline-block;\n\t\t\t\twidth: 8px;\n\t\t\t\theight: 8px;\n\t\t\t\tborder-right: 1px solid #a7b1c2;\n\t\t\t\tborder-bottom: 1px solid #a7b1c2;\n\t\t\t\ttransform: rotate(-45deg);\n\t\t\t\t-webkit-transform: rotate(-45deg);\n\t\t\t\tfloat: right;\n\t\t\t\tmargin-top: 20px;\n\t\t\t}\n\t\t\t.arrowDown:after {\n\t\t\t\tcontent: '';\n\t\t\t\tdisplay: inline-block;\n\t\t\t\twidth: 6px;\n\t\t\t\theight: 6px;\n\t\t\t\tborder-bottom: 1px solid #a7b1c2;\n\t\t\t\tborder-right: 1px solid #a7b1c2;\n\t\t\t\ttransform: rotate(45deg);\n\t\t\t\t-webkit-transform: rotate(45deg);\n\t\t\t\tfloat: right;\n\t\t\t\tmargin-top: 20px;\n\t\t\t}\n\t\t\t.titleNone {\n\t\t\t\twidth: 118px;\n\t\t\t\theight: 35px;\n\t\t\t\tdisplay: none;\n\t\t\t\tmargin-top: -1px;\n\t\t\t\tborder: 1px solid rgb(180, 180, 180);\n\t\t\t\tbackground-color:white;\n\t\t\t}\n\t\t\t.titleNone>ul>li{\n\t\t\t\theight: 35px;\n\t\t\t\tline-height: 35px;\n\t\t\t}\n\t\t\t.titleNone>ul>li:hover {\n\t\t\t\tbackground-color: rgb(242, 242, 242);\n\t\t\t}\n\t\t\t.titleNone>ul>li>a {\n\t\t\t\tcolor: black;\n\t\t\t\tfont-size: 14px;\n\t\t\t\tmargin-left: 33px;\n\t\t\t}\n\t\t\t.menu {\n\t\t\t\twidth: 220px;\n\t\t\t\tmin-height: 100%;\n\t\t\t\theight: auto;\n\t\t\t\tbackground-color: #272C4F;\n\t\t\t\tfloat: left;\n\t\t\t}\n\t\t\t.menu>li {\n\t\t\t\twidth: 100%;\n\t\t\t\tborder-top: 1px solid rgb(61, 73, 87);\n\t\t\t\ttext-align: center;\n\t\t\t\tposition: relative;\n\t\t\t}\n\t\t\t.menu>li>img{\n\t\t\t\tposition: absolute;\n\t\t\t\ttop: 12px;\n\t\t\t\tleft: 30px;\n\t\t\t}\n\t\t\t.menuSpan:hover {\n\t\t\t\tbackground-color: rgb(44, 53, 66);\n\t\t\t}\n\t\t\t.menuSpan {\n\t\t\t\tdisplay: inline-block;\n\t\t\t\twidth: 100%;\n\t\t\t\theight: 40px;\n\t\t\t\tline-height: 40px;\n\t\t\t\tcursor: pointer;\n\t\t\t\tcolor: #a7b1c2;\n\t\t\t}\n\t\t\t.menuSpan:after {\n\t\t\t\tcontent: '';\n\t\t\t\tdisplay: inline-block;\n\t\t\t\twidth: 8px;\n\t\t\t\theight: 8px;\n\t\t\t\tborder-right: 1px solid #a7b1c2;\n\t\t\t\tborder-bottom: 1px solid #a7b1c2;\n\t\t\t\ttransform: rotate(-45deg);\n\t\t\t\t-webkit-transform: rotate(-45deg);\n\t\t\t\tfloat: right;\n\t\t\t\tmargin-top: 15px;\n\t\t\t\tmargin-right: 20px;\n\t\t\t}\n\t\t\t.menuSpan2:after {\n\t\t\t\tcontent: '';\n\t\t\t\tdisplay: inline-block;\n\t\t\t\twidth: 8px;\n\t\t\t\theight: 8px;\n\t\t\t\tborder-right: 1px solid #a7b1c2;\n\t\t\t\tborder-bottom: 1px solid #a7b1c2;\n\t\t\t\ttransform: rotate(45deg);\n\t\t\t\t-webkit-transform: rotate(45deg);\n\t\t\t\tfloat: right;\n\t\t\t\tmargin-top: 15px;\n\t\t\t\tmargin-right: 20px;\n\t\t\t}\n\t\t\t.minMenu {\n\t\t\t\tdisplay: none;\n\t\t\t}\n\t\t\t.minMenu>li {\n\t\t\t\twidth: 100%;\n\t\t\t\theight: 40px;\n\t\t\t\tline-height: 40px;\n\t\t\t\ttext-align: center;\n\t\t\t\tcursor: pointer;\n\t\t\t}\n\t\t\t.minMenu>li:hover{\n\t\t\t\tbackground-color:rgb(62,75,92);\n\t\t\t}\n\t\t\t.minMenu>li>a{\n\t\t\t\tdisplay: inline-block;\n\t\t\t\twidth: 100%;\n\t\t\t\theight: 100%;\n\t\t\t\tcolor: #a7b1c2;\n\t\t\t}\n\t\t\t.clearfix:after {\n\t\t\t\tcontent: \"\";\n\t\t\t\theight: 0;\n\t\t\t\tline-height: 0;\n\t\t\t\tdisplay: block;\n\t\t\t\tvisibility: hidden;\n\t\t\t\tclear: both;\n\t\t\t}"
  },
  {
    "path": "hacker-service-channel-manage/src/main/resources/static/js/base.js",
    "content": "//适配兼容\n\n(function (doc, win) {\n    var docEle = doc.documentElement,\n        dpr = Math.min(win.devicePixelRatio, 3),\n        scale = 1 / dpr,\n        resizeEvent = 'orientationchange' in window ? 'orientationchange' : 'resize';\n    var metaEle = doc.createElement('meta');\n    metaEle.name = 'viewport';\n    metaEle.content = 'initial-scale=' + scale + ',maximum-scale=' + scale;\n    docEle.firstElementChild.appendChild(metaEle);\n\n    var recalCulate = function () {\n        var width = docEle.clientWidth;\n        docEle.style.fontSize = 100 * (width / 375) + 'px';\n    };\n\n    recalCulate();\n\n    if (!doc.addEventListener) return;\n    win.addEventListener(resizeEvent, recalCulate, false);\n})(document, window);\n"
  },
  {
    "path": "hacker-service-channel-manage/src/main/resources/templates/dr.html",
    "content": "<!DOCTYPE html>\n<html>\n\n<head>\n    <meta charset=\"UTF-8\">\n    <title>登陆</title>\n    <script src=\"http://libs.baidu.com/jquery/2.0.0/jquery.min.js\"></script>\n\n    <style type=\"text/css\">\n        * {\n            padding: 0;\n            margin: 0;\n        }\n\n        html,\n        body {\n            width: 100%;\n            height: 100%;\n        }\n\n        .box {\n            width: 100%;\n            height: 100%;\n            /*//background-color: rgb(54, 65, 80);*/\n            overflow: hidden;\n            background-image: url(\"https://www.wuxf.cn/upload/2019/6/你的名字-2fdcafc6078f4c39b1a4759871cec3c6.jpg\");\n            background-size: 100% 100%;\n        }\n\n        .center {\n            width: 400px;\n            height: 450px;\n            margin: 110px auto;\n            overflow: hidden;\n        }\n        .center > p {\n            color: #fffab7;\n            font-size: 60px;\n            text-align: center;\n            margin-bottom: 50px;\n        }\n\n        .centerDiv {\n            width: 100%;\n            height: 300px;\n            background-color: rgba(253, 251, 255, 0);\n            overflow: hidden;\n        }\n\n        .centerDiv > p {\n            font-size: 20px;\n            color: rgb(255, 153, 140);\n            text-align: center;\n            margin-top: 30px;\n            margin-bottom: 20px;\n        }\n\n        .centerDiv > input {\n            width: 85%;\n            height: 40px;\n            line-height: 40px;\n            margin-bottom: 15px;\n            margin-left: 7.5%;\n            background-color: rgba(253, 251, 255,0);\n            border: 1px solid rgb(12, 12, 11);\n            text-indent: 10px;\n        }\n\n\n\n        .centerDiv > input::-webkit-input-placeholder {\n            text-indent: 10px;\n        }\n\n        .btn1 {\n            width: 85%;\n            height: 40px;\n            line-height: 40px;\n            margin-left: 7.5%;\n            color: #fff;\n            background-color: #132fff;\n            border: #32b64f;\n            font-size: 17px;\n            margin-top: 15px;\n            cursor: pointer;\n        }\n\n        .btn1:hover {\n            background-color: rgb(59, 156, 150);\n            border: rgb(59, 156, 150);\n        }\n    </style>\n</head>\n\n<body>\n<div class=\"box\">\n    <div class=\"center\">\n        <p>堇夏年华</p>\n        <div class=\"centerDiv\">\n            <p>你若不离不弃，我必生死相依</p><br>\n            <input type=\"text\" placeholder=\"请输入用户名\" class=\"username\"/>\n            <input type=\"password\" placeholder=\"请输入密码\" class=\"passWord\"/>\n            <button class=\"btn1\">登录</button>\n\n        </div>\n    </div>\n</div>\n\n<script type=\"text/javascript\">\n\n\n    $('.btn1').click(function () {\n        var username = $('.username').val();\n        var password = $('.passWord').val();\n        console.log(username);\n        console.log(password);\n        $.ajax({\n            type: 'POST',\n            url: '/api/login',\n            data: {\"username\": username, \"password\": password},\n            dataType: 'json',\n            success: function (data) {\n                console.log(data);\n                if (data.data == 1) {\n                    document.cookie = \"yhm=\" + data.msg;\n                     //window.location.href=\"qdst\";\n                     window.location.href=\"https://www.wuxf.cn\";\n                    // alert('登录成功');\n                } else {\n                    alert('账号密码错误');\n                }\n            },\n            error: function () {\n                alert('登录失败');\n            }\n        })\n    })\n\n</script>\n</body>\n</html>"
  },
  {
    "path": "hacker-service-channel-manage/src/main/resources/templates/error/010.html",
    "content": "<!DOCTYPE html>\n<html xmlns:th=\"http://www.thymeleaf.org\">\n<head th:include=\"templates/include :: header\"></head>\n<body class=\"gray-bg\">\n<div class=\"middle-box text-center animated fadeInDown\">\n    <div style=\"color: red\">\n        <h1>0 1 0</h1>\n    </div>\n    <div class=\"error-desc\">\n        sorry,您无权访问...\n        <br/>您可以返回主页看看\n        <br/><a href=\"/hacker-walker\" class=\"btn btn-primary m-t\">主页</a>\n    </div>\n</div>\n\n<!-- 全局js -->\n<script src=\"js/jquery.min.js?v=2.1.4\"></script>\n<script src=\"js/bootstrap.min.js?v=3.3.6\"></script>\n\n<script type=\"text/javascript\" src=\"http://tajs.qq.com/stats?sId=9051096\" charset=\"UTF-8\"></script>\n<!--统计代码，可删除-->\n\n</body>\n\n</html>\n"
  },
  {
    "path": "hacker-service-channel-manage/src/main/resources/templates/error/404.html",
    "content": "<!DOCTYPE html>\n<html xmlns:th=\"http://www.thymeleaf.org\">\n<head th:include=\"templates/include :: header\"></head>\n<body class=\"gray-bg\">\n\n\n<div class=\"middle-box text-center animated fadeInDown\">\n    <h1>404</h1>\n    <h3 class=\"font-bold\">页面未找到！</h3>\n\n    <div class=\"error-desc\">\n        抱歉，页面好像去火星了~\n        <form class=\"form-inline m-t\" role=\"form\">\n            <div class=\"form-group\">\n                <input type=\"email\" class=\"form-control\" placeholder=\"请输入您需要查找的内容 …\">\n            </div>\n            <button type=\"submit\" class=\"btn btn-primary\">搜索</button>\n        </form>\n    </div>\n</div>\n\n<!-- 全局js -->\n<script src=\"js/jquery.min.js?v=2.1.4\"></script>\n<script src=\"js/bootstrap.min.js?v=3.3.6\"></script>\n\n<script type=\"text/javascript\" src=\"http://tajs.qq.com/stats?sId=9051096\" charset=\"UTF-8\"></script>\n<!--统计代码，可删除-->\n\n</body>\n\n</html>\n"
  },
  {
    "path": "hacker-service-channel-manage/src/main/resources/templates/error/500.html",
    "content": "<!DOCTYPE html>\n<html xmlns:th=\"http://www.thymeleaf.org\">\n<head th:include=\"templates/include :: header\"></head>\n<body class=\"gray-bg\">\n\n\n<div class=\"middle-box text-center animated fadeInDown\">\n    <h1>500</h1>\n    <h3 class=\"font-bold\">服务器内部错误</h3>\n\n    <div class=\"error-desc\">\n        服务器好像出错了...\n        <br/>您可以返回主页看看\n        <br/><a href=\"index.html\" class=\"btn btn-primary m-t\">主页</a>\n    </div>\n</div>\n\n<!-- 全局js -->\n<script src=\"js/jquery.min.js?v=2.1.4\"></script>\n<script src=\"js/bootstrap.min.js?v=3.3.6\"></script>\n\n<script type=\"text/javascript\" src=\"http://tajs.qq.com/stats?sId=9051096\" charset=\"UTF-8\"></script>\n<!--统计代码，可删除-->\n\n</body>\n\n</html>\n"
  },
  {
    "path": "hacker-service-channel-manage/src/main/resources/templates/qdst.html",
    "content": "<!DOCTYPE html>\n<html>\n<head>\n    <meta charset=\"UTF-8\">\n    <title>主页</title>\n    <link rel=\"stylesheet\" type=\"text/css\" href=\"../static/css/htshouye.css\"/>\n    <link rel=\"stylesheet\" type=\"text/css\" href=\"http://cdn.datatables.net/1.10.15/css/jquery.dataTables.css\">\n    <script src=\"http://libs.baidu.com/jquery/2.0.0/jquery.min.js\"></script>\n    <script type=\"text/javascript\" charset=\"utf8\"\n            src=\"http://cdn.datatables.net/1.10.15/js/jquery.dataTables.js\"></script>\n    <style type=\"text/css\">\n        .minMenu1 {\n            display: block;\n        }\n\n        .content {\n            overflow: hidden;\n            min-height: 100%;\n            height: auto;\n            position: relative;\n        }\n\n        .contentA {\n            width: 280px;\n            margin-top: 28px;\n            margin-left: 30px;\n            display: inline-block;\n        }\n\n        .contentA > a {\n            color: rgb(198, 194, 194);\n            font-size: 15px;\n        }\n\n        .contentA > span {\n            color: rgb(198, 194, 194);\n        }\n\n        label {\n            margin-right: 50px;\n            width: 235px;\n            height: 35px;\n            float: right;\n            margin-top: -25px;\n            margin-bottom: 10px;\n        }\n\n        label > input {\n            width: 158px;\n            height: 26px;\n            border: 1px solid black;\n            text-indent: 10px;\n        }\n\n        label > input::-webkit-input-placeholder {\n            text-indent: 10px;\n        }\n\n        #example,\n        #example td {\n            border: 1px solid rgb(180, 180, 180);\n            text-align: center;\n            height: 25px;\n            line-height: 25px;\n            font-size: 13px;\n        }\n\n        #example {\n            width: 94% !important;\n            margin-left: 2% !important;\n            margin-top: 30px !important;\n        }\n\n        #example td {\n            padding: 9px 5px;\n        }\n\n        #example tr:nth-child(even) {\n            background: rgb(220, 220, 220);\n        }\n\n        #example button {\n            width: 24%;\n            height: 30px;\n            line-height: 29px;\n            border-radius: 5px;\n            cursor: pointer;\n            text-align: center;\n            margin-right: 10px;\n            margin-left: 10px;\n            font-size: 12px;\n            background-color: rgb(24, 166, 137);\n            border-color: transparent;\n            color: white;\n        }\n\n        .box-min {\n            width: 100%;\n            height: 98%;\n            background-color: transparent;\n            position: absolute;\n            top: 0;\n            left: 0;\n            z-index: 887;\n            display: none;\n        }\n\n        /* 修改信息 */\n        .amend1 {\n            width: 45%;\n            height: 300px;\n            background-color: rgb(220, 220, 220);\n            position: absolute;\n            top: 0;\n            bottom: 0;\n            right: 0;\n            left: 0;\n            margin: auto;\n            z-index: 888;\n            text-align: center;\n            padding-top: 65px;\n            border-radius: 10px;\n        }\n\n        .amend1 > li {\n            height: 40px;\n            line-height: 40px;\n            margin-bottom: 15px;\n        }\n\n        .amend1 > li > input {\n            width: 300px;\n            margin-left: 20px;\n            height: 35px;\n            line-height: 35px;\n        }\n\n        .amend1 > button {\n            width: 72px;\n            height: 36px;\n            line-height: 35px;\n            border-radius: 5px;\n            cursor: pointer;\n            text-align: center;\n            margin-left: 65px;\n            margin-top: 35px;\n        }\n\n        .addBtn {\n            background-color: #009688;\n            border-color: transparent;\n            color: white;\n            margin-left: -15px !important;\n\n        }\n\n        .removeBtn {\n            background-color: rgb(236, 71, 88);\n            border-color: transparent;\n            color: white;\n            margin-left: 15px;\n        }\n\n        .input1 {\n            margin-left: 32px !important;\n        }\n\n        .A2none {\n            display: none;\n        }\n\n        .success1 {\n            width: 180px;\n            height: 50px;\n            line-height: 50px;\n            background-color: #009688;\n            color: white;\n            text-align: center;\n            border-radius: 8px;\n            position: absolute;\n            left: 0;\n            top: 0;\n            bottom: 0;\n            right: 0;\n            margin: auto;\n            display: none;\n        }\n    </style>\n</head>\n<body>\n<!-- 头部   -->\n<div class=\"boxMax\">\n    <div class=\"title\">\n        <a href=\"qdst.html\">堇夏年华</a>\n        <div class=\"titleRight\">\n            <img src=\"../static/img/tx.png\"/>\n            <span class=\"arrowDown yhm\">用户名</span>\n            <div class=\"titleNone\">\n                <ul>\n                    <li><a href=\"dr.html\">退出登录</a></li>\n                </ul>\n            </div>\n        </div>\n    </div>\n    <!-- 左侧导航栏  -->\n    <ul class=\"menu\">\n        <li>\n            <img src=\"../static/img/qdsrc.png\" alt=\"\"/>\n            <span class=\"menuSpan menuSpan2\">主页</span>\n            <ul class=\"minMenu minMenu1\">\n                <li><a href=\"walker\">hacker-walker</a></li>\n                <li><a href=\"qdst.html\">黑客帝国walker</a></li>\n            </ul>\n        </li>\n        <li>\n            <img src=\"../static/img/hysrc.png\" alt=\"\"/>\n            <span class=\"menuSpan\">权限管理</span>\n            <ul class=\"minMenu\">\n                <li><a href=\"yhlb.html\">用户管理</a></li>\n                <li><a href=\"jslb.html\">角色管理</a></li>\n            </ul>\n        </li>\n        <li>\n            <img src=\"../static/img/ygsrc.png\" alt=\"\"/>\n            <span class=\"menuSpan\">系统管理</span>\n            <ul class=\"minMenu \">\n                <li><a href=\"xtlb.html\">系统列表</a></li>\n            </ul>\n        </li>\n    </ul>\n    <!-- 主体内容 -->\n    <div class=\"content\">\n        <div class=\"contentA\">\n            <a href=\"htsy.html\">首页</a>&nbsp;\n            <span> / </span>&nbsp;\n            <a href=\"qxgl.html\">权限管理</a>&nbsp;\n            <span> / </span>&nbsp;\n            <a href=\"xtgl.html\">系统管理</a>\n        </div>\n        <table cellspacing=\"0\" class=\"stTable\" id=\"example\">\n            <thead>\n    <!--  所占百分比 -->\n            <tr>\n                <td width=\"10%\">用户ID</td>\n                <td width=\"15%\">登陆名称</td>\n                <td width=\"15%\">用户名名称</td>\n                <td width=\"10%\">用户状态</td>\n                <td width=\"20%\">创建时间</td>\n                <td width=\"30%\">操作</td>\n            </tr>\n            </thead>\n        </table>\n    </div>\n    <div class=\"box-min\">\n        <ul class=\"amend1\">\n            <li><span>用户ID</span><input type=\"text\" class=\"input1\" disabled=\"disabled\"></li>\n            <li><span>登陆名称</span><input type=\"text\" class=\"input2\"></li>\n            <li><span>用户名名称</span><input type=\"text\" class=\"input3\"></li>\n            <li><span>用户状态</span><input type=\"text\" class=\"input4\"></li>\n            <button class=\"addBtn\">确认修改</button>\n            <button class=\"removeBtn\">取消</button>\n        </ul>\n    </div>\n    <div class=\"success1\">复制成功</div>\n</div>\n\n<script type=\"text/javascript\">\n    var x = document.cookie;\n    var yhm = x.split(\";\")[0].split(\"=\")[1];\n    console.log(x)\n    console.log(yhm);\n    $('.yhm').html(yhm);\n\n\n    $('.titleRight').mouseenter(function () {\n        $('.titleNone').css({\n            display: \"block\"\n        })\n    })\n    $('.titleRight').mouseleave(function () {\n        $('.titleNone').css({\n            display: \"none\"\n        })\n    })\n    $('.menuSpan').click(function () {\n        var notA = $(this).next();\n        $('.menuSpan').not(this).removeClass('menuSpan2');\n        $('.minMenu').not(notA).hide(500);\n        $(this).toggleClass('menuSpan2');\n        $(this).next().toggle(500);\n    })\n\n    //表格\n    $('#example').DataTable({\n        bAutoWidth: false,//自动宽度\n        bDeferRender: true,//延迟渲染\n        lengthChange: false,//控制是否可以改变每页数据量\n        retrieve: true,\n        \"oLanguage\": {//插件的汉化\n            \"sLengthMenu\": \"每页显示 _MENU_ 条记录\",\n            \"sZeroRecords\": \"抱歉， 没有找到\",\n            \"sInfo\": \"从 _START_ 到 _END_ /共 _TOTAL_ 条数据\",\n            \"sInfoEmpty\": \"没有数据\",\n            \"sInfoFiltered\": \"(从 _MAX_ 条数据中检索)\",\n            \"oPaginate\": {\n                \"sFirst\": \"首页\",\n                \"sPrevious\": \"前一页\",\n                \"sNext\": \"后一页\",\n                \"sLast\": \"尾页\"\n            },\n            \"sZeroRecords\": \"没有检索到数据\",\n            \"sProcessing\": \"<img src='' />\",\n            \"sSearch\": \"搜索\"\n        },\n            //显示当前账户的信息\n        //     ajax: {\n        //         url: '/api/channel/findByStatus/1',\n        //         type: 'POST',\n        //         data: JSON.stringify({status: 1, registerDate: sj1}),\n        //         dataSrc: ''\n        //     },\n        //     columns: [{\n        //         data: 'id'\n        //     }, {\n        //         data: 'name'\n        //     }, {\n        //         data: 'price'\n        //     }, {\n        //         data: 'channel_money'\n        //     }, {\n        //         data: 'register_num'\n        //     }, {\n        //         data: 'user_id'\n        //     }\n        //     ],\n        //     columnDefs: [{\n        //         targets: 8,\n        //         render: function (data, type, row, meta) {\n        //             return '<button class=\"xgBtn\" onclick = \"xgBtn1(this)\">修改信息</button><button onclick = \"fzBtn(this)\">复制链接</button><button class=\"rBtn\" onclick = \"jyBtn(this)\">禁用渠道</button>';\n        //         }\n        //     },\n        //         {\"orderable\": false, \"targets\": 8},\n        //     ],\n    });\n\n    // 修改信息\n    function xgBtn1(this1) {\n        $('.box-min').slideToggle(400);\n        var Row1 = $(this1).parents('tr').eq(0);\n        var sz1 = $(\"#example\").dataTable().fnGetData(Row1);\n        $('.input1').val(sz1.id);\n        $('.input2').val(sz1.name);\n        $('.input3').val(sz1.price);\n        $('.input4').val(sz1.staus);\n    }\n\n    $('.removeBtn').click(function () {\n        $('.box-min').slideUp(400);\n    })\n    $('.addBtn').click(function () {\n        var qdID = $('.input1').val();\n        var qdName = $('.input2').val();\n        var qdMoney = $('.input3').val();\n        var qdMoney = $('.input4').val();\n        $.ajax({\n            type: \"post\",\n            url: \"/api/channel/save\",\n            data: JSON.stringify({id: qdID, name: qdName, price: qdMoney,staus:Staus}),\n            asasync: true,\n            cache: false,\n            contentType: 'application/json',\n            success: function (e) {\n                alert('修改成功');\n                window.location.href = \"qdst\";\n            }\n        })\n    })\n\n\n</script>\n</body>\n</html>\n"
  },
  {
    "path": "pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n         xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n    <modelVersion>4.0.0</modelVersion>\n\n    <!--父项目-->\n    <groupId>Hacker.walker</groupId>\n    <artifactId>Hacker-walker-cloud</artifactId>\n    <packaging>pom</packaging>\n    <version>1.0-SNAPSHOT</version>\n\n    <name>Hacker-walker-cloud</name>\n\n    <!--子项目-->\n    <modules>\n        <module>Hacker-framework-model</module>\n        <module>Hacker-framework-common</module>\n        <module>Hacker-framework-util</module>\n        <module>Hacker-service-channel-manage</module>\n        <module>Hacker-govern-center</module>\n        <module>Hacker-govern-gateway</module>\n    </modules>\n    <!--子项目-->\n\n    <!-- 开发不易，希望您可以保留一下版权声明。笔芯~ -->\n    <description>\n        walker开源作品 个人博客:https://wuxf.cn 微信公众号:堇夏年华\n    </description>\n\n    <developers>\n        <developer>\n            <id>LuKe</id>\n            <name>walker</name>\n            <email>a18627830855@163.com</email>\n            <url>https://wuxf.cn</url>\n        </developer>\n    </developers>\n\n    <parent>\n        <groupId>org.springframework.boot</groupId>\n        <artifactId>spring-boot-starter-parent</artifactId>\n        <version>2.0.7.RELEASE</version>\n        <relativePath/>\n    </parent>\n\n    <!--规范下自己的版本号-->\n    <properties>\n        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>\n        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>\n        <java.version>1.8</java.version>\n        <spring-boot.version>2.0.7.RELEASE</spring-boot.version>\n        <springfox-swagger.version>2.9.2</springfox-swagger.version>\n    </properties>\n    <!--规范下自己的版本号-->\n\n    <dependencies>\n        <!--启动-->\n        <dependency>\n            <groupId>org.springframework.boot</groupId>\n            <artifactId>spring-boot-starter</artifactId>\n            <version>2.1.5.RELEASE</version>\n        </dependency>\n        <dependency>\n            <groupId>org.springframework.boot</groupId>\n            <artifactId>spring-boot-starter-test</artifactId>\n            <version>2.1.5.RELEASE</version>\n        </dependency>\n        <dependency>\n            <groupId>org.springframework.boot</groupId>\n            <artifactId>spring-boot-starter-web</artifactId>\n            <version>2.1.4.RELEASE</version>\n        </dependency>\n        <!--启动-->\n\n        <!--lombok-->\n        <dependency>\n            <groupId>org.projectlombok</groupId>\n            <artifactId>lombok</artifactId>\n            <version>1.18.8</version>\n        </dependency>\n        <!--lombok-->\n\n        <!--aspectj-->\n        <dependency>\n            <groupId>org.aspectj</groupId>\n            <artifactId>aspectjweaver</artifactId>\n            <version>1.9.2</version>\n        </dependency>\n        <!--aspectj-->\n\n        <!-- swagger2 -->\n        <dependency>\n            <groupId>io.springfox</groupId>\n            <artifactId>springfox-swagger2</artifactId>\n            <version>${springfox-swagger.version}</version>\n        </dependency>\n        <dependency>\n            <groupId>io.springfox</groupId>\n            <artifactId>springfox-swagger-ui</artifactId>\n            <version>${springfox-swagger.version}</version>\n        </dependency>\n        <!-- swagger2 -->\n\n        <!-- fastjson -->\n        <dependency>\n            <groupId>com.alibaba</groupId>\n            <artifactId>fastjson</artifactId>\n            <version>1.2.54</version>\n        </dependency>\n        <!-- fastjson -->\n\n        <!--mybatis-->\n        <dependency>\n            <groupId>com.baomidou</groupId>\n            <artifactId>mybatis-plus-boot-starter</artifactId>\n            <version>3.1.1</version>\n        </dependency>\n        <!--mybatis-->\n\n        <!--lang3-->\n        <dependency>\n            <groupId>org.apache.commons</groupId>\n            <artifactId>commons-lang3</artifactId>\n            <version>3.8</version>\n        </dependency>\n        <!--lang3-->\n\n        <!-- 七牛云 -->\n        <dependency>\n            <groupId>com.qiniu</groupId>\n            <artifactId>qiniu-java-sdk</artifactId>\n            <version>[7.2.0, 7.2.99]</version>\n        </dependency>\n        <dependency>\n            <groupId>com.squareup.okhttp3</groupId>\n            <artifactId>okhttp</artifactId>\n            <version>3.3.1</version>\n            <scope>compile</scope>\n        </dependency>\n        <dependency>\n            <groupId>com.google.code.gson</groupId>\n            <artifactId>gson</artifactId>\n            <version>2.6.2</version>\n            <scope>compile</scope>\n        </dependency>\n        <dependency>\n            <groupId>com.qiniu</groupId>\n            <artifactId>happy-dns-java</artifactId>\n            <version>0.1.4</version>\n            <scope>compile</scope>\n        </dependency>\n        <!-- 七牛云 -->\n\n        <!--mysql-->\n        <dependency>\n            <groupId>mysql</groupId>\n            <artifactId>mysql-connector-java</artifactId>\n            <version>8.0.15</version>\n        </dependency>\n        <!--mysql-->\n\n        <!-- redis -->\n        <dependency>\n            <groupId>org.springframework.boot</groupId>\n            <artifactId>spring-boot-starter-data-redis</artifactId>\n            <version>2.1.4.RELEASE</version>\n        </dependency>\n        <!-- redis -->\n\n        <!--commons-->\n        <dependency>\n            <groupId>commons-codec</groupId>\n            <artifactId>commons-codec</artifactId>\n            <version>1.12</version>\n        </dependency>\n        <!--commons-->\n\n        <!--shiro-->\n        <dependency>\n            <groupId>org.apache.shiro</groupId>\n            <artifactId>shiro-ehcache</artifactId>\n            <version>1.4.1</version>\n        </dependency>\n        <!--shiro-->\n\n        <!--websocket-->\n        <dependency>\n            <groupId>org.yeauty</groupId>\n            <artifactId>netty-websocket-spring-boot-starter</artifactId>\n            <version>0.6.5</version>\n        </dependency>\n        <!--websocket-->\n\n        <!-- thymeleaf对shiro的支持-->\n        <dependency>\n            <groupId>org.apache.shiro</groupId>\n            <artifactId>shiro-spring</artifactId>\n            <version>1.3.2</version>\n        </dependency>\n        <dependency>\n            <groupId>com.github.theborakompanioni</groupId>\n            <artifactId>thymeleaf-extras-shiro</artifactId>\n            <version>2.0.0</version>\n        </dependency>\n\n        <!-- thymeleaf 模板引擎-->\n        <dependency>\n            <groupId>org.springframework.boot</groupId>\n            <artifactId>spring-boot-starter-thymeleaf</artifactId>\n        </dependency>\n\n    </dependencies>\n\n    <!--build-->\n    <build>\n        <resources>\n            <resource>\n                <directory>src/main/resources</directory>\n                <filtering>true</filtering>\n            </resource>\n        </resources>\n        <plugins>\n            <plugin>\n                <groupId>org.apache.maven.plugins</groupId>\n                <artifactId>maven-compiler-plugin</artifactId>\n                <configuration>\n                    <source>1.8</source>\n                    <target>1.8</target>\n                    <encoding>UTF-8</encoding>\n                </configuration>\n            </plugin>\n            <plugin>\n                <groupId>org.apache.maven.plugins</groupId>\n                <artifactId>maven-source-plugin</artifactId>\n            </plugin>\n            <plugin>\n                <groupId>org.apache.maven.plugins</groupId>\n                <artifactId>maven-archetype-plugin</artifactId>\n            </plugin>\n            <plugin>\n                <groupId>org.apache.maven.plugins</groupId>\n                <artifactId>maven-surefire-plugin</artifactId>\n                <configuration>\n                    <skip>true</skip>\n                </configuration>\n            </plugin>\n        </plugins>\n    </build>\n    <!--build-->\n\n    <!--aliyun-->\n    <repositories>\n        <repository>\n            <id>aliyun-repos</id>\n            <url>http://maven.aliyun.com/nexus/content/groups/public/</url>\n            <snapshots>\n                <enabled>false</enabled>\n            </snapshots>\n        </repository>\n    </repositories>\n\n    <pluginRepositories>\n        <pluginRepository>\n            <id>aliyun-plugin</id>\n            <url>http://maven.aliyun.com/nexus/content/groups/public/</url>\n            <snapshots>\n                <enabled>false</enabled>\n            </snapshots>\n        </pluginRepository>\n    </pluginRepositories>\n    <!--aliyun-->\n\n</project>\n"
  }
]