Browse Source

first commit

master
李世鹏 3 years ago
commit
8c5d40491f
  1. 21
      .editorconfig
  2. 27
      .gitignore
  3. 15
      Dockerfile
  4. 34
      LICENSE
  5. 43
      README.md
  6. 27
      doc/script/docker/elk/README.md
  7. 88
      doc/script/docker/elk/deploy.sh
  8. 115
      doc/script/docker/elk/docker-compose.yml
  9. 28
      doc/script/docker/elk/es-master.yml
  10. 28
      doc/script/docker/elk/es-slave1.yml
  11. 28
      doc/script/docker/elk/es-slave2.yml
  12. 37
      doc/script/docker/elk/filebeat.yml
  13. 8
      doc/script/docker/elk/kibana.yml
  14. 23
      doc/script/docker/elk/logstash-filebeat.conf
  15. 8
      doc/script/docker/elk/logstash.yml
  16. 16
      doc/script/docker/elk/undeploy.sh
  17. 1
      doc/script/fatjar/service.cmd
  18. 76
      doc/script/fatjar/service.sh
  19. 566
      doc/sql/db/database-info.md
  20. BIN
      doc/sql/dm/bladex-flowable-dameng.dmp
  21. BIN
      doc/sql/dm/bladex-saber-dameng.dmp
  22. BIN
      doc/sql/dm/bladex-sword-dameng.dmp
  23. 1777
      doc/sql/mysql/bladex-flowable-mysql.sql
  24. 832
      doc/sql/mysql/bladex-saber-mysql.sql
  25. 832
      doc/sql/mysql/bladex-sword-mysql.sql
  26. 5676
      doc/sql/oracle/bladex-flowable-oracle.sql
  27. 6308
      doc/sql/oracle/bladex-saber-oracle.sql
  28. 6305
      doc/sql/oracle/bladex-sword-oracle.sql
  29. 2741
      doc/sql/postgresql/bladex-flowable-postgresql.sql
  30. 5173
      doc/sql/postgresql/bladex-saber-postgresql.sql
  31. 5173
      doc/sql/postgresql/bladex-sword-postgresql.sql
  32. 4113
      doc/sql/sqlserver/bladex-flowable-sqlserver.sql
  33. 4599
      doc/sql/sqlserver/bladex-saber-sqlserver.sql
  34. 4599
      doc/sql/sqlserver/bladex-sword-sqlserver.sql
  35. 15
      doc/sql/update/bladex-update-dameng-2.9.1~3.0.0.sql
  36. 11
      doc/sql/update/bladex-update-mysql-2.9.1~3.0.0.sql
  37. 15
      doc/sql/update/bladex-update-oracle-2.9.1~3.0.0.sql
  38. 15
      doc/sql/update/bladex-update-postgresql-2.9.1~3.0.0.sql
  39. 26
      doc/sql/update/bladex-update-sqlserver-2.9.1~3.0.0.sql
  40. 299
      pom.xml
  41. 38
      src/main/java/org/springblade/Application.java
  42. 61
      src/main/java/org/springblade/common/cache/CacheNames.java
  43. 116
      src/main/java/org/springblade/common/cache/DictBizCache.java
  44. 143
      src/main/java/org/springblade/common/cache/DictCache.java
  45. 62
      src/main/java/org/springblade/common/cache/ParamCache.java
  46. 56
      src/main/java/org/springblade/common/cache/RegionCache.java
  47. 317
      src/main/java/org/springblade/common/cache/SysCache.java
  48. 77
      src/main/java/org/springblade/common/cache/UserCache.java
  49. 70
      src/main/java/org/springblade/common/config/BladeConfiguration.java
  50. 58
      src/main/java/org/springblade/common/config/BladeLogConfiguration.java
  51. 26
      src/main/java/org/springblade/common/config/BladePreviewConfiguration.java
  52. 43
      src/main/java/org/springblade/common/config/BladeReportConfiguration.java
  53. 120
      src/main/java/org/springblade/common/config/SwaggerConfiguration.java
  54. 84
      src/main/java/org/springblade/common/constant/CommonConstant.java
  55. 38
      src/main/java/org/springblade/common/constant/DictConstant.java
  56. 93
      src/main/java/org/springblade/common/constant/LauncherConstant.java
  57. 66
      src/main/java/org/springblade/common/constant/TenantConstant.java
  58. 39
      src/main/java/org/springblade/common/enums/DictBizEnum.java
  59. 95
      src/main/java/org/springblade/common/enums/DictEnum.java
  60. 60
      src/main/java/org/springblade/common/event/ApiLogListener.java
  61. 57
      src/main/java/org/springblade/common/event/ErrorLogListener.java
  62. 58
      src/main/java/org/springblade/common/event/UsualLogListener.java
  63. 66
      src/main/java/org/springblade/common/filter/PreviewFilter.java
  64. 44
      src/main/java/org/springblade/common/launch/LauncherServiceImpl.java
  65. 26
      src/main/java/org/springblade/common/utils/CommonUtil.java
  66. 35
      src/main/java/org/springblade/ftpdemo/cache/CodeCache.java
  67. 181
      src/main/java/org/springblade/ftpdemo/controller/DockingController.java
  68. 303
      src/main/java/org/springblade/ftpdemo/controller/SSHRemoteCall.java
  69. 32
      src/main/java/org/springblade/ftpdemo/entity/Identification.java
  70. 62
      src/main/java/org/springblade/ftpdemo/entity/NbmsEnprefix.java
  71. 76
      src/main/java/org/springblade/ftpdemo/entity/NbmsEnt.java
  72. 221
      src/main/java/org/springblade/ftpdemo/entity/NbmsEntApply.java
  73. 20
      src/main/java/org/springblade/ftpdemo/entity/SysDict.java
  74. 14
      src/main/java/org/springblade/ftpdemo/mapper/NbmsEnprefixMapper.java
  75. 18
      src/main/java/org/springblade/ftpdemo/mapper/NbmsEntApplyMapper.java
  76. 13
      src/main/java/org/springblade/ftpdemo/mapper/NbmsEntMapper.java
  77. 13
      src/main/java/org/springblade/ftpdemo/mapper/SysDictMapper.java
  78. 34
      src/main/java/org/springblade/ftpdemo/service/IdentificationIp.java
  79. 10
      src/main/java/org/springblade/ftpdemo/service/Method.java
  80. 11
      src/main/java/org/springblade/ftpdemo/service/NbmsEnprefixService.java
  81. 11
      src/main/java/org/springblade/ftpdemo/service/NbmsEntApplyServcie.java
  82. 12
      src/main/java/org/springblade/ftpdemo/service/NbmsEntServcie.java
  83. 14
      src/main/java/org/springblade/ftpdemo/service/SysDictService.java
  84. 74
      src/main/java/org/springblade/ftpdemo/service/impl/MethodImpl.java
  85. 15
      src/main/java/org/springblade/ftpdemo/service/impl/NbmsEnprefixServiceImpl.java
  86. 15
      src/main/java/org/springblade/ftpdemo/service/impl/NbmsEntApplyServcieImpl.java
  87. 15
      src/main/java/org/springblade/ftpdemo/service/impl/NbmsEntServiceImpl.java
  88. 22
      src/main/java/org/springblade/ftpdemo/service/impl/SysDictServiceImpl.java
  89. 32
      src/main/java/org/springblade/ftpdemo/task/IdentificationUp.java
  90. 15
      src/main/java/org/springblade/ftpdemo/util/Constant.java
  91. 249
      src/main/java/org/springblade/ftpdemo/util/Decrypt.java
  92. 294
      src/main/java/org/springblade/ftpdemo/util/Encrypt.java
  93. 97
      src/main/java/org/springblade/modules/auth/endpoint/BladeSocialEndpoint.java
  94. 149
      src/main/java/org/springblade/modules/auth/endpoint/BladeTokenEndPoint.java
  95. 50
      src/main/java/org/springblade/modules/auth/enums/UserEnum.java
  96. 127
      src/main/java/org/springblade/modules/auth/granter/CaptchaTokenGranter.java
  97. 117
      src/main/java/org/springblade/modules/auth/granter/PasswordTokenGranter.java
  98. 114
      src/main/java/org/springblade/modules/auth/granter/RefreshTokenGranter.java
  99. 92
      src/main/java/org/springblade/modules/auth/granter/SocialTokenGranter.java
  100. 36
      src/main/java/org/springblade/modules/auth/provider/ITokenGranter.java
  101. Some files were not shown because too many files have changed in this diff Show More

21
.editorconfig

@ -0,0 +1,21 @@
# http://editorconfig.org
root = true
# 空格替代Tab缩进在各种编辑工具下效果一致
[*]
indent_style = space
indent_size = 4
charset = utf-8
end_of_line = lf
trim_trailing_whitespace = true
insert_final_newline = true
[*.java]
indent_style = tab
[*.{json,yml}]
indent_size = 2
[*.md]
insert_final_newline = false
trim_trailing_whitespace = false

27
.gitignore vendored

@ -0,0 +1,27 @@
# maven #
target
logs
# windows #
Thumbs.db
# Mac #
.DS_Store
# eclipse #
.settings
.project
.classpath
.log
*.class
# idea #
.idea
*.iml
# Package Files #
*.jar
*.war
*.ear
/target

15
Dockerfile

@ -0,0 +1,15 @@
FROM bladex/alpine-java:openjdk8-openj9_cn_slim
MAINTAINER smallchill@163.com
RUN mkdir -p /blade
WORKDIR /blade
EXPOSE 8800
ADD ./target/blade-api.jar ./app.jar
ENTRYPOINT ["java", "-Djava.security.egd=file:/dev/./urandom", "-jar", "app.jar"]
CMD ["--spring.profiles.active=test"]

34
LICENSE

@ -0,0 +1,34 @@
BladeX商业授权许可协议
一、 知识产权:
BladeX系列产品知识产权归上海布雷德科技有限公司独立所有
二、 许可:
1. 在您完全接受并遵守本协议的基础上,本协议授予您使用BladeX的某些权利和非独占性许可。
2. 本协议中,将本产品使用用途分为“专业版用途”和“企业版用途”。
3. “专业版用途”定义:指个人在非团体机构中出于任何目的使用本产品(任何目的包括商业目的或非盈利目的)。
4. “企业版用途”定义:指团体机构(例如公司企业、政府、学校、军队、医院、社会团体等各类组织)(不包含集团,若集团使用则需为各个子公司分别购买企业授权)出于任何目的使用本产品(任何目的包括商业目的或非盈利目的)。
三、 约束和限制:
1. 本产品只能由您为本协议许可的目的而使用,您不得透露给任何第三方;
2. 从本产品取得的任何信息、软件、产品或服务,您不得对其进行修改、改编或基于以上内容创建同种类别的衍生产品并售卖。
3. 您不得对本产品以及与之关联的商业授权进行发布、出租、销售、分销、抵押、转让、许可或发放子许可证。
4. 本产品商业授权版可能包含一些独立功能或特性,这些功能只有在您购买商业授权后才可以使用。在未取得商业授权的情况下,您不得使用、尝试使用或复制这些授权版独立功能。
5. 若您的客户要求以源码方式交付软件,需缴纳企业版授权费用,否则本产品部分不得提供源码。
四、 不得用于非法或禁止的用途:
您在使用本产品或服务时,不得将本产品产品或服务用于任何非法用途或本协议条款、条件和声明禁止的用途。
五、 免责说明:
1. 本产品按“现状”授予许可,您须自行承担使用本产品的风险。BladeX团队不对此提供任何明示、暗示或任何其它形式的担保和表示。在任何情况下,对于因使用或无法使用本软件而导致的任何损失(包括但不仅限于商业利润损失、业务中断或业务信息丢失),BladeX团队无需向您或任何第三方负责,即使BladeX团队已被告知可能会造成此类损失。在任何情况下, BladeX团队均不就任何直接的、间接的、附带的、后果性的、特别的、惩戒性的和处罚性的损害赔偿承担任何责任,无论该主张是基于保证、合同、侵权(包括疏忽)或是基于其他原因作出。
2. 本产品可能内置有第三方服务,您应自行评估使用这些第三方服务的风险,由使用此类第三方服务而产生的纠纷,全部责任由您自行承担。
3. BladeX团队不对使用本产品构建的网站中任何信息内容以及导致的任何版权纠纷、法律争议和后果承担任何责任,全部责任由您自行承担。
4. BladeX团队可能会经常提供产品更新或升级,但BladeX团队没有为根据本协议许可的产品提供维护或更新的责任。
5. BladeX团队可能会按照官方制定的答疑规则为您进行答疑,但BladeX团队没有为根据本协议许可的产品提供技术支持的义务或责任。
六、 权利和所有权的保留:
BladeX团队保留所有未在本协议中明确授予您的所有权利。BladeX团队保留随时更新本协议的权利,并只需公示于对应产品项目的LICENSE文件,无需征得您的事先同意且无需另行通知,更新后的内容应于公示即时生效。您可以随时访问产品地址并查阅最新版许可条款,在更新生效后您继续使用本产品则被视作您已接受了新的条款。
七、 协议终止
1. 您一旦开始复制、下载、安装或者使用本产品,即被视为完全理解并接受本协议的各项条款,在享有上述条款授予的许可权力同时,也受到相关的约束和限制,本协议许可范围以外的行为,将直接违反本协议并构成侵权。
2. 一旦您违反本协议的条款,BladeX团队随时可能终止本协议、收回许可和授权,并要求您承担相应法律和经济责任。

43
README.md

@ -0,0 +1,43 @@
## 版权声明
* BladeX是一个商业化软件,系列产品知识产权归**上海布雷德科技有限公司**独立所有
* 您一旦开始复制、下载、安装或者使用本产品,即被视为完全理解并接受本协议的各项条款
* 更多详情请看:[BladeX商业授权许可协议](/LICENSE)
## 答疑流程
>1. 遇到问题或Bug
>2. 业务型问题打断点调试尝试找出问题所在
>3. 系统型问题通过百度、谷歌、社区查找解决方案
>4. 未解决问题则进入技术社区进行发帖提问:[https://sns.bladex.vip/](https://sns.bladex.vip/)
>5. 将帖子地址发至商业群,特别简单三言两语就能描述清楚的也可在答疑时间内发至商业群提问
>6. 发帖的时候一定要描述清楚,详细描述遇到问题的**重现步骤**、**报错详细信息**、**相关代码与逻辑**、**使用软件版本**以及**操作系统版本**,否则随意发帖提问将会提高我们的答疑难度。
## 答疑时间
* 工作日:9:00 ~ 17:00 提供答疑,周末、节假日休息,暂停答疑
* 请勿**私聊提问**,以免被其他用户的消息覆盖从而无法获得答疑
* 答疑时间外遇到问题可以将问题发帖至[技术社区](https://sns.bladex.vip/),我们后续会逐个回复
## 授权范围
* 专业版:只可用于**个人学习**及**个人私活**项目,不可用于公司或团队,不可泄露给任何第三方
* 企业版:可用于**企业名下**的任何项目,企业版员工在**未购买**专业版授权前,只授权开发**所在授权企业名下**的项目,**不得将BladeX用于个人私活**
* 共同遵守:若甲方需要您提供项目源码,则需代为甲方购买BladeX企业授权,甲方购买后续的所有项目都无需再次购买授权
## 商用权益
* ✔ 遵守[商业协议](/LICENSE)的前提下,将BladeX系列产品用于授权范围内的商用项目,并上线运营
* ✔ 遵守[商业协议](/LICENSE)的前提下,不限制项目数,不限制服务器数
* ✔ 遵守[商业协议](/LICENSE)的前提下,将自行编写的业务代码申请软件著作权
## 何为侵权
* ❌ 不遵守商业协议,私自销售商业源码
* ❌ 以任何理由将BladeX源码用于申请软件著作权
* ❌ 将商业源码以任何途径任何理由泄露给未授权的单位或个人
* ❌ 开发完毕项目,没有为甲方购买企业授权,向甲方提供了BladeX代码
* ❌ 基于BladeX拓展研发与BladeX有竞争关系的衍生框架,并将其开源或销售
## 侵权后果
* 情节较轻:第一次发现警告处理
* 情节较重:封禁账号,踢出商业群,并保留追究法律责任的权利
* 情节严重:与本地律师事务所合作,以公司名义起诉侵犯计算机软件著作权
## 举报有奖
* 向官方提供有用线索并成功捣毁盗版个人或窝点,将会看成果给予 500~10000 不等的现金奖励
* 官方唯一指定QQ:1272154962

27
doc/script/docker/elk/README.md

@ -0,0 +1,27 @@
## 一、调整内存:max virtual memory areas vm.max_map_count [65530] is too low, increase to at least [262144](elasticsearch用户拥有的内存权限太小,至少需要262144)
#### 1.修改配置sysctl.conf
[root@localhost ~]# vi /etc/sysctl.conf
#### 2.添加下面配置:
vm.max_map_count=262144
#### 3.重新加载:
[root@localhost ~]# sysctl -p
#### 4.最后重新启动elasticsearch,即可启动成功。
## 二、Docker 命令自动补全
#### 1.安装依赖工具bash-complete
[root@localhost ~]# yum install -y bash-completion
[root@localhost ~]# source /usr/share/bash-completion/completions/docker
[root@localhost ~]# source /usr/share/bash-completion/bash_completion
## 三、将本文件夹内的文件拷贝至服务器
#### 1.对sh脚本赋予执行权限
#### 2.执行 ./deploy.sh
#### 3.等待服务启动完毕即可
#### 4.卸载执行 ./undeploy.sh

88
doc/script/docker/elk/deploy.sh

@ -0,0 +1,88 @@
#./bin/bash
# 定义颜色
BLUE_COLOR="\033[36m"
RED_COLOR="\033[31m"
GREEN_COLOR="\033[32m"
VIOLET_COLOR="\033[35m"
RES="\033[0m"
echo -e "${BLUE_COLOR}# ######################################################################${RES}"
echo -e "${BLUE_COLOR}# Docker ELK Deploy Script #${RES}"
echo -e "${BLUE_COLOR}# ######################################################################${RES}"
# 创建目录
echo -e "${BLUE_COLOR}---> create [elasticsearch]directory start.${RES}"
if [ ! -d "./elasticsearch/" ]; then
mkdir -p ./elasticsearch/master/conf ./elasticsearch/master/data ./elasticsearch/master/logs \
./elasticsearch/slave1/conf ./elasticsearch/slave1/data ./elasticsearch/slave1/logs \
./elasticsearch/slave2/conf ./elasticsearch/slave2/data ./elasticsearch/slave2/logs
fi
echo -e "${RED_COLOR}---> create [kibana]directory start.${RES}"
if [ ! -d "./kibana/" ]; then
mkdir -p ./kibana/conf ./kibana/logs
fi
echo -e "${GREEN_COLOR}---> create [logstash]directory start.${RES}"
if [ ! -d "./logstash/" ]; then
mkdir -p ./logstash/conf ./logstash/logs
fi
echo -e "${GREEN_COLOR}---> create [filebeat]directory start.${RES}"
if [ ! -d "./filebeat/" ]; then
mkdir -p ./filebeat/conf ./filebeat/logs ./filebeat/data
fi
echo -e "${VIOLET_COLOR}---> create [nginx]directory start.${RES}"
if [ ! -d "./nginx/" ]; then
mkdir -p ./nginx/conf ./nginx/logs ./nginx/www
fi
echo -e "${BLUE_COLOR}===> create directory success.${RES}"
# 目录授权(data/logs 都要授读/写权限)
echo -e "${BLUE_COLOR}---> directory authorize start.${RES}"
if [ -d "./elasticsearch/" ]; then
chmod 777 ./elasticsearch/master/data/ ./elasticsearch/master/logs/ \
./elasticsearch/slave1/data/ ./elasticsearch/slave1/logs/ \
./elasticsearch/slave2/data/ ./elasticsearch/slave2/logs
fi
if [ -d "./filebeat/" ]; then
chmod 777 ./filebeat/data/ ./filebeat/logs/
fi
echo -e "${BLUE_COLOR}===> directory authorize success.${RES}"
# 移动配置文件
echo -e "${BLUE_COLOR}---> move [elasticsearch]config file start.${RES}"
if [ -f "./es-master.yml" ] && [ -f "./es-slave1.yml" ] && [ -f "./es-slave2.yml" ]; then
mv ./es-master.yml ./elasticsearch/master/conf
mv ./es-slave1.yml ./elasticsearch/slave1/conf
mv ./es-slave2.yml ./elasticsearch/slave2/conf
fi
echo -e "${RED_COLOR}---> move [kibana]config file start.${RES}"
if [ -f "./kibana.yml" ]; then
mv ./kibana.yml ./kibana/conf
fi
echo -e "${GREEN_COLOR}---> move [logstash]config file start.${RES}"
if [ -f "./logstash.yml" ] && [ -f "./logstash-filebeat.conf" ]; then
mv ./logstash-filebeat.conf ./logstash/conf
mv ./logstash.yml ./logstash/conf
fi
echo -e "${GREEN_COLOR}---> move [filebeat]config file start.${RES}"
if [ -f "./filebeat.yml" ]; then
mv ./filebeat.yml ./filebeat/conf
fi
echo -e "${VIOLET_COLOR}---> move [nginx]config file start.${RES}"
if [ -f "./nginx.conf" ]; then
mv ./nginx.conf ./nginx/conf
fi
echo -e "${BLUE_COLOR}===> move config files success.${RES}"
echo -e "${GREEN_COLOR}>>>>>>>>>>>>>>>>>> The End <<<<<<<<<<<<<<<<<<${RES}"
# 部署项目
echo -e "${BLUE_COLOR}==================> Docker deploy Start <==================${RES}"
docker-compose up --build -d

115
doc/script/docker/elk/docker-compose.yml

@ -0,0 +1,115 @@
version: "3"
services:
es-master:
container_name: es-master
hostname: es-master
image: elasticsearch:7.1.1
restart: always
ports:
- 9200:9200
- 9300:9300
volumes:
- ./elasticsearch/master/conf/es-master.yml:/usr/share/elasticsearch/config/elasticsearch.yml
- ./elasticsearch/master/data:/usr/share/elasticsearch/data
- ./elasticsearch/master/logs:/usr/share/elasticsearch/logs
environment:
- "ES_JAVA_OPTS=-Xms512m -Xmx512m"
es-slave1:
container_name: es-slave1
image: elasticsearch:7.1.1
restart: always
ports:
- 9201:9200
- 9301:9300
volumes:
- ./elasticsearch/slave1/conf/es-slave1.yml:/usr/share/elasticsearch/config/elasticsearch.yml
- ./elasticsearch/slave1/data:/usr/share/elasticsearch/data
- ./elasticsearch/slave1/logs:/usr/share/elasticsearch/logs
environment:
- "ES_JAVA_OPTS=-Xms512m -Xmx512m"
es-slave2:
container_name: es-slave2
image: elasticsearch:7.1.1
restart: always
ports:
- 9202:9200
- 9302:9300
volumes:
- ./elasticsearch/slave2/conf/es-slave2.yml:/usr/share/elasticsearch/config/elasticsearch.yml
- ./elasticsearch/slave2/data:/usr/share/elasticsearch/data
- ./elasticsearch/slave2/logs:/usr/share/elasticsearch/logs
environment:
- "ES_JAVA_OPTS=-Xms512m -Xmx512m"
es-head:
container_name: es-head
image: mobz/elasticsearch-head:5
restart: always
ports:
- 9100:9100
depends_on:
- es-master
- es-slave1
- es-slave2
kibana:
container_name: kibana
hostname: kibana
image: kibana:7.1.1
restart: always
ports:
- 5601:5601
volumes:
- ./kibana/conf/kibana.yml:/usr/share/kibana/config/kibana.yml
environment:
- elasticsearch.hosts=http://es-master:9200
depends_on:
- es-master
- es-slave1
- es-slave2
filebeat:
# 容器名称
container_name: filebeat
# 主机名称
hostname: filebeat
# 镜像
image: docker.elastic.co/beats/filebeat:7.1.1
# 重启机制
restart: always
# 持久化挂载
volumes:
- ./filebeat/conf/filebeat.yml:/usr/share/filebeat/filebeat.yml
# 映射到容器中[作为数据源]
- ./logs:/home/project/elk/logs
- ./filebeat/logs:/usr/share/filebeat/logs
- ./filebeat/data:/usr/share/filebeat/data
# 将指定容器连接到当前连接,可以设置别名,避免ip方式导致的容器重启动态改变的无法连接情况
links:
- logstash
ports:
- 9000:9000
# 依赖服务[可无]
depends_on:
- es-master
- es-slave1
- es-slave2
logstash:
container_name: logstash
hostname: logstash
image: logstash:7.1.1
command: logstash -f ./conf/logstash-filebeat.conf
restart: always
volumes:
# 映射到容器中
- ./logstash/conf/logstash-filebeat.conf:/usr/share/logstash/conf/logstash-filebeat.conf
- ./logstash/conf/logstash.yml:/usr/share/logstash/config/logstash.yml
ports:
- 5044:5044
depends_on:
- es-master
- es-slave1
- es-slave2

28
doc/script/docker/elk/es-master.yml

@ -0,0 +1,28 @@
# 集群名称
cluster.name: es-cluster
# 节点名称
node.name: es-master
# 是否可以成为master节点
node.master: true
# 是否允许该节点存储数据,默认开启
node.data: false
# 网络绑定
network.host: 0.0.0.0
# 设置对外服务的http端口
http.port: 9200
# 设置节点间交互的tcp端口
transport.port: 9300
# 集群发现
discovery.seed_hosts:
- es-master
- es-slave1
- es-slave2
# 手动指定可以成为 mater 的所有节点的 name 或者 ip,这些配置将会在第一次选举中进行计算
cluster.initial_master_nodes:
- es-master
# 支持跨域访问
http.cors.enabled: true
http.cors.allow-origin: "*"
# 安全认证
xpack.security.enabled: false
#http.cors.allow-headers: "Authorization"

28
doc/script/docker/elk/es-slave1.yml

@ -0,0 +1,28 @@
# 集群名称
cluster.name: es-cluster
# 节点名称
node.name: es-slave1
# 是否可以成为master节点
node.master: true
# 是否允许该节点存储数据,默认开启
node.data: true
# 网络绑定
network.host: 0.0.0.0
# 设置对外服务的http端口
http.port: 9201
# 设置节点间交互的tcp端口
#transport.port: 9301
# 集群发现
discovery.seed_hosts:
- es-master
- es-slave1
- es-slave2
# 手动指定可以成为 mater 的所有节点的 name 或者 ip,这些配置将会在第一次选举中进行计算
cluster.initial_master_nodes:
- es-master
# 支持跨域访问
http.cors.enabled: true
http.cors.allow-origin: "*"
# 安全认证
xpack.security.enabled: false
#http.cors.allow-headers: "Authorization"

28
doc/script/docker/elk/es-slave2.yml

@ -0,0 +1,28 @@
# 集群名称
cluster.name: es-cluster
# 节点名称
node.name: es-slave2
# 是否可以成为master节点
node.master: true
# 是否允许该节点存储数据,默认开启
node.data: true
# 网络绑定
network.host: 0.0.0.0
# 设置对外服务的http端口
http.port: 9202
# 设置节点间交互的tcp端口
#transport.port: 9302
# 集群发现
discovery.seed_hosts:
- es-master
- es-slave1
- es-slave2
# 手动指定可以成为 mater 的所有节点的 name 或者 ip,这些配置将会在第一次选举中进行计算
cluster.initial_master_nodes:
- es-master
# 支持跨域访问
http.cors.enabled: true
http.cors.allow-origin: "*"
# 安全认证
xpack.security.enabled: false
#http.cors.allow-headers: "Authorization"

37
doc/script/docker/elk/filebeat.yml

@ -0,0 +1,37 @@
filebeat.inputs:
- type: log
enabled: true
paths:
# 当前目录下的所有.log文件
- /home/project/elk/logs/*.log
multiline.pattern: ^\[
multiline.negate: true
multiline.match: after
- type: tcp
enabled: true
max_message_size: 10MiB
host: "0.0.0.0:9000"
filebeat.config.modules:
path: ${path.config}/modules.d/*.yml
reload.enabled: false
setup.template.settings:
index.number_of_shards: 1
setup.dashboards.enabled: false
setup.kibana:
host: "http://kibana:5601"
# 不直接传输至ES
#output.elasticsearch:
# hosts: ["http://es-master:9200"]
# index: "filebeat-%{[beat.version]}-%{+yyyy.MM.dd}"
output.logstash:
hosts: ["logstash:5044"]
processors:
- add_host_metadata: ~
- add_cloud_metadata: ~

8
doc/script/docker/elk/kibana.yml

@ -0,0 +1,8 @@
# 服务端口
server.port: 5601
# 服务IP
server.host: "0.0.0.0"
# ES
elasticsearch.hosts: ["http://es-master:9200"]
# 汉化
i18n.locale: "zh-CN"

23
doc/script/docker/elk/logstash-filebeat.conf

@ -0,0 +1,23 @@
input {
# 来源beats
beats {
# 端口
port => "5044"
}
}
# 分析、过滤插件,可以多个
filter {
grok {
match => { "message" => "%{COMBINEDAPACHELOG}"}
}
geoip {
source => "clientip"
}
}
output {
# 选择elasticsearch
elasticsearch {
hosts => ["http://es-master:9200"]
index => "%{[@metadata][beat]}-%{[@metadata][version]}-%{+YYYY.MM.dd}"
}
}

8
doc/script/docker/elk/logstash.yml

@ -0,0 +1,8 @@
# 服务IP
http.host: "0.0.0.0"
# ES
xpack.monitoring.elasticsearch.hosts: [ "http://es-master:9200" ]
xpack.monitoring.enabled: true
xpack.management.enabled: false

16
doc/script/docker/elk/undeploy.sh

@ -0,0 +1,16 @@
#./bin/bash
# 定义颜色
BLUE_COLOR="\033[36m"
RED_COLOR="\033[31m"
GREEN_COLOR="\033[32m"
VIOLET_COLOR="\033[35m"
RES="\033[0m"
echo -e "${BLUE_COLOR}# ######################################################################${RES}"
echo -e "${BLUE_COLOR}# Docker ELK UnDeploy Script #${RES}"
echo -e "${BLUE_COLOR}# ######################################################################${RES}"
# 部署项目
echo -e "${BLUE_COLOR}==================> Docker UnDeploy Start <==================${RES}"
docker-compose stop
docker-compose rm

1
doc/script/fatjar/service.cmd

@ -0,0 +1 @@
java -Xms1024m -Xmx1024m -jar app.jar

76
doc/script/fatjar/service.sh

@ -0,0 +1,76 @@
#!/bin/bash
#设置jar文件名
APP_NAME=app.jar
#使用说明,用来提示输入参数
usage() {
echo "Usage: sh 执行脚本.sh [start|stop|restart|status]"
exit 1
}
#检查程序是否在运行
is_exist(){
pid=`ps -ef|grep $APP_NAME|grep -v grep|awk '{print $2}' `
#如果不存在返回1,存在返回0
if [ -z "${pid}" ]; then
return 1
else
return 0
fi
}
#启动方法
start(){
is_exist
if [ $? -eq "0" ]; then
echo "${APP_NAME} is already running. pid=${pid} ."
else
nohup java -Xms1024m -Xmx1024m -jar $APP_NAME > /dev/null 2>&1 &
fi
}
#停止方法
stop(){
is_exist
if [ $? -eq "0" ]; then
kill -9 $pid
else
echo "${APP_NAME} is not running"
fi
}
#输出运行状态
status(){
is_exist
if [ $? -eq "0" ]; then
echo "${APP_NAME} is running. Pid is ${pid}"
else
echo "${APP_NAME} is NOT running."
fi
}
#重启
restart(){
stop
start
}
#根据输入参数,选择执行对应方法,不输入则执行使用说明
case "$1" in
"start")
start
;;
"stop")
stop
;;
"status")
status
;;
"restart")
restart
;;
*)
usage
;;
esac

566
doc/sql/db/database-info.md

@ -0,0 +1,566 @@
Table: blade_attach(附件表)
| Field | Type | Null | Key | Default | Remarks |
| ------------- | ------------- | ---- | --- | ------- | ------- |
| id | BIGINT(19) | NO | PRI | | 主键 |
| tenant_id | VARCHAR(12) | YES | | 000000 | 租户ID |
| link | VARCHAR(1000) | YES | | | 附件地址 |
| domain_url | VARCHAR(500) | YES | | | 附件域名 |
| name | VARCHAR(500) | YES | | | 附件名称 |
| original_name | VARCHAR(500) | YES | | | 附件原名 |
| extension | VARCHAR(12) | YES | | | 附件拓展名 |
| attach_size | BIGINT(19) | YES | | | 附件大小 |
| create_user | BIGINT(19) | YES | | | 创建人 |
| create_dept | BIGINT(19) | YES | | | 创建部门 |
| create_time | DATETIME(19) | YES | | | 创建时间 |
| update_user | BIGINT(19) | YES | | | 修改人 |
| update_time | DATETIME(19) | YES | | | 修改时间 |
| status | INT(10) | YES | | | 状态 |
| is_deleted | INT(10) | YES | | | 是否已删除 |
Table: blade_client(客户端表)
| Field | Type | Null | Key | Default | Remarks |
| ----------------------- | ------------- | ---- | --- | ------- | ------- |
| id | BIGINT(19) | NO | PRI | | 主键 |
| client_id | VARCHAR(48) | NO | | | 客户端id |
| client_secret | VARCHAR(256) | NO | | | 客户端密钥 |
| resource_ids | VARCHAR(256) | YES | | | 资源集合 |
| scope | VARCHAR(256) | NO | | | 授权范围 |
| authorized_grant_types | VARCHAR(256) | NO | | | 授权类型 |
| web_server_redirect_uri | VARCHAR(256) | YES | | | 回调地址 |
| authorities | VARCHAR(256) | YES | | | 权限 |
| access_token_validity | INT(10) | NO | | | 令牌过期秒数 |
| refresh_token_validity | INT(10) | NO | | | 刷新令牌过期秒数|
| additional_information | VARCHAR(4096) | YES | | | 附加说明 |
| autoapprove | VARCHAR(256) | YES | | | 自动授权 |
| create_user | BIGINT(19) | YES | | | 创建人 |
| create_dept | BIGINT(19) | YES | | | 创建部门 |
| create_time | DATETIME(19) | YES | | | 创建时间 |
| update_user | BIGINT(19) | YES | | | 修改人 |
| update_time | DATETIME(19) | YES | | | 修改时间 |
| status | INT(10) | NO | | | 状态 |
| is_deleted | INT(10) | NO | | | 是否已删除 |
Table: blade_code(代码生成表)
| Field | Type | Null | Key | Default | Remarks |
| ------------- | ------------- | ---- | --- | ------- | ------- |
| id | BIGINT(19) | NO | PRI | | 主键 |
| datasource_id | BIGINT(19) | YES | | | 数据源主键 |
| service_name | VARCHAR(64) | YES | | | 服务名称 |
| code_name | VARCHAR(64) | YES | | | 模块名称 |
| table_name | VARCHAR(64) | YES | | | 表名 |
| table_prefix | VARCHAR(64) | YES | | | 表前缀 |
| pk_name | VARCHAR(32) | YES | | | 主键名 |
| package_name | VARCHAR(500) | YES | | | 后端包名 |
| base_mode | INT(10) | YES | | | 基础业务模式 |
| wrap_mode | INT(10) | YES | | | 包装器模式 |
| feign_mode | INT(10) | YES | | | 远程调用模式 |
| code_style | VARCHAR(32) | YES | | | 代码风格 |
| api_path | VARCHAR(2000) | YES | | | 后端路径 |
| web_path | VARCHAR(2000) | YES | | | 前端路径 |
| is_deleted | INT(10) | YES | | 0 | 是否已删除 |
Table: blade_datasource(数据源配置表)
| Field | Type | Null | Key | Default | Remarks |
| ------------ | ------------ | ---- | --- | ------- | ------- |
| id | BIGINT(19) | NO | PRI | | 主键 |
| name | VARCHAR(100) | YES | | | 名称 |
| driver_class | VARCHAR(100) | YES | | | 驱动类 |
| url | VARCHAR(500) | YES | | | 连接地址 |
| username | VARCHAR(50) | YES | | | 用户名 |
| password | VARCHAR(50) | YES | | | 密码 |
| remark | VARCHAR(255) | YES | | | 备注 |
| create_user | BIGINT(19) | YES | | | 创建人 |
| create_dept | BIGINT(19) | YES | | | 创建部门 |
| create_time | DATETIME(19) | YES | | | 创建时间 |
| update_user | BIGINT(19) | YES | | | 修改人 |
| update_time | DATETIME(19) | YES | | | 修改时间 |
| status | INT(10) | YES | | | 状态 |
| is_deleted | INT(10) | YES | | | 是否已删除 |
Table: blade_dept(机构表)
| Field | Type | Null | Key | Default | Remarks |
| ------------- | ------------- | ---- | --- | ------- | ------- |
| id | BIGINT(19) | NO | PRI | | 主键 |
| tenant_id | VARCHAR(12) | YES | | 000000 | 租户ID |
| parent_id | BIGINT(19) | YES | | 0 | 父主键 |
| ancestors | VARCHAR(2000) | YES | | | 祖级列表 |
| dept_category | INT(10) | YES | | | 部门类型 |
| dept_name | VARCHAR(45) | YES | | | 部门名 |
| full_name | VARCHAR(45) | YES | | | 部门全称 |
| sort | INT(10) | YES | | | 排序 |
| remark | VARCHAR(255) | YES | | | 备注 |
| is_deleted | INT(10) | YES | | 0 | 是否已删除 |
Table: blade_dict(字典表)
| Field | Type | Null | Key | Default | Remarks |
| ---------- | ------------ | ---- | --- | ------- | ------- |
| id | BIGINT(19) | NO | PRI | | 主键 |
| parent_id | BIGINT(19) | YES | | 0 | 父主键 |
| code | VARCHAR(255) | YES | | | 字典码 |
| dict_key | VARCHAR(255) | YES | | | 字典值 |
| dict_value | VARCHAR(255) | YES | | | 字典名称 |
| sort | INT(10) | YES | | | 排序 |
| remark | VARCHAR(255) | YES | | | 字典备注 |
| is_sealed | INT(10) | YES | | 0 | 是否已封存 |
| is_deleted | INT(10) | YES | | 0 | 是否已删除 |
Table: blade_dict_biz(业务字典表)
| Field | Type | Null | Key | Default | Remarks |
| ---------- | ------------ | ---- | --- | ------- | ------- |
| id | BIGINT(19) | NO | PRI | | 主键 |
| tenant_id | VARCHAR(12) | YES | | | 租户ID |
| parent_id | BIGINT(19) | YES | | 0 | 父主键 |
| code | VARCHAR(255) | YES | | | 字典码 |
| dict_key | VARCHAR(255) | YES | | | 字典值 |
| dict_value | VARCHAR(255) | YES | | | 字典名称 |
| sort | INT(10) | YES | | | 排序 |
| remark | VARCHAR(255) | YES | | | 字典备注 |
| is_sealed | INT(10) | YES | | 0 | 是否已封存 |
| is_deleted | INT(10) | YES | | 0 | 是否已删除 |
Table: blade_log_api(接口日志表)
| Field | Type | Null | Key | Default | Remarks |
| ------------ | ------------- | ---- | --- | ----------------- | ------- |
| id | BIGINT(19) | NO | PRI | | 编号 |
| tenant_id | VARCHAR(12) | YES | | 000000 | 租户ID |
| service_id | VARCHAR(32) | YES | | | 服务ID |
| server_host | VARCHAR(255) | YES | | | 服务器名 |
| server_ip | VARCHAR(255) | YES | | | 服务器IP地址 |
| env | VARCHAR(255) | YES | | | 服务器环境 |
| type | CHAR(1) | YES | | 1 | 日志类型 |
| title | VARCHAR(255) | YES | | | 日志标题 |
| method | VARCHAR(10) | YES | | | 操作方式 |
| request_uri | VARCHAR(255) | YES | | | 请求URI |
| user_agent | VARCHAR(1000) | YES | | | 用户代理 |
| remote_ip | VARCHAR(255) | YES | | | 操作IP地址 |
| method_class | VARCHAR(255) | YES | | | 方法类 |
| method_name | VARCHAR(255) | YES | | | 方法名 |
| params | TEXT(65535) | YES | | | 操作提交的数据 |
| time | VARCHAR(64) | YES | | | 执行时间 |
| create_by | VARCHAR(64) | YES | | | 创建者 |
| create_time | DATETIME(19) | YES | | CURRENT_TIMESTAMP | 创建时间 |
Table: blade_log_error(错误日志表)
| Field | Type | Null | Key | Default | Remarks |
| -------------- | ------------- | ---- | --- | ----------------- | ------- |
| id | BIGINT(19) | NO | PRI | | 编号 |
| tenant_id | VARCHAR(12) | YES | | 000000 | 租户ID |
| service_id | VARCHAR(32) | YES | | | 服务ID |
| server_host | VARCHAR(255) | YES | | | 服务器名 |
| server_ip | VARCHAR(255) | YES | | | 服务器IP地址 |
| env | VARCHAR(255) | YES | | | 系统环境 |
| method | VARCHAR(10) | YES | | | 操作方式 |
| request_uri | VARCHAR(255) | YES | | | 请求URI |
| user_agent | VARCHAR(1000) | YES | | | 用户代理 |
| stack_trace | TEXT(65535) | YES | | | 堆栈 |
| exception_name | VARCHAR(255) | YES | | | 异常名 |
| message | TEXT(65535) | YES | | | 异常信息 |
| line_number | INT(10) | YES | | | 错误行数 |
| remote_ip | VARCHAR(255) | YES | | | 操作IP地址 |
| method_class | VARCHAR(255) | YES | | | 方法类 |
| file_name | VARCHAR(1000) | YES | | | 文件名 |
| method_name | VARCHAR(255) | YES | | | 方法名 |
| params | TEXT(65535) | YES | | | 操作提交的数据 |
| create_by | VARCHAR(64) | YES | | | 创建者 |
| create_time | DATETIME(19) | YES | | CURRENT_TIMESTAMP | 创建时间 |
Table: blade_log_usual(通用日志表)
| Field | Type | Null | Key | Default | Remarks |
| ------------ | ------------- | ---- | --- | ----------------- | ------- |
| id | BIGINT(19) | NO | PRI | | 编号 |
| tenant_id | VARCHAR(12) | YES | | 000000 | 租户ID |
| service_id | VARCHAR(32) | YES | | | 服务ID |
| server_host | VARCHAR(255) | YES | | | 服务器名 |
| server_ip | VARCHAR(255) | YES | | | 服务器IP地址 |
| env | VARCHAR(255) | YES | | | 系统环境 |
| log_level | VARCHAR(10) | YES | | | 日志级别 |
| log_id | VARCHAR(100) | YES | | | 日志业务id |
| log_data | TEXT(65535) | YES | | | 日志数据 |
| method | VARCHAR(10) | YES | | | 操作方式 |
| request_uri | VARCHAR(255) | YES | | | 请求URI |
| remote_ip | VARCHAR(255) | YES | | | 操作IP地址 |
| method_class | VARCHAR(255) | YES | | | 方法类 |
| method_name | VARCHAR(255) | YES | | | 方法名 |
| user_agent | VARCHAR(1000) | YES | | | 用户代理 |
| params | TEXT(65535) | YES | | | 操作提交的数据 |
| create_by | VARCHAR(64) | YES | | | 创建者 |
| create_time | DATETIME(19) | YES | | CURRENT_TIMESTAMP | 创建时间 |
Table: blade_menu(菜单表)
| Field | Type | Null | Key | Default | Remarks |
| ---------- | ------------ | ---- | --- | ------- | ------- |
| id | BIGINT(19) | NO | PRI | | 主键 |
| parent_id | BIGINT(19) | YES | | 0 | 父级菜单 |
| code | VARCHAR(255) | YES | | | 菜单编号 |
| name | VARCHAR(255) | YES | | | 菜单名称 |
| alias | VARCHAR(255) | YES | | | 菜单别名 |
| path | VARCHAR(255) | YES | | | 请求地址 |
| source | VARCHAR(255) | YES | | | 菜单资源 |
| sort | INT(10) | YES | | | 排序 |
| category | INT(10) | YES | | | 菜单类型 |
| action | INT(10) | YES | | 0 | 操作按钮类型 |
| is_open | INT(10) | YES | | 1 | 是否打开新页面 |
| remark | VARCHAR(255) | YES | | | 备注 |
| is_deleted | INT(10) | YES | | 0 | 是否已删除 |
Table: blade_notice(通知公告表)
| Field | Type | Null | Key | Default | Remarks |
| ------------ | ------------- | ---- | --- | ------- | ------- |
| id | BIGINT(19) | NO | PRI | | 主键 |
| tenant_id | VARCHAR(12) | YES | | 000000 | 租户ID |
| title | VARCHAR(255) | YES | | | 标题 |
| category | INT(10) | YES | | | 类型 |
| release_time | DATETIME(19) | YES | | | 发布时间 |
| content | VARCHAR(2000) | YES | | | 内容 |
| create_user | BIGINT(19) | YES | | | 创建人 |
| create_dept | BIGINT(19) | YES | | | 创建部门 |
| create_time | DATETIME(19) | YES | | | 创建时间 |
| update_user | BIGINT(19) | YES | | | 修改人 |
| update_time | DATETIME(19) | YES | | | 修改时间 |
| status | INT(10) | YES | | | 状态 |
| is_deleted | INT(10) | YES | | | 是否已删除 |
Table: blade_oss(对象存储表)
| Field | Type | Null | Key | Default | Remarks |
| ----------- | ------------ | ---- | --- | ------- | ------- |
| id | BIGINT(19) | NO | PRI | | 主键 |
| tenant_id | VARCHAR(12) | YES | | 000000 | 租户ID |
| category | INT(10) | YES | | | 分类 |
| oss_code | VARCHAR(32) | YES | | | 资源编号 |
| endpoint | VARCHAR(255) | YES | | | 资源地址 |
| access_key | VARCHAR(255) | YES | | | accessKey|
| secret_key | VARCHAR(255) | YES | | | secretKey|
| bucket_name | VARCHAR(255) | YES | | | 空间名 |
| app_id | VARCHAR(255) | YES | | | 应用ID |
| region | VARCHAR(255) | YES | | | 地域简称 |
| remark | VARCHAR(255) | YES | | | 备注 |
| create_user | BIGINT(19) | YES | | | 创建人 |
| create_dept | BIGINT(19) | YES | | | 创建部门 |
| create_time | DATETIME(19) | YES | | | 创建时间 |
| update_user | BIGINT(19) | YES | | | 修改人 |
| update_time | DATETIME(19) | YES | | | 修改时间 |
| status | INT(10) | YES | | | 状态 |
| is_deleted | INT(10) | YES | | 0 | 是否已删除 |
Table: blade_param(参数表)
| Field | Type | Null | Key | Default | Remarks |
| ----------- | ------------ | ---- | --- | ------- | ------- |
| id | BIGINT(19) | NO | PRI | | 主键 |
| param_name | VARCHAR(255) | YES | | | 参数名 |
| param_key | VARCHAR(255) | YES | | | 参数键 |
| param_value | VARCHAR(255) | YES | | | 参数值 |
| remark | VARCHAR(255) | YES | | | 备注 |
| create_user | BIGINT(19) | YES | | | 创建人 |
| create_dept | BIGINT(19) | YES | | | 创建部门 |
| create_time | DATETIME(19) | YES | | | 创建时间 |
| update_user | BIGINT(19) | YES | | | 修改人 |
| update_time | DATETIME(19) | YES | | | 修改时间 |
| status | INT(10) | YES | | | 状态 |
| is_deleted | INT(10) | YES | | 0 | 是否已删除 |
Table: blade_post(岗位表)
| Field | Type | Null | Key | Default | Remarks |
| ----------- | ------------ | ---- | --- | ------- | ------- |
| id | BIGINT(19) | NO | PRI | | 主键 |
| tenant_id | VARCHAR(12) | YES | | 000000 | 租户ID |
| category | INT(10) | YES | | | 岗位类型 |
| post_code | VARCHAR(12) | YES | | | 岗位编号 |
| post_name | VARCHAR(64) | YES | | | 岗位名称 |
| sort | INT(10) | YES | | | 岗位排序 |
| remark | VARCHAR(255) | YES | | | 岗位描述 |
| create_user | BIGINT(19) | YES | | | 创建人 |
| create_dept | BIGINT(19) | YES | | | 创建部门 |
| create_time | DATETIME(19) | YES | | | 创建时间 |
| update_user | BIGINT(19) | YES | | | 修改人 |
| update_time | DATETIME(19) | YES | | | 修改时间 |
| status | INT(10) | YES | | | 状态 |
| is_deleted | INT(10) | YES | | | 是否已删除 |
Table: blade_process_leave(流程请假业务表)
| Field | Type | Null | Key | Default | Remarks |
| --------------------- | ------------ | ---- | --- | ------- | ------- |
| id | BIGINT(19) | NO | PRI | | 编号 |
| process_definition_id | VARCHAR(64) | YES | | | 流程定义主键 |
| process_instance_id | VARCHAR(64) | YES | | | 流程实例主键 |
| start_time | DATETIME(19) | YES | | | 开始时间 |
| end_time | DATETIME(19) | YES | | | 结束时间 |
| reason | VARCHAR(255) | YES | | | 请假理由 |
| task_user | VARCHAR(255) | YES | | | 第一级审批人 |
| apply_time | DATETIME(19) | YES | | | 申请时间 |
| create_user | BIGINT(19) | YES | | | 创建人 |
| create_dept | BIGINT(19) | YES | | | 创建部门 |
| create_time | DATETIME(19) | YES | | | 创建时间 |
| update_user | BIGINT(19) | YES | | | 修改人 |
| update_time | DATETIME(19) | YES | | | 修改时间 |
| status | INT(10) | YES | | | 状态 |
| is_deleted | INT(10) | YES | | | 是否已删除 |
Table: blade_region(行政区划表)
| Field | Type | Null | Key | Default | Remarks |
| ------------- | ------------ | ---- | --- | ------- | ------- |
| code | VARCHAR(12) | NO | PRI | | 区划编号 |
| parent_code | VARCHAR(12) | YES | | | 父区划编号 |
| ancestors | VARCHAR(255) | YES | | | 祖区划编号 |
| name | VARCHAR(32) | YES | | | 区划名称 |
| province_code | VARCHAR(12) | YES | | | 省级区划编号 |
| province_name | VARCHAR(32) | YES | | | 省级名称 |
| city_code | VARCHAR(12) | YES | | | 市级区划编号 |
| city_name | VARCHAR(32) | YES | | | 市级名称 |
| district_code | VARCHAR(12) | YES | | | 区级区划编号 |
| district_name | VARCHAR(32) | YES | | | 区级名称 |
| town_code | VARCHAR(12) | YES | | | 镇级区划编号 |
| town_name | VARCHAR(32) | YES | | | 镇级名称 |
| village_code | VARCHAR(12) | YES | | | 村级区划编号 |
| village_name | VARCHAR(32) | YES | | | 村级名称 |
| region_level | INT(10) | YES | | | 层级 |
| sort | INT(10) | YES | | | 排序 |
| remark | VARCHAR(255) | YES | | | 备注 |
Table: blade_report_file(报表文件表)
| Field | Type | Null | Key | Default | Remarks |
| ----------- | -------------------- | ---- | --- | ------- | ------- |
| id | BIGINT(19) | NO | PRI | | 主键 |
| name | VARCHAR(100) | NO | | | 文件名 |
| content | MEDIUMBLOB(16777215) | YES | | | 文件内容 |
| create_time | DATETIME(19) | YES | | | 创建时间 |
| update_time | DATETIME(19) | YES | | | 更新时间 |
| is_deleted | INT(10) | YES | | 0 | 是否已删除 |
Table: blade_role(角色表)
| Field | Type | Null | Key | Default | Remarks |
| ---------- | ------------ | ---- | --- | ------- | ------- |
| id | BIGINT(19) | NO | PRI | | 主键 |
| tenant_id | VARCHAR(12) | YES | | 000000 | 租户ID |
| parent_id | BIGINT(19) | YES | | 0 | 父主键 |
| role_name | VARCHAR(255) | YES | | | 角色名 |
| sort | INT(10) | YES | | | 排序 |
| role_alias | VARCHAR(255) | YES | | | 角色别名 |
| is_deleted | INT(10) | YES | | 0 | 是否已删除 |
Table: blade_role_menu(角色菜单关联表)
| Field | Type | Null | Key | Default | Remarks |
| ------- | ---------- | ---- | --- | ------- | ------- |
| id | BIGINT(19) | NO | PRI | | 主键 |
| menu_id | BIGINT(19) | YES | | | 菜单id |
| role_id | BIGINT(19) | YES | | | 角色id |
Table: blade_role_scope(角色数据权限关联表)
| Field | Type | Null | Key | Default | Remarks |
| -------------- | ---------- | ---- | --- | ------- | ------- |
| id | BIGINT(19) | NO | PRI | | 主键 |
| scope_category | INT(10) | YES | | | 权限类型(1:数据权限、2:接口权限)|
| scope_id | BIGINT(19) | YES | | | 权限id |
| role_id | BIGINT(19) | YES | | | 角色id |
Table: blade_scope_api(接口权限表)
| Field | Type | Null | Key | Default | Remarks |
| ------------- | ------------ | ---- | --- | ------- | ------- |
| id | BIGINT(19) | NO | PRI | | 主键 |
| menu_id | BIGINT(19) | YES | | | 菜单主键 |
| resource_code | VARCHAR(255) | YES | | | 资源编号 |
| scope_name | VARCHAR(255) | YES | | | 接口权限名 |
| scope_path | VARCHAR(255) | YES | | | 接口权限地址 |
| scope_type | INT(10) | YES | | | 接口权限类型 |
| remark | VARCHAR(255) | YES | | | 接口权限备注 |
| create_user | BIGINT(19) | YES | | | 创建人 |
| create_dept | BIGINT(19) | YES | | | 创建部门 |
| create_time | DATETIME(19) | YES | | | 创建时间 |
| update_user | BIGINT(19) | YES | | | 修改人 |
| update_time | DATETIME(19) | YES | | | 修改时间 |
| status | INT(10) | YES | | | 状态 |
| is_deleted | INT(10) | YES | | | 是否已删除 |
Table: blade_scope_data(数据权限表)
| Field | Type | Null | Key | Default | Remarks |
| ------------- | ------------- | ---- | --- | ------- | ------- |
| id | BIGINT(19) | NO | PRI | | 主键 |
| menu_id | BIGINT(19) | YES | | | 菜单主键 |
| resource_code | VARCHAR(255) | YES | | | 资源编号 |
| scope_name | VARCHAR(255) | YES | | | 数据权限名称 |
| scope_field | VARCHAR(255) | YES | | | 数据权限字段 |
| scope_class | VARCHAR(500) | YES | | | 数据权限类名 |
| scope_column | VARCHAR(255) | YES | | | 数据权限字段 |
| scope_type | INT(10) | YES | | | 数据权限类型 |
| scope_value | VARCHAR(2000) | YES | | | 数据权限值域 |
| remark | VARCHAR(255) | YES | | | 数据权限备注 |
| create_user | BIGINT(19) | YES | | | 创建人 |
| create_dept | BIGINT(19) | YES | | | 创建部门 |
| create_time | DATETIME(19) | YES | | | 创建时间 |
| update_user | BIGINT(19) | YES | | | 修改人 |
| update_time | DATETIME(19) | YES | | | 修改时间 |
| status | INT(10) | YES | | | 状态 |
| is_deleted | INT(10) | YES | | | 是否已删除 |
Table: blade_sms(短信配置表)
| Field | Type | Null | Key | Default | Remarks |
| ----------- | ------------ | ---- | --- | ------- | ------- |
| id | BIGINT(19) | NO | PRI | | 主键 |
| tenant_id | VARCHAR(12) | YES | | 000000 | 租户ID |
| category | INT(10) | YES | | | 分类 |
| sms_code | VARCHAR(32) | YES | | | 资源编号 |
| template_id | VARCHAR(64) | YES | | | 模板ID |
| access_key | VARCHAR(255) | YES | | | accessKey|
| secret_key | VARCHAR(255) | YES | | | secretKey|
| region_id | VARCHAR(255) | YES | | | regionId|
| sign_name | VARCHAR(64) | YES | | | 短信签名 |
| remark | VARCHAR(255) | YES | | | 备注 |
| create_user | BIGINT(19) | YES | | | 创建人 |
| create_dept | BIGINT(19) | YES | | | 创建部门 |
| create_time | DATETIME(19) | YES | | | 创建时间 |
| update_user | BIGINT(19) | YES | | | 修改人 |
| update_time | DATETIME(19) | YES | | | 修改时间 |
| status | INT(10) | YES | | | 状态 |
| is_deleted | INT(10) | YES | | 0 | 是否已删除 |
Table: blade_tenant(租户表)
| Field | Type | Null | Key | Default | Remarks |
| -------------- | ------------- | ---- | --- | ------- | ------- |
| id | BIGINT(19) | NO | PRI | | 主键 |
| tenant_id | VARCHAR(12) | YES | | 000000 | 租户ID |
| tenant_name | VARCHAR(50) | NO | | | 租户名称 |
| domain_url | VARCHAR(255) | YES | | | 域名地址 |
| background_url | VARCHAR(1000) | YES | | | 系统背景 |
| linkman | VARCHAR(20) | YES | | | 联系人 |
| contact_number | VARCHAR(20) | YES | | | 联系电话 |
| address | VARCHAR(255) | YES | | | 联系地址 |
| account_number | INT(10) | YES | | -1 | 账号额度 |
| expire_time | DATETIME(19) | YES | | | 过期时间 |
| datasource | BIGINT(19) | YES | | | 数据源ID |
| license_key | VARCHAR(1000) | YES | | | 授权码 |
| create_user | BIGINT(19) | YES | | | 创建人 |
| create_dept | BIGINT(19) | YES | | | 创建部门 |
| create_time | DATETIME(19) | YES | | | 创建时间 |
| update_user | BIGINT(19) | YES | | | 修改人 |
| update_time | DATETIME(19) | YES | | | 修改时间 |
| status | INT(10) | YES | | | 状态 |
| is_deleted | INT(10) | YES | | 0 | 是否已删除 |
Table: blade_top_menu(顶部菜单表)
| Field | Type | Null | Key | Default | Remarks |
| ----------- | ------------ | ---- | --- | ------- | ------- |
| id | BIGINT(19) | NO | PRI | | 主键 |
| tenant_id | VARCHAR(12) | YES | | | 租户id |
| code | VARCHAR(255) | YES | | | 顶部菜单编号 |
| name | VARCHAR(255) | YES | | | 顶部菜单名 |
| source | VARCHAR(255) | YES | | | 顶部菜单资源 |
| sort | INT(10) | YES | | | 顶部菜单排序 |
| create_user | BIGINT(19) | YES | | | 创建人 |
| create_dept | BIGINT(19) | YES | | | 创建部门 |
| create_time | DATETIME(19) | YES | | | 创建时间 |
| update_user | BIGINT(19) | YES | | | 修改人 |
| update_time | DATETIME(19) | YES | | | 修改时间 |
| status | INT(10) | YES | | | 状态 |
| is_deleted | INT(10) | YES | | | 是否已删除 |
Table: blade_top_menu_setting(顶部菜单配置表)
| Field | Type | Null | Key | Default | Remarks |
| ----------- | ---------- | ---- | --- | ------- | ------- |
| id | BIGINT(19) | NO | PRI | | 主键 |
| top_menu_id | BIGINT(19) | YES | | | 顶部菜单主键 |
| menu_id | BIGINT(19) | YES | | | 菜单主键 |
Table: blade_user(用户表)
| Field | Type | Null | Key | Default | Remarks |
| ----------- | ------------- | ---- | --- | ------- | ------- |
| id | BIGINT(19) | NO | PRI | | 主键 |
| tenant_id | VARCHAR(12) | YES | | 000000 | 租户ID |
| code | VARCHAR(12) | YES | | | 用户编号 |
| user_type | SMALLINT(5) | YES | | | 用户平台 |
| account | VARCHAR(45) | YES | | | 账号 |
| password | VARCHAR(45) | YES | | | 密码 |
| name | VARCHAR(20) | YES | | | 昵称 |
| real_name | VARCHAR(10) | YES | | | 真名 |
| avatar | VARCHAR(500) | YES | | | 头像 |
| email | VARCHAR(45) | YES | | | 邮箱 |
| phone | VARCHAR(45) | YES | | | 手机 |
| birthday | DATETIME(19) | YES | | | 生日 |
| sex | SMALLINT(5) | YES | | | 性别 |
| role_id | VARCHAR(1000) | YES | | | 角色id |
| dept_id | VARCHAR(1000) | YES | | | 部门id |
| post_id | VARCHAR(1000) | YES | | | 岗位id |
| create_user | BIGINT(19) | YES | | | 创建人 |
| create_dept | BIGINT(19) | YES | | | 创建部门 |
| create_time | DATETIME(19) | YES | | | 创建时间 |
| update_user | BIGINT(19) | YES | | | 修改人 |
| update_time | DATETIME(19) | YES | | | 修改时间 |
| status | INT(10) | YES | | | 状态 |
| is_deleted | INT(10) | YES | | 0 | 是否已删除 |
Table: blade_user_dept(用户部门表)
| Field | Type | Null | Key | Default | Remarks |
| ------- | ---------- | ---- | --- | ------- | ------- |
| id | BIGINT(19) | NO | PRI | | 主键 |
| user_id | BIGINT(19) | YES | | 0 | 用户ID |
| dept_id | BIGINT(19) | YES | | 0 | 部门ID |
Table: blade_user_oauth(用户第三方认证表)
| Field | Type | Null | Key | Default | Remarks |
| --------- | ------------- | ---- | --- | ------- | ------- |
| id | BIGINT(19) | NO | PRI | | 主键 |
| tenant_id | VARCHAR(12) | YES | | | 租户ID |
| uuid | VARCHAR(64) | YES | | | 第三方系统用户ID|
| user_id | BIGINT(19) | YES | | | 用户ID |
| username | VARCHAR(32) | YES | | | 账号 |
| nickname | VARCHAR(64) | YES | | | 用户名 |
| avatar | VARCHAR(1000) | YES | | | 头像 |
| blog | VARCHAR(50) | YES | | | 应用主页 |
| company | VARCHAR(255) | YES | | | 公司名 |
| location | VARCHAR(255) | YES | | | 地址 |
| email | VARCHAR(255) | YES | | | 邮件 |
| remark | VARCHAR(255) | YES | | | 备注 |
| gender | VARCHAR(16) | YES | | | 性别 |
| source | VARCHAR(16) | YES | | | 来源 |
Table: blade_user_web(用户平台拓展表)
| Field | Type | Null | Key | Default | Remarks |
| ------- | ---------- | ---- | --- | ------- | ------- |
| id | BIGINT(19) | NO | PRI | | 主键 |
| user_id | BIGINT(19) | YES | | 0 | 用户ID |
| user_ext | VARCHAR(255) | YES | | | 用户拓展信息 |
Table: blade_user_app(用户平台拓展表)
| Field | Type | Null | Key | Default | Remarks |
| ------- | ---------- | ---- | --- | ------- | ------- |
| id | BIGINT(19) | NO | PRI | | 主键 |
| user_id | BIGINT(19) | YES | | 0 | 用户ID |
| user_ext | VARCHAR(255) | YES | | | 用户拓展信息 |
Table: blade_user_other(用户平台拓展表)
| Field | Type | Null | Key | Default | Remarks |
| ------- | ---------- | ---- | --- | ------- | ------- |
| id | BIGINT(19) | NO | PRI | | 主键 |
| user_id | BIGINT(19) | YES | | 0 | 用户ID |
| user_ext | VARCHAR(255) | YES | | | 用户拓展信息 |

BIN
doc/sql/dm/bladex-flowable-dameng.dmp

Binary file not shown.

BIN
doc/sql/dm/bladex-saber-dameng.dmp

Binary file not shown.

BIN
doc/sql/dm/bladex-sword-dameng.dmp

Binary file not shown.

1777
doc/sql/mysql/bladex-flowable-mysql.sql

File diff suppressed because it is too large Load Diff

832
doc/sql/mysql/bladex-saber-mysql.sql

File diff suppressed because one or more lines are too long

832
doc/sql/mysql/bladex-sword-mysql.sql

File diff suppressed because one or more lines are too long

5676
doc/sql/oracle/bladex-flowable-oracle.sql

File diff suppressed because it is too large Load Diff

6308
doc/sql/oracle/bladex-saber-oracle.sql

File diff suppressed because it is too large Load Diff

6305
doc/sql/oracle/bladex-sword-oracle.sql

File diff suppressed because it is too large Load Diff

2741
doc/sql/postgresql/bladex-flowable-postgresql.sql

File diff suppressed because it is too large Load Diff

5173
doc/sql/postgresql/bladex-saber-postgresql.sql

File diff suppressed because it is too large Load Diff

5173
doc/sql/postgresql/bladex-sword-postgresql.sql

File diff suppressed because it is too large Load Diff

4113
doc/sql/sqlserver/bladex-flowable-sqlserver.sql

File diff suppressed because it is too large Load Diff

4599
doc/sql/sqlserver/bladex-saber-sqlserver.sql

File diff suppressed because one or more lines are too long

4599
doc/sql/sqlserver/bladex-sword-sqlserver.sql

File diff suppressed because one or more lines are too long

15
doc/sql/update/bladex-update-dameng-2.9.1~3.0.0.sql

@ -0,0 +1,15 @@
-- -----------------------------------
-- 给代码生成添加字段
-- -----------------------------------
ALTER TABLE "BLADEX"."BLADE_CODE" ADD "FEIGN_MODE" INT ;
ALTER TABLE "BLADEX"."BLADE_CODE" ADD "CODE_STYLE" VARCHAR(32) ;
COMMENT ON COLUMN "BLADEX"."BLADE_CODE"."FEIGN_MODE" IS '远程调用模式';
COMMENT ON COLUMN "BLADEX"."BLADE_CODE"."CODE_STYLE" IS '代码风格';
-- -----------------------------------
-- 修改应用表saber的访问地址
-- -----------------------------------
UPDATE "BLADEX"."BLADE_CLIENT" SET WEB_SERVER_REDIRECT_URI = 'http://localhost:1888' WHERE CLIENT_ID = 'saber';

11
doc/sql/update/bladex-update-mysql-2.9.1~3.0.0.sql

@ -0,0 +1,11 @@
-- -----------------------------------
-- 给代码生成添加字段
-- -----------------------------------
ALTER TABLE `blade_code`
ADD COLUMN `feign_mode` int(2) NULL COMMENT '远程调用模式' AFTER `wrap_mode`,
ADD COLUMN `code_style` varchar(32) NULL COMMENT '代码风格' AFTER `feign_mode`;
-- -----------------------------------
-- 修改应用表saber的访问地址
-- -----------------------------------
UPDATE blade_client SET web_server_redirect_uri = 'http://localhost:1888' WHERE client_id = 'saber';

15
doc/sql/update/bladex-update-oracle-2.9.1~3.0.0.sql

@ -0,0 +1,15 @@
-- -----------------------------------
-- 给代码生成添加字段
-- -----------------------------------
ALTER TABLE "BLADEX"."BLADE_CODE"
ADD ("FEIGN_MODE" NUMBER(11) )
ADD ("CODE_STYLE" VARCHAR2(32) );
COMMENT ON COLUMN "BLADEX"."BLADE_CODE"."FEIGN_MODE" IS '远程调用模式';
COMMENT ON COLUMN "BLADEX"."BLADE_CODE"."CODE_STYLE" IS '代码风格';
-- -----------------------------------
-- 修改应用表saber的访问地址
-- -----------------------------------
UPDATE "BLADEX"."BLADE_CLIENT" SET WEB_SERVER_REDIRECT_URI = 'http://localhost:1888' WHERE CLIENT_ID = 'saber';

15
doc/sql/update/bladex-update-postgresql-2.9.1~3.0.0.sql

@ -0,0 +1,15 @@
-- -----------------------------------
-- 给代码生成添加字段
-- -----------------------------------
ALTER TABLE "blade_code"
ADD COLUMN "feign_mode" int2,
ADD COLUMN "code_style" varchar(32);
COMMENT ON COLUMN "blade_code"."feign_mode" IS '远程调用模式';
COMMENT ON COLUMN "blade_code"."code_style" IS '代码风格';
-- -----------------------------------
-- 修改应用表saber的访问地址
-- -----------------------------------
UPDATE blade_client SET web_server_redirect_uri = 'http://localhost:1888' WHERE client_id = 'saber';

26
doc/sql/update/bladex-update-sqlserver-2.9.1~3.0.0.sql

@ -0,0 +1,26 @@
-- -----------------------------------
-- 给代码生成添加字段
-- -----------------------------------
ALTER TABLE [dbo].[blade_code] ADD [feign_mode] int
GO
ALTER TABLE [dbo].[blade_code] ADD [code_style] varchar(32)
GO
EXEC sp_addextendedproperty
'MS_Description', N'远程调用模式',
'SCHEMA', N'dbo',
'TABLE', N'blade_code',
'COLUMN', N'feign_mode'
GO
EXEC sp_addextendedproperty
'MS_Description', N'代码风格',
'SCHEMA', N'dbo',
'TABLE', N'blade_code',
'COLUMN', N'code_style';
-- -----------------------------------
-- 修改应用表saber的访问地址
-- -----------------------------------
UPDATE blade_client SET web_server_redirect_uri = 'http://localhost:1888' WHERE client_id = 'saber';

299
pom.xml

@ -0,0 +1,299 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.springblade</groupId>
<artifactId>BladeX-Boot</artifactId>
<packaging>jar</packaging>
<version>3.0.0.RELEASE</version>
<properties>
<bladex.project.id>blade-api</bladex.project.id>
<bladex.project.version>3.0.0.RELEASE</bladex.project.version>
<java.version>1.8</java.version>
<maven.plugin.version>3.8.1</maven.plugin.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<spring.boot.version>2.7.1</spring.boot.version>
<spring.platform.version>Cairo-SR8</spring.platform.version>
<!-- 推荐使用Harbor -->
<docker.registry.url>192.168.0.157</docker.registry.url>
<docker.registry.host>http://${docker.registry.url}:2375</docker.registry.host>
<docker.username>admin</docker.username>
<docker.password>Harbor12345</docker.password>
<docker.namespace>blade</docker.namespace>
<docker.plugin.version>1.4.13</docker.plugin.version>
</properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springblade.platform</groupId>
<artifactId>blade-bom</artifactId>
<version>${bladex.project.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>${spring.boot.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>io.spring.platform</groupId>
<artifactId>platform-bom</artifactId>
<version>${spring.platform.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<!-- Blade -->
<dependency>
<groupId>org.springblade</groupId>
<artifactId>blade-core-boot</artifactId>
<exclusions>
<exclusion>
<groupId>org.springblade</groupId>
<artifactId>blade-core-cloud</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springblade</groupId>
<artifactId>blade-starter-http</artifactId>
</dependency>
<dependency>
<groupId>org.springblade</groupId>
<artifactId>blade-starter-api-crypto</artifactId>
</dependency>
<dependency>
<groupId>org.springblade</groupId>
<artifactId>blade-starter-datascope</artifactId>
</dependency>
<dependency>
<groupId>org.springblade</groupId>
<artifactId>blade-starter-tenant</artifactId>
</dependency>
<dependency>
<groupId>org.springblade</groupId>
<artifactId>blade-starter-develop</artifactId>
</dependency>
<dependency>
<groupId>org.springblade</groupId>
<artifactId>blade-starter-swagger</artifactId>
</dependency>
<dependency>
<groupId>org.springblade</groupId>
<artifactId>blade-starter-excel</artifactId>
</dependency>
<dependency>
<groupId>org.springblade</groupId>
<artifactId>blade-starter-social</artifactId>
</dependency>
<dependency>
<groupId>com.github.xiaoymin</groupId>
<artifactId>knife4j-spring-ui</artifactId>
</dependency>
<dependency>
<groupId>org.springblade</groupId>
<artifactId>blade-core-auto</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.springblade</groupId>
<artifactId>blade-core-test</artifactId>
<scope>test</scope>
</dependency>
<!-- 报表 -->
<dependency>
<groupId>org.springblade</groupId>
<artifactId>blade-starter-report</artifactId>
</dependency>
<!-- 工作流 -->
<!-- <dependency>-->
<!-- <groupId>org.springblade</groupId>-->
<!-- <artifactId>blade-starter-flowable</artifactId>-->
<!-- </dependency>-->
<!-- 验证码 -->
<dependency>
<groupId>com.github.whvcse</groupId>
<artifactId>easy-captcha</artifactId>
</dependency>
<!-- Mybatis-Plus -->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-generator</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.apache.velocity</groupId>
<artifactId>velocity</artifactId>
<version>1.7</version>
<scope>provided</scope>
</dependency>
<!--Oss-->
<dependency>
<groupId>org.springblade</groupId>
<artifactId>blade-starter-oss</artifactId>
</dependency>
<!--Sms-->
<dependency>
<groupId>org.springblade</groupId>
<artifactId>blade-starter-sms</artifactId>
</dependency>
<!--MinIO-->
<dependency>
<groupId>io.minio</groupId>
<artifactId>minio</artifactId>
</dependency>
<!--Alioss-->
<dependency>
<groupId>com.aliyun.oss</groupId>
<artifactId>aliyun-sdk-oss</artifactId>
</dependency>
<!--AliSms-->
<dependency>
<groupId>com.aliyun</groupId>
<artifactId>aliyun-java-sdk-core</artifactId>
</dependency>
<!--腾讯COS-->
<dependency>
<groupId>com.qcloud</groupId>
<artifactId>cos_api</artifactId>
</dependency>
<!--腾讯SMS-->
<dependency>
<groupId>com.github.qcloudsms</groupId>
<artifactId>qcloudsms</artifactId>
</dependency>
<!--QiNiu-->
<dependency>
<groupId>com.qiniu</groupId>
<artifactId>qiniu-java-sdk</artifactId>
</dependency>
<!--YunPian-->
<dependency>
<groupId>com.yunpian.sdk</groupId>
<artifactId>yunpian-java-sdk</artifactId>
</dependency>
<!-- lombok -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<scope>provided</scope>
</dependency>
</dependencies>
<build>
<finalName>${bladex.project.id}</finalName>
<resources>
<resource>
<directory>src/main/resources</directory>
</resource>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.xml</include>
</includes>
</resource>
</resources>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>${spring.boot.version}</version>
<configuration>
<finalName>${project.build.finalName}</finalName>
</configuration>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>com.spotify</groupId>
<artifactId>dockerfile-maven-plugin</artifactId>
<version>${docker.plugin.version}</version>
<configuration>
<username>${docker.username}</username>
<password>${docker.password}</password>
<repository>${docker.registry.url}/${docker.namespace}/${project.build.finalName}</repository>
<tag>${project.version}</tag>
<useMavenSettingsForAuth>true</useMavenSettingsForAuth>
<buildArgs>
<JAR_FILE>target/${project.build.finalName}.jar</JAR_FILE>
</buildArgs>
</configuration>
<!--添加如下配置,运行 mvn deploy 命令便会自动打包镜像-->
<!--<executions>
<execution>
<id>default</id>
<goals>
<goal>build</goal>
<goal>push</goal>
</goals>
</execution>
</executions>-->
</plugin>
</plugins>
</pluginManagement>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>${maven.plugin.version}</version>
<configuration>
<source>${java.version}</source>
<target>${java.version}</target>
<encoding>UTF-8</encoding>
<compilerArgs>
<arg>-parameters</arg>
</compilerArgs>
</configuration>
</plugin>
</plugins>
</build>
<repositories>
<repository>
<id>aliyun-repos</id>
<url>https://maven.aliyun.com/repository/public/</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
<repository>
<id>blade-release</id>
<name>Release Repository</name>
<url>http://nexus.bladex.vip/repository/maven-releases/</url>
</repository>
</repositories>
<pluginRepositories>
<pluginRepository>
<id>aliyun-plugin</id>
<url>https://maven.aliyun.com/repository/public/</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</pluginRepository>
</pluginRepositories>
</project>

38
src/main/java/org/springblade/Application.java

@ -0,0 +1,38 @@
/*
* Copyright (c) 2018-2028, Chill Zhuang All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* Neither the name of the dreamlu.net developer nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
* Author: Chill 庄骞 (smallchill@163.com)
*/
package org.springblade;
//import org.springblade.common.constant.CommonConstant;
import org.springblade.core.launch.BladeApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.scheduling.annotation.EnableScheduling;
/**
* 启动器
*
* @author Chill
*/
@EnableScheduling
@SpringBootApplication
public class Application {
public static void main(String[] args) {
BladeApplication.run("blade-x", Application.class, args);
}
}

61
src/main/java/org/springblade/common/cache/CacheNames.java vendored

@ -0,0 +1,61 @@
/*
* Copyright (c) 2018-2028, Chill Zhuang All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* Neither the name of the dreamlu.net developer nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
* Author: Chill 庄骞 (smallchill@163.com)
*/
package org.springblade.common.cache;
import org.springblade.core.tool.utils.StringPool;
/**
* 缓存名
*
* @author Chill
*/
public interface CacheNames {
/**
* 返回拼接后的key
*
* @param cacheKey 缓存key
* @param cacheKeyValue 缓存key值
* @return tenantKey
*/
static String cacheKey(String cacheKey, String cacheKeyValue) {
return cacheKey.concat(cacheKeyValue);
}
/**
* 返回租户格式的key
*
* @param tenantId 租户编号
* @param cacheKey 缓存key
* @param cacheKeyValue 缓存key值
* @return tenantKey
*/
static String tenantKey(String tenantId, String cacheKey, String cacheKeyValue) {
return tenantId.concat(StringPool.COLON).concat(cacheKey).concat(cacheKeyValue);
}
/**
* 验证码key
*/
String CAPTCHA_KEY = "blade:auth::blade:captcha:";
/**
* 登录失败key
*/
String USER_FAIL_KEY = "blade:user::blade:fail:";
}

116
src/main/java/org/springblade/common/cache/DictBizCache.java vendored

@ -0,0 +1,116 @@
/*
* Copyright (c) 2018-2028, Chill Zhuang All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* Neither the name of the dreamlu.net developer nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
* Author: Chill 庄骞 (smallchill@163.com)
*/
package org.springblade.common.cache;
import org.springblade.common.enums.DictBizEnum;
import org.springblade.core.cache.utils.CacheUtil;
import org.springblade.core.secure.utils.AuthUtil;
import org.springblade.core.tool.utils.SpringUtil;
import org.springblade.core.tool.utils.StringPool;
import org.springblade.modules.system.entity.DictBiz;
import org.springblade.modules.system.service.IDictBizService;
import java.util.List;
import static org.springblade.core.cache.constant.CacheConstant.DICT_CACHE;
/**
* 业务字典缓存工具类
*
* @author Chill
*/
public class DictBizCache {
private static final String DICT_ID = "dictBiz:id";
private static final String DICT_VALUE = "dictBiz:value";
private static final String DICT_LIST = "dictBiz:list";
private static final IDictBizService dictService;
static {
dictService = SpringUtil.getBean(IDictBizService.class);
}
/**
* 获取字典实体
*
* @param id 主键
* @return DictBiz
*/
public static DictBiz getById(Long id) {
String keyPrefix = DICT_ID.concat(StringPool.DASH).concat(AuthUtil.getTenantId()).concat(StringPool.COLON);
return CacheUtil.get(DICT_CACHE, keyPrefix, id, () -> dictService.getById(id));
}
/**
* 获取字典值
*
* @param code 字典编号枚举
* @param dictKey Integer型字典键
* @return String
*/
public static String getValue(DictBizEnum code, Integer dictKey) {
return getValue(code.getName(), dictKey);
}
/**
* 获取字典值
*
* @param code 字典编号
* @param dictKey Integer型字典键
* @return String
*/
public static String getValue(String code, Integer dictKey) {
String keyPrefix = DICT_VALUE.concat(StringPool.DASH).concat(AuthUtil.getTenantId()).concat(StringPool.COLON);
return CacheUtil.get(DICT_CACHE, keyPrefix + code + StringPool.COLON, String.valueOf(dictKey), () -> dictService.getValue(code, String.valueOf(dictKey)));
}
/**
* 获取字典值
*
* @param code 字典编号枚举
* @param dictKey String型字典键
* @return String
*/
public static String getValue(DictBizEnum code, String dictKey) {
return getValue(code.getName(), dictKey);
}
/**
* 获取字典值
*
* @param code 字典编号
* @param dictKey String型字典键
* @return String
*/
public static String getValue(String code, String dictKey) {
String keyPrefix = DICT_VALUE.concat(StringPool.DASH).concat(AuthUtil.getTenantId()).concat(StringPool.COLON);
return CacheUtil.get(DICT_CACHE, keyPrefix + code + StringPool.COLON, dictKey, () -> dictService.getValue(code, dictKey));
}
/**
* 获取字典集合
*
* @param code 字典编号
* @return List<DictBiz>
*/
public static List<DictBiz> getList(String code) {
String keyPrefix = DICT_LIST.concat(StringPool.DASH).concat(AuthUtil.getTenantId()).concat(StringPool.COLON);
return CacheUtil.get(DICT_CACHE, keyPrefix, code, () -> dictService.getList(code));
}
}

143
src/main/java/org/springblade/common/cache/DictCache.java vendored

@ -0,0 +1,143 @@
/*
* Copyright (c) 2018-2028, Chill Zhuang All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* Neither the name of the dreamlu.net developer nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
* Author: Chill 庄骞 (smallchill@163.com)
*/
package org.springblade.common.cache;
import org.springblade.common.enums.DictEnum;
import org.springblade.core.cache.utils.CacheUtil;
import org.springblade.core.tool.utils.SpringUtil;
import org.springblade.core.tool.utils.StringPool;
import org.springblade.modules.system.entity.Dict;
import org.springblade.modules.system.service.IDictService;
import java.util.List;
import java.util.Optional;
import static org.springblade.core.cache.constant.CacheConstant.DICT_CACHE;
/**
* 字典缓存工具类
*
* @author Chill
*/
public class DictCache {
private static final String DICT_ID = "dict:id:";
private static final String DICT_KEY = "dict:key:";
private static final String DICT_VALUE = "dict:value:";
private static final String DICT_LIST = "dict:list:";
private static final Boolean TENANT_MODE = Boolean.FALSE;
private static final IDictService dictService;
static {
dictService = SpringUtil.getBean(IDictService.class);
}
/**
* 获取字典实体
*
* @param id 主键
* @return Dict
*/
public static Dict getById(Long id) {
return CacheUtil.get(DICT_CACHE, DICT_ID, id, () -> dictService.getById(id), TENANT_MODE);
}
/**
* 获取字典值
*
* @param code 字典编号枚举
* @param dictValue 字典值
* @return String
*/
public static String getKey(DictEnum code, String dictValue) {
return getKey(code.getName(), dictValue);
}
/**
* 获取字典键
*
* @param code 字典编号
* @param dictValue 字典值
* @return String
*/
public static String getKey(String code, String dictValue) {
return CacheUtil.get(DICT_CACHE, DICT_KEY + code + StringPool.COLON, dictValue, () -> {
List<Dict> list = getList(code);
Optional<String> key = list.stream().filter(
dict -> dict.getDictValue().equalsIgnoreCase(dictValue)
).map(Dict::getDictKey).findFirst();
return key.orElse(StringPool.EMPTY);
}, TENANT_MODE);
}
/**
* 获取字典值
*
* @param code 字典编号枚举
* @param dictKey Integer型字典键
* @return String
*/
public static String getValue(DictEnum code, Integer dictKey) {
return getValue(code.getName(), dictKey);
}
/**
* 获取字典值
*
* @param code 字典编号
* @param dictKey Integer型字典键
* @return String
*/
public static String getValue(String code, Integer dictKey) {
return CacheUtil.get(DICT_CACHE, DICT_VALUE + code + StringPool.COLON, String.valueOf(dictKey), () -> dictService.getValue(code, String.valueOf(dictKey)), TENANT_MODE);
}
/**
* 获取字典值
*
* @param code 字典编号枚举
* @param dictKey String型字典键
* @return String
*/
public static String getValue(DictEnum code, String dictKey) {
return getValue(code.getName(), dictKey);
}
/**
* 获取字典值
*
* @param code 字典编号
* @param dictKey String型字典键
* @return String
*/
public static String getValue(String code, String dictKey) {
return CacheUtil.get(DICT_CACHE, DICT_VALUE + code + StringPool.COLON, dictKey, () -> dictService.getValue(code, dictKey), TENANT_MODE);
}
/**
* 获取字典集合
*
* @param code 字典编号
* @return List<Dict>
*/
public static List<Dict> getList(String code) {
return CacheUtil.get(DICT_CACHE, DICT_LIST, code, () -> dictService.getList(code), TENANT_MODE);
}
}

62
src/main/java/org/springblade/common/cache/ParamCache.java vendored

@ -0,0 +1,62 @@
/*
* Copyright (c) 2018-2028, Chill Zhuang All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* Neither the name of the dreamlu.net developer nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
* Author: Chill 庄骞 (smallchill@163.com)
*/
package org.springblade.common.cache;
import org.springblade.core.cache.utils.CacheUtil;
import org.springblade.core.tool.utils.SpringUtil;
import org.springblade.modules.system.entity.Param;
import org.springblade.modules.system.service.IParamService;
import static org.springblade.core.cache.constant.CacheConstant.PARAM_CACHE;
/**
* 参数缓存工具类
*
* @author Chill
*/
public class ParamCache {
private static final String PARAM_ID = "param:id:";
private static final String PARAM_VALUE = "param:value:";
private static final IParamService paramService;
static {
paramService = SpringUtil.getBean(IParamService.class);
}
/**
* 获取参数实体
*
* @param id 主键
* @return Param
*/
public static Param getById(Long id) {
return CacheUtil.get(PARAM_CACHE, PARAM_ID, id, () -> paramService.getById(id));
}
/**
* 获取参数配置
*
* @param paramKey 参数值
* @return String
*/
public static String getValue(String paramKey) {
return CacheUtil.get(PARAM_CACHE, PARAM_VALUE, paramKey, () -> paramService.getValue(paramKey));
}
}

56
src/main/java/org/springblade/common/cache/RegionCache.java vendored

@ -0,0 +1,56 @@
/*
* Copyright (c) 2018-2028, Chill Zhuang All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* Neither the name of the dreamlu.net developer nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
* Author: Chill 庄骞 (smallchill@163.com)
*/
package org.springblade.common.cache;
import org.springblade.core.cache.utils.CacheUtil;
import org.springblade.core.tool.utils.SpringUtil;
import org.springblade.modules.system.entity.Region;
import org.springblade.modules.system.service.IRegionService;
import static org.springblade.core.cache.constant.CacheConstant.SYS_CACHE;
/**
* 行政区划缓存工具类
*
* @author Chill
*/
public class RegionCache {
public static final int PROVINCE_LEVEL = 1;
public static final int CITY_LEVEL = 2;
public static final int DISTRICT_LEVEL = 3;
public static final int TOWN_LEVEL = 4;
public static final int VILLAGE_LEVEL = 5;
private static final String REGION_CODE = "region:code:";
private static final IRegionService regionService;
static {
regionService = SpringUtil.getBean(IRegionService.class);
}
/**
* 获取行政区划实体
*
* @param code 区划编号
* @return Param
*/
public static Region getByCode(String code) {
return CacheUtil.get(SYS_CACHE, REGION_CODE, code, () -> regionService.getById(code));
}
}

317
src/main/java/org/springblade/common/cache/SysCache.java vendored

@ -0,0 +1,317 @@
/*
* Copyright (c) 2018-2028, Chill Zhuang All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* Neither the name of the dreamlu.net developer nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
* Author: Chill 庄骞 (smallchill@163.com)
*/
package org.springblade.common.cache;
import org.springblade.core.cache.utils.CacheUtil;
import org.springblade.core.tool.utils.SpringUtil;
import org.springblade.core.tool.utils.StringPool;
import org.springblade.modules.system.entity.*;
import org.springblade.modules.system.service.*;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
import static org.springblade.core.cache.constant.CacheConstant.SYS_CACHE;
/**
* 系统缓存
*
* @author Chill
*/
public class SysCache {
private static final String MENU_ID = "menu:id:";
private static final String DEPT_ID = "dept:id:";
private static final String DEPT_NAME = "dept:name:";
private static final String DEPT_NAME_FUZZY = "dept:nameFuzzy:";
private static final String DEPT_NAME_ID = "deptName:id:";
private static final String DEPT_NAMES_ID = "deptNames:id:";
private static final String DEPT_CHILD_ID = "deptChild:id:";
private static final String DEPT_CHILDIDS_ID = "deptChildIds:id:";
private static final String POST_ID = "post:id:";
private static final String POST_NAME = "post:name:";
private static final String POST_NAME_FUZZY = "post:nameFuzzy:";
private static final String POST_NAME_ID = "postName:id:";
private static final String POST_NAMES_ID = "postNames:id:";
private static final String ROLE_ID = "role:id:";
private static final String ROLE_NAME = "role:name:";
private static final String ROLE_NAME_ID = "roleName:id:";
private static final String ROLE_NAMES_ID = "roleNames:id:";
private static final String ROLE_ALIAS_ID = "roleAlias:id:";
private static final String ROLE_ALIASES_ID = "roleAliases:id:";
public static final String TENANT_ID = "tenant:id:";
public static final String TENANT_TENANT_ID = "tenant:tenantId:";
public static final String TENANT_PACKAGE_ID = "tenant:packageId:";
private static final IMenuService menuService;
private static final IDeptService deptService;
private static final IPostService postService;
private static final IRoleService roleService;
private static final ITenantService tenantService;
private static final ITenantPackageService tenantPackageService;
static {
menuService = SpringUtil.getBean(IMenuService.class);
deptService = SpringUtil.getBean(IDeptService.class);
postService = SpringUtil.getBean(IPostService.class);
roleService = SpringUtil.getBean(IRoleService.class);
tenantService = SpringUtil.getBean(ITenantService.class);
tenantPackageService = SpringUtil.getBean(ITenantPackageService.class);
}
/**
* 获取菜单
*
* @param id 主键
* @return 菜单
*/
public static Menu getMenu(Long id) {
return CacheUtil.get(SYS_CACHE, MENU_ID, id, () -> menuService.getById(id));
}
/**
* 获取部门
*
* @param id 主键
* @return 部门
*/
public static Dept getDept(Long id) {
return CacheUtil.get(SYS_CACHE, DEPT_ID, id, () -> deptService.getById(id));
}
/**
* 获取部门id
*
* @param tenantId 租户id
* @param deptNames 部门名
* @return 部门id
*/
public static String getDeptIds(String tenantId, String deptNames) {
return CacheUtil.get(SYS_CACHE, DEPT_NAME, tenantId + StringPool.DASH + deptNames, () -> deptService.getDeptIds(tenantId, deptNames));
}
/**
* 获取部门id
*
* @param tenantId 租户id
* @param deptNames 部门名模糊查询
* @return 部门id
*/
public static String getDeptIdsByFuzzy(String tenantId, String deptNames) {
return CacheUtil.get(SYS_CACHE, DEPT_NAME_FUZZY, tenantId + StringPool.DASH + deptNames, () -> deptService.getDeptIdsByFuzzy(tenantId, deptNames));
}
/**
* 获取部门名
*
* @param id 主键
* @return 部门名
*/
public static String getDeptName(Long id) {
return CacheUtil.get(SYS_CACHE, DEPT_NAME_ID, id, () -> deptService.getById(id).getDeptName());
}
/**
* 获取部门名集合
*
* @param deptIds 主键集合
* @return 部门名
*/
public static List<String> getDeptNames(String deptIds) {
return CacheUtil.get(SYS_CACHE, DEPT_NAMES_ID, deptIds, () -> deptService.getDeptNames(deptIds));
}
/**
* 获取子部门集合
*
* @param deptId 主键
* @return 子部门
*/
public static List<Dept> getDeptChild(Long deptId) {
return CacheUtil.get(SYS_CACHE, DEPT_CHILD_ID, deptId, () -> deptService.getDeptChild(deptId));
}
/**
* 获取子部门ID集合
*
* @param deptId 主键
* @return 子部门ID
*/
public static List<Long> getDeptChildIds(Long deptId) {
if (deptId == null) {
return null;
}
List<Long> deptIdList = CacheUtil.get(SYS_CACHE, DEPT_CHILDIDS_ID, deptId, List.class);
if (deptIdList == null) {
deptIdList = new ArrayList<>();
List<Dept> deptChild = getDeptChild(deptId);
if (deptChild != null) {
List<Long> collect = deptChild.stream().map(Dept::getId).collect(Collectors.toList());
deptIdList.addAll(collect);
}
deptIdList.add(deptId);
CacheUtil.put(SYS_CACHE, DEPT_CHILDIDS_ID, deptId, deptIdList);
}
return deptIdList;
}
/**
* 获取岗位
*
* @param id 主键
* @return
*/
public static Post getPost(Long id) {
return CacheUtil.get(SYS_CACHE, POST_ID, id, () -> postService.getById(id));
}
/**
* 获取岗位id
*
* @param tenantId 租户id
* @param postNames 岗位名
* @return
*/
public static String getPostIds(String tenantId, String postNames) {
return CacheUtil.get(SYS_CACHE, POST_NAME, tenantId + StringPool.DASH + postNames, () -> postService.getPostIds(tenantId, postNames));
}
/**
* 获取岗位id
*
* @param tenantId 租户id
* @param postNames 岗位名模糊查询
* @return
*/
public static String getPostIdsByFuzzy(String tenantId, String postNames) {
return CacheUtil.get(SYS_CACHE, POST_NAME_FUZZY, tenantId + StringPool.DASH + postNames, () -> postService.getPostIdsByFuzzy(tenantId, postNames));
}
/**
* 获取岗位名
*
* @param id 主键
* @return 岗位名
*/
public static String getPostName(Long id) {
return CacheUtil.get(SYS_CACHE, POST_NAME_ID, id, () -> postService.getById(id).getPostName());
}
/**
* 获取岗位名集合
*
* @param postIds 主键集合
* @return 岗位名
*/
public static List<String> getPostNames(String postIds) {
return CacheUtil.get(SYS_CACHE, POST_NAMES_ID, postIds, () -> postService.getPostNames(postIds));
}
/**
* 获取角色
*
* @param id 主键
* @return Role
*/
public static Role getRole(Long id) {
return CacheUtil.get(SYS_CACHE, ROLE_ID, id, () -> roleService.getById(id));
}
/**
* 获取角色id
*
* @param tenantId 租户id
* @param roleNames 角色名
* @return
*/
public static String getRoleIds(String tenantId, String roleNames) {
return CacheUtil.get(SYS_CACHE, ROLE_NAME, tenantId + StringPool.DASH + roleNames, () -> roleService.getRoleIds(tenantId, roleNames));
}
/**
* 获取角色名
*
* @param id 主键
* @return 角色名
*/
public static String getRoleName(Long id) {
return CacheUtil.get(SYS_CACHE, ROLE_NAME_ID, id, () -> roleService.getById(id).getRoleName());
}
/**
* 获取角色名集合
*
* @param roleIds 主键集合
* @return 角色名
*/
public static List<String> getRoleNames(String roleIds) {
return CacheUtil.get(SYS_CACHE, ROLE_NAMES_ID, roleIds, () -> roleService.getRoleNames(roleIds));
}
/**
* 获取角色别名
*
* @param id 主键
* @return 角色别名
*/
public static String getRoleAlias(Long id) {
return CacheUtil.get(SYS_CACHE, ROLE_ALIAS_ID, id, () -> roleService.getById(id).getRoleAlias());
}
/**
* 获取角色别名集合
*
* @param roleIds 主键集合
* @return 角色别名
*/
public static List<String> getRoleAliases(String roleIds) {
return CacheUtil.get(SYS_CACHE, ROLE_ALIASES_ID, roleIds, () -> roleService.getRoleAliases(roleIds));
}
/**
* 获取租户
*
* @param id 主键
* @return Tenant
*/
public static Tenant getTenant(Long id) {
return CacheUtil.get(SYS_CACHE, TENANT_ID, id, () -> tenantService.getById(id), Boolean.FALSE);
}
/**
* 获取租户
*
* @param tenantId 租户id
* @return Tenant
*/
public static Tenant getTenant(String tenantId) {
return CacheUtil.get(SYS_CACHE, TENANT_TENANT_ID, tenantId, () -> tenantService.getByTenantId(tenantId), Boolean.FALSE);
}
/**
* 获取租户产品包
*
* @param tenantId 租户id
* @return Tenant
*/
public static TenantPackage getTenantPackage(String tenantId) {
Tenant tenant = getTenant(tenantId);
return CacheUtil.get(SYS_CACHE, TENANT_PACKAGE_ID, tenantId, () -> tenantPackageService.getById(tenant.getPackageId()), Boolean.FALSE);
}
}

77
src/main/java/org/springblade/common/cache/UserCache.java vendored

@ -0,0 +1,77 @@
/*
* Copyright (c) 2018-2028, Chill Zhuang All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* Neither the name of the dreamlu.net developer nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
* Author: Chill 庄骞 (smallchill@163.com)
*/
package org.springblade.common.cache;
import org.springblade.core.cache.utils.CacheUtil;
import org.springblade.core.tool.utils.Func;
import org.springblade.core.tool.utils.SpringUtil;
import org.springblade.core.tool.utils.StringPool;
import org.springblade.core.tool.utils.StringUtil;
import org.springblade.modules.system.entity.User;
import org.springblade.modules.system.service.IUserService;
import static org.springblade.core.cache.constant.CacheConstant.USER_CACHE;
import static org.springblade.core.launch.constant.FlowConstant.TASK_USR_PREFIX;
/**
* 系统缓存
*
* @author Chill
*/
public class UserCache {
private static final String USER_CACHE_ID = "user:id:";
private static final String USER_CACHE_ACCOUNT = "user:account:";
private static final IUserService userService;
static {
userService = SpringUtil.getBean(IUserService.class);
}
/**
* 根据任务用户id获取用户信息
*
* @param taskUserId 任务用户id
* @return
*/
public static User getUserByTaskUser(String taskUserId) {
Long userId = Func.toLong(StringUtil.removePrefix(taskUserId, TASK_USR_PREFIX));
return getUser(userId);
}
/**
* 获取用户
*
* @param userId 用户id
* @return
*/
public static User getUser(Long userId) {
return CacheUtil.get(USER_CACHE, USER_CACHE_ID, userId, () -> userService.getById(userId));
}
/**
* 获取用户
*
* @param tenantId 租户id
* @param account 账号名
* @return
*/
public static User getUser(String tenantId, String account) {
return CacheUtil.get(USER_CACHE, USER_CACHE_ACCOUNT, tenantId + StringPool.DASH + account, () -> userService.userByAccount(tenantId, account));
}
}

70
src/main/java/org/springblade/common/config/BladeConfiguration.java

@ -0,0 +1,70 @@
/*
* Copyright (c) 2018-2028, Chill Zhuang All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* Neither the name of the dreamlu.net developer nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
* Author: Chill 庄骞 (smallchill@163.com)
*/
package org.springblade.common.config;
import org.springblade.core.secure.registry.SecureRegistry;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
/**
* Blade配置
*
* @author Chill
*/
@Configuration(proxyBeanMethods = false)
public class BladeConfiguration implements WebMvcConfigurer {
/**
* 安全框架配置
*/
@Bean
public SecureRegistry secureRegistry() {
SecureRegistry secureRegistry = new SecureRegistry();
secureRegistry.setEnabled(true);
secureRegistry.excludePathPatterns("/blade-auth/**");
secureRegistry.excludePathPatterns("/blade-system/menu/routes");
secureRegistry.excludePathPatterns("/blade-system/menu/auth-routes");
secureRegistry.excludePathPatterns("/blade-system/menu/top-menu");
secureRegistry.excludePathPatterns("/blade-system/tenant/info");
secureRegistry.excludePathPatterns("/blade-flow/process/resource-view");
secureRegistry.excludePathPatterns("/blade-flow/process/diagram-view");
secureRegistry.excludePathPatterns("/blade-flow/manager/check-upload");
secureRegistry.excludePathPatterns("/doc.html");
secureRegistry.excludePathPatterns("/js/**");
secureRegistry.excludePathPatterns("/webjars/**");
secureRegistry.excludePathPatterns("/swagger-resources/**");
secureRegistry.excludePathPatterns("/druid/**");
return secureRegistry;
}
/**
* 跨域配置
*/
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/cors/**")
.allowedOrigins("*")
.allowedHeaders("*")
.allowedMethods("*")
.maxAge(3600)
.allowCredentials(true);
}
}

58
src/main/java/org/springblade/common/config/BladeLogConfiguration.java

@ -0,0 +1,58 @@
/*
* Copyright (c) 2018-2028, Chill Zhuang All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* Neither the name of the dreamlu.net developer nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
* Author: Chill 庄骞 (smallchill@163.com)
*/
package org.springblade.common.config;
import lombok.AllArgsConstructor;
import org.springblade.common.event.ApiLogListener;
import org.springblade.common.event.ErrorLogListener;
import org.springblade.common.event.UsualLogListener;
import org.springblade.core.launch.props.BladeProperties;
import org.springblade.core.launch.server.ServerInfo;
import org.springblade.modules.system.service.ILogService;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* 日志工具自动配置
*
* @author Chill
*/
@Configuration(proxyBeanMethods = false)
@AllArgsConstructor
public class BladeLogConfiguration {
private final ILogService logService;
private final ServerInfo serverInfo;
private final BladeProperties bladeProperties;
@Bean(name = "apiLogListener")
public ApiLogListener apiLogListener() {
return new ApiLogListener(logService, serverInfo, bladeProperties);
}
@Bean(name = "errorEventListener")
public ErrorLogListener errorEventListener() {
return new ErrorLogListener(logService, serverInfo, bladeProperties);
}
@Bean(name = "usualEventListener")
public UsualLogListener usualEventListener() {
return new UsualLogListener(logService, serverInfo, bladeProperties);
}
}

26
src/main/java/org/springblade/common/config/BladePreviewConfiguration.java

@ -0,0 +1,26 @@
package org.springblade.common.config;
import org.springblade.common.filter.PreviewFilter;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* 演示配置类
*
* @author Chill
*/
@Configuration(proxyBeanMethods = false)
@ConditionalOnProperty(value = "blade.preview.enabled", havingValue = "true")
public class BladePreviewConfiguration {
/**
* 演示模式配置
*/
@Bean
public PreviewFilter previewFilter() {
return new PreviewFilter();
}
}

43
src/main/java/org/springblade/common/config/BladeReportConfiguration.java

@ -0,0 +1,43 @@
/*
* Copyright (c) 2018-2028, Chill Zhuang All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* Neither the name of the dreamlu.net developer nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
* Author: Chill 庄骞 (smallchill@163.com)
*/
package org.springblade.common.config;
import org.springblade.core.report.datasource.ReportDataSource;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import javax.sql.DataSource;
/**
* 报表配置类
*
* @author Chill
*/
@Configuration(proxyBeanMethods = false)
@ConditionalOnProperty(value = "report.enabled", havingValue = "true", matchIfMissing = true)
public class BladeReportConfiguration {
/**
* 自定义报表可选数据源
*/
@Bean
public ReportDataSource reportDataSource(DataSource dataSource) {
return new ReportDataSource(dataSource);
}
}

120
src/main/java/org/springblade/common/config/SwaggerConfiguration.java

@ -0,0 +1,120 @@
/*
* Copyright (c) 2018-2028, Chill Zhuang All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* Neither the name of the dreamlu.net developer nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
* Author: Chill 庄骞 (smallchill@163.com)
*/
package org.springblade.common.config;
import com.github.xiaoymin.knife4j.spring.extension.OpenApiExtensionResolver;
import com.google.common.collect.Lists;
import lombok.AllArgsConstructor;
import org.springblade.core.launch.constant.AppConstant;
import org.springblade.core.secure.BladeUser;
import org.springblade.core.swagger.EnableSwagger;
import org.springblade.core.swagger.SwaggerProperties;
import org.springblade.core.swagger.SwaggerUtil;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.service.*;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spi.service.contexts.SecurityContext;
import springfox.documentation.spring.web.plugins.Docket;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
/**
* Swagger配置类
*
* @author Chill
*/
@Configuration(proxyBeanMethods = false)
@EnableSwagger
@AllArgsConstructor
public class SwaggerConfiguration {
/**
* 引入swagger配置类
*/
private final SwaggerProperties swaggerProperties;
/**
* 引入Knife4j扩展类
*/
private final OpenApiExtensionResolver openApiExtensionResolver;
@Bean
public Docket authDocket() {
return docket("授权模块", Collections.singletonList(AppConstant.BASE_PACKAGES + ".modules.auth"));
}
@Bean
public Docket sysDocket() {
return docket("系统模块",
Arrays.asList(AppConstant.BASE_PACKAGES + ".modules.system", AppConstant.BASE_PACKAGES + ".modules.resource"));
}
@Bean
public Docket flowDocket() {
return docket("工作流模块", Collections.singletonList(AppConstant.BASE_PACKAGES + ".flow"));
}
private Docket docket(String groupName, List<String> basePackages) {
return new Docket(DocumentationType.SWAGGER_2)
.groupName(groupName)
.apiInfo(apiInfo())
.ignoredParameterTypes(BladeUser.class)
.select()
.apis(SwaggerUtil.basePackages(basePackages))
.paths(PathSelectors.any())
.build().securityContexts(securityContexts()).securitySchemes(securitySchemas())
.extensions(openApiExtensionResolver.buildExtensions(groupName));
}
private List<SecurityContext> securityContexts() {
return Collections.singletonList(SecurityContext.builder()
.securityReferences(defaultAuth())
.forPaths(PathSelectors.regex("^.*$"))
.build());
}
List<SecurityReference> defaultAuth() {
AuthorizationScope authorizationScope = new AuthorizationScope("global", "accessEverywhere");
AuthorizationScope[] authorizationScopes = new AuthorizationScope[1];
authorizationScopes[0] = authorizationScope;
return Lists.newArrayList(new SecurityReference(SwaggerUtil.clientInfo().getName(), authorizationScopes),
new SecurityReference(SwaggerUtil.bladeAuth().getName(), authorizationScopes),
new SecurityReference(SwaggerUtil.bladeTenant().getName(), authorizationScopes));
}
private List<SecurityScheme> securitySchemas() {
return Lists.newArrayList(SwaggerUtil.clientInfo(), SwaggerUtil.bladeAuth(), SwaggerUtil.bladeTenant());
}
private ApiInfo apiInfo() {
return new ApiInfoBuilder()
.title(swaggerProperties.getTitle())
.description(swaggerProperties.getDescription())
.license(swaggerProperties.getLicense())
.licenseUrl(swaggerProperties.getLicenseUrl())
.termsOfServiceUrl(swaggerProperties.getTermsOfServiceUrl())
.contact(new Contact(swaggerProperties.getContact().getName(), swaggerProperties.getContact().getUrl(), swaggerProperties.getContact().getEmail()))
.version(swaggerProperties.getVersion())
.build();
}
}

84
src/main/java/org/springblade/common/constant/CommonConstant.java

@ -0,0 +1,84 @@
/*
* Copyright (c) 2018-2028, Chill Zhuang All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* Neither the name of the dreamlu.net developer nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
* Author: Chill 庄骞 (smallchill@163.com)
*/
package org.springblade.common.constant;
import org.springblade.core.launch.constant.AppConstant;
/**
* 通用常量
*
* @author Chill
*/
public interface CommonConstant {
/**
* app name
*/
String APPLICATION_NAME = AppConstant.APPLICATION_NAME_PREFIX + "api";
/**
* sword 系统名
*/
String SWORD_NAME = "sword";
/**
* saber 系统名
*/
String SABER_NAME = "saber";
/**
* 顶级父节点id
*/
Long TOP_PARENT_ID = 0L;
/**
* 顶级父节点名称
*/
String TOP_PARENT_NAME = "顶级";
/**
* 未封存状态值
*/
Integer NOT_SEALED_ID = 0;
/**
* 默认密码
*/
String DEFAULT_PASSWORD = "123456";
/**
* 默认密码参数值
*/
String DEFAULT_PARAM_PASSWORD = "account.initPassword";
/**
* 默认排序字段
*/
String SORT_FIELD = "sort";
/**
* 数据权限类型
*/
Integer DATA_SCOPE_CATEGORY = 1;
/**
* 接口权限类型
*/
Integer API_SCOPE_CATEGORY = 2;
}

38
src/main/java/org/springblade/common/constant/DictConstant.java

@ -0,0 +1,38 @@
/*
* Copyright (c) 2018-2028, Chill Zhuang All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* Neither the name of the dreamlu.net developer nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
* Author: Chill 庄骞 (smallchill@163.com)
*/
package org.springblade.common.constant;
/**
* 字典常量.
*
* @author zhuangqian
*/
public interface DictConstant {
String SEX_CODE = "sex";
String NOTICE_CODE = "notice";
String MENU_CATEGORY_CODE = "menu_category";
String BUTTON_FUNC_CODE = "button_func";
String YES_NO_CODE = "yes_no";
String FLOW_CATEGORY_CODE = "flow_category";
}

93
src/main/java/org/springblade/common/constant/LauncherConstant.java

@ -0,0 +1,93 @@
/*
* Copyright (c) 2018-2028, Chill Zhuang All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* Neither the name of the dreamlu.net developer nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
* Author: Chill 庄骞 (smallchill@163.com)
*/
package org.springblade.common.constant;
import org.springblade.core.launch.constant.AppConstant;
/**
* 启动常量
*
* @author Chill
*/
public interface LauncherConstant {
/**
* sentinel dev 地址
*/
String SENTINEL_DEV_ADDR = "127.0.0.1:8858";
/**
* sentinel prod 地址
*/
String SENTINEL_PROD_ADDR = "10.211.55.5:8858";
/**
* sentinel test 地址
*/
String SENTINEL_TEST_ADDR = "172.30.0.58:8858";
/**
* elk dev 地址
*/
String ELK_DEV_ADDR = "127.0.0.1:9000";
/**
* elk prod 地址
*/
String ELK_PROD_ADDR = "172.30.0.58:9000";
/**
* elk test 地址
*/
String ELK_TEST_ADDR = "172.30.0.58:9000";
/**
* 动态获取sentinel地址
*
* @param profile 环境变量
* @return addr
*/
static String sentinelAddr(String profile) {
switch (profile) {
case (AppConstant.PROD_CODE):
return SENTINEL_PROD_ADDR;
case (AppConstant.TEST_CODE):
return SENTINEL_TEST_ADDR;
default:
return SENTINEL_DEV_ADDR;
}
}
/**
* 动态获取elk地址
*
* @param profile 环境变量
* @return addr
*/
static String elkAddr(String profile) {
switch (profile) {
case (AppConstant.PROD_CODE):
return ELK_PROD_ADDR;
case (AppConstant.TEST_CODE):
return ELK_TEST_ADDR;
default:
return ELK_DEV_ADDR;
}
}
}

66
src/main/java/org/springblade/common/constant/TenantConstant.java

@ -0,0 +1,66 @@
/*
* Copyright (c) 2018-2028, Chill Zhuang All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* Neither the name of the dreamlu.net developer nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
* Author: Chill 庄骞 (smallchill@163.com)
*/
package org.springblade.common.constant;
import java.util.Arrays;
import java.util.List;
/**
* 租户常量
*
* @author Chill
*/
public interface TenantConstant {
/**
* 租户默认密码KEY
*/
String PASSWORD_KEY = "tenant.default.password";
/**
* 租户默认账号额度KEY
*/
String ACCOUNT_NUMBER_KEY = "tenant.default.accountNumber";
/**
* 租户默认菜单集合KEY
*/
String ACCOUNT_MENU_CODE_KEY = "tenant.default.menuCode";
/**
* 租户默认密码
*/
String DEFAULT_PASSWORD = "123456";
/**
* 租户授权码默认16位密钥
*/
String DES_KEY = "0000000000000000";
/**
* 租户默认账号额度
*/
Integer DEFAULT_ACCOUNT_NUMBER = -1;
/**
* 租户默认菜单集合
*/
List<String> MENU_CODES = Arrays.asList(
"desk", "flow", "work", "monitor", "resource", "role", "user", "dept", "dictbiz", "topmenu"
);
}

39
src/main/java/org/springblade/common/enums/DictBizEnum.java

@ -0,0 +1,39 @@
/*
* Copyright (c) 2018-2028, Chill Zhuang All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* Neither the name of the dreamlu.net developer nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
* Author: Chill 庄骞 (smallchill@163.com)
*/
package org.springblade.common.enums;
import lombok.AllArgsConstructor;
import lombok.Getter;
/**
* 业务字典枚举类
*
* @author Chill
*/
@Getter
@AllArgsConstructor
public enum DictBizEnum {
/**
* 测试
*/
TEST("test"),
;
final String name;
}

95
src/main/java/org/springblade/common/enums/DictEnum.java

@ -0,0 +1,95 @@
/*
* Copyright (c) 2018-2028, Chill Zhuang All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* Neither the name of the dreamlu.net developer nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
* Author: Chill 庄骞 (smallchill@163.com)
*/
package org.springblade.common.enums;
import lombok.AllArgsConstructor;
import lombok.Getter;
/**
* 系统字典枚举类
*
* @author Chill
*/
@Getter
@AllArgsConstructor
public enum DictEnum {
/**
* 性别
*/
SEX("sex"),
/**
* 通知类型
*/
NOTICE("notice"),
/**
* 菜单类型
*/
MENU_CATEGORY("menu_category"),
/**
* 按钮功能
*/
BUTTON_FUNC("button_func"),
/**
* 是否
*/
YES_NO("yes_no"),
/**
* 流程类型
*/
FLOW("flow"),
/**
* 机构类型
*/
ORG_CATEGORY("org_category"),
/**
* 数据权限
*/
DATA_SCOPE_TYPE("data_scope_type"),
/**
* 接口权限
*/
API_SCOPE_TYPE("api_scope_type"),
/**
* 权限类型
*/
SCOPE_CATEGORY("scope_category"),
/**
* 对象存储类型
*/
OSS("oss"),
/**
* 短信服务类型
*/
SMS("sms"),
/**
* 岗位类型
*/
POST_CATEGORY("post_category"),
/**
* 行政区划
*/
REGION("region"),
/**
* 用户平台
*/
USER_TYPE("user_type"),
;
final String name;
}

60
src/main/java/org/springblade/common/event/ApiLogListener.java

@ -0,0 +1,60 @@
/*
* Copyright (c) 2018-2028, Chill Zhuang All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* Neither the name of the dreamlu.net developer nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
* Author: Chill 庄骞 (smallchill@163.com)
*/
package org.springblade.common.event;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springblade.core.launch.props.BladeProperties;
import org.springblade.core.launch.server.ServerInfo;
import org.springblade.core.log.constant.EventConstant;
import org.springblade.core.log.event.ApiLogEvent;
import org.springblade.core.log.model.LogApi;
import org.springblade.core.log.utils.LogAbstractUtil;
import org.springblade.modules.system.service.ILogService;
import org.springframework.context.event.EventListener;
import org.springframework.core.annotation.Order;
import org.springframework.scheduling.annotation.Async;
import java.util.Map;
/**
* 异步监听日志事件
*
* @author Chill
*/
@Slf4j
@AllArgsConstructor
public class ApiLogListener {
private final ILogService logService;
private final ServerInfo serverInfo;
private final BladeProperties bladeProperties;
@Async
@Order
@EventListener(ApiLogEvent.class)
public void saveApiLog(ApiLogEvent event) {
Map<String, Object> source = (Map<String, Object>) event.getSource();
LogApi logApi = (LogApi) source.get(EventConstant.EVENT_LOG);
LogAbstractUtil.addOtherInfoToLog(logApi, bladeProperties, serverInfo);
logService.saveApiLog(logApi);
}
}

57
src/main/java/org/springblade/common/event/ErrorLogListener.java

@ -0,0 +1,57 @@
/*
* Copyright (c) 2018-2028, Chill Zhuang All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* Neither the name of the dreamlu.net developer nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
* Author: Chill 庄骞 (smallchill@163.com)
*/
package org.springblade.common.event;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springblade.core.launch.props.BladeProperties;
import org.springblade.core.launch.server.ServerInfo;
import org.springblade.core.log.constant.EventConstant;
import org.springblade.core.log.event.ErrorLogEvent;
import org.springblade.core.log.model.LogError;
import org.springblade.core.log.utils.LogAbstractUtil;
import org.springblade.modules.system.service.ILogService;
import org.springframework.context.event.EventListener;
import org.springframework.core.annotation.Order;
import org.springframework.scheduling.annotation.Async;
import java.util.Map;
/**
* 异步监听错误日志事件
*
* @author Chill
*/
@Slf4j
@AllArgsConstructor
public class ErrorLogListener {
private final ILogService logService;
private final ServerInfo serverInfo;
private final BladeProperties bladeProperties;
@Async
@Order
@EventListener(ErrorLogEvent.class)
public void saveErrorLog(ErrorLogEvent event) {
Map<String, Object> source = (Map<String, Object>) event.getSource();
LogError logError = (LogError) source.get(EventConstant.EVENT_LOG);
LogAbstractUtil.addOtherInfoToLog(logError, bladeProperties, serverInfo);
logService.saveErrorLog(logError);
}
}

58
src/main/java/org/springblade/common/event/UsualLogListener.java

@ -0,0 +1,58 @@
/*
* Copyright (c) 2018-2028, Chill Zhuang All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* Neither the name of the dreamlu.net developer nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
* Author: Chill 庄骞 (smallchill@163.com)
*/
package org.springblade.common.event;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springblade.core.launch.props.BladeProperties;
import org.springblade.core.launch.server.ServerInfo;
import org.springblade.core.log.constant.EventConstant;
import org.springblade.core.log.event.UsualLogEvent;
import org.springblade.core.log.model.LogUsual;
import org.springblade.core.log.utils.LogAbstractUtil;
import org.springblade.modules.system.service.ILogService;
import org.springframework.context.event.EventListener;
import org.springframework.core.annotation.Order;
import org.springframework.scheduling.annotation.Async;
import java.util.Map;
/**
* 异步监听日志事件
*
* @author Chill
*/
@Slf4j
@AllArgsConstructor
public class UsualLogListener {
private final ILogService logService;
private final ServerInfo serverInfo;
private final BladeProperties bladeProperties;
@Async
@Order
@EventListener(UsualLogEvent.class)
public void saveUsualLog(UsualLogEvent event) {
Map<String, Object> source = (Map<String, Object>) event.getSource();
LogUsual logUsual = (LogUsual) source.get(EventConstant.EVENT_LOG);
LogAbstractUtil.addOtherInfoToLog(logUsual, bladeProperties, serverInfo);
logService.saveUsualLog(logUsual);
}
}

66
src/main/java/org/springblade/common/filter/PreviewFilter.java

@ -0,0 +1,66 @@
/*
* Copyright (c) 2018-2028, Chill Zhuang All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* Neither the name of the dreamlu.net developer nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
* Author: Chill 庄骞 (smallchill@163.com)
*/
package org.springblade.common.filter;
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
/**
* 演示过滤器
*
* @author Chill
*/
public class PreviewFilter implements Filter {
private static final List<String> KEYS = new ArrayList<>();
static {
KEYS.add("notice");
KEYS.add("process");
KEYS.add("work");
KEYS.add("token");
}
@Override
public void init(FilterConfig filterConfig) {
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
HttpServletRequest httpServletRequest = (HttpServletRequest) servletRequest;
String path = httpServletRequest.getServletPath();
String method = httpServletRequest.getMethod();
String get = "GET";
if (method.equals(get) || KEYS.stream().anyMatch(path::contains)) {
filterChain.doFilter(servletRequest, servletResponse);
} else {
throw new RuntimeException("演示环境暂时无法操作!");
}
}
@Override
public void destroy() {
}
}

44
src/main/java/org/springblade/common/launch/LauncherServiceImpl.java

@ -0,0 +1,44 @@
/*
* Copyright (c) 2018-2028, Chill Zhuang All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* Neither the name of the dreamlu.net developer nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
* Author: Chill 庄骞 (smallchill@163.com)
*/
package org.springblade.common.launch;
import org.springblade.common.constant.LauncherConstant;
import org.springblade.core.auto.service.AutoService;
import org.springblade.core.launch.service.LauncherService;
import org.springblade.core.launch.utils.PropsUtil;
import org.springframework.boot.builder.SpringApplicationBuilder;
import java.util.Properties;
/**
* 启动参数拓展
*
* @author smallchil
*/
@AutoService(LauncherService.class)
public class LauncherServiceImpl implements LauncherService {
@Override
public void launcher(SpringApplicationBuilder builder, String appName, String profile, boolean isLocalDev) {
Properties props = System.getProperties();
PropsUtil.setProperty(props, "spring.cloud.sentinel.transport.dashboard", LauncherConstant.sentinelAddr(profile));
PropsUtil.setProperty(props, "spring.datasource.dynamic.enabled", "false");
// 开启elk日志
//PropsUtil.setProperty(props, "blade.log.elk.destination", LauncherConstant.elkAddr(profile));
}
}

26
src/main/java/org/springblade/common/utils/CommonUtil.java

@ -0,0 +1,26 @@
/*
* Copyright (c) 2018-2028, Chill Zhuang All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* Neither the name of the dreamlu.net developer nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
* Author: Chill 庄骞 (smallchill@163.com)
*/
package org.springblade.common.utils;
/**
* 通用工具类
*
* @author Chill
*/
public class CommonUtil {
}

35
src/main/java/org/springblade/ftpdemo/cache/CodeCache.java vendored

@ -0,0 +1,35 @@
package org.springblade.ftpdemo.cache;
import org.springblade.ftpdemo.entity.SysDict;
import org.springblade.ftpdemo.service.SysDictService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@Component
public class CodeCache {
public static Map<String, String> codeMap = new HashMap<String, String>();
@Autowired
private SysDictService codeService;
@PostConstruct
public void init(){
System.out.println("系统启动中。。。加载codeMap");
List<SysDict> codeList = codeService.selectAll();
for (SysDict code : codeList) {
codeMap.put(code.getDictCode(), code.getDictValue());
}
}
@PreDestroy
public void destroy(){
System.out.println("系统运行结束");
}
}

181
src/main/java/org/springblade/ftpdemo/controller/DockingController.java

@ -0,0 +1,181 @@
package org.springblade.ftpdemo.controller;
//import io.swagger.annotations.Api;
//import io.swagger.annotations.ApiOperation;
import cn.hutool.core.date.DateUtil;
import org.springblade.ftpdemo.util.Encrypt;
import lombok.AllArgsConstructor;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
@RestController
@AllArgsConstructor
@RequestMapping("/docking")
public class DockingController {
private static final String ipAddress = "123.233.115.26";// ip地址
private static final String userName = "qingniao";// 账号
private static final String password = "SDguzRp";// 密码
// private static final String SOURCEIPADDRESS = "223.99.228.240";// ip地址
// private static final String SOURCEUSERNAME = "root";// 账号
// private static final String SOURCEPASSWORD = "Qingniao@123!";// 密码
//
// private static final String ipAddress = "47.97.5.58";// ip地址
// private static final String userName = "root";// 账号
// private static final String password = "Aa1572427111.";// 密码
// private static final String SRC = "/opt";
@GetMapping("/operation")
public void operation() {
// 连接到指定的服务器
try {
// 1、首先远程连接ssh
SSHRemoteCall.getInstance().sshRemoteCallLogin(ipAddress, userName, password);
// 2、执行相关的命令
// 查看目录信息
// String command = "ls /home/hadoop/package ";
// 查看文件信息
// String command = "cat /home/hadoop/package/test ";
// 查看磁盘空间大小
// String command = "df -lh ";
// 查看cpu的使用情况
// String command = "top -bn -i -c ";
// 查看内存的使用情况
// String command = "free ";
// SSHRemoteCall.getInstance().execCommand(command);
// 3、下载文件
// src 是linux服务器文件地址,dst 本地存放地址,采用默认的传输模式:OVERWRITE
//test为文件名称哈
// donwnLoad(ipAddress, userName, password);
// 2.1、 读取文件
// 查看目录信息
String command = "ls /opt ";
String s = SSHRemoteCall.getInstance().execCommand(command);
if (s.contains("test.txt")) {
// 切换到相应目录下,并将文件进行压缩
String tasuo = "cd /opt;zip -r test.zip test.txt";
SSHRemoteCall.getInstance().execCommand(tasuo);
System.out.println("压缩完成!");
}
// 3.下载文件
String src = "/opt/test.zip";
String dst = "d:/aaa";
SSHRemoteCall.getInstance().fileDownload(src, dst);
System.out.println("下载完成");
// 3.1 下载完成后,将linux上的压缩包删除
// 解压文件
// SSHRemoteCall.getInstance().listFiles(SRC);
// 3.1.1 将xmls文件进行压缩操作
// 3.2、 处理文件
// 3.3、 压缩文件
// 3.4、 加密文件
// 4、上传文件
// String directory = "/opt/ZS-2022101411360002695255-SST-2022102710524094202.xml.tar.gz";// 目标文件名
String directory = "/opt";// 目标文件目录
String uploadFile = "C:\\Users\\Lenven\\Desktop\\ZS-2022101411360002695255-SST-2022102710524094202.xml.tar.gz";// 本地文件名
SSHRemoteCall.getInstance().uploadFile(directory, uploadFile);
// 5、刪除文件
// String deleteDirectoryFile = "/opt/ZS-2022101411360002695255-SST-2022102710524094202.xml.tar.gz";
// SSHRemoteCall.getInstance().deleteFile(deleteDirectoryFile);
// 6、展示目录下的文件信息
String lsDirectory = "/opt/";
// SSHRemoteCall.getInstance().listFiles(lsDirectory);
// 7、关闭连接
SSHRemoteCall.getInstance().closeSession();
} catch (Exception e) {
// 打印错误信息
System.err.println("远程连接失败......");
e.printStackTrace();
}
}
@GetMapping("/test")
public void test1() {
String test = "88.100|山东青鸟工业互联网有限公司|4|山东省|济南市|20220628|信息传输、软件和信息技术服务业、制造业|软件和信息技术服务业、医药制造业、化学原料和化学制品制造业|私营企业|软件和信息技术服务业、医药制造业、化学原料和化学制品制造业\n";
// 将字符串压缩成zip文件并获得字节数据
byte[] bytes = Encrypt.zipToBytes("D:\\data", test);
// upload是压缩加密后的内容
byte[] upload = Encrypt.encryptAlgorithm("1", bytes, "1234567890abcDEF",
"1234567890abcDEF");
// 写文件
String dateStr = Long.toString(System.currentTimeMillis()); // 生成13位时间戳
String fileName = "SDQN-basic_identification-" + dateStr + "-all.bin";
String src = "D:/aaa/" + fileName;
FileOutputStream stream = null;
try {
stream = new FileOutputStream(src);
} catch (FileNotFoundException e) {
throw new RuntimeException(e);
}
try {
stream.write(upload);
} catch (IOException e) {
throw new RuntimeException(e);
}
System.out.println("写入成功:" + fileName);
// 远程连接(要上传文件的服务器)
try {
SSHRemoteCall.getInstance().sshRemoteCallLogin(ipAddress, userName, password);
} catch (Exception e) {
throw new RuntimeException(e);
}
// 要上传的目录
String upSrc = "/001/"+ DateUtil.format(DateUtil.date(),"yyyyMMdd");
System.out.println("目录地址"+upSrc);
// 确保目录一定存在
SSHRemoteCall.getInstance().directory(upSrc);
// 上传文件到指定目录
SSHRemoteCall.getInstance().uploadFile("/data1/qingniao/"+upSrc+"/"+fileName,src);
try {
stream.close();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
private void donwnLoad(String ipAddress, String userName, String password) throws Exception {
// 远程连接ssh(下载文件的服务器)
SSHRemoteCall.getInstance().sshRemoteCallLogin(ipAddress, userName, password);
String src = "/opt/test.txt";
String dst = "d:\\aaa";
SSHRemoteCall.getInstance().fileDownload(src, dst);
}
}

303
src/main/java/org/springblade/ftpdemo/controller/SSHRemoteCall.java

@ -0,0 +1,303 @@
package org.springblade.ftpdemo.controller;
import com.jcraft.jsch.*;
import java.io.*;
public class SSHRemoteCall {
// 私有的对象
private static SSHRemoteCall sshRemoteCall;
/**
* 私有的构造方法
*/
private SSHRemoteCall() {
}
// 懒汉式,线程不安全,适合单线程
// public static SSHRemoteCall getInstance() {
// if (sshRemoteCall == null) {
// sshRemoteCall = new SSHRemoteCall();
// }
// return sshRemoteCall;
// }
// 懒汉式,线程安全,适合多线程
public static synchronized SSHRemoteCall getInstance() {
if (sshRemoteCall == null) {
sshRemoteCall = new SSHRemoteCall();
}
return sshRemoteCall;
}
private static final int DEFAULT_PORT = 30020;// 默认端口号
private int port;// 端口号
private static String ipAddress = "223.99.228.240";// ip地址
private static String userName = "root";// 账号
private static String password = "Qingniao@123!";// 密码
private Session session;// JSCH session
private boolean logined = false;// 是否登陆
/**
* 构造方法,可以直接使用DEFAULT_PORT
*
* @param ipAddress
* @param userName
* @param password
*/
public SSHRemoteCall(String ipAddress, String userName, String password) {
this(ipAddress, DEFAULT_PORT, userName, password);
}
/**
* 构造方法,方便直接传入ipAddress,userName,password进行调用
*
* @param ipAddress
* @param port
* @param userName
* @param password
*/
public SSHRemoteCall(String ipAddress, int port, String userName, String password) {
super();
this.ipAddress = ipAddress;
this.userName = userName;
this.password = password;
this.port = port;
}
/**
* 远程登陆
*
* @throws Exception
*/
public void sshRemoteCallLogin(String ipAddress, String userName, String password) throws Exception {
// 如果登陆就直接返回
if (logined) {
return;
}
// 创建jSch对象
JSch jSch = new JSch();
try {
// 获取到jSch的session, 根据用户名、主机ip、端口号获取一个Session对象
session = jSch.getSession(userName, ipAddress, 22102);
// 设置密码
session.setPassword(password);
// 方式一,通过Session建立连接
// session.setConfig("StrictHostKeyChecking", "no");
// session.connect();
// 方式二,通过Session建立连接
// java.util.Properties;
// Properties config = new Properties();
// config.put("StrictHostKeyChecking", "no");
// session.setConfig(config);// 为Session对象设置properties
// session.setTimeout( );// 设置超时
session.setConfig("StrictHostKeyChecking", "no");
session.connect();//// 通过Session建立连接
// 设置登陆状态
logined = true;
} catch (JSchException e) {
// 设置登陆状态为false
logined = false;
throw new Exception(
"主机登录失败, IP = " + ipAddress + ", USERNAME = " + userName + ", Exception:" + e.getMessage());
}
}
/**
* 关闭连接
*/
public void closeSession() {
// 调用session的关闭连接的方法
if (session != null) {
// 如果session不为空,调用session的关闭连接的方法
session.disconnect();
}
}
/**
* 执行相关的命令
*
* @param command
* @throws IOException
*/
public String execCommand(String command) throws IOException {
InputStream in = null;// 输入流(读)
Channel channel = null;// 定义channel变量
try {
// 如果命令command不等于null
if (command != null) {
// 打开channel
//说明:exec用于执行命令;sftp用于文件处理
channel = session.openChannel("exec");
// 设置command
((ChannelExec) channel).setCommand(command);
// channel进行连接
channel.connect();
// 获取到输入流
in = channel.getInputStream();
// 执行相关的命令
String processDataStream = processDataStream(in);
// 打印相关的命令
return processDataStream;
}
} catch (JSchException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
} finally {
if (in != null) {
in.close();
}
if (channel != null) {
channel.disconnect();
}
}
return null;
}
/**
* 对将要执行的linux的命令进行遍历
*
* @param in
* @return
* @throws Exception
*/
public String processDataStream(InputStream in) throws Exception {
StringBuffer sb = new StringBuffer();
BufferedReader br = new BufferedReader(new InputStreamReader(in));
String result = "";
try {
while ((result = br.readLine()) != null) {
sb.append(result);
// System.out.println(sb.toString());
}
} catch (Exception e) {
throw new Exception("获取数据流失败: " + e);
} finally {
br.close();
}
return sb.toString();
}
/**
* 上传文件 可参考:https://www.cnblogs.com/longyg/archive/ / / / .html
*
* @param directory 上传文件的目录
* @param uploadFile 将要上传的文件
*/
public void uploadFile(String directory, String uploadFile) {
try {
// 打开channelSftp
ChannelSftp channelSftp = (ChannelSftp) session.openChannel("sftp");
// 远程连接
channelSftp.connect();
// 创建一个文件名称问uploadFile的文件
File file = new File(uploadFile);
// 将文件进行上传(sftp协议)
// 将本地文件名为src的文件上传到目标服务器,目标文件名为dst,若dst为目录,则目标文件名将与src文件名相同.
// 采用默认的传输模式:OVERWRITE
channelSftp.put(new FileInputStream(file), directory, ChannelSftp.OVERWRITE);
// 切断远程连接
channelSftp.exit();
System.out.println("上传文件:" + file.getName());
} catch (JSchException e) {
e.printStackTrace();
} catch (SftpException e) {
e.printStackTrace();
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
/**
* 下载文件 采用默认的传输模式OVERWRITE
*
* @param src linux服务器文件地址
* @param dst 本地存放地址
* @throws JSchException
* @throws SftpException
*/
public void fileDownload(String src, String dst) throws JSchException, SftpException {
// src 是linux服务器文件地址,dst 本地存放地址
ChannelSftp channelSftp = (ChannelSftp) session.openChannel("sftp");
// 远程连接
channelSftp.connect();
// 下载文件,多个重载方法
channelSftp.get(src, dst);
// 切断远程连接,quit()等同于exit(),都是调用disconnect()
channelSftp.quit();
// channelSftp.disconnect();
System.out.println("下载文件:" + src);
}
/**
* 删除文件
*
* @throws SftpException
* @throws JSchException
*/
public void deleteFile(String directoryFile) throws SftpException, JSchException {
// 打开openChannel的sftp
ChannelSftp channelSftp = (ChannelSftp) session.openChannel("sftp");
// 远程连接
channelSftp.connect();
// 删除文件
channelSftp.rm(directoryFile);
// 切断远程连接
channelSftp.exit();
System.out.println("删除文件:" + directoryFile);
}
/**
* 如果此目录不存在将新建目录
*/
public void directory(String path) {
// 打开openChannel的sftp
ChannelSftp channelSftp = null;
try {
channelSftp = (ChannelSftp) session.openChannel("sftp");
// 远程连接
channelSftp.connect();
// 切换到主目录
// channelSftp.cd("/");
} catch (JSchException e) {
throw new RuntimeException(e);
}
String[] folders = path.split( "/" );
for ( String folder : folders ) {
if ( folder.length() > 0 ) {
try {
channelSftp.cd( folder );
System.out.println("切换目录"+folder);
}
catch ( SftpException e ) {
try {
channelSftp.mkdir( folder );
System.out.println("生成目录"+folder);
channelSftp.cd( folder );
} catch (SftpException ex) {
throw new RuntimeException(ex);
}
}
}
}
}
}

32
src/main/java/org/springblade/ftpdemo/entity/Identification.java

@ -0,0 +1,32 @@
package org.springblade.ftpdemo.entity;
import lombok.Data;
/**
* @author laifeng
* @since 2022/11/25
*/
@Data
public class Identification {
// 标识码企业前缀
private String companyCode;
//标识解析节点经营主体名称
private String companyName;
//标识解析系统级别
private int level;
//接入省份
private String accessProvince;
//接入地市
private String accessCity;
//注册时间
private String registerTime;
//经营主体行业门类
private String categoryA;
//经营主体行业大类
private String categoryB;
//公司性质
private String companyType;
//节点服务行业
private String serviceProfession;
}

62
src/main/java/org/springblade/ftpdemo/entity/NbmsEnprefix.java

@ -0,0 +1,62 @@
package org.springblade.ftpdemo.entity;
import com.baomidou.mybatisplus.annotation.TableName;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.annotation.JsonProperty;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.io.Serializable;
import java.util.Date;
@Data
@TableName("nbms_ent_prefix")
public class NbmsEnprefix implements Serializable {
private static final long serialVersionUID = 1L;
@ApiModelProperty(value = "主键ID")
private Long id;
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone="GMT+8")
@ApiModelProperty(value = "")
private Date createDate;
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone="GMT+8")
@ApiModelProperty(value = "")
private Date updateDate;
@ApiModelProperty(value = "企业通用id")
private String entGeneralId;
@ApiModelProperty(value = "企业名称")
private String entName;
@ApiModelProperty(value = "企业用户ID")
private Long userId;
@ApiModelProperty(value = "标识前缀")
private String entPrefix;
@ApiModelProperty(value = "状态是否有效 1启用2停用")
private Integer state;
@ApiModelProperty(value = "托管状态 1未托管2托管申请中3托管被驳回4已托管")
private Integer proxyState;
@ApiModelProperty(value = "前缀历史状态是否有效 0停用1启用")
private Integer historyState;
@ApiModelProperty(value = "路由 0:否,1:是")
private Integer isDeleted;
@ApiModelProperty(value = "路由xml创建状态")
private Integer xmlCreated;
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone="GMT+8")
@ApiModelProperty(value = "路由最新上传时间")
private Date xmlUpdateTime;
@ApiModelProperty(value = "路由xml删除状态")
private Integer xmlDeleted;
@ApiModelProperty(value = "路由同步状态1同步,0待同步,2同步中")
private Integer xmlSync;
}

76
src/main/java/org/springblade/ftpdemo/entity/NbmsEnt.java

@ -0,0 +1,76 @@
package org.springblade.ftpdemo.entity;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import java.util.Date;
/**
* @author laifeng
* @since 2022/11/28
*/
@TableName("nbms_ent")
@Data
public class NbmsEnt {
private long id;
private Date createDate;
private Date updateDate;
private String contactEmail;
private String orgAddr;
private String orgAddrCity;
private String orgAddrCounty;
private String orgCrtCode;
private int orgCrtType;
private String orgDesc;
private String entGeneralId;
private String industryCategory;
private String orgName;
private String orgAddrProvince;
private String industrySpecific;
private int orgNature;
private String website;
private String legalCrtNo;
private int legalCrtType;
private String legalName;
private String contactPhone;
private Integer operateType;
private Long userId;
private String userName;
private String contactName;
private Integer sync;
private Integer contactCrtType;
private String contactCrtNo;
private String regAuthority;
private Long regCapital;
private Date establishDate;
private Date periodValidity;
private String legalEmail;
private String legalPhone;
private String legalFax;
private Integer servSysBuildType;
private String servSysBuildName;
private Integer servSysOperType;
private String servSysOperName;
private String dataHostingOrg;
private String servHostingOrg;
private Integer regRealNaImpType;
private String regRealNaImpName;
private String idRegNaImp;
private String extWebName;
private String extDomain;
private String extIpAddr;
private Long orgCrtImgRid;
private Long contactCrtFrontImgRid;
private Long contactCrtBackImgRid;
private Long legalCrtFrontImgRid;
private Long legalCrtBackImgRid;
private Long servSysBuildContractFileRid;
private Long servSysOperContractFileRid;
private Long dataHostingContractFileRid;
private Long servHostingContractFileRid;
private Integer isDeleted;
private Integer xmlCreated;
private Date xmlUpdateTime;
private Integer xmlDeleted;
private Integer xmlSync;
}

221
src/main/java/org/springblade/ftpdemo/entity/NbmsEntApply.java

@ -0,0 +1,221 @@
package org.springblade.ftpdemo.entity;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableName;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.annotation.JsonProperty;
import io.swagger.annotations.ApiModelProperty;
import java.io.Serializable;
import java.util.Date;
@TableName("nbms_ent_apply")
public class NbmsEntApply implements Serializable {
private static final long serialVersionUID = 1L;
@ApiModelProperty(value = "主键ID")
private Long id;
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone="GMT+8")
@ApiModelProperty(value = "")
private Date createDate;
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone="GMT+8")
@ApiModelProperty(value = "")
private Date updateDate;
@ApiModelProperty(value = "1注册2部分修改3全量修改4分配前缀")
private Integer applyType;
@ApiModelProperty(value = "联系人邮箱,正则表达式:")
private String contactEmail;
@ApiModelProperty(value = "单位地址,详细地址")
private String orgAddr;
@ApiModelProperty(value = "单位地址,市,取值遵从全国省市区行政编码,如北京市则展示为直辖市,取值110100")
private String orgAddrCity;
@ApiModelProperty(value = "单位地址,县,取值遵从全国省市区行政编码,如北京的东城区110101")
private String orgAddrCounty;
@ApiModelProperty(value = "单位证件号")
private String orgCrtCode;
@ApiModelProperty(value = "单位证件类型,统一社会信用代码、其他,对应取值1-2")
private Integer orgCrtType;
@ApiModelProperty(value = "单位简介,200字左右企业简介,包括公司名称、成立时间、所在省市、主营业务、主要用户群体、行业地位等信息。")
private String orgDesc;
@ApiModelProperty(value = "企业通用id,注册时为空")
private String entGeneralId;
@ApiModelProperty(value = "服务行业,行业门类,参考《GB/T 4754—2017国民经济行业分类》,如门类“农、林、牧、渔业”对应“A”")
private String industryCategory;
@ApiModelProperty(value = "单位名称")
private String orgName;
@ApiModelProperty(value = "单位地址,省,取值遵从全国省市区行政编码,如北京110000")
private String orgAddrProvince;
@ApiModelProperty(value = "服务行业,行业大类,参考《GB/T 4754—2017国民经济行业分类》,如大类“农业”对应“01”。和门类有级联关系")
private String industrySpecific;
@ApiModelProperty(value = "单位性质,国有控股、民营控股、外商控股、事业单位、民营非盈利,对应取值1-5")
private Integer orgNature;
@ApiModelProperty(value = "官方网站")
private String website;
@ApiModelProperty(value = "")
private String industry;
@ApiModelProperty(value = "0未提交1已提交")
private Integer isSubmit;
@ApiModelProperty(value = "法定代表人证件号")
private String legalCrtNo;
@ApiModelProperty(value = "法定代表人证件类型,中国居民身份证、护照、其他,对应取值1-3")
private Integer legalCrtType;
@ApiModelProperty(value = "法定代表人姓名")
private String legalName;
@ApiModelProperty(value = "联系人手机号,正则表达式")
private String contactPhone;
@ApiModelProperty(value = "企业前缀")
private String entPrefix;
@ApiModelProperty(value = "节点用户给出的审核状态:1待审核2审核通过3被驳回")
private Integer firstAuditStatus;
@ApiModelProperty(value = "节点用户给出的审核结果描述")
private String firstAuditMsg;
@ApiModelProperty(value = "实名核验结果")
private Integer thirdServiceStatus;
@ApiModelProperty(value = "实名核验结果说明")
private String thirdServiceMsg;
@ApiModelProperty(value = "企业用户名称不能为空")
private String userName;
@ApiModelProperty(value = "顶级bms给出的审核状态:1待审核2审核通过3被驳回")
private Integer finalAuditStatus;
@ApiModelProperty(value = "顶级bms企业审核员对企业信息的审核结果描述")
private String finalAuditMsg;
@ApiModelProperty(value = "svTRId: 服务端id自动生成")
@TableField("svTRId")
private String svTRId;
@ApiModelProperty(value = "clTRId: 客户端Id")
@TableField("clTRId")
private String clTRId;
@ApiModelProperty(value = "联系人姓名")
private String contactName;
@ApiModelProperty(value = "企业用户id")
private Long userId;
@ApiModelProperty(value = "申请前缀执行到的第几步")
private Integer applyStep;
@ApiModelProperty(value = "联系人证件类型,中国居民身份证、护照、其他,对应取值1-3")
private Integer contactCrtType;
@ApiModelProperty(value = "联系人证件号")
private String contactCrtNo;
@ApiModelProperty(value = "注册机关")
private String regAuthority;
@ApiModelProperty(value = "注册资本,单位元")
private Long regCapital;
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone="GMT+8")
@ApiModelProperty(value = "成立日期,时间格式:yyyy-MM-dd ")
private Date establishDate;
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone="GMT+8")
@ApiModelProperty(value = "有效期")
private Date periodValidity;
@ApiModelProperty(value = "法人代表人邮箱,正则表达式:")
private String legalEmail;
@ApiModelProperty(value = "法人代表人手机号,正则表达式")
private String legalPhone;
@ApiModelProperty(value = "法人代表人传真")
private String legalFax;
@ApiModelProperty(value = "服务系统建设,建设类型,□自营 □委托 描述对应的编码取值1-2")
private Integer servSysBuildType;
@ApiModelProperty(value = "委托机构名称,委托机构名称,建设类型选“委托”,该字段必填")
private String servSysBuildName;
@ApiModelProperty(value = "服务系统运营,运营类型,□自营 □委托 描述对应的编码取值1-2")
private Integer servSysOperType;
@ApiModelProperty(value = "服务系统运营,委托机构名称,建设类型选“委托”,该字段必填")
private String servSysOperName;
@ApiModelProperty(value = "数据托管单位,例:国家顶级节点(北京)")
private String dataHostingOrg;
@ApiModelProperty(value = "服务托管单位,例:南京ZB节点")
private String servHostingOrg;
@ApiModelProperty(value = "注册实名核验实施,实施类型□自营 □委托 描述对应的编码取值1-2")
private Integer regRealNaImpType;
@ApiModelProperty(value = "注册实名核验实施,委托机构名称,建设类型选“委托”,该字段必填")
private String regRealNaImpName;
@ApiModelProperty(value = "标识注册名称合规实施")
private String idRegNaImp;
@ApiModelProperty(value = "对外提供标识服务的网站名称、域名、IP地址,网站名称")
private String extWebName;
@ApiModelProperty(value = "对外提供标识服务的网站名称、域名、IP地址,域名")
private String extDomain;
@ApiModelProperty(value = "对外提供标识服务的网站名称、域名、IP地址,IP地址,支持IPv4和IPv6,多个IP间以;分割")
private String extIpAddr;
@ApiModelProperty(value = "营业执照")
private Long orgCrtImgRid;
@ApiModelProperty(value = "联系人证件照正面")
private Long contactCrtFrontImgRid;
@ApiModelProperty(value = "联系人证件照反面")
private Long contactCrtBackImgRid;
@ApiModelProperty(value = "法人证件照正面")
private Long legalCrtFrontImgRid;
@ApiModelProperty(value = "法人证件照反面")
private Long legalCrtBackImgRid;
@ApiModelProperty(value = "服务系统建设合同")
private Long servSysBuildContractFileRid;
@ApiModelProperty(value = "服务系统运营合同")
private Long servSysOperContractFileRid;
@ApiModelProperty(value = "数据托管合同")
private Long dataHostingContractFileRid;
@ApiModelProperty(value = "服务托管合同")
private Long servHostingContractFileRid;
}

20
src/main/java/org/springblade/ftpdemo/entity/SysDict.java

@ -0,0 +1,20 @@
package org.springblade.ftpdemo.entity;
import lombok.Data;
import java.util.Date;
/**
* @author laifeng
* @since 2022/11/28
*/
@Data
public class SysDict {
private Long id;
private String dictKey;
private String dictCode;
private String dictValue;
private Long parentId;
private Date createDate;
private Date updateDate;
}

14
src/main/java/org/springblade/ftpdemo/mapper/NbmsEnprefixMapper.java

@ -0,0 +1,14 @@
package org.springblade.ftpdemo.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.springblade.ftpdemo.entity.NbmsEnprefix;
import org.apache.ibatis.annotations.Mapper;
/**
* @author laifeng
* @since 2022/11/28
*/
@Mapper
public interface NbmsEnprefixMapper extends BaseMapper<NbmsEnprefix> {
}

18
src/main/java/org/springblade/ftpdemo/mapper/NbmsEntApplyMapper.java

@ -0,0 +1,18 @@
package org.springblade.ftpdemo.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.springblade.ftpdemo.entity.NbmsEntApply;
import org.apache.ibatis.annotations.Mapper;
/**
* NbmsEnapplyMapper
* @author fuce_自动生成
* @email ${email}
* @date 2022-11-28 17:12:08
*/
@Mapper
public interface NbmsEntApplyMapper extends BaseMapper<NbmsEntApply> {
}

13
src/main/java/org/springblade/ftpdemo/mapper/NbmsEntMapper.java

@ -0,0 +1,13 @@
package org.springblade.ftpdemo.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.springblade.ftpdemo.entity.NbmsEnt;
import org.apache.ibatis.annotations.Mapper;
/**
* @author laifeng
* @since 2022/11/28
*/
@Mapper
public interface NbmsEntMapper extends BaseMapper<NbmsEnt> {
}

13
src/main/java/org/springblade/ftpdemo/mapper/SysDictMapper.java

@ -0,0 +1,13 @@
package org.springblade.ftpdemo.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.springblade.ftpdemo.entity.SysDict;
import org.apache.ibatis.annotations.Mapper;
/**
* @author laifeng
* @since 2022/11/28
*/
@Mapper
public interface SysDictMapper extends BaseMapper<SysDict> {
}

34
src/main/java/org/springblade/ftpdemo/service/IdentificationIp.java

@ -0,0 +1,34 @@
package org.springblade.ftpdemo.service;
import org.springblade.core.tool.utils.DateUtil;
import org.springblade.ftpdemo.service.impl.MethodImpl;
import java.io.File;
/**
* 标识解析节点使用IP段上报
*
* @author laifeng
* @since 2022/11/27
*/
public class IdentificationIp {
public static void main(String[] args) throws Exception {
MethodImpl method = new MethodImpl();
String fileName = "d://aaa//test.txt";
// 要上传的目录
String upSrc = "/002/" + DateUtil.format(DateUtil.now(), "yyyyMMdd");
// 表名(文件名的一部分)
String tableName = "SDQN-basic_identification_ip-";
method.upMethod(fileName, upSrc,tableName);
}
public static void deleteFile(String src) {
System.out.println(src);
File file = new File(src);
boolean delete = file.delete();
System.out.println(delete);
}
}

10
src/main/java/org/springblade/ftpdemo/service/Method.java

@ -0,0 +1,10 @@
package org.springblade.ftpdemo.service;
/**
* @author laifeng
* @since 2022/11/27
*/
public interface Method {
void upMethod(String readFile, String upSrc,String tableName) throws Exception;
String creatFile();
}

11
src/main/java/org/springblade/ftpdemo/service/NbmsEnprefixService.java

@ -0,0 +1,11 @@
package org.springblade.ftpdemo.service;
import com.baomidou.mybatisplus.extension.service.IService;
import org.springblade.ftpdemo.entity.NbmsEnprefix;
/**
* @author laifeng
* @since 2022/11/28
*/
public interface NbmsEnprefixService extends IService<NbmsEnprefix> {
}

11
src/main/java/org/springblade/ftpdemo/service/NbmsEntApplyServcie.java

@ -0,0 +1,11 @@
package org.springblade.ftpdemo.service;
import com.baomidou.mybatisplus.extension.service.IService;
import org.springblade.ftpdemo.entity.NbmsEntApply;
/**
* @author laifeng
* @since 2022/11/28
*/
public interface NbmsEntApplyServcie extends IService<NbmsEntApply> {
}

12
src/main/java/org/springblade/ftpdemo/service/NbmsEntServcie.java

@ -0,0 +1,12 @@
package org.springblade.ftpdemo.service;
import com.baomidou.mybatisplus.extension.service.IService;
import org.springblade.ftpdemo.entity.NbmsEnt;
/**
* @author laifeng
* @since 2022/11/28
*/
public interface NbmsEntServcie extends IService<NbmsEnt> {
}

14
src/main/java/org/springblade/ftpdemo/service/SysDictService.java

@ -0,0 +1,14 @@
package org.springblade.ftpdemo.service;
import com.baomidou.mybatisplus.extension.service.IService;
import org.springblade.ftpdemo.entity.SysDict;
import java.util.List;
/**
* @author laifeng
* @since 2022/11/28
*/
public interface SysDictService extends IService<SysDict> {
List<SysDict> selectAll();
}

74
src/main/java/org/springblade/ftpdemo/service/impl/MethodImpl.java

@ -0,0 +1,74 @@
package org.springblade.ftpdemo.service.impl;
import org.springblade.ftpdemo.controller.SSHRemoteCall;
import org.springblade.ftpdemo.service.Method;
import org.springblade.ftpdemo.util.Constant;
import org.springblade.ftpdemo.util.Encrypt;
import java.io.*;
/**
* @author laifeng
* @since 2022/11/27
*/
public class MethodImpl implements Method {
@Override
public void upMethod(String readFile, String upSrc,String tableName) throws Exception {
File file = new File(readFile);
BufferedReader br = new BufferedReader(new InputStreamReader(
new FileInputStream(file)));
StringBuilder sb = new StringBuilder();
String line = null;
while ((line = br.readLine()) != null) {
sb.append(line).append("\n");
}
br.close();
// 将字符串压缩成zip文件并获得字节数据
byte[] bytes = Encrypt.zipToBytes("D:\\aaa", sb.toString());
// upload是压缩加密后的内容
byte[] upload = Encrypt.encryptAlgorithm("1", bytes, "1234567890abcDEF",
"1234567890abcDEF");
// 生成文件名
String dateStr = Long.toString(System.currentTimeMillis()); // 生成13位时间戳
String fileName = tableName + dateStr + "-all.bin";
String src = "D:\\aaa\\" + fileName;
// 写入文件
FileOutputStream stream = new FileOutputStream(src);
stream.write(upload);
System.out.println("写入成功:" + fileName);
// 关闭输出流
stream.close();
// 远程连接服务器
SSHRemoteCall.getInstance().sshRemoteCallLogin(Constant.ipAddress, Constant.userName, Constant.password);
// 确保目录一定存在
SSHRemoteCall.getInstance().directory(upSrc);
// 上传文件到指定目录
// SSHRemoteCall.getInstance().uploadFile("/data1/qingniao/" + upSrc + "/" + fileName, src);
SSHRemoteCall.getInstance().uploadFile("/data1/qingniao/" + upSrc + "/" + fileName, src);
// 关闭连接
SSHRemoteCall.getInstance().closeSession();
}
@Override
public String creatFile() {
return null;
}
// private void deleteFile(String src) {
//
// System.out.println(src);
// File file = new File( src);
// boolean delete = file.delete();
// System.out.println(delete);
// }
}

15
src/main/java/org/springblade/ftpdemo/service/impl/NbmsEnprefixServiceImpl.java

@ -0,0 +1,15 @@
package org.springblade.ftpdemo.service.impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springblade.ftpdemo.entity.NbmsEnprefix;
import org.springblade.ftpdemo.mapper.NbmsEnprefixMapper;
import org.springblade.ftpdemo.service.NbmsEnprefixService;
import org.springframework.stereotype.Service;
/**
* @author laifeng
* @since 2022/11/28
*/
@Service
public class NbmsEnprefixServiceImpl extends ServiceImpl<NbmsEnprefixMapper, NbmsEnprefix> implements NbmsEnprefixService {
}

15
src/main/java/org/springblade/ftpdemo/service/impl/NbmsEntApplyServcieImpl.java

@ -0,0 +1,15 @@
package org.springblade.ftpdemo.service.impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springblade.ftpdemo.entity.NbmsEntApply;
import org.springblade.ftpdemo.mapper.NbmsEntApplyMapper;
import org.springblade.ftpdemo.service.NbmsEntApplyServcie;
import org.springframework.stereotype.Service;
/**
* @author laifeng
* @since 2022/11/28
*/
@Service
public class NbmsEntApplyServcieImpl extends ServiceImpl<NbmsEntApplyMapper, NbmsEntApply> implements NbmsEntApplyServcie {
}

15
src/main/java/org/springblade/ftpdemo/service/impl/NbmsEntServiceImpl.java

@ -0,0 +1,15 @@
package org.springblade.ftpdemo.service.impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springblade.ftpdemo.entity.NbmsEnt;
import org.springblade.ftpdemo.mapper.NbmsEntMapper;
import org.springblade.ftpdemo.service.NbmsEntServcie;
import org.springframework.stereotype.Service;
/**
* @author laifeng
* @since 2022/11/28
*/
@Service
public class NbmsEntServiceImpl extends ServiceImpl<NbmsEntMapper, NbmsEnt> implements NbmsEntServcie {
}

22
src/main/java/org/springblade/ftpdemo/service/impl/SysDictServiceImpl.java

@ -0,0 +1,22 @@
package org.springblade.ftpdemo.service.impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springblade.ftpdemo.entity.SysDict;
import org.springblade.ftpdemo.mapper.SysDictMapper;
import org.springblade.ftpdemo.service.SysDictService;
import org.springframework.stereotype.Service;
import java.util.List;
/**
* @author laifeng
* @since 2022/11/28
*/
@Service
public class SysDictServiceImpl extends ServiceImpl<SysDictMapper, SysDict> implements SysDictService {
@Override
public List<SysDict> selectAll() {
List<SysDict> list = baseMapper.selectList(null);
return list;
}
}

32
src/main/java/org/springblade/ftpdemo/task/IdentificationUp.java

@ -0,0 +1,32 @@
package org.springblade.ftpdemo.task;
import org.springblade.ftpdemo.entity.NbmsEntApply;
import org.springblade.ftpdemo.service.NbmsEntApplyServcie;
import lombok.AllArgsConstructor;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import java.util.List;
/**
* 标识解析企业主体信息上报
* @author laifeng
* @since 2022/11/29
*/
@Component
@EnableScheduling
@AllArgsConstructor
public class IdentificationUp {
private final NbmsEntApplyServcie service;
@Scheduled(cron = "0 0/5 * * * ?")
public void refreshAliDeviceStatus() {
// 查询昨日新增注册
List<NbmsEntApply> list = service.lambdaQuery().eq(NbmsEntApply::getFirstAuditStatus, 2)
.eq(NbmsEntApply::getApplyType, 1)
.eq(NbmsEntApply::getApplyStep,4)
.list();
}
}

15
src/main/java/org/springblade/ftpdemo/util/Constant.java

@ -0,0 +1,15 @@
package org.springblade.ftpdemo.util;
/**
* @author laifeng
* @since 2022/11/27
*/
public interface Constant {
String ipAddress = "123.233.115.26";// ip地址
String userName = "qingniao";// 账号
String password = "SDguzRp";// 密码
// String ipAddress = "47.97.5.58";// ip地址
// String userName = "root";// 账号
// String password = "Aa1572427111.";// 密码
}

249
src/main/java/org/springblade/ftpdemo/util/Decrypt.java

@ -0,0 +1,249 @@
package org.springblade.ftpdemo.util;
import org.apache.commons.codec.binary.Base64;
import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.io.*;
import java.util.ArrayList;
import java.util.List;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
public class Decrypt {
public static void main(String[] args) throws Exception {
File file = new File("D:\\aaa\\SDQN-basic_identification-1669636651805-all.bin");
long fileSize = file.length();
FileInputStream fi = new FileInputStream(file);
byte[] dataArray = new byte[(int) fileSize];
int offset = 0;
int numRead = 0;
while (offset < dataArray.length
&& (numRead = fi.read(dataArray, offset, dataArray.length - offset)) >= 0) {
offset += numRead;
}
fi.close();
// 确保所有数据均被读取
if (offset != dataArray.length) {
throw new RuntimeException("Could not completely read file "
+ file.getName());
}
// 解密
dataArray = decryptAlgorithm("1", dataArray, "1234567890abcDEF",
"1234567890abcDEF");
String xmlInfo = unZipCompression("1", dataArray);
// xmlInfo为解密后内容
System.out.println(xmlInfo);
}
public static List<File> getFiles(File[] files) {
List<File> list = new ArrayList<File>();
for (File file : files) {
if (file.isFile() && file.getName().endsWith(".txt")
&& !file.getName().endsWith("-0.txt")) {
list.add(file);
} else if (file.isDirectory()) {
list.addAll(getFiles(file.listFiles()));
}
}
return list;
}
// 解密
public static void decrypt(File file, String aesKey, String aesOffset)
throws Exception {
BufferedReader br = new BufferedReader(new InputStreamReader(
new FileInputStream(file)));
StringBuilder sb = new StringBuilder();
String line = null;
while ((line = br.readLine()) != null) {
sb.append(line);
}
br.close();
String dataUpload = sb.toString();
byte[] dataArray = getByteByBaseString(dataUpload);
dataArray = decryptAlgorithm("1", dataArray, aesKey, aesOffset);
String xmlInfo = unZipCompression("1", dataArray);
File file1 = new File(file.getAbsolutePath().substring(0,
file.getAbsolutePath().lastIndexOf("."))
+ "-0.txt");
FileWriter fw = new FileWriter(file1);
fw.write(xmlInfo);
fw.close();
}
/**
* BASE64解码
*
* @param str
* @return
*/
public static byte[] getByteByBaseString(String str) {
byte[] bArray = null;
try {
bArray = str.getBytes("utf-8");
if (Base64.isArrayByteBase64(bArray)) {
bArray = Base64.decodeBase64(bArray);
}
} catch (Exception e) {
e.printStackTrace();
}
return bArray;
}
/**
* 对称解密
*
* @param encryptType
* 加密类型
* @param zipxml
* 指令文件压缩后的结果
* @param aesKey
* AES加密钥匙
* @param aesOffsets
* AES加密偏移量
* @return
*/
public static byte[] decryptAlgorithm(String encryptType, byte[] basexml,
String aesKey, String aesOffsets) throws Exception {
byte[] command = null;
if (encryptType != null && encryptType.equals("0")) { // 不加密
command = basexml;
} else { // AES加密算法
command = decrypt(basexml, aesKey, aesOffsets);
}
return command;
}
/**
* 对AES算法加密的数据解密
*
* @param cipherText
* 要解密的字节数组
* @param key
* 密钥
* @return 解密后的字节数组
*/
public static byte[] decrypt(byte[] cipherText, String aeskey,
String aesOffsets) throws Exception {
byte[] aesBytes = aeskey.getBytes("utf-8");
if (aeskey.length() > 16) {
aesBytes = parseHexStr2Byte(aeskey);
}
SecretKeySpec skeySpec = new SecretKeySpec(aesBytes, "AES");
Cipher cipher = null;
if (aesOffsets != null && !(aesOffsets.trim()).equals("")) {
cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
byte[] bytes = aesOffsets.getBytes("utf-8");
if (aesOffsets.length() > 16) {
bytes = parseHexStr2Byte(aesOffsets);
}
IvParameterSpec iv = new IvParameterSpec(bytes);
cipher.init(Cipher.DECRYPT_MODE, skeySpec, iv);
} else {
cipher = Cipher.getInstance("AES");
cipher.init(Cipher.DECRYPT_MODE, skeySpec);
}
byte[] plainText = null;
if (cipher != null) {
plainText = cipher.doFinal(cipherText);
}
return plainText;
}
/**
* 将16进制转换为二进制   
*/
public static byte[] parseHexStr2Byte(String hexStr) {
if (hexStr.length() < 1)
return null;
byte[] result = new byte[hexStr.length() / 2];
for (int i = 0; i < hexStr.length() / 2; i++) {
int high = Integer.parseInt(hexStr.substring(i * 2, i * 2 + 1), 16);
int low = Integer.parseInt(hexStr.substring(i * 2 + 1, i * 2 + 2),
16);
result[i] = (byte) (high * 16 + low);
}
return result;
}
/**
* zip解压缩
*
* @param compressType
* @param dataArray
* @return
* @throws Exception
*/
public static String unZipCompression(String compressType, byte[] dataArray)
throws Exception {
String xmlData = null;
if (compressType != null && compressType.equals("0")) { // 无压缩
try {
xmlData = new String(dataArray, "utf-8");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
} else { // zip解压缩
xmlData = unzipToString(dataArray);
}
return xmlData;
}
/**
* 根据zip文件的字节数组解析出zip文件中第一个压缩文件内容的字符串
*
* @param info
* @return
*/
public static String unzipToString(byte[] info) throws Exception {
String strInfo = "";
byte[] bytes = unzip(info);
if (bytes != null) {
try {
strInfo = new String(bytes, "utf-8");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
}
return strInfo;
}
/**
* 根据zip文件的字节数组解析出zip文件中第一个压缩文件内容的字节数组
*
* @param info
* @return
*/
public static byte[] unzip(byte[] info) throws Exception {
byte[] bytes = null;
if (info != null) {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ZipInputStream in = new ZipInputStream(new ByteArrayInputStream(
info));
ZipEntry z = null;
if ((z = in.getNextEntry()) != null) {// zip中只有一个文件
if (!z.isDirectory()) {
int len = -1;
byte data[] = new byte[1024];
while ((len = in.read(data)) != -1) {
baos.write(data, 0, len);
}
}
}
baos.flush();
bytes = baos.toByteArray();
}
return bytes;
}
}

294
src/main/java/org/springblade/ftpdemo/util/Encrypt.java

@ -0,0 +1,294 @@
package org.springblade.ftpdemo.util;
import org.apache.commons.codec.binary.Base64;
import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.io.*;
import java.util.Date;
import java.util.Random;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
public class Encrypt {
public static void main(String[] args) throws Exception {
String readFile = "C:\\Users\\Reborn\\Desktop\\test.txt";
File file = new File(readFile);
BufferedReader br = new BufferedReader(new InputStreamReader(
new FileInputStream(file)));
StringBuilder sb = new StringBuilder();
String line = null;
while ((line = br.readLine()) != null) {
sb.append(line).append("\n");
}
br.close();
byte[] zip = zipToBytes("D:\\aaa", sb.toString());
// dataUpload是压缩加密后的内容
byte[] upload = encryptAlgorithm("1", zip, "1234567890abcDEF",
"1234567890abcDEF");
// 写文件
FileOutputStream fos = new FileOutputStream(new File("d:\\aaa\\test.bin"));
fos.write(upload);
fos.close();
}
/**
* 将字符数组base64后转字符串
*
* @param bArray
* 字符数组
* @return 字符转
*/
public static String getBaseByByte(byte[] bArray) {
String str = null;
bArray = Base64.encodeBase64(bArray);
try {
str = new String(bArray, "utf-8");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
return str;
}
/**
* 将字符串压缩成zip文件并获得字节数据
*
* @param path
* @param info
* @return
*/
public static byte[] zipToBytes(String path, String info) {
String zipFileName = zip(path, info);
byte[] zipBytes = getBytes(zipFileName);
return zipBytes;
}
static AtomicInteger count = new AtomicInteger(0);
/**
* 根据文件内容生成zip文件
*
* @param path
* @param info
* @return
*/
public static String zip(String path, String info) {
if (count.get() / 10000 == 0) {
count.getAndSet(0);
}
int t = count.getAndIncrement();
Long time = new Date().getTime();
String commandId = String.valueOf(time & 0xffffffffl);
// 添加4位随机数,ID重复问题。
commandId = commandId + randomString(4);
String filename = commandId + t;
String zipFileName = path + "/" + filename + ".zip";
System.out.println("zipFileName=" + zipFileName);
if (info != null) {
if (!checkDir(path)) {
createDir(path);
}
File zipFile = new File(zipFileName);
ZipOutputStream out = null;
try {
out = new ZipOutputStream(new FileOutputStream(zipFile));
Date date = new Date();
out.putNextEntry(new ZipEntry(date.getTime() + filename
+ ".xml"));
out.write(info.getBytes("utf-8"));
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if (out != null) {
out.flush();
out.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
return zipFileName;
}
/**
* 对称加密
*
* @param encryptType
* 加密类型
* @param zipxml
* 指令文件压缩后的结果
* @param aesKey
* AES加密钥匙
* @param aesOffsets
* AES加密偏移量
* @return
*/
public static byte[] encryptAlgorithm(String encryptType, byte[] zipxml,
String aesKey, String aesOffsets) {
byte[] command = null;
if (encryptType != null && encryptType.equals("0")) { // 不加密
command = zipxml;
} else { // AES加密算法
command = aes(zipxml, aesKey, aesOffsets);
}
return command;
}
/**
* 获得指定文件的byte数组
*/
public static byte[] getBytes(String filePath) {
byte[] buffer = null;
try {
File file = new File(filePath);
if (file.exists()) {
FileInputStream fis = new FileInputStream(file);
ByteArrayOutputStream bos = new ByteArrayOutputStream(1000);
byte[] b = new byte[1000];
int n;
while ((n = fis.read(b)) != -1) {
bos.write(b, 0, n);
}
fis.close();
bos.close();
buffer = bos.toByteArray();
}
file.delete();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return buffer;
}
/**
* aes加密
*
* @param plainText
* @param aeskey
* @param aesOffsets
* @return
*/
public static byte[] aes(byte[] plainText, String aeskey, String aesOffsets) {
try {
byte[] aesBytes = aeskey.getBytes("utf-8");
if (aeskey.length() > 16) {
aesBytes = parseHexStr2Byte(aeskey);
System.out.println(111);
}
SecretKeySpec skeySpec = new SecretKeySpec(aesBytes, "AES");
Cipher cipher = null;
if (aesOffsets != null && !(aesOffsets.trim()).equals("")) {
cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
byte[] bytes = aesOffsets.getBytes("utf-8");
if (aesOffsets.length() > 16) {
bytes = parseHexStr2Byte(aesOffsets);
}
IvParameterSpec iv = new IvParameterSpec(bytes);
cipher.init(Cipher.ENCRYPT_MODE, skeySpec, iv);
} else {
cipher = Cipher.getInstance("AES");
cipher.init(Cipher.ENCRYPT_MODE, skeySpec);
}
byte[] decryptText = null;
if (cipher != null) {
decryptText = cipher.doFinal(plainText);
}
return decryptText;
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
/**
* 将16进制转换为二进制   
*/
public static byte[] parseHexStr2Byte(String hexStr) {
if (hexStr.length() < 1)
return null;
byte[] result = new byte[hexStr.length() / 2];
for (int i = 0; i < hexStr.length() / 2; i++) {
int high = Integer.parseInt(hexStr.substring(i * 2, i * 2 + 1), 16);
int low = Integer.parseInt(hexStr.substring(i * 2 + 1, i * 2 + 2),
16);
result[i] = (byte) (high * 16 + low);
}
return result;
}
// 生成n个字节的随机字符串
public static String randomString(int length) {
Random randGen = null;
char[] numbersAndLetters = null;
if (length < 1) {
return null;
}
if (randGen == null) {
randGen = new Random();
numbersAndLetters = ("0123456789abcdefghijklmnopqrstuvwxyz"
+ "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ").toCharArray();
// numbersAndLetters =
// ("0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ").toCharArray();
}
char[] randBuffer = new char[length];
for (int i = 0; i < randBuffer.length; i++) {
randBuffer[i] = numbersAndLetters[randGen.nextInt(71)];
// randBuffer[i] = numbersAndLetters[randGen.nextInt(35)];
}
return new String(randBuffer);
}
/**
* 目录是否存在
*
* @param dirName
* @return
*/
public static boolean checkDir(String dirName) {
File dir = new File(dirName);
if (dir.exists()) {
return true;
} else {
return false;
}
}
/**
* 创建目录
*
* @param dirName
* @return
*/
public static boolean createDir(String dirName) {
File dir = new File(dirName);
if (!dirName.endsWith(File.separator)) {
dirName = dirName + File.separator;
}
// 创建目录
if (dir.mkdirs()) {
System.out.println("创建目录" + dirName + "成功!");
return true;
} else {
System.out.println("创建目录" + dirName + "失败!");
return false;
}
}
}

97
src/main/java/org/springblade/modules/auth/endpoint/BladeSocialEndpoint.java

@ -0,0 +1,97 @@
/*
* Copyright (c) 2018-2028, Chill Zhuang All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* Neither the name of the dreamlu.net developer nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
* Author: Chill 庄骞 (smallchill@163.com)
*/
package org.springblade.modules.auth.endpoint;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import me.zhyd.oauth.model.AuthCallback;
import me.zhyd.oauth.model.AuthToken;
import me.zhyd.oauth.request.AuthRequest;
import me.zhyd.oauth.utils.AuthStateUtils;
import org.springblade.core.launch.constant.AppConstant;
import org.springblade.core.social.props.SocialProperties;
import org.springblade.core.social.utils.SocialUtil;
import org.springblade.core.tenant.annotation.NonDS;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* 第三方登陆端点
*
* @author Chill
*/
@NonDS
@Slf4j
@RestController
@AllArgsConstructor
@RequestMapping(AppConstant.APPLICATION_AUTH_NAME)
@ConditionalOnProperty(value = "social.enabled", havingValue = "true")
@Api(value = "第三方登陆", tags = "第三方登陆端点")
public class BladeSocialEndpoint {
private final SocialProperties socialProperties;
/**
* 授权完毕跳转
*/
@ApiOperation(value = "授权完毕跳转")
@RequestMapping("/oauth/render/{source}")
public void renderAuth(@PathVariable("source") String source, HttpServletResponse response) throws IOException {
AuthRequest authRequest = SocialUtil.getAuthRequest(source, socialProperties);
String authorizeUrl = authRequest.authorize(AuthStateUtils.createState());
response.sendRedirect(authorizeUrl);
}
/**
* 获取认证信息
*/
@ApiOperation(value = "获取认证信息")
@RequestMapping("/oauth/callback/{source}")
public Object login(@PathVariable("source") String source, AuthCallback callback) {
AuthRequest authRequest = SocialUtil.getAuthRequest(source, socialProperties);
return authRequest.login(callback);
}
/**
* 撤销授权
*/
@ApiOperation(value = "撤销授权")
@RequestMapping("/oauth/revoke/{source}/{token}")
public Object revokeAuth(@PathVariable("source") String source, @PathVariable("token") String token) {
AuthRequest authRequest = SocialUtil.getAuthRequest(source, socialProperties);
return authRequest.revoke(AuthToken.builder().accessToken(token).build());
}
/**
* 续期accessToken
*/
@ApiOperation(value = "续期令牌")
@RequestMapping("/oauth/refresh/{source}")
public Object refreshAuth(@PathVariable("source") String source, String token) {
AuthRequest authRequest = SocialUtil.getAuthRequest(source, socialProperties);
return authRequest.refresh(AuthToken.builder().refreshToken(token).build());
}
}

149
src/main/java/org/springblade/modules/auth/endpoint/BladeTokenEndPoint.java

@ -0,0 +1,149 @@
/*
* Copyright (c) 2018-2028, Chill Zhuang All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* Neither the name of the dreamlu.net developer nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
* Author: Chill 庄骞 (smallchill@163.com)
*/
package org.springblade.modules.auth.endpoint;
import com.github.xiaoymin.knife4j.annotations.ApiSort;
import com.wf.captcha.SpecCaptcha;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import lombok.AllArgsConstructor;
import org.springblade.common.cache.CacheNames;
import org.springblade.core.cache.utils.CacheUtil;
import org.springblade.core.jwt.JwtUtil;
import org.springblade.core.jwt.props.JwtProperties;
import org.springblade.core.launch.constant.AppConstant;
import org.springblade.core.launch.constant.TokenConstant;
import org.springblade.core.log.annotation.ApiLog;
import org.springblade.core.redis.cache.BladeRedis;
import org.springblade.core.secure.BladeUser;
import org.springblade.core.secure.utils.AuthUtil;
import org.springblade.core.tenant.annotation.NonDS;
import org.springblade.core.tool.support.Kv;
import org.springblade.core.tool.utils.Func;
import org.springblade.core.tool.utils.WebUtil;
import org.springblade.modules.auth.provider.ITokenGranter;
import org.springblade.modules.auth.provider.TokenGranterBuilder;
import org.springblade.modules.auth.provider.TokenParameter;
import org.springblade.modules.auth.utils.TokenUtil;
import org.springblade.modules.system.entity.UserInfo;
import org.springframework.web.bind.annotation.*;
import springfox.documentation.annotations.ApiIgnore;
import javax.servlet.http.HttpServletResponse;
import java.time.Duration;
import java.util.UUID;
import static org.springblade.core.cache.constant.CacheConstant.*;
/**
* 令牌端点
*
* @author Chill
*/
@NonDS
@ApiSort(1)
@RestController
@AllArgsConstructor
@RequestMapping(AppConstant.APPLICATION_AUTH_NAME)
@Api(value = "用户授权认证", tags = "授权接口")
public class BladeTokenEndPoint {
private final BladeRedis bladeRedis;
private final JwtProperties jwtProperties;
@ApiLog("登录用户验证")
@PostMapping("/oauth/token")
@ApiOperation(value = "获取认证令牌", notes = "传入租户ID:tenantId,账号:account,密码:password")
public Kv token(@ApiParam(value = "租户ID", required = true) @RequestParam String tenantId,
@ApiParam(value = "账号", required = true) @RequestParam(required = false) String username,
@ApiParam(value = "密码", required = true) @RequestParam(required = false) String password,
@ApiIgnore @RequestHeader(name = TokenUtil.DEPT_HEADER_KEY, required = false) String deptId,
@ApiIgnore @RequestHeader(name = TokenUtil.ROLE_HEADER_KEY, required = false) String roleId) {
Kv authInfo = Kv.create();
String grantType = WebUtil.getRequest().getParameter("grant_type");
String refreshToken = WebUtil.getRequest().getParameter("refresh_token");
String userType = Func.toStr(WebUtil.getRequest().getHeader(TokenUtil.USER_TYPE_HEADER_KEY), TokenUtil.DEFAULT_USER_TYPE);
TokenParameter tokenParameter = new TokenParameter();
tokenParameter.getArgs().set("tenantId", tenantId)
.set("username", username)
.set("password", password)
.set("grantType", grantType)
.set("refreshToken", refreshToken)
.set("userType", userType)
.set("deptId", deptId).set("roleId", roleId);
ITokenGranter granter = TokenGranterBuilder.getGranter(grantType);
UserInfo userInfo = granter.grant(tokenParameter);
if (userInfo == null || userInfo.getUser() == null) {
return authInfo.set("error_code", HttpServletResponse.SC_BAD_REQUEST).set("error_description", "用户名或密码不正确");
}
if (Func.isEmpty(userInfo.getRoles())) {
return authInfo.set("error_code", HttpServletResponse.SC_BAD_REQUEST).set("error_description", "未获得用户的角色信息");
}
return TokenUtil.createAuthInfo(userInfo);
}
@GetMapping("/oauth/logout")
@ApiOperation(value = "退出登录")
public Kv logout() {
BladeUser user = AuthUtil.getUser();
if (user != null && jwtProperties.getState()) {
String token = JwtUtil.getToken(WebUtil.getRequest().getHeader(TokenConstant.HEADER));
JwtUtil.removeAccessToken(user.getTenantId(), String.valueOf(user.getUserId()), token);
}
return Kv.create().set("success", "true").set("msg", "success");
}
@GetMapping("/oauth/captcha")
@ApiOperation(value = "获取验证码")
public Kv captcha() {
SpecCaptcha specCaptcha = new SpecCaptcha(130, 48, 5);
String verCode = specCaptcha.text().toLowerCase();
String key = UUID.randomUUID().toString();
// 存入redis并设置过期时间为30分钟
bladeRedis.setEx(CacheNames.CAPTCHA_KEY + key, verCode, Duration.ofMinutes(30));
// 将key和base64返回给前端
return Kv.create().set("key", key).set("image", specCaptcha.toBase64());
}
@GetMapping("/oauth/clear-cache")
@ApiOperation(value = "清除缓存")
public Kv clearCache() {
CacheUtil.clear(BIZ_CACHE);
CacheUtil.clear(USER_CACHE);
CacheUtil.clear(DICT_CACHE);
CacheUtil.clear(FLOW_CACHE);
CacheUtil.clear(SYS_CACHE);
CacheUtil.clear(PARAM_CACHE);
CacheUtil.clear(RESOURCE_CACHE);
CacheUtil.clear(MENU_CACHE);
CacheUtil.clear(DICT_CACHE, Boolean.FALSE);
CacheUtil.clear(MENU_CACHE, Boolean.FALSE);
CacheUtil.clear(SYS_CACHE, Boolean.FALSE);
CacheUtil.clear(PARAM_CACHE, Boolean.FALSE);
return Kv.create().set("success", "true").set("msg", "success");
}
}

50
src/main/java/org/springblade/modules/auth/enums/UserEnum.java

@ -0,0 +1,50 @@
/*
* Copyright (c) 2018-2028, Chill Zhuang All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* Neither the name of the dreamlu.net developer nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
* Author: Chill 庄骞 (smallchill@163.com)
*/
package org.springblade.modules.auth.enums;
import lombok.AllArgsConstructor;
import lombok.Getter;
/**
* 用户类型枚举
*
* @author Chill
*/
@Getter
@AllArgsConstructor
public enum UserEnum {
/**
* web
*/
WEB("web", 1),
/**
* app
*/
APP("app", 2),
/**
* other
*/
OTHER("other", 3),
;
final String name;
final int category;
}

127
src/main/java/org/springblade/modules/auth/granter/CaptchaTokenGranter.java

@ -0,0 +1,127 @@
/*
* Copyright (c) 2018-2028, Chill Zhuang All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* Neither the name of the dreamlu.net developer nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
* Author: Chill 庄骞 (smallchill@163.com)
*/
package org.springblade.modules.auth.granter;
import lombok.AllArgsConstructor;
import org.springblade.common.cache.CacheNames;
import org.springblade.common.cache.ParamCache;
import org.springblade.core.log.exception.ServiceException;
import org.springblade.core.redis.cache.BladeRedis;
import org.springblade.core.tool.utils.DigestUtil;
import org.springblade.core.tool.utils.Func;
import org.springblade.core.tool.utils.StringUtil;
import org.springblade.core.tool.utils.WebUtil;
import org.springblade.modules.auth.enums.UserEnum;
import org.springblade.modules.auth.provider.ITokenGranter;
import org.springblade.modules.auth.provider.TokenParameter;
import org.springblade.modules.auth.utils.TokenUtil;
import org.springblade.modules.system.entity.Tenant;
import org.springblade.modules.system.entity.UserInfo;
import org.springblade.modules.system.service.IRoleService;
import org.springblade.modules.system.service.ITenantService;
import org.springblade.modules.system.service.IUserService;
import org.springframework.stereotype.Component;
import javax.servlet.http.HttpServletRequest;
import java.time.Duration;
import java.util.List;
/**
* 验证码TokenGranter
*
* @author Chill
*/
@Component
@AllArgsConstructor
public class CaptchaTokenGranter implements ITokenGranter {
public static final String GRANT_TYPE = "captcha";
public static final Integer FAIL_COUNT = 5;
public static final String FAIL_COUNT_VALUE = "account.failCount";
private final IUserService userService;
private final IRoleService roleService;
private final ITenantService tenantService;
private final BladeRedis bladeRedis;
@Override
public UserInfo grant(TokenParameter tokenParameter) {
HttpServletRequest request = WebUtil.getRequest();
// 获取用户绑定ID
String headerDept = request.getHeader(TokenUtil.DEPT_HEADER_KEY);
String headerRole = request.getHeader(TokenUtil.ROLE_HEADER_KEY);
// 获取验证码信息
String key = request.getHeader(TokenUtil.CAPTCHA_HEADER_KEY);
String code = request.getHeader(TokenUtil.CAPTCHA_HEADER_CODE);
// 获取验证码
String redisCode = bladeRedis.get(CacheNames.CAPTCHA_KEY + key);
// 判断验证码
if (code == null || !StringUtil.equalsIgnoreCase(redisCode, code)) {
throw new ServiceException(TokenUtil.CAPTCHA_NOT_CORRECT);
}
String tenantId = tokenParameter.getArgs().getStr("tenantId");
String username = tokenParameter.getArgs().getStr("username");
String password = tokenParameter.getArgs().getStr("password");
// 判断登录是否锁定
int cnt = Func.toInt(bladeRedis.get(CacheNames.tenantKey(tenantId, CacheNames.USER_FAIL_KEY, username)), 0);
int failCount = Func.toInt(ParamCache.getValue(FAIL_COUNT_VALUE), FAIL_COUNT);
if (cnt >= failCount) {
throw new ServiceException(TokenUtil.USER_HAS_TOO_MANY_FAILS);
}
UserInfo userInfo = null;
if (Func.isNoneBlank(username, password)) {
// 获取租户信息
Tenant tenant = tenantService.getByTenantId(tenantId);
if (TokenUtil.judgeTenant(tenant)) {
throw new ServiceException(TokenUtil.USER_HAS_NO_TENANT_PERMISSION);
}
// 获取用户类型
String userType = tokenParameter.getArgs().getStr("userType");
// 根据不同用户类型调用对应的接口返回数据,用户可自行拓展
if (userType.equals(UserEnum.WEB.getName())) {
userInfo = userService.userInfo(tenantId, username, DigestUtil.hex(password), UserEnum.WEB);
} else if (userType.equals(UserEnum.APP.getName())) {
userInfo = userService.userInfo(tenantId, username, DigestUtil.hex(password), UserEnum.APP);
} else {
userInfo = userService.userInfo(tenantId, username, DigestUtil.hex(password), UserEnum.OTHER);
}
}
if (userInfo == null || userInfo.getUser() == null) {
// 增加错误锁定次数
bladeRedis.setEx(CacheNames.tenantKey(tenantId, CacheNames.USER_FAIL_KEY, username), cnt + 1, Duration.ofMinutes(30));
} else {
// 成功则清除登录错误次数
bladeRedis.del(CacheNames.tenantKey(tenantId, CacheNames.USER_FAIL_KEY, username));
}
// 多部门情况下指定单部门
if (Func.isNotEmpty(headerDept) && userInfo != null && userInfo.getUser().getDeptId().contains(headerDept)) {
userInfo.getUser().setDeptId(headerDept);
}
// 多角色情况下指定单角色
if (Func.isNotEmpty(headerRole) && userInfo != null && userInfo.getUser().getRoleId().contains(headerRole)) {
List<String> roleResult = roleService.getRoleAliases(headerRole);
userInfo.setRoles(roleResult);
userInfo.getUser().setRoleId(headerRole);
}
return userInfo;
}
}

117
src/main/java/org/springblade/modules/auth/granter/PasswordTokenGranter.java

@ -0,0 +1,117 @@
/*
* Copyright (c) 2018-2028, Chill Zhuang All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* Neither the name of the dreamlu.net developer nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
* Author: Chill 庄骞 (smallchill@163.com)
*/
package org.springblade.modules.auth.granter;
import lombok.AllArgsConstructor;
import org.springblade.common.cache.CacheNames;
import org.springblade.common.cache.ParamCache;
import org.springblade.core.log.exception.ServiceException;
import org.springblade.core.redis.cache.BladeRedis;
import org.springblade.core.tool.utils.DigestUtil;
import org.springblade.core.tool.utils.Func;
import org.springblade.core.tool.utils.WebUtil;
import org.springblade.modules.auth.enums.UserEnum;
import org.springblade.modules.auth.provider.ITokenGranter;
import org.springblade.modules.auth.provider.TokenParameter;
import org.springblade.modules.auth.utils.TokenUtil;
import org.springblade.modules.system.entity.Tenant;
import org.springblade.modules.system.entity.UserInfo;
import org.springblade.modules.system.service.IRoleService;
import org.springblade.modules.system.service.ITenantService;
import org.springblade.modules.system.service.IUserService;
import org.springframework.stereotype.Component;
import javax.servlet.http.HttpServletRequest;
import java.time.Duration;
import java.util.List;
/**
* PasswordTokenGranter
*
* @author Chill
*/
@Component
@AllArgsConstructor
public class PasswordTokenGranter implements ITokenGranter {
public static final String GRANT_TYPE = "password";
public static final Integer FAIL_COUNT = 5;
public static final String FAIL_COUNT_VALUE = "account.failCount";
private final IUserService userService;
private final IRoleService roleService;
private final ITenantService tenantService;
private final BladeRedis bladeRedis;
@Override
public UserInfo grant(TokenParameter tokenParameter) {
HttpServletRequest request = WebUtil.getRequest();
// 获取用户绑定ID
String headerDept = request.getHeader(TokenUtil.DEPT_HEADER_KEY);
String headerRole = request.getHeader(TokenUtil.ROLE_HEADER_KEY);
// 获取用户信息
String tenantId = tokenParameter.getArgs().getStr("tenantId");
String username = tokenParameter.getArgs().getStr("username");
String password = tokenParameter.getArgs().getStr("password");
// 判断登录是否锁定
int cnt = Func.toInt(bladeRedis.get(CacheNames.tenantKey(tenantId, CacheNames.USER_FAIL_KEY, username)), 0);
int failCount = Func.toInt(ParamCache.getValue(FAIL_COUNT_VALUE), FAIL_COUNT);
if (cnt >= failCount) {
throw new ServiceException(TokenUtil.USER_HAS_TOO_MANY_FAILS);
}
UserInfo userInfo = null;
if (Func.isNoneBlank(username, password)) {
// 获取租户信息
Tenant tenant = tenantService.getByTenantId(tenantId);
if (TokenUtil.judgeTenant(tenant)) {
throw new ServiceException(TokenUtil.USER_HAS_NO_TENANT_PERMISSION);
}
// 获取用户类型
String userType = tokenParameter.getArgs().getStr("userType");
// 根据不同用户类型调用对应的接口返回数据,用户可自行拓展
if (userType.equals(UserEnum.WEB.getName())) {
userInfo = userService.userInfo(tenantId, username, DigestUtil.hex(password), UserEnum.WEB);
} else if (userType.equals(UserEnum.APP.getName())) {
userInfo = userService.userInfo(tenantId, username, DigestUtil.hex(password), UserEnum.APP);
} else {
userInfo = userService.userInfo(tenantId, username, DigestUtil.hex(password), UserEnum.OTHER);
}
}
if (userInfo == null || userInfo.getUser() == null) {
// 增加错误锁定次数
bladeRedis.setEx(CacheNames.tenantKey(tenantId, CacheNames.USER_FAIL_KEY, username), cnt + 1, Duration.ofMinutes(30));
} else {
// 成功则清除登录错误次数
bladeRedis.del(CacheNames.tenantKey(tenantId, CacheNames.USER_FAIL_KEY, username));
}
// 多部门情况下指定单部门
if (Func.isNotEmpty(headerDept) && userInfo != null && userInfo.getUser().getDeptId().contains(headerDept)) {
userInfo.getUser().setDeptId(headerDept);
}
// 多角色情况下指定单角色
if (Func.isNotEmpty(headerRole) && userInfo != null && userInfo.getUser().getRoleId().contains(headerRole)) {
List<String> roleAliases = roleService.getRoleAliases(headerRole);
userInfo.setRoles(roleAliases);
userInfo.getUser().setRoleId(headerRole);
}
return userInfo;
}
}

114
src/main/java/org/springblade/modules/auth/granter/RefreshTokenGranter.java

@ -0,0 +1,114 @@
/*
* Copyright (c) 2018-2028, Chill Zhuang All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* Neither the name of the dreamlu.net developer nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
* Author: Chill 庄骞 (smallchill@163.com)
*/
package org.springblade.modules.auth.granter;
import io.jsonwebtoken.Claims;
import lombok.AllArgsConstructor;
import org.springblade.core.jwt.JwtUtil;
import org.springblade.core.jwt.props.JwtProperties;
import org.springblade.core.launch.constant.TokenConstant;
import org.springblade.core.log.exception.ServiceException;
import org.springblade.core.secure.utils.AuthUtil;
import org.springblade.core.tool.utils.Func;
import org.springblade.core.tool.utils.StringUtil;
import org.springblade.modules.auth.provider.ITokenGranter;
import org.springblade.modules.auth.provider.TokenParameter;
import org.springblade.modules.auth.utils.TokenUtil;
import org.springblade.modules.system.entity.Tenant;
import org.springblade.modules.system.entity.UserInfo;
import org.springblade.modules.system.service.IRoleService;
import org.springblade.modules.system.service.ITenantService;
import org.springblade.modules.system.service.IUserService;
import org.springframework.stereotype.Component;
import java.util.List;
/**
* RefreshTokenGranter
*
* @author Chill
*/
@Component
@AllArgsConstructor
public class RefreshTokenGranter implements ITokenGranter {
public static final String GRANT_TYPE = "refresh_token";
private final IUserService userService;
private final IRoleService roleService;
private final ITenantService tenantService;
private final JwtProperties jwtProperties;
@Override
public UserInfo grant(TokenParameter tokenParameter) {
String tenantId = tokenParameter.getArgs().getStr("tenantId");
String grantType = tokenParameter.getArgs().getStr("grantType");
String refreshToken = tokenParameter.getArgs().getStr("refreshToken");
String deptId = tokenParameter.getArgs().getStr("deptId");
String roleId = tokenParameter.getArgs().getStr("roleId");
UserInfo userInfo = null;
if (Func.isNoneBlank(grantType, refreshToken) && grantType.equals(TokenConstant.REFRESH_TOKEN)) {
// 判断令牌合法性
if (!judgeRefreshToken(grantType, refreshToken)) {
throw new ServiceException(TokenUtil.TOKEN_NOT_PERMISSION);
}
Claims claims = AuthUtil.parseJWT(refreshToken);
if (claims != null) {
String tokenType = Func.toStr(claims.get(TokenConstant.TOKEN_TYPE));
if (tokenType.equals(TokenConstant.REFRESH_TOKEN)) {
// 获取租户信息
Tenant tenant = tenantService.getByTenantId(tenantId);
if (TokenUtil.judgeTenant(tenant)) {
throw new ServiceException(TokenUtil.USER_HAS_NO_TENANT_PERMISSION);
}
// 获取用户信息
userInfo = userService.userInfo(Func.toLong(claims.get(TokenConstant.USER_ID)));
// 设置多部门信息
if (Func.isNotEmpty(deptId) && userInfo.getUser().getDeptId().contains(deptId)) {
userInfo.getUser().setDeptId(deptId);
}
// 设置多角色信息
if (Func.isNotEmpty(roleId) && userInfo.getUser().getRoleId().contains(roleId)) {
userInfo.getUser().setRoleId(roleId);
List<String> roleAliases = roleService.getRoleAliases(roleId);
userInfo.setRoles(roleAliases);
}
}
}
}
return userInfo;
}
/**
* 校验refreshToken合法性
*
* @param grantType 认证类型
* @param refreshToken refreshToken
*/
private boolean judgeRefreshToken(String grantType, String refreshToken) {
if (jwtProperties.getState() && jwtProperties.getSingle()) {
Claims claims = JwtUtil.parseJWT(refreshToken);
String tenantId = String.valueOf(claims.get("tenant_id"));
String userId = String.valueOf(claims.get("user_id"));
String token = JwtUtil.getRefreshToken(tenantId, userId, refreshToken);
return StringUtil.equalsIgnoreCase(token, refreshToken);
}
return true;
}
}

92
src/main/java/org/springblade/modules/auth/granter/SocialTokenGranter.java

@ -0,0 +1,92 @@
/*
* Copyright (c) 2018-2028, Chill Zhuang All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* Neither the name of the dreamlu.net developer nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
* Author: Chill 庄骞 (smallchill@163.com)
*/
package org.springblade.modules.auth.granter;
import lombok.AllArgsConstructor;
import me.zhyd.oauth.model.AuthCallback;
import me.zhyd.oauth.model.AuthResponse;
import me.zhyd.oauth.model.AuthUser;
import me.zhyd.oauth.request.AuthRequest;
import org.springblade.core.log.exception.ServiceException;
import org.springblade.core.social.props.SocialProperties;
import org.springblade.core.social.utils.SocialUtil;
import org.springblade.core.tool.utils.BeanUtil;
import org.springblade.core.tool.utils.Func;
import org.springblade.core.tool.utils.WebUtil;
import org.springblade.modules.auth.provider.ITokenGranter;
import org.springblade.modules.auth.provider.TokenParameter;
import org.springblade.modules.auth.utils.TokenUtil;
import org.springblade.modules.system.entity.UserInfo;
import org.springblade.modules.system.entity.UserOauth;
import org.springblade.modules.system.service.IUserService;
import org.springframework.stereotype.Component;
import javax.servlet.http.HttpServletRequest;
import java.util.Objects;
/**
* SocialTokenGranter
*
* @author Chill
*/
@Component
@AllArgsConstructor
public class SocialTokenGranter implements ITokenGranter {
public static final String GRANT_TYPE = "social";
private static final Integer AUTH_SUCCESS_CODE = 2000;
private final IUserService userService;
private final SocialProperties socialProperties;
@Override
public UserInfo grant(TokenParameter tokenParameter) {
HttpServletRequest request = WebUtil.getRequest();
String tenantId = Func.toStr(request.getHeader(TokenUtil.TENANT_HEADER_KEY), TokenUtil.DEFAULT_TENANT_ID);
// 开放平台来源
String sourceParameter = request.getParameter("source");
// 匹配是否有别名定义
String source = socialProperties.getAlias().getOrDefault(sourceParameter, sourceParameter);
// 开放平台授权码
String code = request.getParameter("code");
// 开放平台状态吗
String state = request.getParameter("state");
// 获取开放平台授权数据
AuthRequest authRequest = SocialUtil.getAuthRequest(source, socialProperties);
AuthCallback authCallback = new AuthCallback();
authCallback.setCode(code);
authCallback.setState(state);
AuthResponse authResponse = authRequest.login(authCallback);
AuthUser authUser;
if (authResponse.getCode() == AUTH_SUCCESS_CODE) {
authUser = (AuthUser) authResponse.getData();
} else {
throw new ServiceException("social grant failure, auth response is not success");
}
// 组装数据
UserOauth userOauth = Objects.requireNonNull(BeanUtil.copy(authUser, UserOauth.class));
userOauth.setSource(authUser.getSource());
userOauth.setTenantId(tenantId);
userOauth.setUuid(authUser.getUuid());
// 返回UserInfo
return userService.userInfo(userOauth);
}
}

36
src/main/java/org/springblade/modules/auth/provider/ITokenGranter.java

@ -0,0 +1,36 @@
/*
* Copyright (c) 2018-2028, Chill Zhuang All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* Neither the name of the dreamlu.net developer nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
* Author: Chill 庄骞 (smallchill@163.com)
*/
package org.springblade.modules.auth.provider;
import org.springblade.modules.system.entity.UserInfo;
/**
* 授权认证统一接口.
*
* @author Chill
*/
public interface ITokenGranter {
/**
* 获取用户信息
*
* @param tokenParameter 授权参数
* @return UserInfo
*/
UserInfo grant(TokenParameter tokenParameter);
}

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

Loading…
Cancel
Save