Browse Source

Merge branch 'master' of https://git.gygxzc.cn/Envir_Group/Zen-Framework

tuonina 6 years ago
parent
commit
a40485101b
100 changed files with 2886 additions and 1585 deletions
  1. 1 1
      .gitignore
  2. 37 0
      DEPLOY.md
  3. 181 0
      FRAMEWORK.md
  4. 1 37
      README.md
  5. 24 42
      build.gradle
  6. 5 0
      c-docs/项目相关资料文档整理.md
  7. 0 0
      c-sql/archives_sys.sql
  8. 0 0
      c-sql/archives_xxl-job.sql
  9. 6 0
      cloud-bus/README.md
  10. 14 0
      cloud-bus/build.gradle
  11. 10 0
      cloud-bus/src/main/java/cn/gygxzc/envir/bus/QueueName.java
  12. 53 0
      cloud-bus/src/main/java/cn/gygxzc/envir/bus/RabbitConfiguration.java
  13. 90 0
      cloud-bus/src/main/java/cn/gygxzc/envir/bus/entity/PushModel.java
  14. 19 0
      cloud-bus/src/main/java/cn/gygxzc/envir/bus/mail/IFeignMailSender.java
  15. 12 0
      cloud-bus/src/main/java/cn/gygxzc/envir/bus/mail/IMailBusSender.java
  16. 27 0
      cloud-bus/src/main/java/cn/gygxzc/envir/bus/mail/impl/MailBusSenderImpl.java
  17. 17 0
      cloud-bus/src/main/java/cn/gygxzc/envir/bus/message/IMessagePusher.java
  18. 32 0
      cloud-bus/src/main/java/cn/gygxzc/envir/bus/message/impl/MessagePusher.java
  19. 13 0
      cloud-bus/src/main/java/cn/gygxzc/tina/cloud/bus/constant/QueueName.java
  20. 27 0
      cloud-bus/src/main/java/cn/gygxzc/tina/cloud/bus/framweork/bean/FrameworkBean.java
  21. 31 0
      cloud-bus/src/main/java/cn/gygxzc/tina/cloud/bus/framweork/receiver/FrameworkReceiver.java
  22. 22 0
      cloud-bus/src/main/java/cn/gygxzc/tina/cloud/bus/framweork/receiver/LoggerReceiver.java
  23. 36 0
      cloud-bus/src/main/java/cn/gygxzc/tina/cloud/bus/messager/bean/MessageBean.java
  24. 15 0
      cloud-bus/src/main/java/cn/gygxzc/tina/cloud/bus/messager/sender/IMessagerSender.java
  25. 42 0
      cloud-bus/src/main/java/cn/gygxzc/tina/cloud/bus/messager/sender/impl/MessagerSender.java
  26. 26 0
      cloud-bus/src/main/java/cn/gygxzc/tina/cloud/bus/utils/GsonUtils.java
  27. 15 0
      fastdfs-client/build.gradle
  28. 23 0
      fastdfs-client/src/main/java/cn/gygxzc/cloud/tina/fastdfs/client/EnableFastDFSClient.java
  29. 20 0
      fastdfs-client/src/main/java/cn/gygxzc/cloud/tina/fastdfs/client/FastDFSClientConfiguration.java
  30. 60 0
      fastdfs-client/src/main/java/cn/gygxzc/cloud/tina/fastdfs/client/controller/FdfsDownloadController.java
  31. 120 0
      fastdfs-client/src/main/java/cn/gygxzc/cloud/tina/fastdfs/client/controller/FdfsUploadController.java
  32. 32 0
      fastdfs-client/src/main/java/cn/gygxzc/cloud/tina/fastdfs/client/mata/CommonFileMata.java
  33. 42 0
      fastdfs-client/src/main/java/cn/gygxzc/cloud/tina/fastdfs/client/mata/FailedStorePath.java
  34. 28 0
      fastdfs-client/src/main/java/cn/gygxzc/cloud/tina/fastdfs/client/utils/FileUtils.java
  35. 27 0
      fastdfs-client/src/main/resources/application-fdfs.yml
  36. 60 0
      fastdfs-client/src/test/java/cn/gygxzc/cloud/tina/fdfs/RxJavaTest.java
  37. 14 0
      fastdfs-client/src/test/java/cn/gygxzc/cloud/tina/fdfs/utils/FileUtilsTest.java
  38. 1 1
      gradle/wrapper/gradle-wrapper.properties
  39. BIN
      jwt-session-1.2.jar
  40. 2 1
      settings.gradle
  41. 3 0
      zen-api/src/main/java/cn/gygxzc/envir/biz/dao/Dao.java
  42. 16 0
      zen-api/src/main/java/cn/gygxzc/envir/test/dao/ITestLogDao.java
  43. 22 0
      zen-api/src/main/java/cn/gygxzc/envir/test/model/TestLog.java
  44. 39 0
      zen-api/src/main/java/cn/gygxzc/envir/test/service/ITestLogService.java
  45. 51 0
      zen-api/src/main/java/cn/gygxzc/envir/test/service/impl/TestLogService.java
  46. 0 139
      zen-api/src/main/kotlin/cn/gygxzc/envir/config/shiro/ShiroConfig.kt
  47. 0 61
      zen-api/src/main/kotlin/cn/gygxzc/envir/config/shiro/cache/RedisConfiguration.kt
  48. 0 119
      zen-api/src/main/kotlin/cn/gygxzc/envir/config/shiro/cache/ShiroRedisCache.kt
  49. 0 21
      zen-api/src/main/kotlin/cn/gygxzc/envir/config/shiro/cache/ShiroRedisCacheManager.kt
  50. 0 61
      zen-api/src/main/kotlin/cn/gygxzc/envir/config/shiro/common/ZenAuthToken.kt
  51. 0 54
      zen-api/src/main/kotlin/cn/gygxzc/envir/config/shiro/common/ZenPermission.kt
  52. 0 106
      zen-api/src/main/kotlin/cn/gygxzc/envir/config/shiro/common/ZenSimpleByteSource.kt
  53. 0 40
      zen-api/src/main/kotlin/cn/gygxzc/envir/config/shiro/filter/AjaxAuthorizationFilter.kt
  54. 0 41
      zen-api/src/main/kotlin/cn/gygxzc/envir/config/shiro/filter/ZenCorsAnonymousFilter.kt
  55. 0 39
      zen-api/src/main/kotlin/cn/gygxzc/envir/config/shiro/filter/ZenCorsPathMatchingFilter.kt
  56. 0 63
      zen-api/src/main/kotlin/cn/gygxzc/envir/config/shiro/realm/ZenShiroRealm.kt
  57. 0 82
      zen-api/src/main/kotlin/cn/gygxzc/envir/config/shiro/utils/SerializeUtils.kt
  58. 0 42
      zen-api/src/main/kotlin/cn/gygxzc/envir/config/shiro/utils/ShiroRedisUtil.kt
  59. 0 42
      zen-api/src/main/kotlin/cn/gygxzc/envir/config/shiro/utils/ShiroUtils.java
  60. 197 0
      zen-api/src/main/kotlin/cn/gygxzc/envir/sys/model/CommonFile.java
  61. 0 81
      zen-api/src/main/kotlin/cn/gygxzc/envir/sys/model/SysUser.kt
  62. 65 0
      zen-api/src/main/kotlin/cn/gygxzc/envir/sys/service/IFUserService.kt
  63. 33 0
      zen-api/src/main/kotlin/cn/gygxzc/envir/sys/service/IFileInfoService.kt
  64. 1 2
      zen-api/src/main/kotlin/cn/gygxzc/envir/sys/service/ILoginService.kt
  65. 1 1
      zen-api/src/main/kotlin/cn/gygxzc/envir/utils/Byte2Hex.kt
  66. 1 1
      zen-api/src/main/kotlin/cn/gygxzc/envir/utils/MD5Salt.kt
  67. 0 43
      zen-api/src/main/kotlin/com/gxzc/zen/msg/ws/config/WebSocketConfig.kt
  68. 0 12
      zen-api/src/main/kotlin/com/gxzc/zen/msg/ws/config/WebSocketProperties.kt
  69. 0 39
      zen-api/src/main/kotlin/com/gxzc/zen/orm/config/MybatisPlusConfig.kt
  70. 0 30
      zen-api/src/main/kotlin/com/gxzc/zen/orm/data/authority/DAHelper.kt
  71. 0 24
      zen-api/src/main/kotlin/com/gxzc/zen/orm/data/authority/DataAuthority.kt
  72. 0 43
      zen-api/src/main/kotlin/com/gxzc/zen/orm/data/authority/DataAuthorityBuilder.kt
  73. 0 43
      zen-api/src/main/kotlin/com/gxzc/zen/orm/data/authority/visitor/DataAuthoritySelectVisitor.kt
  74. 18 0
      zen-api/src/main/resources/mapper/test/TestLogMapper.xml
  75. 0 19
      zen-api/src/test/kotlin/com/gxzc/zen/api/PasswordGen.kt
  76. 0 35
      zen-api/src/test/kotlin/com/gxzc/zen/api/TestCollectionUtil.kt
  77. 0 110
      zen-api/src/test/kotlin/com/gxzc/zen/api/TestDictTypeTreeRedis.kt
  78. 0 24
      zen-api/src/test/kotlin/com/gxzc/zen/api/TestKotlinReplace.kt
  79. 0 22
      zen-api/src/test/kotlin/com/gxzc/zen/api/TestTreePath.kt
  80. 0 39
      zen-api/src/test/kotlin/com/gxzc/zen/api/base/BaseTestKt.kt
  81. 0 1
      zen-core/build.gradle
  82. 91 0
      zen-core/src/main/java/cn/gygxzc/envir/core/base/BaseModel.java
  83. 191 0
      zen-core/src/main/java/cn/gygxzc/envir/core/entity/MailEntity.java
  84. 12 0
      zen-core/src/main/java/cn/gygxzc/envir/core/ex/ParamMissException.java
  85. 108 0
      zen-core/src/main/java/cn/gygxzc/envir/core/logger/CoreLoggerEvent.java
  86. 12 0
      zen-core/src/main/java/cn/gygxzc/envir/core/logger/ILoggerSender.java
  87. 13 0
      zen-core/src/main/java/cn/gygxzc/envir/core/logger/IMarkerName.java
  88. 175 0
      zen-core/src/main/java/cn/gygxzc/envir/core/logger/LogMessage.java
  89. 51 0
      zen-core/src/main/java/cn/gygxzc/envir/core/logger/MQAppender.java
  90. 87 0
      zen-core/src/main/java/cn/gygxzc/envir/core/logger/MQAsyncAppender.java
  91. 16 0
      zen-core/src/main/java/cn/gygxzc/envir/core/orm/DataSourceConfiguration.java
  92. 126 0
      zen-core/src/main/java/cn/gygxzc/envir/core/redis/JedisConnectionConfiguration.java
  93. 68 0
      zen-core/src/main/java/cn/gygxzc/envir/core/redis/RedisAutoConfiguration.java
  94. 157 0
      zen-core/src/main/java/cn/gygxzc/envir/core/redis/RedisConnectionConfiguration.java
  95. 40 0
      zen-core/src/main/java/cn/gygxzc/envir/core/utils/ApplicationUtils.java
  96. 26 0
      zen-core/src/main/java/cn/gygxzc/envir/core/utils/GsonUtils.java
  97. 26 0
      zen-core/src/main/java/cn/gygxzc/envir/core/utils/HttpUtils.java
  98. 23 0
      zen-core/src/main/kotlin/cn/gygxzc/envir/core/CoreConfiguration.kt
  99. 8 0
      zen-core/src/main/kotlin/cn/gygxzc/envir/core/CoreConst.kt
  100. 24 24
      zen-core/src/main/kotlin/cn/gygxzc/envir/core/caffeine/CaffeineConfiguration.kt

+ 1 - 1
.gitignore

@@ -137,7 +137,7 @@ log/
 logs/
 *.log
 *.log.*
-
+.log/
 
 # IntelliJ IDEA
 *.iml

+ 37 - 0
DEPLOY.md

@@ -0,0 +1,37 @@
+# 项目部署文档
+
+## 一、MySQL8 数据库部署
+
+项目的数据库基于docker部署,默认用户名为 root 默认的密码为 root_20190113,即当天数据库部署日期。
+使用的数据库版本为:8.0.13;
+
+本文以工商192.168.1.202 服务器为例
+
+一下为操作步骤:
+
+ - 登录服务器:root gxzc666
+ - 拉取MySQL镜像:docker pull mysql:8.0.13
+ - 运行mysql容器:
+ docker run -d --name mysql8 -p 3307:3306 -v /envir/mysql/cnf:/etc/mysql/conf.d -v /envir/mysql/data:/var/lib/mysql 
+ -e MYSQL_ROOT_PASSWORD="root_20190116" mysql:8.0.13
+ 
+ - 进入容器,分配用户及权限:docker exec -it mysql8 bash
+ - 使用mysql 进入数据库命令行:mysql -uroot -p ,输入密码:root_20190116
+ - 创建个系统使用的用户,这里不一一说明。为了方便,这里统一给各个系统创建同一个账号:envir  envir
+    <br> create user envir@'envir' identified with mysql_native_password by 'envir'<br>
+    
+ - 给用户授予事物恢复的权限;XA_RECOVER_ADMIN,  grant XA_RECOVER_ADMIN on *.* to envir@'envir';
+ - 刷新权限:flush privileges;
+ - 创建数据库,建表;
+  - mysql 时区问题
+ 
+          -e TZ=Asis/Shanghai   生成容器的时候,指定时区
+         set global time_zone = '+8:00'  临时修改,重启后失效
+         
+ 
+## 二、文件服务器部署
+文件服务器采用的是fastdfs分布式服务器。
+该服务器分成两部分:跟踪服务器和文件存储服务器。
+部署该服务同样采用docker 容器
+
+ 

+ 181 - 0
FRAMEWORK.md

@@ -0,0 +1,181 @@
+### 项目自定义规范
+
+只是一些建议性的东西,大家有什么好的想法,都可以提出来。
+
+- 现在暂时定义为v1版本,所有的api以 /v1/模块/功能
+- 采用restFul风格的URL
+- 返回数据的格式,全部采用ResponseDto ,data字段为传递的数据
+- 前后端分离,采用json格式进行数据传输
+- 根据 ResponseDto 的code字段判断请求操作是否成功。如果失败,返回非200的请求码
+- *最好将系统的代码和自己的区分开来,自己的代码写在cn.gygxzc.envir.biz 目录下*
+
+- *一键生成数据库相关代码配置在cn.gygxzc.envir.config.orm 包下,请自行配置相关参数*
+
+### 项目说明
+
+项目采用Spring Cloud分布式解决方案。
+目前系统中涉及到的知识点有 :
+- Eureka服务发现与注册中心,
+- Spring Cloud Config Server 微服务配置中心;
+- Spring Cloud Gateway 网关
+- Spring Cloud Bus 消息总线(结合rabbitmq)
+- Spring Session 结合Redis 做分布式权限认证
+- Mybatis-Plus 3.0
+
+需要的可以去了解一下。
+
+项目中缓存可以分成三类:
+- 系统Spring session缓存,shiro缓存
+
+-  获取当前登录用户信息 SessionUtils 工具类
+
+
+### 框架项目升级日志
+#### 2018/9/27
+升级框架的安全认证方式,改成jwt 和Spring session分布式方式认证。权限由网关统一认证。
+
+#### 2018/9/28
+已初步完成Spring session的分布式认证,下一步将移除shiro 依赖即权限认证。
+
+- 将数据库 DAO类文件卸载 zen-api 下的 cn.gygxzc.envir.biz.dao 路径下
+- 如果需要写 mapper.xml 请写在  resources/mapper 文件夹下,可以在有目录比如;resources/mapper/biz
+- 项目包名统一为 cn.gygxzc.envir.**
+- 项目对mybatis plus进行了升级,使用的是mybatis-plus 3.0,与之前有一定区别,具体可见[文档](http://mp.baomidou.com/guide/wrapper.html#querywrapper)
+
+#### 2018/9/29
+##### 1、添加配置中心,将配置中心与即时通信消息系统结合起来
+##### 2、 添加Spring bus。服务间的消息通知。
+
+        这一点举一点应用:业务系统需要向前端或者用户发送消息,
+        只需要调用发送消息的sender即可。由消息中心把消息发送给前端用户。
+
+##### 3、 删除shiro配置。
+        
+        但是因为授权中心使用shiro,导致客户端不能完全移除shiro依赖,但是只引用了shiro的核心包。
+        具体原因是:授权中心shiro在生成的session中放入了shiro包中的类实体对象,jdk序列化之后,在各自的业务系统中反序列化,如果不引入shiro核心包,将
+        导致jdk反序列化失败,导致各自业务系统无法获取到当前登录的用户信息。
+##### 4、 精简大量yml 文件配置,只保留必要的部分。
+ 有了配置中心的存在,可以将所有项目的公有和私有配置放到配置中心,而无需大量放到本地。
+ 
+##### 5、移除Tomcat依赖,添加jetty依赖
+Jetty 更加轻量化,更符合Spring Cloud 分布式部署;当然,这个还需要验证和考量。
+
+#### 2018/9/30
+ - 这次项目更新主要是去掉shiro的权限认证,但是保留了shiro的核心包,原因见上昨天更新日志。
+ - 删除了很多配置文件,集中到配置中心配置。
+ - 保留的配置文件 bootstrap.yml 为配置注册中心,配置中心相关信息,application.yml内只有数据库连接相关配置。
+ application-cache.yml为项目的一个内存缓存配置。里面需要修改的有备注,但是暂时可以不修改。
+ - 完成了mybatis-plus 的物理删除功能,具体见zen-api 下的test 包。
+ 
+ 到目前为止,框架这部分基本上不会有太多更新。目前业务中需要的即时通信相关服务,会单独写一个即时通信服务。
+ 业务系统通过rabbitmq 消息总线发送消息到 消息推送系统完成这方面的需求。后期会提供相关的接口包。
+
+#### 2018/10/31
+- 文件上传已完成,请查看 fastdfs-client 查看上传案例写法。
+
+#### 2018/11/1
+- 调整了zen-core 包的目录结构,各位耐心改正一个引入包的路径
+- 给每个客户端添加跨域配置,方便调试
+
+#### 2018/12/20
+- 修复了IFUserService 无法使用,
+- 新增了IFUserService 根据账号信息获取用户信息接口和修改用户的接口
+- 新增了获取文件信息的接口,未测试
+
+
+#### 2019/1/5
+
+- 更新User 字段,添加 avatar字段信息
+- 更新两个与安全有关的依赖包
+
+#### 2019/1/8
+
+- 解决docker 从容器无法限制JVM内存问题
+- 更改基础镜像为openjdk:8-jre-alpine (以前为8-jdk-alpine),减小镜像体积。
+
+#### 2019/2/26 添加加密解密方法
+
+数据从后端返回前端,后端对重要数据进行对称加密,并实现签名,保证数据不会被中途拦截篡改;
+数据从前端发送到后端,前端用公钥对数据进行加密,保证数据安全,不会被拦截,并且也需要实现签名,保证数据不被伪造。
+
+
+- 在 安全(auth) 依赖包中添加了关于加密解密相关功能。
+- 修改ClientInfo 实体类,添加了非对称加密的密钥信息
+
+#### 2019/3/4 完成前后端加密解密方法bug修复与集成,已可正常使用,添加邮件MQ发送及Feign发送服务
+
+- 后端使用,添加 SerializedField 注解即可
+- 前端使用,配置中添加 encrypt:true 即可
+- 需要邮件服务去实现相关的发送实现
+- cloud-bus module 的包结构调整比较大,有使用的需要更改一下。
+
+
+
+
+### 后期我的工作计划
+
+- 将继续精简shiro相关配置,直至完全移除;(已完成)
+- 消息总线 (已完成)
+- 日志记录
+- 即时通信(估计会另外建一个项目来做即时通信)
+- 网关的权限管理。
+- 阿里云对象存储,前后端文件上传功能。
+
+
+## Docker 相关介绍
+### 打包
+运行任务 : task dockerBuilder。
+特别注意在打包之前需要在idea 的命令行中登陆到镜像中心。
+登陆命令为:docker login --username=gxzcalyqy registry.cn-qingdao.aliyuncs.com
+密码为:docker20181018
+
+
+如果一切没有问题,打包成功之后会自动上传到镜像中心。等待上传完成。出现如下提示说明上传完成:
+
+        
+    BUILD SUCCESSFUL in 4m 10s
+    26 actionable tasks: 5 executed, 21 up-to-date
+    17:40:25: Task execution finished 'dockerBuilder'.
+
+
+
+### 运行命令
+
+docker run -t  --name `NAME` -m568m --expose=`PORT`  -p `PORT`:`PORT` -e "EUREKA_INSTANCE_IP-ADDRESS=`IP`" -e "SERVER_PORT=`PORT`"  IMAGE_NAME
+
+- IP 宿主机的ip
+- PORT 服务部署的端口号
+- NAME 容器名称,这个自定义
+- IMAGE_NAME 镜像名称或者镜像的ID
+- -m ,限制容器使用内存
+
+### 注意事项
+
+- 修改zen-web下的zen-web.gradle 中 task dockerBuilder applicationName为项目自己的内容
+
+以下片段位于zen-web.gradle ,修改其中的applicationName
+
+
+        task dockerBuilder(type: Docker) {
+            registry='registry.cn-qingdao.aliyuncs.com/gxzc-envir'
+            applicationName = 'fw'
+            tagVersion = jar.version
+            addFile("./build/libs/${jar.baseName}-${jar.version}.jar","app.jar")
+            entryPoint(["java","-Djava.security.egd=file:/dev/./urandom","-jar",'app.jar'])
+            exposePort(11000)
+            doFirst {
+                copy {
+                    from jar
+                    into stageDir
+                }
+            }
+            push = true
+        }
+        
+        
+ - mysql 时区问题
+
+         -e TZ=Asis/Shanghai   生成容器的时候,指定时区
+        set global time_zone = '+8:00'  临时修改,重启后失效
+        
+## 其他说明

+ 1 - 37
README.md

@@ -1,37 +1 @@
-### 项目自定义规范
-
-只是一些建议性的东西,大家有什么好的想法,都可以提出来。
-
-- 现在暂时定义为v1版本,所有的api以 /v1/模块/功能
-- 采用restFul风格的URL
-- 返回数据的格式,全部采用ResponseDto ,data字段为传递的数据
-- 前后端分离,采用json格式进行数据传输
-- 根据 ResponseDto 的code字段判断请求操作是否成功。如果失败,返回非200的请求码
-- *最好将系统的代码和自己的区分开来,自己的代码写在cn.gygxzc.envir.biz 目录下*
-
-### 项目说明
-项目中缓存可以分成三类:
-- 系统Spring session缓存,shiro缓存
-
--  获取当前登录用户信息 SessionUtils 工具类
-
-
-### 框架项目升级日志
-#### 2018/9/27
-升级框架的安全认证方式,改成jwt 和Spring session分布式方式认证。权限由网关统一认证。
-
-#### 2018/9/28
-已初步完成Spring session的分布式认证,下一步将移除shiro 依赖即权限认证。
-
-- 将数据库 DAO类文件卸载 zen-api 下的 cn.gygxzc.envir.biz.dao 路径下
-- 如果需要写 mapper.xml 请写在  resources/mapper 文件夹下,可以在有目录比如;resources/mapper/biz
-- 项目包名统一为 cn.gygxzc.envir.**
-- 项目对mybatis plus进行了升级,使用的是mybatis-plus 3.0,与之前有一定区别,具体可见[文档](http://mp.baomidou.com/guide/wrapper.html#querywrapper)
-
-
-### 后期计划
-
-- 将继续精简shiro相关配置,直至完全移除;
-- 消息总线
-- 日志记录
-- 即时通信整合(估计会另外建一个项目来做即时通信)
+# 项目说明

+ 24 - 42
build.gradle

@@ -8,28 +8,17 @@ buildscript {
         commons_io_version = '2.5'
         commons_lang3_version = '3.5'
         commons_codec_version = '1.10'
-        commons_fileupload_version = '1.3.2'
         slf4j_api_version = '1.7.25'
-        ehcache_version = '3.4.0'
-        ehcache_core_version = '2.6.11'
         mysql_connector_version = '5.1.45'
-        alidruid_version = '1.1.6'
         mybatis_plus_version = '2.2.0'
         mybatis_plus_boot_version = '1.0.5'
-        activiti_starter_version = '6.0.0'
-//        rocketmq_starter_version = '1.1.0-RELEASE'
-        rocketmq_starter_version = '0.1.0'
-        xxljob_version = '1.9.0'
         swagger_version = '2.7.0'
-        fastjson_version = '1.2.44'
-        pinyin4j_version = '2.5.1'
-//        kisso_version = '3.6.13'
         caffeine_version = '2.6.1'
         shiro_version = '1.4.0'
-        dubbo_starter_version = '0.1.0'
-        dubbo_version = "2.6.1"
-        jsqlparser_version = '1.2'
-        fastdfs_client_version = '1.26.2'
+        pinyin4j_version = '2.5.1'
+        rxJavaVersion='2.2.3'
+        jwtVersion = '1.4.0'
+        authVersion='1.2'
     }
     repositories {
         mavenCentral()
@@ -43,8 +32,8 @@ buildscript {
 }
 
 allprojects {
-    group = "com.gxzc.zen"
-    version = "1.0-SNAPSHOT"
+    group = "cn.gygxzc.cloud"
+    version = "1.1"
 }
 
 subprojects {
@@ -68,10 +57,10 @@ subprojects {
         mavenCentral()
         jcenter()
         maven {
-            url("https://repo.rdc.aliyun.com/repository/33224-release-ycBLfV")
+            url("https://repo.rdc.aliyun.com/repository/37165-release-a3lssL")
             credentials {
-                username 'TbLzWL'
-                password 'mCl1FI5SVB'
+                username 'Dz38pq'
+                password 'U1oB2RJOJa'
             }
         }
         maven {
@@ -89,6 +78,9 @@ subprojects {
         }
     }
 
+    configurations{
+        all*.exclude group: 'org.springframework.boot', module: 'spring-boot-starter-tomcat'
+    }
 
     dependencies {
         // Kotlin
@@ -104,9 +96,11 @@ subprojects {
 //
 
         compile('org.springframework.boot:spring-boot-starter-web')
+        compile('org.springframework.boot:spring-boot-starter-jdbc')
         compile('org.springframework.boot:spring-boot-starter-actuator')
-        compile('org.springframework.boot:spring-boot-starter-websocket')
+
         compile('org.springframework.boot:spring-boot-starter-jta-atomikos')
+        compile('org.springframework.boot:spring-boot-starter-jetty')
 
 //        cache
         compile('org.springframework.boot:spring-boot-starter-cache')
@@ -114,23 +108,23 @@ subprojects {
         compile('redis.clients:jedis:2.9.0')
 
 
+        compile('org.springframework.cloud:spring-cloud-starter-config')
+
         testCompile('org.springframework.boot:spring-boot-starter-test')
         // mq
+        compile('com.fasterxml.jackson.module:jackson-module-kotlin:2.9.6')
+        compile("io.reactivex.rxjava2:rxjava:$rxJavaVersion")
+
 
-        // shiro
+        //只因用shiro核心包
         compile("org.apache.shiro:shiro-spring:$shiro_version")
 
-        compile group: 'com.fasterxml.jackson.module', name: 'jackson-module-kotlin', version: '2.9.6'
+        compile("com.belerweb:pinyin4j:$pinyin4j_version")
 
         // commons
         compile("commons-io:commons-io:$commons_io_version")
         compile("org.apache.commons:commons-lang3:$commons_lang3_version")
         compile("commons-codec:commons-codec:$commons_codec_version")
-        compile("commons-fileupload:commons-fileupload:$commons_fileupload_version")
-
-        // logger
-        compile("org.slf4j:slf4j-api:$slf4j_api_version")
-
         compile("javax.servlet:javax.servlet-api:3.1.0")
         compile("javax.servlet:servlet-api:2.5")
 
@@ -139,24 +133,12 @@ subprojects {
         // db
         compile("mysql:mysql-connector-java:$mysql_connector_version")
         compile("com.baomidou:mybatis-plus-boot-starter:$mybatisPlusVersion")
-        // job
-        compile("com.xuxueli:xxl-job-core:$xxljob_version")
-
         // swagger
         compile("io.springfox:springfox-swagger2:$swagger_version")
         compile("io.springfox:springfox-swagger-ui:$swagger_version")
 
-        // utils
-        compile("org.projectlombok:lombok:1.18.2")
-        compile("com.alibaba:fastjson:$fastjson_version")
-        compile("com.belerweb:pinyin4j:$pinyin4j_version")
-
-
-        compile("org.apache.velocity:velocity-engine-core:2.0")
-        // sql parser
-        compile("com.github.jsqlparser:jsqlparser:$jsqlparser_version")
-        // fastdfs
-        compile("com.github.tobato:fastdfs-client:$fastdfs_client_version")
+        compile("cn.gygxzc.cloud:jwt-session:$jwtVersion")
+        compile("cn.gygxzc.cloud:tina-auth:$authVersion")
 
         ext.jarTree = fileTree(dir: 'libs', include: '**/*.jar')
         compile jarTree

+ 5 - 0
c-docs/项目相关资料文档整理.md

@@ -0,0 +1,5 @@
+# 基于Spring Cloud 的项目集成框架
+## 几个知识点
+### 服务注册中心Eureka
+### 服务配置中心 Spring Cloud Config Server
+### 消息总线 Spring Cloud Bus

+ 0 - 0
sql/archives_sys.sql → c-sql/archives_sys.sql


+ 0 - 0
sql/archives_xxl-job.sql → c-sql/archives_xxl-job.sql


+ 6 - 0
cloud-bus/README.md

@@ -0,0 +1,6 @@
+# Spring Cloud Bus 消息总线
+服务间消息通知调用。
+
+如果不需要不依赖该包。
+
+用法见里面的代码

+ 14 - 0
cloud-bus/build.gradle

@@ -0,0 +1,14 @@
+
+group 'cn.gygxzc.tina'
+version '1.0'
+
+sourceCompatibility = 1.8
+
+repositories {
+    mavenCentral()
+}
+
+dependencies {
+    compile 'org.springframework.cloud:spring-cloud-starter-bus-amqp'
+    compile project(":zen-core")
+}

+ 10 - 0
cloud-bus/src/main/java/cn/gygxzc/envir/bus/QueueName.java

@@ -0,0 +1,10 @@
+package cn.gygxzc.envir.bus;
+
+/**
+ * @author tuonina
+ * @createTime 2019/3/4
+ */
+public interface QueueName {
+
+    String EMAIL="Email";
+}

+ 53 - 0
cloud-bus/src/main/java/cn/gygxzc/envir/bus/RabbitConfiguration.java

@@ -0,0 +1,53 @@
+package cn.gygxzc.envir.bus;
+
+import cn.gygxzc.tina.cloud.bus.constant.QueueName;
+import cn.gygxzc.tina.cloud.bus.framweork.receiver.LoggerReceiver;
+import cn.gygxzc.tina.cloud.bus.messager.sender.IMessagerSender;
+import cn.gygxzc.tina.cloud.bus.messager.sender.impl.MessagerSender;
+import org.springframework.amqp.core.AmqpTemplate;
+import org.springframework.amqp.core.Queue;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.ComponentScan;
+import org.springframework.context.annotation.Configuration;
+
+/**
+ * Created by niantuo on 2018/9/29.
+ * rabbit配置.
+ * 暂时对这个不了解,暂时使用自动配置结果
+ * 注意分包方式。
+ * 只要导入该包,即可自动配置,无需再用注解。
+ */
+
+@Configuration
+@ComponentScan
+public class RabbitConfiguration {
+
+
+    /***
+     * 这个如果需要使用,改成自己项目的名称
+     * @return 消息队列
+     */
+    @Bean
+    public Queue frameworkQueue() {
+        return new Queue(QueueName.Framework);
+    }
+
+
+    @Bean
+    public IMessagerSender messagerSender(AmqpTemplate template){
+        return new MessagerSender(template);
+    }
+
+
+//    @Bean
+//    public Queue logQueue(){
+//        return  new Queue(QueueName.LOG);
+//    }
+//
+//
+//    @Bean
+//    public LoggerReceiver loggerReceiver(){
+//        return new LoggerReceiver();
+//    }
+
+}

+ 90 - 0
cloud-bus/src/main/java/cn/gygxzc/envir/bus/entity/PushModel.java

@@ -0,0 +1,90 @@
+package cn.gygxzc.envir.bus.entity;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Created by niantuo on 2018/12/17.
+ * 消息推送的模型
+ * @see   PushModel
+ * type 为100 表示群发系统消息。content 应该是富文本。toUserIds 可为null或者是空
+ */
+
+public class PushModel {
+
+    public static final int TYPE_SYS=100;//群发的系统消息
+
+    private String content;
+    private int type;
+    private String contentType;
+    private String urls;
+    private String title;
+    private String remark;
+    private List<Long> toUserIds = new ArrayList<>();
+
+    public String getContent() {
+        return content;
+    }
+
+    public void setContent(String content) {
+        this.content = content;
+    }
+
+    public int getType() {
+        return type;
+    }
+
+    public void setType(int type) {
+        this.type = type;
+    }
+
+    public String getContentType() {
+        return contentType;
+    }
+
+    public void setContentType(String contentType) {
+        this.contentType = contentType;
+    }
+
+    public String getUrls() {
+        return urls;
+    }
+
+    public void setUrls(String urls) {
+        this.urls = urls;
+    }
+
+    public String getTitle() {
+        return title;
+    }
+
+    public void setTitle(String title) {
+        this.title = title;
+    }
+
+    public String getRemark() {
+        return remark;
+    }
+
+    public void setRemark(String remark) {
+        this.remark = remark;
+    }
+
+    public List<Long> getToUserIds() {
+        return toUserIds;
+    }
+
+    public void setToUserIds(List<Long> toUserIds) {
+        this.toUserIds = toUserIds;
+    }
+
+
+    /**
+     * 这个先随便写点吧,
+     * @return
+     */
+    @Override
+    public String toString() {
+        return String.format("type: %s,content:%s",type,content);
+    }
+}

+ 19 - 0
cloud-bus/src/main/java/cn/gygxzc/envir/bus/mail/IFeignMailSender.java

@@ -0,0 +1,19 @@
+package cn.gygxzc.envir.bus.mail;
+
+import cn.gygxzc.envir.core.entity.MailEntity;
+import org.springframework.cloud.openfeign.FeignClient;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+
+/**
+ * 用Feign进行服务间调用方式发送邮件
+ *
+ * @author tuonina
+ * @createTime 2019/3/4
+ */
+@FeignClient("msg")
+public interface IFeignMailSender {
+
+    @PostMapping(value = "/mail")
+    void sendMail(@RequestBody MailEntity mail);
+}

+ 12 - 0
cloud-bus/src/main/java/cn/gygxzc/envir/bus/mail/IMailBusSender.java

@@ -0,0 +1,12 @@
+package cn.gygxzc.envir.bus.mail;
+
+import cn.gygxzc.envir.core.entity.MailEntity;
+
+/**
+ * @author tuonina
+ * @createTime 2019/3/4
+ */
+public interface IMailBusSender {
+
+    void sendMail(MailEntity mail);
+}

+ 27 - 0
cloud-bus/src/main/java/cn/gygxzc/envir/bus/mail/impl/MailBusSenderImpl.java

@@ -0,0 +1,27 @@
+package cn.gygxzc.envir.bus.mail.impl;
+
+import cn.gygxzc.envir.bus.QueueName;
+import cn.gygxzc.envir.bus.mail.IMailBusSender;
+import cn.gygxzc.envir.core.entity.MailEntity;
+import org.springframework.amqp.core.AmqpTemplate;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+/**
+ * @author tuonina
+ * @createTime 2019/3/4
+ */
+@Service
+public class MailBusSenderImpl implements IMailBusSender {
+    private final AmqpTemplate template;
+
+    @Autowired
+    public MailBusSenderImpl(AmqpTemplate template) {
+        this.template = template;
+    }
+
+    @Override
+    public void sendMail(MailEntity mail) {
+        template.convertAndSend(QueueName.EMAIL, mail);
+    }
+}

+ 17 - 0
cloud-bus/src/main/java/cn/gygxzc/envir/bus/message/IMessagePusher.java

@@ -0,0 +1,17 @@
+package cn.gygxzc.envir.bus.message;
+
+import cn.gygxzc.envir.bus.entity.PushModel;
+
+import java.util.List;
+
+/**
+ * Created by niantuo on 2018/12/17.
+ */
+
+public interface IMessagePusher {
+
+    void pushTo(List<Long> userIds, PushModel model);
+
+
+
+}

+ 32 - 0
cloud-bus/src/main/java/cn/gygxzc/envir/bus/message/impl/MessagePusher.java

@@ -0,0 +1,32 @@
+package cn.gygxzc.envir.bus.message.impl;
+
+import cn.gygxzc.envir.bus.entity.PushModel;
+import cn.gygxzc.envir.bus.message.IMessagePusher;
+import cn.gygxzc.tina.cloud.bus.constant.QueueName;
+import cn.gygxzc.tina.cloud.bus.utils.GsonUtils;
+import org.springframework.amqp.core.AmqpTemplate;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.util.List;
+
+/**
+ * Created by niantuo on 2018/12/17.
+ * 消息推送的服务
+ */
+@Service
+public class MessagePusher implements IMessagePusher {
+
+    private final AmqpTemplate amqpTemplate;
+
+    @Autowired
+    public MessagePusher(AmqpTemplate amqpTemplate) {
+        this.amqpTemplate = amqpTemplate;
+    }
+
+    @Override
+    public void pushTo(List<Long> userIds, PushModel model) {
+        model.setToUserIds(userIds);
+        amqpTemplate.convertAndSend(QueueName.PUSHER, GsonUtils.toJson(model));
+    }
+}

+ 13 - 0
cloud-bus/src/main/java/cn/gygxzc/tina/cloud/bus/constant/QueueName.java

@@ -0,0 +1,13 @@
+package cn.gygxzc.tina.cloud.bus.constant;
+
+/**
+ * Created by niantuo on 2018/9/29.
+ * 消息队列的名称,固定的
+ */
+
+public interface QueueName {
+    String Messager = "Messager";
+    String PUSHER = "PUSHER";//消息推送服务
+    String Framework = "Framework";
+    String LOG = "LOG";
+}

+ 27 - 0
cloud-bus/src/main/java/cn/gygxzc/tina/cloud/bus/framweork/bean/FrameworkBean.java

@@ -0,0 +1,27 @@
+package cn.gygxzc.tina.cloud.bus.framweork.bean;
+
+/**
+ * Created by niantuo on 2018/9/29.
+ * 框架消息的实体类
+ */
+
+public class FrameworkBean {
+    private int cloud;
+    private String message;
+
+    public int getCloud() {
+        return cloud;
+    }
+
+    public void setCloud(int cloud) {
+        this.cloud = cloud;
+    }
+
+    public String getMessage() {
+        return message;
+    }
+
+    public void setMessage(String message) {
+        this.message = message;
+    }
+}

+ 31 - 0
cloud-bus/src/main/java/cn/gygxzc/tina/cloud/bus/framweork/receiver/FrameworkReceiver.java

@@ -0,0 +1,31 @@
+package cn.gygxzc.tina.cloud.bus.framweork.receiver;
+
+import cn.gygxzc.tina.cloud.bus.constant.QueueName;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.amqp.rabbit.annotation.RabbitHandler;
+import org.springframework.amqp.rabbit.annotation.RabbitListener;
+import org.springframework.stereotype.Component;
+
+/**
+ * Created by niantuo on 2018/9/29.
+ * 框架消息接收者,这个扯淡的
+ */
+@Component
+@RabbitListener(queues = {QueueName.Framework})
+public class FrameworkReceiver {
+
+    private Logger logger = LoggerFactory.getLogger(FrameworkReceiver.class);
+
+    /**
+     * 接收消息处理
+     *
+     * @param receiver 消息实体类
+     */
+    @RabbitHandler
+    public void process(FrameworkReceiver receiver) {
+        logger.info("receive :{}", receiver);
+    }
+
+
+}

+ 22 - 0
cloud-bus/src/main/java/cn/gygxzc/tina/cloud/bus/framweork/receiver/LoggerReceiver.java

@@ -0,0 +1,22 @@
+package cn.gygxzc.tina.cloud.bus.framweork.receiver;
+
+import cn.gygxzc.envir.core.logger.LogMessage;
+import cn.gygxzc.tina.cloud.bus.constant.QueueName;
+import org.springframework.amqp.rabbit.annotation.RabbitHandler;
+import org.springframework.amqp.rabbit.annotation.RabbitListener;
+import org.springframework.stereotype.Component;
+
+/**
+ * Created by niantuo on 2018/11/5.
+ * 日志收集器.
+ */
+@Component
+@RabbitListener(queues = QueueName.LOG)
+public class LoggerReceiver {
+
+    @RabbitHandler
+    public void mqLog(LogMessage message) {
+        System.out.printf("message:%s",message);
+    }
+
+}

+ 36 - 0
cloud-bus/src/main/java/cn/gygxzc/tina/cloud/bus/messager/bean/MessageBean.java

@@ -0,0 +1,36 @@
+package cn.gygxzc.tina.cloud.bus.messager.bean;
+
+import java.io.Serializable;
+
+/**
+ * Created by niantuo on 2018/9/29.
+ * 消息发送的实体类
+ */
+
+public class MessageBean implements Serializable {
+    public static final long serialVersionUID = 1L;
+    private int code;
+    private String message;
+
+    public int getCode() {
+        return code;
+    }
+
+    public void setCode(int code) {
+        this.code = code;
+    }
+
+    public String getMessage() {
+        return message;
+    }
+
+    public void setMessage(String message) {
+        this.message = message;
+    }
+
+    @Override
+    public String toString() {
+        return "code: " + code + "  message: " + message;
+    }
+
+}

+ 15 - 0
cloud-bus/src/main/java/cn/gygxzc/tina/cloud/bus/messager/sender/IMessagerSender.java

@@ -0,0 +1,15 @@
+package cn.gygxzc.tina.cloud.bus.messager.sender;
+
+import cn.gygxzc.envir.core.logger.ILoggerSender;
+import cn.gygxzc.tina.cloud.bus.messager.bean.MessageBean;
+
+/**
+ * Created by niantuo on 2018/9/29.
+ * 定义发送消息给消息中心的消息发送者
+ */
+
+public interface IMessagerSender extends ILoggerSender {
+
+    void send(MessageBean message);
+
+}

+ 42 - 0
cloud-bus/src/main/java/cn/gygxzc/tina/cloud/bus/messager/sender/impl/MessagerSender.java

@@ -0,0 +1,42 @@
+package cn.gygxzc.tina.cloud.bus.messager.sender.impl;
+
+import cn.gygxzc.envir.core.logger.LogMessage;
+import cn.gygxzc.tina.cloud.bus.constant.QueueName;
+import cn.gygxzc.tina.cloud.bus.messager.bean.MessageBean;
+import cn.gygxzc.tina.cloud.bus.messager.sender.IMessagerSender;
+import org.springframework.amqp.core.AmqpTemplate;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+/**
+ * Created by niantuo on 2018/9/29.
+ * 发送给消息中心的发送者
+ */
+@Component
+public class MessagerSender implements IMessagerSender {
+
+    private final AmqpTemplate amqpTemplate;
+
+    @Autowired
+    public MessagerSender(AmqpTemplate amqpTemplate) {
+        this.amqpTemplate = amqpTemplate;
+    }
+
+    /**
+     * 发送消息给消息中心
+     *
+     * @param message 消息内容
+     */
+    @Override
+    public void send(MessageBean message) {
+        amqpTemplate.convertAndSend(QueueName.Messager, message);
+    }
+
+
+    @Override
+    public void send(LogMessage message) {
+        amqpTemplate.convertAndSend(QueueName.LOG, message);
+    }
+
+
+}

+ 26 - 0
cloud-bus/src/main/java/cn/gygxzc/tina/cloud/bus/utils/GsonUtils.java

@@ -0,0 +1,26 @@
+package cn.gygxzc.tina.cloud.bus.utils;
+
+import com.google.gson.Gson;
+
+/**
+ * Created by niantuo on 2018/11/5.
+ */
+
+public class GsonUtils {
+    private final static Gson mGson = new Gson();
+
+    public static String toJson(Object obj) {
+        return mGson.toJson(obj);
+    }
+
+    /**
+     * 实际上如果是数组,这样子是解析不出来的吧。
+     * @param clz 要返回的类型
+     * @param json 原始json数据
+     * @param <T> 泛型
+     * @return
+     */
+    public static <T> T fromJson(Class<T> clz, String json) {
+        return mGson.fromJson(json, clz);
+    }
+}

+ 15 - 0
fastdfs-client/build.gradle

@@ -0,0 +1,15 @@
+group 'cn.gygxzc.cloud'
+version '1.0'
+
+sourceCompatibility = 1.8
+
+repositories {
+    mavenCentral()
+}
+
+dependencies {
+    testCompile group: 'junit', name: 'junit', version: '4.12'
+    // https://mvnrepository.com/artifact/com.github.tobato/fastdfs-client
+    compile("com.github.tobato:fastdfs-client:1.26.3")
+
+}

+ 23 - 0
fastdfs-client/src/main/java/cn/gygxzc/cloud/tina/fastdfs/client/EnableFastDFSClient.java

@@ -0,0 +1,23 @@
+package cn.gygxzc.cloud.tina.fastdfs.client;
+
+import com.github.tobato.fastdfs.FdfsClientConfig;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.EnableMBeanExport;
+import org.springframework.context.annotation.Import;
+import org.springframework.jmx.support.RegistrationPolicy;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+/**
+ * Created by niantuo on 2018/10/27.
+ * 开启dfs客户端支持
+ */
+@Configuration
+@Documented
+@Retention(java.lang.annotation.RetentionPolicy.RUNTIME)
+@Target({java.lang.annotation.ElementType.TYPE})
+@Import(value = {FastDFSClientConfiguration.class})
+public @interface EnableFastDFSClient {
+}

+ 20 - 0
fastdfs-client/src/main/java/cn/gygxzc/cloud/tina/fastdfs/client/FastDFSClientConfiguration.java

@@ -0,0 +1,20 @@
+package cn.gygxzc.cloud.tina.fastdfs.client;
+
+import com.github.tobato.fastdfs.FdfsClientConfig;
+import org.springframework.context.annotation.ComponentScan;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.EnableMBeanExport;
+import org.springframework.context.annotation.Import;
+import org.springframework.jmx.support.RegistrationPolicy;
+
+/**
+ * Created by niantuo on 2018/10/27.
+ * 使用fastDFS 客户端配置
+ */
+
+@Configuration
+@ComponentScan
+@Import(FdfsClientConfig.class)
+@EnableMBeanExport(registration = RegistrationPolicy.IGNORE_EXISTING)
+public class FastDFSClientConfiguration {
+}

+ 60 - 0
fastdfs-client/src/main/java/cn/gygxzc/cloud/tina/fastdfs/client/controller/FdfsDownloadController.java

@@ -0,0 +1,60 @@
+package cn.gygxzc.cloud.tina.fastdfs.client.controller;
+
+import com.github.tobato.fastdfs.proto.storage.DownloadCallback;
+import com.github.tobato.fastdfs.service.FastFileStorageClient;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestMapping;
+
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+/**
+ * Created by niantuo on 2018/10/29.
+ * 文件下载或者说是
+ */
+@Controller
+@RequestMapping("/files")
+public class FdfsDownloadController {
+
+    @Autowired
+    private FastFileStorageClient storageClient;
+
+    @RequestMapping("/{group}/{path}")
+    public void download(@PathVariable("group") String group, @PathVariable("path") String path, HttpServletResponse response) {
+        InputStream inputStream = null;
+        OutputStream outputStream = null;
+        try {
+            inputStream = storageClient.downloadFile(group, path, ins -> ins);
+            outputStream = response.getOutputStream();
+            byte[] bytes = new byte[1024];
+            while ((inputStream.read(bytes)) != -1) {
+                outputStream.write(bytes, 0, bytes.length);
+            }
+            response.flushBuffer();
+        } catch (IOException e) {
+            throw new RuntimeException("文件下载失败,请重试。");
+        } finally {
+            if (inputStream != null) {
+                try {
+                    inputStream.close();
+                } catch (IOException e) {
+                    e.printStackTrace();
+                }
+            }
+            if (outputStream != null) {
+                try {
+                    outputStream.flush();
+                    outputStream.close();
+                } catch (IOException e) {
+                    e.printStackTrace();
+                }
+
+            }
+        }
+    }
+
+}

+ 120 - 0
fastdfs-client/src/main/java/cn/gygxzc/cloud/tina/fastdfs/client/controller/FdfsUploadController.java

@@ -0,0 +1,120 @@
+package cn.gygxzc.cloud.tina.fastdfs.client.controller;
+
+import cn.gygxzc.cloud.tina.fastdfs.client.mata.CommonFileMata;
+import cn.gygxzc.cloud.tina.fastdfs.client.mata.FailedStorePath;
+import cn.gygxzc.cloud.tina.fastdfs.client.utils.FileUtils;
+import com.github.tobato.fastdfs.domain.MataData;
+import com.github.tobato.fastdfs.domain.StorePath;
+import com.github.tobato.fastdfs.proto.AbstractFdfsCommand;
+import com.github.tobato.fastdfs.service.FastFileStorageClient;
+import io.reactivex.Observable;
+import io.reactivex.Single;
+import io.reactivex.SingleOnSubscribe;
+import io.reactivex.schedulers.Schedulers;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.*;
+import org.springframework.web.multipart.MultipartFile;
+
+import java.io.IOException;
+import java.util.*;
+import java.util.concurrent.TimeUnit;
+
+
+/**
+ * Created by niantuo on 2018/10/27.
+ * 文件上传接口。
+ * 文件上传的接口
+ */
+@RestController
+@RequestMapping("/files/upload")
+public class FdfsUploadController {
+
+    @Autowired
+    private FastFileStorageClient storageClient;
+
+
+    /**
+     * 上传文件,需要自己附带一些信息
+     *
+     * @param file     文件本身信息
+     * @param fileMata 文件的自定义数据
+     * @return 文件的
+     */
+    @PostMapping
+    public Object upload(@RequestParam("file") MultipartFile file, CommonFileMata fileMata) {
+
+        Set<MataData> mataData = fileMata.mataData(file);
+        String fileExtName = FileUtils.getFileExtName(file.getOriginalFilename());
+        try {
+            return storageClient.uploadFile(file.getInputStream(), file.getSize(), fileExtName, mataData);
+        } catch (IOException e) {
+            throw new RuntimeException("文件上传失败,请重试。");
+        }
+    }
+
+    /**
+     * 多文件上传。
+     * 暂时这种方式不知道会有什么风险。
+     * 把这个线程挂起来是不是也浪费了一些性能。
+     *
+     * @param files    文件信息
+     * @param fileMata 文件描述
+     * @return 文件的下载路径,不保证,顺序
+     */
+    @PostMapping("/multi")
+    public Object multiUpload(@RequestParam("files") List<MultipartFile> files, CommonFileMata fileMata) {
+
+        final Object mLock = new Object();
+        List<FailedStorePath> failedStorePaths = new ArrayList<>();
+        List<StorePath> storePaths = new ArrayList<>();
+        Observable.fromIterable(files)
+                .flatMapSingle(file -> uploadToFdfs(file, fileMata))
+                .doOnNext(storePath -> {
+                    if (storePath instanceof FailedStorePath) {
+                        failedStorePaths.add((FailedStorePath) storePath);
+                    } else {
+                        storePaths.add(storePath);
+                    }
+                })
+                .toList()
+                .subscribe(results -> {
+                    synchronized (mLock) {
+                        mLock.notifyAll();
+                    }
+                });
+        synchronized (mLock) {
+            try {
+                mLock.wait();
+            } catch (InterruptedException e) {
+                e.printStackTrace();
+            }
+        }
+        Map<String, Object> results = new HashMap<>();
+        results.put("paths", storePaths);
+        results.put("error", failedStorePaths);
+        return results;
+    }
+
+
+    /**
+     * 多文件上传,有可能只有一两个文件失败,这个时候,需要做一些处理.
+     * 设置文件上传最大的超时时长为两分钟,过长会影响用户体验
+     *
+     * @param file     上传的文件
+     * @param fileMata 文件的描述
+     * @return 文件的地址信息
+     */
+    private Single<StorePath> uploadToFdfs(MultipartFile file, CommonFileMata fileMata) {
+        return Single.create((SingleOnSubscribe<StorePath>) subscriber -> {
+            Set<MataData> mataData = fileMata.mataData(file);
+            String fileExtName = file.getOriginalFilename();
+            StorePath storePath = storageClient.uploadFile(file.getInputStream(), file.getSize(), fileExtName, mataData);
+            subscriber.onSuccess(storePath);
+        })
+                .timeout(2, TimeUnit.MINUTES)
+                .retry(3)
+                .onErrorReturn(throwable -> new FailedStorePath(file))
+                .subscribeOn(Schedulers.io());
+    }
+
+}

+ 32 - 0
fastdfs-client/src/main/java/cn/gygxzc/cloud/tina/fastdfs/client/mata/CommonFileMata.java

@@ -0,0 +1,32 @@
+package cn.gygxzc.cloud.tina.fastdfs.client.mata;
+
+import com.github.tobato.fastdfs.domain.MataData;
+import org.springframework.web.multipart.MultipartFile;
+
+import java.util.HashSet;
+import java.util.Set;
+
+/**
+ * Created by niantuo on 2018/10/27.
+ */
+
+public class CommonFileMata {
+    private String description;
+
+    public void setDescription(String description) {
+        this.description = description;
+    }
+
+    public String getDescription() {
+        return description;
+    }
+
+    public Set<MataData> mataData(MultipartFile file){
+        Set<MataData> mataDataSet = new HashSet<>();
+        mataDataSet.add(new MataData("originalName",file.getOriginalFilename()));
+        mataDataSet.add(new MataData("size",String.valueOf(file.getSize())));
+        mataDataSet.add(new MataData("name",file.getName()));
+        mataDataSet.add(new MataData("description",description));
+        return mataDataSet;
+    }
+}

+ 42 - 0
fastdfs-client/src/main/java/cn/gygxzc/cloud/tina/fastdfs/client/mata/FailedStorePath.java

@@ -0,0 +1,42 @@
+package cn.gygxzc.cloud.tina.fastdfs.client.mata;
+
+import com.github.tobato.fastdfs.domain.StorePath;
+import org.springframework.web.multipart.MultipartFile;
+
+/**
+ * Created by niantuo on 2018/10/27.
+ * 上传失败的storePath
+ */
+
+public class FailedStorePath extends StorePath {
+
+    private String originalName;
+    private String fileName;
+
+
+    public FailedStorePath(MultipartFile file){
+        this.fileName = file.getName();
+        this.originalName = file.getOriginalFilename();
+    }
+
+    public FailedStorePath(String fileName, String originalName) {
+        this.originalName = originalName;
+        this.fileName = fileName;
+    }
+
+    public void setFileName(String fileName) {
+        this.fileName = fileName;
+    }
+
+    public void setOriginalName(String originalName) {
+        this.originalName = originalName;
+    }
+
+    public String getFileName() {
+        return fileName;
+    }
+
+    public String getOriginalName() {
+        return originalName;
+    }
+}

+ 28 - 0
fastdfs-client/src/main/java/cn/gygxzc/cloud/tina/fastdfs/client/utils/FileUtils.java

@@ -0,0 +1,28 @@
+package cn.gygxzc.cloud.tina.fastdfs.client.utils;
+
+import org.apache.commons.lang.StringUtils;
+
+/**
+ * Created by niantuo on 2018/10/29.
+ * 文件相关的方法
+ */
+
+public class FileUtils {
+    private final static String UNKNOWN_EXT = "unknown";
+
+    /**
+     * 获取文件的后缀名称
+     *
+     * @return 文件的后缀
+     */
+    public static String getFileExtName(String fileName) {
+        if (StringUtils.isBlank(fileName)) {
+            return UNKNOWN_EXT;
+        }
+        int index = fileName.lastIndexOf(".");
+        if (index == 0) {
+            return UNKNOWN_EXT;
+        }
+        return fileName.substring(index + 1);
+    }
+}

+ 27 - 0
fastdfs-client/src/main/resources/application-fdfs.yml

@@ -0,0 +1,27 @@
+
+
+# fdfs 分布式文件服务器
+
+---
+spring:
+  profiles: dev
+fdfs:
+  connect-timeout: 600
+  so-timeout: 1500
+  thumb-image:
+    height: 150
+    width: 150
+  tracker-list:
+    - 192.168.1.206:22122
+---
+spring:
+  profiles: prod
+
+fdfs:
+  connect-timeout: 600
+  so-timeout: 1500
+  thumb-image:
+    height: 150
+    width: 150
+  tracker-list:
+  -  192.168.1.206:22122

+ 60 - 0
fastdfs-client/src/test/java/cn/gygxzc/cloud/tina/fdfs/RxJavaTest.java

@@ -0,0 +1,60 @@
+package cn.gygxzc.cloud.tina.fdfs;
+
+import io.reactivex.Observable;
+import io.reactivex.Single;
+import io.reactivex.SingleEmitter;
+import io.reactivex.SingleOnSubscribe;
+import io.reactivex.schedulers.Schedulers;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Created by niantuo on 2018/10/27.
+ * 这种方式的确是可以使用的,但是不知道在实际过程中会不会表现很糟糕
+ */
+
+public class RxJavaTest {
+
+    public static void main(String[] args) {
+        List<Integer> integers = new ArrayList<>();
+        final Object mLock = new Object();
+        integers.add(1000);
+        integers.add(2000);
+        integers.add(2500);
+        integers.add(500);
+        integers.add(1500);
+        long startTime = System.currentTimeMillis();
+        Observable.fromIterable(integers)
+                .flatMapSingle(RxJavaTest::task)
+                .doOnNext(threadId->{
+                    System.out.printf("onNex: %d,threadId:%d \n",System.currentTimeMillis(),threadId);
+                })
+                .toList()
+                .subscribe(list->{
+                    System.out.printf("complete time: %d \n",System.currentTimeMillis());
+                    synchronized (mLock){
+                        mLock.notifyAll();
+                    }
+                });
+        synchronized (mLock){
+            try {
+                mLock.wait();
+            } catch (InterruptedException e) {
+                e.printStackTrace();
+            }
+        }
+        System.out.printf("main thread:%d  耗时:%d  \n",System.currentTimeMillis(),System.currentTimeMillis()-startTime);
+    }
+
+    private static Single<Long> task(long sleep){
+        return Single.create((SingleOnSubscribe<Long>) emitter -> {
+            System.out.printf("current thread: %d,start Time: %d \n",Thread.currentThread().getId(),System.currentTimeMillis());
+            Thread.sleep(sleep);
+            emitter.onSuccess(Thread.currentThread().getId());
+            System.out.printf("current thread: %d,end Time: %d \n",Thread.currentThread().getId(),System.currentTimeMillis());
+        }).subscribeOn(Schedulers.io())
+                .retry(3);
+    }
+
+}

+ 14 - 0
fastdfs-client/src/test/java/cn/gygxzc/cloud/tina/fdfs/utils/FileUtilsTest.java

@@ -0,0 +1,14 @@
+package cn.gygxzc.cloud.tina.fdfs.utils;
+
+import cn.gygxzc.cloud.tina.fastdfs.client.utils.FileUtils;
+
+/**
+ * Created by niantuo on 2018/10/29.
+ */
+
+public class FileUtilsTest {
+    public static void main(String[] args) {
+        String fileName="123.png";
+        System.out.printf("extName:%s", FileUtils.getFileExtName(fileName));
+    }
+}

+ 1 - 1
gradle/wrapper/gradle-wrapper.properties

@@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME
 distributionPath=wrapper/dists
 zipStoreBase=GRADLE_USER_HOME
 zipStorePath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-4.0-all.zip
+distributionUrl=https\://services.gradle.org/distributions/gradle-4.4-all.zip

BIN
jwt-session-1.2.jar


+ 2 - 1
settings.gradle

@@ -2,5 +2,6 @@ rootProject.name = 'Zen-Framework'
 include 'zen-core'
 include 'zen-api'
 include 'zen-web'
-include 'zen-job'
+include 'cloud-bus'
+include 'fastdfs-client'
 

+ 3 - 0
zen-api/src/main/java/cn/gygxzc/envir/biz/dao/Dao.java

@@ -1,9 +1,12 @@
 package cn.gygxzc.envir.biz.dao;
 
+import com.baomidou.mybatisplus.core.toolkit.IdWorker;
+
 /**
  * Created by niantuo on 2018/9/28.
  * 把 Dao 类写在该路径下
  */
 
 public class Dao {
+
 }

+ 16 - 0
zen-api/src/main/java/cn/gygxzc/envir/test/dao/ITestLogDao.java

@@ -0,0 +1,16 @@
+package cn.gygxzc.envir.test.dao;
+
+import cn.gygxzc.envir.test.model.TestLog;
+import cn.gygxzc.envir.core.orm.base.IPhysicalMapper;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import org.springframework.stereotype.Repository;
+
+/**
+ * Created by niantuo on 2018/9/30.
+ * 数据库dao类
+ *
+ * @see IPhysicalMapper  物理操作需要继承该类
+ */
+@Repository
+public interface ITestLogDao extends BaseMapper<TestLog>, IPhysicalMapper<TestLog> {
+}

+ 22 - 0
zen-api/src/main/java/cn/gygxzc/envir/test/model/TestLog.java

@@ -0,0 +1,22 @@
+package cn.gygxzc.envir.test.model;
+
+
+import cn.gygxzc.envir.core.base.BaseModel;
+import com.baomidou.mybatisplus.annotation.TableName;
+
+/**
+ * Created by niantuo on 2018/9/30.
+ * 测试用的数据库表模型
+ */
+@TableName(value = "test_log")
+public class TestLog extends BaseModel {
+    private String message;
+
+    public void setMessage(String message) {
+        this.message = message;
+    }
+
+    public String getMessage() {
+        return message;
+    }
+}

+ 39 - 0
zen-api/src/main/java/cn/gygxzc/envir/test/service/ITestLogService.java

@@ -0,0 +1,39 @@
+package cn.gygxzc.envir.test.service;
+
+import cn.gygxzc.envir.test.model.TestLog;
+
+/**
+ * Created by niantuo on 2018/9/30.
+ */
+
+public interface ITestLogService {
+
+    /**
+     * 添加数据
+     *
+     * @param log 添加数据
+     */
+    TestLog addLog(TestLog log);
+
+    /**
+     * 更新数据
+     *
+     * @param log 数据对象
+     */
+    void update(TestLog log);
+
+    /**
+     * 物理删除
+     *
+     * @param id 记录的id
+     */
+    void physicalDeleteById(long id);
+
+    /**
+     * 逻辑删除
+     *
+     * @param id 记录的id
+     */
+    void deleteById(long id);
+
+}

+ 51 - 0
zen-api/src/main/java/cn/gygxzc/envir/test/service/impl/TestLogService.java

@@ -0,0 +1,51 @@
+package cn.gygxzc.envir.test.service.impl;
+
+import cn.gygxzc.envir.test.dao.ITestLogDao;
+import cn.gygxzc.envir.test.model.TestLog;
+import cn.gygxzc.envir.test.service.ITestLogService;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+/**
+ * Created by niantuo on 2018/9/30.
+ */
+@Service
+public class TestLogService implements ITestLogService {
+    private final static Logger logger = LoggerFactory.getLogger(TestLogService.class);
+
+    private final ITestLogDao testLogDao;
+
+    @Autowired
+    public TestLogService(ITestLogDao testLogDao) {
+        this.testLogDao = testLogDao;
+    }
+
+
+    @Override
+    public TestLog addLog(TestLog log) {
+        int result = testLogDao.insert(log);
+        logger.info("add log  result:{},entity:{}", result, log);
+        return log;
+    }
+
+    @Override
+    public void update(TestLog log) {
+        int result = testLogDao.updateById(log);
+        logger.info("update result:{},entity:{}", result, log);
+    }
+
+    @Override
+    public void physicalDeleteById(long id) {
+        int result = testLogDao.physicalDeleteById(id);
+        logger.info("physicalDeleteById result:{}", result);
+
+    }
+
+    @Override
+    public void deleteById(long id) {
+        int result = testLogDao.deleteById(id);
+        logger.info("deleteById  result:{}", result);
+    }
+}

+ 0 - 139
zen-api/src/main/kotlin/cn/gygxzc/envir/config/shiro/ShiroConfig.kt

@@ -1,139 +0,0 @@
-package cn.gygxzc.envir.config.shiro
-
-import cn.gygxzc.envir.config.shiro.cache.RedisConfiguration
-import cn.gygxzc.envir.config.shiro.filter.AjaxAuthorizationFilter
-import cn.gygxzc.envir.config.shiro.filter.ZenCorsAnonymousFilter
-import cn.gygxzc.envir.config.shiro.filter.ZenCorsPathMatchingFilter
-import cn.gygxzc.envir.config.shiro.realm.ZenShiroRealm
-import org.apache.shiro.authc.credential.HashedCredentialsMatcher
-import org.apache.shiro.cache.CacheManager
-import org.apache.shiro.mgt.SecurityManager
-import org.apache.shiro.realm.AuthorizingRealm
-import org.apache.shiro.spring.LifecycleBeanPostProcessor
-import org.apache.shiro.spring.web.ShiroFilterFactoryBean
-import org.apache.shiro.web.filter.authc.AnonymousFilter
-import org.apache.shiro.web.mgt.DefaultWebSecurityManager
-import org.apache.shiro.web.session.mgt.ServletContainerSessionManager
-import org.springframework.beans.factory.annotation.Qualifier
-import org.springframework.boot.autoconfigure.condition.ConditionalOnClass
-import org.springframework.boot.web.servlet.FilterRegistrationBean
-import org.springframework.context.annotation.Bean
-import org.springframework.context.annotation.Configuration
-import org.springframework.context.annotation.DependsOn
-import org.springframework.core.annotation.Order
-import org.springframework.web.filter.DelegatingFilterProxy
-import javax.servlet.DispatcherType
-import javax.servlet.Filter
-
-
-/**
- * Shiro配置
- * @author NorthLan
- * @date 2018/4/21
- * @url https://noahlan.com
- */
-@Configuration
-@ConditionalOnClass(value = [RedisConfiguration::class])
-class ShiroConfig {
-
-    @Bean("shiroLifecycleBeanPostProcessor")
-    fun lifecycleBeanPostProcessor(): LifecycleBeanPostProcessor {
-        return LifecycleBeanPostProcessor()
-    }
-
-    @Bean
-    @DependsOn(value = ["shiroLifecycleBeanPostProcessor", "shiroRedisCacheManager"])
-    fun userRealm(@Qualifier("shiroRedisCacheManager") cacheManager: CacheManager): ZenShiroRealm {
-        val shiroRealm = ZenShiroRealm()
-                .apply {
-                    isCachingEnabled = true
-                    isAuthenticationCachingEnabled = true
-                    isAuthorizationCachingEnabled = true
-                    //加密验证方法
-                    credentialsMatcher = HashedCredentialsMatcher().also {
-                        it.hashAlgorithmName = "md5"
-                        it.hashIterations = 2 // 两次md5
-                    }
-                }
-        shiroRealm.cacheManager = cacheManager
-        return shiroRealm
-    }
-
-    @Bean(name = ["securityManager"])
-    fun securityManager(userRealm: AuthorizingRealm,
-                        @Qualifier("shiroRedisCacheManager") redisCacheManager: CacheManager): DefaultWebSecurityManager {
-        return DefaultWebSecurityManager().apply {
-            setRealm(userRealm)
-            cacheManager = redisCacheManager
-            sessionManager = ServletContainerSessionManager()
-        }
-    }
-
-    @Bean("shiroFilterRegistrationBean")
-    @DependsOn("shiroFilter")
-    fun filterRegistrationBean(): FilterRegistrationBean<DelegatingFilterProxy> {
-        return FilterRegistrationBean<DelegatingFilterProxy>().apply {
-            filter = DelegatingFilterProxy("shiroFilter")
-            isEnabled = true
-            addUrlPatterns("/*")
-            setDispatcherTypes(DispatcherType.REQUEST)
-        }
-    }
-
-    @Bean(name = ["shiroFilter"])
-    @Order(2)
-    fun shiroFilter(securityManager: SecurityManager): ShiroFilterFactoryBean {
-        return ShiroFilterFactoryBean().apply {
-            setSecurityManager(securityManager)
-
-            filters = hashMapOf<String, Filter>(
-                    "canon" to ZenCorsAnonymousFilter(),
-                    "cors" to ZenCorsPathMatchingFilter(),
-                    "authc" to AjaxAuthorizationFilter(),
-                    "anon" to AnonymousFilter()
-            )
-            /**
-             * anon(匿名)  org.apache.shiro.web.filter.authc.AnonymousFilter
-             * authc(身份验证)       org.apache.shiro.web.filter.authc.FormAuthenticationFilter
-             * authcBasic(http基本验证)    org.apache.shiro.web.filter.authc.BasicHttpAuthenticationFilter
-             * logout(退出)        org.apache.shiro.web.filter.authc.LogoutFilter
-             * noSessionCreation(不创建session) org.apache.shiro.web.filter.session.NoSessionCreationFilter
-             * perms(许可验证)  org.apache.shiro.web.filter.authz.PermissionsAuthorizationFilter
-             * port(端口验证)   org.apache.shiro.web.filter.authz.PortFilter
-             * rest  (rest方面)  org.apache.shiro.web.filter.authz.HttpMethodPermissionFilter
-             * roles(权限验证)  org.apache.shiro.web.filter.authz.RolesAuthorizationFilter
-             * ssl (ssl方面)   org.apache.shiro.web.filter.authz.SslFilter
-             * member (用户方面)  org.apache.shiro.web.filter.authc.UserFilter
-             * user  表示用户不一定已通过认证,只要曾被Shiro记住过登录状态的用户就可以正常发起请求,比如rememberMe
-             */
-            filterChainDefinitionMap = linkedMapOf<String, String>( // BUG 此处一定要使用 linkedHashMap 否则顺序有问题
-                    "/auth/setcookie" to "canon", // 设置cookie
-                    "/auth/check" to "canon", // 检查登录状态
-                    "/auth/logout" to "canon", // 登出
-                    "/test/**" to "canon", // 测试 免登录
-                    "/upload/**" to "canon", // 上传免登录
-                    "/fdfsupload/**" to "canon", // 上传免登录
-                    "/api/**" to "canon", // api 免登陆
-                    "/ws/**" to "canon", // websocket 免登陆
-                    "/" to "canon",
-                    "/v1/login/**" to "canon",
-                    ////////////////////// 静态资源 /////////////////////
-                    "/v2/api-docs" to "canon",
-                    "/swagger-resources/**" to "anon",
-                    "/swagger-ui.html" to "anon",
-                    "/webjars*" to "anon",
-                    "/webjars/**" to "anon",
-                    "/druid/**" to "anon",
-                    "/druid/sql.json" to "anon",
-                    "/**/favicon.*" to "anon",
-                    "/eureka*" to "anon",
-                    "/eureka/**" to "anon",
-                    "/v1/sys" to "anon",
-                    ////////////////////// 静态资源 /////////////////////
-                    "/**" to "cors,authc" // 对于其他未配置的所有url 先设置cors头 再进行登陆判定 最后判定权限
-            )
-        }
-    }
-
-
-}

+ 0 - 61
zen-api/src/main/kotlin/cn/gygxzc/envir/config/shiro/cache/RedisConfiguration.kt

@@ -1,61 +0,0 @@
-package cn.gygxzc.envir.config.shiro.cache
-
-import cn.gygxzc.envir.sys.config.properties.ShiroRedisCacheProperties
-import cn.gygxzc.envir.sys.config.properties.ShiroSessionProperties
-import org.springframework.beans.factory.annotation.Autowired
-import org.springframework.boot.context.properties.EnableConfigurationProperties
-import org.springframework.context.annotation.Bean
-import org.springframework.context.annotation.Configuration
-import org.springframework.context.annotation.DependsOn
-import org.springframework.data.redis.connection.jedis.JedisConnectionFactory
-import org.springframework.data.redis.core.RedisTemplate
-import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer
-import org.springframework.data.redis.serializer.JdkSerializationRedisSerializer
-import org.springframework.data.redis.serializer.StringRedisSerializer
-
-/**
- * @program: Zen-Framework
- *
- * @description: ${description}
- *
- * @author: tuonina
- *
- * @create: 2018-09-20 21:41
- **/
-@Configuration
-@EnableConfigurationProperties(value = [ShiroRedisCacheProperties::class, ShiroSessionProperties::class])
-class RedisConfiguration {
-
-    @Autowired
-    private lateinit var redisProperties: ShiroRedisCacheProperties
-
-    @Autowired
-    private lateinit var sessionProperties: ShiroSessionProperties
-
-    @Bean("shiroRedisConnectionFactory")
-    fun connectionFactory(): JedisConnectionFactory {
-        return JedisConnectionFactory(redisProperties)
-    }
-
-
-    @Bean(name = ["shiroRedisTemplate"])
-    fun redisTemplate(): RedisTemplate<String, Any> {
-        return RedisTemplate<String, Any>().apply {
-            connectionFactory = connectionFactory()
-            val stringSerializer = StringRedisSerializer()
-            keySerializer = stringSerializer
-            valueSerializer = JdkSerializationRedisSerializer()
-            hashKeySerializer = stringSerializer
-            hashValueSerializer = Jackson2JsonRedisSerializer(Any::class.java)
-        }
-    }
-
-
-    @Bean(name = ["shiroRedisCacheManager"])
-    @DependsOn(value = ["shiroRedisTemplate"])
-    fun redisCacheManager(): ShiroRedisCacheManager {
-        return ShiroRedisCacheManager(redisTemplate(), sessionProperties)
-    }
-
-
-}

+ 0 - 119
zen-api/src/main/kotlin/cn/gygxzc/envir/config/shiro/cache/ShiroRedisCache.kt

@@ -1,119 +0,0 @@
-package cn.gygxzc.envir.config.shiro.cache
-
-import cn.gygxzc.tina.cache.redis.RedisKeyGenerator
-import cn.gygxzc.envir.sys.config.properties.ShiroSessionProperties
-import cn.gygxzc.envir.config.shiro.utils.SerializeUtils
-import org.apache.shiro.cache.Cache
-import org.apache.shiro.cache.CacheException
-import org.apache.shiro.subject.PrincipalCollection
-import org.slf4j.LoggerFactory
-import org.springframework.data.redis.core.RedisTemplate
-import java.nio.charset.Charset
-import java.util.*
-import java.util.concurrent.TimeUnit
-
-
-/**
- *
- * @author NorthLan
- * @date 2018/4/23
- * @url https://noahlan.com
- */
-@Suppress("UNCHECKED_CAST")
-class ShiroRedisCache<V> : Cache<Any, V> {
-    companion object {
-        private val logger = LoggerFactory.getLogger(ShiroRedisCache::class.java)
-    }
-
-    private var redisTemplate: RedisTemplate<String, V>
-    private var prefix = "shiro_redis:"
-    private var charset: Charset = Charsets.UTF_8
-    private val properties: ShiroSessionProperties
-
-    constructor(redisTemplate: RedisTemplate<String, V>, properties: ShiroSessionProperties) {
-        this.redisTemplate = redisTemplate
-        this.properties = properties
-    }
-
-    constructor(redisTemplate: RedisTemplate<String, V>, prefix: String, properties: ShiroSessionProperties, charset: Charset = Charsets.UTF_8) {
-        this.redisTemplate = redisTemplate
-        this.prefix = prefix
-        this.properties = properties
-        this.charset = charset
-    }
-
-    override fun values(): MutableCollection<V> {
-        val keys = keys()
-        val values = ArrayList<V>(keys.size)
-        for (k in keys) {
-            get(k)?.let {
-                values.add(it)
-            }
-        }
-        return values
-    }
-
-    override fun clear() {
-        redisTemplate.delete(keys())
-    }
-
-    override fun put(p0: Any?, p1: V?): V? {
-        logger.debug("Put/ Key: $p0, value: $p1")
-        if (p0 == null || p1 == null) {
-            return null
-        }
-        return try {
-            redisTemplate.boundValueOps(getByteKey(p0)).set(p1)
-//            vo.expire(properties.cacheTime, TimeUnit.SECONDS)
-            p1
-        } catch (e: Throwable) {
-            throw CacheException(e)
-        }
-    }
-
-    override fun remove(p0: Any?): V? {
-        logger.debug("Remove/ Key: $p0")
-        if (p0 == null) {
-            return null
-        }
-        return try {
-            val key = getByteKey(p0)
-            val v = redisTemplate.boundValueOps(key).get()
-            redisTemplate.delete(key)
-            v
-        } catch (e: Throwable) {
-            throw CacheException(e)
-        }
-    }
-
-    override fun size(): Int {
-        return keys().size
-    }
-
-    override fun get(p0: Any?): V? {
-        logger.debug("Get/ key: $p0")
-        if (p0 == null) {
-            return null
-        }
-        return try {
-            val vo = redisTemplate.boundValueOps(getByteKey(p0))
-            vo.expire(properties.expired.seconds, TimeUnit.SECONDS)
-            vo.get()
-        } catch (e: Throwable) {
-            throw CacheException(e)
-        }
-    }
-
-    override fun keys(): MutableSet<String> {
-        logger.debug("Keys/ ")
-        return redisTemplate.keys(getByteKey("*"))
-    }
-
-    private fun getByteKey(key: Any): String {
-        return when (key) {
-            is String -> "${this.prefix}${RedisKeyGenerator.SEPARATOR}$key"
-            is PrincipalCollection -> getByteKey(key.primaryPrincipal)
-            else -> SerializeUtils.serialize(key).toString()
-        }
-    }
-}

+ 0 - 21
zen-api/src/main/kotlin/cn/gygxzc/envir/config/shiro/cache/ShiroRedisCacheManager.kt

@@ -1,21 +0,0 @@
-package cn.gygxzc.envir.config.shiro.cache
-
-import cn.gygxzc.envir.sys.config.properties.ShiroSessionProperties
-import org.apache.shiro.cache.AbstractCacheManager
-import org.apache.shiro.cache.Cache
-import org.springframework.data.redis.core.RedisTemplate
-
-
-/**
- *
- * @author NorthLan
- * @date 2018/4/23
- * @url https://noahlan.com
- */
-class ShiroRedisCacheManager(private val redisTemplate: RedisTemplate<String, Any>,
-                             private val properties: ShiroSessionProperties) : AbstractCacheManager() {
-
-    override fun createCache(p0: String): Cache<*, *> {
-        return ShiroRedisCache(redisTemplate, p0, properties)
-    }
-}

+ 0 - 61
zen-api/src/main/kotlin/cn/gygxzc/envir/config/shiro/common/ZenAuthToken.kt

@@ -1,61 +0,0 @@
-package cn.gygxzc.envir.config.shiro.common
-
-import cn.gygxzc.envir.sys.model.SysUser
-import org.apache.shiro.authc.UsernamePasswordToken
-
-/**
- * 登陆用token
- * @author NorthLan
- * @date 2018/4/29
- * @url https://noahlan.com
- */
-class ZenAuthToken : UsernamePasswordToken {
-    var user: SysUser? = null
-
-    constructor() : super()
-    constructor(username: String, password: CharArray) : super(username, password)
-    constructor(username: String, password: String) : super(username, password)
-    constructor(username: String, password: CharArray, host: String) : super(username, password, host)
-    constructor(username: String, password: String, host: String) : super(username, password, host)
-    constructor(username: String, password: CharArray, rememberMe: Boolean) : super(username, password, rememberMe)
-    constructor(username: String, password: String, rememberMe: Boolean) : super(username, password, rememberMe)
-    constructor(username: String, password: CharArray, rememberMe: Boolean, host: String) : super(username, password, rememberMe, host)
-    constructor(username: String, password: String, rememberMe: Boolean, host: String) : super(username, password, rememberMe, host)
-
-    constructor(username: String, password: CharArray, user: SysUser?) : super(username, password) {
-        this.user = user
-    }
-
-    constructor(username: String, password: String, user: SysUser?) : super(username, password) {
-        this.user = user
-    }
-
-    constructor(username: String, password: CharArray, host: String, user: SysUser?) : super(username, password, host) {
-        this.user = user
-    }
-
-    constructor(username: String, password: String, host: String, user: SysUser?) : super(username, password, host) {
-        this.user = user
-    }
-
-    constructor(username: String, password: CharArray, rememberMe: Boolean, user: SysUser?) : super(username, password, rememberMe) {
-        this.user = user
-    }
-
-    constructor(username: String, password: String, rememberMe: Boolean, user: SysUser?) : super(username, password, rememberMe) {
-        this.user = user
-    }
-
-    constructor(username: String, password: CharArray, rememberMe: Boolean, host: String, user: SysUser?) : super(username, password, rememberMe, host) {
-        this.user = user
-    }
-
-    constructor(username: String, password: String, rememberMe: Boolean, host: String, user: SysUser?) : super(username, password, rememberMe, host) {
-        this.user = user
-    }
-
-    override fun clear() {
-        super.clear()
-        this.user = null
-    }
-}

+ 0 - 54
zen-api/src/main/kotlin/cn/gygxzc/envir/config/shiro/common/ZenPermission.kt

@@ -1,54 +0,0 @@
-package cn.gygxzc.envir.config.shiro.common
-
-import java.io.Serializable
-
-/**
- * 权限数据结构
- *
- * 从Resource/Menu抽象
- *
- * @author NorthLan
- * @date 2018/4/29
- * @url https://noahlan.com
- */
-open class ZenPermission : Serializable {
-    companion object {
-        private const val serialVersionUID = 5640224091610186666L
-    }
-
-    /**
-     * ResourceId
-     */
-    var id: Long? = null
-
-    /**
-     * 权限代码 (前端使用)
-     */
-    var code: String? = null
-
-    /**
-     * 请求地址
-     */
-    var uri: String? = null
-
-    /**
-     * 请求方法
-     */
-    var method: String? = null
-
-    /**
-     * 权限类型
-     * 1. 按钮 2.url
-     */
-    var type: Int? = null
-
-    /**
-     * 简短名称
-     */
-    var name: String? = null
-
-    /**
-     * 树ID
-     */
-    var treeId: Long? = null
-}

+ 0 - 106
zen-api/src/main/kotlin/cn/gygxzc/envir/config/shiro/common/ZenSimpleByteSource.kt

@@ -1,106 +0,0 @@
-package cn.gygxzc.envir.config.shiro.common
-
-import org.apache.shiro.codec.Base64
-import org.apache.shiro.codec.CodecSupport
-import org.apache.shiro.codec.Hex
-import org.apache.shiro.util.ByteSource
-import java.io.File
-import java.io.InputStream
-import java.io.Serializable
-import java.util.*
-
-/**
- * 实现序列化接口,否则 序列化 反序列化 凉凉
- * @author NorthLan
- * @date 2018/4/24
- * @url https://noahlan.com
- */
-class ZenSimpleByteSource : ByteSource, Serializable {
-    companion object {
-        private const val serialVersionUID = 5640224091610182940L
-    }
-
-    private var bytes: ByteArray? = null
-    private var cachedHex: String? = null
-    private var cachedBase64: String? = null
-
-    constructor()
-    constructor(bytes: ByteArray?) {
-        this.bytes = bytes
-    }
-
-    constructor(chars: CharArray?) {
-        this.bytes = CodecSupport.toBytes(chars)
-    }
-
-    constructor(string: String?) {
-        this.bytes = CodecSupport.toBytes(string)
-    }
-
-    constructor(source: ByteSource?) {
-        this.bytes = source?.bytes
-    }
-
-    constructor(file: File?) {
-        this.bytes = BytesHelper().getBytes(file)
-    }
-
-    constructor(stream: InputStream?) {
-        this.bytes = BytesHelper().getBytes(stream)
-    }
-
-    override fun toHex(): String? {
-        if (this.cachedHex == null) {
-            this.cachedHex = Hex.encodeToString(getBytes())
-        }
-        return this.cachedHex
-    }
-
-    override fun isEmpty(): Boolean {
-        return this.bytes == null || this.bytes!!.isEmpty()
-    }
-
-    override fun getBytes(): ByteArray? {
-        return this.bytes
-    }
-
-    override fun toBase64(): String {
-        if (this.cachedBase64 == null) {
-            this.cachedBase64 = Base64.encodeToString(getBytes())
-        }
-        return this.cachedBase64!!
-    }
-
-    override fun toString(): String {
-        return toBase64()
-    }
-
-    override fun hashCode(): Int {
-        return if (isEmpty) {
-            0
-        } else Arrays.hashCode(this.bytes)
-    }
-
-    override fun equals(other: Any?): Boolean {
-        if (other === this) {
-            return true
-        }
-        if (other is ByteSource) {
-            val bs = other as ByteSource?
-            return Arrays.equals(getBytes(), bs!!.bytes)
-        }
-        return false
-    }
-
-    private class BytesHelper : CodecSupport {
-        constructor()
-
-        fun getBytes(file: File?): ByteArray {
-            return toBytes(file)
-        }
-
-        fun getBytes(stream: InputStream?): ByteArray {
-            return toBytes(stream)
-        }
-    }
-}

+ 0 - 40
zen-api/src/main/kotlin/cn/gygxzc/envir/config/shiro/filter/AjaxAuthorizationFilter.kt

@@ -1,40 +0,0 @@
-package cn.gygxzc.envir.config.shiro.filter
-
-import org.apache.shiro.web.filter.authc.FormAuthenticationFilter
-import org.springframework.http.HttpMethod
-import org.springframework.http.HttpStatus
-import javax.servlet.ServletRequest
-import javax.servlet.ServletResponse
-import javax.servlet.http.HttpServletRequest
-import javax.servlet.http.HttpServletResponse
-
-
-/**
- * 对没有登录的请求进行拦截, 全部返回json信息. 覆盖掉shiro原本的跳转login.jsp的拦截方式
- *
- * 拦截状态码修改为401-UNAUTHORIZED
- * @author NorthLan
- * @date 2018/4/23
- * @url https://noahlan.com
- */
-class AjaxAuthorizationFilter : FormAuthenticationFilter() {
-
-    override fun isAccessAllowed(request: ServletRequest, response: ServletResponse, mappedValue: Any?): Boolean {
-        if (request is HttpServletRequest) {
-            if (HttpMethod.valueOf(request.method) == HttpMethod.OPTIONS) {
-                return true
-            }
-        }
-        return super.isAccessAllowed(request, response, mappedValue)
-    }
-
-    override fun onAccessDenied(request: ServletRequest, response: ServletResponse): Boolean {
-        response as HttpServletResponse
-        response.apply {
-            characterEncoding = "UTF-8"
-            contentType = "application/json"
-            sendError(HttpStatus.UNAUTHORIZED.value(), "you need login first...") // 401
-        }
-        return false
-    }
-}

+ 0 - 41
zen-api/src/main/kotlin/cn/gygxzc/envir/config/shiro/filter/ZenCorsAnonymousFilter.kt

@@ -1,41 +0,0 @@
-package cn.gygxzc.envir.config.shiro.filter
-
-import org.apache.shiro.web.filter.PathMatchingFilter
-import org.apache.shiro.web.util.WebUtils
-import org.springframework.http.HttpMethod
-import org.springframework.http.HttpStatus
-import javax.servlet.ServletRequest
-import javax.servlet.ServletResponse
-
-/**
- * Cors 的 canon 过滤器
- * @author NorthLan
- * @date 2018/4/25
- * @url https://noahlan.com
- */
-class ZenCorsAnonymousFilter : PathMatchingFilter() {
-
-    /**
-     * Always returns <code>true</code> allowing unchecked access to the underlying path or resource.
-     *
-     * @return <code>true</code> always, allowing unchecked access to the underlying path or resource.
-     */
-    override fun onPreHandle(request: ServletRequest?, response: ServletResponse?, mappedValue: Any?): Boolean {
-        val httpRequest = WebUtils.toHttp(request)
-        val httpResponse = WebUtils.toHttp(response)
-        httpResponse.apply {
-            setHeader("Access-control-Allow-Origin", httpRequest.getHeader("Origin"))
-            setHeader("Access-Control-Allow-Methods", "GET, HEAD, POST, PUT, DELETE, TRACE, OPTIONS, PATCH")
-            setHeader("Access-Control-Allow-Credentials", "true")
-            setHeader("Access-Control-Allow-Headers", httpRequest.getHeader("Access-Control-Request-Headers"))
-            val method = HttpMethod.valueOf(httpRequest.method)
-            if (method == HttpMethod.POST || method == HttpMethod.PUT) {
-                setHeader("Access-Control-Expose-Headers", "Location")
-            } else if (method == HttpMethod.OPTIONS) {
-                status = HttpStatus.OK.value()
-                return false
-            }
-        }
-        return true
-    }
-}

+ 0 - 39
zen-api/src/main/kotlin/cn/gygxzc/envir/config/shiro/filter/ZenCorsPathMatchingFilter.kt

@@ -1,39 +0,0 @@
-package cn.gygxzc.envir.config.shiro.filter
-
-import org.apache.shiro.web.filter.PathMatchingFilter
-import org.apache.shiro.web.util.WebUtils
-import org.springframework.http.HttpMethod
-import org.springframework.http.HttpStatus
-import javax.servlet.ServletRequest
-import javax.servlet.ServletResponse
-
-/**
- * 允许cors头
- * @author NorthLan
- * @date 2018/4/25
- * @url https://noahlan.com
- */
-class ZenCorsPathMatchingFilter : PathMatchingFilter() {
-
-    /**
-     * 实际上如果是options 方式的请求,没有必要继续下去了,直接返回就好了
-     */
-    override fun onPreHandle(request: ServletRequest?, response: ServletResponse?, mappedValue: Any?): Boolean {
-        val httpRequest = WebUtils.toHttp(request)
-        val httpResponse = WebUtils.toHttp(response)
-        httpResponse.apply {
-            setHeader("Access-control-Allow-Origin", httpRequest.getHeader("Origin"))
-            setHeader("Access-Control-Allow-Methods", "GET, HEAD, POST, PUT, DELETE, TRACE, OPTIONS, PATCH")
-            setHeader("Access-Control-Allow-Credentials", "true")
-            setHeader("Access-Control-Allow-Headers", httpRequest.getHeader("Access-Control-Request-Headers"))
-            val method = HttpMethod.valueOf(httpRequest.method)
-            if (method == HttpMethod.POST || method == HttpMethod.PUT) {
-                setHeader("Access-Control-Expose-Headers", "Location")
-            } else if (method == HttpMethod.OPTIONS) {
-                status = HttpStatus.OK.value()
-                return false
-            }
-        }
-        return true
-    }
-}

+ 0 - 63
zen-api/src/main/kotlin/cn/gygxzc/envir/config/shiro/realm/ZenShiroRealm.kt

@@ -1,63 +0,0 @@
-package cn.gygxzc.envir.config.shiro.realm
-
-import cn.gygxzc.envir.config.shiro.common.ZenAuthToken
-import cn.gygxzc.envir.config.shiro.common.ZenSimpleByteSource
-import org.apache.shiro.authc.*
-import org.apache.shiro.authz.AuthorizationInfo
-import org.apache.shiro.authz.SimpleAuthorizationInfo
-import org.apache.shiro.realm.AuthorizingRealm
-import org.apache.shiro.subject.PrincipalCollection
-import org.slf4j.LoggerFactory
-
-/**
- *
- * @author NorthLan
- * @date 2018/4/23
- * @url https://noahlan.com
- */
-class ZenShiroRealm : AuthorizingRealm() {
-    companion object {
-        private val logger = LoggerFactory.getLogger(ZenShiroRealm::class.java)
-    }
-
-    init {
-        this.name = "zen_realm"
-    }
-
-
-    /**
-     * 只支持这个
-     */
-    override fun supports(token: AuthenticationToken): Boolean {
-        return token is ZenAuthToken
-    }
-
-    /**
-     * 登陆验证
-     */
-    override fun doGetAuthenticationInfo(token: AuthenticationToken): AuthenticationInfo {
-        logger.debug("ZenShiroRealm doGetAuthenticationInfo [${token.principal}]")
-        if (token !is ZenAuthToken) {
-            throw AccountException("token must be ZenAuthToken")
-        }
-        // 获取用户信息
-        val user = token.user ?: throw UnknownAccountException()
-
-        // 账号锁定判定
-        if (user.lock_ != null && user.lock_!!) {
-            throw LockedAccountException()
-        }
-        return SimpleAuthenticationInfo(user, user.password, ZenSimpleByteSource(user.account + user.salt), user.username)
-    }
-
-    /**
-     * <p>调用subject的权限验证,如 hasRole,hasPermission <br>
-     *     将调用此方法给subject设置定义的权限
-     *     而后交由Realm处理 <br></p>
-     * 现改为集中式基于数据库的动态权限管理,此功能不做任何处理
-     */
-    override fun doGetAuthorizationInfo(principals: PrincipalCollection?): AuthorizationInfo {
-        logger.debug("ZenShiroRealm doGetAuthorizationInfo [${principals?.primaryPrincipal}]")
-        return SimpleAuthorizationInfo()
-    }
-}

+ 0 - 82
zen-api/src/main/kotlin/cn/gygxzc/envir/config/shiro/utils/SerializeUtils.kt

@@ -1,82 +0,0 @@
-package cn.gygxzc.envir.config.shiro.utils
-
-import org.slf4j.LoggerFactory
-import java.io.*
-
-
-/**
- * 序列化工具
- * @author NorthLan
- * @date 2018/4/23
- * @url https://noahlan.com
- */
-object SerializeUtils {
-    private val logger = LoggerFactory.getLogger(SerializeUtils::class.java)
-
-    /**
-     * deserialize
-     * @param bytes
-     * @return
-     */
-    fun deserialize(bytes: ByteArray): Any? {
-        var result: Any? = null
-        if (isEmpty(bytes)) {
-            return null
-        }
-
-        try {
-            val byteStream = ByteArrayInputStream(bytes)
-            try {
-                val objectInputStream = ObjectInputStream(byteStream)
-                try {
-                    result = objectInputStream.readObject()
-                } catch (ex: ClassNotFoundException) {
-                    throw Exception("Failed to deserialize object type", ex)
-                }
-
-            } catch (ex: Throwable) {
-                throw Exception("Failed to deserialize", ex)
-            }
-
-        } catch (e: Exception) {
-            logger.error("Failed to deserialize", e)
-        }
-        return result
-    }
-
-    private fun isEmpty(data: ByteArray?): Boolean {
-        return data == null || data.isEmpty()
-    }
-
-    /**
-     * serialize
-     * @param object
-     * @return
-     */
-    fun serialize(`object`: Any?): ByteArray? {
-        var result: ByteArray? = null
-        if (`object` == null) {
-            return ByteArray(0)
-        }
-        try {
-            val byteStream = ByteArrayOutputStream(128)
-            try {
-                if (`object` !is Serializable) {
-                    throw IllegalArgumentException(
-                            SerializeUtils::class.java.simpleName + " requires a Serializable payload "
-                                    + "but received an object of type [" + `object`.javaClass.name + "]")
-                }
-                val objectOutputStream = ObjectOutputStream(byteStream)
-                objectOutputStream.writeObject(`object`)
-                objectOutputStream.flush()
-                result = byteStream.toByteArray()
-            } catch (ex: Throwable) {
-                throw Exception("Failed to serialize", ex)
-            }
-        } catch (ex: Exception) {
-            logger.error("Failed to serialize", ex)
-        }
-
-        return result
-    }
-}

+ 0 - 42
zen-api/src/main/kotlin/cn/gygxzc/envir/config/shiro/utils/ShiroRedisUtil.kt

@@ -1,42 +0,0 @@
-package cn.gygxzc.envir.config.shiro.utils
-
-import com.gxzc.zen.common.util.SpringContextHolder
-import org.apache.shiro.session.Session
-import org.apache.shiro.session.mgt.eis.SessionDAO
-
-/**
- * Shiro redis 工具类
- * @author NorthLan
- * @date 2018/5/3
- * @url https://noahlan.com
- */
-object ShiroRedisUtil {
-    private var sessionDAO = SpringContextHolder.getBean(SessionDAO::class.java)
-        get() {
-            if (field == null) {
-                field = SpringContextHolder.getBean(SessionDAO::class.java)
-            }
-            return field
-        }
-
-    fun getActiveSessions(): MutableCollection<Session> {
-        return sessionDAO!!.activeSessions
-    }
-
-    private fun updateSession(session: Session) {
-        sessionDAO!!.update(session)
-    }
-
-    fun removeAllSessionsAttributeKey(key: Any?) {
-        val sessions = getActiveSessions()
-        sessions.forEach { s ->
-            s.setAttribute(key, null)
-            updateSession(s)
-        }
-    }
-
-    fun removeSessionAttributeKey(session: Session, key: Any?) {
-        session.setAttribute(key, null)
-        updateSession(session)
-    }
-}

+ 0 - 42
zen-api/src/main/kotlin/cn/gygxzc/envir/config/shiro/utils/ShiroUtils.java

@@ -1,42 +0,0 @@
-package cn.gygxzc.envir.config.shiro.utils;
-
-import cn.gygxzc.envir.sys.model.SysUser;
-
-import org.apache.shiro.SecurityUtils;
-import org.apache.shiro.subject.Subject;
-
-/**
- * shiro 工具类
- *
- * @author ruoyi
- */
-public class ShiroUtils {
-
-    public static Subject getSubjct() {
-        return SecurityUtils.getSubject();
-    }
-
-    public static void logout() {
-        getSubjct().logout();
-    }
-
-    public static SysUser getUser() {
-        return (SysUser) getSubjct().getPrincipal();
-    }
-
-    public static Long getUserId() {
-        return getUser().getId();
-    }
-
-    public static String getLoginName() {
-        return getUser().getAccount();
-    }
-
-    public static String getIp() {
-        return getSubjct().getSession().getHost();
-    }
-
-    public static String getSessionId() {
-        return String.valueOf(getSubjct().getSession().getId());
-    }
-}

+ 197 - 0
zen-api/src/main/kotlin/cn/gygxzc/envir/sys/model/CommonFile.java

@@ -0,0 +1,197 @@
+package cn.gygxzc.envir.sys.model;
+
+import com.baomidou.mybatisplus.annotation.TableName;
+
+import java.io.Serializable;
+import java.util.Date;
+
+/**
+ * Created by niantuo on 2018/12/10.
+ * 文件属性.
+ */
+@TableName("common_files")
+public class CommonFile implements Serializable, Cloneable {
+
+    public static final long serialVersionUID = 1L;
+
+    private Long id;
+    private Boolean enable;
+    private String fileName;
+    private Long fileSize;
+    private String originName;
+    private String fileType;
+    private String fileDesc;
+    private String fullPath;
+    private String clientKey;
+    private String useType;
+    private String remark;
+    private String createBy;
+    private Date createTime;
+    private String updateBy;
+    private Date updateTime;
+    private String fileMd5;
+    private Boolean failed;
+
+
+    public CommonFile() {
+
+    }
+
+
+    public void setId(Long id) {
+        this.id = id;
+    }
+
+    public void setEnable(Boolean enable) {
+        this.enable = enable;
+    }
+
+    public Long getId() {
+        return id;
+    }
+
+    public Boolean getEnable() {
+        return enable;
+    }
+
+    public String getFileName() {
+        return fileName;
+    }
+
+    public void setFileMd5(String fileMd5) {
+        this.fileMd5 = fileMd5;
+    }
+
+    public String getFileMd5() {
+        return fileMd5;
+    }
+
+    public void setFailed(Boolean failed) {
+        this.failed = failed;
+    }
+
+    public Boolean getFailed() {
+        return failed;
+    }
+
+
+    public void setFileName(String fileName) {
+        this.fileName = fileName;
+    }
+
+    public Long getFileSize() {
+        return fileSize;
+    }
+
+    public void setFileSize(Long fileSize) {
+        this.fileSize = fileSize;
+    }
+
+    public String getOriginName() {
+        return originName;
+    }
+
+    public void setOriginName(String originName) {
+        this.originName = originName;
+    }
+
+    public String getFileType() {
+        return fileType;
+    }
+
+    public void setFileType(String fileType) {
+        this.fileType = fileType;
+    }
+
+    public String getFileDesc() {
+        return fileDesc;
+    }
+
+    public void setFileDesc(String fileDesc) {
+        this.fileDesc = fileDesc;
+    }
+
+    public String getFullPath() {
+        return fullPath;
+    }
+
+    public void setFullPath(String fullPath) {
+        this.fullPath = fullPath;
+    }
+
+    public String getClientKey() {
+        return clientKey;
+    }
+
+    public void setClientKey(String clientKey) {
+        this.clientKey = clientKey;
+    }
+
+    public String getUseType() {
+        return useType;
+    }
+
+    public void setUseType(String useType) {
+        this.useType = useType;
+    }
+
+    public String getRemark() {
+        return remark;
+    }
+
+    public void setRemark(String remark) {
+        this.remark = remark;
+    }
+
+    public String getCreateBy() {
+        return createBy;
+    }
+
+    public void setCreateBy(String createBy) {
+        this.createBy = createBy;
+    }
+
+    public Date getCreateTime() {
+        return createTime;
+    }
+
+    public void setCreateTime(Date createTime) {
+        this.createTime = createTime;
+    }
+
+    public String getUpdateBy() {
+        return updateBy;
+    }
+
+    public void setUpdateBy(String updateBy) {
+        this.updateBy = updateBy;
+    }
+
+    public Date getUpdateTime() {
+        return updateTime;
+    }
+
+    public void setUpdateTime(Date updateTime) {
+        this.updateTime = updateTime;
+    }
+
+    @Override
+    public CommonFile clone() throws CloneNotSupportedException {
+        CommonFile commonFile = (CommonFile) super.clone();
+        commonFile.setOriginName(originName);
+        commonFile.setFileName(fileName);
+        commonFile.setClientKey(clientKey);
+        commonFile.setRemark(remark);
+        commonFile.setUseType(useType);
+        commonFile.setFileDesc(fileDesc);
+        commonFile.setFileSize(fileSize);
+        commonFile.setFullPath(fullPath);
+        commonFile.setFileMd5(fileMd5);
+        return commonFile;
+    }
+
+    @Override
+    public String toString() {
+        return String.format("{ fileName: %s  originName: %s ,fullPath:%s }", fileName, originName, fullPath);
+    }
+}

+ 0 - 81
zen-api/src/main/kotlin/cn/gygxzc/envir/sys/model/SysUser.kt

@@ -1,81 +0,0 @@
-package cn.gygxzc.envir.sys.model
-
-import com.baomidou.mybatisplus.annotation.TableField
-import com.baomidou.mybatisplus.annotation.TableName
-import com.gxzc.zen.common.base.BaseModel
-
-/**
- * <p>
- * 用户管理
- * </p>
- *
- * @author NorthLan
- * @since 2018-04-27
- */
-@TableName("sys_user")
-open class SysUser : BaseModel() {
-    companion object {
-        private const val serialVersionUID = 1000000000000000002L
-    }
-
-    /**
-     * 登陆帐户
-     */
-    var account: String? = null
-    /**
-     * 姓名
-     */
-    var username: String? = null
-    /**
-     * 密码
-     */
-    var password: String? = null
-    /**
-     * 密码盐值
-     */
-    var salt: String? = null
-    /**
-     * 电话
-     */
-    var phone: String? = null
-    /**
-     * 邮箱
-     */
-    var email: String? = null
-    /**
-     * 职位
-     */
-    var position: String? = null
-    /**
-     * 详细地址
-     */
-    var address: String? = null
-    /**
-     * 工号
-     */
-    var staffNo: String? = null
-    /**
-     * 账号锁定(1.锁定;0.不锁定;)
-     */
-    var lock_: Boolean? = null
-    /**
-     * 备用字段
-     */
-    var ext1: String? = null
-    /**
-     * 备用字段
-     */
-    var ext2: String? = null
-    /**
-     * 备用字段
-     */
-    var ext3: String? = null
-    /**
-     * 备用字段
-     */
-    var ext4: String? = null
-    /**
-     * 性别,定义 1:男 0:女 -1:保密
-     */
-    var gender: Int? = null
-}

+ 65 - 0
zen-api/src/main/kotlin/cn/gygxzc/envir/sys/service/IFUserService.kt

@@ -0,0 +1,65 @@
+package cn.gygxzc.envir.sys.service
+
+import cn.gygxzc.cloud.tina.auth.annotation.ResourceApi
+import cn.gygxzc.cloud.tina.auth.enums.ResourceLevel
+import cn.gygxzc.tina.cloud.jwt.session.bean.User
+import org.springframework.cloud.openfeign.FeignClient
+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.RequestMethod
+
+/**
+ * Created by niantuo on 2018/12/17.
+ * 通过feign 调用获取用户信心。
+ */
+@FeignClient("sys")
+interface IFUserService {
+
+
+    /**
+     * 根据用户的id获取用户信息
+     */
+    @RequestMapping(method = [RequestMethod.POST], value = ["/feign/user"])
+    fun getUserInfoByIds(@RequestBody ids: List<Long>): List<User>
+
+    /**
+     * 根据用户的id获取用户信息
+     */
+    @RequestMapping("/feign/user/{id}", method = [RequestMethod.GET])
+    fun getUserInfo(@PathVariable("id") id: Long): User?
+
+    /**
+     * 根据用户的账号获取用户信息
+     */
+    @RequestMapping("/feign/user/info/{account}", method = [RequestMethod.GET])
+    fun getUserByAccount(@PathVariable("account") account: String): User?
+
+    /**
+     * 根据用户的id获取用户的账号信息
+     */
+    @RequestMapping("/feign/user/account/{id}", method = [RequestMethod.GET])
+    fun getAccountById(@PathVariable("id") id: Long): String?
+
+    /**
+     * 根据用户id获取用户的账号信息...
+     * 这个不知道有什么用...
+     */
+    @RequestMapping("/feign/user/accounts", method = [RequestMethod.POST])
+    fun getAccountByIds(@RequestBody ids: List<Long>): List<String>
+
+
+    /**
+     * 根据用户的id修改用户信息,并不是全部信息。
+     */
+    @RequestMapping("/feign/user/{id}", method = [RequestMethod.PUT])
+    fun updateUserInfo(@PathVariable("id") id: Long, @RequestBody user: User)
+
+    /**
+     * 根据用户账户批量获取用户信息
+     */
+    @RequestMapping("/feign/user/info", method = [RequestMethod.POST])
+    @ResourceApi(name = "", level = ResourceLevel.AUTHC)
+    fun getUserInfoByAccounts(@RequestBody accounts: List<String>): List<User>
+
+}

+ 33 - 0
zen-api/src/main/kotlin/cn/gygxzc/envir/sys/service/IFileInfoService.kt

@@ -0,0 +1,33 @@
+package cn.gygxzc.envir.sys.service
+
+import cn.gygxzc.envir.sys.model.CommonFile
+import org.springframework.cloud.openfeign.FeignClient
+import org.springframework.web.bind.annotation.RequestBody
+import org.springframework.web.bind.annotation.RequestMapping
+import org.springframework.web.bind.annotation.RequestMethod
+
+/**
+ * Created by niantuo on 2018/12/20.
+ * 获取文件的信息服务
+ */
+@FeignClient("gateway")
+interface IFileInfoService {
+
+    /**
+     * 根据文件的id获取文件的详细信息
+     *
+     * @param ids 文件的id
+     * @return 文件的详细信息
+     */
+    @RequestMapping(value = ["/info"], method = [RequestMethod.POST])
+    fun queryByIds(@RequestBody ids: List<Long>): List<CommonFile>
+
+    /**
+     * 根据文件的id获取文件的简单信息
+     *
+     * @param ids 文件的id
+     * @return 文件的简略信息
+     */
+    @RequestMapping(value = ["/info/simp"], method = [RequestMethod.POST])
+    fun querySimpByIds(@RequestBody ids: List<Long>): List<CommonFile>
+}

+ 1 - 2
zen-api/src/main/kotlin/cn/gygxzc/envir/sys/service/ILoginService.kt

@@ -9,7 +9,7 @@ import org.springframework.web.bind.annotation.RequestMethod
 
 /**
  * Created by niantuo on 2018/9/21.
- * 登陆远程调用
+ * 登陆远程调用登陆系统的登录方法
  */
 @FeignClient("sys")
 interface ILoginService {
@@ -20,5 +20,4 @@ interface ILoginService {
     @RequestMapping(method = [RequestMethod.POST], value = ["/auth/v2/login"])
     fun login(@RequestBody dto: LoginDto): ResponseDto
 
-
 }

+ 1 - 1
zen-api/src/main/kotlin/cn/gygxzc/envir/config/shiro/utils/Byte2Hex.kt → zen-api/src/main/kotlin/cn/gygxzc/envir/utils/Byte2Hex.kt

@@ -1,4 +1,4 @@
-package cn.gygxzc.envir.config.shiro.utils
+package cn.gygxzc.envir.utils
 
 import java.util.*
 

+ 1 - 1
zen-api/src/main/kotlin/cn/gygxzc/envir/config/shiro/utils/MD5Salt.kt → zen-api/src/main/kotlin/cn/gygxzc/envir/utils/MD5Salt.kt

@@ -1,4 +1,4 @@
-package cn.gygxzc.envir.config.shiro.utils
+package cn.gygxzc.envir.utils
 
 import org.slf4j.LoggerFactory
 import java.security.MessageDigest

+ 0 - 43
zen-api/src/main/kotlin/com/gxzc/zen/msg/ws/config/WebSocketConfig.kt

@@ -1,43 +0,0 @@
-package com.gxzc.zen.msg.ws.config
-
-import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty
-import org.springframework.context.annotation.Configuration
-import org.springframework.messaging.simp.config.MessageBrokerRegistry
-import org.springframework.web.socket.config.annotation.AbstractWebSocketMessageBrokerConfigurer
-import org.springframework.web.socket.config.annotation.EnableWebSocketMessageBroker
-import org.springframework.web.socket.config.annotation.StompEndpointRegistry
-
-/**
- * WebSocket 配置
- * @author NorthLan
- * @date 2018/7/30
- * @url https://noahlan.com
- */
-@Configuration
-@EnableWebSocketMessageBroker
-@ConditionalOnProperty(prefix = "ws", name = ["enabled"], havingValue = "true", matchIfMissing = true)
-//@EnableConfigurationProperties(WebSocketProperties::class)
-class WebSocketConfig : AbstractWebSocketMessageBrokerConfigurer() {
-
-    //    @Autowired
-    //    private lateinit var webSocketProperties: WebSocketProperties
-
-    override fun configureMessageBroker(registry: MessageBrokerRegistry) {
-        /**
-         * 客户端需订阅如下地址的消息
-         * 服务端通过 @SendTo 或者使用SimpMessageTemplate来发送消息
-         */
-        registry.enableSimpleBroker("/topic", "/user")
-        /**
-         * 客户端需用如下地址作为前缀发送消息,经由Broker转发
-         */
-        registry.setApplicationDestinationPrefixes("/app", "/web")
-    }
-
-    override fun registerStompEndpoints(registry: StompEndpointRegistry) {
-        /**
-         * 以 /ws 作为 Stomp 端点,对外暴露
-         */
-        registry.addEndpoint("/ws").setAllowedOrigins("*")
-    }
-}

+ 0 - 12
zen-api/src/main/kotlin/com/gxzc/zen/msg/ws/config/WebSocketProperties.kt

@@ -1,12 +0,0 @@
-package com.gxzc.zen.msg.ws.config
-
-/**
- * WebSocket 配置类 暂无用
- * @author NorthLan
- * @date 2018/7/31
- * @url https://noahlan.com
- */
-//@ConfigurationProperties(prefix = "ws")
-open class WebSocketProperties {
-
-}

+ 0 - 39
zen-api/src/main/kotlin/com/gxzc/zen/orm/config/MybatisPlusConfig.kt

@@ -1,39 +0,0 @@
-package com.gxzc.zen.orm.config
-
-import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler
-import com.baomidou.mybatisplus.extension.plugins.PaginationInterceptor
-import org.mybatis.spring.annotation.MapperScan
-import org.springframework.context.annotation.Bean
-import org.springframework.context.annotation.Configuration
-
-/**
- *
- * @author NorthLan at 2018/1/30
- */
-@Configuration
-@MapperScan("com.gxzc.zen.api.*.mapper*")
-class MybatisPlusConfig {
-
-//    /**
-//     * 性能分析插件
-//     */
-//    @Bean
-//    @Profile("dev") // 开发环境开启
-//    fun performanceInterceptor(): PerformanceInterceptor {
-//        return PerformanceInterceptor().also { it.isFormat = true }
-//    }
-
-    /**
-     * 分页插件
-     */
-    @Bean
-    fun paginationInterceptor(): PaginationInterceptor {
-        return PaginationInterceptor()
-    }
-
-    @Bean
-    fun metaObjectHandler(): MetaObjectHandler {
-        return CustomMetaObjectHandler()
-    }
-
-}

+ 0 - 30
zen-api/src/main/kotlin/com/gxzc/zen/orm/data/authority/DAHelper.kt

@@ -1,30 +0,0 @@
-package com.gxzc.zen.orm.data.authority
-
-import org.slf4j.LoggerFactory
-
-/**
- * 数据权限辅助类(适用于全局)
- * @author NorthLan
- * @date 2018/7/16
- * @url https://noahlan.com
- */
-object DAHelper {
-    private val log = LoggerFactory.getLogger(DAHelper::class.java)
-
-    /**
-     * 数据权限 线程局部变量
-     */
-    private val LOCAL_DA = ThreadLocal<DataAuthority>()
-
-    fun getDA(): DataAuthority? {
-        return LOCAL_DA.get()
-    }
-
-    fun startDA(dataAuthority: DataAuthority) {
-        LOCAL_DA.set(dataAuthority)
-    }
-
-    fun remove() {
-        LOCAL_DA.remove()
-    }
-}

+ 0 - 24
zen-api/src/main/kotlin/com/gxzc/zen/orm/data/authority/DataAuthority.kt

@@ -1,24 +0,0 @@
-package com.gxzc.zen.orm.data.authority
-
-/**
- * 数据权限 包装类
- * @author NorthLan
- * @date 2018/7/16
- * @url https://noahlan.com
- */
-open class DataAuthority {
-    /**
-     * 是否启用系统 数权
-     */
-    var sysDAEnabled: Boolean = false
-
-    /**
-     * 是否启用业务 数权
-     */
-    var bizDAEnabled: Boolean = false
-
-    /**
-     * 业务数权 需要过滤的createBy
-     */
-    var createByList: String? = null
-}

+ 0 - 43
zen-api/src/main/kotlin/com/gxzc/zen/orm/data/authority/DataAuthorityBuilder.kt

@@ -1,43 +0,0 @@
-package com.gxzc.zen.orm.data.authority
-
-/**
- * 数据权限 构建器
- * @author NorthLan
- * @date 2018/7/25
- * @url https://noahlan.com
- */
-open class DataAuthorityBuilder {
-    private val da: DataAuthority = DataAuthority()
-
-    fun createByList(createByList: String): DataAuthorityBuilder {
-        da.createByList = createByList
-        configBizDA()
-        return this
-    }
-
-    fun createByList(createByList: Collection<String>): DataAuthorityBuilder {
-        da.createByList = createByList.joinToString(",")
-        configBizDA()
-        return this
-    }
-
-    fun systemDA(enabled: Boolean): DataAuthorityBuilder {
-        da.sysDAEnabled = enabled
-        return this
-    }
-
-    fun bizDA(enabled: Boolean): DataAuthorityBuilder {
-        da.bizDAEnabled = enabled
-        return this
-    }
-
-    fun build(): DataAuthority {
-        return da
-    }
-
-    private fun configBizDA() {
-        if (!da.createByList.isNullOrEmpty()) {
-            da.bizDAEnabled = true
-        }
-    }
-}

+ 0 - 43
zen-api/src/main/kotlin/com/gxzc/zen/orm/data/authority/visitor/DataAuthoritySelectVisitor.kt

@@ -1,43 +0,0 @@
-package com.gxzc.zen.orm.data.authority.visitor
-
-import net.sf.jsqlparser.expression.StringValue
-import net.sf.jsqlparser.expression.operators.conditional.AndExpression
-import net.sf.jsqlparser.expression.operators.relational.ExpressionList
-import net.sf.jsqlparser.expression.operators.relational.InExpression
-import net.sf.jsqlparser.schema.Column
-import net.sf.jsqlparser.statement.select.PlainSelect
-import net.sf.jsqlparser.statement.select.SelectVisitor
-import net.sf.jsqlparser.statement.select.SetOperationList
-import net.sf.jsqlparser.statement.select.WithItem
-
-/**
- * 数据权限 Select Visitor (处理sql)
- * @author NorthLan
- * @date 2018/7/9
- * @url https://noahlan.com
- */
-class DataAuthoritySelectVisitor : SelectVisitor {
-
-    override fun visit(plainSelect: PlainSelect) {
-        val inExp = InExpression().apply {
-            this.leftExpression = Column("create_by")
-            this.rightItemsList = ExpressionList(StringValue("admin"), StringValue("haha"))
-        }
-
-        if (plainSelect.where == null) {
-            plainSelect.where = inExp
-        } else {
-            plainSelect.where = AndExpression(plainSelect.where, inExp)
-        }
-    }
-
-    override fun visit(setOpList: SetOperationList) {
-        setOpList.selects.forEach {
-            it.accept(DataAuthoritySelectVisitor())
-        }
-    }
-
-    override fun visit(withItem: WithItem) {
-        withItem.selectBody.accept(DataAuthoritySelectVisitor())
-    }
-}

+ 18 - 0
zen-api/src/main/resources/mapper/test/TestLogMapper.xml

@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="cn.gygxzc.envir.test.dao.ITestLogDao">
+
+    <!-- 通用查询映射结果 -->
+    <resultMap id="BaseResultMap" type="cn.gygxzc.envir.test.model.TestLog">
+        <result column="id" property="id"/>
+        <result column="create_time" property="createTime"/>
+        <result column="create_by" property="createBy"/>
+        <result column="update_time" property="updateTime"/>
+        <result column="update_by" property="updateBy"/>
+        <result column="enable" property="enable"/>
+        <result column="remark" property="remark"/>
+        <result column="message" property="message"/>
+    </resultMap>
+
+
+</mapper>

+ 0 - 19
zen-api/src/test/kotlin/com/gxzc/zen/api/PasswordGen.kt

@@ -1,19 +0,0 @@
-package com.gxzc.zen.api
-
-import org.apache.shiro.crypto.hash.SimpleHash
-import org.junit.Test
-
-/**
- *
- * @author NorthLan
- * @date 2018/4/24
- * @url https://noahlan.com
- */
-class PasswordGen {
-    @Test
-    fun genPassword() {
-        println(SimpleHash("md5", "123456", "guest" + "hahahaha", 2))
-        println(SimpleHash("md5", "123456", "guest" + "hahahaha", 2).toHex())
-        println(SimpleHash("md5", "123456", "guest" + "hahahaha", 2).toString())
-    }
-}

+ 0 - 35
zen-api/src/test/kotlin/com/gxzc/zen/api/TestCollectionUtil.kt

@@ -1,35 +0,0 @@
-package com.gxzc.zen.api
-
-import org.apache.commons.collections.CollectionUtils
-import org.junit.Test
-
-/**
- *
- * @author NorthLan
- * @date 2018/5/4
- * @url https://noahlan.com
- */
-@Suppress("UNUSED_VARIABLE")
-class TestCollectionUtil {
-    @Test
-    fun testJiao() {
-        val a = mutableListOf<Int>().apply {
-            add(1)
-            add(2)
-            add(3)
-        }
-
-        val b = mutableListOf<Int>().apply {
-            add(1)
-            add(4)
-        }
-        // 差集 a b
-        val asubb = CollectionUtils.subtract(b, a)
-        // 并集
-        val union = CollectionUtils.union(a, b)
-        // 交集
-        val ins = CollectionUtils.intersection(a, b)
-
-        println("test")
-    }
-}

+ 0 - 110
zen-api/src/test/kotlin/com/gxzc/zen/api/TestDictTypeTreeRedis.kt

@@ -1,110 +0,0 @@
-//package com.gxzc.zen.api
-//
-//import com.fasterxml.jackson.databind.ObjectMapper
-//import com.gxzc.zen.api.sys.common.DictTypeTree
-//import com.gxzc.zen.common.util.TreeUtil
-//import org.junit.Test
-//
-///**
-// *
-// * @author NorthLan
-// * @date 2018/4/28
-// * @url https://noahlan.com
-// */
-//class TestDictTypeTreeRedis {
-//
-//    fun buildData(): MutableList<DictTypeTree> {
-//        return mutableListOf<DictTypeTree>().apply {
-//            add(DictTypeTree().apply {
-//                id = 1
-//                parentId = 0
-//                type = 1
-//            })
-//            add(DictTypeTree().apply {
-//                id = 2
-//                parentId = 1
-//                type = 1
-//            })
-//            add(DictTypeTree().apply {
-//                id = 3
-//                parentId = 1
-//                type = 1
-//            })
-//            add(DictTypeTree().apply {
-//                id = 4
-//                parentId = 2
-//                type = 1
-//                code = "test"
-//            })
-//            add(DictTypeTree().apply {
-//                id = 5
-//                parentId = 4
-//                type = 2
-//                value = "1"
-//                code = "test"
-//            })
-//            add(DictTypeTree().apply {
-//                id = 6
-//                parentId = 4
-//                type = 2
-//                value = "2"
-//                code = "test"
-//            })
-//            add(DictTypeTree().apply {
-//                id = 7
-//                parentId = 4
-//                type = 2
-//                value = "3"
-//                code = "test"
-//            })
-//            add(DictTypeTree().apply {
-//                id = 8
-//                parentId = 4
-//                type = 2
-//                value = "4"
-//                code = "test"
-//            })
-//            add(DictTypeTree().apply {
-//                id = 9
-//                parentId = 4
-//                type = 2
-//                value = "5"
-//                code = "test"
-//            })
-//            add(DictTypeTree().apply {
-//                id = 10
-//                parentId = 4
-//                type = 2
-//                value = "6"
-//                code = "test"
-//            })
-//        }
-//    }
-//
-//    @Test
-//    fun testTreeFind() {
-//        val data = buildData()
-//        val tree = TreeUtil.buildByRecursive(data, 0)
-//
-//        println(ObjectMapper().writeValueAsString(tree))
-//
-//        var now = System.currentTimeMillis()
-//        val find = TreeUtil.findBFS(tree) {
-//            it.type == 1 && it.code == "test"
-//        }
-//
-//        println("BFS: ${System.currentTimeMillis() - now}")
-//
-//        println(ObjectMapper().writeValueAsString(find))
-//
-//        now = System.currentTimeMillis()
-//        val find2 = TreeUtil.findDFS(tree) {
-//            it.type == 1 && it.code == "test"
-//        }
-//
-//        println("DFS: ${System.currentTimeMillis() - now}")
-//
-//
-//        println(ObjectMapper().writeValueAsString(find2))
-//    }
-//}

+ 0 - 24
zen-api/src/test/kotlin/com/gxzc/zen/api/TestKotlinReplace.kt

@@ -1,24 +0,0 @@
-package com.gxzc.zen.api
-
-import org.junit.Test
-import java.util.regex.Pattern
-
-/**
- *
- * @author NorthLan
- * @date 2018/4/29
- * @url https://noahlan.com
- */
-class TestKotlinReplace {
-
-    @Test
-    fun testKotlinReplace() {
-        val url = "/user/info/{*}"
-        val patternUrl = url.replace("\\{\\*}".toRegex(), "[a-zA-Z\\\\d]+")
-        println("^$patternUrl\$")
-
-        println(Pattern.compile("^$patternUrl\$").matcher("/user/info/1").find())
-
-        println("/user/info/haha".startsWith("/user/info" + "/"))
-    }
-}

+ 0 - 22
zen-api/src/test/kotlin/com/gxzc/zen/api/TestTreePath.kt

@@ -1,22 +0,0 @@
-package com.gxzc.zen.api
-
-import com.gxzc.zen.common.contants.ZenConstants
-import org.junit.Test
-
-/**
- *
- * @author NorthLan
- * @date 2018/4/30
- * @url https://noahlan.com
- */
-class TestTreePath {
-    @Test
-    fun test1() {
-        val path = "1-2-3-4"
-        val paths = path.split(ZenConstants.TREE_PATH_SEPARATOR)
-        println(path)
-        println(paths)
-        val a = paths.subList(0, paths.size - 2)
-        println(a)
-    }
-}

+ 0 - 39
zen-api/src/test/kotlin/com/gxzc/zen/api/base/BaseTestKt.kt

@@ -1,39 +0,0 @@
-package com.gxzc.zen.api.base
-
-import org.junit.Before
-import org.junit.runner.RunWith
-import org.springframework.beans.factory.annotation.Autowired
-import org.springframework.boot.test.context.SpringBootTest
-import org.springframework.test.context.junit4.SpringJUnit4ClassRunner
-import org.springframework.test.context.web.WebAppConfiguration
-import org.springframework.test.web.servlet.MockMvc
-import org.springframework.test.web.servlet.setup.MockMvcBuilders
-import org.springframework.web.context.WebApplicationContext
-
-/**
- * Spring单元测试基类
- * @author NorthLan
- * @date 2018/1/26
- * @url https://noahlan.com
- */
-@RunWith(SpringJUnit4ClassRunner::class)
-@SpringBootTest
-@WebAppConfiguration
-//@Transactional  // 事物支持
-class BaseTestKt {
-
-    @Autowired
-    lateinit var webApplicationContext: WebApplicationContext
-
-    lateinit var mockMvc: MockMvc
-
-    @Before
-    fun setupMockMvc() {
-        mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext).build()
-    }
-
-    @Before
-    fun initDataBase() {
-        // Nothing
-    }
-}

+ 0 - 1
zen-core/build.gradle

@@ -18,5 +18,4 @@ dependencies {
     compile 'io.jsonwebtoken:jjwt-api:0.10.5'
     runtime 'io.jsonwebtoken:jjwt-impl:0.10.5',
             'io.jsonwebtoken:jjwt-jackson:0.10.5'
-    compile("cn.gygxzc.tina:jwt-session:1.2")
 }

+ 91 - 0
zen-core/src/main/java/cn/gygxzc/envir/core/base/BaseModel.java

@@ -0,0 +1,91 @@
+package cn.gygxzc.envir.core.base;
+
+import com.baomidou.mybatisplus.annotation.*;
+import com.fasterxml.jackson.annotation.JsonFormat;
+
+import java.io.Serializable;
+import java.util.Date;
+
+/**
+ * Created by niantuo on 2018/9/30.
+ * 数据库类的基类
+ */
+
+public class BaseModel implements Serializable {
+
+    public static final long serialVersionUID = 1L;
+
+    @TableId(type = IdType.ID_WORKER)
+    private Long id;
+    @TableLogic
+    private Boolean enable;
+
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    @TableField(fill = FieldFill.INSERT)
+    private Date createTime;
+    @TableField(fill = FieldFill.INSERT)
+    private String createBy;
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    @TableField(fill = FieldFill.UPDATE)
+    private Date updateTime;
+    @TableField(fill = FieldFill.UPDATE)
+    private String updateBy;
+
+    private String remark;
+
+    public Long getId() {
+        return id;
+    }
+
+    public void setId(Long id) {
+        this.id = id;
+    }
+
+    public Boolean getEnable() {
+        return enable;
+    }
+
+    public void setEnable(Boolean enable) {
+        this.enable = enable;
+    }
+
+    public Date getCreateTime() {
+        return createTime;
+    }
+
+    public void setCreateTime(Date createTime) {
+        this.createTime = createTime;
+    }
+
+    public String getCreateBy() {
+        return createBy;
+    }
+
+    public void setCreateBy(String createBy) {
+        this.createBy = createBy;
+    }
+
+    public Date getUpdateTime() {
+        return updateTime;
+    }
+
+    public void setUpdateTime(Date updateTime) {
+        this.updateTime = updateTime;
+    }
+
+    public String getUpdateBy() {
+        return updateBy;
+    }
+
+    public void setUpdateBy(String updateBy) {
+        this.updateBy = updateBy;
+    }
+
+    public String getRemark() {
+        return remark;
+    }
+
+    public void setRemark(String remark) {
+        this.remark = remark;
+    }
+}

+ 191 - 0
zen-core/src/main/java/cn/gygxzc/envir/core/entity/MailEntity.java

@@ -0,0 +1,191 @@
+package cn.gygxzc.envir.core.entity;
+
+import cn.gygxzc.envir.core.ex.ParamMissException;
+import com.baomidou.mybatisplus.core.toolkit.IdWorker;
+import org.springframework.util.StringUtils;
+
+import javax.activation.DataSource;
+import java.io.Serializable;
+import java.util.Collections;
+import java.util.Date;
+import java.util.List;
+
+/**
+ * @author tuonina
+ * @createTime 2019/2/25
+ * 自定义的邮件实体类
+ */
+public class MailEntity implements Serializable {
+
+    public final static long serialVersionUID = 2L;
+    public final static String SEP = ",";
+
+    private Long id;
+    private String to;
+    private String subject;
+    private String content;
+    private String attachments;
+    private MailType type = MailType.SIMP;
+    private String rscPath;
+    private String filePath;
+    private String rscId;
+    /**
+     * 抄送收件人信息
+     * 收件人能看见抄送人信息
+     */
+    private List<String> cc;
+    /**
+     * 匿名抄送收件人,
+     * 匿名:表示收件人看不见抄送人的邮箱地址
+     */
+    private List<String> bcc;
+    private DataSource dataSource;
+    private String fileName;
+    private Date createTime;
+
+    public MailEntity() {
+        this.cc = Collections.emptyList();
+        this.bcc = Collections.emptyList();
+        this.createTime = new Date();
+        id = IdWorker.getId();
+    }
+
+    public void setDataSource(DataSource dataSource) {
+        this.dataSource = dataSource;
+    }
+
+    public void setCreateTime(Date createTime) {
+        this.createTime = createTime;
+    }
+
+    public Date getCreateTime() {
+        return createTime;
+    }
+
+    public DataSource getDataSource() {
+        return dataSource;
+    }
+
+    public void setFileName(String fileName) {
+        this.fileName = fileName;
+    }
+
+    public String getFileName() {
+        return fileName;
+    }
+
+    public String getTo() {
+        return to;
+    }
+
+    public void setTo(String to) {
+        this.to = to;
+    }
+
+    public String getSubject() {
+        return subject;
+    }
+
+    public void setSubject(String subject) {
+        this.subject = subject;
+    }
+
+    public String getContent() {
+        return content;
+    }
+
+    public void setContent(String content) {
+        this.content = content;
+    }
+
+    public String getAttachments() {
+        return attachments;
+    }
+
+    public void setAttachments(String attachments) {
+        this.attachments = attachments;
+    }
+
+    public void setFilePath(String filePath) {
+        this.filePath = filePath;
+    }
+
+    public String getFilePath() {
+        return filePath;
+    }
+
+    public MailType getType() {
+        return type;
+    }
+
+    public void setType(MailType type) {
+        this.type = type;
+    }
+
+    public String getRscPath() {
+        return rscPath;
+    }
+
+    public void setRscPath(String rscPath) {
+        this.rscPath = rscPath;
+    }
+
+    public String getRscId() {
+        return rscId;
+    }
+
+    public void setRscId(String rscId) {
+        this.rscId = rscId;
+    }
+
+    public List<String> getCc() {
+        return cc;
+    }
+
+    public void setCc(List<String> cc) {
+        this.cc = cc;
+    }
+
+
+    public List<String> getBcc() {
+        return bcc;
+    }
+
+    public void setBcc(List<String> bcc) {
+        this.bcc = bcc;
+    }
+
+    public void checkParams() throws RuntimeException {
+        if (!StringUtils.hasLength(to)) {
+            throw new ParamMissException("无发送对象!");
+        }
+        if (!StringUtils.hasLength(subject)) {
+            throw new ParamMissException("无邮件主题!");
+        }
+        if (!StringUtils.hasLength(content)) {
+            throw new ParamMissException("无邮件内容!");
+        }
+    }
+
+    public void setId(Long id) {
+        this.id = id;
+    }
+
+    public Long getId() {
+        return id;
+    }
+
+    /**
+     * SIMP  纯文档,也不存在附件的
+     */
+    public enum MailType {
+        SIMP, HTML, ATTACHMENTS, TEMPLATE
+    }
+
+    @Override
+    public String toString() {
+        return String.format("to:%s  ", to) +
+                String.format("subject:%s  ", subject) +
+                String.format("content:%s  ", content);
+    }
+}

+ 12 - 0
zen-core/src/main/java/cn/gygxzc/envir/core/ex/ParamMissException.java

@@ -0,0 +1,12 @@
+package cn.gygxzc.envir.core.ex;
+
+/**
+ * @author tuonina
+ * @createTime 2019/2/25
+ */
+public class ParamMissException extends RuntimeException {
+
+    public ParamMissException(String message){
+        super(message);
+    }
+}

+ 108 - 0
zen-core/src/main/java/cn/gygxzc/envir/core/logger/CoreLoggerEvent.java

@@ -0,0 +1,108 @@
+package cn.gygxzc.envir.core.logger;
+
+import ch.qos.logback.classic.Level;
+import ch.qos.logback.classic.spi.ILoggingEvent;
+import ch.qos.logback.classic.spi.IThrowableProxy;
+import ch.qos.logback.classic.spi.LoggerContextVO;
+import cn.gygxzc.tina.cloud.jwt.session.bean.User;
+import org.slf4j.Marker;
+
+import java.util.Map;
+
+/**
+ * @author tuonina
+ * @createTime 2019/3/25
+ */
+public class CoreLoggerEvent implements ILoggingEvent {
+
+
+    private ILoggingEvent realEvent;
+    private User user;
+
+    public CoreLoggerEvent(ILoggingEvent event){
+        this.realEvent = event;
+    }
+
+    public void setUser(User user) {
+        this.user = user;
+    }
+
+    public User getUser() {
+        return user;
+    }
+
+    @Override
+    public String getThreadName() {
+        return realEvent.getThreadName();
+    }
+
+    @Override
+    public Level getLevel() {
+        return realEvent.getLevel();
+    }
+
+    @Override
+    public String getMessage() {
+        return realEvent.getMessage();
+    }
+
+    @Override
+    public Object[] getArgumentArray() {
+        return realEvent.getArgumentArray();
+    }
+
+    @Override
+    public String getFormattedMessage() {
+        return realEvent.getFormattedMessage();
+    }
+
+    @Override
+    public String getLoggerName() {
+        return realEvent.getLoggerName();
+    }
+
+    @Override
+    public LoggerContextVO getLoggerContextVO() {
+        return realEvent.getLoggerContextVO();
+    }
+
+    @Override
+    public IThrowableProxy getThrowableProxy() {
+        return realEvent.getThrowableProxy();
+    }
+
+    @Override
+    public StackTraceElement[] getCallerData() {
+        return realEvent.getCallerData();
+    }
+
+    @Override
+    public boolean hasCallerData() {
+        return realEvent.hasCallerData();
+    }
+
+    @Override
+    public Marker getMarker() {
+        return realEvent.getMarker();
+    }
+
+    @Override
+    public Map<String, String> getMDCPropertyMap() {
+        return realEvent.getMDCPropertyMap();
+    }
+
+    @Override
+    public Map<String, String> getMdc() {
+        return realEvent.getMdc();
+    }
+
+    @Override
+    public long getTimeStamp() {
+        return realEvent.getTimeStamp();
+    }
+
+    @Override
+    public void prepareForDeferredProcessing() {
+        realEvent.prepareForDeferredProcessing();
+    }
+}

+ 12 - 0
zen-core/src/main/java/cn/gygxzc/envir/core/logger/ILoggerSender.java

@@ -0,0 +1,12 @@
+package cn.gygxzc.envir.core.logger;
+
+/**
+ * @program: Zen-Framework
+ * @description: ${description}
+ * @author: tuonina
+ * @create: 2018-12-15 18:48
+ **/
+public interface ILoggerSender {
+
+    public void send(LogMessage message);
+}

+ 13 - 0
zen-core/src/main/java/cn/gygxzc/envir/core/logger/IMarkerName.java

@@ -0,0 +1,13 @@
+package cn.gygxzc.envir.core.logger;
+
+/**
+ * @author tuonina
+ * @createTime 2019/3/25
+ */
+public interface IMarkerName {
+
+    String REQ="REQ";
+    String OP="OP";
+    String ERR="ERR";
+    String BIZ_ERR="BIZ_ERR";
+}

+ 175 - 0
zen-core/src/main/java/cn/gygxzc/envir/core/logger/LogMessage.java

@@ -0,0 +1,175 @@
+package cn.gygxzc.envir.core.logger;
+
+import ch.qos.logback.classic.spi.ILoggingEvent;
+import cn.gygxzc.envir.core.utils.GsonUtils;
+import cn.gygxzc.tina.cloud.jwt.session.bean.User;
+import org.slf4j.Marker;
+
+import java.io.Serializable;
+
+/**
+ * Created by niantuo on 2018/11/5.
+ * 分布式日志记录
+ */
+
+public class LogMessage implements Serializable {
+
+
+    public static final long serialVersionUID = 1L;
+
+    private String sysName;
+    private String threadName;
+    private String level;
+    private String message;
+    private String arguments;
+    private String formattedMessage;
+    private String loggerName;
+    private String callerData;
+    private String marker;
+    private String propertyMap;
+    private Long timeStamp;
+    private Long userId;
+    private String account;
+    private String errMsg;
+
+    public LogMessage() {
+
+    }
+
+    public LogMessage(ILoggingEvent event, String name) {
+        this.sysName = name;
+        this.threadName = event.getThreadName();
+        level = event.getLevel().levelStr;
+        message = event.getMessage();
+        arguments = GsonUtils.toJson(event.getArgumentArray());
+        formattedMessage = event.getFormattedMessage();
+        loggerName = event.getLoggerName();
+        callerData = GsonUtils.toJson(event.getCallerData());
+
+        propertyMap = GsonUtils.toJson(event.getMDCPropertyMap());
+        timeStamp = event.getTimeStamp();
+        errMsg = GsonUtils.toJson(event.getThrowableProxy());
+        Marker eventMarker = event.getMarker();
+        if (eventMarker != null) {
+            marker = eventMarker.toString();
+        }
+    }
+
+    public void setUser(User user){
+        if (user==null)return;
+        setUserId(user.getId());
+        setAccount(user.getAccount());
+    }
+
+    public void setUserId(Long userId) {
+        this.userId = userId;
+    }
+
+    public Long getUserId() {
+        return userId;
+    }
+
+    public void setAccount(String account) {
+        this.account = account;
+    }
+
+    public String getAccount() {
+        return account;
+    }
+
+    public void setSysName(String sysName) {
+        this.sysName = sysName;
+    }
+
+    public String getSysName() {
+        return sysName;
+    }
+
+    public String getThreadName() {
+        return threadName;
+    }
+
+    public void setThreadName(String threadName) {
+        this.threadName = threadName;
+    }
+
+    public String getLevel() {
+        return level;
+    }
+
+    public void setLevel(String level) {
+        this.level = level;
+    }
+
+    public String getMessage() {
+        return message;
+    }
+
+    public void setMessage(String message) {
+        this.message = message;
+    }
+
+    public String getArguments() {
+        return arguments;
+    }
+
+    public void setArguments(String arguments) {
+        this.arguments = arguments;
+    }
+
+    public String getFormattedMessage() {
+        return formattedMessage;
+    }
+
+    public void setFormattedMessage(String formattedMessage) {
+        this.formattedMessage = formattedMessage;
+    }
+
+    public String getLoggerName() {
+        return loggerName;
+    }
+
+    public void setLoggerName(String loggerName) {
+        this.loggerName = loggerName;
+    }
+
+    public String getCallerData() {
+        return callerData;
+    }
+
+    public void setCallerData(String callerData) {
+        this.callerData = callerData;
+    }
+
+    public String getMarker() {
+        return marker;
+    }
+
+    public void setMarker(String marker) {
+        this.marker = marker;
+    }
+
+    public String getPropertyMap() {
+        return propertyMap;
+    }
+
+    public void setPropertyMap(String propertyMap) {
+        this.propertyMap = propertyMap;
+    }
+
+    public Long getTimeStamp() {
+        return timeStamp;
+    }
+
+    public void setTimeStamp(Long timeStamp) {
+        this.timeStamp = timeStamp;
+    }
+
+    public void setErrMsg(String errMsg) {
+        this.errMsg = errMsg;
+    }
+
+    public String getErrMsg() {
+        return errMsg;
+    }
+}

+ 51 - 0
zen-core/src/main/java/cn/gygxzc/envir/core/logger/MQAppender.java

@@ -0,0 +1,51 @@
+package cn.gygxzc.envir.core.logger;
+
+import ch.qos.logback.classic.spi.ILoggingEvent;
+import ch.qos.logback.core.AppenderBase;
+import cn.gygxzc.envir.core.utils.ApplicationUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Created by niantuo on 2018/11/5.
+ * 这个异步日志收集。
+ * 利用Rabbitmq 消息中间件,将日志异步传递的日志分析系统中统计去记录和处理
+ */
+public class MQAppender extends AppenderBase<ILoggingEvent> {
+    private final static Logger logger = LoggerFactory.getLogger(MQAppender.class);
+
+    private ILoggerSender mMessageSender;
+    private String sysName;
+
+    public MQAppender() {
+        logger.debug("construct");
+    }
+
+    public void setSysName(String sysName) {
+        this.sysName = sysName;
+    }
+
+    public String getSysName() {
+        return sysName;
+    }
+
+    private void ensureSender() {
+        if (mMessageSender == null) {
+            mMessageSender = ApplicationUtils.getBean(ILoggerSender.class);
+        }
+    }
+
+
+    @Override
+    protected void append(ILoggingEvent eventObject) {
+        LogMessage message = new LogMessage(eventObject, sysName);
+        if (eventObject instanceof CoreLoggerEvent){
+            message.setUser(((CoreLoggerEvent) eventObject).getUser());
+        }
+        ensureSender();
+        if (mMessageSender != null) {
+            mMessageSender.send(message);
+        }
+    }
+
+}

+ 87 - 0
zen-core/src/main/java/cn/gygxzc/envir/core/logger/MQAsyncAppender.java

@@ -0,0 +1,87 @@
+package cn.gygxzc.envir.core.logger;
+
+import ch.qos.logback.classic.Level;
+import ch.qos.logback.classic.spi.ILoggingEvent;
+import ch.qos.logback.core.AsyncAppenderBase;
+import ch.qos.logback.core.spi.FilterReply;
+import ch.qos.logback.core.status.WarnStatus;
+import cn.gygxzc.tina.cloud.jwt.session.utils.SessionUtils;
+
+/**
+ * @author tuonina
+ * @createTime 2019/3/25
+ */
+public class MQAsyncAppender extends AsyncAppenderBase<ILoggingEvent> {
+
+
+    private boolean includeCallerData = false;
+    /**
+     * The guard prevents an appender from repeatedly calling its own doAppend
+     * method.
+     */
+    private ThreadLocal<Boolean> guard = new ThreadLocal<Boolean>();
+    private int statusRepeatCount = 0;
+    private int exceptionCount = 0;
+    private static final int ALLOWED_REPEATS = 3;
+
+
+    @Override
+    public void doAppend(ILoggingEvent eventObject) {
+        // WARNING: The guard check MUST be the first statement in the
+        // doAppend() method.
+        // prevent re-entry.
+        if (Boolean.TRUE.equals(guard.get())) {
+            return;
+        }
+        try {
+            guard.set(Boolean.TRUE);
+            if (!this.started) {
+                if (statusRepeatCount++ < ALLOWED_REPEATS) {
+                    addStatus(new WarnStatus("Attempted to append to non started appender [" + name + "].", this));
+                }
+                return;
+            }
+
+            if (getFilterChainDecision(eventObject) == FilterReply.DENY) {
+                return;
+            }
+
+            CoreLoggerEvent loggerEvent = new CoreLoggerEvent(eventObject);
+            loggerEvent.setUser(SessionUtils.getUser());
+            // ok, we now invoke derived class' implementation of append
+            this.append(loggerEvent);
+
+        } catch (Exception e) {
+            if (exceptionCount++ < ALLOWED_REPEATS) {
+                addError("Appender [" + name + "] failed to append.", e);
+            }
+        } finally {
+            guard.set(Boolean.FALSE);
+        }
+    }
+
+    /**
+     * Events of level TRACE, DEBUG and INFO are deemed to be discardable.
+     *
+     * @param event
+     * @return true if the event is of level TRACE, DEBUG or INFO false otherwise.
+     */
+    protected boolean isDiscardable(ILoggingEvent event) {
+        Level level = event.getLevel();
+        return level.toInt() <= Level.INFO_INT;
+    }
+
+    protected void preprocess(ILoggingEvent eventObject) {
+        eventObject.prepareForDeferredProcessing();
+        if (includeCallerData)
+            eventObject.getCallerData();
+    }
+
+    public boolean isIncludeCallerData() {
+        return includeCallerData;
+    }
+
+    public void setIncludeCallerData(boolean includeCallerData) {
+        this.includeCallerData = includeCallerData;
+    }
+}

+ 16 - 0
zen-core/src/main/java/cn/gygxzc/envir/core/orm/DataSourceConfiguration.java

@@ -0,0 +1,16 @@
+package cn.gygxzc.envir.core.orm;
+
+import com.baomidou.mybatisplus.autoconfigure.MybatisPlusAutoConfiguration;
+import org.springframework.boot.autoconfigure.AutoConfigureBefore;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.jdbc.datasource.init.DataSourceInitializer;
+
+/**
+ * Created by niantuo on 2018/12/13.
+ */
+@Configuration
+@AutoConfigureBefore(MybatisPlusAutoConfiguration.class)
+public class DataSourceConfiguration {
+
+
+}

+ 126 - 0
zen-core/src/main/java/cn/gygxzc/envir/core/redis/JedisConnectionConfiguration.java

@@ -0,0 +1,126 @@
+package cn.gygxzc.envir.core.redis;
+
+import org.apache.commons.pool2.impl.GenericObjectPool;
+import org.springframework.beans.factory.ObjectProvider;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
+import org.springframework.boot.autoconfigure.data.redis.JedisClientConfigurationBuilderCustomizer;
+import org.springframework.boot.autoconfigure.data.redis.RedisProperties;
+import org.springframework.boot.context.properties.EnableConfigurationProperties;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.Primary;
+import org.springframework.data.redis.connection.RedisClusterConfiguration;
+import org.springframework.data.redis.connection.RedisConnectionFactory;
+import org.springframework.data.redis.connection.RedisSentinelConfiguration;
+import org.springframework.data.redis.connection.jedis.JedisClientConfiguration;
+import org.springframework.data.redis.connection.jedis.JedisConnection;
+import org.springframework.data.redis.connection.jedis.JedisConnectionFactory;
+import org.springframework.util.StringUtils;
+import redis.clients.jedis.Jedis;
+import redis.clients.jedis.JedisPoolConfig;
+
+import java.time.Duration;
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * Created by niantuo on 2018/11/1.
+ * Jedis 配置
+ */
+
+@Configuration
+@EnableConfigurationProperties(RedisProperties.class)
+@ConditionalOnClass({GenericObjectPool.class, JedisConnection.class, Jedis.class})
+public class JedisConnectionConfiguration extends RedisConnectionConfiguration {
+
+    private final RedisProperties properties;
+
+    private final List<JedisClientConfigurationBuilderCustomizer> builderCustomizers;
+
+    JedisConnectionConfiguration(RedisProperties properties,
+                                 ObjectProvider<RedisSentinelConfiguration> sentinelConfiguration,
+                                 ObjectProvider<RedisClusterConfiguration> clusterConfiguration,
+                                 ObjectProvider<List<JedisClientConfigurationBuilderCustomizer>> builderCustomizers) {
+        super(properties, sentinelConfiguration, clusterConfiguration);
+        this.properties = properties;
+        this.builderCustomizers = builderCustomizers
+                .getIfAvailable(Collections::emptyList);
+    }
+
+    @Bean
+    @Primary
+    public RedisConnectionFactory redisConnectionFactory() {
+        return createJedisConnectionFactory();
+    }
+
+    private JedisConnectionFactory createJedisConnectionFactory() {
+        JedisClientConfiguration clientConfiguration = getJedisClientConfiguration();
+        if (getSentinelConfig() != null) {
+            return new JedisConnectionFactory(getSentinelConfig(), clientConfiguration);
+        }
+        if (getClusterConfiguration() != null) {
+            return new JedisConnectionFactory(getClusterConfiguration(),
+                    clientConfiguration);
+        }
+        return new JedisConnectionFactory(getStandaloneConfig(), clientConfiguration);
+    }
+
+    private JedisClientConfiguration getJedisClientConfiguration() {
+        JedisClientConfiguration.JedisClientConfigurationBuilder builder = applyProperties(
+                JedisClientConfiguration.builder());
+        RedisProperties.Pool pool = this.properties.getJedis().getPool();
+        if (pool != null) {
+            applyPooling(pool, builder);
+        }
+        if (StringUtils.hasText(this.properties.getUrl())) {
+            customizeConfigurationFromUrl(builder);
+        }
+        customize(builder);
+        return builder.build();
+    }
+
+    private JedisClientConfiguration.JedisClientConfigurationBuilder applyProperties(
+            JedisClientConfiguration.JedisClientConfigurationBuilder builder) {
+        if (this.properties.isSsl()) {
+            builder.useSsl();
+        }
+        if (this.properties.getTimeout() != null) {
+            Duration timeout = this.properties.getTimeout();
+            builder.readTimeout(timeout).connectTimeout(timeout);
+        }
+        return builder;
+    }
+
+    private void applyPooling(RedisProperties.Pool pool,
+                              JedisClientConfiguration.JedisClientConfigurationBuilder builder) {
+        builder.usePooling().poolConfig(jedisPoolConfig(pool));
+    }
+
+    private JedisPoolConfig jedisPoolConfig(RedisProperties.Pool pool) {
+        JedisPoolConfig config = new JedisPoolConfig();
+        config.setMaxTotal(pool.getMaxActive());
+        config.setMaxIdle(pool.getMaxIdle());
+        config.setMinIdle(pool.getMinIdle());
+        if (pool.getMaxWait() != null) {
+            config.setMaxWaitMillis(pool.getMaxWait().toMillis());
+        }
+        return config;
+    }
+
+    private void customizeConfigurationFromUrl(
+            JedisClientConfiguration.JedisClientConfigurationBuilder builder) {
+        RedisConnectionConfiguration.ConnectionInfo connectionInfo = parseUrl(this.properties.getUrl());
+        if (connectionInfo.isUseSsl()) {
+            builder.useSsl();
+        }
+    }
+
+    private void customize(
+            JedisClientConfiguration.JedisClientConfigurationBuilder builder) {
+        for (JedisClientConfigurationBuilderCustomizer customizer : this.builderCustomizers) {
+            customizer.customize(builder);
+        }
+    }
+
+
+}

+ 68 - 0
zen-core/src/main/java/cn/gygxzc/envir/core/redis/RedisAutoConfiguration.java

@@ -0,0 +1,68 @@
+package cn.gygxzc.envir.core.redis;
+
+import com.fasterxml.jackson.annotation.JsonTypeInfo;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
+import org.springframework.boot.autoconfigure.data.redis.RedisProperties;
+import org.springframework.boot.context.properties.EnableConfigurationProperties;
+import org.springframework.cache.CacheManager;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.Primary;
+import org.springframework.data.redis.cache.RedisCacheManager;
+import org.springframework.data.redis.connection.RedisConnectionFactory;
+import org.springframework.data.redis.core.RedisOperations;
+import org.springframework.data.redis.core.RedisTemplate;
+import org.springframework.data.redis.core.StringRedisTemplate;
+import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;
+import org.springframework.data.redis.serializer.StringRedisSerializer;
+
+import java.text.SimpleDateFormat;
+
+/**
+ * Created by niantuo on 2018/11/1.
+ * redis 缓存配置
+ */
+@Configuration
+@ConditionalOnClass(RedisOperations.class)
+@EnableConfigurationProperties(RedisProperties.class)
+public class RedisAutoConfiguration {
+
+
+    @Primary
+    @Bean("redisCacheManager")
+    public CacheManager cacheManager(RedisConnectionFactory connectionFactory) {
+        return RedisCacheManager.create(connectionFactory);
+
+    }
+
+    @Primary
+    @Bean("redisTemplate")
+    public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
+        RedisTemplate<Object, Object> template = new RedisTemplate<>();
+        StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
+        template.setKeySerializer(stringRedisSerializer);
+        template.setHashKeySerializer(stringRedisSerializer);
+
+
+        ObjectMapper objectMapper = new ObjectMapper();
+        objectMapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"));
+        objectMapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL, JsonTypeInfo.As.PROPERTY);
+
+        GenericJackson2JsonRedisSerializer jsonRedisSerializer = new GenericJackson2JsonRedisSerializer(objectMapper);
+        template.setValueSerializer(jsonRedisSerializer);
+        template.setHashValueSerializer(jsonRedisSerializer);
+        template.setConnectionFactory(redisConnectionFactory);
+        return template;
+    }
+
+    @Bean
+    @Primary
+    public StringRedisTemplate stringRedisTemplate(RedisConnectionFactory redisConnectionFactory) {
+        StringRedisTemplate template = new StringRedisTemplate();
+        template.setConnectionFactory(redisConnectionFactory);
+        return template;
+    }
+
+
+}

+ 157 - 0
zen-core/src/main/java/cn/gygxzc/envir/core/redis/RedisConnectionConfiguration.java

@@ -0,0 +1,157 @@
+package cn.gygxzc.envir.core.redis;
+
+import org.springframework.beans.factory.ObjectProvider;
+import org.springframework.boot.autoconfigure.data.redis.RedisProperties;
+import org.springframework.data.redis.connection.*;
+import org.springframework.util.Assert;
+import org.springframework.util.StringUtils;
+
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Created by niantuo on 2018/11/1.
+ * 完全的抄袭源代码
+ */
+
+public class RedisConnectionConfiguration {
+
+    private final RedisProperties properties;
+
+    private final RedisSentinelConfiguration sentinelConfiguration;
+
+    private final RedisClusterConfiguration clusterConfiguration;
+
+    protected RedisConnectionConfiguration(RedisProperties properties,
+                                           ObjectProvider<RedisSentinelConfiguration> sentinelConfigurationProvider,
+                                           ObjectProvider<RedisClusterConfiguration> clusterConfigurationProvider) {
+        this.properties = properties;
+        this.sentinelConfiguration = sentinelConfigurationProvider.getIfAvailable();
+        this.clusterConfiguration = clusterConfigurationProvider.getIfAvailable();
+    }
+
+    protected final RedisStandaloneConfiguration getStandaloneConfig() {
+        RedisStandaloneConfiguration config = new RedisStandaloneConfiguration();
+        if (StringUtils.hasText(this.properties.getUrl())) {
+            ConnectionInfo connectionInfo = parseUrl(this.properties.getUrl());
+            config.setHostName(connectionInfo.getHostName());
+            config.setPort(connectionInfo.getPort());
+            config.setPassword(RedisPassword.of(connectionInfo.getPassword()));
+        } else {
+            config.setHostName(this.properties.getHost());
+            config.setPort(this.properties.getPort());
+            config.setPassword(RedisPassword.of(this.properties.getPassword()));
+        }
+        config.setDatabase(this.properties.getDatabase());
+        return config;
+    }
+
+    protected final RedisSentinelConfiguration getSentinelConfig() {
+        if (this.sentinelConfiguration != null) {
+            return this.sentinelConfiguration;
+        }
+        RedisProperties.Sentinel sentinelProperties = this.properties.getSentinel();
+        if (sentinelProperties != null) {
+            RedisSentinelConfiguration config = new RedisSentinelConfiguration();
+            config.master(sentinelProperties.getMaster());
+            config.setSentinels(createSentinels(sentinelProperties));
+            if (this.properties.getPassword() != null) {
+                config.setPassword(RedisPassword.of(this.properties.getPassword()));
+            }
+            config.setDatabase(this.properties.getDatabase());
+            return config;
+        }
+        return null;
+    }
+
+    /**
+     * Create a {@link RedisClusterConfiguration} if necessary.
+     *
+     * @return {@literal null} if no cluster settings are set.
+     */
+    protected final RedisClusterConfiguration getClusterConfiguration() {
+        if (this.clusterConfiguration != null) {
+            return this.clusterConfiguration;
+        }
+        if (this.properties.getCluster() == null) {
+            return null;
+        }
+        RedisProperties.Cluster clusterProperties = this.properties.getCluster();
+        RedisClusterConfiguration config = new RedisClusterConfiguration(
+                clusterProperties.getNodes());
+        if (clusterProperties.getMaxRedirects() != null) {
+            config.setMaxRedirects(clusterProperties.getMaxRedirects());
+        }
+        if (this.properties.getPassword() != null) {
+            config.setPassword(RedisPassword.of(this.properties.getPassword()));
+        }
+        return config;
+    }
+
+    private List<RedisNode> createSentinels(RedisProperties.Sentinel sentinel) {
+        List<RedisNode> nodes = new ArrayList<>();
+        for (String node : sentinel.getNodes()) {
+            try {
+                String[] parts = StringUtils.split(node, ":");
+                Assert.state(parts.length == 2, "Must be defined as 'host:port'");
+                nodes.add(new RedisNode(parts[0], Integer.valueOf(parts[1])));
+            } catch (RuntimeException ex) {
+                throw new IllegalStateException(
+                        "Invalid redis sentinel " + "property '" + node + "'", ex);
+            }
+        }
+        return nodes;
+    }
+
+    protected ConnectionInfo parseUrl(String url) {
+        try {
+            URI uri = new URI(url);
+            boolean useSsl = (url.startsWith("rediss://"));
+            String password = null;
+            if (uri.getUserInfo() != null) {
+                password = uri.getUserInfo();
+                int index = password.indexOf(':');
+                if (index >= 0) {
+                    password = password.substring(index + 1);
+                }
+            }
+            return new ConnectionInfo(uri, useSsl, password);
+        } catch (URISyntaxException ex) {
+            throw new IllegalArgumentException("Malformed url '" + url + "'", ex);
+        }
+    }
+
+    protected static class ConnectionInfo {
+
+        private final URI uri;
+
+        private final boolean useSsl;
+
+        private final String password;
+
+        public ConnectionInfo(URI uri, boolean useSsl, String password) {
+            this.uri = uri;
+            this.useSsl = useSsl;
+            this.password = password;
+        }
+
+        public boolean isUseSsl() {
+            return this.useSsl;
+        }
+
+        public String getHostName() {
+            return this.uri.getHost();
+        }
+
+        public int getPort() {
+            return this.uri.getPort();
+        }
+
+        public String getPassword() {
+            return this.password;
+        }
+
+    }
+}

+ 40 - 0
zen-core/src/main/java/cn/gygxzc/envir/core/utils/ApplicationUtils.java

@@ -0,0 +1,40 @@
+package cn.gygxzc.envir.core.utils;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.BeansException;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.ApplicationContextAware;
+import org.springframework.stereotype.Component;
+
+/**
+ * Created by niantuo on 2018/11/5.
+ * 获取bean类
+ */
+@Component
+public class ApplicationUtils implements ApplicationContextAware {
+
+    private static ApplicationContext mContext;
+    private final static Logger logger = LoggerFactory.getLogger(ApplicationUtils.class);
+
+
+    /**
+     * @param clz s
+     * @param <T>
+     * @return
+     */
+    public static <T> T getBean(Class<T> clz) {
+        if (mContext == null) return null;
+        try {
+            return mContext.getBean(clz);
+        } catch (Exception ignored) {
+            logger.info("no bean found {}",clz.getName());
+        }
+        return null;
+    }
+
+    @Override
+    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
+        mContext = applicationContext;
+    }
+}

+ 26 - 0
zen-core/src/main/java/cn/gygxzc/envir/core/utils/GsonUtils.java

@@ -0,0 +1,26 @@
+package cn.gygxzc.envir.core.utils;
+
+import com.google.gson.Gson;
+
+/**
+ * Created by niantuo on 2018/11/5.
+ */
+
+public class GsonUtils {
+    private final static Gson mGson = new Gson();
+
+    public static String toJson(Object obj) {
+        return mGson.toJson(obj);
+    }
+
+    /**
+     * 实际上如果是数组,这样子是解析不出来的吧。
+     * @param clz 要返回的类型
+     * @param json 原始json数据
+     * @param <T> 泛型
+     * @return
+     */
+    public static <T> T fromJson(Class<T> clz, String json) {
+        return mGson.fromJson(json, clz);
+    }
+}

+ 26 - 0
zen-core/src/main/java/cn/gygxzc/envir/core/utils/HttpUtils.java

@@ -0,0 +1,26 @@
+package cn.gygxzc.envir.core.utils;
+
+import org.springframework.web.context.request.RequestContextHolder;
+import org.springframework.web.context.request.ServletRequestAttributes;
+
+import javax.servlet.http.HttpServletRequest;
+
+/**
+ * Created by niantuo on 2018/10/19.
+ * 工具类
+ */
+
+public class HttpUtils {
+
+    /**
+     * 获取请求体
+     * @return 请求
+     */
+    public HttpServletRequest getRequest(){
+        return ((ServletRequestAttributes)(RequestContextHolder.getRequestAttributes())).getRequest();
+    }
+
+    public static ServletRequestAttributes getRequestAttributes(){
+        return (ServletRequestAttributes)RequestContextHolder.getRequestAttributes();
+    }
+}

+ 23 - 0
zen-core/src/main/kotlin/cn/gygxzc/envir/core/CoreConfiguration.kt

@@ -0,0 +1,23 @@
+package cn.gygxzc.envir.core
+
+import cn.gygxzc.cloud.tina.auth.AUTH_REDIS_TEMPLATE
+import cn.gygxzc.cloud.tina.auth.shiro.cache.ShiroCacheManager
+import org.apache.shiro.cache.CacheManager
+import org.springframework.beans.factory.annotation.Qualifier
+import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean
+import org.springframework.context.annotation.Bean
+import org.springframework.context.annotation.Configuration
+import org.springframework.data.redis.core.RedisTemplate
+
+/**
+ * Created by niantuo on 2018/11/1.
+ */
+@Configuration
+class CoreConfiguration {
+
+    @Bean
+    @ConditionalOnMissingBean(CacheManager::class)
+    fun shiroRedisCacheManager(@Qualifier(AUTH_REDIS_TEMPLATE) redisTemplate: RedisTemplate<String, Any>):CacheManager{
+        return ShiroCacheManager(redisTemplate)
+    }
+}

+ 8 - 0
zen-core/src/main/kotlin/cn/gygxzc/envir/core/CoreConst.kt

@@ -0,0 +1,8 @@
+package cn.gygxzc.envir.core
+
+/**
+ * @author tuonina
+ * @createTime 2019/2/26
+ * 系统界别的常量
+ */
+

+ 24 - 24
zen-core/src/main/kotlin/com/gxzc/zen/common/config/cache/caffeine/CaffeineConfig.kt → zen-core/src/main/kotlin/cn/gygxzc/envir/core/caffeine/CaffeineConfiguration.kt

@@ -1,31 +1,31 @@
-package com.gxzc.zen.common.config.cache.caffeine
+package cn.gygxzc.envir.core.caffeine
 
 import com.github.benmanes.caffeine.cache.Caffeine
+import org.springframework.beans.factory.annotation.Autowired
 import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty
-import org.springframework.boot.context.properties.ConfigurationProperties
+import org.springframework.boot.context.properties.EnableConfigurationProperties
 import org.springframework.cache.CacheManager
-import org.springframework.cache.annotation.EnableCaching
 import org.springframework.cache.caffeine.CaffeineCache
 import org.springframework.cache.support.SimpleCacheManager
 import org.springframework.context.annotation.Bean
 import org.springframework.context.annotation.Configuration
-import org.springframework.context.annotation.Primary
 import java.util.concurrent.TimeUnit
 
 /**
- * 缓存配置类
- * @author NorthLan at 2018/2/4
+ * Created by niantuo on 2018/9/29.
+ * caffeine 缓存配置
  */
+
 @Configuration
-@EnableCaching
-@ConfigurationProperties(prefix = "cache.caffeine")
-@ConditionalOnProperty(prefix = "cache.caffeine", name = ["enable"], havingValue = "true")
-class CaffeineConfig {
+@EnableConfigurationProperties(CaffeineProperties::class)
+@ConditionalOnProperty(prefix = "cache.caffeine", name = arrayOf("enable"), havingValue = "true")
+open class CaffeineConfiguration {
 
-    var cacheSpecs: Map<String, CacheSpec>? = null
+    @Autowired
+    private lateinit var properties: CaffeineProperties
 
     @Bean("caffeineCacheManager")
-    fun caffeineCacheManager(): CacheManager {
+   open fun caffeineCacheManager(): CacheManager {
         return SimpleCacheManager().also {
             it.setCaches(buildCache())
         }
@@ -33,37 +33,37 @@ class CaffeineConfig {
 
     fun buildCache(): MutableCollection<CaffeineCache> {
         val collection = mutableListOf<CaffeineCache>()
-        cacheSpecs?.forEach { name, spec ->
+        properties.cacheSpec.forEach { name, spec ->
             run {
                 val builder = Caffeine.newBuilder().also {
-                    if (spec.initialCapacity >= 0) {
+                    if (spec.initialCapacity > 0) {
                         it.initialCapacity(spec.initialCapacity)
                     }
-                    if (spec.maximumSize >= 0) {
+                    if (spec.maximumSize > 0) {
                         it.maximumSize(spec.maximumSize)
                     }
-                    if (spec.maximumWeight >= 0) {
+                    if (spec.maximumWeight > 0) {
                         it.maximumWeight(spec.maximumWeight)
                     }
-                    if (spec.expireAfterAccess >= 0) {
+                    if (spec.expireAfterAccess > 0) {
                         it.expireAfterAccess(spec.expireAfterAccess, TimeUnit.SECONDS)
                     }
-                    if (spec.expireAfterWrite >= 0) {
+                    if (spec.expireAfterWrite > 0) {
                         it.expireAfterWrite(spec.expireAfterWrite, TimeUnit.SECONDS)
                     }
-                    if (spec.refreshAfterWrite >= 0) {
+                    if (spec.refreshAfterWrite > 0) {
                         it.refreshAfterWrite(spec.refreshAfterWrite, TimeUnit.SECONDS)
                     }
-                    if (spec.weakKeys) {
+                    if (spec.isWeakKeys) {
                         it.weakKeys()
                     }
-                    if (spec.weakValues) {
+                    if (spec.isWeakValues) {
                         it.weakValues()
                     }
-                    if (spec.softValues) {
+                    if (spec.isSoftValues) {
                         it.softValues()
                     }
-                    if (spec.recordStats) {
+                    if (spec.isRecordStats) {
                         it.recordStats()
                     }
                 }
@@ -72,4 +72,4 @@ class CaffeineConfig {
         }
         return collection
     }
-}
+}

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