Browse Source

ly create

ly 3 years ago
commit
16510882f9
100 changed files with 7179 additions and 0 deletions
  1. 3 0
      .gitignore
  2. 7 0
      Dockerfile
  3. 191 0
      LICENSE
  4. 116 0
      README.md
  5. 8 0
      docker-compose.yml
  6. 441 0
      pom.xml
  7. 25 0
      src/main/java/io/renren/RenrenApplication.java
  8. 37 0
      src/main/java/io/renren/common/annotation/DataFilter.java
  9. 40 0
      src/main/java/io/renren/common/annotation/PlantDataFilter.java
  10. 28 0
      src/main/java/io/renren/common/annotation/SysLog.java
  11. 123 0
      src/main/java/io/renren/common/aspect/DataFilterAspect.java
  12. 126 0
      src/main/java/io/renren/common/aspect/PlantDataFilterAspect.java
  13. 46 0
      src/main/java/io/renren/common/aspect/RedisAspect.java
  14. 101 0
      src/main/java/io/renren/common/aspect/SysLogAspect.java
  15. 47 0
      src/main/java/io/renren/common/constant/JxlsTemplateEnum.java
  16. 27 0
      src/main/java/io/renren/common/constant/JxlsTemplateFree.java
  17. 61 0
      src/main/java/io/renren/common/exception/RRException.java
  18. 64 0
      src/main/java/io/renren/common/exception/RRExceptionHandler.java
  19. 21 0
      src/main/java/io/renren/common/utils/ConfigConstant.java
  20. 141 0
      src/main/java/io/renren/common/utils/Constant.java
  21. 228 0
      src/main/java/io/renren/common/utils/DateUtils.java
  22. 40 0
      src/main/java/io/renren/common/utils/EmailUtils.java
  23. 275 0
      src/main/java/io/renren/common/utils/ExcelUtils.java
  24. 49 0
      src/main/java/io/renren/common/utils/ExportWordUtils.java
  25. 51 0
      src/main/java/io/renren/common/utils/HttpContextUtils.java
  26. 64 0
      src/main/java/io/renren/common/utils/IPUtils.java
  27. 61 0
      src/main/java/io/renren/common/utils/LocalFile.java
  28. 26 0
      src/main/java/io/renren/common/utils/MapUtils.java
  29. 109 0
      src/main/java/io/renren/common/utils/PDFTemplateUtil.java
  30. 110 0
      src/main/java/io/renren/common/utils/PageUtils.java
  31. 77 0
      src/main/java/io/renren/common/utils/Query.java
  32. 64 0
      src/main/java/io/renren/common/utils/R.java
  33. 21 0
      src/main/java/io/renren/common/utils/RedisKeys.java
  34. 99 0
      src/main/java/io/renren/common/utils/RedisUtils.java
  35. 61 0
      src/main/java/io/renren/common/utils/ShiroUtils.java
  36. 51 0
      src/main/java/io/renren/common/utils/SpringContextUtils.java
  37. 35 0
      src/main/java/io/renren/common/utils/export/EncodeTools.java
  38. 20 0
      src/main/java/io/renren/common/utils/export/JxlsTemplate.java
  39. 74 0
      src/main/java/io/renren/common/utils/export/JxlsView.java
  40. 32 0
      src/main/java/io/renren/common/validator/Assert.java
  41. 49 0
      src/main/java/io/renren/common/validator/ValidatorUtils.java
  42. 17 0
      src/main/java/io/renren/common/validator/group/AddGroup.java
  43. 17 0
      src/main/java/io/renren/common/validator/group/AliyunGroup.java
  44. 21 0
      src/main/java/io/renren/common/validator/group/Group.java
  45. 17 0
      src/main/java/io/renren/common/validator/group/QcloudGroup.java
  46. 17 0
      src/main/java/io/renren/common/validator/group/QiniuGroup.java
  47. 19 0
      src/main/java/io/renren/common/validator/group/UpdateGroup.java
  48. 554 0
      src/main/java/io/renren/common/xss/HTMLFilter.java
  49. 50 0
      src/main/java/io/renren/common/xss/SQLFilter.java
  50. 37 0
      src/main/java/io/renren/common/xss/XssFilter.java
  51. 147 0
      src/main/java/io/renren/common/xss/XssHttpServletRequestWrapper.java
  52. 26 0
      src/main/java/io/renren/config/CorsConfig.java
  53. 49 0
      src/main/java/io/renren/config/FilterConfig.java
  54. 39 0
      src/main/java/io/renren/config/KaptchaConfig.java
  55. 37 0
      src/main/java/io/renren/config/MybatisPlusConfig.java
  56. 63 0
      src/main/java/io/renren/config/RedisConfig.java
  57. 93 0
      src/main/java/io/renren/config/ShiroConfig.java
  58. 61 0
      src/main/java/io/renren/config/SwaggerConfig.java
  59. 41 0
      src/main/java/io/renren/config/TomcatConfig.java
  60. 22 0
      src/main/java/io/renren/modules/app/annotation/Login.java
  61. 25 0
      src/main/java/io/renren/modules/app/annotation/LoginUser.java
  62. 51 0
      src/main/java/io/renren/modules/app/config/WebMvcConfig.java
  63. 64 0
      src/main/java/io/renren/modules/app/controller/AppLoginController.java
  64. 55 0
      src/main/java/io/renren/modules/app/controller/AppRegisterController.java
  65. 53 0
      src/main/java/io/renren/modules/app/controller/AppTestController.java
  66. 23 0
      src/main/java/io/renren/modules/app/dao/UserDao.java
  67. 54 0
      src/main/java/io/renren/modules/app/entity/UserEntity.java
  68. 33 0
      src/main/java/io/renren/modules/app/form/LoginForm.java
  69. 33 0
      src/main/java/io/renren/modules/app/form/RegisterForm.java
  70. 72 0
      src/main/java/io/renren/modules/app/interceptor/AuthorizationInterceptor.java
  71. 53 0
      src/main/java/io/renren/modules/app/resolver/LoginUserHandlerMethodArgumentResolver.java
  72. 31 0
      src/main/java/io/renren/modules/app/service/UserService.java
  73. 44 0
      src/main/java/io/renren/modules/app/service/impl/UserServiceImpl.java
  74. 95 0
      src/main/java/io/renren/modules/app/utils/JwtUtils.java
  75. 90 0
      src/main/java/io/renren/modules/aspen/controller/TAlarmstatisticsDayController.java
  76. 17 0
      src/main/java/io/renren/modules/aspen/dao/TAlarmstatisticsDayDao.java
  77. 80 0
      src/main/java/io/renren/modules/aspen/entity/TAlarmstatisticsDayEntity.java
  78. 20 0
      src/main/java/io/renren/modules/aspen/service/TAlarmstatisticsDayService.java
  79. 29 0
      src/main/java/io/renren/modules/aspen/service/impl/TAlarmstatisticsDayServiceImpl.java
  80. 54 0
      src/main/java/io/renren/modules/common/AspenController.java
  81. 62 0
      src/main/java/io/renren/modules/oss/cloud/AliyunCloudStorageService.java
  82. 94 0
      src/main/java/io/renren/modules/oss/cloud/CloudStorageConfig.java
  83. 78 0
      src/main/java/io/renren/modules/oss/cloud/CloudStorageService.java
  84. 44 0
      src/main/java/io/renren/modules/oss/cloud/OSSFactory.java
  85. 88 0
      src/main/java/io/renren/modules/oss/cloud/QcloudCloudStorageService.java
  86. 77 0
      src/main/java/io/renren/modules/oss/cloud/QiniuCloudStorageService.java
  87. 135 0
      src/main/java/io/renren/modules/oss/controller/SysOssController.java
  88. 23 0
      src/main/java/io/renren/modules/oss/dao/SysOssDao.java
  89. 39 0
      src/main/java/io/renren/modules/oss/entity/SysOssEntity.java
  90. 25 0
      src/main/java/io/renren/modules/oss/service/SysOssService.java
  91. 35 0
      src/main/java/io/renren/modules/oss/service/impl/SysOssServiceImpl.java
  92. 31 0
      src/main/java/io/renren/modules/sys/controller/AbstractController.java
  93. 22 0
      src/main/java/io/renren/modules/sys/controller/GetPwdController.java
  94. 98 0
      src/main/java/io/renren/modules/sys/controller/SysConfigController.java
  95. 145 0
      src/main/java/io/renren/modules/sys/controller/SysDeptController.java
  96. 98 0
      src/main/java/io/renren/modules/sys/controller/SysDictController.java
  97. 47 0
      src/main/java/io/renren/modules/sys/controller/SysLogController.java
  98. 120 0
      src/main/java/io/renren/modules/sys/controller/SysLoginController.java
  99. 198 0
      src/main/java/io/renren/modules/sys/controller/SysMenuController.java
  100. 168 0
      src/main/java/io/renren/modules/sys/controller/SysPlantController.java

+ 3 - 0
.gitignore

@@ -0,0 +1,3 @@
+/.idea/
+/db/
+/target/classes/

+ 7 - 0
Dockerfile

@@ -0,0 +1,7 @@
+FROM java:8
+EXPOSE 8080
+
+VOLUME /tmp
+ADD renren-fast.jar  /app.jar
+RUN bash -c 'touch /app.jar'
+ENTRYPOINT ["java","-jar","/app.jar"]

+ 191 - 0
LICENSE

@@ -0,0 +1,191 @@
+Apache License
+Version 2.0, January 2004
+http://www.apache.org/licenses/
+
+TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+1. Definitions.
+
+"License" shall mean the terms and conditions for use, reproduction, and
+distribution as defined by Sections 1 through 9 of this document.
+
+"Licensor" shall mean the copyright owner or entity authorized by the copyright
+owner that is granting the License.
+
+"Legal Entity" shall mean the union of the acting entity and all other entities
+that control, are controlled by, or are under common control with that entity.
+For the purposes of this definition, "control" means (i) the power, direct or
+indirect, to cause the direction or management of such entity, whether by
+contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the
+outstanding shares, or (iii) beneficial ownership of such entity.
+
+"You" (or "Your") shall mean an individual or Legal Entity exercising
+permissions granted by this License.
+
+"Source" form shall mean the preferred form for making modifications, including
+but not limited to software source code, documentation source, and configuration
+files.
+
+"Object" form shall mean any form resulting from mechanical transformation or
+translation of a Source form, including but not limited to compiled object code,
+generated documentation, and conversions to other media types.
+
+"Work" shall mean the work of authorship, whether in Source or Object form, made
+available under the License, as indicated by a copyright notice that is included
+in or attached to the work (an example is provided in the Appendix below).
+
+"Derivative Works" shall mean any work, whether in Source or Object form, that
+is based on (or derived from) the Work and for which the editorial revisions,
+annotations, elaborations, or other modifications represent, as a whole, an
+original work of authorship. For the purposes of this License, Derivative Works
+shall not include works that remain separable from, or merely link (or bind by
+name) to the interfaces of, the Work and Derivative Works thereof.
+
+"Contribution" shall mean any work of authorship, including the original version
+of the Work and any modifications or additions to that Work or Derivative Works
+thereof, that is intentionally submitted to Licensor for inclusion in the Work
+by the copyright owner or by an individual or Legal Entity authorized to submit
+on behalf of the copyright owner. For the purposes of this definition,
+"submitted" means any form of electronic, verbal, or written communication sent
+to the Licensor or its representatives, including but not limited to
+communication on electronic mailing lists, source code control systems, and
+issue tracking systems that are managed by, or on behalf of, the Licensor for
+the purpose of discussing and improving the Work, but excluding communication
+that is conspicuously marked or otherwise designated in writing by the copyright
+owner as "Not a Contribution."
+
+"Contributor" shall mean Licensor and any individual or Legal Entity on behalf
+of whom a Contribution has been received by Licensor and subsequently
+incorporated within the Work.
+
+2. Grant of Copyright License.
+
+Subject to the terms and conditions of this License, each Contributor hereby
+grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free,
+irrevocable copyright license to reproduce, prepare Derivative Works of,
+publicly display, publicly perform, sublicense, and distribute the Work and such
+Derivative Works in Source or Object form.
+
+3. Grant of Patent License.
+
+Subject to the terms and conditions of this License, each Contributor hereby
+grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free,
+irrevocable (except as stated in this section) patent license to make, have
+made, use, offer to sell, sell, import, and otherwise transfer the Work, where
+such license applies only to those patent claims licensable by such Contributor
+that are necessarily infringed by their Contribution(s) alone or by combination
+of their Contribution(s) with the Work to which such Contribution(s) was
+submitted. If You institute patent litigation against any entity (including a
+cross-claim or counterclaim in a lawsuit) alleging that the Work or a
+Contribution incorporated within the Work constitutes direct or contributory
+patent infringement, then any patent licenses granted to You under this License
+for that Work shall terminate as of the date such litigation is filed.
+
+4. Redistribution.
+
+You may reproduce and distribute copies of the Work or Derivative Works thereof
+in any medium, with or without modifications, and in Source or Object form,
+provided that You meet the following conditions:
+
+You must give any other recipients of the Work or Derivative Works a copy of
+this License; and
+You must cause any modified files to carry prominent notices stating that You
+changed the files; and
+You must retain, in the Source form of any Derivative Works that You distribute,
+all copyright, patent, trademark, and attribution notices from the Source form
+of the Work, excluding those notices that do not pertain to any part of the
+Derivative Works; and
+If the Work includes a "NOTICE" text file as part of its distribution, then any
+Derivative Works that You distribute must include a readable copy of the
+attribution notices contained within such NOTICE file, excluding those notices
+that do not pertain to any part of the Derivative Works, in at least one of the
+following places: within a NOTICE text file distributed as part of the
+Derivative Works; within the Source form or documentation, if provided along
+with the Derivative Works; or, within a display generated by the Derivative
+Works, if and wherever such third-party notices normally appear. The contents of
+the NOTICE file are for informational purposes only and do not modify the
+License. You may add Your own attribution notices within Derivative Works that
+You distribute, alongside or as an addendum to the NOTICE text from the Work,
+provided that such additional attribution notices cannot be construed as
+modifying the License.
+You may add Your own copyright statement to Your modifications and may provide
+additional or different license terms and conditions for use, reproduction, or
+distribution of Your modifications, or for any such Derivative Works as a whole,
+provided Your use, reproduction, and distribution of the Work otherwise complies
+with the conditions stated in this License.
+
+5. Submission of Contributions.
+
+Unless You explicitly state otherwise, any Contribution intentionally submitted
+for inclusion in the Work by You to the Licensor shall be under the terms and
+conditions of this License, without any additional terms or conditions.
+Notwithstanding the above, nothing herein shall supersede or modify the terms of
+any separate license agreement you may have executed with Licensor regarding
+such Contributions.
+
+6. Trademarks.
+
+This License does not grant permission to use the trade names, trademarks,
+service marks, or product names of the Licensor, except as required for
+reasonable and customary use in describing the origin of the Work and
+reproducing the content of the NOTICE file.
+
+7. Disclaimer of Warranty.
+
+Unless required by applicable law or agreed to in writing, Licensor provides the
+Work (and each Contributor provides its Contributions) on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied,
+including, without limitation, any warranties or conditions of TITLE,
+NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are
+solely responsible for determining the appropriateness of using or
+redistributing the Work and assume any risks associated with Your exercise of
+permissions under this License.
+
+8. Limitation of Liability.
+
+In no event and under no legal theory, whether in tort (including negligence),
+contract, or otherwise, unless required by applicable law (such as deliberate
+and grossly negligent acts) or agreed to in writing, shall any Contributor be
+liable to You for damages, including any direct, indirect, special, incidental,
+or consequential damages of any character arising as a result of this License or
+out of the use or inability to use the Work (including but not limited to
+damages for loss of goodwill, work stoppage, computer failure or malfunction, or
+any and all other commercial damages or losses), even if such Contributor has
+been advised of the possibility of such damages.
+
+9. Accepting Warranty or Additional Liability.
+
+While redistributing the Work or Derivative Works thereof, You may choose to
+offer, and charge a fee for, acceptance of support, warranty, indemnity, or
+other liability obligations and/or rights consistent with this License. However,
+in accepting such obligations, You may act only on Your own behalf and on Your
+sole responsibility, not on behalf of any other Contributor, and only if You
+agree to indemnify, defend, and hold each Contributor harmless for any liability
+incurred by, or claims asserted against, such Contributor by reason of your
+accepting any such warranty or additional liability.
+
+END OF TERMS AND CONDITIONS
+
+APPENDIX: How to apply the Apache License to your work
+
+To apply the Apache License to your work, attach the following boilerplate
+notice, with the fields enclosed by brackets "{}" replaced with your own
+identifying information. (Don't include the brackets!) The text should be
+enclosed in the appropriate comment syntax for the file format. We also
+recommend that a file or class name and description of purpose be included on
+the same "printed page" as the copyright notice for easier identification within
+third-party archives.
+
+   Copyright 2019 人人开源
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+     http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.

+ 116 - 0
README.md

@@ -0,0 +1,116 @@
+**项目说明** 
+- renren-fast是一个轻量级的,前后端分离的Java快速开发平台,能快速开发项目并交付【接私活利器】
+- 支持MySQL、Oracle、SQL Server、PostgreSQL等主流数据库
+- 前端地址:https://gitee.com/renrenio/renren-fast-vue
+- 代码生成器:https://gitee.com/renrenio/renren-generator
+
+<br>
+ 
+
+**具有如下特点** 
+- 友好的代码结构及注释,便于阅读及二次开发
+- 实现前后端分离,通过token进行数据交互,前端再也不用关注后端技术
+- 灵活的权限控制,可控制到页面或按钮,满足绝大部分的权限需求
+- 页面交互使用Vue2.x,极大的提高了开发效率
+- 完善的代码生成机制,可在线生成entity、xml、dao、service、vue、sql代码,减少70%以上的开发任务
+- 引入quartz定时任务,可动态完成任务的添加、修改、删除、暂停、恢复及日志查看等功能
+- 引入API模板,根据token作为登录令牌,极大的方便了APP接口开发
+- 引入Hibernate Validator校验框架,轻松实现后端校验
+- 引入云存储服务,已支持:七牛云、阿里云、腾讯云等
+- 引入swagger文档支持,方便编写API接口文档
+<br> 
+
+**项目结构** 
+```
+renren-fast
+├─db  项目SQL语句
+│
+├─common 公共模块
+│  ├─aspect 系统日志
+│  ├─exception 异常处理
+│  ├─validator 后台校验
+│  └─xss XSS过滤
+│ 
+├─config 配置信息
+│ 
+├─modules 功能模块
+│  ├─app API接口模块(APP调用)
+│  ├─job 定时任务模块
+│  ├─oss 文件服务模块
+│  └─sys 权限模块
+│ 
+├─RenrenApplication 项目启动类
+│  
+├──resources 
+│  ├─mapper SQL对应的XML文件
+│  └─static 静态资源
+
+```
+<br> 
+
+**如何交流、反馈、参与贡献?** 
+- 开发文档:https://www.renren.io/guide
+- Git仓库:https://gitee.com/renrenio/renren-fast
+- [人人开源社区](https://www.renren.io/community):https://www.renren.io/community
+- 官方QQ群:324780204、145799952
+- 技术讨论、二次开发等咨询、问题和建议,请移步到人人开源社区,我会在第一时间进行解答和回复!
+- 如需关注项目最新动态,请Watch、Star项目,同时也是对项目最好的支持
+- 微信扫码并关注【人人开源】,获得项目最新动态及更新提醒
+
+<br>
+
+![输入图片说明](https://images.gitee.com/uploads/images/2019/0307/090140_260d672d_63154.jpeg "在这里输入图片标题")
+
+<br> 
+
+
+**技术选型:** 
+- 核心框架:Spring Boot 2.1
+- 安全框架:Apache Shiro 1.4
+- 视图框架:Spring MVC 5.0
+- 持久层框架:MyBatis 3.3
+- 定时器:Quartz 2.3
+- 数据库连接池:Druid 1.0
+- 日志管理:SLF4J 1.7、Log4j
+- 页面交互:Vue2.x 
+<br> 
+
+
+ **后端部署**
+- 通过git下载源码
+- idea、eclipse需安装lombok插件,不然会提示找不到entity的get set方法
+- 创建数据库renren_fast,数据库编码为UTF-8
+- 执行db/mysql.sql文件,初始化数据
+- 修改application-dev.yml,更新MySQL账号和密码
+- Eclipse、IDEA运行RenrenApplication.java,则可启动项目
+- Swagger文档路径:http://localhost:8080/renren-fast/swagger/index.html
+- Swagger注解路径:http://localhost:8080/renren-fast/swagger-ui.html
+
+<br> 
+
+ **前端部署**
+ - 本项目是前后端分离的,还需要部署前端,才能运行起来
+ - 前端下载地址:https://gitee.com/renrenio/renren-fast-vue
+ - 前端部署文档:https://gitee.com/renrenio/renren-fast-vue/wikis/Home
+ - 前端部署完毕,就可以访问项目了,账号:admin,密码:admin
+ 
+ <br>
+
+ **项目演示**
+- 演示地址:http://demo.open.renren.io/renren-fast
+- 账号密码:admin/admin
+<br> 
+
+**接口文档效果图:**
+![输入图片说明](https://images.gitee.com/uploads/images/2018/0728/145341_73ba6f75_63154.jpeg "在这里输入图片标题")
+
+<br> <br> <br> 
+
+
+**效果图:**
+![输入图片说明](https://gitee.com/uploads/images/2018/0505/173115_d3c045ef_63154.jpeg "在这里输入图片标题")
+![输入图片说明](https://gitee.com/uploads/images/2018/0624/225728_b06f72b3_63154.jpeg "在这里输入图片标题")
+![输入图片说明](https://gitee.com/uploads/images/2018/0505/173140_79928d91_63154.jpeg "在这里输入图片标题")
+![输入图片说明](https://gitee.com/uploads/images/2018/0505/173151_12d065db_63154.jpeg "在这里输入图片标题")
+
+<br>

+ 8 - 0
docker-compose.yml

@@ -0,0 +1,8 @@
+version: '2'
+services:
+  renren-fast:
+    image: renren/fast
+    ports:
+      - "8080:8080"
+    environment:
+      - spring.profiles.active=dev

+ 441 - 0
pom.xml

@@ -0,0 +1,441 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+    <groupId>io.renren</groupId>
+    <artifactId>cpms-aspen</artifactId>
+    <version>1.0.1</version>
+    <packaging>jar</packaging>
+    <description>cpms-aspen</description>
+
+    <parent>
+        <groupId>org.springframework.boot</groupId>
+        <artifactId>spring-boot-starter-parent</artifactId>
+        <version>2.2.4.RELEASE</version>
+    </parent>
+
+    <properties>
+        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
+        <java.version>1.8</java.version>
+        <mybatisplus.version>3.3.1</mybatisplus.version>
+        <mysql.version>8.0.17</mysql.version>
+        <!--		<mysql.version>5.1.35</mysql.version>-->
+        <mssql.version>4.0</mssql.version>
+        <oracle.version>11.2.0.3</oracle.version>
+        <druid.version>1.1.13</druid.version>
+        <quartz.version>2.3.0</quartz.version>
+        <commons.lang.version>2.6</commons.lang.version>
+        <commons.fileupload.version>1.2.2</commons.fileupload.version>
+        <commons.io.version>2.5</commons.io.version>
+        <commons.codec.version>1.10</commons.codec.version>
+        <commons.configuration.version>1.10</commons.configuration.version>
+        <shiro.version>1.4.0</shiro.version>
+        <jwt.version>0.7.0</jwt.version>
+        <kaptcha.version>0.0.9</kaptcha.version>
+        <qiniu.version>7.2.23</qiniu.version>
+        <aliyun.oss.version>2.8.3</aliyun.oss.version>
+        <qcloud.cos.version>4.4</qcloud.cos.version>
+        <swagger.version>2.7.0</swagger.version>
+        <joda.time.version>2.9.9</joda.time.version>
+        <gson.version>2.8.5</gson.version>
+        <fastjson.version>1.2.60</fastjson.version>
+        <hutool.version>4.1.1</hutool.version>
+        <lombok.version>1.18.4</lombok.version>
+        <jxls.version>2.4.2</jxls.version>
+        <jxls-poi.version>1.0.13</jxls-poi.version>
+        <jxls-reader.version>2.0.3</jxls-reader.version>
+
+        <!--wagon plugin 配置-->
+        <service-path>/work/renren</service-path>
+        <pack-name>${project.artifactId}-${project.version}.jar</pack-name>
+        <remote-addr>192.168.1.10:22</remote-addr>
+        <remote-username>root</remote-username>
+        <remote-passwd>123456</remote-passwd>
+    </properties>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-test</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-web</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-aop</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework</groupId>
+            <artifactId>spring-context-support</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-data-redis</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-configuration-processor</artifactId>
+            <optional>true</optional>
+        </dependency>
+        <!--<dependency>-->
+        <!--<groupId>org.springframework.boot</groupId>-->
+        <!--<artifactId>spring-boot-devtools</artifactId>-->
+        <!--<optional>true</optional>-->
+        <!--</dependency>-->
+        <dependency>
+            <groupId>com.baomidou</groupId>
+            <artifactId>mybatis-plus-boot-starter</artifactId>
+            <version>${mybatisplus.version}</version>
+            <exclusions>
+                <exclusion>
+                    <groupId>com.baomidou</groupId>
+                    <artifactId>mybatis-plus-generator</artifactId>
+                </exclusion>
+            </exclusions>
+        </dependency>
+        <dependency>
+            <groupId>mysql</groupId>
+            <artifactId>mysql-connector-java</artifactId>
+            <version>${mysql.version}</version>
+        </dependency>
+        <!--oracle驱动-->
+        <dependency>
+            <groupId>com.oracle</groupId>
+            <artifactId>ojdbc6</artifactId>
+            <version>${oracle.version}</version>
+        </dependency>
+        <!--mssql驱动-->
+        <dependency>
+            <groupId>com.microsoft.sqlserver</groupId>
+            <artifactId>sqljdbc4</artifactId>
+            <version>${mssql.version}</version>
+        </dependency>
+        <!--postgresql驱动-->
+        <dependency>
+            <groupId>org.postgresql</groupId>
+            <artifactId>postgresql</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>com.alibaba</groupId>
+            <artifactId>druid-spring-boot-starter</artifactId>
+            <version>${druid.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.quartz-scheduler</groupId>
+            <artifactId>quartz</artifactId>
+            <version>${quartz.version}</version>
+            <exclusions>
+                <exclusion>
+                    <groupId>com.mchange</groupId>
+                    <artifactId>c3p0</artifactId>
+                </exclusion>
+            </exclusions>
+        </dependency>
+        <dependency>
+            <groupId>commons-lang</groupId>
+            <artifactId>commons-lang</artifactId>
+            <version>${commons.lang.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>commons-fileupload</groupId>
+            <artifactId>commons-fileupload</artifactId>
+            <version>${commons.fileupload.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>commons-io</groupId>
+            <artifactId>commons-io</artifactId>
+            <version>${commons.io.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>commons-codec</groupId>
+            <artifactId>commons-codec</artifactId>
+            <version>${commons.codec.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>commons-configuration</groupId>
+            <artifactId>commons-configuration</artifactId>
+            <version>${commons.configuration.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.shiro</groupId>
+            <artifactId>shiro-core</artifactId>
+            <version>${shiro.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.shiro</groupId>
+            <artifactId>shiro-spring</artifactId>
+            <version>${shiro.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>io.jsonwebtoken</groupId>
+            <artifactId>jjwt</artifactId>
+            <version>${jwt.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>com.github.axet</groupId>
+            <artifactId>kaptcha</artifactId>
+            <version>${kaptcha.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>io.springfox</groupId>
+            <artifactId>springfox-swagger2</artifactId>
+            <version>${swagger.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>io.springfox</groupId>
+            <artifactId>springfox-swagger-ui</artifactId>
+            <version>${swagger.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>com.qiniu</groupId>
+            <artifactId>qiniu-java-sdk</artifactId>
+            <version>${qiniu.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>com.aliyun.oss</groupId>
+            <artifactId>aliyun-sdk-oss</artifactId>
+            <version>${aliyun.oss.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>com.qcloud</groupId>
+            <artifactId>cos_api</artifactId>
+            <version>${qcloud.cos.version}</version>
+            <exclusions>
+                <exclusion>
+                    <groupId>org.slf4j</groupId>
+                    <artifactId>slf4j-log4j12</artifactId>
+                </exclusion>
+            </exclusions>
+        </dependency>
+        <dependency>
+            <groupId>joda-time</groupId>
+            <artifactId>joda-time</artifactId>
+            <version>${joda.time.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>com.google.code.gson</groupId>
+            <artifactId>gson</artifactId>
+            <version>${gson.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>com.alibaba</groupId>
+            <artifactId>fastjson</artifactId>
+            <version>${fastjson.version}</version>
+        </dependency>
+
+        <dependency>
+            <groupId>cn.hutool</groupId>
+            <artifactId>hutool-all</artifactId>
+            <version>${hutool.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.projectlombok</groupId>
+            <artifactId>lombok</artifactId>
+            <version>${lombok.version}</version>
+        </dependency>
+
+        <dependency>
+            <groupId>org.apache.poi</groupId>
+            <artifactId>poi</artifactId>
+            <version>3.16</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.poi</groupId>
+            <artifactId>poi-ooxml</artifactId>
+            <version>3.16</version>
+        </dependency>
+
+        <dependency>
+            <groupId>org.jxls</groupId>
+            <artifactId>jxls</artifactId>
+            <version>${jxls.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.jxls</groupId>
+            <artifactId>jxls-poi</artifactId>
+            <version>${jxls-poi.version}</version>
+        </dependency>
+
+        <dependency>
+            <groupId>com.github.ulisesbocchio</groupId>
+            <artifactId>jasypt-spring-boot-starter</artifactId>
+            <version>1.16</version>
+        </dependency>
+
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-mail</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>org.activiti</groupId>
+            <artifactId>activiti-engine</artifactId>
+            <version>6.0.0</version>
+            <exclusions>
+                <exclusion>
+                    <groupId>org.mybatis</groupId>
+                    <artifactId>mybatis</artifactId>
+                </exclusion>
+            </exclusions>
+        </dependency>
+        <dependency>
+            <groupId>org.activiti</groupId>
+            <artifactId>activiti-spring</artifactId>
+            <version>6.0.0</version>
+        </dependency>
+
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-web-services</artifactId>
+        </dependency>
+
+        <!--framework-->
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-freemarker</artifactId>
+            <version>2.1.2.RELEASE</version>
+        </dependency>
+        <dependency>
+            <groupId>com.itextpdf</groupId>
+            <artifactId>itextpdf</artifactId>
+            <version>5.4.2</version>
+        </dependency>
+        <dependency>
+            <groupId>com.itextpdf.tool</groupId>
+            <artifactId>xmlworker</artifactId>
+            <version>5.4.1</version>
+        </dependency>
+        <dependency>
+            <groupId>com.itextpdf</groupId>
+            <artifactId>itext-asian</artifactId>
+            <version>5.2.0</version>
+        </dependency>
+        <dependency>
+            <groupId>org.xhtmlrenderer</groupId>
+            <artifactId>flying-saucer-pdf</artifactId>
+            <version>9.0.3</version>
+        </dependency>
+
+        <!--jpinyin-->
+        <dependency>
+            <groupId>com.github.stuxuhai</groupId>
+            <artifactId>jpinyin</artifactId>
+            <version>1.1.8</version>
+        </dependency>
+    </dependencies>
+
+
+
+    <build>
+        <finalName>${project.artifactId}</finalName>
+        <extensions>
+            <extension>
+                <groupId>org.apache.maven.wagon</groupId>
+                <artifactId>wagon-ssh</artifactId>
+                <version>2.8</version>
+            </extension>
+        </extensions>
+        <plugins>
+            <plugin>
+                <groupId>org.springframework.boot</groupId>
+                <artifactId>spring-boot-maven-plugin</artifactId>
+                <configuration>
+                    <fork>true</fork>
+                </configuration>
+            </plugin>
+            <!-- resource插件 -->
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-resources-plugin</artifactId>
+                <version>2.6</version>
+                <configuration>
+                    <encoding>UTF-8</encoding>
+                </configuration>
+            </plugin>
+            <!-- 跳过单元测试 -->
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-surefire-plugin</artifactId>
+                <configuration>
+                    <skipTests>true</skipTests>
+                </configuration>
+            </plugin>
+            <plugin>
+                <groupId>org.codehaus.mojo</groupId>
+                <artifactId>wagon-maven-plugin</artifactId>
+                <version>1.0</version>
+                <configuration>
+                    <fromFile>target/${pack-name}</fromFile>
+                    <url><![CDATA[scp://${remote-username}:${remote-passwd}@${remote-addr}${service-path}]]></url>
+                    <commands>
+                        <!-- Kill Old Process -->
+                        <command>kill -9 `ps -ef |grep ${project.artifactId}.jar|grep -v "grep" |awk '{print $2}'`
+                        </command>
+                        <!-- Restart jar package,write result into renren.log -->
+                        <command>
+                            <![CDATA[nohup java -jar ${service-path}/${pack-name} --spring.profiles.active=test > ${service-path}/renren.log 2>&1 & ]]></command>
+                        <command><![CDATA[netstat -nptl]]></command>
+                        <command><![CDATA[ps -ef | grep java | grep -v grep]]></command>
+                    </commands>
+                    <!-- 运行命令 mvn clean package wagon:upload-single wagon:sshexec-->
+                    <displayCommandOutputs>true</displayCommandOutputs>
+                </configuration>
+            </plugin>
+
+            <plugin>
+                <groupId>com.spotify</groupId>
+                <artifactId>docker-maven-plugin</artifactId>
+                <version>0.4.14</version>
+                <!--<executions>-->
+                <!--<execution>-->
+                <!--<phase>package</phase>-->
+                <!--<goals>-->
+                <!--<goal>build</goal>-->
+                <!--</goals>-->
+                <!--</execution>-->
+                <!--</executions>-->
+                <configuration>
+                    <imageName>renren/fast</imageName>
+                    <dockerDirectory>${project.basedir}</dockerDirectory>
+                    <resources>
+                        <resource>
+                            <targetPath>/</targetPath>
+                            <directory>${project.build.directory}</directory>
+                            <include>${project.build.finalName}.jar</include>
+                        </resource>
+                    </resources>
+                </configuration>
+                <!-- 运行命令 mvn clean package docker:build 打包并生成docker镜像 -->
+            </plugin>
+        </plugins>
+    </build>
+
+    <repositories>
+        <repository>
+            <id>public</id>
+            <name>aliyun nexus</name>
+            <url>http://maven.aliyun.com/nexus/content/groups/public/</url>
+            <releases>
+                <enabled>true</enabled>
+            </releases>
+        </repository>
+    </repositories>
+    <pluginRepositories>
+        <pluginRepository>
+            <id>public</id>
+            <name>aliyun nexus</name>
+            <url>http://maven.aliyun.com/nexus/content/groups/public/</url>
+            <releases>
+                <enabled>true</enabled>
+            </releases>
+            <snapshots>
+                <enabled>false</enabled>
+            </snapshots>
+        </pluginRepository>
+    </pluginRepositories>
+
+</project>

+ 25 - 0
src/main/java/io/renren/RenrenApplication.java

@@ -0,0 +1,25 @@
+/**
+ * Copyright (c) 2016-2019 人人开源 All rights reserved.
+ * <p>
+ * https://www.renren.io
+ * <p>
+ * 版权所有,侵权必究!
+ */
+
+package io.renren;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
+import org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration;
+import org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration;
+
+
+@SpringBootApplication( exclude={SecurityAutoConfiguration.class,DataSourceAutoConfiguration.class})   // springboot2.0集成activiti6要加后面这个,因为6比较老版本
+public class RenrenApplication {
+
+    public static void main(String[] args) {
+        SpringApplication.run(RenrenApplication.class, args);
+    }
+
+}

+ 37 - 0
src/main/java/io/renren/common/annotation/DataFilter.java

@@ -0,0 +1,37 @@
+/**
+ * Copyright (c) 2016-2019 人人开源 All rights reserved.
+ * <p>
+ * https://www.renren.io
+ * <p>
+ * 版权所有,侵权必究!
+ */
+
+package io.renren.common.annotation;
+
+import java.lang.annotation.*;
+
+/**
+ * 数据过滤
+ *
+ * @author Mark 735032128@qq.com
+ */
+@Target(ElementType.METHOD)
+@Retention(RetentionPolicy.RUNTIME)
+@Documented
+public @interface DataFilter {
+    /**  表的别名 */
+    String tableAlias() default "";
+
+    /**  true:没有本部门数据权限,也能查询本人数据 */
+    boolean user() default true;
+
+    /**  true:拥有子部门数据权限 */
+    boolean subDept() default false;
+
+    /**  部门ID */
+    String deptId() default "dept_id";
+
+    /**  用户ID */
+    String userId() default "user_id";
+}
+

+ 40 - 0
src/main/java/io/renren/common/annotation/PlantDataFilter.java

@@ -0,0 +1,40 @@
+/**
+ * Copyright (c) 2016-2019 人人开源 All rights reserved.
+ * <p>
+ * https://www.renren.io
+ * <p>
+ * 版权所有,侵权必究!
+ */
+
+package io.renren.common.annotation;
+
+import java.lang.annotation.*;
+
+/**
+ * 数据过滤
+ *
+ * @author Mark 735032128@qq.com
+ */
+@Target(ElementType.METHOD)
+@Retention(RetentionPolicy.RUNTIME)
+@Documented
+public @interface PlantDataFilter {
+    /**  表的别名 */
+    String tableAlias() default "";
+
+    /**  true:没有本部门数据权限,也能查询本人数据 */
+    boolean user() default true;
+
+    /**  true:拥有子部门数据权限 */
+    boolean subDept() default false;
+
+    /**  部门ID */
+    String deptId() default "dept_id";
+
+    /**  部门ID */
+    String plantCode() default "plant_code";
+
+    /**  用户ID */
+    String userId() default "user_id";
+}
+

+ 28 - 0
src/main/java/io/renren/common/annotation/SysLog.java

@@ -0,0 +1,28 @@
+/**
+ * Copyright (c) 2016-2019 人人开源 All rights reserved.
+ * <p>
+ * https://www.renren.io
+ * <p>
+ * 版权所有,侵权必究!
+ */
+
+package io.renren.common.annotation;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * 系统日志注解
+ *
+ * @author Mark 735032128@qq.com
+ */
+@Target(ElementType.METHOD)
+@Retention(RetentionPolicy.RUNTIME)
+@Documented
+public @interface SysLog {
+
+    String value() default "";
+}

+ 123 - 0
src/main/java/io/renren/common/aspect/DataFilterAspect.java

@@ -0,0 +1,123 @@
+/**
+ * Copyright (c) 2016-2019 人人开源 All rights reserved.
+ * <p>
+ * https://www.renren.io
+ * <p>
+ * 版权所有,侵权必究!
+ */
+
+package io.renren.common.aspect;
+
+
+import io.renren.common.annotation.DataFilter;
+import io.renren.common.exception.RRException;
+import io.renren.common.utils.Constant;
+import io.renren.common.utils.ShiroUtils;
+import io.renren.modules.sys.entity.SysUserEntity;
+import io.renren.modules.sys.service.SysDeptService;
+import io.renren.modules.sys.service.SysRoleDeptService;
+import io.renren.modules.sys.service.SysUserRoleService;
+import org.apache.commons.lang.StringUtils;
+import org.aspectj.lang.JoinPoint;
+import org.aspectj.lang.annotation.Aspect;
+import org.aspectj.lang.annotation.Before;
+import org.aspectj.lang.annotation.Pointcut;
+import org.aspectj.lang.reflect.MethodSignature;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * 数据过滤,切面处理类
+ *
+ * @author Mark 735032128@qq.com
+ */
+@Aspect
+@Component
+public class DataFilterAspect {
+    @Autowired
+    private SysDeptService sysDeptService;
+    @Autowired
+    private SysUserRoleService sysUserRoleService;
+    @Autowired
+    private SysRoleDeptService sysRoleDeptService;
+
+    @Pointcut("@annotation(io.renren.common.annotation.DataFilter)")
+    public void dataFilterCut() {
+
+    }
+
+    @Before("dataFilterCut()")
+    public void dataFilter(JoinPoint point) throws Throwable {
+        Object params = point.getArgs()[0];
+        if (params != null && params instanceof Map) {
+            SysUserEntity user = ShiroUtils.getUserEntity();
+
+            //如果不是超级管理员,则进行数据过滤
+            if (user.getUserId() != Constant.SUPER_ADMIN) {
+                Map map = (Map) params;
+                map.put(Constant.SQL_FILTER, getSQLFilter(user, point));
+            }
+
+            return;
+        }
+
+        throw new RRException("数据权限接口,只能是Map类型参数,且不能为NULL");
+    }
+
+    /**
+     * 获取数据过滤的SQL
+     */
+    private String getSQLFilter(SysUserEntity user, JoinPoint point) {
+        MethodSignature signature = (MethodSignature) point.getSignature();
+        DataFilter dataFilter = signature.getMethod().getAnnotation(DataFilter.class);
+        //获取表的别名
+        String tableAlias = dataFilter.tableAlias();
+        if (StringUtils.isNotBlank(tableAlias)) {
+            tableAlias += ".";
+        }
+
+        //部门ID列表
+        Set<Long> deptIdList = new HashSet<>();
+
+        //用户角色对应的部门ID列表
+        List<Long> roleIdList = sysUserRoleService.queryRoleIdList(user.getUserId());
+        if (roleIdList.size() > 0) {
+            List<Long> userDeptIdList = sysRoleDeptService.queryDeptIdList(roleIdList.toArray(new Long[roleIdList.size()]));
+            deptIdList.addAll(userDeptIdList);
+        }
+
+        //用户子部门ID列表
+        if (dataFilter.subDept()) {
+            List<Long> subDeptIdList = sysDeptService.getSubDeptIdList(user.getDeptId());
+            deptIdList.addAll(subDeptIdList);
+        }
+
+        StringBuilder sqlFilter = new StringBuilder();
+        sqlFilter.append(" (");
+
+        if (deptIdList.size() > 0) {
+            sqlFilter.append(tableAlias).append(dataFilter.deptId()).append(" in(").append(StringUtils.join(deptIdList, ",")).append(")");
+        }
+
+        //没有本部门数据权限,也能查询本人数据
+        if (dataFilter.user()) {
+            if (deptIdList.size() > 0) {
+                sqlFilter.append(" or ");
+            }
+            sqlFilter.append(tableAlias).append(dataFilter.userId()).append("=").append(user.getUserId());
+        }
+
+        sqlFilter.append(")");
+
+        if (sqlFilter.toString().trim().equals("()")) {
+            return null;
+        }
+
+        return sqlFilter.toString();
+    }
+}

+ 126 - 0
src/main/java/io/renren/common/aspect/PlantDataFilterAspect.java

@@ -0,0 +1,126 @@
+/**
+ * Copyright (c) 2016-2019 人人开源 All rights reserved.
+ * <p>
+ * https://www.renren.io
+ * <p>
+ * 版权所有,侵权必究!
+ */
+
+package io.renren.common.aspect;
+
+
+import io.renren.common.annotation.DataFilter;
+import io.renren.common.annotation.PlantDataFilter;
+import io.renren.common.exception.RRException;
+import io.renren.common.utils.Constant;
+import io.renren.common.utils.ShiroUtils;
+import io.renren.modules.sys.entity.SysUserEntity;
+import io.renren.modules.sys.service.SysDeptService;
+import io.renren.modules.sys.service.SysRoleDeptService;
+import io.renren.modules.sys.service.SysUserPlantService;
+import io.renren.modules.sys.service.SysUserRoleService;
+import org.apache.commons.lang.StringUtils;
+import org.aspectj.lang.JoinPoint;
+import org.aspectj.lang.annotation.Aspect;
+import org.aspectj.lang.annotation.Before;
+import org.aspectj.lang.annotation.Pointcut;
+import org.aspectj.lang.reflect.MethodSignature;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * 数据过滤,切面处理类
+ *
+ * @author Mark 735032128@qq.com
+ */
+@Aspect
+@Component
+public class PlantDataFilterAspect {
+    @Autowired
+    private SysDeptService sysDeptService;
+    @Autowired
+    private SysUserPlantService sysUserPlantService;
+    @Autowired
+    private SysRoleDeptService sysRoleDeptService;
+
+    @Pointcut("@annotation(io.renren.common.annotation.PlantDataFilter)")
+    public void dataFilterCut() {
+
+    }
+
+    @Before("dataFilterCut()")
+    public void dataFilter(JoinPoint point) throws Throwable {
+        Object params = point.getArgs()[0];
+        if (params != null && params instanceof Map) {
+            SysUserEntity user = ShiroUtils.getUserEntity();
+
+            //如果不是超级管理员,则进行数据过滤
+            if (user.getUserId() != Constant.SUPER_ADMIN) {
+                Map map = (Map) params;
+                map.put(Constant.SQL_FILTER, getSQLFilter(user, point));
+            }
+
+            return;
+        }
+
+        throw new RRException("数据权限接口,只能是Map类型参数,且不能为NULL");
+    }
+
+    /**
+     * 获取数据过滤的SQL
+     */
+    private String getSQLFilter(SysUserEntity user, JoinPoint point) {
+        MethodSignature signature = (MethodSignature) point.getSignature();
+        PlantDataFilter dataFilter = signature.getMethod().getAnnotation(PlantDataFilter.class);
+        //获取表的别名
+        String tableAlias = dataFilter.tableAlias();
+        if (StringUtils.isNotBlank(tableAlias)) {
+            tableAlias += ".";
+        }
+
+        //装置ID名称列表
+        Set<String> plantNameList = new HashSet<>();
+
+        //用户角色对应的部门ID列表
+        List<String> plantList = sysUserPlantService.queryPlantNameList(user.getUserId());
+
+        //用户子部门ID列表
+//        if (dataFilter.subDept()) {
+//            List<Long> subDeptIdList = sysDeptService.getSubDeptIdList(user.getDeptId());
+//            plantNameList.addAll(subDeptIdList);
+//        }
+
+        StringBuilder sqlFilter = new StringBuilder();
+        sqlFilter.append(" (");
+
+        if (plantList.size() > 0) {
+            for (String s : plantList
+            ) {
+                s = "'" + s + "'";
+                plantNameList.add(s);
+            }
+            sqlFilter.append(tableAlias).append(dataFilter.plantCode()).append(" in(").append(StringUtils.join(plantNameList, ",")).append(")");
+        }
+
+        //没有本部门数据权限,也能查询本人数据
+        if (dataFilter.user()) {
+            if (plantNameList.size() > 0) {
+                sqlFilter.append(" or ");
+            }
+            sqlFilter.append(tableAlias).append(dataFilter.userId()).append("=").append(user.getUserId());
+        }
+
+        sqlFilter.append(")");
+
+        if (sqlFilter.toString().trim().equals("()")) {
+            return null;
+        }
+
+        return sqlFilter.toString();
+    }
+}

+ 46 - 0
src/main/java/io/renren/common/aspect/RedisAspect.java

@@ -0,0 +1,46 @@
+/**
+ * Copyright (c) 2016-2019 人人开源 All rights reserved.
+ * <p>
+ * https://www.renren.io
+ * <p>
+ * 版权所有,侵权必究!
+ */
+
+package io.renren.common.aspect;
+
+import io.renren.common.exception.RRException;
+import org.aspectj.lang.ProceedingJoinPoint;
+import org.aspectj.lang.annotation.Around;
+import org.aspectj.lang.annotation.Aspect;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.annotation.Configuration;
+
+/**
+ * Redis切面处理类
+ *
+ * @author Mark 735032128@qq.com
+ */
+@Aspect
+@Configuration
+public class RedisAspect {
+    private Logger logger = LoggerFactory.getLogger(getClass());
+    //是否开启redis缓存  true开启   false关闭
+    @Value("${spring.redis.open: false}")
+    private boolean open;
+
+    @Around("execution(* io.renren.common.utils.RedisUtils.*(..))")
+    public Object around(ProceedingJoinPoint point) throws Throwable {
+        Object result = null;
+        if (open) {
+            try {
+                result = point.proceed();
+            } catch (Exception e) {
+                logger.error("redis error", e);
+                throw new RRException("Redis服务异常");
+            }
+        }
+        return result;
+    }
+}

+ 101 - 0
src/main/java/io/renren/common/aspect/SysLogAspect.java

@@ -0,0 +1,101 @@
+/**
+ * Copyright (c) 2016-2019 人人开源 All rights reserved.
+ * <p>
+ * https://www.renren.io
+ * <p>
+ * 版权所有,侵权必究!
+ */
+
+package io.renren.common.aspect;
+
+import com.google.gson.Gson;
+import io.renren.common.annotation.SysLog;
+import io.renren.common.utils.HttpContextUtils;
+import io.renren.common.utils.IPUtils;
+import io.renren.modules.sys.entity.SysLogEntity;
+import io.renren.modules.sys.entity.SysUserEntity;
+import io.renren.modules.sys.service.SysLogService;
+import org.apache.shiro.SecurityUtils;
+import org.aspectj.lang.ProceedingJoinPoint;
+import org.aspectj.lang.annotation.Around;
+import org.aspectj.lang.annotation.Aspect;
+import org.aspectj.lang.annotation.Pointcut;
+import org.aspectj.lang.reflect.MethodSignature;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+import javax.servlet.http.HttpServletRequest;
+import java.lang.reflect.Method;
+import java.util.Date;
+
+
+/**
+ * 系统日志,切面处理类
+ *
+ * @author Mark 735032128@qq.com
+ */
+@Aspect
+@Component
+public class SysLogAspect {
+    @Autowired
+    private SysLogService sysLogService;
+
+    @Pointcut("@annotation(io.renren.common.annotation.SysLog)")
+    public void logPointCut() {
+
+    }
+
+    @Around("logPointCut()")
+    public Object around(ProceedingJoinPoint point) throws Throwable {
+        long beginTime = System.currentTimeMillis();
+        //执行方法
+        Object result = point.proceed();
+        //执行时长(毫秒)
+        long time = System.currentTimeMillis() - beginTime;
+
+        //保存日志
+        saveSysLog(point, time);
+
+        return result;
+    }
+
+    private void saveSysLog(ProceedingJoinPoint joinPoint, long time) {
+        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
+        Method method = signature.getMethod();
+
+        SysLogEntity sysLog = new SysLogEntity();
+        SysLog syslog = method.getAnnotation(SysLog.class);
+        if (syslog != null) {
+            //注解上的描述
+            sysLog.setOperation(syslog.value());
+        }
+
+        //请求的方法名
+        String className = joinPoint.getTarget().getClass().getName();
+        String methodName = signature.getName();
+        sysLog.setMethod(className + "." + methodName + "()");
+
+        //请求的参数
+        Object[] args = joinPoint.getArgs();
+        try {
+            String params = new Gson().toJson(args);
+            sysLog.setParams(params);
+        } catch (Exception e) {
+
+        }
+
+        //获取request
+        HttpServletRequest request = HttpContextUtils.getHttpServletRequest();
+        //设置IP地址
+        sysLog.setIp(IPUtils.getIpAddr(request));
+
+        //用户名
+        String username = ((SysUserEntity) SecurityUtils.getSubject().getPrincipal()).getUsername();
+        sysLog.setUsername(username);
+
+        sysLog.setTime(time);
+        sysLog.setCreateDate(new Date());
+        //保存系统日志
+        sysLogService.save(sysLog);
+    }
+}

+ 47 - 0
src/main/java/io/renren/common/constant/JxlsTemplateEnum.java

@@ -0,0 +1,47 @@
+package io.renren.common.constant;
+
+
+import io.renren.common.utils.export.JxlsTemplate;
+
+/**
+ * Created by xk on 2017/12/4 0004.
+ */
+public enum JxlsTemplateEnum implements JxlsTemplate {
+
+    DONE_TASK_LIST("/template/doneTaskTest.xlsx", "审批请单.xlsx"),
+    DEV_YLRQ_LIST("/template/ylrqExport.xlsx", "压力容器设备请单.xlsx"),
+    DEV_YLGD_LIST("/template/ylgdExport.xlsx", "压力管道设备请单.xlsx"),
+    DEV_DZSB_LIST("/template/dzsbExport.xlsx", "起重机械设备请单.xlsx"),
+    DEV_GL_LIST("/template/glExport.xlsx", "锅炉设备请单.xlsx"),
+    DEV_DT_LIST("/template/dtExport.xlsx", "电梯设备请单.xlsx"),
+    DEV_CC_LIST("/template/ccExport.xlsx", "叉车设备请单.xlsx"),
+    DEV_TANK_LIST("/template/tankExport.xlsx", "常压罐设备请单.xlsx"),
+    DEV_YLRQ_UPDATE("/template/ylrqInspectionInfo.xlsx", "压力容器检验信息更新清单.xlsx"),
+    DEV_YLGD_UPDATE("/template/ylgdInspectionInfo.xlsx", "压力管道检验信息更新清单.xlsx"),
+    DEV_DZSB_UPDATE("/template/dzsbInspectionInfo.xlsx", "起重机械检验信息更新清单.xlsx"),
+    DEV_GL_UPDATE("/template/glInspectionInfo.xlsx", "锅炉设备检验信息更新清单.xlsx"),
+    DEV_DT_UPDATE("/template/dtInspectionInfo.xlsx", "电梯设备检验信息更新清单.xlsx"),
+    DEV_CC_UPDATE("/template/ccInspectionInfo.xlsx", "叉车设备检验信息更新清单.xlsx");
+
+    private String path;
+    private String name;
+
+    JxlsTemplateEnum(String path, String name) {
+        this.path = path;
+        this.name = name;
+    }
+
+    @Override
+    public String getPath() {
+        return this.path;
+    }
+
+    @Override
+    public String getName() {
+        return this.name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+}

+ 27 - 0
src/main/java/io/renren/common/constant/JxlsTemplateFree.java

@@ -0,0 +1,27 @@
+package io.renren.common.constant;
+
+
+import io.renren.common.utils.export.JxlsTemplate;
+
+public class JxlsTemplateFree implements JxlsTemplate {
+    private String path;
+    private String name;
+
+    public void setPath(String path) {
+        this.path = path;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    @Override
+    public String getPath() {
+        return this.path;
+    }
+
+    @Override
+    public String getName() {
+        return this.name;
+    }
+}

+ 61 - 0
src/main/java/io/renren/common/exception/RRException.java

@@ -0,0 +1,61 @@
+/**
+ * Copyright (c) 2016-2019 人人开源 All rights reserved.
+ * <p>
+ * https://www.renren.io
+ * <p>
+ * 版权所有,侵权必究!
+ */
+
+package io.renren.common.exception;
+
+/**
+ * 自定义异常
+ *
+ * @author Mark 735032128@qq.com
+ */
+public class RRException extends RuntimeException {
+    private static final long serialVersionUID = 1L;
+
+    private String msg;
+    private int code = 500;
+
+    public RRException(String msg) {
+        super(msg);
+        this.msg = msg;
+    }
+
+    public RRException(String msg, Throwable e) {
+        super(msg, e);
+        this.msg = msg;
+    }
+
+    public RRException(String msg, int code) {
+        super(msg);
+        this.msg = msg;
+        this.code = code;
+    }
+
+    public RRException(String msg, int code, Throwable e) {
+        super(msg, e);
+        this.msg = msg;
+        this.code = code;
+    }
+
+    public String getMsg() {
+        return msg;
+    }
+
+    public void setMsg(String msg) {
+        this.msg = msg;
+    }
+
+    public int getCode() {
+        return code;
+    }
+
+    public void setCode(int code) {
+        this.code = code;
+    }
+
+
+}

+ 64 - 0
src/main/java/io/renren/common/exception/RRExceptionHandler.java

@@ -0,0 +1,64 @@
+/**
+ * Copyright (c) 2016-2019 人人开源 All rights reserved.
+ * <p>
+ * https://www.renren.io
+ * <p>
+ * 版权所有,侵权必究!
+ */
+
+package io.renren.common.exception;
+
+import io.renren.common.utils.R;
+import org.apache.shiro.authz.AuthorizationException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.dao.DuplicateKeyException;
+import org.springframework.web.bind.annotation.ExceptionHandler;
+import org.springframework.web.bind.annotation.RestControllerAdvice;
+import org.springframework.web.servlet.NoHandlerFoundException;
+
+/**
+ * 异常处理器
+ *
+ * @author Mark 735032128@qq.com
+ */
+@RestControllerAdvice
+public class RRExceptionHandler {
+    private Logger logger = LoggerFactory.getLogger(getClass());
+
+    /**
+     * 处理自定义异常
+     */
+    @ExceptionHandler(RRException.class)
+    public R handleRRException(RRException e) {
+        R r = new R();
+        r.put("code", e.getCode());
+        r.put("msg", e.getMessage());
+
+        return r;
+    }
+
+    @ExceptionHandler(NoHandlerFoundException.class)
+    public R handlerNoFoundException(Exception e) {
+        logger.error(e.getMessage(), e);
+        return R.error(404, "路径不存在,请检查路径是否正确");
+    }
+
+    @ExceptionHandler(DuplicateKeyException.class)
+    public R handleDuplicateKeyException(DuplicateKeyException e) {
+        logger.error(e.getMessage(), e);
+        return R.error("数据库中已存在该记录");
+    }
+
+    @ExceptionHandler(AuthorizationException.class)
+    public R handleAuthorizationException(AuthorizationException e) {
+        logger.error(e.getMessage(), e);
+        return R.error("没有权限,请联系管理员授权");
+    }
+
+    @ExceptionHandler(Exception.class)
+    public R handleException(Exception e) {
+        logger.error(e.getMessage(), e);
+        return R.error();
+    }
+}

+ 21 - 0
src/main/java/io/renren/common/utils/ConfigConstant.java

@@ -0,0 +1,21 @@
+/**
+ * Copyright (c) 2016-2019 人人开源 All rights reserved.
+ * <p>
+ * https://www.renren.io
+ * <p>
+ * 版权所有,侵权必究!
+ */
+
+package io.renren.common.utils;
+
+/**
+ * 系统参数相关Key
+ *
+ * @author Mark 735032128@qq.com
+ */
+public class ConfigConstant {
+    /**
+     * 云存储配置KEY
+     */
+    public final static String CLOUD_STORAGE_CONFIG_KEY = "CLOUD_STORAGE_CONFIG_KEY";
+}

+ 141 - 0
src/main/java/io/renren/common/utils/Constant.java

@@ -0,0 +1,141 @@
+/**
+ * Copyright (c) 2016-2019 人人开源 All rights reserved.
+ * <p>
+ * https://www.renren.io
+ * <p>
+ * 版权所有,侵权必究!
+ */
+
+package io.renren.common.utils;
+
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.stereotype.Component;
+
+/**
+ * 常量
+ *
+ * @author Mark 735032128@qq.com
+ */
+@Component
+public class Constant {
+
+    /** 超级管理员ID */
+    public static final int SUPER_ADMIN = 1;
+
+    /** 管理员ID */
+    public static final int FIRST_ADMIN = 2;
+
+    public static final int SEC_ADMIN = 3;
+
+    /** 数据权限过滤 */
+    public static final String SQL_FILTER = "sql_filter";
+    /**
+     * 当前页码
+     */
+    public static final String PAGE = "page";
+    /**
+     * 每页显示记录数
+     */
+    public static final String LIMIT = "limit";
+    /**
+     * 排序字段
+     */
+    public static final String ORDER_FIELD = "sidx";
+    /**
+     * 排序方式
+     */
+    public static final String ORDER = "order";
+    /**
+     *  升序
+     */
+    public static final String ASC = "asc";
+
+    /**
+     * 菜单类型
+     *
+     * @author liyang
+     * @email 735032128@qq.com
+     * @date 2016年11月15日 下午1:24:29
+     */
+    public enum MenuType {
+        /**
+         * 目录
+         */
+        CATALOG(0),
+        /**
+         * 菜单
+         */
+        MENU(1),
+        /**
+         * 按钮
+         */
+        BUTTON(2);
+
+        private int value;
+
+        MenuType(int value) {
+            this.value = value;
+        }
+
+        public int getValue() {
+            return value;
+        }
+    }
+
+    /**
+     * 定时任务状态
+     *
+     * @author liyang
+     * @email 735032128@qq.com
+     * @date 2016年12月3日 上午12:07:22
+     */
+    public enum ScheduleStatus {
+        /**
+         * 正常
+         */
+        NORMAL(0),
+        /**
+         * 暂停
+         */
+        PAUSE(1);
+
+        private int value;
+
+        ScheduleStatus(int value) {
+            this.value = value;
+        }
+
+        public int getValue() {
+            return value;
+        }
+    }
+
+    /**
+     * 云服务商
+     */
+    public enum CloudService {
+        /**
+         * 七牛云
+         */
+        QINIU(1),
+        /**
+         * 阿里云
+         */
+        ALIYUN(2),
+        /**
+         * 腾讯云
+         */
+        QCLOUD(3);
+
+        private int value;
+
+        CloudService(int value) {
+            this.value = value;
+        }
+
+        public int getValue() {
+            return value;
+        }
+    }
+
+}

+ 228 - 0
src/main/java/io/renren/common/utils/DateUtils.java

@@ -0,0 +1,228 @@
+/**
+ * Copyright (c) 2016-2019 人人开源 All rights reserved.
+ * <p>
+ * https://www.renren.io
+ * <p>
+ * 版权所有,侵权必究!
+ */
+
+package io.renren.common.utils;
+
+import org.apache.commons.lang.StringUtils;
+import org.joda.time.DateTime;
+import org.joda.time.LocalDate;
+import org.joda.time.format.DateTimeFormat;
+import org.joda.time.format.DateTimeFormatter;
+
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.regex.Pattern;
+
+/**
+ * 日期处理
+ *
+ * @author Mark 735032128@qq.com
+ */
+public class DateUtils {
+    /** 时间格式(yyyy-MM-dd) */
+    public final static String DATE_PATTERN = "yyyy-MM-dd";
+    /** 时间格式(yyyy-MM-dd HH:mm:ss) */
+    public final static String DATE_TIME_PATTERN = "yyyy-MM-dd HH:mm:ss";
+
+    /**
+     * 日期格式化 日期格式为:yyyy-MM-dd
+     * @param date  日期
+     * @return 返回yyyy-MM-dd格式日期
+     */
+    public static String format(Date date) {
+        return format(date, DATE_PATTERN);
+    }
+
+    /**
+     * 日期格式化 日期格式为:yyyy-MM-dd
+     * @param date  日期
+     * @param pattern  格式,如:DateUtils.DATE_TIME_PATTERN
+     * @return 返回yyyy-MM-dd格式日期
+     */
+    public static String format(Date date, String pattern) {
+        if (date != null) {
+            SimpleDateFormat df = new SimpleDateFormat(pattern);
+            return df.format(date);
+        }
+        return null;
+    }
+
+    /**
+     * 字符串转换成日期
+     * @param strDate 日期字符串
+     * @param pattern 日期的格式,如:DateUtils.DATE_TIME_PATTERN
+     */
+    public static Date stringToDate(String strDate, String pattern) {
+        if (StringUtils.isBlank(strDate)) {
+            return null;
+        }
+
+        DateTimeFormatter fmt = DateTimeFormat.forPattern(pattern);
+        return fmt.parseLocalDateTime(strDate).toDate();
+    }
+
+    /**
+     * 根据周数,获取开始日期、结束日期
+     * @param week  周期  0本周,-1上周,-2上上周,1下周,2下下周
+     * @return 返回date[0]开始日期、date[1]结束日期
+     */
+    public static Date[] getWeekStartAndEnd(int week) {
+        DateTime dateTime = new DateTime();
+        LocalDate date = new LocalDate(dateTime.plusWeeks(week));
+
+        date = date.dayOfWeek().withMinimumValue();
+        Date beginDate = date.toDate();
+        Date endDate = date.plusDays(6).toDate();
+        return new Date[]{beginDate, endDate};
+    }
+
+    /**
+     * 对日期的【秒】进行加/减
+     *
+     * @param date 日期
+     * @param seconds 秒数,负数为减
+     * @return 加/减几秒后的日期
+     */
+    public static Date addDateSeconds(Date date, int seconds) {
+        DateTime dateTime = new DateTime(date);
+        return dateTime.plusSeconds(seconds).toDate();
+    }
+
+    /**
+     * 对日期的【分钟】进行加/减
+     *
+     * @param date 日期
+     * @param minutes 分钟数,负数为减
+     * @return 加/减几分钟后的日期
+     */
+    public static Date addDateMinutes(Date date, int minutes) {
+        DateTime dateTime = new DateTime(date);
+        return dateTime.plusMinutes(minutes).toDate();
+    }
+
+    /**
+     * 对日期的【小时】进行加/减
+     *
+     * @param date 日期
+     * @param hours 小时数,负数为减
+     * @return 加/减几小时后的日期
+     */
+    public static Date addDateHours(Date date, int hours) {
+        DateTime dateTime = new DateTime(date);
+        return dateTime.plusHours(hours).toDate();
+    }
+
+    /**
+     * 对日期的【天】进行加/减
+     *
+     * @param date 日期
+     * @param days 天数,负数为减
+     * @return 加/减几天后的日期
+     */
+    public static Date addDateDays(Date date, int days) {
+        DateTime dateTime = new DateTime(date);
+        return dateTime.plusDays(days).toDate();
+    }
+
+    /**
+     * 对日期的【周】进行加/减
+     *
+     * @param date 日期
+     * @param weeks 周数,负数为减
+     * @return 加/减几周后的日期
+     */
+    public static Date addDateWeeks(Date date, int weeks) {
+        DateTime dateTime = new DateTime(date);
+        return dateTime.plusWeeks(weeks).toDate();
+    }
+
+    /**
+     * 对日期的【月】进行加/减
+     *
+     * @param date 日期
+     * @param months 月数,负数为减
+     * @return 加/减几月后的日期
+     */
+    public static Date addDateMonths(Date date, int months) {
+        DateTime dateTime = new DateTime(date);
+        return dateTime.plusMonths(months).toDate();
+    }
+
+    /**
+     * 对日期的【年】进行加/减
+     *
+     * @param date 日期
+     * @param years 年数,负数为减
+     * @return 加/减几年后的日期
+     */
+    public static Date addDateYears(Date date, int years) {
+        DateTime dateTime = new DateTime(date);
+        return dateTime.plusYears(years).toDate();
+    }
+
+    /**
+     * 常规自动日期格式识别
+     * @param str 时间字符串
+     * @return Date
+     * @author dc
+     */
+    public static String getDateFormat(String str) {
+        boolean year = false;
+        Pattern pattern = Pattern.compile("^[-\\+]?[\\d]*$");
+        if (pattern.matcher(str.substring(0, 4)).matches()) {
+            year = true;
+        }
+        StringBuilder sb = new StringBuilder();
+        int index = 0;
+        if (!year) {
+            if (str.contains("月") || str.contains("-") || str.contains("/") || str.contains(".")) {
+                if (Character.isDigit(str.charAt(0))) {
+                    index = 1;
+                }
+            } else {
+                index = 3;
+            }
+        }
+        for (int i = 0; i < str.length(); i++) {
+            char chr = str.charAt(i);
+            if (Character.isDigit(chr)) {
+                if (index == 0) {
+                    sb.append("y");
+                }
+                if (index == 1) {
+                    sb.append("M");
+                }
+                if (index == 2) {
+                    sb.append("d");
+                }
+                if (index == 3) {
+                    sb.append("H");
+                }
+                if (index == 4) {
+                    sb.append("m");
+                }
+                if (index == 5) {
+                    sb.append("s");
+                }
+                if (index == 6) {
+                    sb.append("S");
+                }
+            } else {
+                if (i > 0) {
+                    char lastChar = str.charAt(i - 1);
+                    if (Character.isDigit(lastChar)) {
+                        index++;
+                    }
+                }
+                sb.append(chr);
+            }
+        }
+        return sb.toString();
+    }
+
+}

+ 40 - 0
src/main/java/io/renren/common/utils/EmailUtils.java

@@ -0,0 +1,40 @@
+package io.renren.common.utils;
+
+import com.aliyun.oss.ServiceException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.mail.MailException;
+import org.springframework.mail.SimpleMailMessage;
+import org.springframework.mail.javamail.JavaMailSender;
+import org.springframework.stereotype.Component;
+
+@Component
+public class EmailUtils {
+
+    private final Logger logger = LoggerFactory.getLogger(getClass());
+
+    @Autowired
+    private JavaMailSender javaMailSender;
+
+    public void sendSimpleEmail(String deliver, String[] receiver, String[] carbonCopy, String subject, String content) throws ServiceException {
+
+        long startTimestamp = System.currentTimeMillis();
+        logger.info("Start send mail ... ");
+
+        try {
+            SimpleMailMessage message = new SimpleMailMessage();
+            message.setFrom(deliver);
+            message.setTo(receiver);
+            message.setCc(carbonCopy);
+            message.setSubject(subject);
+            message.setText(content);
+            javaMailSender.send(message);
+            logger.info("Send mail success, cost {} million seconds", System.currentTimeMillis() - startTimestamp);
+        } catch (MailException e) {
+            logger.error("Send mail failed, error message is : {} \n", e.getMessage());
+            e.printStackTrace();
+            throw new ServiceException(e.getMessage());
+        }
+    }
+}

+ 275 - 0
src/main/java/io/renren/common/utils/ExcelUtils.java

@@ -0,0 +1,275 @@
+package io.renren.common.utils;
+
+import org.apache.poi.hssf.usermodel.HSSFDataFormat;
+import org.apache.poi.hssf.usermodel.HSSFDateUtil;
+import org.apache.poi.hssf.usermodel.HSSFWorkbook;
+import org.apache.poi.ss.usermodel.*;
+import org.apache.poi.ss.util.CellRangeAddress;
+import org.apache.poi.xssf.usermodel.XSSFWorkbook;
+import org.springframework.web.multipart.MultipartFile;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.text.DecimalFormat;
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+
+/**
+ * Created by Administrator on 2018/7/26 0026.
+ */
+public class ExcelUtils {
+
+    public static Workbook getWorkBook(MultipartFile file) {
+        //获得文件名
+        String fileName = file.getOriginalFilename();
+        //创建Workbook工作薄对象,表示整个excel
+        Workbook workbook = null;
+        try {
+            //获取excel文件的io流
+            InputStream is = file.getInputStream();
+            //根据文件后缀名不同(xls和xlsx)获得不同的Workbook实现类对象
+            if (fileName.endsWith("xls")) {
+                //2003
+                workbook = new HSSFWorkbook(is);
+            } else if (fileName.endsWith("xlsx")) {
+                //2007 及2007以上
+                workbook = new XSSFWorkbook(is);
+            }
+        } catch (IOException e) {
+//            log.error(e.getMessage());
+        }
+        return workbook;
+    }
+
+    public static Workbook getWorkBook(String fileUrl) {
+        //获得文件名
+        File file = new File(fileUrl);
+        String fileName = fileUrl;
+        //创建Workbook工作薄对象,表示整个excel
+        Workbook workbook = null;
+        try {
+            InputStream inputStream = new FileInputStream(file);
+            //获取excel文件的io流
+            //根据文件后缀名不同(xls和xlsx)获得不同的Workbook实现类对象
+            if (fileName.endsWith("xls")) {
+                //2003
+                workbook = new HSSFWorkbook(inputStream);
+            } else if (fileName.endsWith("xlsx") || fileName.endsWith("xlsm")) {
+                //2007 及2007以上
+                workbook = new XSSFWorkbook(inputStream);
+            }
+        } catch (IOException e) {
+//            log.error(e.getMessage());
+        }
+        return workbook;
+    }
+
+    public static String getCellValue(Cell cell) {
+        String cellValue = "";
+        if (cell == null) {
+            return cellValue;
+        }
+        //判断数据的类型
+        switch (cell.getCellType()) {
+            case Cell.CELL_TYPE_NUMERIC: //数字
+                cellValue = stringDateProcess(cell);
+                break;
+            case Cell.CELL_TYPE_STRING: //字符串
+                cellValue = String.valueOf(cell.getStringCellValue());
+                break;
+            case Cell.CELL_TYPE_BOOLEAN: //Boolean
+                cellValue = String.valueOf(cell.getBooleanCellValue());
+                break;
+            case Cell.CELL_TYPE_FORMULA: //公式
+                cellValue = String.valueOf(cell.getCellFormula());
+                break;
+            case Cell.CELL_TYPE_BLANK: //空值
+                cellValue = "";
+                break;
+            case Cell.CELL_TYPE_ERROR: //故障
+                cellValue = "非法字符";
+                break;
+            default:
+                cellValue = "未知类型";
+                break;
+        }
+        return cellValue;
+    }
+
+    /**
+     * 时间格式处理
+     *
+     * @return
+     * @author Liu Xin Nan
+     * @data 2017年11月27日
+     */
+    public static String stringDateProcess(Cell cell) {
+        String result = new String();
+        if (HSSFDateUtil.isCellDateFormatted(cell)) {// 处理日期格式、时间格式
+            SimpleDateFormat sdf = null;
+            if (cell.getCellStyle().getDataFormat() == HSSFDataFormat.getBuiltinFormat("h:mm")) {
+                sdf = new SimpleDateFormat("HH:mm");
+            } else {// 日期
+                sdf = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
+            }
+            Date date = cell.getDateCellValue();
+            result = sdf.format(date);
+        } else if (cell.getCellStyle().getDataFormat() == 58) {
+            // 处理自定义日期格式:m月d日(通过判断单元格的格式id解决,id的值是58)
+            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
+            double value = cell.getNumericCellValue();
+            Date date = DateUtil
+                    .getJavaDate(value);
+            result = sdf.format(date);
+        } else {
+            double value = cell.getNumericCellValue();
+            CellStyle style = cell.getCellStyle();
+            DecimalFormat format = new DecimalFormat();
+            String temp = style.getDataFormatString();
+            // 单元格设置成常规
+            if (temp.equals("General")) {
+                format.applyPattern("#");
+            }
+            result = format.format(value);
+        }
+
+        return result;
+    }
+
+    /**
+     * 合并单元格处理,获取合并行
+     *
+     * @param sheet
+     * @return List<CellRangeAddress>
+     */
+    public static List<CellRangeAddress> getCombineCell(Sheet sheet) {
+        List<CellRangeAddress> list = new ArrayList<CellRangeAddress>();
+        //获得一个 sheet 中合并单元格的数量
+        int sheetmergerCount = sheet.getNumMergedRegions();
+        //遍历所有的合并单元格
+        for (int i = 0; i < sheetmergerCount; i++) {
+            //获得合并单元格保存进list中
+            CellRangeAddress ca = sheet.getMergedRegion(i);
+            list.add(ca);
+        }
+        return list;
+    }
+
+    public static int getRowNum(List<CellRangeAddress> listCombineCell, Cell cell, Sheet sheet) {
+        int xr = 0;
+        int firstC = 0;
+        int lastC = 0;
+        int firstR = 0;
+        int lastR = 0;
+        for (CellRangeAddress ca : listCombineCell) {
+            //获得合并单元格的起始行, 结束行, 起始列, 结束列
+            firstC = ca.getFirstColumn();
+            lastC = ca.getLastColumn();
+            firstR = ca.getFirstRow();
+            lastR = ca.getLastRow();
+            if (cell.getRowIndex() >= firstR && cell.getRowIndex() <= lastR) {
+                if (cell.getColumnIndex() >= firstC && cell.getColumnIndex() <= lastC) {
+                    xr = lastR;
+                }
+            }
+
+        }
+        return xr;
+
+    }
+
+    /**
+     * 判断单元格是否为合并单元格,是的话则将单元格的值返回
+     *
+     * @param listCombineCell 存放合并单元格的list
+     * @param cell            需要判断的单元格
+     * @param sheet           sheet
+     * @return
+     */
+    public static String isCombineCell(List<CellRangeAddress> listCombineCell, Cell cell, Sheet sheet)
+            throws Exception {
+        int firstC = 0;
+        int lastC = 0;
+        int firstR = 0;
+        int lastR = 0;
+        String cellValue = null;
+        for (CellRangeAddress ca : listCombineCell) {
+            //获得合并单元格的起始行, 结束行, 起始列, 结束列
+            firstC = ca.getFirstColumn();
+            lastC = ca.getLastColumn();
+            firstR = ca.getFirstRow();
+            lastR = ca.getLastRow();
+            if (cell.getRowIndex() >= firstR && cell.getRowIndex() <= lastR) {
+                if (cell.getColumnIndex() >= firstC && cell.getColumnIndex() <= lastC) {
+                    Row fRow = sheet.getRow(firstR);
+                    Cell fCell = fRow.getCell(firstC);
+                    cellValue = getCellValue(fCell);
+                    break;
+                }
+            } else {
+                cellValue = "";
+            }
+        }
+        return cellValue;
+    }
+
+    /**
+     * 获取合并单元格的值
+     *
+     * @param sheet
+     * @param row
+     * @param column
+     * @return
+     */
+    public static String getMergedRegionValue(Sheet sheet, int row, int column) {
+        int sheetMergeCount = sheet.getNumMergedRegions();
+
+        for (int i = 0; i < sheetMergeCount; i++) {
+            CellRangeAddress ca = sheet.getMergedRegion(i);
+            int firstColumn = ca.getFirstColumn();
+            int lastColumn = ca.getLastColumn();
+            int firstRow = ca.getFirstRow();
+            int lastRow = ca.getLastRow();
+
+            if (row >= firstRow && row <= lastRow) {
+                if (column >= firstColumn && column <= lastColumn) {
+                    Row fRow = sheet.getRow(firstRow);
+                    Cell fCell = fRow.getCell(firstColumn);
+                    return getCellValue(fCell);
+                }
+            }
+        }
+
+        return null;
+    }
+
+    /**
+     * 判断指定的单元格是否是合并单元格
+     *
+     * @param sheet
+     * @param row    行下标
+     * @param column 列下标
+     * @return
+     */
+    public static boolean isMergedRegion(Sheet sheet, int row, int column) {
+        int sheetMergeCount = sheet.getNumMergedRegions();
+        for (int i = 0; i < sheetMergeCount; i++) {
+            CellRangeAddress range = sheet.getMergedRegion(i);
+            int firstColumn = range.getFirstColumn();
+            int lastColumn = range.getLastColumn();
+            int firstRow = range.getFirstRow();
+            int lastRow = range.getLastRow();
+            if (row >= firstRow && row <= lastRow) {
+                if (column >= firstColumn && column <= lastColumn) {
+                    return true;
+                }
+            }
+        }
+        return false;
+    }
+
+}

+ 49 - 0
src/main/java/io/renren/common/utils/ExportWordUtils.java

@@ -0,0 +1,49 @@
+package io.renren.common.utils;
+
+import freemarker.template.Configuration;
+import freemarker.template.Template;
+import freemarker.template.TemplateException;
+import org.apache.commons.lang.StringUtils;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.OutputStreamWriter;
+import java.io.UnsupportedEncodingException;
+import java.net.URLEncoder;
+import java.util.Map;
+
+@SuppressWarnings("deprecation")
+public class ExportWordUtils {
+    private Template template;
+
+    public ExportWordUtils(String basePackage, String templateName) throws Exception {
+        init(basePackage, templateName);
+    }
+
+    private void init(String basePackage, String templateName) throws Exception {
+        Configuration config = new Configuration();//需要指定版本
+        config.setClassLoaderForTemplateLoading(io.renren.common.utils.ExportWordUtils.class.getClassLoader(), basePackage);//去那个文件夹下寻找模板文件
+        config.setOutputEncoding("utf-8");
+        template = config.getTemplate(templateName);//模板名称获取模板
+    }
+
+    public <K, V> void doExport(OutputStream out, Map<K, V> results) throws TemplateException, IOException {
+        template.process(results, new OutputStreamWriter(out));//对模板进行数据填充
+    }
+
+    public void setHeader(HttpServletRequest request, HttpServletResponse response, String fileName) throws UnsupportedEncodingException {
+        String userAgent = request.getHeader("User-Agent");
+        if(StringUtils.contains(userAgent, "MSIE")||StringUtils.contains(userAgent, "Trident") ||
+                StringUtils.contains(userAgent, "Edge")){ //解决IE中文名称乱码
+            fileName = URLEncoder.encode(fileName,"UTF8");
+        }else if(StringUtils.contains(userAgent, "Firefox")){//火狐和其他浏览器中文名乱码
+            fileName = new String(fileName.getBytes("utf8"), "ISO8859-1");
+        }
+        response.setContentType("application/octet-stream;charset=utf-8");
+        response.setHeader("Content-Disposition", "attachment;" + " filename=\""+fileName+"\"");
+    }
+}
+
+

+ 51 - 0
src/main/java/io/renren/common/utils/HttpContextUtils.java

@@ -0,0 +1,51 @@
+/**
+ * Copyright (c) 2016-2019 人人开源 All rights reserved.
+ * <p>
+ * https://www.renren.io
+ * <p>
+ * 版权所有,侵权必究!
+ */
+
+package io.renren.common.utils;
+
+import org.apache.commons.io.IOUtils;
+import org.springframework.web.context.request.RequestContextHolder;
+import org.springframework.web.context.request.ServletRequestAttributes;
+
+import javax.servlet.http.HttpServletRequest;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+public class HttpContextUtils {
+
+    public static void copyImageStream(InputStream inputStream, OutputStream outputStream) {
+        try {
+            IOUtils.copy(inputStream, outputStream);
+        } catch (IOException e) {
+            e.printStackTrace();
+        } finally {
+            try {
+                inputStream.close();
+                outputStream.close();
+            } catch (IOException e) {
+                e.printStackTrace();
+            }
+        }
+    }
+
+    public static HttpServletRequest getHttpServletRequest() {
+        return ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
+    }
+
+    public static String getDomain() {
+        HttpServletRequest request = getHttpServletRequest();
+        StringBuffer url = request.getRequestURL();
+        return url.delete(url.length() - request.getRequestURI().length(), url.length()).toString();
+    }
+
+    public static String getOrigin() {
+        HttpServletRequest request = getHttpServletRequest();
+        return request.getHeader("Origin");
+    }
+}

+ 64 - 0
src/main/java/io/renren/common/utils/IPUtils.java

@@ -0,0 +1,64 @@
+/**
+ * Copyright (c) 2016-2019 人人开源 All rights reserved.
+ * <p>
+ * https://www.renren.io
+ * <p>
+ * 版权所有,侵权必究!
+ */
+
+package io.renren.common.utils;
+
+import com.alibaba.druid.util.StringUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.servlet.http.HttpServletRequest;
+
+/**
+ * IP地址
+ *
+ * @author Mark 735032128@qq.com
+ */
+public class IPUtils {
+    private static Logger logger = LoggerFactory.getLogger(IPUtils.class);
+
+    /**
+     * 获取IP地址
+     *
+     * 使用Nginx等反向代理软件, 则不能通过request.getRemoteAddr()获取IP地址
+     * 如果使用了多级反向代理的话,X-Forwarded-For的值并不止一个,而是一串IP地址,X-Forwarded-For中第一个非unknown的有效IP字符串,则为真实IP地址
+     */
+    public static String getIpAddr(HttpServletRequest request) {
+        String ip = null;
+        try {
+            ip = request.getHeader("x-forwarded-for");
+            if (StringUtils.isEmpty(ip) || "unknown".equalsIgnoreCase(ip)) {
+                ip = request.getHeader("Proxy-Client-IP");
+            }
+            if (StringUtils.isEmpty(ip) || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
+                ip = request.getHeader("WL-Proxy-Client-IP");
+            }
+            if (StringUtils.isEmpty(ip) || "unknown".equalsIgnoreCase(ip)) {
+                ip = request.getHeader("HTTP_CLIENT_IP");
+            }
+            if (StringUtils.isEmpty(ip) || "unknown".equalsIgnoreCase(ip)) {
+                ip = request.getHeader("HTTP_X_FORWARDED_FOR");
+            }
+            if (StringUtils.isEmpty(ip) || "unknown".equalsIgnoreCase(ip)) {
+                ip = request.getRemoteAddr();
+            }
+        } catch (Exception e) {
+            logger.error("IPUtils ERROR ", e);
+        }
+
+//        //使用代理,则获取第一个IP地址
+//        if(StringUtils.isEmpty(ip) && ip.length() > 15) {
+//			if(ip.indexOf(",") > 0) {
+//				ip = ip.substring(0, ip.indexOf(","));
+//			}
+//		}
+
+        return ip;
+    }
+
+}

+ 61 - 0
src/main/java/io/renren/common/utils/LocalFile.java

@@ -0,0 +1,61 @@
+package io.renren.common.utils;
+
+import org.apache.commons.io.FileUtils;
+import org.apache.commons.io.IOUtils;
+import org.apache.commons.lang.StringUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.stereotype.Component;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.text.MessageFormat;
+import java.util.Random;
+
+@Component
+public class LocalFile {
+
+
+    public static String baseDirtory;
+
+    @Value("${file.baseDirtory}")
+    public void setBaseDirtory(String baseDirtory) {
+        LocalFile.baseDirtory = baseDirtory;
+    }
+
+
+    public static String saveDefault(byte[] bytes, String fileName, String ditcory) throws IOException {
+        System.out.println(baseDirtory);
+        if (ditcory == null) {
+            ditcory = new Random().nextInt(99999999) + "/";
+        }
+        String saveDic = MessageFormat.format("{0}{1}", baseDirtory, ditcory);
+        File dic = new File(saveDic);
+        FileUtils.forceMkdir(dic);
+//		String format = DrayFileUtils.getFileTypeByStream(bytes);
+        String format = StringUtils.substringAfterLast(fileName, ".");
+        String name = StringUtils.substringBeforeLast(fileName, ".");
+        if (format.equals("jpeg")) {
+            format = "jpg";
+        }
+        if (StringUtils.isBlank(format)) {
+            format = "jpg";
+        }
+        String filePath = MessageFormat.format("{0}{1}.{2}", saveDic, name, format);
+        File file = new File(filePath);
+        if (!file.exists()) {
+            file.createNewFile();
+        }
+        FileOutputStream fout = new FileOutputStream(file);
+        IOUtils.write(bytes, fout);
+        fout.flush();
+        fout.close();
+
+        return MessageFormat.format("{0}{1}.{2}", ditcory, name, format);
+    }
+
+
+}

+ 26 - 0
src/main/java/io/renren/common/utils/MapUtils.java

@@ -0,0 +1,26 @@
+/**
+ * Copyright (c) 2016-2019 人人开源 All rights reserved.
+ * <p>
+ * https://www.renren.io
+ * <p>
+ * 版权所有,侵权必究!
+ */
+
+package io.renren.common.utils;
+
+import java.util.HashMap;
+
+
+/**
+ * Map工具类
+ *
+ * @author Mark 735032128@qq.com
+ */
+public class MapUtils extends HashMap<String, Object> {
+
+    @Override
+    public MapUtils put(String key, Object value) {
+        super.put(key, value);
+        return this;
+    }
+}

+ 109 - 0
src/main/java/io/renren/common/utils/PDFTemplateUtil.java

@@ -0,0 +1,109 @@
+package io.renren.common.utils;
+
+import com.alibaba.fastjson.JSON;
+import com.lowagie.text.pdf.BaseFont;
+import freemarker.template.Configuration;
+import freemarker.template.Template;
+import io.renren.modules.sys.controller.AbstractController;
+import org.xhtmlrenderer.pdf.ITextRenderer;
+
+import javax.servlet.http.HttpServletResponse;
+import java.io.ByteArrayOutputStream;
+import java.io.OutputStream;
+import java.io.StringWriter;
+import java.net.URLEncoder;
+import java.util.Locale;
+import java.util.Map;
+
+/**
+ * @Description: 通过模板导出pdf文件
+ * @Author: cq
+ * @CreateDate: 2020/9/21 9:37
+ */
+public class PDFTemplateUtil extends AbstractController {
+
+    /**
+     * 通过模板导出pdf文件
+     *
+     * @param map             数据
+     * @param templateFileName 模板文件名
+     * @throws Exception
+     */
+    private static ByteArrayOutputStream createPDF(Map<String, Object> map, String templateFileName) throws Exception {
+        // 创建一个FreeMarker实例, 负责管理FreeMarker模板的Configuration实例
+        Configuration cfg = new Configuration(Configuration.DEFAULT_INCOMPATIBLE_IMPROVEMENTS);
+        // 指定FreeMarker模板文件的位置
+        cfg.setClassForTemplateLoading(PDFTemplateUtil.class, "/freeMaker");
+        ITextRenderer renderer = new ITextRenderer();
+        OutputStream out = new ByteArrayOutputStream();
+        try {
+            // 设置 css中 的字体样式(暂时仅支持宋体和黑体) 必须,不然中文不显示
+            renderer.getFontResolver().addFont("/freeMaker/font/simsun.ttc", BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED);
+            // 设置模板的编码格式
+            cfg.setEncoding(Locale.CHINA, "UTF-8");
+            // 获取模板文件
+            Template template = cfg.getTemplate(templateFileName, "UTF-8");
+            StringWriter writer = new StringWriter();
+
+            // 将数据输出到html中
+            template.process(map, writer);
+            writer.flush();
+
+            String html = writer.toString();
+            // 把html代码传入渲染器中
+            renderer.setDocumentFromString(html);
+
+            // 设置模板中的图片路径 (这里的images在resources/freeMaker目录下) 模板中img标签src路径需要相对路径加图片名 如<img src="images/xh.jpg"/>
+            //String url = PDFTemplateUtil.class.getClassLoader().getResource("freeMaker").toURI().toString();
+            //renderer.getSharedContext().setBaseURL(url);
+            renderer.getSharedContext().setBaseURL("file:/D:/ssyFile/");
+            renderer.layout();
+
+            renderer.createPDF(out, false);
+            renderer.finishPDF();
+            out.flush();
+            return (ByteArrayOutputStream) out;
+        } finally {
+            if (out != null) {
+                out.close();
+            }
+        }
+    }
+
+    /**
+     * 通过模板导出pdf文件
+     *
+     * @param templateName 模板文件名(模板文件名+后缀)
+     * @param pdfName      pdf文件名(pdf文件名+后缀)
+     * @param map         数据
+     * @param response     HttpServletResponse
+     * @throws Exception
+     */
+    public static void exportPdf(String templateName, String pdfName, Map<String, Object> map, HttpServletResponse response) throws Exception {
+        ByteArrayOutputStream baos = null;
+        OutputStream out = null;
+        try {
+            baos = createPDF(map, templateName);
+            ;
+            // 设置响应消息头,告诉浏览器当前响应是一个下载文件
+            response.setContentType("application/x-msdownload");
+            // 告诉浏览器,当前响应数据要求用户干预保存到文件中,以及文件名是什么 如果文件名有中文,必须URL编码
+            String fileName = URLEncoder.encode(pdfName, "UTF-8");
+            response.setHeader("Content-Disposition", "attachment;filename=" + fileName);
+            out = response.getOutputStream();
+            baos.writeTo(out);
+            baos.close();
+        } catch (Exception e) {
+            e.printStackTrace();
+            throw new Exception("导出失败:" + e.getMessage());
+        } finally {
+            if (baos != null) {
+                baos.close();
+            }
+            if (out != null) {
+                out.close();
+            }
+        }
+    }
+
+}

+ 110 - 0
src/main/java/io/renren/common/utils/PageUtils.java

@@ -0,0 +1,110 @@
+/**
+ * Copyright (c) 2016-2019 人人开源 All rights reserved.
+ * <p>
+ * https://www.renren.io
+ * <p>
+ * 版权所有,侵权必究!
+ */
+
+package io.renren.common.utils;
+
+import com.baomidou.mybatisplus.core.metadata.IPage;
+
+import java.io.Serializable;
+import java.util.List;
+
+/**
+ * 分页工具类
+ *
+ * @author Mark 735032128@qq.com
+ */
+public class PageUtils implements Serializable {
+    private static final long serialVersionUID = 1L;
+    /**
+     * 总记录数
+     */
+    private int totalCount;
+    /**
+     * 每页记录数
+     */
+    private int pageSize;
+    /**
+     * 总页数
+     */
+    private int totalPage;
+    /**
+     * 当前页数
+     */
+    private int currPage;
+    /**
+     * 列表数据
+     */
+    private List<?> list;
+
+    /**
+     * 分页
+     * @param list        列表数据
+     * @param totalCount  总记录数
+     * @param pageSize    每页记录数
+     * @param currPage    当前页数
+     */
+    public PageUtils(List<?> list, int totalCount, int pageSize, int currPage) {
+        this.list = list;
+        this.totalCount = totalCount;
+        this.pageSize = pageSize;
+        this.currPage = currPage;
+        this.totalPage = (int) Math.ceil((double) totalCount / pageSize);
+    }
+
+    /**
+     * 分页
+     */
+    public PageUtils(IPage<?> page) {
+        this.list = page.getRecords();
+        this.totalCount = (int) page.getTotal();
+        this.pageSize = (int) page.getSize();
+        this.currPage = (int) page.getCurrent();
+        this.totalPage = (int) page.getPages();
+    }
+
+    public int getTotalCount() {
+        return totalCount;
+    }
+
+    public void setTotalCount(int totalCount) {
+        this.totalCount = totalCount;
+    }
+
+    public int getPageSize() {
+        return pageSize;
+    }
+
+    public void setPageSize(int pageSize) {
+        this.pageSize = pageSize;
+    }
+
+    public int getTotalPage() {
+        return totalPage;
+    }
+
+    public void setTotalPage(int totalPage) {
+        this.totalPage = totalPage;
+    }
+
+    public int getCurrPage() {
+        return currPage;
+    }
+
+    public void setCurrPage(int currPage) {
+        this.currPage = currPage;
+    }
+
+    public List<?> getList() {
+        return list;
+    }
+
+    public void setList(List<?> list) {
+        this.list = list;
+    }
+
+}

+ 77 - 0
src/main/java/io/renren/common/utils/Query.java

@@ -0,0 +1,77 @@
+/**
+ * Copyright (c) 2016-2019 人人开源 All rights reserved.
+ * <p>
+ * https://www.renren.io
+ * <p>
+ * 版权所有,侵权必究!
+ */
+
+package io.renren.common.utils;
+
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.core.metadata.OrderItem;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import io.renren.common.xss.SQLFilter;
+import org.apache.commons.lang.StringUtils;
+
+import java.util.Map;
+
+/**
+ * 查询参数
+ *
+ * @author Mark 735032128@qq.com
+ */
+public class Query<T> {
+
+    public IPage<T> getPage(Map<String, Object> params) {
+        return this.getPage(params, null, false);
+    }
+
+    public IPage<T> getPage(Map<String, Object> params, String defaultOrderField, boolean isAsc) {
+        //分页参数
+        long curPage = 1;
+        long limit = 10;
+
+        if (params.get(Constant.PAGE) != null) {
+            curPage = Long.parseLong((String) params.get(Constant.PAGE));
+        }
+        if (params.get(Constant.LIMIT) != null) {
+            limit = Long.parseLong((String) params.get(Constant.LIMIT));
+        }
+
+        //分页对象
+        Page<T> page = new Page<>(curPage, limit);
+
+        //分页参数
+        params.put(Constant.PAGE, page);
+
+        //排序字段
+        //防止SQL注入(因为sidx、order是通过拼接SQL实现排序的,会有SQL注入风险)
+        String orderField = SQLFilter.sqlInject((String) params.get(Constant.ORDER_FIELD));
+        String order = (String) params.get(Constant.ORDER);
+
+
+        //前端字段排序
+        if (StringUtils.isNotEmpty(orderField) && StringUtils.isNotEmpty(order)) {
+            if (Constant.ASC.equalsIgnoreCase(order)) {
+                return page.addOrder(OrderItem.asc(orderField));
+            } else {
+                return page.addOrder(OrderItem.desc(orderField));
+            }
+        }
+
+        //没有排序字段,则不排序
+        if (StringUtils.isBlank(defaultOrderField)) {
+            return page;
+        }
+
+        //默认排序
+        if (isAsc) {
+            page.addOrder(OrderItem.asc(defaultOrderField));
+        } else {
+            page.addOrder(OrderItem.desc(defaultOrderField));
+        }
+
+        return page;
+    }
+}

+ 64 - 0
src/main/java/io/renren/common/utils/R.java

@@ -0,0 +1,64 @@
+/**
+ * Copyright (c) 2016-2019 人人开源 All rights reserved.
+ * <p>
+ * https://www.renren.io
+ * <p>
+ * 版权所有,侵权必究!
+ */
+
+package io.renren.common.utils;
+
+import org.apache.http.HttpStatus;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * 返回数据
+ *
+ * @author Mark 735032128@qq.com
+ */
+public class R extends HashMap<String, Object> {
+    private static final long serialVersionUID = 1L;
+
+    public R() {
+        put("code", 0);
+        put("msg", "success");
+    }
+
+    public static R error() {
+        return error(HttpStatus.SC_INTERNAL_SERVER_ERROR, "未知异常,请联系管理员");
+    }
+
+    public static R error(String msg) {
+        return error(HttpStatus.SC_INTERNAL_SERVER_ERROR, msg);
+    }
+
+    public static R error(int code, String msg) {
+        R r = new R();
+        r.put("code", code);
+        r.put("msg", msg);
+        return r;
+    }
+
+    public static R ok(String msg) {
+        R r = new R();
+        r.put("msg", msg);
+        return r;
+    }
+
+    public static R ok(Map<String, Object> map) {
+        R r = new R();
+        r.putAll(map);
+        return r;
+    }
+
+    public static R ok() {
+        return new R();
+    }
+
+    public R put(String key, Object value) {
+        super.put(key, value);
+        return this;
+    }
+}

+ 21 - 0
src/main/java/io/renren/common/utils/RedisKeys.java

@@ -0,0 +1,21 @@
+/**
+ * Copyright (c) 2016-2019 人人开源 All rights reserved.
+ * <p>
+ * https://www.renren.io
+ * <p>
+ * 版权所有,侵权必究!
+ */
+
+package io.renren.common.utils;
+
+/**
+ * Redis所有Keys
+ *
+ * @author Mark 735032128@qq.com
+ */
+public class RedisKeys {
+
+    public static String getSysConfigKey(String key) {
+        return "sys:config:" + key;
+    }
+}

+ 99 - 0
src/main/java/io/renren/common/utils/RedisUtils.java

@@ -0,0 +1,99 @@
+/**
+ * Copyright (c) 2016-2019 人人开源 All rights reserved.
+ * <p>
+ * https://www.renren.io
+ * <p>
+ * 版权所有,侵权必究!
+ */
+
+package io.renren.common.utils;
+
+import com.google.gson.Gson;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.redis.core.*;
+import org.springframework.stereotype.Component;
+
+import java.util.concurrent.TimeUnit;
+
+/**
+ * Redis工具类
+ *
+ * @author Mark 735032128@qq.com
+ */
+@Component
+public class RedisUtils {
+    @Autowired
+    private RedisTemplate<String, Object> redisTemplate;
+    @Autowired
+    private ValueOperations<String, String> valueOperations;
+    @Autowired
+    private HashOperations<String, String, Object> hashOperations;
+    @Autowired
+    private ListOperations<String, Object> listOperations;
+    @Autowired
+    private SetOperations<String, Object> setOperations;
+    @Autowired
+    private ZSetOperations<String, Object> zSetOperations;
+    /**  默认过期时长,单位:秒 */
+    public final static long DEFAULT_EXPIRE = 60 * 60 * 24;
+    /**  不设置过期时长 */
+    public final static long NOT_EXPIRE = -1;
+    private final static Gson gson = new Gson();
+
+    public void set(String key, Object value, long expire) {
+        valueOperations.set(key, toJson(value));
+        if (expire != NOT_EXPIRE) {
+            redisTemplate.expire(key, expire, TimeUnit.SECONDS);
+        }
+    }
+
+    public void set(String key, Object value) {
+        set(key, value, DEFAULT_EXPIRE);
+    }
+
+    public <T> T get(String key, Class<T> clazz, long expire) {
+        String value = valueOperations.get(key);
+        if (expire != NOT_EXPIRE) {
+            redisTemplate.expire(key, expire, TimeUnit.SECONDS);
+        }
+        return value == null ? null : fromJson(value, clazz);
+    }
+
+    public <T> T get(String key, Class<T> clazz) {
+        return get(key, clazz, NOT_EXPIRE);
+    }
+
+    public String get(String key, long expire) {
+        String value = valueOperations.get(key);
+        if (expire != NOT_EXPIRE) {
+            redisTemplate.expire(key, expire, TimeUnit.SECONDS);
+        }
+        return value;
+    }
+
+    public String get(String key) {
+        return get(key, NOT_EXPIRE);
+    }
+
+    public void delete(String key) {
+        redisTemplate.delete(key);
+    }
+
+    /**
+     * Object转成JSON数据
+     */
+    private String toJson(Object object) {
+        if (object instanceof Integer || object instanceof Long || object instanceof Float ||
+                object instanceof Double || object instanceof Boolean || object instanceof String) {
+            return String.valueOf(object);
+        }
+        return gson.toJson(object);
+    }
+
+    /**
+     * JSON数据,转成Object
+     */
+    private <T> T fromJson(String json, Class<T> clazz) {
+        return gson.fromJson(json, clazz);
+    }
+}

+ 61 - 0
src/main/java/io/renren/common/utils/ShiroUtils.java

@@ -0,0 +1,61 @@
+/**
+ * Copyright (c) 2016-2019 人人开源 All rights reserved.
+ * <p>
+ * https://www.renren.io
+ * <p>
+ * 版权所有,侵权必究!
+ */
+
+package io.renren.common.utils;
+
+import io.renren.common.exception.RRException;
+import io.renren.modules.sys.entity.SysUserEntity;
+import org.apache.shiro.SecurityUtils;
+import org.apache.shiro.session.Session;
+import org.apache.shiro.subject.Subject;
+
+/**
+ * Shiro工具类
+ *
+ * @author Mark 735032128@qq.com
+ */
+public class ShiroUtils {
+
+    public static Session getSession() {
+        return SecurityUtils.getSubject().getSession();
+    }
+
+    public static Subject getSubject() {
+        return SecurityUtils.getSubject();
+    }
+
+    public static SysUserEntity getUserEntity() {
+        return (SysUserEntity) SecurityUtils.getSubject().getPrincipal();
+    }
+
+    public static Long getUserId() {
+        return getUserEntity().getUserId();
+    }
+
+    public static void setSessionAttribute(Object key, Object value) {
+        getSession().setAttribute(key, value);
+    }
+
+    public static Object getSessionAttribute(Object key) {
+        return getSession().getAttribute(key);
+    }
+
+    public static boolean isLogin() {
+        return SecurityUtils.getSubject().getPrincipal() != null;
+    }
+
+    public static String getKaptcha(String key) {
+        Object kaptcha = getSessionAttribute(key);
+        if (kaptcha == null) {
+            throw new RRException("验证码已失效");
+        }
+        getSession().removeAttribute(key);
+        return kaptcha.toString();
+    }
+
+}

+ 51 - 0
src/main/java/io/renren/common/utils/SpringContextUtils.java

@@ -0,0 +1,51 @@
+/**
+ * Copyright (c) 2016-2019 人人开源 All rights reserved.
+ * <p>
+ * https://www.renren.io
+ * <p>
+ * 版权所有,侵权必究!
+ */
+
+package io.renren.common.utils;
+
+import org.springframework.beans.BeansException;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.ApplicationContextAware;
+import org.springframework.stereotype.Component;
+
+/**
+ * Spring Context 工具类
+ *
+ * @author Mark 735032128@qq.com
+ */
+@Component
+public class SpringContextUtils implements ApplicationContextAware {
+    public static ApplicationContext applicationContext;
+
+    @Override
+    public void setApplicationContext(ApplicationContext applicationContext)
+            throws BeansException {
+        SpringContextUtils.applicationContext = applicationContext;
+    }
+
+    public static Object getBean(String name) {
+        return applicationContext.getBean(name);
+    }
+
+    public static <T> T getBean(String name, Class<T> requiredType) {
+        return applicationContext.getBean(name, requiredType);
+    }
+
+    public static boolean containsBean(String name) {
+        return applicationContext.containsBean(name);
+    }
+
+    public static boolean isSingleton(String name) {
+        return applicationContext.isSingleton(name);
+    }
+
+    public static Class<? extends Object> getType(String name) {
+        return applicationContext.getType(name);
+    }
+
+}

+ 35 - 0
src/main/java/io/renren/common/utils/export/EncodeTools.java

@@ -0,0 +1,35 @@
+package io.renren.common.utils.export;
+
+import org.apache.commons.lang3.StringUtils;
+
+import javax.servlet.http.HttpServletRequest;
+import java.net.URLEncoder;
+
+/**
+ * @author kai
+ */
+public class EncodeTools {
+    /**
+     * 根据浏览器编码文件名 <br>
+     *
+     * @param fileName 文件名
+     * @param request  HttpServletRequest 对象,用来获取浏览器信息
+     * @return 编码后的文件名
+     * @author Hunter
+     * @version [1.0.0, 2015年10月24日]
+     * @since [1.0.0]
+     */
+    public static String encodeFileNameByBrowser(String fileName, HttpServletRequest request) {
+        String res = fileName;
+        try {
+            String userAgent = request.getHeader("USER-AGENT");
+            if (StringUtils.contains(userAgent, "Edge") || StringUtils.contains(userAgent, "MSIE")) {
+                res = URLEncoder.encode(fileName, "UTF8");
+            } else {
+                res = new String(fileName.getBytes(), "ISO8859-1");
+            }
+        } catch (Exception e) {
+        }
+        return res;
+    }
+}

+ 20 - 0
src/main/java/io/renren/common/utils/export/JxlsTemplate.java

@@ -0,0 +1,20 @@
+package io.renren.common.utils.export;
+
+/**
+ * Created by xk on 2017/12/4 0004.
+ */
+public interface JxlsTemplate {
+    /**
+     * 模板路径
+     *
+     * @return
+     */
+    String getPath();
+
+    /**
+     * 生成名称
+     *
+     * @return
+     */
+    String getName();
+}

+ 74 - 0
src/main/java/io/renren/common/utils/export/JxlsView.java

@@ -0,0 +1,74 @@
+package io.renren.common.utils.export;
+
+import org.jxls.common.Context;
+import org.jxls.util.JxlsHelper;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.web.servlet.view.AbstractView;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Map;
+
+/**
+ * Created by xk on 2017/12/4 0004.
+ */
+public class JxlsView extends AbstractView {
+    private static Logger log = LoggerFactory.getLogger(JxlsView.class);
+
+    private JxlsTemplate template;
+
+    private Object data;
+    private Object sheetdata;
+
+    public JxlsView() {
+        this.setContentType("application/vnd.ms-excel");
+    }
+
+    public JxlsView(JxlsTemplate template, Object data) {
+        this();
+        this.template = template;
+        this.data = data;
+    }
+
+    public JxlsView(JxlsTemplate template, Object data, Object sheetdata) {
+        this();
+        this.template = template;
+        this.data = data;
+        this.sheetdata = sheetdata;
+    }
+
+    protected boolean generatesDownloadContent() {
+        return true;
+    }
+
+    protected final void renderMergedOutputModel(Map<String, Object> model, HttpServletRequest request, HttpServletResponse response) throws Exception {
+        response.setContentType(this.getContentType());
+        response.setHeader("Content-Disposition", "attachment;filename="
+                + EncodeTools.encodeFileNameByBrowser(template.getName(), request));
+        InputStream is = null;
+        try {
+            is = JxlsView.class.getResourceAsStream(template.getPath());
+            Context context = new Context();
+            context.putVar("data", data);
+            context.putVar("sheetNames", sheetdata);
+            logger.info("data" + data);
+            logger.info("is" + is);
+            logger.info("getOutputStream" + response.getOutputStream());
+            JxlsHelper.getInstance().processTemplate(is, response.getOutputStream(), context);
+        } catch (Exception e) {
+            log.error("导出失败", e);
+        } finally {
+            if (is != null) {
+                try {
+                    is.close();
+                } catch (IOException e) {
+                    log.error("is关闭失败", e);
+                }
+            }
+        }
+
+    }
+}

+ 32 - 0
src/main/java/io/renren/common/validator/Assert.java

@@ -0,0 +1,32 @@
+/**
+ * Copyright (c) 2016-2019 人人开源 All rights reserved.
+ * <p>
+ * https://www.renren.io
+ * <p>
+ * 版权所有,侵权必究!
+ */
+
+package io.renren.common.validator;
+
+import io.renren.common.exception.RRException;
+import org.apache.commons.lang.StringUtils;
+
+/**
+ * 数据校验
+ *
+ * @author Mark 735032128@qq.com
+ */
+public abstract class Assert {
+
+    public static void isBlank(String str, String message) {
+        if (StringUtils.isBlank(str)) {
+            throw new RRException(message);
+        }
+    }
+
+    public static void isNull(Object object, String message) {
+        if (object == null) {
+            throw new RRException(message);
+        }
+    }
+}

+ 49 - 0
src/main/java/io/renren/common/validator/ValidatorUtils.java

@@ -0,0 +1,49 @@
+/**
+ * Copyright (c) 2016-2019 人人开源 All rights reserved.
+ * <p>
+ * https://www.renren.io
+ * <p>
+ * 版权所有,侵权必究!
+ */
+
+package io.renren.common.validator;
+
+import io.renren.common.exception.RRException;
+
+import javax.validation.ConstraintViolation;
+import javax.validation.Validation;
+import javax.validation.Validator;
+import java.util.Set;
+
+/**
+ * hibernate-validator校验工具类
+ *
+ * 参考文档:http://docs.jboss.org/hibernate/validator/5.4/reference/en-US/html_single/
+ *
+ * @author Mark 735032128@qq.com
+ */
+public class ValidatorUtils {
+    private static Validator validator;
+
+    static {
+        validator = Validation.buildDefaultValidatorFactory().getValidator();
+    }
+
+    /**
+     * 校验对象
+     * @param object        待校验对象
+     * @param groups        待校验的组
+     * @throws RRException  校验不通过,则报RRException异常
+     */
+    public static void validateEntity(Object object, Class<?>... groups)
+            throws RRException {
+        Set<ConstraintViolation<Object>> constraintViolations = validator.validate(object, groups);
+        if (!constraintViolations.isEmpty()) {
+            StringBuilder msg = new StringBuilder();
+            for (ConstraintViolation<Object> constraint : constraintViolations) {
+                msg.append(constraint.getMessage()).append("<br>");
+            }
+            throw new RRException(msg.toString());
+        }
+    }
+}

+ 17 - 0
src/main/java/io/renren/common/validator/group/AddGroup.java

@@ -0,0 +1,17 @@
+/**
+ * Copyright (c) 2016-2019 人人开源 All rights reserved.
+ * <p>
+ * https://www.renren.io
+ * <p>
+ * 版权所有,侵权必究!
+ */
+
+package io.renren.common.validator.group;
+
+/**
+ * 新增数据 Group
+ *
+ * @author Mark 735032128@qq.com
+ */
+public interface AddGroup {
+}

+ 17 - 0
src/main/java/io/renren/common/validator/group/AliyunGroup.java

@@ -0,0 +1,17 @@
+/**
+ * Copyright (c) 2016-2019 人人开源 All rights reserved.
+ * <p>
+ * https://www.renren.io
+ * <p>
+ * 版权所有,侵权必究!
+ */
+
+package io.renren.common.validator.group;
+
+/**
+ * 阿里云
+ *
+ * @author Mark 735032128@qq.com
+ */
+public interface AliyunGroup {
+}

+ 21 - 0
src/main/java/io/renren/common/validator/group/Group.java

@@ -0,0 +1,21 @@
+/**
+ * Copyright (c) 2016-2019 人人开源 All rights reserved.
+ * <p>
+ * https://www.renren.io
+ * <p>
+ * 版权所有,侵权必究!
+ */
+
+package io.renren.common.validator.group;
+
+import javax.validation.GroupSequence;
+
+/**
+ * 定义校验顺序,如果AddGroup组失败,则UpdateGroup组不会再校验
+ *
+ * @author Mark 735032128@qq.com
+ */
+@GroupSequence({AddGroup.class, UpdateGroup.class})
+public interface Group {
+
+}

+ 17 - 0
src/main/java/io/renren/common/validator/group/QcloudGroup.java

@@ -0,0 +1,17 @@
+/**
+ * Copyright (c) 2016-2019 人人开源 All rights reserved.
+ * <p>
+ * https://www.renren.io
+ * <p>
+ * 版权所有,侵权必究!
+ */
+
+package io.renren.common.validator.group;
+
+/**
+ * 腾讯云
+ *
+ * @author Mark 735032128@qq.com
+ */
+public interface QcloudGroup {
+}

+ 17 - 0
src/main/java/io/renren/common/validator/group/QiniuGroup.java

@@ -0,0 +1,17 @@
+/**
+ * Copyright (c) 2016-2019 人人开源 All rights reserved.
+ * <p>
+ * https://www.renren.io
+ * <p>
+ * 版权所有,侵权必究!
+ */
+
+package io.renren.common.validator.group;
+
+/**
+ * 七牛
+ *
+ * @author Mark 735032128@qq.com
+ */
+public interface QiniuGroup {
+}

+ 19 - 0
src/main/java/io/renren/common/validator/group/UpdateGroup.java

@@ -0,0 +1,19 @@
+/**
+ * Copyright (c) 2016-2019 人人开源 All rights reserved.
+ * <p>
+ * https://www.renren.io
+ * <p>
+ * 版权所有,侵权必究!
+ */
+
+package io.renren.common.validator.group;
+
+/**
+ * 更新数据 Group
+ *
+ * @author Mark 735032128@qq.com
+ */
+
+public interface UpdateGroup {
+
+}

+ 554 - 0
src/main/java/io/renren/common/xss/HTMLFilter.java

@@ -0,0 +1,554 @@
+package io.renren.common.xss;
+
+import java.util.*;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+import java.util.logging.Logger;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * HTML filtering utility for protecting against XSS (Cross Site Scripting).
+ * <p>
+ * This code is licensed LGPLv3
+ * <p>
+ * This code is a Java port of the original work in PHP by Cal Hendersen.
+ * http://code.iamcal.com/php/lib_filter/
+ * <p>
+ * The trickiest part of the translation was handling the differences in regex handling
+ * between PHP and Java.  These resources were helpful in the process:
+ * <p>
+ * http://java.sun.com/j2se/1.4.2/docs/api/java/util/regex/Pattern.html
+ * http://us2.php.net/manual/en/reference.pcre.pattern.modifiers.php
+ * http://www.regular-expressions.info/modifiers.html
+ * <p>
+ * A note on naming conventions: instance variables are prefixed with a "v"; global
+ * constants are in all caps.
+ * <p>
+ * Sample use:
+ * String input = ...
+ * String clean = new HTMLFilter().filter( input );
+ * <p>
+ * The class is not thread safe. Create a new instance if in doubt.
+ * <p>
+ * If you find bugs or have suggestions on improvement (especially regarding
+ * performance), please contact us.  The latest version of this
+ * source, and our contact details, can be found at http://xss-html-filter.sf.net
+ *
+ * @author Joseph O'Connell
+ * @author Cal Hendersen
+ * @author Michael Semb Wever
+ */
+public final class HTMLFilter {
+
+    /**
+     * regex flag union representing /si modifiers in php
+     **/
+    private static final int REGEX_FLAGS_SI = Pattern.CASE_INSENSITIVE | Pattern.DOTALL;
+    private static final Pattern P_COMMENTS = Pattern.compile("<!--(.*?)-->", Pattern.DOTALL);
+    private static final Pattern P_COMMENT = Pattern.compile("^!--(.*)--$", REGEX_FLAGS_SI);
+    private static final Pattern P_TAGS = Pattern.compile("<(.*?)>", Pattern.DOTALL);
+    private static final Pattern P_END_TAG = Pattern.compile("^/([a-z0-9]+)", REGEX_FLAGS_SI);
+    private static final Pattern P_START_TAG = Pattern.compile("^([a-z0-9]+)(.*?)(/?)$", REGEX_FLAGS_SI);
+    private static final Pattern P_QUOTED_ATTRIBUTES = Pattern.compile("([a-z0-9]+)=([\"'])(.*?)\\2", REGEX_FLAGS_SI);
+    private static final Pattern P_UNQUOTED_ATTRIBUTES = Pattern.compile("([a-z0-9]+)(=)([^\"\\s']+)", REGEX_FLAGS_SI);
+    private static final Pattern P_PROTOCOL = Pattern.compile("^([^:]+):", REGEX_FLAGS_SI);
+    private static final Pattern P_ENTITY = Pattern.compile("&#(\\d+);?");
+    private static final Pattern P_ENTITY_UNICODE = Pattern.compile("&#x([0-9a-f]+);?");
+    private static final Pattern P_ENCODE = Pattern.compile("%([0-9a-f]{2});?");
+    private static final Pattern P_VALID_ENTITIES = Pattern.compile("&([^&;]*)(?=(;|&|$))");
+    private static final Pattern P_VALID_QUOTES = Pattern.compile("(>|^)([^<]+?)(<|$)", Pattern.DOTALL);
+    private static final Pattern P_END_ARROW = Pattern.compile("^>");
+    private static final Pattern P_BODY_TO_END = Pattern.compile("<([^>]*?)(?=<|$)");
+    private static final Pattern P_XML_CONTENT = Pattern.compile("(^|>)([^<]*?)(?=>)");
+    private static final Pattern P_STRAY_LEFT_ARROW = Pattern.compile("<([^>]*?)(?=<|$)");
+    private static final Pattern P_STRAY_RIGHT_ARROW = Pattern.compile("(^|>)([^<]*?)(?=>)");
+    private static final Pattern P_AMP = Pattern.compile("&");
+    private static final Pattern P_QUOTE = Pattern.compile("<");
+    private static final Pattern P_LEFT_ARROW = Pattern.compile("<");
+    private static final Pattern P_RIGHT_ARROW = Pattern.compile(">");
+    private static final Pattern P_BOTH_ARROWS = Pattern.compile("<>");
+
+    // @xxx could grow large... maybe use sesat's ReferenceMap
+    private static final ConcurrentMap<String, Pattern> P_REMOVE_PAIR_BLANKS = new ConcurrentHashMap<String, Pattern>();
+    private static final ConcurrentMap<String, Pattern> P_REMOVE_SELF_BLANKS = new ConcurrentHashMap<String, Pattern>();
+
+    /**
+     * set of allowed html elements, along with allowed attributes for each element
+     **/
+    private final Map<String, List<String>> vAllowed;
+    /**
+     * counts of open tags for each (allowable) html element
+     **/
+    private final Map<String, Integer> vTagCounts = new HashMap<String, Integer>();
+
+    /**
+     * html elements which must always be self-closing (e.g. "<img />")
+     **/
+    private final String[] vSelfClosingTags;
+    /**
+     * html elements which must always have separate opening and closing tags (e.g. "<b></b>")
+     **/
+    private final String[] vNeedClosingTags;
+    /**
+     * set of disallowed html elements
+     **/
+    private final String[] vDisallowed;
+    /**
+     * attributes which should be checked for valid protocols
+     **/
+    private final String[] vProtocolAtts;
+    /**
+     * allowed protocols
+     **/
+    private final String[] vAllowedProtocols;
+    /**
+     * tags which should be removed if they contain no content (e.g. "<b></b>" or "<b />")
+     **/
+    private final String[] vRemoveBlanks;
+    /**
+     * entities allowed within html markup
+     **/
+    private final String[] vAllowedEntities;
+    /**
+     * flag determining whether comments are allowed in input String.
+     */
+    private final boolean stripComment;
+    private final boolean encodeQuotes;
+    private boolean vDebug = false;
+    /**
+     * flag determining whether to try to make tags when presented with "unbalanced"
+     * angle brackets (e.g. "<b text </b>" becomes "<b> text </b>").  If set to false,
+     * unbalanced angle brackets will be html escaped.
+     */
+    private final boolean alwaysMakeTags;
+
+    /**
+     * Default constructor.
+     */
+    public HTMLFilter() {
+        vAllowed = new HashMap<>();
+
+        final ArrayList<String> a_atts = new ArrayList<String>();
+        a_atts.add("href");
+        a_atts.add("target");
+        vAllowed.put("a", a_atts);
+
+        final ArrayList<String> img_atts = new ArrayList<String>();
+        img_atts.add("src");
+        img_atts.add("width");
+        img_atts.add("height");
+        img_atts.add("alt");
+        vAllowed.put("img", img_atts);
+
+        final ArrayList<String> no_atts = new ArrayList<String>();
+        vAllowed.put("b", no_atts);
+        vAllowed.put("strong", no_atts);
+        vAllowed.put("i", no_atts);
+        vAllowed.put("em", no_atts);
+
+        vSelfClosingTags = new String[]{"img"};
+        vNeedClosingTags = new String[]{"a", "b", "strong", "i", "em"};
+        vDisallowed = new String[]{};
+        vAllowedProtocols = new String[]{"http", "mailto", "https"}; // no ftp.
+        vProtocolAtts = new String[]{"src", "href"};
+        vRemoveBlanks = new String[]{"a", "b", "strong", "i", "em"};
+        vAllowedEntities = new String[]{"amp", "gt", "lt", "quot"};
+        stripComment = true;
+        encodeQuotes = true;
+        alwaysMakeTags = true;
+    }
+
+    /**
+     * Set debug flag to true. Otherwise use default settings. See the default constructor.
+     *
+     * @param debug turn debug on with a true argument
+     */
+    public HTMLFilter(final boolean debug) {
+        this();
+        vDebug = debug;
+
+    }
+
+    /**
+     * Map-parameter configurable constructor.
+     *
+     * @param conf map containing configuration. keys match field names.
+     */
+    public HTMLFilter(final Map<String, Object> conf) {
+
+        assert conf.containsKey("vAllowed") : "configuration requires vAllowed";
+        assert conf.containsKey("vSelfClosingTags") : "configuration requires vSelfClosingTags";
+        assert conf.containsKey("vNeedClosingTags") : "configuration requires vNeedClosingTags";
+        assert conf.containsKey("vDisallowed") : "configuration requires vDisallowed";
+        assert conf.containsKey("vAllowedProtocols") : "configuration requires vAllowedProtocols";
+        assert conf.containsKey("vProtocolAtts") : "configuration requires vProtocolAtts";
+        assert conf.containsKey("vRemoveBlanks") : "configuration requires vRemoveBlanks";
+        assert conf.containsKey("vAllowedEntities") : "configuration requires vAllowedEntities";
+
+        vAllowed = Collections.unmodifiableMap((HashMap<String, List<String>>) conf.get("vAllowed"));
+        vSelfClosingTags = (String[]) conf.get("vSelfClosingTags");
+        vNeedClosingTags = (String[]) conf.get("vNeedClosingTags");
+        vDisallowed = (String[]) conf.get("vDisallowed");
+        vAllowedProtocols = (String[]) conf.get("vAllowedProtocols");
+        vProtocolAtts = (String[]) conf.get("vProtocolAtts");
+        vRemoveBlanks = (String[]) conf.get("vRemoveBlanks");
+        vAllowedEntities = (String[]) conf.get("vAllowedEntities");
+        stripComment = conf.containsKey("stripComment") ? (Boolean) conf.get("stripComment") : true;
+        encodeQuotes = conf.containsKey("encodeQuotes") ? (Boolean) conf.get("encodeQuotes") : true;
+        alwaysMakeTags = conf.containsKey("alwaysMakeTags") ? (Boolean) conf.get("alwaysMakeTags") : true;
+    }
+
+    private void reset() {
+        vTagCounts.clear();
+    }
+
+    private void debug(final String msg) {
+        if (vDebug) {
+            Logger.getAnonymousLogger().info(msg);
+        }
+    }
+
+    //---------------------------------------------------------------
+    // my versions of some PHP library functions
+    public static String chr(final int decimal) {
+        return String.valueOf((char) decimal);
+    }
+
+    public static String htmlSpecialChars(final String s) {
+        String result = s;
+        result = regexReplace(P_AMP, "&amp;", result);
+        result = regexReplace(P_QUOTE, "&quot;", result);
+        result = regexReplace(P_LEFT_ARROW, "&lt;", result);
+        result = regexReplace(P_RIGHT_ARROW, "&gt;", result);
+        return result;
+    }
+
+    //---------------------------------------------------------------
+
+    /**
+     * given a user submitted input String, filter out any invalid or restricted
+     * html.
+     *
+     * @param input text (i.e. submitted by a user) than may contain html
+     * @return "clean" version of input, with only valid, whitelisted html elements allowed
+     */
+    public String filter(final String input) {
+        reset();
+        String s = input;
+
+        debug("************************************************");
+        debug("              INPUT: " + input);
+
+        s = escapeComments(s);
+        debug("     escapeComments: " + s);
+
+        s = balanceHTML(s);
+        debug("        balanceHTML: " + s);
+
+        s = checkTags(s);
+        debug("          checkTags: " + s);
+
+        s = processRemoveBlanks(s);
+        debug("processRemoveBlanks: " + s);
+
+        s = validateEntities(s);
+        debug("    validateEntites: " + s);
+
+        debug("************************************************\n\n");
+        return s;
+    }
+
+    public boolean isAlwaysMakeTags() {
+        return alwaysMakeTags;
+    }
+
+    public boolean isStripComments() {
+        return stripComment;
+    }
+
+    private String escapeComments(final String s) {
+        final Matcher m = P_COMMENTS.matcher(s);
+        final StringBuffer buf = new StringBuffer();
+        if (m.find()) {
+            final String match = m.group(1); //(.*?)
+            m.appendReplacement(buf, Matcher.quoteReplacement("<!--" + htmlSpecialChars(match) + "-->"));
+        }
+        m.appendTail(buf);
+
+        return buf.toString();
+    }
+
+    private String balanceHTML(String s) {
+        if (alwaysMakeTags) {
+            //
+            // try and form html
+            //
+            s = regexReplace(P_END_ARROW, "", s);
+            s = regexReplace(P_BODY_TO_END, "<$1>", s);
+            s = regexReplace(P_XML_CONTENT, "$1<$2", s);
+
+        } else {
+            //
+            // escape stray brackets
+            //
+            s = regexReplace(P_STRAY_LEFT_ARROW, "&lt;$1", s);
+            s = regexReplace(P_STRAY_RIGHT_ARROW, "$1$2&gt;<", s);
+
+            //
+            // the last regexp causes '<>' entities to appear
+            // (we need to do a lookahead assertion so that the last bracket can
+            // be used in the next pass of the regexp)
+            //
+            s = regexReplace(P_BOTH_ARROWS, "", s);
+        }
+
+        return s;
+    }
+
+    private String checkTags(String s) {
+        Matcher m = P_TAGS.matcher(s);
+
+        final StringBuffer buf = new StringBuffer();
+        while (m.find()) {
+            String replaceStr = m.group(1);
+            replaceStr = processTag(replaceStr);
+            m.appendReplacement(buf, Matcher.quoteReplacement(replaceStr));
+        }
+        m.appendTail(buf);
+
+        s = buf.toString();
+
+        // these get tallied in processTag
+        // (remember to reset before subsequent calls to filter method)
+        for (String key : vTagCounts.keySet()) {
+            for (int ii = 0; ii < vTagCounts.get(key); ii++) {
+                s += "</" + key + ">";
+            }
+        }
+
+        return s;
+    }
+
+    private String processRemoveBlanks(final String s) {
+        String result = s;
+        for (String tag : vRemoveBlanks) {
+            if (!P_REMOVE_PAIR_BLANKS.containsKey(tag)) {
+                P_REMOVE_PAIR_BLANKS.putIfAbsent(tag, Pattern.compile("<" + tag + "(\\s[^>]*)?></" + tag + ">"));
+            }
+            result = regexReplace(P_REMOVE_PAIR_BLANKS.get(tag), "", result);
+            if (!P_REMOVE_SELF_BLANKS.containsKey(tag)) {
+                P_REMOVE_SELF_BLANKS.putIfAbsent(tag, Pattern.compile("<" + tag + "(\\s[^>]*)?/>"));
+            }
+            result = regexReplace(P_REMOVE_SELF_BLANKS.get(tag), "", result);
+        }
+
+        return result;
+    }
+
+    private static String regexReplace(final Pattern regex_pattern, final String replacement, final String s) {
+        Matcher m = regex_pattern.matcher(s);
+        return m.replaceAll(replacement);
+    }
+
+    private String processTag(final String s) {
+        // ending tags
+        Matcher m = P_END_TAG.matcher(s);
+        if (m.find()) {
+            final String name = m.group(1).toLowerCase();
+            if (allowed(name)) {
+                if (!inArray(name, vSelfClosingTags)) {
+                    if (vTagCounts.containsKey(name)) {
+                        vTagCounts.put(name, vTagCounts.get(name) - 1);
+                        return "</" + name + ">";
+                    }
+                }
+            }
+        }
+
+        // starting tags
+        m = P_START_TAG.matcher(s);
+        if (m.find()) {
+            final String name = m.group(1).toLowerCase();
+            final String body = m.group(2);
+            String ending = m.group(3);
+
+            //debug( "in a starting tag, name='" + name + "'; body='" + body + "'; ending='" + ending + "'" );
+            if (allowed(name)) {
+                String params = "";
+
+                final Matcher m2 = P_QUOTED_ATTRIBUTES.matcher(body);
+                final Matcher m3 = P_UNQUOTED_ATTRIBUTES.matcher(body);
+                final List<String> paramNames = new ArrayList<String>();
+                final List<String> paramValues = new ArrayList<String>();
+                while (m2.find()) {
+                    paramNames.add(m2.group(1)); //([a-z0-9]+)
+                    paramValues.add(m2.group(3)); //(.*?)
+                }
+                while (m3.find()) {
+                    paramNames.add(m3.group(1)); //([a-z0-9]+)
+                    paramValues.add(m3.group(3)); //([^\"\\s']+)
+                }
+
+                String paramName, paramValue;
+                for (int ii = 0; ii < paramNames.size(); ii++) {
+                    paramName = paramNames.get(ii).toLowerCase();
+                    paramValue = paramValues.get(ii);
+
+//          debug( "paramName='" + paramName + "'" );
+//          debug( "paramValue='" + paramValue + "'" );
+//          debug( "allowed? " + vAllowed.get( name ).contains( paramName ) );
+
+                    if (allowedAttribute(name, paramName)) {
+                        if (inArray(paramName, vProtocolAtts)) {
+                            paramValue = processParamProtocol(paramValue);
+                        }
+                        params += " " + paramName + "=\"" + paramValue + "\"";
+                    }
+                }
+
+                if (inArray(name, vSelfClosingTags)) {
+                    ending = " /";
+                }
+
+                if (inArray(name, vNeedClosingTags)) {
+                    ending = "";
+                }
+
+                if (ending == null || ending.length() < 1) {
+                    if (vTagCounts.containsKey(name)) {
+                        vTagCounts.put(name, vTagCounts.get(name) + 1);
+                    } else {
+                        vTagCounts.put(name, 1);
+                    }
+                } else {
+                    ending = " /";
+                }
+                return "<" + name + params + ending + ">";
+            } else {
+                return "";
+            }
+        }
+
+        // comments
+        m = P_COMMENT.matcher(s);
+        if (!stripComment && m.find()) {
+            return "<" + m.group() + ">";
+        }
+
+        return "";
+    }
+
+    private String processParamProtocol(String s) {
+        s = decodeEntities(s);
+        final Matcher m = P_PROTOCOL.matcher(s);
+        if (m.find()) {
+            final String protocol = m.group(1);
+            if (!inArray(protocol, vAllowedProtocols)) {
+                // bad protocol, turn into local anchor link instead
+                s = "#" + s.substring(protocol.length() + 1, s.length());
+                if (s.startsWith("#//")) {
+                    s = "#" + s.substring(3, s.length());
+                }
+            }
+        }
+
+        return s;
+    }
+
+    private String decodeEntities(String s) {
+        StringBuffer buf = new StringBuffer();
+
+        Matcher m = P_ENTITY.matcher(s);
+        while (m.find()) {
+            final String match = m.group(1);
+            final int decimal = Integer.decode(match).intValue();
+            m.appendReplacement(buf, Matcher.quoteReplacement(chr(decimal)));
+        }
+        m.appendTail(buf);
+        s = buf.toString();
+
+        buf = new StringBuffer();
+        m = P_ENTITY_UNICODE.matcher(s);
+        while (m.find()) {
+            final String match = m.group(1);
+            final int decimal = Integer.valueOf(match, 16).intValue();
+            m.appendReplacement(buf, Matcher.quoteReplacement(chr(decimal)));
+        }
+        m.appendTail(buf);
+        s = buf.toString();
+
+        buf = new StringBuffer();
+        m = P_ENCODE.matcher(s);
+        while (m.find()) {
+            final String match = m.group(1);
+            final int decimal = Integer.valueOf(match, 16).intValue();
+            m.appendReplacement(buf, Matcher.quoteReplacement(chr(decimal)));
+        }
+        m.appendTail(buf);
+        s = buf.toString();
+
+        s = validateEntities(s);
+        return s;
+    }
+
+    private String validateEntities(final String s) {
+        StringBuffer buf = new StringBuffer();
+
+        // validate entities throughout the string
+        Matcher m = P_VALID_ENTITIES.matcher(s);
+        while (m.find()) {
+            final String one = m.group(1); //([^&;]*)
+            final String two = m.group(2); //(?=(;|&|$))
+            m.appendReplacement(buf, Matcher.quoteReplacement(checkEntity(one, two)));
+        }
+        m.appendTail(buf);
+
+        return encodeQuotes(buf.toString());
+    }
+
+    private String encodeQuotes(final String s) {
+        if (encodeQuotes) {
+            StringBuffer buf = new StringBuffer();
+            Matcher m = P_VALID_QUOTES.matcher(s);
+            while (m.find()) {
+                final String one = m.group(1); //(>|^)
+                final String two = m.group(2); //([^<]+?)
+                final String three = m.group(3); //(<|$)
+                m.appendReplacement(buf, Matcher.quoteReplacement(one + regexReplace(P_QUOTE, "&quot;", two) + three));
+            }
+            m.appendTail(buf);
+            return buf.toString();
+        } else {
+            return s;
+        }
+    }
+
+    private String checkEntity(final String preamble, final String term) {
+
+        return ";".equals(term) && isValidEntity(preamble)
+                ? '&' + preamble
+                : "&amp;" + preamble;
+    }
+
+    private boolean isValidEntity(final String entity) {
+        return inArray(entity, vAllowedEntities);
+    }
+
+    private static boolean inArray(final String s, final String[] array) {
+        for (String item : array) {
+            if (item != null && item.equals(s)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    private boolean allowed(final String name) {
+        return (vAllowed.isEmpty() || vAllowed.containsKey(name)) && !inArray(name, vDisallowed);
+    }
+
+    private boolean allowedAttribute(final String name, final String paramName) {
+        return allowed(name) && (vAllowed.isEmpty() || vAllowed.get(name).contains(paramName));
+    }
+}

+ 50 - 0
src/main/java/io/renren/common/xss/SQLFilter.java

@@ -0,0 +1,50 @@
+/**
+ * Copyright (c) 2016-2019 人人开源 All rights reserved.
+ * <p>
+ * https://www.renren.io
+ * <p>
+ * 版权所有,侵权必究!
+ */
+
+package io.renren.common.xss;
+
+import io.renren.common.exception.RRException;
+import org.apache.commons.lang.StringUtils;
+
+/**
+ * SQL过滤
+ *
+ * @author Mark 735032128@qq.com
+ */
+public class SQLFilter {
+
+    /**
+     * SQL注入过滤
+     * @param str  待验证的字符串
+     */
+    public static String sqlInject(String str) {
+        if (StringUtils.isBlank(str)) {
+            return null;
+        }
+        //去掉'|"|;|\字符
+        str = StringUtils.replace(str, "'", "");
+        str = StringUtils.replace(str, "\"", "");
+        str = StringUtils.replace(str, ";", "");
+        str = StringUtils.replace(str, "\\", "");
+
+        //转换成小写
+        str = str.toLowerCase();
+
+        //非法字符
+        String[] keywords = {"master", "truncate", "insert", "select", "delete", "update", "declare", "alter", "drop"};
+
+        //判断是否包含非法字符
+        for (String keyword : keywords) {
+            if (str.indexOf(keyword) != -1) {
+                throw new RRException("包含非法字符");
+            }
+        }
+
+        return str;
+    }
+}

+ 37 - 0
src/main/java/io/renren/common/xss/XssFilter.java

@@ -0,0 +1,37 @@
+/**
+ * Copyright (c) 2016-2019 人人开源 All rights reserved.
+ * <p>
+ * https://www.renren.io
+ * <p>
+ * 版权所有,侵权必究!
+ */
+
+package io.renren.common.xss;
+
+import javax.servlet.*;
+import javax.servlet.http.HttpServletRequest;
+import java.io.IOException;
+
+/**
+ * XSS过滤
+ *
+ * @author Mark 735032128@qq.com
+ */
+public class XssFilter implements Filter {
+
+    @Override
+    public void init(FilterConfig config) throws ServletException {
+    }
+
+    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
+            throws IOException, ServletException {
+        XssHttpServletRequestWrapper xssRequest = new XssHttpServletRequestWrapper(
+                (HttpServletRequest) request);
+        chain.doFilter(xssRequest, response);
+    }
+
+    @Override
+    public void destroy() {
+    }
+
+}

+ 147 - 0
src/main/java/io/renren/common/xss/XssHttpServletRequestWrapper.java

@@ -0,0 +1,147 @@
+/**
+ * Copyright (c) 2016-2019 人人开源 All rights reserved.
+ * <p>
+ * https://www.renren.io
+ * <p>
+ * 版权所有,侵权必究!
+ */
+
+package io.renren.common.xss;
+
+import org.apache.commons.io.IOUtils;
+import org.apache.commons.lang.StringUtils;
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.MediaType;
+
+import javax.servlet.ReadListener;
+import javax.servlet.ServletInputStream;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletRequestWrapper;
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.util.LinkedHashMap;
+import java.util.Map;
+
+/**
+ * XSS过滤处理
+ *
+ * @author Mark 735032128@qq.com
+ */
+public class XssHttpServletRequestWrapper extends HttpServletRequestWrapper {
+    //没被包装过的HttpServletRequest(特殊场景,需要自己过滤)
+    HttpServletRequest orgRequest;
+    //html过滤
+    private final static HTMLFilter htmlFilter = new HTMLFilter();
+
+    public XssHttpServletRequestWrapper(HttpServletRequest request) {
+        super(request);
+        orgRequest = request;
+    }
+
+    @Override
+    public ServletInputStream getInputStream() throws IOException {
+        //非json类型,直接返回
+        if (!MediaType.APPLICATION_JSON_VALUE.equalsIgnoreCase(super.getHeader(HttpHeaders.CONTENT_TYPE))) {
+            return super.getInputStream();
+        }
+
+        //为空,直接返回
+        String json = IOUtils.toString(super.getInputStream(), "utf-8");
+        if (StringUtils.isBlank(json)) {
+            return super.getInputStream();
+        }
+
+        //xss过滤
+        json = xssEncode(json);
+        final ByteArrayInputStream bis = new ByteArrayInputStream(json.getBytes("utf-8"));
+        return new ServletInputStream() {
+            @Override
+            public boolean isFinished() {
+                return true;
+            }
+
+            @Override
+            public boolean isReady() {
+                return true;
+            }
+
+            @Override
+            public void setReadListener(ReadListener readListener) {
+
+            }
+
+            @Override
+            public int read() throws IOException {
+                return bis.read();
+            }
+        };
+    }
+
+    @Override
+    public String getParameter(String name) {
+        String value = super.getParameter(xssEncode(name));
+        if (StringUtils.isNotBlank(value)) {
+            value = xssEncode(value);
+        }
+        return value;
+    }
+
+    @Override
+    public String[] getParameterValues(String name) {
+        String[] parameters = super.getParameterValues(name);
+        if (parameters == null || parameters.length == 0) {
+            return null;
+        }
+
+        for (int i = 0; i < parameters.length; i++) {
+            parameters[i] = xssEncode(parameters[i]);
+        }
+        return parameters;
+    }
+
+    @Override
+    public Map<String, String[]> getParameterMap() {
+        Map<String, String[]> map = new LinkedHashMap<>();
+        Map<String, String[]> parameters = super.getParameterMap();
+        for (String key : parameters.keySet()) {
+            String[] values = parameters.get(key);
+            for (int i = 0; i < values.length; i++) {
+                values[i] = xssEncode(values[i]);
+            }
+            map.put(key, values);
+        }
+        return map;
+    }
+
+    @Override
+    public String getHeader(String name) {
+        String value = super.getHeader(xssEncode(name));
+        if (StringUtils.isNotBlank(value)) {
+            value = xssEncode(value);
+        }
+        return value;
+    }
+
+    private String xssEncode(String input) {
+        return htmlFilter.filter(input);
+    }
+
+    /**
+     * 获取最原始的request
+     */
+    public HttpServletRequest getOrgRequest() {
+        return orgRequest;
+    }
+
+    /**
+     * 获取最原始的request
+     */
+    public static HttpServletRequest getOrgRequest(HttpServletRequest request) {
+        if (request instanceof XssHttpServletRequestWrapper) {
+            return ((XssHttpServletRequestWrapper) request).getOrgRequest();
+        }
+
+        return request;
+    }
+
+}

+ 26 - 0
src/main/java/io/renren/config/CorsConfig.java

@@ -0,0 +1,26 @@
+/**
+ * Copyright (c) 2016-2019 人人开源 All rights reserved.
+ * <p>
+ * https://www.renren.io
+ * <p>
+ * 版权所有,侵权必究!
+ */
+
+package io.renren.config;
+
+import org.springframework.context.annotation.Configuration;
+import org.springframework.web.servlet.config.annotation.CorsRegistry;
+import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
+
+@Configuration
+public class CorsConfig implements WebMvcConfigurer {
+
+    @Override
+    public void addCorsMappings(CorsRegistry registry) {
+        registry.addMapping("/**")
+                .allowedOrigins("*")
+                .allowCredentials(true)
+                .allowedMethods("GET", "POST", "PUT", "DELETE", "OPTIONS")
+                .maxAge(3600);
+    }
+}

+ 49 - 0
src/main/java/io/renren/config/FilterConfig.java

@@ -0,0 +1,49 @@
+/**
+ * Copyright (c) 2016-2019 人人开源 All rights reserved.
+ * <p>
+ * https://www.renren.io
+ * <p>
+ * 版权所有,侵权必究!
+ */
+
+package io.renren.config;
+
+import io.renren.common.xss.XssFilter;
+import org.springframework.boot.web.servlet.FilterRegistrationBean;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.web.filter.DelegatingFilterProxy;
+
+import javax.servlet.DispatcherType;
+
+/**
+ * Filter配置
+ *
+ * @author Mark 735032128@qq.com
+ */
+@Configuration
+public class FilterConfig {
+
+    @Bean
+    public FilterRegistrationBean shiroFilterRegistration() {
+        FilterRegistrationBean registration = new FilterRegistrationBean();
+        registration.setFilter(new DelegatingFilterProxy("shiroFilter"));
+        //该值缺省为false,表示生命周期由SpringApplicationContext管理,设置为true则表示由ServletContainer管理
+        registration.addInitParameter("targetFilterLifecycle", "true");
+        registration.setEnabled(true);
+        registration.setOrder(Integer.MAX_VALUE - 1);
+        registration.addUrlPatterns("/*");
+        return registration;
+    }
+
+    @Bean
+    public FilterRegistrationBean xssFilterRegistration() {
+        FilterRegistrationBean registration = new FilterRegistrationBean();
+        registration.setDispatcherTypes(DispatcherType.REQUEST);
+        registration.setFilter(new XssFilter());
+        registration.addUrlPatterns("/*");
+        registration.setName("xssFilter");
+        registration.setOrder(Integer.MAX_VALUE);
+        return registration;
+    }
+}

+ 39 - 0
src/main/java/io/renren/config/KaptchaConfig.java

@@ -0,0 +1,39 @@
+/**
+ * Copyright (c) 2016-2019 人人开源 All rights reserved.
+ * <p>
+ * https://www.renren.io
+ * <p>
+ * 版权所有,侵权必究!
+ */
+
+package io.renren.config;
+
+import com.google.code.kaptcha.impl.DefaultKaptcha;
+import com.google.code.kaptcha.util.Config;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+import java.util.Properties;
+
+
+/**
+ * 生成验证码配置
+ *
+ * @author Mark 735032128@qq.com
+ */
+@Configuration
+public class KaptchaConfig {
+
+    @Bean
+    public DefaultKaptcha producer() {
+        Properties properties = new Properties();
+        properties.put("kaptcha.border", "no");
+        properties.put("kaptcha.textproducer.font.color", "black");
+        properties.put("kaptcha.textproducer.char.space", "5");
+        properties.put("kaptcha.textproducer.font.names", "Arial,Courier,cmr10,宋体,楷体,微软雅黑");
+        Config config = new Config(properties);
+        DefaultKaptcha defaultKaptcha = new DefaultKaptcha();
+        defaultKaptcha.setConfig(config);
+        return defaultKaptcha;
+    }
+}

+ 37 - 0
src/main/java/io/renren/config/MybatisPlusConfig.java

@@ -0,0 +1,37 @@
+/**
+ * Copyright (c) 2016-2019 人人开源 All rights reserved.
+ * <p>
+ * https://www.renren.io
+ * <p>
+ * 版权所有,侵权必究!
+ */
+
+package io.renren.config;
+
+import com.baomidou.mybatisplus.core.incrementer.IKeyGenerator;
+import com.baomidou.mybatisplus.extension.incrementer.OracleKeyGenerator;
+import com.baomidou.mybatisplus.extension.plugins.PaginationInterceptor;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+/**
+ * mybatis-plus配置
+ *
+ * @author Mark 735032128@qq.com
+ */
+@Configuration
+public class MybatisPlusConfig {
+
+    /**
+     * 分页插件
+     */
+    @Bean
+    public PaginationInterceptor paginationInterceptor() {
+        return new PaginationInterceptor();
+    }
+
+    @Bean
+    public IKeyGenerator keyGenerator() {
+        return new OracleKeyGenerator();
+    }
+}

+ 63 - 0
src/main/java/io/renren/config/RedisConfig.java

@@ -0,0 +1,63 @@
+/**
+ * Copyright (c) 2016-2019 人人开源 All rights reserved.
+ * <p>
+ * https://www.renren.io
+ * <p>
+ * 版权所有,侵权必究!
+ */
+
+package io.renren.config;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.data.redis.connection.RedisConnectionFactory;
+import org.springframework.data.redis.core.*;
+import org.springframework.data.redis.serializer.StringRedisSerializer;
+
+/**
+ * Redis配置
+ *
+ * @author Mark 735032128@qq.com
+ */
+@Configuration
+public class RedisConfig {
+    @Autowired
+    private RedisConnectionFactory factory;
+
+    @Bean
+    public RedisTemplate<String, Object> redisTemplate() {
+        RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
+        redisTemplate.setKeySerializer(new StringRedisSerializer());
+        redisTemplate.setHashKeySerializer(new StringRedisSerializer());
+        redisTemplate.setHashValueSerializer(new StringRedisSerializer());
+        redisTemplate.setValueSerializer(new StringRedisSerializer());
+        redisTemplate.setConnectionFactory(factory);
+        return redisTemplate;
+    }
+
+    @Bean
+    public HashOperations<String, String, Object> hashOperations(RedisTemplate<String, Object> redisTemplate) {
+        return redisTemplate.opsForHash();
+    }
+
+    @Bean
+    public ValueOperations<String, String> valueOperations(RedisTemplate<String, String> redisTemplate) {
+        return redisTemplate.opsForValue();
+    }
+
+    @Bean
+    public ListOperations<String, Object> listOperations(RedisTemplate<String, Object> redisTemplate) {
+        return redisTemplate.opsForList();
+    }
+
+    @Bean
+    public SetOperations<String, Object> setOperations(RedisTemplate<String, Object> redisTemplate) {
+        return redisTemplate.opsForSet();
+    }
+
+    @Bean
+    public ZSetOperations<String, Object> zSetOperations(RedisTemplate<String, Object> redisTemplate) {
+        return redisTemplate.opsForZSet();
+    }
+}

+ 93 - 0
src/main/java/io/renren/config/ShiroConfig.java

@@ -0,0 +1,93 @@
+/**
+ * Copyright (c) 2016-2019 人人开源 All rights reserved.
+ * <p>
+ * https://www.renren.io
+ * <p>
+ * 版权所有,侵权必究!
+ */
+
+package io.renren.config;
+
+import io.renren.modules.sys.oauth2.OAuth2Filter;
+import io.renren.modules.sys.oauth2.OAuth2Realm;
+import org.apache.shiro.mgt.SecurityManager;
+import org.apache.shiro.spring.LifecycleBeanPostProcessor;
+import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
+import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
+import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+import javax.servlet.Filter;
+import java.util.HashMap;
+import java.util.LinkedHashMap;
+import java.util.Map;
+
+/**
+ * Shiro配置
+ *
+ * @author Mark 735032128@qq.com
+ */
+@Configuration
+public class ShiroConfig {
+
+    @Bean("securityManager")
+    public SecurityManager securityManager(OAuth2Realm oAuth2Realm) {
+        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
+        securityManager.setRealm(oAuth2Realm);
+        securityManager.setRememberMeManager(null);
+        return securityManager;
+    }
+
+    @Bean("shiroFilter")
+    public ShiroFilterFactoryBean shiroFilter(SecurityManager securityManager) {
+        ShiroFilterFactoryBean shiroFilter = new ShiroFilterFactoryBean();
+        shiroFilter.setSecurityManager(securityManager);
+
+        //oauth过滤
+        Map<String, Filter> filters = new HashMap<>();
+        filters.put("oauth2", new OAuth2Filter());
+        shiroFilter.setFilters(filters);
+
+        Map<String, String> filterMap = new LinkedHashMap<>();
+        filterMap.put("/webjars/**", "anon");
+        filterMap.put("/static/**", "anon");
+        filterMap.put("/act/**", "anon");
+        filterMap.put("/approve/tapprove/processImg/**", "anon");
+        filterMap.put("/ssy/pipeline/import", "anon");
+        filterMap.put("/getpwd/**", "anon");
+        filterMap.put("/druid/**", "anon");
+        filterMap.put("/app/**", "anon");
+        filterMap.put("/sys/login", "anon");
+        filterMap.put("/swagger/**", "anon");
+        filterMap.put("/v2/api-docs", "anon");
+        filterMap.put("/swagger-ui.html", "anon");
+        filterMap.put("/index.html", "anon");
+        filterMap.put("/swagger-resources/**", "anon");
+        filterMap.put("/captcha.jpg", "anon");
+        filterMap.put("/getMailCode", "anon");
+        filterMap.put("/forgetPassword", "anon");
+        filterMap.put("/aaa.txt", "anon");
+        filterMap.put("/common/download/**", "anon");
+        filterMap.put("/approve/word/**", "anon");
+
+//        filterMap.put("/**", "anon");
+        filterMap.put("/**", "oauth2");
+        shiroFilter.setFilterChainDefinitionMap(filterMap);
+
+        return shiroFilter;
+    }
+
+    @Bean("lifecycleBeanPostProcessor")
+    public LifecycleBeanPostProcessor lifecycleBeanPostProcessor() {
+        return new LifecycleBeanPostProcessor();
+    }
+
+    @Bean
+    public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager) {
+        AuthorizationAttributeSourceAdvisor advisor = new AuthorizationAttributeSourceAdvisor();
+        advisor.setSecurityManager(securityManager);
+        return advisor;
+    }
+
+}

+ 61 - 0
src/main/java/io/renren/config/SwaggerConfig.java

@@ -0,0 +1,61 @@
+/**
+ * Copyright (c) 2016-2019 人人开源 All rights reserved.
+ * <p>
+ * https://www.renren.io
+ * <p>
+ * 版权所有,侵权必究!
+ */
+
+package io.renren.config;
+
+import io.swagger.annotations.ApiOperation;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
+import springfox.documentation.builders.ApiInfoBuilder;
+import springfox.documentation.builders.PathSelectors;
+import springfox.documentation.builders.RequestHandlerSelectors;
+import springfox.documentation.service.ApiInfo;
+import springfox.documentation.service.ApiKey;
+import springfox.documentation.spi.DocumentationType;
+import springfox.documentation.spring.web.plugins.Docket;
+import springfox.documentation.swagger2.annotations.EnableSwagger2;
+
+import java.util.List;
+
+import static com.google.common.collect.Lists.newArrayList;
+
+@Configuration
+@EnableSwagger2
+public class SwaggerConfig implements WebMvcConfigurer {
+
+    @Bean
+    public Docket createRestApi() {
+        return new Docket(DocumentationType.SWAGGER_2)
+                .apiInfo(apiInfo())
+                .select()
+                //加了ApiOperation注解的类,才生成接口文档
+                .apis(RequestHandlerSelectors.withMethodAnnotation(ApiOperation.class))
+                //包下的类,才生成接口文档
+                //.apis(RequestHandlerSelectors.basePackage("io.renren.controller"))
+                .paths(PathSelectors.any())
+                .build()
+                .securitySchemes(security());
+    }
+
+    private ApiInfo apiInfo() {
+        return new ApiInfoBuilder()
+                .title("人人开源")
+                .description("renren-fast文档")
+                .termsOfServiceUrl("https://www.renren.io")
+                .version("3.0.0")
+                .build();
+    }
+
+    private List<ApiKey> security() {
+        return newArrayList(
+                new ApiKey("token", "token", "header")
+        );
+    }
+
+}

+ 41 - 0
src/main/java/io/renren/config/TomcatConfig.java

@@ -0,0 +1,41 @@
+package io.renren.config;
+
+import org.apache.catalina.Context;
+import org.apache.catalina.connector.Connector;
+import org.apache.tomcat.util.descriptor.web.SecurityCollection;
+import org.apache.tomcat.util.descriptor.web.SecurityConstraint;
+import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+@Configuration
+public class TomcatConfig {
+
+//    @Bean
+//    TomcatServletWebServerFactory tomcatServletWebServerFactory() {
+//        TomcatServletWebServerFactory factory = new TomcatServletWebServerFactory(){
+//            @Override
+//            protected void postProcessContext(Context context) {
+//                SecurityConstraint constraint = new SecurityConstraint();
+//                constraint.setUserConstraint("CONFIDENTIAL");
+//                SecurityCollection collection = new SecurityCollection();
+//                collection.addPattern("/*");
+//                constraint.addCollection(collection);
+//                context.addConstraint(constraint);
+//            }
+//        };
+//        factory.addAdditionalTomcatConnectors(createTomcatConnector());
+//        return factory;
+//    }
+//    private Connector createTomcatConnector() {
+//        Connector connector = new
+//                Connector("org.apache.coyote.http11.Http11NioProtocol");
+//        connector.setScheme("http");
+//        connector.setPort(8080);
+//        connector.setSecure(false);
+//        connector.setRedirectPort(443);
+//        return connector;
+//    }
+
+
+}

+ 22 - 0
src/main/java/io/renren/modules/app/annotation/Login.java

@@ -0,0 +1,22 @@
+/**
+ * Copyright (c) 2016-2019 人人开源 All rights reserved.
+ * <p>
+ * https://www.renren.io
+ * <p>
+ * 版权所有,侵权必究!
+ */
+
+package io.renren.modules.app.annotation;
+
+import java.lang.annotation.*;
+
+/**
+ * app登录效验
+ *
+ * @author Mark 735032128@qq.com
+ */
+@Target(ElementType.METHOD)
+@Retention(RetentionPolicy.RUNTIME)
+@Documented
+public @interface Login {
+}

+ 25 - 0
src/main/java/io/renren/modules/app/annotation/LoginUser.java

@@ -0,0 +1,25 @@
+/**
+ * Copyright (c) 2016-2019 人人开源 All rights reserved.
+ * <p>
+ * https://www.renren.io
+ * <p>
+ * 版权所有,侵权必究!
+ */
+
+package io.renren.modules.app.annotation;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * 登录用户信息
+ *
+ * @author Mark 735032128@qq.com
+ */
+@Target(ElementType.PARAMETER)
+@Retention(RetentionPolicy.RUNTIME)
+public @interface LoginUser {
+
+}

+ 51 - 0
src/main/java/io/renren/modules/app/config/WebMvcConfig.java

@@ -0,0 +1,51 @@
+/**
+ * Copyright (c) 2016-2019 人人开源 All rights reserved.
+ * <p>
+ * https://www.renren.io
+ * <p>
+ * 版权所有,侵权必究!
+ */
+
+package io.renren.modules.app.config;
+
+import io.renren.modules.app.interceptor.AuthorizationInterceptor;
+import io.renren.modules.app.resolver.LoginUserHandlerMethodArgumentResolver;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.web.method.support.HandlerMethodArgumentResolver;
+import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
+import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
+import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
+
+import java.util.List;
+
+/**
+ * MVC配置
+ *
+ * @author Mark 735032128@qq.com
+ */
+@Configuration
+public class WebMvcConfig implements WebMvcConfigurer {
+    @Autowired
+    private AuthorizationInterceptor authorizationInterceptor;
+    @Autowired
+    private LoginUserHandlerMethodArgumentResolver loginUserHandlerMethodArgumentResolver;
+
+    @Override
+    public void addInterceptors(InterceptorRegistry registry) {
+        registry.addInterceptor(authorizationInterceptor).addPathPatterns("/app/**");
+    }
+
+    @Override
+    public void addArgumentResolvers(List<HandlerMethodArgumentResolver> argumentResolvers) {
+        argumentResolvers.add(loginUserHandlerMethodArgumentResolver);
+    }
+
+    /**
+     * 访问根路径默认跳转 index.html页面
+     */
+    @Override
+    public void addViewControllers(ViewControllerRegistry registry) {
+        registry.addViewController("/").setViewName("index.html");
+    }
+}

+ 64 - 0
src/main/java/io/renren/modules/app/controller/AppLoginController.java

@@ -0,0 +1,64 @@
+/**
+ * Copyright (c) 2016-2019 人人开源 All rights reserved.
+ * <p>
+ * https://www.renren.io
+ * <p>
+ * 版权所有,侵权必究!
+ */
+
+package io.renren.modules.app.controller;
+
+
+import io.renren.common.utils.R;
+import io.renren.common.validator.ValidatorUtils;
+import io.renren.modules.app.form.LoginForm;
+import io.renren.modules.app.service.UserService;
+import io.renren.modules.app.utils.JwtUtils;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * APP登录授权
+ *
+ * @author Mark 735032128@qq.com
+ */
+@RestController
+@RequestMapping("/app")
+@Api("APP登录接口")
+public class AppLoginController {
+    @Autowired
+    private UserService userService;
+    @Autowired
+    private JwtUtils jwtUtils;
+
+    /**
+     * 登录
+     */
+    @PostMapping("login")
+    @ApiOperation("登录")
+    public R login(@RequestBody LoginForm form) {
+        //表单校验
+        ValidatorUtils.validateEntity(form);
+
+        //用户登录
+        long userId = userService.login(form);
+
+        //生成token
+        String token = jwtUtils.generateToken(userId);
+
+        Map<String, Object> map = new HashMap<>();
+        map.put("token", token);
+        map.put("expire", jwtUtils.getExpire());
+
+        return R.ok(map);
+    }
+
+}

+ 55 - 0
src/main/java/io/renren/modules/app/controller/AppRegisterController.java

@@ -0,0 +1,55 @@
+/**
+ * Copyright (c) 2016-2019 人人开源 All rights reserved.
+ * <p>
+ * https://www.renren.io
+ * <p>
+ * 版权所有,侵权必究!
+ */
+
+package io.renren.modules.app.controller;
+
+
+import io.renren.common.utils.R;
+import io.renren.common.validator.ValidatorUtils;
+import io.renren.modules.app.entity.UserEntity;
+import io.renren.modules.app.form.RegisterForm;
+import io.renren.modules.app.service.UserService;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import org.apache.commons.codec.digest.DigestUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import java.util.Date;
+
+/**
+ * 注册
+ *
+ * @author Mark 735032128@qq.com
+ */
+@RestController
+@RequestMapping("/app")
+@Api("APP注册接口")
+public class AppRegisterController {
+    @Autowired
+    private UserService userService;
+
+    @PostMapping("register")
+    @ApiOperation("注册")
+    public R register(@RequestBody RegisterForm form) {
+        //表单校验
+        ValidatorUtils.validateEntity(form);
+
+        UserEntity user = new UserEntity();
+        user.setMobile(form.getMobile());
+        user.setUsername(form.getMobile());
+        user.setPassword(DigestUtils.sha256Hex(form.getPassword()));
+        user.setCreateTime(new Date());
+        userService.save(user);
+
+        return R.ok();
+    }
+}

+ 53 - 0
src/main/java/io/renren/modules/app/controller/AppTestController.java

@@ -0,0 +1,53 @@
+/**
+ * Copyright (c) 2016-2019 人人开源 All rights reserved.
+ * <p>
+ * https://www.renren.io
+ * <p>
+ * 版权所有,侵权必究!
+ */
+
+package io.renren.modules.app.controller;
+
+
+import io.renren.common.utils.R;
+import io.renren.modules.app.annotation.Login;
+import io.renren.modules.app.annotation.LoginUser;
+import io.renren.modules.app.entity.UserEntity;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestAttribute;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+/**
+ * APP测试接口
+ *
+ * @author Mark 735032128@qq.com
+ */
+@RestController
+@RequestMapping("/app")
+@Api("APP测试接口")
+public class AppTestController {
+
+    @Login
+    @GetMapping("userInfo")
+    @ApiOperation("获取用户信息")
+    public R userInfo(@LoginUser UserEntity user) {
+        return R.ok().put("user", user);
+    }
+
+    @Login
+    @GetMapping("userId")
+    @ApiOperation("获取用户ID")
+    public R userInfo(@RequestAttribute("userId") Integer userId) {
+        return R.ok().put("userId", userId);
+    }
+
+    @GetMapping("notToken")
+    @ApiOperation("忽略Token验证测试")
+    public R notToken() {
+        return R.ok().put("msg", "无需token也能访问。。。");
+    }
+
+}

+ 23 - 0
src/main/java/io/renren/modules/app/dao/UserDao.java

@@ -0,0 +1,23 @@
+/**
+ * Copyright (c) 2016-2019 人人开源 All rights reserved.
+ * <p>
+ * https://www.renren.io
+ * <p>
+ * 版权所有,侵权必究!
+ */
+
+package io.renren.modules.app.dao;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import io.renren.modules.app.entity.UserEntity;
+import org.apache.ibatis.annotations.Mapper;
+
+/**
+ * 用户
+ *
+ * @author Mark 735032128@qq.com
+ */
+@Mapper
+public interface UserDao extends BaseMapper<UserEntity> {
+
+}

+ 54 - 0
src/main/java/io/renren/modules/app/entity/UserEntity.java

@@ -0,0 +1,54 @@
+/**
+ * Copyright (c) 2016-2019 人人开源 All rights reserved.
+ * <p>
+ * https://www.renren.io
+ * <p>
+ * 版权所有,侵权必究!
+ */
+
+package io.renren.modules.app.entity;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.KeySequence;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Data;
+
+import java.io.Serializable;
+import java.util.Date;
+
+
+/**
+ * 用户
+ *
+ * @author Mark 735032128@qq.com
+ */
+@Data
+@TableName("tb_user")
+@KeySequence(value = "SSY_SEQ")
+public class UserEntity implements Serializable {
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 用户ID
+     */
+    @TableId(type = IdType.INPUT)
+    private Long userId;
+    /**
+     * 用户名
+     */
+    private String username;
+    /**
+     * 手机号
+     */
+    private String mobile;
+    /**
+     * 密码
+     */
+    private String password;
+    /**
+     * 创建时间
+     */
+    private Date createTime;
+
+}

+ 33 - 0
src/main/java/io/renren/modules/app/form/LoginForm.java

@@ -0,0 +1,33 @@
+/**
+ * Copyright (c) 2016-2019 人人开源 All rights reserved.
+ * <p>
+ * https://www.renren.io
+ * <p>
+ * 版权所有,侵权必究!
+ */
+
+package io.renren.modules.app.form;
+
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import javax.validation.constraints.NotBlank;
+
+/**
+ * 登录表单
+ *
+ * @author Mark 735032128@qq.com
+ */
+@Data
+@ApiModel(value = "登录表单")
+public class LoginForm {
+    @ApiModelProperty(value = "手机号")
+    @NotBlank(message = "手机号不能为空")
+    private String mobile;
+
+    @ApiModelProperty(value = "密码")
+    @NotBlank(message = "密码不能为空")
+    private String password;
+
+}

+ 33 - 0
src/main/java/io/renren/modules/app/form/RegisterForm.java

@@ -0,0 +1,33 @@
+/**
+ * Copyright (c) 2016-2019 人人开源 All rights reserved.
+ * <p>
+ * https://www.renren.io
+ * <p>
+ * 版权所有,侵权必究!
+ */
+
+package io.renren.modules.app.form;
+
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import javax.validation.constraints.NotBlank;
+
+/**
+ * 注册表单
+ *
+ * @author Mark 735032128@qq.com
+ */
+@Data
+@ApiModel(value = "注册表单")
+public class RegisterForm {
+    @ApiModelProperty(value = "手机号")
+    @NotBlank(message = "手机号不能为空")
+    private String mobile;
+
+    @ApiModelProperty(value = "密码")
+    @NotBlank(message = "密码不能为空")
+    private String password;
+
+}

+ 72 - 0
src/main/java/io/renren/modules/app/interceptor/AuthorizationInterceptor.java

@@ -0,0 +1,72 @@
+/**
+ * Copyright (c) 2016-2019 人人开源 All rights reserved.
+ * <p>
+ * https://www.renren.io
+ * <p>
+ * 版权所有,侵权必究!
+ */
+
+package io.renren.modules.app.interceptor;
+
+
+import io.jsonwebtoken.Claims;
+import io.renren.common.exception.RRException;
+import io.renren.modules.app.utils.JwtUtils;
+import io.renren.modules.app.annotation.Login;
+import org.apache.commons.lang.StringUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.HttpStatus;
+import org.springframework.stereotype.Component;
+import org.springframework.web.method.HandlerMethod;
+import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+/**
+ * 权限(Token)验证
+ *
+ * @author Mark 735032128@qq.com
+ */
+@Component
+public class AuthorizationInterceptor extends HandlerInterceptorAdapter {
+    @Autowired
+    private JwtUtils jwtUtils;
+
+    public static final String USER_KEY = "userId";
+
+    @Override
+    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
+        Login annotation;
+        if (handler instanceof HandlerMethod) {
+            annotation = ((HandlerMethod) handler).getMethodAnnotation(Login.class);
+        } else {
+            return true;
+        }
+
+        if (annotation == null) {
+            return true;
+        }
+
+        //获取用户凭证
+        String token = request.getHeader(jwtUtils.getHeader());
+        if (StringUtils.isBlank(token)) {
+            token = request.getParameter(jwtUtils.getHeader());
+        }
+
+        //凭证为空
+        if (StringUtils.isBlank(token)) {
+            throw new RRException(jwtUtils.getHeader() + "不能为空", HttpStatus.UNAUTHORIZED.value());
+        }
+
+        Claims claims = jwtUtils.getClaimByToken(token);
+        if (claims == null || jwtUtils.isTokenExpired(claims.getExpiration())) {
+            throw new RRException(jwtUtils.getHeader() + "失效,请重新登录", HttpStatus.UNAUTHORIZED.value());
+        }
+
+        //设置userId到request里,后续根据userId,获取用户信息
+        request.setAttribute(USER_KEY, Long.parseLong(claims.getSubject()));
+
+        return true;
+    }
+}

+ 53 - 0
src/main/java/io/renren/modules/app/resolver/LoginUserHandlerMethodArgumentResolver.java

@@ -0,0 +1,53 @@
+/**
+ * Copyright (c) 2016-2019 人人开源 All rights reserved.
+ * <p>
+ * https://www.renren.io
+ * <p>
+ * 版权所有,侵权必究!
+ */
+
+package io.renren.modules.app.resolver;
+
+import io.renren.modules.app.annotation.LoginUser;
+import io.renren.modules.app.entity.UserEntity;
+import io.renren.modules.app.interceptor.AuthorizationInterceptor;
+import io.renren.modules.app.service.UserService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.core.MethodParameter;
+import org.springframework.stereotype.Component;
+import org.springframework.web.bind.support.WebDataBinderFactory;
+import org.springframework.web.context.request.NativeWebRequest;
+import org.springframework.web.context.request.RequestAttributes;
+import org.springframework.web.method.support.HandlerMethodArgumentResolver;
+import org.springframework.web.method.support.ModelAndViewContainer;
+
+/**
+ * 有@LoginUser注解的方法参数,注入当前登录用户
+ *
+ * @author Mark 735032128@qq.com
+ */
+@Component
+public class LoginUserHandlerMethodArgumentResolver implements HandlerMethodArgumentResolver {
+    @Autowired
+    private UserService userService;
+
+    @Override
+    public boolean supportsParameter(MethodParameter parameter) {
+        return parameter.getParameterType().isAssignableFrom(UserEntity.class) && parameter.hasParameterAnnotation(LoginUser.class);
+    }
+
+    @Override
+    public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer container,
+                                  NativeWebRequest request, WebDataBinderFactory factory) throws Exception {
+        //获取用户ID
+        Object object = request.getAttribute(AuthorizationInterceptor.USER_KEY, RequestAttributes.SCOPE_REQUEST);
+        if (object == null) {
+            return null;
+        }
+
+        //获取用户信息
+        UserEntity user = userService.getById((Long) object);
+
+        return user;
+    }
+}

+ 31 - 0
src/main/java/io/renren/modules/app/service/UserService.java

@@ -0,0 +1,31 @@
+/**
+ * Copyright (c) 2016-2019 人人开源 All rights reserved.
+ * <p>
+ * https://www.renren.io
+ * <p>
+ * 版权所有,侵权必究!
+ */
+
+package io.renren.modules.app.service;
+
+
+import com.baomidou.mybatisplus.extension.service.IService;
+import io.renren.modules.app.entity.UserEntity;
+import io.renren.modules.app.form.LoginForm;
+
+/**
+ * 用户
+ *
+ * @author Mark 735032128@qq.com
+ */
+public interface UserService extends IService<UserEntity> {
+
+    UserEntity queryByMobile(String mobile);
+
+    /**
+     * 用户登录
+     * @param form    登录表单
+     * @return 返回用户ID
+     */
+    long login(LoginForm form);
+}

+ 44 - 0
src/main/java/io/renren/modules/app/service/impl/UserServiceImpl.java

@@ -0,0 +1,44 @@
+/**
+ * Copyright (c) 2016-2019 人人开源 All rights reserved.
+ * <p>
+ * https://www.renren.io
+ * <p>
+ * 版权所有,侵权必究!
+ */
+
+package io.renren.modules.app.service.impl;
+
+
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import io.renren.common.exception.RRException;
+import io.renren.common.validator.Assert;
+import io.renren.modules.app.dao.UserDao;
+import io.renren.modules.app.entity.UserEntity;
+import io.renren.modules.app.form.LoginForm;
+import io.renren.modules.app.service.UserService;
+import org.apache.commons.codec.digest.DigestUtils;
+import org.springframework.stereotype.Service;
+
+
+@Service("userService")
+public class UserServiceImpl extends ServiceImpl<UserDao, UserEntity> implements UserService {
+
+    @Override
+    public UserEntity queryByMobile(String mobile) {
+        return baseMapper.selectOne(new QueryWrapper<UserEntity>().eq("mobile", mobile));
+    }
+
+    @Override
+    public long login(LoginForm form) {
+        UserEntity user = queryByMobile(form.getMobile());
+        Assert.isNull(user, "手机号或密码错误");
+
+        //密码错误
+        if (!user.getPassword().equals(DigestUtils.sha256Hex(form.getPassword()))) {
+            throw new RRException("手机号或密码错误");
+        }
+
+        return user.getUserId();
+    }
+}

+ 95 - 0
src/main/java/io/renren/modules/app/utils/JwtUtils.java

@@ -0,0 +1,95 @@
+/**
+ * Copyright (c) 2016-2019 人人开源 All rights reserved.
+ * <p>
+ * https://www.renren.io
+ * <p>
+ * 版权所有,侵权必究!
+ */
+
+package io.renren.modules.app.utils;
+
+import io.jsonwebtoken.Claims;
+import io.jsonwebtoken.Jwts;
+import io.jsonwebtoken.SignatureAlgorithm;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.stereotype.Component;
+
+import java.util.Date;
+
+/**
+ * jwt工具类
+ *
+ * @author Mark 735032128@qq.com
+ */
+@ConfigurationProperties(prefix = "renren.jwt")
+@Component
+public class JwtUtils {
+    private Logger logger = LoggerFactory.getLogger(getClass());
+
+    private String secret;
+    private long expire;
+    private String header;
+
+    /**
+     * 生成jwt token
+     */
+    public String generateToken(long userId) {
+        Date nowDate = new Date();
+        //过期时间
+        Date expireDate = new Date(nowDate.getTime() + expire * 1000);
+
+        return Jwts.builder()
+                .setHeaderParam("typ", "JWT")
+                .setSubject(userId + "")
+                .setIssuedAt(nowDate)
+                .setExpiration(expireDate)
+                .signWith(SignatureAlgorithm.HS512, secret)
+                .compact();
+    }
+
+    public Claims getClaimByToken(String token) {
+        try {
+            return Jwts.parser()
+                    .setSigningKey(secret)
+                    .parseClaimsJws(token)
+                    .getBody();
+        } catch (Exception e) {
+            logger.debug("validate is token error ", e);
+            return null;
+        }
+    }
+
+    /**
+     * token是否过期
+     * @return true:过期
+     */
+    public boolean isTokenExpired(Date expiration) {
+        return expiration.before(new Date());
+    }
+
+    public String getSecret() {
+        return secret;
+    }
+
+    public void setSecret(String secret) {
+        this.secret = secret;
+    }
+
+    public long getExpire() {
+        return expire;
+    }
+
+    public void setExpire(long expire) {
+        this.expire = expire;
+    }
+
+    public String getHeader() {
+        return header;
+    }
+
+    public void setHeader(String header) {
+        this.header = header;
+    }
+}

+ 90 - 0
src/main/java/io/renren/modules/aspen/controller/TAlarmstatisticsDayController.java

@@ -0,0 +1,90 @@
+package io.renren.modules.aspen.controller;
+
+import java.util.Arrays;
+import java.util.Map;
+
+import org.apache.shiro.authz.annotation.RequiresPermissions;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.RestController;
+
+import io.renren.modules.aspen.entity.TAlarmstatisticsDayEntity;
+import io.renren.modules.aspen.service.TAlarmstatisticsDayService;
+import io.renren.common.utils.PageUtils;
+import io.renren.common.utils.R;
+
+
+
+/**
+ * 报警统计表(当天)
+ *
+ * @author chenshun
+ * @email sunlightcs@gmail.com
+ * @date 2021-05-11 16:13:06
+ */
+@RestController
+@RequestMapping("aspen/talarmstatisticsday")
+public class TAlarmstatisticsDayController {
+    @Autowired
+    private TAlarmstatisticsDayService tAlarmstatisticsDayService;
+
+    /**
+     * 列表
+     */
+    @RequestMapping("/list")
+    @RequiresPermissions("aspen:talarmstatisticsday:list")
+    public R list(@RequestParam Map<String, Object> params){
+        PageUtils page = tAlarmstatisticsDayService.queryPage(params);
+
+        return R.ok().put("page", page);
+    }
+
+
+    /**
+     * 信息
+     */
+    @RequestMapping("/info/{id}")
+    @RequiresPermissions("aspen:talarmstatisticsday:info")
+    public R info(@PathVariable("id") Integer id){
+		TAlarmstatisticsDayEntity tAlarmstatisticsDay = tAlarmstatisticsDayService.getById(id);
+
+        return R.ok().put("tAlarmstatisticsDay", tAlarmstatisticsDay);
+    }
+
+    /**
+     * 保存
+     */
+    @RequestMapping("/save")
+    @RequiresPermissions("aspen:talarmstatisticsday:save")
+    public R save(@RequestBody TAlarmstatisticsDayEntity tAlarmstatisticsDay){
+		tAlarmstatisticsDayService.save(tAlarmstatisticsDay);
+
+        return R.ok();
+    }
+
+    /**
+     * 修改
+     */
+    @RequestMapping("/update")
+    @RequiresPermissions("aspen:talarmstatisticsday:update")
+    public R update(@RequestBody TAlarmstatisticsDayEntity tAlarmstatisticsDay){
+		tAlarmstatisticsDayService.updateById(tAlarmstatisticsDay);
+
+        return R.ok();
+    }
+
+    /**
+     * 删除
+     */
+    @RequestMapping("/delete")
+    @RequiresPermissions("aspen:talarmstatisticsday:delete")
+    public R delete(@RequestBody Integer[] ids){
+		tAlarmstatisticsDayService.removeByIds(Arrays.asList(ids));
+
+        return R.ok();
+    }
+
+}

+ 17 - 0
src/main/java/io/renren/modules/aspen/dao/TAlarmstatisticsDayDao.java

@@ -0,0 +1,17 @@
+package io.renren.modules.aspen.dao;
+
+import io.renren.modules.aspen.entity.TAlarmstatisticsDayEntity;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import org.apache.ibatis.annotations.Mapper;
+
+/**
+ * 报警统计表(当天)
+ * 
+ * @author chenshun
+ * @email sunlightcs@gmail.com
+ * @date 2021-05-11 16:13:06
+ */
+@Mapper
+public interface TAlarmstatisticsDayDao extends BaseMapper<TAlarmstatisticsDayEntity> {
+	
+}

+ 80 - 0
src/main/java/io/renren/modules/aspen/entity/TAlarmstatisticsDayEntity.java

@@ -0,0 +1,80 @@
+package io.renren.modules.aspen.entity;
+
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+
+import java.io.Serializable;
+import java.util.Date;
+import lombok.Data;
+
+/**
+ * 报警统计表(当天)
+ * 
+ * @author chenshun
+ * @email sunlightcs@gmail.com
+ * @date 2021-05-11 16:13:06
+ */
+@Data
+@TableName("T_ALARMSTATISTICS_DAY")
+public class TAlarmstatisticsDayEntity implements Serializable {
+	private static final long serialVersionUID = 1L;
+
+	/**
+	 * 唯一标识ID
+	 */
+	@TableId
+	private Integer id;
+	/**
+	 * 装置名称
+	 */
+	private String plantCode;
+	/**
+	 * 内容
+	 */
+	private String modulename;
+	/**
+	 * 等级
+	 */
+	private String levelname;
+	/**
+	 * 次数
+	 */
+	private Integer count;
+	/**
+	 * 录入日期
+	 */
+	private Date inputdate;
+	/**
+	 * ANALYSIS
+	 */
+	private String analysis;
+	/**
+	 * 状态
+	 */
+	private Integer delFlag;
+	/**
+	 * 创建人
+	 */
+	private String createrCode;
+	/**
+	 * 创建日期
+	 */
+	private Date createdate;
+	/**
+	 * 修改人
+	 */
+	private String updaterCode;
+	/**
+	 * 修改时间
+	 */
+	private Date updatedate;
+	/**
+	 * 备注
+	 */
+	private String remarks;
+	/**
+	 * 部门编号
+	 */
+	private Integer deptId;
+
+}

+ 20 - 0
src/main/java/io/renren/modules/aspen/service/TAlarmstatisticsDayService.java

@@ -0,0 +1,20 @@
+package io.renren.modules.aspen.service;
+
+import com.baomidou.mybatisplus.extension.service.IService;
+import io.renren.common.utils.PageUtils;
+import io.renren.modules.aspen.entity.TAlarmstatisticsDayEntity;
+
+import java.util.Map;
+
+/**
+ * 报警统计表(当天)
+ *
+ * @author chenshun
+ * @email sunlightcs@gmail.com
+ * @date 2021-05-11 16:13:06
+ */
+public interface TAlarmstatisticsDayService extends IService<TAlarmstatisticsDayEntity> {
+
+    PageUtils queryPage(Map<String, Object> params);
+}
+

+ 29 - 0
src/main/java/io/renren/modules/aspen/service/impl/TAlarmstatisticsDayServiceImpl.java

@@ -0,0 +1,29 @@
+package io.renren.modules.aspen.service.impl;
+
+import org.springframework.stereotype.Service;
+import java.util.Map;
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import io.renren.common.utils.PageUtils;
+import io.renren.common.utils.Query;
+
+import io.renren.modules.aspen.dao.TAlarmstatisticsDayDao;
+import io.renren.modules.aspen.entity.TAlarmstatisticsDayEntity;
+import io.renren.modules.aspen.service.TAlarmstatisticsDayService;
+
+
+@Service("tAlarmstatisticsDayService")
+public class TAlarmstatisticsDayServiceImpl extends ServiceImpl<TAlarmstatisticsDayDao, TAlarmstatisticsDayEntity> implements TAlarmstatisticsDayService {
+
+    @Override
+    public PageUtils queryPage(Map<String, Object> params) {
+        IPage<TAlarmstatisticsDayEntity> page = this.page(
+                new Query<TAlarmstatisticsDayEntity>().getPage(params),
+                new QueryWrapper<TAlarmstatisticsDayEntity>()
+        );
+
+        return new PageUtils(page);
+    }
+
+}

+ 54 - 0
src/main/java/io/renren/modules/common/AspenController.java

@@ -0,0 +1,54 @@
+package io.renren.modules.common;
+
+import com.alibaba.fastjson.JSON;
+import io.renren.common.utils.ExcelUtils;
+import io.renren.modules.aspen.entity.TAlarmstatisticsDayEntity;
+import io.renren.modules.aspen.service.TAlarmstatisticsDayService;
+import io.renren.modules.sys.controller.AbstractController;
+import io.renren.modules.sys.entity.SysMenuEntity;
+import io.renren.modules.sys.service.SysMenuService;
+import org.apache.poi.ss.usermodel.Cell;
+import org.apache.poi.ss.usermodel.Row;
+import org.apache.poi.ss.usermodel.Sheet;
+import org.apache.poi.ss.usermodel.Workbook;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.scheduling.annotation.EnableScheduling;
+import org.springframework.scheduling.annotation.Scheduled;
+import org.springframework.stereotype.Component;
+
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.List;
+@Component
+@Configuration      //1.主要用于标记配置类,兼备Component的效果。
+@EnableScheduling   // 2.开启定时任务
+public class AspenController extends AbstractController {
+
+    @Autowired
+    private SysMenuService sysMenuService;
+    @Autowired
+    private TAlarmstatisticsDayService tAlarmstatisticsDayService;
+
+    @Scheduled(cron = "0/9 * * * * ?")
+    public void getExcelData(){
+        Workbook workbook = ExcelUtils.getWorkBook("D://ssyFile/K300.xlsm");
+        Sheet sheet = workbook.getSheetAt(0);
+        int rowNum = sheet.getPhysicalNumberOfRows();
+        for (int i = 1; i < rowNum; i++) {
+            Row row = sheet.getRow(i);
+            int cellNum = row.getPhysicalNumberOfCells();
+            for (int j = 0; j < cellNum; j++) {
+                Cell cell = row.getCell(j);
+                String cellValue = ExcelUtils.getCellValue(cell);
+                if (j == 0) {
+                    logger.info(cellValue + "第一列");
+                }else if (j ==1) {
+                    logger.info(cellValue + "第二列");
+                }
+            }
+        }
+        List<TAlarmstatisticsDayEntity> menuList = tAlarmstatisticsDayService.list();
+        logger.info(JSON.toJSONString(menuList));
+    }
+}

+ 62 - 0
src/main/java/io/renren/modules/oss/cloud/AliyunCloudStorageService.java

@@ -0,0 +1,62 @@
+/**
+ * Copyright (c) 2016-2019 人人开源 All rights reserved.
+ * <p>
+ * https://www.renren.io
+ * <p>
+ * 版权所有,侵权必究!
+ */
+
+package io.renren.modules.oss.cloud;
+
+import com.aliyun.oss.OSSClient;
+import io.renren.common.exception.RRException;
+
+import java.io.ByteArrayInputStream;
+import java.io.InputStream;
+
+/**
+ * 阿里云存储
+ *
+ * @author Mark 735032128@qq.com
+ */
+public class AliyunCloudStorageService extends CloudStorageService {
+    private OSSClient client;
+
+    public AliyunCloudStorageService(CloudStorageConfig config) {
+        this.config = config;
+
+        //初始化
+        init();
+    }
+
+    private void init() {
+        client = new OSSClient(config.getAliyunEndPoint(), config.getAliyunAccessKeyId(),
+                config.getAliyunAccessKeySecret());
+    }
+
+    @Override
+    public String upload(byte[] data, String path) {
+        return upload(new ByteArrayInputStream(data), path);
+    }
+
+    @Override
+    public String upload(InputStream inputStream, String path) {
+        try {
+            client.putObject(config.getAliyunBucketName(), path, inputStream);
+        } catch (Exception e) {
+            throw new RRException("上传文件失败,请检查配置信息", e);
+        }
+
+        return config.getAliyunDomain() + "/" + path;
+    }
+
+    @Override
+    public String uploadSuffix(byte[] data, String suffix) {
+        return upload(data, getPath(config.getAliyunPrefix(), suffix));
+    }
+
+    @Override
+    public String uploadSuffix(InputStream inputStream, String suffix) {
+        return upload(inputStream, getPath(config.getAliyunPrefix(), suffix));
+    }
+}

+ 94 - 0
src/main/java/io/renren/modules/oss/cloud/CloudStorageConfig.java

@@ -0,0 +1,94 @@
+/**
+ * Copyright (c) 2016-2019 人人开源 All rights reserved.
+ * <p>
+ * https://www.renren.io
+ * <p>
+ * 版权所有,侵权必究!
+ */
+
+package io.renren.modules.oss.cloud;
+
+
+import io.renren.common.validator.group.AliyunGroup;
+import io.renren.common.validator.group.QcloudGroup;
+import io.renren.common.validator.group.QiniuGroup;
+import lombok.Data;
+import org.hibernate.validator.constraints.Range;
+import org.hibernate.validator.constraints.URL;
+
+import javax.validation.constraints.NotBlank;
+import javax.validation.constraints.NotNull;
+import java.io.Serializable;
+
+/**
+ * 云存储配置信息
+ *
+ * @author Mark 735032128@qq.com
+ */
+@Data
+public class CloudStorageConfig implements Serializable {
+    private static final long serialVersionUID = 1L;
+
+    //类型 1:七牛  2:阿里云  3:腾讯云
+    @Range(min = 1, max = 3, message = "类型错误")
+    private Integer type;
+
+    //七牛绑定的域名
+    @NotBlank(message = "七牛绑定的域名不能为空", groups = QiniuGroup.class)
+    @URL(message = "七牛绑定的域名格式不正确", groups = QiniuGroup.class)
+    private String qiniuDomain;
+    //七牛路径前缀
+    private String qiniuPrefix;
+    //七牛ACCESS_KEY
+    @NotBlank(message = "七牛AccessKey不能为空", groups = QiniuGroup.class)
+    private String qiniuAccessKey;
+    //七牛SECRET_KEY
+    @NotBlank(message = "七牛SecretKey不能为空", groups = QiniuGroup.class)
+    private String qiniuSecretKey;
+    //七牛存储空间名
+    @NotBlank(message = "七牛空间名不能为空", groups = QiniuGroup.class)
+    private String qiniuBucketName;
+
+    //阿里云绑定的域名
+    @NotBlank(message = "阿里云绑定的域名不能为空", groups = AliyunGroup.class)
+    @URL(message = "阿里云绑定的域名格式不正确", groups = AliyunGroup.class)
+    private String aliyunDomain;
+    //阿里云路径前缀
+    private String aliyunPrefix;
+    //阿里云EndPoint
+    @NotBlank(message = "阿里云EndPoint不能为空", groups = AliyunGroup.class)
+    private String aliyunEndPoint;
+    //阿里云AccessKeyId
+    @NotBlank(message = "阿里云AccessKeyId不能为空", groups = AliyunGroup.class)
+    private String aliyunAccessKeyId;
+    //阿里云AccessKeySecret
+    @NotBlank(message = "阿里云AccessKeySecret不能为空", groups = AliyunGroup.class)
+    private String aliyunAccessKeySecret;
+    //阿里云BucketName
+    @NotBlank(message = "阿里云BucketName不能为空", groups = AliyunGroup.class)
+    private String aliyunBucketName;
+
+    //腾讯云绑定的域名
+    @NotBlank(message = "腾讯云绑定的域名不能为空", groups = QcloudGroup.class)
+    @URL(message = "腾讯云绑定的域名格式不正确", groups = QcloudGroup.class)
+    private String qcloudDomain;
+    //腾讯云路径前缀
+    private String qcloudPrefix;
+    //腾讯云AppId
+    @NotNull(message = "腾讯云AppId不能为空", groups = QcloudGroup.class)
+    private Integer qcloudAppId;
+    //腾讯云SecretId
+    @NotBlank(message = "腾讯云SecretId不能为空", groups = QcloudGroup.class)
+    private String qcloudSecretId;
+    //腾讯云SecretKey
+    @NotBlank(message = "腾讯云SecretKey不能为空", groups = QcloudGroup.class)
+    private String qcloudSecretKey;
+    //腾讯云BucketName
+    @NotBlank(message = "腾讯云BucketName不能为空", groups = QcloudGroup.class)
+    private String qcloudBucketName;
+    //腾讯云COS所属地区
+    @NotBlank(message = "所属地区不能为空", groups = QcloudGroup.class)
+    private String qcloudRegion;
+
+
+}

+ 78 - 0
src/main/java/io/renren/modules/oss/cloud/CloudStorageService.java

@@ -0,0 +1,78 @@
+/**
+ * Copyright (c) 2016-2019 人人开源 All rights reserved.
+ * <p>
+ * https://www.renren.io
+ * <p>
+ * 版权所有,侵权必究!
+ */
+
+package io.renren.modules.oss.cloud;
+
+import io.renren.common.utils.DateUtils;
+import org.apache.commons.lang.StringUtils;
+
+import java.io.InputStream;
+import java.util.Date;
+import java.util.UUID;
+
+/**
+ * 云存储(支持七牛、阿里云、腾讯云、又拍云)
+ *
+ * @author Mark 735032128@qq.com
+ */
+public abstract class CloudStorageService {
+    /** 云存储配置信息 */
+    CloudStorageConfig config;
+
+    /**
+     * 文件路径
+     * @param prefix 前缀
+     * @param suffix 后缀
+     * @return 返回上传路径
+     */
+    public String getPath(String prefix, String suffix) {
+        //生成uuid
+        String uuid = UUID.randomUUID().toString().replaceAll("-", "");
+        //文件路径
+        String path = DateUtils.format(new Date(), "yyyyMMdd") + "/" + uuid;
+
+        if (StringUtils.isNotBlank(prefix)) {
+            path = prefix + "/" + path;
+        }
+
+        return path + suffix;
+    }
+
+    /**
+     * 文件上传
+     * @param data    文件字节数组
+     * @param path    文件路径,包含文件名
+     * @return 返回http地址
+     */
+    public abstract String upload(byte[] data, String path);
+
+    /**
+     * 文件上传
+     * @param data     文件字节数组
+     * @param suffix   后缀
+     * @return 返回http地址
+     */
+    public abstract String uploadSuffix(byte[] data, String suffix);
+
+    /**
+     * 文件上传
+     * @param inputStream   字节流
+     * @param path          文件路径,包含文件名
+     * @return 返回http地址
+     */
+    public abstract String upload(InputStream inputStream, String path);
+
+    /**
+     * 文件上传
+     * @param inputStream  字节流
+     * @param suffix       后缀
+     * @return 返回http地址
+     */
+    public abstract String uploadSuffix(InputStream inputStream, String suffix);
+
+}

+ 44 - 0
src/main/java/io/renren/modules/oss/cloud/OSSFactory.java

@@ -0,0 +1,44 @@
+/**
+ * Copyright (c) 2016-2019 人人开源 All rights reserved.
+ * <p>
+ * https://www.renren.io
+ * <p>
+ * 版权所有,侵权必究!
+ */
+
+package io.renren.modules.oss.cloud;
+
+
+import io.renren.common.utils.ConfigConstant;
+import io.renren.common.utils.Constant;
+import io.renren.common.utils.SpringContextUtils;
+import io.renren.modules.sys.service.SysConfigService;
+
+/**
+ * 文件上传Factory
+ *
+ * @author Mark 735032128@qq.com
+ */
+public final class OSSFactory {
+    private static SysConfigService sysConfigService;
+
+    static {
+        OSSFactory.sysConfigService = (SysConfigService) SpringContextUtils.getBean("sysConfigService");
+    }
+
+    public static CloudStorageService build() {
+        //获取云存储配置信息
+        CloudStorageConfig config = sysConfigService.getConfigObject(ConfigConstant.CLOUD_STORAGE_CONFIG_KEY, CloudStorageConfig.class);
+
+        if (config.getType() == Constant.CloudService.QINIU.getValue()) {
+            return new QiniuCloudStorageService(config);
+        } else if (config.getType() == Constant.CloudService.ALIYUN.getValue()) {
+            return new AliyunCloudStorageService(config);
+        } else if (config.getType() == Constant.CloudService.QCLOUD.getValue()) {
+            return new QcloudCloudStorageService(config);
+        }
+
+        return null;
+    }
+
+}

+ 88 - 0
src/main/java/io/renren/modules/oss/cloud/QcloudCloudStorageService.java

@@ -0,0 +1,88 @@
+/**
+ * Copyright (c) 2016-2019 人人开源 All rights reserved.
+ * <p>
+ * https://www.renren.io
+ * <p>
+ * 版权所有,侵权必究!
+ */
+
+package io.renren.modules.oss.cloud;
+
+
+import com.alibaba.fastjson.JSONObject;
+import com.qcloud.cos.COSClient;
+import com.qcloud.cos.ClientConfig;
+import com.qcloud.cos.request.UploadFileRequest;
+import com.qcloud.cos.sign.Credentials;
+import io.renren.common.exception.RRException;
+import org.apache.commons.io.IOUtils;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+/**
+ * 腾讯云存储
+ *
+ * @author Mark 735032128@qq.com
+ */
+public class QcloudCloudStorageService extends CloudStorageService {
+    private COSClient client;
+
+    public QcloudCloudStorageService(CloudStorageConfig config) {
+        this.config = config;
+
+        //初始化
+        init();
+    }
+
+    private void init() {
+        Credentials credentials = new Credentials(config.getQcloudAppId(), config.getQcloudSecretId(),
+                config.getQcloudSecretKey());
+
+        //初始化客户端配置
+        ClientConfig clientConfig = new ClientConfig();
+        //设置bucket所在的区域,华南:gz 华北:tj 华东:sh
+        clientConfig.setRegion(config.getQcloudRegion());
+
+        client = new COSClient(clientConfig, credentials);
+    }
+
+    @Override
+    public String upload(byte[] data, String path) {
+        //腾讯云必需要以"/"开头
+        if (!path.startsWith("/")) {
+            path = "/" + path;
+        }
+
+        //上传到腾讯云
+        UploadFileRequest request = new UploadFileRequest(config.getQcloudBucketName(), path, data);
+        String response = client.uploadFile(request);
+
+        JSONObject jsonObject = JSONObject.parseObject(response);
+        if (jsonObject.getInteger("code") != 0) {
+            throw new RRException("文件上传失败," + jsonObject.getString("message"));
+        }
+
+        return config.getQcloudDomain() + path;
+    }
+
+    @Override
+    public String upload(InputStream inputStream, String path) {
+        try {
+            byte[] data = IOUtils.toByteArray(inputStream);
+            return this.upload(data, path);
+        } catch (IOException e) {
+            throw new RRException("上传文件失败", e);
+        }
+    }
+
+    @Override
+    public String uploadSuffix(byte[] data, String suffix) {
+        return upload(data, getPath(config.getQcloudPrefix(), suffix));
+    }
+
+    @Override
+    public String uploadSuffix(InputStream inputStream, String suffix) {
+        return upload(inputStream, getPath(config.getQcloudPrefix(), suffix));
+    }
+}

+ 77 - 0
src/main/java/io/renren/modules/oss/cloud/QiniuCloudStorageService.java

@@ -0,0 +1,77 @@
+/**
+ * Copyright (c) 2016-2019 人人开源 All rights reserved.
+ * <p>
+ * https://www.renren.io
+ * <p>
+ * 版权所有,侵权必究!
+ */
+
+package io.renren.modules.oss.cloud;
+
+import com.qiniu.common.Zone;
+import com.qiniu.http.Response;
+import com.qiniu.storage.Configuration;
+import com.qiniu.storage.UploadManager;
+import com.qiniu.util.Auth;
+import io.renren.common.exception.RRException;
+import org.apache.commons.io.IOUtils;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+/**
+ * 七牛云存储
+ *
+ * @author Mark 735032128@qq.com
+ */
+public class QiniuCloudStorageService extends CloudStorageService {
+    private UploadManager uploadManager;
+    private String token;
+
+    public QiniuCloudStorageService(CloudStorageConfig config) {
+        this.config = config;
+
+        //初始化
+        init();
+    }
+
+    private void init() {
+        uploadManager = new UploadManager(new Configuration(Zone.autoZone()));
+        token = Auth.create(config.getQiniuAccessKey(), config.getQiniuSecretKey()).
+                uploadToken(config.getQiniuBucketName());
+    }
+
+    @Override
+    public String upload(byte[] data, String path) {
+        try {
+            Response res = uploadManager.put(data, path, token);
+            if (!res.isOK()) {
+                throw new RuntimeException("上传七牛出错:" + res.toString());
+            }
+        } catch (Exception e) {
+            throw new RRException("上传文件失败,请核对七牛配置信息", e);
+        }
+
+        return config.getQiniuDomain() + "/" + path;
+    }
+
+    @Override
+    public String upload(InputStream inputStream, String path) {
+        try {
+            byte[] data = IOUtils.toByteArray(inputStream);
+            return this.upload(data, path);
+        } catch (IOException e) {
+            throw new RRException("上传文件失败", e);
+        }
+    }
+
+    @Override
+    public String uploadSuffix(byte[] data, String suffix) {
+        return upload(data, getPath(config.getQiniuPrefix(), suffix));
+    }
+
+    @Override
+    public String uploadSuffix(InputStream inputStream, String suffix) {
+        return upload(inputStream, getPath(config.getQiniuPrefix(), suffix));
+    }
+}

+ 135 - 0
src/main/java/io/renren/modules/oss/controller/SysOssController.java

@@ -0,0 +1,135 @@
+/**
+ * Copyright (c) 2016-2019 人人开源 All rights reserved.
+ * <p>
+ * https://www.renren.io
+ * <p>
+ * 版权所有,侵权必究!
+ */
+
+package io.renren.modules.oss.controller;
+
+import com.google.gson.Gson;
+import io.renren.common.exception.RRException;
+import io.renren.common.utils.ConfigConstant;
+import io.renren.common.utils.Constant;
+import io.renren.common.utils.PageUtils;
+import io.renren.common.utils.R;
+import io.renren.common.validator.ValidatorUtils;
+import io.renren.common.validator.group.AliyunGroup;
+import io.renren.common.validator.group.QcloudGroup;
+import io.renren.common.validator.group.QiniuGroup;
+import io.renren.modules.oss.cloud.CloudStorageConfig;
+import io.renren.modules.oss.cloud.OSSFactory;
+import io.renren.modules.oss.entity.SysOssEntity;
+import io.renren.modules.oss.service.SysOssService;
+import io.renren.modules.sys.service.SysConfigService;
+import org.apache.shiro.authz.annotation.RequiresPermissions;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.*;
+import org.springframework.web.multipart.MultipartFile;
+
+import java.util.Arrays;
+import java.util.Date;
+import java.util.Map;
+
+/**
+ * 文件上传
+ *
+ * @author Mark 735032128@qq.com
+ */
+@RestController
+@RequestMapping("sys/oss")
+public class SysOssController {
+    @Autowired
+    private SysOssService sysOssService;
+    @Autowired
+    private SysConfigService sysConfigService;
+
+    private final static String KEY = ConfigConstant.CLOUD_STORAGE_CONFIG_KEY;
+
+    /**
+     * 列表
+     */
+    @GetMapping("/list")
+    @RequiresPermissions("sys:oss:all")
+    public R list(@RequestParam Map<String, Object> params) {
+        PageUtils page = sysOssService.queryPage(params);
+
+        return R.ok().put("page", page);
+    }
+
+
+    /**
+     * 云存储配置信息
+     */
+    @GetMapping("/config")
+    @RequiresPermissions("sys:oss:all")
+    public R config() {
+        CloudStorageConfig config = sysConfigService.getConfigObject(KEY, CloudStorageConfig.class);
+
+        return R.ok().put("config", config);
+    }
+
+
+    /**
+     * 保存云存储配置信息
+     */
+    @PostMapping("/saveConfig")
+    @RequiresPermissions("sys:oss:all")
+    public R saveConfig(@RequestBody CloudStorageConfig config) {
+        //校验类型
+        ValidatorUtils.validateEntity(config);
+
+        if (config.getType() == Constant.CloudService.QINIU.getValue()) {
+            //校验七牛数据
+            ValidatorUtils.validateEntity(config, QiniuGroup.class);
+        } else if (config.getType() == Constant.CloudService.ALIYUN.getValue()) {
+            //校验阿里云数据
+            ValidatorUtils.validateEntity(config, AliyunGroup.class);
+        } else if (config.getType() == Constant.CloudService.QCLOUD.getValue()) {
+            //校验腾讯云数据
+            ValidatorUtils.validateEntity(config, QcloudGroup.class);
+        }
+
+        sysConfigService.updateValueByKey(KEY, new Gson().toJson(config));
+
+        return R.ok();
+    }
+
+
+    /**
+     * 上传文件
+     */
+    @PostMapping("/upload")
+    @RequiresPermissions("sys:oss:all")
+    public R upload(@RequestParam("file") MultipartFile file) throws Exception {
+        if (file.isEmpty()) {
+            throw new RRException("上传文件不能为空");
+        }
+
+        //上传文件
+        String suffix = file.getOriginalFilename().substring(file.getOriginalFilename().lastIndexOf("."));
+        String url = OSSFactory.build().uploadSuffix(file.getBytes(), suffix);
+
+        //保存文件信息
+        SysOssEntity ossEntity = new SysOssEntity();
+        ossEntity.setUrl(url);
+        ossEntity.setCreateDate(new Date());
+        sysOssService.save(ossEntity);
+
+        return R.ok().put("url", url);
+    }
+
+
+    /**
+     * 删除
+     */
+    @PostMapping("/delete")
+    @RequiresPermissions("sys:oss:all")
+    public R delete(@RequestBody Long[] ids) {
+        sysOssService.removeByIds(Arrays.asList(ids));
+
+        return R.ok();
+    }
+
+}

+ 23 - 0
src/main/java/io/renren/modules/oss/dao/SysOssDao.java

@@ -0,0 +1,23 @@
+/**
+ * Copyright (c) 2016-2019 人人开源 All rights reserved.
+ * <p>
+ * https://www.renren.io
+ * <p>
+ * 版权所有,侵权必究!
+ */
+
+package io.renren.modules.oss.dao;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import io.renren.modules.oss.entity.SysOssEntity;
+import org.apache.ibatis.annotations.Mapper;
+
+/**
+ * 文件上传
+ *
+ * @author Mark 735032128@qq.com
+ */
+@Mapper
+public interface SysOssDao extends BaseMapper<SysOssEntity> {
+
+}

+ 39 - 0
src/main/java/io/renren/modules/oss/entity/SysOssEntity.java

@@ -0,0 +1,39 @@
+/**
+ * Copyright (c) 2016-2019 人人开源 All rights reserved.
+ * <p>
+ * https://www.renren.io
+ * <p>
+ * 版权所有,侵权必究!
+ */
+
+package io.renren.modules.oss.entity;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.KeySequence;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Data;
+
+import java.io.Serializable;
+import java.util.Date;
+
+
+/**
+ * 文件上传
+ *
+ * @author Mark 735032128@qq.com
+ */
+@Data
+@TableName("sys_oss")
+@KeySequence(value = "SSY_SEQ")
+public class SysOssEntity implements Serializable {
+    private static final long serialVersionUID = 1L;
+
+    @TableId(type = IdType.INPUT)
+    private Long id;
+    //URL地址
+    private String url;
+    //创建时间
+    private Date createDate;
+
+}

+ 25 - 0
src/main/java/io/renren/modules/oss/service/SysOssService.java

@@ -0,0 +1,25 @@
+/**
+ * Copyright (c) 2016-2019 人人开源 All rights reserved.
+ * <p>
+ * https://www.renren.io
+ * <p>
+ * 版权所有,侵权必究!
+ */
+
+package io.renren.modules.oss.service;
+
+import com.baomidou.mybatisplus.extension.service.IService;
+import io.renren.common.utils.PageUtils;
+import io.renren.modules.oss.entity.SysOssEntity;
+
+import java.util.Map;
+
+/**
+ * 文件上传
+ *
+ * @author Mark 735032128@qq.com
+ */
+public interface SysOssService extends IService<SysOssEntity> {
+
+    PageUtils queryPage(Map<String, Object> params);
+}

+ 35 - 0
src/main/java/io/renren/modules/oss/service/impl/SysOssServiceImpl.java

@@ -0,0 +1,35 @@
+/**
+ * Copyright (c) 2016-2019 人人开源 All rights reserved.
+ * <p>
+ * https://www.renren.io
+ * <p>
+ * 版权所有,侵权必究!
+ */
+
+package io.renren.modules.oss.service.impl;
+
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import io.renren.common.utils.PageUtils;
+import io.renren.common.utils.Query;
+import io.renren.modules.oss.dao.SysOssDao;
+import io.renren.modules.oss.entity.SysOssEntity;
+import io.renren.modules.oss.service.SysOssService;
+import org.springframework.stereotype.Service;
+
+import java.util.Map;
+
+
+@Service("sysOssService")
+public class SysOssServiceImpl extends ServiceImpl<SysOssDao, SysOssEntity> implements SysOssService {
+
+    @Override
+    public PageUtils queryPage(Map<String, Object> params) {
+        IPage<SysOssEntity> page = this.page(
+                new Query<SysOssEntity>().getPage(params)
+        );
+
+        return new PageUtils(page);
+    }
+
+}

+ 31 - 0
src/main/java/io/renren/modules/sys/controller/AbstractController.java

@@ -0,0 +1,31 @@
+/**
+ * Copyright (c) 2016-2019 人人开源 All rights reserved.
+ * <p>
+ * https://www.renren.io
+ * <p>
+ * 版权所有,侵权必究!
+ */
+
+package io.renren.modules.sys.controller;
+
+import io.renren.modules.sys.entity.SysUserEntity;
+import org.apache.shiro.SecurityUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Controller公共组件
+ *
+ * @author Mark 735032128@qq.com
+ */
+public abstract class AbstractController {
+    protected Logger logger = LoggerFactory.getLogger(getClass());
+
+    protected SysUserEntity getUser() {
+        return (SysUserEntity) SecurityUtils.getSubject().getPrincipal();
+    }
+
+    protected Long getUserId() {
+        return getUser().getUserId();
+    }
+}

+ 22 - 0
src/main/java/io/renren/modules/sys/controller/GetPwdController.java

@@ -0,0 +1,22 @@
+package io.renren.modules.sys.controller;
+
+import org.jasypt.encryption.StringEncryptor;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+
+@Controller
+@RequestMapping("/getpwd")
+public class GetPwdController {
+    @Autowired
+    StringEncryptor encryptor;
+
+    @GetMapping("/dataBase")
+    public void test() {
+        String username = encryptor.encrypt("");
+        System.out.println(username);
+        String password = encryptor.encrypt("");
+        System.out.println(password);
+    }
+}

+ 98 - 0
src/main/java/io/renren/modules/sys/controller/SysConfigController.java

@@ -0,0 +1,98 @@
+/**
+ * Copyright (c) 2016-2019 人人开源 All rights reserved.
+ * <p>
+ * https://www.renren.io
+ * <p>
+ * 版权所有,侵权必究!
+ */
+
+package io.renren.modules.sys.controller;
+
+
+import io.renren.common.annotation.SysLog;
+import io.renren.common.utils.PageUtils;
+import io.renren.common.utils.R;
+import io.renren.common.validator.ValidatorUtils;
+import io.renren.modules.sys.entity.SysConfigEntity;
+import io.renren.modules.sys.service.SysConfigService;
+import org.apache.shiro.authz.annotation.RequiresPermissions;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.Map;
+
+/**
+ * 系统配置信息
+ *
+ * @author Mark 735032128@qq.com
+ */
+@RestController
+@RequestMapping("/sys/config")
+public class SysConfigController extends AbstractController {
+    @Autowired
+    private SysConfigService sysConfigService;
+
+    /**
+     * 所有配置列表
+     */
+    @GetMapping("/list")
+    @RequiresPermissions("sys:config:list")
+    public R list(@RequestParam Map<String, Object> params) {
+        PageUtils page = sysConfigService.queryPage(params);
+
+        return R.ok().put("page", page);
+    }
+
+
+    /**
+     * 配置信息
+     */
+    @GetMapping("/info/{id}")
+    @RequiresPermissions("sys:config:info")
+    public R info(@PathVariable("id") Long id) {
+        SysConfigEntity config = sysConfigService.getById(id);
+
+        return R.ok().put("config", config);
+    }
+
+    /**
+     * 保存配置
+     */
+    @SysLog("保存配置")
+    @PostMapping("/save")
+    @RequiresPermissions("sys:config:save")
+    public R save(@RequestBody SysConfigEntity config) {
+        ValidatorUtils.validateEntity(config);
+
+        sysConfigService.saveConfig(config);
+
+        return R.ok();
+    }
+
+    /**
+     * 修改配置
+     */
+    @SysLog("修改配置")
+    @PostMapping("/update")
+    @RequiresPermissions("sys:config:update")
+    public R update(@RequestBody SysConfigEntity config) {
+        ValidatorUtils.validateEntity(config);
+
+        sysConfigService.update(config);
+
+        return R.ok();
+    }
+
+    /**
+     * 删除配置
+     */
+    @SysLog("删除配置")
+    @PostMapping("/delete")
+    @RequiresPermissions("sys:config:delete")
+    public R delete(@RequestBody Long[] ids) {
+        sysConfigService.deleteBatch(ids);
+
+        return R.ok();
+    }
+
+}

+ 145 - 0
src/main/java/io/renren/modules/sys/controller/SysDeptController.java

@@ -0,0 +1,145 @@
+/**
+ * Copyright (c) 2016-2019 人人开源 All rights reserved.
+ * <p>
+ * https://www.renren.io
+ * <p>
+ * 版权所有,侵权必究!
+ */
+
+package io.renren.modules.sys.controller;
+
+import io.renren.common.utils.Constant;
+import io.renren.common.utils.R;
+import io.renren.modules.sys.entity.SysDeptEntity;
+import io.renren.modules.sys.service.SysDeptService;
+import org.apache.shiro.authz.annotation.RequiresPermissions;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import java.util.HashMap;
+import java.util.List;
+
+
+/**
+ * 部门管理
+ *
+ * @author Mark 735032128@qq.com
+ */
+@RestController
+@RequestMapping("/sys/dept")
+public class SysDeptController extends AbstractController {
+    @Autowired
+    private SysDeptService sysDeptService;
+
+    /**
+     * 列表
+     */
+    @RequestMapping("/list")
+    @RequiresPermissions("sys:dept:list")
+    public List<SysDeptEntity> list() {
+        List<SysDeptEntity> deptList = sysDeptService.queryList(new HashMap<String, Object>());
+
+        return deptList;
+    }
+
+    /**
+     * 选择部门(添加、修改菜单)
+     */
+    @RequestMapping("/select")
+    @RequiresPermissions("sys:dept:select")
+    public R select() {
+        List<SysDeptEntity> deptList = sysDeptService.queryList(new HashMap<String, Object>());
+
+        //添加一级部门
+        if (getUserId() == Constant.SUPER_ADMIN) {
+            SysDeptEntity root = new SysDeptEntity();
+            root.setDeptId(0L);
+            root.setName("一级部门");
+            root.setParentId(-1L);
+            root.setOpen(true);
+            deptList.add(root);
+        }
+
+        return R.ok().put("deptList", deptList);
+    }
+
+    /**
+     * 上级部门Id(管理员则为0)
+     */
+    @RequestMapping("/info")
+    @RequiresPermissions("sys:dept:list")
+    public R info() {
+        long deptId = 0;
+        if (getUserId() != Constant.SUPER_ADMIN) {
+            List<SysDeptEntity> deptList = sysDeptService.queryList(new HashMap<String, Object>());
+            Long parentId = null;
+            for (SysDeptEntity sysDeptEntity : deptList) {
+                if (parentId == null) {
+                    parentId = sysDeptEntity.getParentId();
+                    continue;
+                }
+
+                if (parentId > sysDeptEntity.getParentId().longValue()) {
+                    parentId = sysDeptEntity.getParentId();
+                }
+            }
+            deptId = parentId;
+        }
+
+        return R.ok().put("deptId", deptId);
+    }
+
+    /**
+     * 信息
+     */
+    @RequestMapping("/info/{deptId}")
+    @RequiresPermissions("sys:dept:info")
+    public R info(@PathVariable("deptId") Long deptId) {
+        SysDeptEntity dept = sysDeptService.getById(deptId);
+
+        return R.ok().put("dept", dept);
+    }
+
+    /**
+     * 保存
+     */
+    @RequestMapping("/save")
+    @RequiresPermissions("sys:dept:save")
+    public R save(@RequestBody SysDeptEntity dept) {
+        sysDeptService.save(dept);
+
+        return R.ok();
+    }
+
+    /**
+     * 修改
+     */
+    @RequestMapping("/update")
+    @RequiresPermissions("sys:dept:update")
+    public R update(@RequestBody SysDeptEntity dept) {
+        sysDeptService.updateById(dept);
+
+        return R.ok();
+    }
+
+    /**
+     * 删除
+     */
+    @RequestMapping("/delete/{deptId}")
+    @RequiresPermissions("sys:dept:delete")
+    public R delete(@PathVariable("deptId") long deptId) {
+        //判断是否有子部门
+        List<Long> deptList = sysDeptService.queryDetpIdList(deptId);
+        if (deptList.size() > 0) {
+            return R.error("请先删除子部门");
+        }
+
+        sysDeptService.removeById(deptId);
+
+        return R.ok();
+    }
+
+}

+ 98 - 0
src/main/java/io/renren/modules/sys/controller/SysDictController.java

@@ -0,0 +1,98 @@
+/**
+ * Copyright (c) 2016-2019 人人开源 All rights reserved.
+ * <p>
+ * https://www.renren.io
+ * <p>
+ * 版权所有,侵权必究!
+ */
+
+package io.renren.modules.sys.controller;
+
+import io.renren.common.utils.PageUtils;
+import io.renren.common.utils.R;
+import io.renren.common.validator.ValidatorUtils;
+import io.renren.modules.sys.entity.SysDictEntity;
+import io.renren.modules.sys.service.SysDictService;
+import org.apache.shiro.authz.annotation.RequiresPermissions;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.Arrays;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * 数据字典
+ *
+ * @author Mark 735032128@qq.com
+ */
+@RestController
+@RequestMapping("sys/sysdict")
+public class SysDictController {
+    @Autowired
+    private SysDictService sysDictService;
+
+
+    /**
+     * 列表
+     */
+    @RequestMapping("/list")
+    @RequiresPermissions("sys:sysdict:list")
+    public R list(@RequestParam Map<String, Object> params) {
+        PageUtils page = sysDictService.queryPage(params);
+
+        return R.ok().put("page", page);
+    }
+
+
+    /**
+     * 信息
+     */
+    @RequestMapping("/info/{id}")
+    @RequiresPermissions("sys:sysdict:info")
+    public R info(@PathVariable("id") Long id) {
+        SysDictEntity dict = sysDictService.getById(id);
+
+        return R.ok().put("dict", dict);
+    }
+
+    /**
+     * 保存
+     */
+    @RequestMapping("/save")
+    @RequiresPermissions("sys:sysdict:save")
+    public R save(@RequestBody SysDictEntity dict) {
+        //校验类型
+        ValidatorUtils.validateEntity(dict);
+
+        sysDictService.save(dict);
+
+        return R.ok();
+    }
+
+    /**
+     * 修改
+     */
+    @RequestMapping("/update")
+    @RequiresPermissions("sys:sysdict:update")
+    public R update(@RequestBody SysDictEntity dict) {
+        //校验类型
+        ValidatorUtils.validateEntity(dict);
+
+        sysDictService.updateById(dict);
+
+        return R.ok();
+    }
+
+    /**
+     * 删除
+     */
+    @RequestMapping("/delete")
+    @RequiresPermissions("sys:sysdict:delete")
+    public R delete(@RequestBody Long[] ids) {
+        sysDictService.removeByIds(Arrays.asList(ids));
+
+        return R.ok();
+    }
+
+}

+ 47 - 0
src/main/java/io/renren/modules/sys/controller/SysLogController.java

@@ -0,0 +1,47 @@
+/**
+ * Copyright (c) 2016-2019 人人开源 All rights reserved.
+ * <p>
+ * https://www.renren.io
+ * <p>
+ * 版权所有,侵权必究!
+ */
+
+package io.renren.modules.sys.controller;
+
+import io.renren.common.utils.PageUtils;
+import io.renren.common.utils.R;
+import io.renren.modules.sys.service.SysLogService;
+import org.apache.shiro.authz.annotation.RequiresPermissions;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.ResponseBody;
+
+import java.util.Map;
+
+
+/**
+ * 系统日志
+ *
+ * @author Mark 735032128@qq.com
+ */
+@Controller
+@RequestMapping("/sys/log")
+public class SysLogController {
+    @Autowired
+    private SysLogService sysLogService;
+
+    /**
+     * 列表
+     */
+    @ResponseBody
+    @GetMapping("/list")
+    @RequiresPermissions("sys:log:list")
+    public R list(@RequestParam Map<String, Object> params) {
+        PageUtils page = sysLogService.queryPage(params);
+        return R.ok().put("page", page);
+    }
+
+}

+ 120 - 0
src/main/java/io/renren/modules/sys/controller/SysLoginController.java

@@ -0,0 +1,120 @@
+/**
+ * Copyright (c) 2016-2019 人人开源 All rights reserved.
+ * <p>
+ * https://www.renren.io
+ * <p>
+ * 版权所有,侵权必究!
+ */
+
+package io.renren.modules.sys.controller;
+
+import io.renren.common.annotation.SysLog;
+import io.renren.common.utils.HttpContextUtils;
+import io.renren.common.utils.IPUtils;
+import io.renren.common.utils.R;
+import io.renren.modules.sys.entity.SysLogEntity;
+import io.renren.modules.sys.entity.SysUserEntity;
+import io.renren.modules.sys.form.SysLoginForm;
+import io.renren.modules.sys.service.SysCaptchaService;
+import io.renren.modules.sys.service.SysLogService;
+import io.renren.modules.sys.service.SysUserService;
+import io.renren.modules.sys.service.SysUserTokenService;
+import org.apache.commons.io.IOUtils;
+import org.apache.shiro.crypto.hash.Sha256Hash;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.*;
+
+import javax.imageio.ImageIO;
+import javax.servlet.ServletOutputStream;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.awt.image.BufferedImage;
+import java.io.Console;
+import java.io.IOException;
+import java.util.Date;
+import java.util.Map;
+
+/**
+ * 登录相关
+ *
+ * @author Mark 735032128@qq.com
+ */
+@RestController
+public class SysLoginController extends AbstractController {
+    @Autowired
+    private SysUserService sysUserService;
+    @Autowired
+    private SysUserTokenService sysUserTokenService;
+    @Autowired
+    private SysCaptchaService sysCaptchaService;
+    @Autowired
+    private SysLogService sysLogService;
+
+    /**
+     * 验证码
+     */
+    @GetMapping("captcha.jpg")
+    public void captcha(HttpServletResponse response, String uuid) throws IOException {
+        response.setHeader("Cache-Control", "no-store, no-cache");
+        response.setContentType("image/jpeg");
+
+        //获取图片验证码
+        BufferedImage image = sysCaptchaService.getCaptcha(uuid);
+
+        ServletOutputStream out = response.getOutputStream();
+        ImageIO.write(image, "jpg", out);
+        IOUtils.closeQuietly(out);
+    }
+
+    /**
+     * 登录
+     */
+    @PostMapping("/sys/login")
+    public Map<String, Object> login(@RequestBody SysLoginForm form) throws IOException {
+        /*boolean captcha = sysCaptchaService.validate(form.getUuid(), form.getCaptcha());
+        if (!form.getCaptcha().equals("8888")) {
+            if (!captcha) {
+                return R.error("验证码不正确");
+            }
+        }*/
+        //用户信息
+        SysUserEntity user = sysUserService.queryByUserName(form.getUsername());
+
+        //账号不存在、密码错误
+        if (user == null || !user.getPassword().equals(new Sha256Hash(form.getPassword(), user.getSalt()).toHex())) {
+            return R.error("账号或密码不正确");
+        }
+
+        //账号锁定
+        if (user.getStatus() == 0) {
+            return R.error("账号已被锁定,请联系管理员");
+        }
+
+        //生成token,并保存到数据库
+        R r = sysUserTokenService.createToken(user.getUserId());
+        //
+        SysLogEntity sysLog = new SysLogEntity();
+        //获取request
+        HttpServletRequest request = HttpContextUtils.getHttpServletRequest();
+        //设置IP地址
+        sysLog.setIp(IPUtils.getIpAddr(request));
+        //用户名
+        sysLog.setUsername(user.getUsername());
+        sysLog.setCreateDate(new Date());
+        sysLog.setTime(0l);
+        sysLog.setOperation("登录");
+        //保存系统日志
+        sysLogService.save(sysLog);
+        return r;
+    }
+
+    /**
+     * 退出
+     */
+    @PostMapping("/sys/logout")
+    public R logout() {
+        sysUserTokenService.logout(getUserId());
+        return R.ok();
+    }
+
+}

+ 198 - 0
src/main/java/io/renren/modules/sys/controller/SysMenuController.java

@@ -0,0 +1,198 @@
+/**
+ * Copyright (c) 2016-2019 人人开源 All rights reserved.
+ * <p>
+ * https://www.renren.io
+ * <p>
+ * 版权所有,侵权必究!
+ */
+
+package io.renren.modules.sys.controller;
+
+import com.baomidou.mybatisplus.core.conditions.Wrapper;
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import io.renren.common.annotation.SysLog;
+import io.renren.common.exception.RRException;
+import io.renren.common.utils.Constant;
+import io.renren.common.utils.R;
+import io.renren.modules.sys.entity.SysDictEntity;
+import io.renren.modules.sys.entity.SysMenuEntity;
+import io.renren.modules.sys.service.ShiroService;
+import io.renren.modules.sys.service.SysDictService;
+import io.renren.modules.sys.service.SysMenuService;
+import org.apache.commons.lang.StringUtils;
+import org.apache.shiro.authz.annotation.RequiresPermissions;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.List;
+import java.util.Set;
+
+/**
+ * 系统菜单
+ *
+ * @author Mark 735032128@qq.com
+ */
+@RestController
+@RequestMapping("/sys/menu")
+public class SysMenuController extends AbstractController {
+    @Autowired
+    private SysMenuService sysMenuService;
+    @Autowired
+    private ShiroService shiroService;
+    @Autowired
+    private SysDictService sysDictService;
+
+    /**
+     * 导航菜单
+     */
+    @GetMapping("/nav")
+    public R nav() {
+        List<SysMenuEntity> menuList = sysMenuService.getUserMenuList(getUserId());
+        Set<String> permissions = shiroService.getUserPermissions(getUserId());
+        List<SysDictEntity> dictList = sysDictService.list(new QueryWrapper<SysDictEntity>().orderByAsc("ORDER_NUM"));
+        return R.ok().put("menuList", menuList).put("permissions", permissions).put("dict", dictList);
+    }
+
+    /**
+     * 所有菜单列表
+     */
+    @GetMapping("/list")
+    @RequiresPermissions("sys:menu:list")
+    public List<SysMenuEntity> list() {
+        List<SysMenuEntity> menuList = sysMenuService.list();
+        for (SysMenuEntity sysMenuEntity : menuList) {
+            SysMenuEntity parentMenuEntity = sysMenuService.getById(sysMenuEntity.getParentId());
+            if (parentMenuEntity != null) {
+                sysMenuEntity.setParentName(parentMenuEntity.getName());
+            }
+        }
+
+        return menuList;
+    }
+
+    /**
+     * 选择菜单(添加、修改菜单)
+     */
+    @GetMapping("/select")
+    @RequiresPermissions("sys:menu:select")
+    public R select() {
+        //查询列表数据
+        List<SysMenuEntity> menuList = sysMenuService.queryNotButtonList();
+
+        //添加顶级菜单
+        SysMenuEntity root = new SysMenuEntity();
+        root.setMenuId(0L);
+        root.setName("一级菜单");
+        root.setParentId(-1L);
+        root.setOpen(true);
+        menuList.add(root);
+
+        return R.ok().put("menuList", menuList);
+    }
+
+    /**
+     * 菜单信息
+     */
+    @GetMapping("/info/{menuId}")
+    @RequiresPermissions("sys:menu:info")
+    public R info(@PathVariable("menuId") Long menuId) {
+        SysMenuEntity menu = sysMenuService.getById(menuId);
+        return R.ok().put("menu", menu);
+    }
+
+    /**
+     * 保存
+     */
+    @SysLog("保存菜单")
+    @PostMapping("/save")
+    @RequiresPermissions("sys:menu:save")
+    public R save(@RequestBody SysMenuEntity menu) {
+        //数据校验
+        verifyForm(menu);
+
+        sysMenuService.save(menu);
+
+        return R.ok();
+    }
+
+    /**
+     * 修改
+     */
+    @SysLog("修改菜单")
+    @PostMapping("/update")
+    @RequiresPermissions("sys:menu:update")
+    public R update(@RequestBody SysMenuEntity menu) {
+        //数据校验
+        verifyForm(menu);
+
+        sysMenuService.updateById(menu);
+
+        return R.ok();
+    }
+
+    /**
+     * 删除
+     */
+    @SysLog("删除菜单")
+    @PostMapping("/delete/{menuId}")
+    @RequiresPermissions("sys:menu:delete")
+    public R delete(@PathVariable("menuId") long menuId) {
+        if (menuId <= 31) {
+            return R.error("系统菜单,不能删除");
+        }
+
+        //判断是否有子菜单或按钮
+        List<SysMenuEntity> menuList = sysMenuService.queryListParentId(menuId);
+        if (menuList.size() > 0) {
+            return R.error("请先删除子菜单或按钮");
+        }
+
+        sysMenuService.delete(menuId);
+
+        return R.ok();
+    }
+
+    /**
+     * 验证参数是否正确
+     */
+    private void verifyForm(SysMenuEntity menu) {
+        if (StringUtils.isBlank(menu.getName())) {
+            throw new RRException("菜单名称不能为空");
+        }
+
+        if (menu.getParentId() == null) {
+            throw new RRException("上级菜单不能为空");
+        }
+
+        //菜单
+        if (menu.getType() == Constant.MenuType.MENU.getValue()) {
+            if (StringUtils.isBlank(menu.getUrl())) {
+                throw new RRException("菜单URL不能为空");
+            }
+        }
+
+        //上级菜单类型
+        int parentType = Constant.MenuType.CATALOG.getValue();
+        if (menu.getParentId() != 0) {
+            SysMenuEntity parentMenu = sysMenuService.getById(menu.getParentId());
+            parentType = parentMenu.getType();
+        }
+
+        //目录、菜单
+        if (menu.getType() == Constant.MenuType.CATALOG.getValue() ||
+                menu.getType() == Constant.MenuType.MENU.getValue()) {
+            if (parentType != Constant.MenuType.CATALOG.getValue()) {
+                throw new RRException("上级菜单只能为目录类型");
+            }
+            return;
+        }
+
+        //按钮
+        if (menu.getType() == Constant.MenuType.BUTTON.getValue()) {
+            if (parentType != Constant.MenuType.MENU.getValue()) {
+                throw new RRException("上级菜单只能为菜单类型");
+            }
+            return;
+        }
+    }
+}

+ 168 - 0
src/main/java/io/renren/modules/sys/controller/SysPlantController.java

@@ -0,0 +1,168 @@
+/**
+ * Copyright (c) 2016-2019 人人开源 All rights reserved.
+ * <p>
+ * https://www.renren.io
+ * <p>
+ * 版权所有,侵权必究!
+ */
+
+package io.renren.modules.sys.controller;
+
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import io.renren.common.utils.Constant;
+import io.renren.common.utils.R;
+import io.renren.modules.sys.entity.SysPlantEntity;
+import io.renren.modules.sys.entity.SysUserPlantEntity;
+import io.renren.modules.sys.service.SysPlantService;
+import io.renren.modules.sys.service.SysUserPlantService;
+import org.apache.shiro.authz.annotation.RequiresPermissions;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+
+
+/**
+ * 装置管理
+ *
+ * @author Mark 735032128@qq.com
+ */
+@RestController
+@RequestMapping("/sys/plant")
+public class SysPlantController extends AbstractController {
+    @Autowired
+    private SysPlantService sysPlantService;
+    @Autowired
+    private SysUserPlantService sysUserPlantService;
+
+    /**
+     * 列表
+     */
+    @RequestMapping("/list")
+    @RequiresPermissions("sys:plant:list")
+    public List<SysPlantEntity> list() {
+        List<SysPlantEntity> plantList = sysPlantService.queryList(new HashMap<String, Object>());
+
+        return plantList;
+    }
+
+    /**
+     * 用户列表
+     */
+    @RequestMapping("/mylist")
+    public List<SysPlantEntity> mylist() {
+        List<SysUserPlantEntity> userPlantList = sysUserPlantService.list(new QueryWrapper<SysUserPlantEntity>()
+                .eq("user_id" ,getUserId()));
+        List<SysPlantEntity> plantList = new ArrayList<>();
+        for (SysUserPlantEntity s : userPlantList
+             ) {
+            SysPlantEntity sysPlantEntity =  sysPlantService.getById(s.getPlantId());
+            if (sysPlantEntity != null)
+            plantList.add(sysPlantEntity);
+        }
+        return plantList;
+    }
+
+    /**
+     * 选择装置(添加、修改菜单)
+     */
+    @RequestMapping("/select")
+    @RequiresPermissions("sys:plant:select")
+    public R select() {
+        List<SysPlantEntity> plantList = sysPlantService.queryList(new HashMap<String, Object>());
+
+        //添加一级装置
+        if (getUserId() == Constant.SUPER_ADMIN) {
+            SysPlantEntity root = new SysPlantEntity();
+            root.setPlantId(0L);
+            root.setName("一级装置");
+            root.setParentId(-1L);
+            root.setOpen(true);
+            plantList.add(root);
+        }
+
+        return R.ok().put("plantList", plantList);
+    }
+
+    /**
+     * 上级装置Id(管理员则为0)
+     */
+    @RequestMapping("/info")
+    @RequiresPermissions("sys:plant:list")
+    public R info() {
+        long plantId = 0;
+        if (getUserId() != Constant.SUPER_ADMIN) {
+            List<SysPlantEntity> plantList = sysPlantService.queryList(new HashMap<String, Object>());
+            Long parentId = null;
+            for (SysPlantEntity sysPlantEntity : plantList) {
+                if (parentId == null) {
+                    parentId = sysPlantEntity.getParentId();
+                    continue;
+                }
+
+                if (parentId > sysPlantEntity.getParentId().longValue()) {
+                    parentId = sysPlantEntity.getParentId();
+                }
+            }
+            plantId = parentId;
+        }
+
+        return R.ok().put("plantId", plantId);
+    }
+
+    /**
+     * 信息
+     */
+    @RequestMapping("/info/{plantId}")
+    @RequiresPermissions("sys:plant:info")
+    public R info(@PathVariable("plantId") Long plantId) {
+        SysPlantEntity plant = sysPlantService.getById(plantId);
+
+        return R.ok().put("plant", plant);
+    }
+
+    /**
+     * 保存
+     */
+    @RequestMapping("/save")
+    @RequiresPermissions("sys:plant:save")
+    public R save(@RequestBody SysPlantEntity plant) {
+        sysPlantService.save(plant);
+
+        return R.ok();
+    }
+
+    /**
+     * 修改
+     */
+    @RequestMapping("/update")
+    @RequiresPermissions("sys:plant:update")
+    public R update(@RequestBody SysPlantEntity plant) {
+        sysPlantService.updateById(plant);
+
+        return R.ok();
+    }
+
+    /**
+     * 删除
+     */
+    @RequestMapping("/delete/{plantId}")
+    @RequiresPermissions("sys:plant:delete")
+    public R delete(@PathVariable("plantId") long plantId) {
+        //判断是否有子装置
+        List<Long> plantList = sysPlantService.queryPlantIdList(plantId);
+        if (plantList.size() > 0) {
+            return R.error("请先删除子装置");
+        }
+
+        sysPlantService.removeById(plantId);
+
+        return R.ok();
+    }
+
+}

Some files were not shown because too many files changed in this diff