Compare commits

..

128 Commits
0.2.0 ... 1.0.1

Author SHA1 Message Date
曾文豪
0cb1581176 publish 1.0.1 2023-05-10 15:53:50 +08:00
曾文豪
5ed663e112 perf:fastjson禁用 将相同的对象写成引用的形式 2023-05-10 15:53:22 +08:00
曾文豪
b5fd837ccf perf:调整yml 2023-05-08 14:00:26 +08:00
曾文豪
38d6bae04f publish 1.0.0 2023-04-26 14:43:43 +08:00
曾文豪
e49bf32117 perf:增加参数配置时的额外校验 2023-04-23 16:35:48 +08:00
曾文豪
bc3ea0e10c perf:依赖更新 2023-04-23 16:32:29 +08:00
曾文豪
305dc743b2 chore:更新gitlab-ci 2023-04-21 15:43:07 +08:00
曾文豪
6f0360bad5 chore:更新gitlab-ci 2023-04-21 15:37:43 +08:00
曾文豪
5012c4bd53 chore:更新gitlab-ci 2023-04-21 15:29:07 +08:00
曾文豪
dd69b3bb1f perf:依赖更新 2023-04-21 15:28:21 +08:00
曾文豪
33d20c518e publish 0.9.14 2023-04-17 15:23:45 +08:00
曾文豪
d0935cbda0 publish 0.9.13 2023-04-17 15:08:24 +08:00
曾文豪
3ed9a47c66 publish 0.9.13 2023-04-17 14:47:24 +08:00
曾文豪
3f6989d039 publish 0.9.12 2023-04-11 16:32:16 +08:00
曾文豪
6f6e997fd3 perf:版本号现在可以从外部目录中获取 2023-04-11 16:18:37 +08:00
曾文豪
d9987b41ea publish 0.9.11 2023-04-10 16:48:18 +08:00
曾文豪
c33ad6075e perf:调整导入流程的条数 2023-04-10 16:48:02 +08:00
曾文豪
a32c333a6c publish 0.9.10 2023-04-10 14:22:45 +08:00
曾文豪
ed66f035e5 perf:调整导入流程的泛型 2023-04-10 14:22:20 +08:00
曾文豪
f5dd706e6e perf:调整demo 2023-04-10 14:21:15 +08:00
曾文豪
6766694272 publish 0.9.9 2023-04-06 10:29:37 +08:00
曾文豪
2f22b64c0e publish 0.9.8 2023-04-06 09:57:37 +08:00
曾文豪
4e6b108e7e publish 0.9.8 2023-04-06 09:54:01 +08:00
曾文豪
24629f06b4 publish 0.9.7 2023-04-06 00:05:49 +08:00
曾文豪
47c9251389 publish 0.9.7 2023-04-06 00:01:26 +08:00
曾文豪
dda5f64910 publish 0.9.7 2023-04-05 23:42:58 +08:00
曾文豪
704030729a publish 0.9.7 2023-04-05 23:38:21 +08:00
曾文豪
c708809a19 perf:登录导入进度 2023-04-05 23:36:51 +08:00
曾文豪
2bbec9b79a perf:登录调整 2023-04-05 23:06:09 +08:00
曾文豪
e19f27f597 publish 0.9.6 2023-03-31 16:33:21 +08:00
曾文豪
68781d4685 publish 0.9.5 2023-03-31 16:12:44 +08:00
曾文豪
da69124968 publish 0.9.4 2023-03-31 14:21:32 +08:00
曾文豪
8d9632bcaa perf:调整消息通知 2023-03-31 14:21:07 +08:00
曾文豪
1c0e63bf98 publish 0.9.3 2023-03-31 12:07:21 +08:00
曾文豪
c04d45431c publish 0.9.3 2023-03-31 11:54:21 +08:00
曾文豪
c5f8508a9e perf:增加版本对比器 2023-03-31 10:35:21 +08:00
曾文豪
06f295bb66 publish 0.9.2 2023-03-28 17:56:59 +08:00
曾文豪
bfc578e77c publish 0.9.1 2023-03-28 17:12:19 +08:00
曾文豪
b5c10fc224 feat:职位表增加扩展 2023-03-28 17:12:01 +08:00
曾文豪
60580b40a4 publish 0.9.0 2023-03-28 16:43:14 +08:00
曾文豪
af70808da6 feat:增加职位管理功能 2023-03-28 16:40:54 +08:00
2715557295@qq.com
c446ee8f75 publish 0.8.8 2023-03-24 09:39:04 +08:00
2715557295@qq.com
86384a1f23 publish 0.8.7 2023-03-22 17:22:54 +08:00
2715557295@qq.com
d63b6ab094 publish 0.8.7 2023-03-22 16:52:51 +08:00
2715557295@qq.com
020d1d99e1 publish 0.8.6 2023-03-22 11:12:23 +08:00
曾文豪
32fb562775 publish 0.8.5 2023-03-14 14:20:56 +08:00
曾文豪
af50468743 perf: 调整token校验 2023-03-14 14:20:23 +08:00
曾文豪
cab794ecc4 Merge branch 'test-uploadDir' into 'master'
GlobalConfig新加uploadDir配置

See merge request tiesheng/tiesheng!2
2023-03-14 06:10:02 +00:00
‘毛文春’
0c511940aa GlobalConfig新加uploadDir配置 2023-03-14 14:03:53 +08:00
‘毛文春’
60dea50e43 修改 过滤不要需要验证的接口(path) 2023-03-14 14:01:11 +08:00
‘毛文春’
cbfeb09a22 修改 过滤不要需要验证的接口(path) 2023-03-13 17:45:29 +08:00
曾文豪
ef97488ea0 publish 0.8.4 2023-03-09 15:58:41 +08:00
曾文豪
8873053c06 perf: 优化脱敏工具,修复父类中脱敏注解无效的bug 2023-03-09 15:58:05 +08:00
曾文豪
a65ea27485 perf: 优化代码 2023-03-08 09:02:13 +08:00
曾文豪
4343601da1 perf: 更新changelog 2023-03-08 08:58:38 +08:00
曾文豪
f07e6d99e3 publish 0.8.3 2023-03-07 18:16:51 +08:00
曾文豪
fc4b3139aa perf: 调整文件上传的接口 2023-03-07 18:16:31 +08:00
曾文豪
fe9d107eef publish 0.8.2 2023-03-07 15:16:53 +08:00
曾文豪
0094bf2e69 perf: 加解密数据处理 2023-03-07 15:16:26 +08:00
曾文豪
c0fb149558 perf:添加一个是否成功的方法 2023-03-07 14:38:46 +08:00
曾文豪
eb55969063 publish 0.8.1 2023-03-07 09:52:48 +08:00
曾文豪
488c53def0 publish 0.8.0 2023-03-06 15:35:39 +08:00
曾文豪
c02e67f85f perf;对数据库文件排序后执行 2023-03-06 14:02:27 +08:00
曾文豪
9f62986a1e perf;优化log日志 2023-02-28 11:35:33 +08:00
曾文豪
07136a6679 publish 0.7.4 2023-02-28 11:32:45 +08:00
曾文豪
c3edb50e80 perf;区分token过期 2023-02-27 09:54:27 +08:00
曾文豪
aee1861630 publish 0.7.3 2023-02-26 18:57:10 +08:00
曾文豪
4196b2531d perf;PasswordUtils校验调整 2023-02-26 12:12:42 +08:00
曾文豪
dfaeacae92 perf;调整TsTokenConfig中的ignores 2023-02-26 11:10:51 +08:00
曾文豪
b304c48dd1 perf;调整TsTokenConfig中的ignores 2023-02-26 11:10:33 +08:00
曾文豪
d045534be6 perf;调整TsTokenConfig中的ignores 2023-02-26 11:09:05 +08:00
曾文豪
56b923f5db publish 0.7.2 2023-02-24 18:42:42 +08:00
曾文豪
f3e8231814 fixed:修复登录日志中未正确保存userId的bug 2023-02-24 12:02:32 +08:00
曾文豪
2ca04e654f perf:tokenignore提到类上面 2023-02-23 14:03:26 +08:00
曾文豪
149f4ab061 publish 0.7.1 2023-02-23 12:13:55 +08:00
曾文豪
a22c08738a publish 0.7.0 2023-02-23 11:57:01 +08:00
曾文豪
d28f3250e3 perf:优化脱敏类 2023-02-22 12:52:14 +08:00
曾文豪
bf3b88b43b publish 0.6.2 2023-02-22 12:16:51 +08:00
曾文豪
0a98e81109 perf:标记为false,可以不实现 2023-02-22 12:04:45 +08:00
曾文豪
e3c051d443 publish 0.6.1 2023-02-22 00:26:15 +08:00
曾文豪
282a46458a publish 40.6.1 2023-02-22 00:25:33 +08:00
曾文豪
637a9d1ace perf:增加数据库同步后的执行 2023-02-22 00:24:26 +08:00
曾文豪
959eff62df publish 0.6.0 2023-02-21 10:47:52 +08:00
曾文豪
fdbdf79383 perf:移除数据库备份方案 2023-02-21 10:47:12 +08:00
曾文豪
800c53c6fd perf:移除数据库备份方案 2023-02-21 10:47:05 +08:00
曾文豪
c3f4f91a37 feat:增加微信小程序登录 2023-02-21 10:45:44 +08:00
曾文豪
31f6babb97 perf:测试数据库备份 2023-02-21 09:25:32 +08:00
曾文豪
668e7069f7 perf:测试数据库备份 2023-02-21 09:22:40 +08:00
曾文豪
5cd4994624 perf:测试数据库备份 2023-02-21 09:14:27 +08:00
曾文豪
941bd0f65e perf:测试数据库备份 2023-02-21 09:11:45 +08:00
曾文豪
5cf6e1f8d4 perf:测试数据库备份 2023-02-21 09:09:25 +08:00
曾文豪
def1b4e06a perf:测试数据库备份 2023-02-21 09:08:19 +08:00
曾文豪
f5b8e989b7 perf:测试数据库备份 2023-02-21 09:06:53 +08:00
曾文豪
1918dfbaa0 perf:增加数据库备份 2023-02-20 18:25:36 +08:00
曾文豪
7fcc407514 perf:升级Ip2Region 2023-02-20 14:28:13 +08:00
曾文豪
b79895aa56 perf:.gitignore调整 2023-02-20 13:13:49 +08:00
曾文豪
4700d4e061 perf:调整ip2region存放目录 2023-02-20 13:10:37 +08:00
曾文豪
a8be751e65 publish 0.5.0 2023-02-17 17:15:45 +08:00
曾文豪
1b1073eab1 publish 0.4.1 2023-02-17 15:22:51 +08:00
曾文豪
56e2a66bdf fixed:修改sql文件执行过滤的判断方式 2023-02-17 15:22:11 +08:00
曾文豪
c5654474b0 perf:增加runtime目录,日志也移动到runtime目录中 2023-02-17 14:55:32 +08:00
曾文豪
a125c6f907 publish 0.4.0 2023-02-17 10:07:31 +08:00
曾文豪
a314351fc9 publish 0.0.4 2023-02-17 10:07:16 +08:00
‘毛文春’
23493afb2f 允许TokenIgnore标记在类上面 2023-02-17 10:03:56 +08:00
曾文豪
e8369320ab perf:调整插件 2023-02-17 09:54:56 +08:00
曾文豪
a19fa65166 chore:标记ademo模块不发布到maven仓库中 2023-02-16 13:17:15 +08:00
曾文豪
ea12290f03 perf:调整依赖 2023-02-15 15:47:34 +08:00
曾文豪
c6662407a7 Revert "publish 0.4.0"
This reverts commit f0493cea
2023-02-15 15:43:15 +08:00
曾文豪
29e45fff7f perf:调整pom 2023-02-09 15:03:35 +08:00
曾文豪
e7089d9cc5 publish 0.4.0 2023-02-09 14:47:04 +08:00
曾文豪
f0493cea77 publish 0.4.0 2023-02-09 14:39:27 +08:00
曾文豪
8854225934 publish 0.3.0 2023-02-08 19:22:17 +08:00
曾文豪
5ad35cefda publish 0.3.0 2023-02-08 19:20:45 +08:00
曾文豪
1921efa27b perf:移除插件代码 2023-02-08 19:19:00 +08:00
曾文豪
2e9de7ee64 publish 0.2.6 2023-02-08 13:30:22 +08:00
曾文豪
e352927396 publish 0.2.5 2023-02-08 13:19:50 +08:00
曾文豪
51b26c077d perf:更新新的脚本 2023-02-08 13:18:58 +08:00
曾文豪
2c5f55a876 publish 0.2.4 2023-02-07 10:04:06 +08:00
曾文豪
c52f7f5c77 perf:token有效期调整 2023-02-07 10:00:21 +08:00
曾文豪
7f46d2d371 perf:initScript增加执行成功的log 2023-02-07 09:40:15 +08:00
曾文豪
34d8201641 perf:调整ipdb的默认存放位置 2023-02-07 09:39:16 +08:00
曾文豪
92e1c1d9ef perf:文件路径生成调整 2023-02-07 09:32:24 +08:00
曾文豪
ee3748c361 perf:调整项目配置 2023-02-07 08:59:42 +08:00
曾文豪
439947caad publish 0.2.3 2023-02-01 16:43:04 +08:00
曾文豪
17706e8065 perf:删除无效配置 2023-02-01 12:08:15 +08:00
曾文豪
8853e3170d perf:删除无效配置 2023-02-01 12:07:49 +08:00
曾文豪
222f37afc1 publish 0.2.2 2023-02-01 12:05:20 +08:00
曾文豪
f8bc11d456 publish 0.2.1 2023-02-01 11:59:53 +08:00
123 changed files with 3695 additions and 1985 deletions

BIN
.DS_Store vendored Normal file

Binary file not shown.

3
.gitignore vendored
View File

@@ -4,4 +4,5 @@ rebel.xml
/.idea/
*.iml
/static/
/ipdb/
/config/
/runtime/

View File

@@ -9,14 +9,10 @@ deploy-jar:
rules:
- if: $CI_COMMIT_TAG
script:
- cd springboot-launcher
- mvn clean install
- cd ..
- mvn clean deploy -Dmaven.test.skip -DaltDeploymentRepository=master::default::file:/usr/local/nginx/html/kepai-repo
- cd /usr/local/nginx/html/kepai-repo
- mvn clean deploy -Dmaven.test.skip -DaltDeploymentRepository=master::default::file:$TAG_REPO_FOLDER
- cd $TAG_REPO_FOLDER
- git checkout master
- git pull
- git add .
- git commit -m "deploy $CI_PROJECT_NAME $CI_COMMIT_TAG"
- git push origin master

37
CHANGELOG.md Normal file
View File

@@ -0,0 +1,37 @@
## 0.9.3
> 1增加版本对比器防止某些情况下版本对比失效
>
## 0.8.3
### 调整
> 1优化返回数据加密
> 2上传文件接口调整统一为**application/json**格式;
## 0.8.0
### 调整
> 1移除**PasswordUtil**类,新增**EncryptConfig**配置;
> 2默认启用网络请求的加解密前端请配合接口使用。
## 0.7.4
### 新增
> 现在操作日志默认收集不包括GET请求使用方法名称和接口作为参数存储。如果存在OperationLog注解则使用注解的内容。
## 0.7.3
### 增加
> 1TsTokenConfig增加新的属性**ignorePaths**用于通过路径忽略token
> 2PasswordUtils增加密码复杂度校验方法
> 3PasswordUtils.verifyPassword增加登录次数限制10分钟内不能错误6次
>
### 调整
> 1TsTokenConfig中的**ignores**属性调整为**testMap**

4
README.md Normal file
View File

@@ -0,0 +1,4 @@
## 杭州铁晟科技有限公司基础项目
更新日志可点击查看[changelog](./CHANGELOG.md ':include')

69
pom.xml
View File

@@ -4,9 +4,9 @@
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>com.tiesheng</groupId>
<groupId>com.tiesheng.springboot-parent</groupId>
<artifactId>springboot-parent</artifactId>
<version>0.2.0</version>
<version>1.0.1</version>
<packaging>pom</packaging>
<name>springboot-parent</name>
<description>杭州铁晟科技有限公司基础依赖</description>
@@ -19,7 +19,7 @@
<modules>
<module>springboot-ademo</module>
<module>springboot-db-migration</module>
<module>springboot-database</module>
<module>springboot-login</module>
<module>springboot-web</module>
<module>springboot-util</module>
@@ -28,7 +28,6 @@
<module>springboot-message</module>
<module>springboot-encrypt</module>
<module>springboot-annotation</module>
<module>springboot-launcher</module>
</modules>
<properties>
@@ -56,63 +55,57 @@
<dependencyManagement>
<dependencies>
<dependency>
<groupId>com.tiesheng</groupId>
<artifactId>springboot-db-migration</artifactId>
<version>0.2.0</version>
<groupId>com.tiesheng.springboot-parent</groupId>
<artifactId>springboot-database</artifactId>
<version>1.0.1</version>
</dependency>
<dependency>
<groupId>com.tiesheng</groupId>
<groupId>com.tiesheng.springboot-parent</groupId>
<artifactId>springboot-login</artifactId>
<version>0.2.0</version>
<version>1.0.1</version>
</dependency>
<dependency>
<groupId>com.tiesheng</groupId>
<groupId>com.tiesheng.springboot-parent</groupId>
<artifactId>springboot-web</artifactId>
<version>0.2.0</version>
<version>1.0.1</version>
</dependency>
<dependency>
<groupId>com.tiesheng</groupId>
<groupId>com.tiesheng.springboot-parent</groupId>
<artifactId>springboot-util</artifactId>
<version>0.2.0</version>
<version>1.0.1</version>
</dependency>
<dependency>
<groupId>com.tiesheng</groupId>
<groupId>com.tiesheng.springboot-parent</groupId>
<artifactId>springboot-platform</artifactId>
<version>0.2.0</version>
<version>1.0.1</version>
</dependency>
<dependency>
<groupId>com.tiesheng</groupId>
<groupId>com.tiesheng.springboot-parent</groupId>
<artifactId>springboot-message</artifactId>
<version>0.2.0</version>
<version>1.0.1</version>
</dependency>
<dependency>
<groupId>com.tiesheng</groupId>
<groupId>com.tiesheng.springboot-parent</groupId>
<artifactId>springboot-encrypt</artifactId>
<version>0.2.0</version>
<version>1.0.1</version>
</dependency>
<dependency>
<groupId>com.tiesheng</groupId>
<groupId>com.tiesheng.springboot-parent</groupId>
<artifactId>springboot-annotation</artifactId>
<version>0.2.0</version>
<version>1.0.1</version>
</dependency>
<dependency>
<groupId>com.tiesheng</groupId>
<groupId>com.tiesheng.springboot-parent</groupId>
<artifactId>springboot-poi</artifactId>
<version>0.2.0</version>
</dependency>
<dependency>
<groupId>com.tiesheng</groupId>
<artifactId>springboot-launcher</artifactId>
<version>0.0.1</version>
<version>1.0.1</version>
</dependency>
<dependency>
@@ -124,22 +117,32 @@
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.5.1</version>
<version>3.5.3</version>
</dependency>
</dependencies>
</dependencyManagement>
<pluginRepositories>
<pluginRepository>
<id>kepai-repo-plugin</id>
<url>http://git.kepai365.com/tiesheng/repository/raw/master</url>
</pluginRepository>
</pluginRepositories>
<build>
<pluginManagement>
<plugins>
<plugin>
<groupId>com.tiesheng</groupId>
<artifactId>launcher-maven-plugin</artifactId>
<groupId>com.tiesheng.springboot-plugin</groupId>
<artifactId>tiesheng-maven-plugin</artifactId>
<version>0.0.5</version>
<executions>
<execution>
<goals>
<goal>initScript</goal>
<goal>initStartScript</goal>
<goal>mysqlComparison</goal>
<goal>mysqlDoc</goal>
</goals>
</execution>
</executions>

BIN
springboot-ademo/.DS_Store vendored Normal file

Binary file not shown.

View File

@@ -4,42 +4,47 @@
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>
<parent>
<groupId>com.tiesheng</groupId>
<groupId>com.tiesheng.springboot-parent</groupId>
<artifactId>springboot-parent</artifactId>
<version>0.2.0</version>
<version>1.0.1</version>
</parent>
<artifactId>springboot-ademo</artifactId>
<version>1.0.0</version>
<version>1.0.1</version>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<!-- 该模块不发布到maven仓库 -->
<maven.deploy.skip>true</maven.deploy.skip>
</properties>
<dependencies>
<dependency>
<groupId>com.tiesheng</groupId>
<groupId>com.tiesheng.springboot-parent</groupId>
<artifactId>springboot-web</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>easyexcel</artifactId>
</dependency>
</dependencies>
<repositories>
<repository>
<id>kepai-repo</id>
<url>http://git.kepai365.com/zeng_wenhao/kepai-repo/raw/master</url>
<releases>
<enabled>true</enabled>
</releases>
<url>http://git.kepai365.com/tiesheng/repository/raw/master</url>
</repository>
</repositories>
<build>
<plugins>
<plugin>
<groupId>com.tiesheng</groupId>
<artifactId>launcher-maven-plugin</artifactId>
<groupId>com.tiesheng.springboot-plugin</groupId>
<artifactId>tiesheng-maven-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.springframework.boot</groupId>

View File

@@ -3,6 +3,7 @@ package com.tiesheng.demo;
import com.tiesheng.core.EnableTieshengWeb;
import com.tiesheng.demo.config.DemoWebConfigurer;
import com.tiesheng.encrypt.EnableEncryptConfig;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.transaction.annotation.EnableTransactionManagement;
@@ -13,6 +14,7 @@ import org.springframework.transaction.annotation.EnableTransactionManagement;
@EnableTransactionManagement
@SpringBootApplication
@EnableTieshengWeb(webConfigurer = DemoWebConfigurer.class)
//@EnableEncryptConfig
public class DemoApplication {
public static void main(String[] args) {

View File

@@ -1,7 +1,7 @@
package com.tiesheng.demo.config;
import cn.hutool.core.util.StrUtil;
import com.tiesheng.core.pojos.CurrentWebUser;
import com.tiesheng.core.pojos.RequestUserInfo;
import com.tiesheng.core.pojos.dao.CorePlatformUnique;
import com.tiesheng.core.service.TieshengWebConfigurer;
import com.tiesheng.login.config.token.bean.TokenBean;
@@ -19,35 +19,36 @@ public class DemoWebConfigurer implements TieshengWebConfigurer {
GlobalConfig globalConfig;
@Override
public CurrentWebUser getCurrentUserName(String userId) {
return null;
public RequestUserInfo getCurrentUserName(TokenBean tokenBean) {
RequestUserInfo info = new RequestUserInfo();
info.setId("1");
info.setName("test");
return info;
}
@Override
public LoginConfigurer loginConfigurer() {
return new LoginConfigurer() {
@Override
public TokenBean doLogin(CorePlatformUnique platformUnique, String to) {
public TokenBean login(CorePlatformUnique platformUnique) {
TokenBean tokenBean = null;
if (!StrUtil.isEmpty(platformUnique.getUserId())) {
tokenBean = new TokenBean(platformUnique.getUserId(), "", globalConfig.getService());
} else {
// 获取用户信息判断是否可登录
// 默认跳转到mobile
to = StrUtil.emptyToDefault(to, "mobile");
}
TokenBean tokenBean = null;
if (!StrUtil.isEmpty(platformUnique.getUserId())) {
tokenBean = new TokenBean(platformUnique.getUserId(), to, globalConfig.getService());
} else {
// 获取用户信息判断是否可登录
}
return tokenBean;
}
@Override
public void redirect(TokenBean bean, String to, String extra, HttpServletResponse response) {
if (Objects.equals(bean.getEnvironmentType(), "mobile")) {
globalConfig.redirect("mobile", "/?token=" + bean.toToken(), response);
}
}
};
return tokenBean;
}
@Override
public void redirect(TokenBean bean, String to, String extra, HttpServletResponse response) {
// 默认跳转到mobile
to = StrUtil.emptyToDefault(to, "mobile");
bean.setEnvironmentType(to);
if (Objects.equals(bean.getEnvironmentType(), "mobile")) {
globalConfig.redirect("mobile", "/?token=" + bean.toToken(), response);
}
}
}

View File

@@ -0,0 +1,32 @@
package com.tiesheng.demo.config;
import com.tiesheng.core.service.CoreConfigService;
import com.tiesheng.core.service.CoreJobService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
/**
* @author hao
*/
@Component
public class TestJobConfig {
@Autowired
CoreJobService coreJobService;
@Autowired
CoreConfigService coreConfigService;
@PostConstruct
public void init() {
coreConfigService.refreshFunc("230328001", "demo", "辅导员统计", "辅导员责任班级,学生展示");
// 辅导员职位
coreJobService.refresh("class_fdy", "辅导员", "辅导员", 1);
}
}

View File

@@ -1,10 +1,26 @@
package com.tiesheng.demo.controller;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.TimeInterval;
import cn.hutool.core.thread.ThreadUtil;
import cn.hutool.json.JSONUtil;
import cn.hutool.log.LogFactory;
import cn.hutool.poi.excel.ExcelUtil;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.read.listener.ReadListener;
import com.tiesheng.annotation.token.TokenIgnore;
import com.tiesheng.message.config.aliyun.AliyunSmsConfig;
import com.tiesheng.core.service.CoreLogService;
import com.tiesheng.core.service.CoreMessageService;
import com.tiesheng.core.util.ProcessImportConsumer;
import com.tiesheng.demo.pojos.PoiBean;
import com.tiesheng.demo.pojos.TestFile;
import com.tiesheng.login.config.token.TsTokenConfig;
import com.tiesheng.login.config.token.bean.TokenBean;
import com.tiesheng.message.pojos.MessageReqResp;
import com.tiesheng.util.config.EncryptConfig;
import com.tiesheng.util.config.GlobalConfig;
import com.tiesheng.util.config.Ip2regionConfig;
import com.tiesheng.util.pojos.ApiResp;
import com.tiesheng.util.pojos.FileUploadPath;
import org.springframework.beans.factory.annotation.Autowired;
@@ -12,6 +28,9 @@ import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
/**
* @author hao
@@ -23,17 +42,49 @@ public class TestController {
@Autowired
GlobalConfig globalConfig;
@Autowired
AliyunSmsConfig aliyunSmsConfig;
TsTokenConfig tsTokenConfig;
@Autowired
Ip2regionConfig ip2regionConfig;
@Autowired
EncryptConfig encryptConfig;
@Autowired
CoreMessageService coreMessageService;
@Autowired
CoreLogService coreLogService;
@RequestMapping("/index")
@TokenIgnore
public ApiResp<String> index() {
TokenBean tokenBean = new TokenBean("11", "", "fdfd");
LogFactory.get().info(tokenBean.toToken());
return ApiResp.respOK("hello world");
}
@RequestMapping("/redirect")
@TokenIgnore
public void redirect(HttpServletResponse response) {
ArrayList<String> strings = CollUtil.newArrayList("11111","22222");
coreLogService.addProcess("fdfd", strings, new ProcessImportConsumer<String>() {
@Override
public int accept(List<String> list) {
LogFactory.get().info("list: " + list.size());
return 0;
}
@Override
public String getFailFile() {
LogFactory.get().info("getFailFile: " + strings.size());
return null;
}
});
LogFactory.get().info("strings: " + strings.size());
// tsTokenConfig.validToken("eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJleHAiOjE2NzYwMDY4NzUsImlkIjoiMSIsImVudmlyb25tZW50VHlwZSI6Im1vYmlsZSIsInNlcnZpY2UiOiJjb250ZXN0LXJlc2VydmUiLCJleHRyYSI6IiJ9.nsfxEFpCNHC7eNCS5DJXdu1VDdnHrTjSfgrozND70Lc", true);
globalConfig.redirect("mobile", "/test", response);
}
@@ -41,14 +92,15 @@ public class TestController {
@RequestMapping("/send")
@TokenIgnore
public ApiResp<MessageReqResp> sendMessage() {
MessageReqResp reqResp = aliyunSmsConfig.sendSms("13567116463", "SMS_154950909",
JSONUtil.createObj().putOpt("code", "123456"));
MessageReqResp reqResp = coreMessageService.send("13567116463", "SMS_154950909",
JSONUtil.createObj().putOpt("code", "123456"), "sms");
return ApiResp.respOK(reqResp);
}
@RequestMapping("/export")
@TokenIgnore
public ApiResp<String> export() {
// List<TestFile> list = new ArrayList<>();
@@ -66,8 +118,78 @@ public class TestController {
@RequestMapping("/uploadPath")
@TokenIgnore
public ApiResp<String> uploadPath() {
FileUploadPath uploadPath = FileUploadPath.get("http://scv6.tmp.kepai365.ltd/upload/2023-01/2b4b6b7b-70d0-4683-859a-f799adc4f04c.xls");
FileUploadPath uploadPath = FileUploadPath.file("http://scv6.tmp.kepai365.ltd/upload/2023-01/2b4b6b7b-70d0-4683-859a-f799adc4f04c.xls");
return ApiResp.respOK(uploadPath.getAbsolutePath());
}
@RequestMapping("searchIP")
@TokenIgnore
public ApiResp<String> searchIp() {
String search = ip2regionConfig.search("127.0.0.1");
return ApiResp.respOK(search);
}
@RequestMapping("desensitize")
@TokenIgnore
public ApiResp<List<TestFile>> desensitize() {
TestFile file = new TestFile("11111");
file.setTest("111111");
TestFile file1 = new TestFile("22222");
file1.setTest("22222");
return ApiResp.respOK(CollUtil.newArrayList(file, file1));
}
@RequestMapping("passwd")
@TokenIgnore
public ApiResp<String> passwd() {
String passwdCreate = encryptConfig.passwdCreate("12345Zeng!", "");
LogFactory.get().info(passwdCreate);
encryptConfig.passwdVerify("12345Zeng!", passwdCreate);
return ApiResp.respOK("");
}
@RequestMapping("poi")
@TokenIgnore
public ApiResp<String> poi() {
TimeInterval timeInterval = new TimeInterval();
FileUploadPath file = FileUploadPath.file("/upload/test.xlsx");
EasyExcel.read(new File(file.getAbsolutePath()), PoiBean.class, new ReadListener<PoiBean>() {
@Override
public void invoke(PoiBean poiBean, AnalysisContext analysisContext) {
}
@Override
public void doAfterAllAnalysed(AnalysisContext analysisContext) {
}
}).sheet().doRead();
System.out.println("timeInterval: " + timeInterval.interval());
return ApiResp.respOK("");
}
@RequestMapping("poiTool")
@TokenIgnore
public ApiResp<String> poiTool() {
TimeInterval timeInterval = new TimeInterval();
FileUploadPath file = FileUploadPath.file("/upload/test.xlsx");
ExcelUtil.getReader(new File(file.getAbsolutePath())).read();
System.out.println("timeInterval: " + timeInterval.interval());
return ApiResp.respOK("");
}
}

View File

@@ -0,0 +1,75 @@
package com.tiesheng.demo.pojos;
import com.alibaba.excel.annotation.ExcelProperty;
public class PoiBean {
@ExcelProperty("学院")
private String college;
private String type;
private String name;
private String no;
private String sex;
private String fdy;
private String fdyNo;
///////////////////////////////////////////////////////////////////////////
// setter\getter
///////////////////////////////////////////////////////////////////////////
public String getCollege() {
return college;
}
public void setCollege(String college) {
this.college = college;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getNo() {
return no;
}
public void setNo(String no) {
this.no = no;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public String getFdy() {
return fdy;
}
public void setFdy(String fdy) {
this.fdy = fdy;
}
public String getFdyNo() {
return fdyNo;
}
public void setFdyNo(String fdyNo) {
this.fdyNo = fdyNo;
}
}

View File

@@ -1,27 +1,21 @@
//package com.tiesheng.demo.pojos;
//
//import com.alibaba.excel.annotation.ExcelProperty;
//import com.tiesheng.poi.pojos.PoiWriteBase;
//
//public class TestFile implements PoiWriteBase {
//
//
// @ExcelProperty("测试")
// private String test;
//
// public TestFile(String test) {
// this.test = test;
// }
//
// ///////////////////////////////////////////////////////////////////////////
// // setter、getter
// ///////////////////////////////////////////////////////////////////////////
//
// public String getTest() {
// return test;
// }
//
// public void setTest(String test) {
// this.test = test;
// }
//}
package com.tiesheng.demo.pojos;
import com.tiesheng.poi.pojos.PoiWriteBase;
public class TestFile extends TestParent implements PoiWriteBase {
private String name;
public TestFile(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}

View File

@@ -0,0 +1,33 @@
package com.tiesheng.demo.pojos;
import com.tiesheng.annotation.desensitize.Desensitize;
import com.tiesheng.poi.pojos.PoiWriteBase;
public class TestParent implements PoiWriteBase {
private String id;
@Desensitize()
private String test;
///////////////////////////////////////////////////////////////////////////
// setter、getter
///////////////////////////////////////////////////////////////////////////
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getTest() {
return test;
}
public void setTest(String test) {
this.test = test;
}
}

View File

@@ -0,0 +1,28 @@
## Spring配置
spring:
## 数据库配置
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://47.96.30.85:3306/com_tiesheng_web?useSSL=false&useUnicode=true&characterEncoding=UTF-8&autoReconnect=true&queryTimeout=5400&allowMultiQueries=true&serverTimezone=GMT%2B8
username: com_tiesheng_web
password: 4Xo$XheGFc
platform:
wxmp:
global:
app-id: wxa0343fe519824651
app-secret: 776f089ba70bcd66455a7c7893f810b9
tiesheng:
token:
test-map:
"1111":
id: "1111"
global:
version: 2
host: http://localhost:8100
aliyun:
access-key-id: LTAI5tJtbgBCnTY5eS4SmrTf
access-key-secret: JIHqpRUFffCHhXaJEVvWN31WcexWqG
sign-name: 阿里云短信测试

View File

@@ -1,28 +1,26 @@
server:
compression:
enabled: true
port: 8100
## Spring配置
spring:
## 数据库配置
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://47.96.30.85:3306/com_tiesheng_web?useSSL=false&useUnicode=true&characterEncoding=UTF-8&autoReconnect=true&queryTimeout=5400&allowMultiQueries=true&serverTimezone=GMT%2B8
username: com_tiesheng_web
password: 4Xo$XheGFc
platform:
wxmp:
global:
app-id: wxa0343fe519824651
app-secret: 776f089ba70bcd66455a7c7893f810b9
servlet:
multipart:
max-file-size: 20MB
web:
resources:
static-locations: classpath:/static/,file:static/
mvc:
pathmatch:
matching-strategy: ant_path_matcher
## 日志
logging:
file:
name: runtime/logs/tiesheng.log
tiesheng:
token:
ignores:
"1111":
id: "1111"
global:
version: 2
host: http://localhost:8080
aliyun:
access-key-id: LTAI5tJtbgBCnTY5eS4SmrTf
access-key-secret: JIHqpRUFffCHhXaJEVvWN31WcexWqG
sign-name: 阿里云短信测试
ignore-paths:
- /test/index

View File

@@ -0,0 +1,16 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8"/>
<meta content="IE=edge" http-equiv="X-UA-Compatible"/>
<meta
content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0"
name="viewport"
/>
</head>
<body>
<script type="text/javascript">
</script>
</body>
</html>

View File

@@ -0,0 +1,17 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8"/>
<meta content="IE=edge" http-equiv="X-UA-Compatible"/>
<meta
content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0"
name="viewport"
/>
</head>
<body>
<script type="text/javascript">
</script>
</body>
</html>

View File

@@ -1,37 +0,0 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8"/>
<meta content="IE=edge" http-equiv="X-UA-Compatible"/>
<meta
content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0"
name="viewport"
/>
<title>钉钉授权</title>
</head>
<body>
<script src="dingtalk.open.js"></script>
<script type="text/javascript">
function getQueryString(name) {
var reg = new RegExp("(^|&)" + name + "=([^&]*)(&|$)", "i");
var r = window.location.search.substr(1).match(reg);
if (r != null) return decodeURI(r[2]);
return null;
}
dd.runtime.permission.requestAuthCode({
corpId: getQueryString("corpId"),
onSuccess: function (result) {
let search = window.location.search + "&code=" + result.code;
window.location.href = "/auth/ding/oauth2/" + getQueryString("service") + search;
},
onFail: function (err) {
window.location.href = "./error.html?message=" + JSON.stringify(err);
}
})
</script>
</body>
</html>

View File

@@ -1,37 +0,0 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8"/>
<meta content="IE=edge" http-equiv="X-UA-Compatible"/>
<meta
content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0"
name="viewport"
/>
<title>钉钉授权</title>
</head>
<body>
<script src="dingtalk.open.js"></script>
<script type="text/javascript">
function getQueryString(name) {
var reg = new RegExp("(^|&)" + name + "=([^&]*)(&|$)", "i");
var r = window.location.search.substr(1).match(reg);
if (r != null) return decodeURI(r[2]);
return null;
}
dd.runtime.permission.requestAuthCode({
corpId: getQueryString("corpId"),
onSuccess: function (result) {
let search = window.location.search + "&code=" + result.code;
window.location.href = "/auth/ding/oauth2/" + getQueryString("service") + search;
},
onFail: function (err) {
window.location.href = "./error.html?message=" + JSON.stringify(err);
}
})
</script>
</body>
</html>

View File

@@ -4,9 +4,9 @@
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>
<parent>
<groupId>com.tiesheng</groupId>
<groupId>com.tiesheng.springboot-parent</groupId>
<artifactId>springboot-parent</artifactId>
<version>0.2.0</version>
<version>1.0.1</version>
</parent>
<artifactId>springboot-annotation</artifactId>

View File

@@ -0,0 +1,16 @@
package com.tiesheng.annotation.desensitize;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
/**
* @author hao
*/
@Retention(RetentionPolicy.RUNTIME)
public @interface Desensitize {
int prefix() default 1;
int suffix() default 1;
}

View File

@@ -1,12 +0,0 @@
package com.tiesheng.annotation.encrypt;
import java.lang.annotation.*;
/**
* @author hao
*/
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface EncryptedRespBody {
}

View File

@@ -5,7 +5,7 @@ import java.lang.annotation.*;
/**
* @author hao
*/
@Target(ElementType.METHOD)
@Target({ElementType.METHOD,ElementType.TYPE})
@Documented
@Retention(RetentionPolicy.RUNTIME)
public @interface TokenIgnore {

View File

@@ -4,12 +4,12 @@
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>
<parent>
<groupId>com.tiesheng</groupId>
<groupId>com.tiesheng.springboot-parent</groupId>
<artifactId>springboot-parent</artifactId>
<version>0.2.0</version>
<version>1.0.1</version>
</parent>
<artifactId>springboot-db-migration</artifactId>
<artifactId>springboot-database</artifactId>
<properties>
<maven.compiler.source>8</maven.compiler.source>
@@ -19,7 +19,7 @@
<dependencies>
<dependency>
<groupId>com.tiesheng</groupId>
<groupId>com.tiesheng.springboot-parent</groupId>
<artifactId>springboot-util</artifactId>
</dependency>

View File

@@ -0,0 +1,12 @@
package com.tiesheng.database;
import org.springframework.context.annotation.ComponentScan;
/**
* @author hao
*/
@ComponentScan({
"com.tiesheng.database.**.*"
})
public class DatabaseAutoConfigurer {
}

View File

@@ -0,0 +1,72 @@
package com.tiesheng.database.config;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.RuntimeUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.extra.spring.SpringUtil;
import cn.hutool.log.LogFactory;
import com.tiesheng.database.utls.TieshengDbUtil;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;
import java.util.Date;
/**
* @author hao
*/
@Configuration
@ConfigurationProperties(prefix = "tiesheng.db-backup")
public class DbBackupConfig {
/**
* 数据库备份的路径
*/
private String path = "/root/backup/";
/**
* 备份文件的时间格式
*/
private String format = "yyyyMMdd";
public void dbBackup() {
String url = SpringUtil.getProperty("spring.datasource.url");
String username = SpringUtil.getProperty("spring.datasource.username");
String password = SpringUtil.getProperty("spring.datasource.password");
String dbName = TieshengDbUtil.getTableSchema(url);
try {
String saveFile = StrUtil.format("{}{}/{}.sql", getPath(), dbName, DateUtil.format(new Date(), format));
FileUtil.mkParentDirs(saveFile);
String cmd = StrUtil.format("mysqldump -u{} -p {} > {}", username, dbName, saveFile);
LogFactory.get().info("cmd: " + cmd);
String forStr = RuntimeUtil.execForStr(cmd);
LogFactory.get().info("dbBackup: " + forStr);
forStr = RuntimeUtil.execForStr(password);
LogFactory.get().info("dbBackup: " + forStr);
} catch (Exception ignored) {
}
}
///////////////////////////////////////////////////////////////////////////
// setter\getter
///////////////////////////////////////////////////////////////////////////
public String getPath() {
return path;
}
public void setPath(String path) {
this.path = path;
}
public String getFormat() {
return format;
}
public void setFormat(String format) {
this.format = format;
}
}

View File

@@ -1,4 +1,4 @@
package com.tiesheng.migration.config;
package com.tiesheng.database.config;
import cn.hutool.core.collection.CollUtil;
@@ -21,7 +21,7 @@ public class DbMigrationConfig {
private String table = "core_config_db";
private List<String> locations = CollUtil.newArrayList("classpath*:db/migration/*.sql");
private String ignoreSqls = "drop,delete";
private String ignoreSqls = "drop table,delete from";
/**
* 检查数据库是否存在

View File

@@ -0,0 +1,16 @@
package com.tiesheng.database.service;
import org.springframework.stereotype.Component;
/**
* @author hao
*/
@Component
public interface DbDataInitializer {
/**
* 初始化数据
*/
void init();
}

View File

@@ -1,15 +1,15 @@
package com.tiesheng.migration.service;
package com.tiesheng.database.service;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.IoUtil;
import cn.hutool.core.lang.func.VoidFunc1;
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.db.Db;
import cn.hutool.db.Entity;
import com.tiesheng.migration.config.DbMigrationConfig;
import cn.hutool.log.LogFactory;
import com.tiesheng.database.config.DbMigrationConfig;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.web.servlet.ServletContextInitializer;
import org.springframework.core.io.Resource;
@@ -20,7 +20,10 @@ import javax.servlet.ServletContext;
import javax.sql.DataSource;
import java.io.InputStream;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.atomic.AtomicReference;
import java.util.zip.Checksum;
/**
@@ -35,12 +38,17 @@ public class DbMigrationInitializer implements ServletContextInitializer {
DataSource dataSource;
@Autowired
DbMigrationConfig dbMigrationConfig;
@Autowired(required = false)
List<DbDataInitializer> dbDataInitializerList;
@Override
public void onStartup(ServletContext servletContext) {
try {
startDeal();
if (dbDataInitializerList != null) {
dbDataInitializerList.forEach(DbDataInitializer::init);
}
} catch (Exception ignore) {
}
}
@@ -56,14 +64,16 @@ public class DbMigrationInitializer implements ServletContextInitializer {
dbMigrationConfig.checkDbExists(coreDb);
PathMatchingResourcePatternResolver patternResolver = new PathMatchingResourcePatternResolver();
List<Resource> resourceList = new ArrayList<>();
for (String location : dbMigrationConfig.getLocations()) {
Resource[] resources = patternResolver.getResources(location);
if (ArrayUtil.isEmpty(resources)) {
return;
}
for (Resource resource : resources) {
migrationByResource(resource, coreDb);
}
resourceList.addAll(Arrays.asList(resources));
}
// 排序后执行sql
resourceList.sort((o1, o2) -> StrUtil.compare(o1.getFilename(), o2.getFilename(), true));
for (Resource resource : resourceList) {
migrationByResource(resource, coreDb);
}
}
@@ -84,6 +94,8 @@ public class DbMigrationInitializer implements ServletContextInitializer {
if (entity == null) {
return;
}
AtomicReference<Integer> success= new AtomicReference<>(0);
AtomicReference<Integer> fail= new AtomicReference<>(0);
db.tx((VoidFunc1<Db>) parameter -> {
List<String> split = StrUtil.split(readUtf8, ";");
for (String sql : split) {
@@ -91,16 +103,18 @@ public class DbMigrationInitializer implements ServletContextInitializer {
if (StrUtil.isEmpty(sql)) {
continue;
}
if (StrUtil.startWithAnyIgnoreCase(sql, StrUtil.splitToArray(dbMigrationConfig.getIgnoreSqls(), ","))) {
if (StrUtil.containsAnyIgnoreCase(sql, StrUtil.splitToArray(dbMigrationConfig.getIgnoreSqls(), ","))) {
continue;
}
try {
parameter.execute(sql);
success.getAndSet(success.get() + 1);
} catch (Exception ignore) {
fail.getAndSet(fail.get() + 1);
}
}
});
LogFactory.get().info("执行sql文件{},成功数:{},失败数:{}。",filename,success.get(),fail.get());
entity.set("checksum", checksum.getValue());
entity.set("update_time", DateUtil.date());
db.update(entity, Entity.create(dbMigrationConfig.getTable()).set("id", entity.get("id")));

View File

@@ -0,0 +1,17 @@
package com.tiesheng.database.utls;
import cn.hutool.core.util.StrUtil;
public class TieshengDbUtil {
/**
* 通过url获取table_schema
*
* @param url
* @return
*/
public static String getTableSchema(String url) {
return StrUtil.sub(url, url.lastIndexOf('/') + 1, StrUtil.indexOf(url, '?'));
}
}

View File

@@ -1,12 +0,0 @@
package com.tiesheng.migration;
import org.springframework.context.annotation.ComponentScan;
/**
* @author hao
*/
@ComponentScan({
"com.tiesheng.migration.**.*"
})
public class MigrationAutoConfigurer {
}

View File

@@ -4,9 +4,9 @@
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>
<parent>
<groupId>com.tiesheng</groupId>
<groupId>com.tiesheng.springboot-parent</groupId>
<artifactId>springboot-parent</artifactId>
<version>0.2.0</version>
<version>1.0.1</version>
</parent>
<artifactId>springboot-encrypt</artifactId>
@@ -18,11 +18,6 @@
</properties>
<dependencies>
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcprov-jdk15to18</artifactId>
<version>1.68</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
@@ -31,12 +26,12 @@
</dependency>
<dependency>
<groupId>com.tiesheng</groupId>
<groupId>com.tiesheng.springboot-parent</groupId>
<artifactId>springboot-util</artifactId>
</dependency>
<dependency>
<groupId>com.tiesheng</groupId>
<groupId>com.tiesheng.springboot-parent</groupId>
<artifactId>springboot-annotation</artifactId>
</dependency>

View File

@@ -1,20 +1,21 @@
package com.tiesheng.encrypt;
import com.tiesheng.encrypt.config.EncryptConfig;
import com.tiesheng.encrypt.config.EncryptRequestBodyAdvice;
import com.tiesheng.encrypt.config.DecryptRequestBodyAdvice;
import com.tiesheng.encrypt.config.EncryptResponseBodyAdvice;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import java.lang.annotation.*;
/**
* @author hao
*/
@Configuration
@ComponentScan(basePackageClasses = {
EncryptConfig.class,
EncryptRequestBodyAdvice.class,
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE})
@Documented
@Import({
DecryptRequestBodyAdvice.class,
EncryptResponseBodyAdvice.class,
})
public class EnableEncryptConfig {
public @interface EnableEncryptConfig {
}

View File

@@ -3,13 +3,8 @@ package com.tiesheng.encrypt.config;
import cn.hutool.core.io.IoUtil;
import cn.hutool.core.util.CharsetUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.ECKeyUtil;
import cn.hutool.crypto.SmUtil;
import cn.hutool.crypto.asymmetric.KeyType;
import cn.hutool.crypto.asymmetric.SM2;
import cn.hutool.json.JSONUtil;
import org.bouncycastle.crypto.params.ECPrivateKeyParameters;
import org.bouncycastle.crypto.params.ECPublicKeyParameters;
import com.tiesheng.util.config.EncryptConfig;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.MethodParameter;
import org.springframework.http.HttpHeaders;
@@ -26,7 +21,7 @@ import java.nio.charset.Charset;
* @author hao
*/
@ControllerAdvice
public class EncryptRequestBodyAdvice implements RequestBodyAdvice {
public class DecryptRequestBodyAdvice implements RequestBodyAdvice {
@Autowired
@@ -42,12 +37,8 @@ public class EncryptRequestBodyAdvice implements RequestBodyAdvice {
public HttpInputMessage beforeBodyRead(HttpInputMessage inputMessage, MethodParameter parameter, Type targetType,
Class<? extends HttpMessageConverter<?>> converterType) {
if (!encryptConfig.isEnable()) {
return inputMessage;
}
try {
return new DecryptHttpInputMessage(inputMessage, encryptConfig.getPrivateQ());
return new DecryptHttpInputMessage(inputMessage, encryptConfig);
} catch (Exception ignore) {
}
@@ -72,16 +63,12 @@ public class EncryptRequestBodyAdvice implements RequestBodyAdvice {
private HttpHeaders headers;
private InputStream body;
DecryptHttpInputMessage(HttpInputMessage inputMessage, String privateQ) throws Exception {
DecryptHttpInputMessage(HttpInputMessage inputMessage, EncryptConfig encryptConfig) throws Exception {
this.headers = inputMessage.getHeaders();
String bodyStr = IoUtil.read(inputMessage.getBody(), CharsetUtil.CHARSET_UTF_8);
String encryptData = JSONUtil.parseObj(bodyStr).getStr("encryptData");
if (!StrUtil.isEmpty(encryptData)) {
// 部分语言加密之后缺少04前缀如果解密失败可尝试增加04
ECPrivateKeyParameters privateKeyParameters = ECKeyUtil.toSm2PrivateParams(privateQ);
ECPublicKeyParameters publicKeyParameters = ECKeyUtil.getPublicParams(privateKeyParameters);
SM2 sm2 = SmUtil.sm2(privateKeyParameters, publicKeyParameters);
String decrypt = sm2.decryptStr(encryptData, KeyType.PrivateKey);
String decrypt = encryptConfig.decrypt(encryptData);
this.body = IoUtil.toStream(decrypt, Charset.defaultCharset());
} else {
this.body = IoUtil.toStream(bodyStr, Charset.defaultCharset());

View File

@@ -1,44 +0,0 @@
package com.tiesheng.encrypt.config;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;
/**
* @author hao
*/
@Configuration
@ConfigurationProperties(prefix = "tiesheng.encrypt")
public class EncryptConfig {
public String publicD;
public String privateQ;
private boolean enable = false;
///////////////////////////////////////////////////////////////////////////
// setter\getter
///////////////////////////////////////////////////////////////////////////
public boolean isEnable() {
return enable;
}
public void setEnable(boolean enable) {
this.enable = enable;
}
public String getPublicD() {
return publicD;
}
public void setPublicD(String publicD) {
this.publicD = publicD;
}
public String getPrivateQ() {
return privateQ;
}
public void setPrivateQ(String privateQ) {
this.privateQ = privateQ;
}
}

View File

@@ -1,17 +1,10 @@
package com.tiesheng.encrypt.config;
import cn.hutool.core.annotation.AnnotationUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.ECKeyUtil;
import cn.hutool.crypto.SmUtil;
import cn.hutool.crypto.asymmetric.KeyType;
import cn.hutool.crypto.asymmetric.SM2;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import cn.hutool.log.LogFactory;
import com.tiesheng.annotation.encrypt.EncryptedRespBody;
import org.bouncycastle.crypto.params.ECPrivateKeyParameters;
import org.bouncycastle.crypto.params.ECPublicKeyParameters;
import com.tiesheng.util.CommonUtil;
import com.tiesheng.util.config.EncryptConfig;
import com.tiesheng.util.pojos.ApiResp;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.MethodParameter;
import org.springframework.http.MediaType;
@@ -19,6 +12,7 @@ import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;
@@ -26,50 +20,30 @@ import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;
* @author hao
*/
@ControllerAdvice
public class EncryptResponseBodyAdvice implements ResponseBodyAdvice<Object> {
public class EncryptResponseBodyAdvice implements ResponseBodyAdvice<ApiResp> {
@Autowired
EncryptConfig encryptConfig;
@Override
public boolean supports(MethodParameter returnType, Class<? extends HttpMessageConverter<?>> converterType) {
return true;
return AnnotationUtil.getAnnotation(returnType.getContainingClass(), RestController.class) != null;
}
@Override
public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType, Class<? extends
public ApiResp beforeBodyWrite(ApiResp body, MethodParameter returnType, MediaType selectedContentType, Class<? extends
HttpMessageConverter<?>> selectedConverterType, ServerHttpRequest request, ServerHttpResponse response) {
if (!encryptConfig.isEnable()) {
return body;
}
boolean encrypt = AnnotationUtil.getAnnotation(returnType.getContainingClass(), EncryptedRespBody.class) != null;
if (!encrypt) {
return body;
}
try {
String content = JSONUtil.toJsonStr(body);
String respData = JSONUtil.parseObj(content).getStr("data");
if (StrUtil.isEmpty(respData)) {
// 无需加密
Object data = body.getData();
if (data == null || !body.successful()) {
return body;
}
JSONObject resp = JSONUtil.parseObj(content);
resp.set("encrypted", true);
if (resp.getInt("code") == 200) {
// 用公钥进行加密
ECPrivateKeyParameters privateKeyParameters = ECKeyUtil.toSm2PrivateParams(encryptConfig.getPrivateQ());
ECPublicKeyParameters publicKeyParameters = ECKeyUtil.getPublicParams(privateKeyParameters);
SM2 sm2 = SmUtil.sm2(privateKeyParameters, publicKeyParameters);
String decrypt = sm2.encryptHex(respData, KeyType.PublicKey);
resp.set("data", decrypt.substring(2));
}
return resp;
body.setEncrypt(true);
body.setData(encryptConfig.encrypt(CommonUtil.writeJsonString(data)));
return body;
} catch (Exception var17) {
LogFactory.get().info("加密数据异常", var17);
}

View File

@@ -1,32 +0,0 @@
<?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>com.tiesheng</groupId>
<artifactId>launcher-maven-plugin</artifactId>
<packaging>maven-plugin</packaging>
<version>0.0.1</version>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-plugin-api</artifactId>
<version>3.5.2</version>
</dependency>
<dependency>
<groupId>org.apache.maven.plugin-tools</groupId>
<artifactId>maven-plugin-annotations</artifactId>
<version>3.5.2</version>
</dependency>
</dependencies>
</project>

View File

@@ -1,72 +0,0 @@
package com.tiesheng.launcher;
import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugins.annotations.LifecyclePhase;
import org.apache.maven.plugins.annotations.Mojo;
import org.apache.maven.plugins.annotations.Parameter;
import java.io.*;
import java.nio.charset.StandardCharsets;
/**
* 指定调用本类execute()方法的目标
**/
@Mojo(name = "initScript", defaultPhase = LifecyclePhase.PREPARE_PACKAGE)
public class CopyLauncherScriptMojo extends AbstractMojo {
@Parameter(defaultValue = "${basedir}/target", required = true)
private File outputDirectory;
public void setOutputDirectory(File outputDirectory) {
this.outputDirectory = outputDirectory;
}
@Override
public void execute() throws MojoExecutionException {
try {
copy("launchScript");
} catch (IOException e) {
throw new MojoExecutionException("copy launchScript error");
}
}
/**
* 复制脚本
*
* @param filename
* @throws IOException
*/
private void copy(String filename) throws IOException {
InputStream inputStream = getClass().getResourceAsStream("/" + filename);
BufferedWriter writer = null;
try {
BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream, StandardCharsets.UTF_8));
File target = new File(outputDirectory + "/" + filename);
target.setExecutable(true, false);
target.setWritable(true, false);
target.setReadable(true, false);
writer = new BufferedWriter(new FileWriter(target));
while (true) {
String line = reader.readLine();
if (line == null) {
break;
}
writer.write(line);
writer.newLine();
}
writer.flush();
} finally {
if (inputStream != null) {
inputStream.close();
}
if (writer != null) {
writer.close();
}
}
}
}

View File

@@ -1,256 +0,0 @@
#!/bin/bash
#
# . ____ _ __ _ _
# /\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \
# ( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
# \\/ ___)| |_)| | | | | || (_| | ) ) ) )
# ' |____| .__|_| |_|_| |_\__, | / / / /
# =========|_|==============|___/=/_/_/_/
# :: Spring Boot Startup Script ::
#
### BEGIN INIT INFO
# Provides: {{initInfoProvides:spring-boot-application}}
# Required-Start: {{initInfoRequiredStart:$remote_fs $syslog $network}}
# Required-Stop: {{initInfoRequiredStop:$remote_fs $syslog $network}}
# Default-Start: {{initInfoDefaultStart:2 3 4 5}}
# Default-Stop: {{initInfoDefaultStop:0 1 6}}
# Short-Description: {{initInfoShortDescription:Spring Boot Application}}
# Description: {{initInfoDescription:Spring Boot Application}}
# chkconfig: {{initInfoChkconfig:2345 99 01}}
### END INIT INFO
[[ -n "$DEBUG" ]] && set -x
# Initialize variables that cannot be provided by a .conf file
WORKING_DIR="$(pwd)"
# shellcheck disable=SC2153
[[ -n "$JARFILE" ]] && jarfile="$JARFILE"
[[ -n "$APP_NAME" ]] && identity="$APP_NAME"
# Follow symlinks to find the real jar and detect init.d script
cd "$(dirname "$0")" || exit 1
[[ -z "$jarfile" ]] && jarfile=$(pwd)/$(basename "$0")
while [[ -L "$jarfile" ]]; do
[[ "$jarfile" =~ init\.d ]] && init_script=$(basename "$jarfile")
jarfile=$(readlink "$jarfile")
cd "$(dirname "$jarfile")" || exit 1
jarfile=$(pwd)/$(basename "$jarfile")
done
jarfolder="$( (cd "$(dirname "$jarfile")" && pwd -P) )"
cd "$WORKING_DIR" || exit 1
# Source any config file
configfile="$(basename "${jarfile%.*}.conf")"
# Initialize CONF_FOLDER location defaulting to jarfolder
[[ -z "$CONF_FOLDER" ]] && CONF_FOLDER="{{confFolder:${jarfolder}}}"
# shellcheck source=/dev/null
[[ -r "${CONF_FOLDER}/${configfile}" ]] && source "${CONF_FOLDER}/${configfile}"
# Initialize PID/LOG locations if they weren't provided by the config file
[[ -z "$PID_FOLDER" ]] && PID_FOLDER="{{pidFolder:/var/run}}"
[[ -z "$LOG_FOLDER" ]] && LOG_FOLDER="{{logFolder:/var/log}}"
! [[ "$PID_FOLDER" == /* ]] && PID_FOLDER="$(dirname "$jarfile")"/"$PID_FOLDER"
! [[ "$LOG_FOLDER" == /* ]] && LOG_FOLDER="$(dirname "$jarfile")"/"$LOG_FOLDER"
! [[ -x "$PID_FOLDER" ]] && PID_FOLDER="/tmp"
! [[ -x "$LOG_FOLDER" ]] && LOG_FOLDER="/tmp"
# Set up defaults
[[ -z "$MODE" ]] && MODE="{{mode:auto}}" # modes are "auto", "service" or "run"
[[ -z "$USE_START_STOP_DAEMON" ]] && USE_START_STOP_DAEMON="{{useStartStopDaemon:true}}"
# Create an identity for log/pid files
if [[ -z "$identity" ]]; then
if [[ -n "$init_script" ]]; then
identity="${init_script}"
else
identity=$(basename "${jarfile%.*}")_${jarfolder//\//}
fi
fi
# Initialize log file name if not provided by the config file
[[ -z "$LOG_FILENAME" ]] && LOG_FILENAME="{{logFilename:${identity}.log}}"
# Initialize stop wait time if not provided by the config file
[[ -z "$STOP_WAIT_TIME" ]] && STOP_WAIT_TIME="{{stopWaitTime:60}}"
# ANSI Colors
echoRed() { echo $'\e[0;31m'"$1"$'\e[0m'; }
echoGreen() { echo $'\e[0;32m'"$1"$'\e[0m'; }
echoYellow() { echo $'\e[0;33m'"$1"$'\e[0m'; }
# Utility functions
checkPermissions() {
touch "$pid_file" &> /dev/null || { echoRed "Operation not permitted (cannot access pid file)"; return 4; }
touch "$log_file" &> /dev/null || { echoRed "Operation not permitted (cannot access log file)"; return 4; }
}
isRunning() {
ps -p "$1" | grep -v "PID" &> /dev/null
}
await_file() {
end=$(date +%s)
let "end+=10"
while [[ ! -s "$1" ]]
do
now=$(date +%s)
if [[ $now -ge $end ]]; then
break
fi
sleep 1
done
}
# Determine the script mode
action="config"
if [[ "$MODE" == "auto" && -n "$init_script" ]] || [[ "$MODE" == "service" ]]; then
action="$1"
shift
fi
# Build the pid and log filenames
PID_FOLDER="$PID_FOLDER/${identity}"
pid_file="$PID_FOLDER/{{pidFilename:${identity}.pid}}"
log_file="$LOG_FOLDER/$LOG_FILENAME"
# Determine the user to run as if we are root
# shellcheck disable=SC2012
[[ $(id -u) == "0" ]] && run_user=$(ls -ld "$jarfile" | awk '{print $3}')
# Find Java
if [[ -n "$JAVA_HOME" ]] && [[ -x "$JAVA_HOME/bin/java" ]]; then
javaexe="$JAVA_HOME/bin/java"
elif type -p java > /dev/null 2>&1; then
javaexe=$(type -p java)
elif [[ -x "/usr/bin/java" ]]; then
javaexe="/usr/bin/java"
else
echo "Unable to find Java"
exit 1
fi
arguments=(-Dsun.misc.URLClassPath.disableJarChecking=true $JAVA_OPTS -jar "$jarfile" $RUN_ARGS "$@")
# Action functions
start() {
if [[ -f "$pid_file" ]]; then
pid=$(cat "$pid_file")
isRunning "$pid" && { echoYellow "Already running [$pid]"; return 0; }
fi
do_start "$@"
}
do_start() {
working_dir=$(dirname "$jarfile")
pushd "$working_dir" > /dev/null
mkdir -p "$PID_FOLDER" &> /dev/null
if [[ -n "$run_user" ]]; then
checkPermissions || return $?
chown "$run_user" "$PID_FOLDER"
chown "$run_user" "$pid_file"
chown "$run_user" "$log_file"
if [ $USE_START_STOP_DAEMON = true ] && type start-stop-daemon > /dev/null 2>&1; then
start-stop-daemon --start --quiet \
--chuid "$run_user" \
--name "$identity" \
--make-pidfile --pidfile "$pid_file" \
--background --no-close \
--startas "$javaexe" \
--chdir "$working_dir" \
-- "${arguments[@]}" \
>> "$log_file" 2>&1
await_file "$pid_file"
else
su -s /bin/sh -c "$javaexe $(printf "\"%s\" " "${arguments[@]}") >> \"$log_file\" 2>&1 & echo \$!" "$run_user" > "$pid_file"
fi
pid=$(cat "$pid_file")
else
checkPermissions || return $?
"$javaexe" "${arguments[@]}" >> "$log_file" 2>&1 &
pid=$!
disown $pid
echo "$pid" > "$pid_file"
fi
[[ -z $pid ]] && { echoRed "Failed to start"; return 1; }
echoGreen "Started [$pid]"
}
stop() {
working_dir=$(dirname "$jarfile")
pushd "$working_dir" > /dev/null
[[ -f $pid_file ]] || { echoYellow "Not running (pidfile not found)"; return 0; }
pid=$(cat "$pid_file")
isRunning "$pid" || { echoYellow "Not running (process ${pid}). Removing stale pid file."; rm -f "$pid_file"; return 0; }
do_stop "$pid" "$pid_file"
}
do_stop() {
kill "$1" &> /dev/null || { echoRed "Unable to kill process $1"; return 1; }
for i in $(seq 1 $STOP_WAIT_TIME); do
isRunning "$1" || { echoGreen "Stopped [$1]"; rm -f "$2"; return 0; }
[[ $i -eq STOP_WAIT_TIME/2 ]] && kill "$1" &> /dev/null
sleep 1
done
echoRed "Unable to kill process $1";
return 1;
}
restart() {
stop && start
}
status() {
working_dir=$(dirname "$jarfile")
pushd "$working_dir" > /dev/null
[[ -f "$pid_file" ]] || { echoRed "Not running"; return 3; }
pid=$(cat "$pid_file")
isRunning "$pid" || { echoRed "Not running (process ${pid} not found)"; return 1; }
echoGreen "Running [$pid]"
return 0
}
run() {
pushd "$(dirname "$jarfile")" > /dev/null
"$javaexe" "${arguments[@]}"
result=$?
popd > /dev/null
return "$result"
}
config() {
## 设置自启动
ln -s $jarfile /etc/init.d/$1
chkconfig --add $1
## 生成配置文件
working_dir=$(dirname "$jarfile")
conf_file="$working_dir/$configfile"
echo "LOG_FOLDER=/dev" > $conf_file
echo "LOG_FILENAME=null" >> $conf_file
echo "RUN_ARGS='--server.port=$2 --spring.profiles.active=$3'" >> $conf_file
echo "JAVA_OPTS='-Dfile.encoding=utf-8'" >> $conf_file
}
# Call the appropriate action function
case "$action" in
start)
start "$@"; exit $?;;
stop)
stop "$@"; exit $?;;
restart)
restart "$@"; exit $?;;
status)
status "$@"; exit $?;;
run)
run "$@"; exit $?;;
config)
config "$1" "$2" "$3" ; exit $?;;
*)
echo "Usage: $0 {start|stop|restart|status|run|config}"; exit 1;
esac
exit 0

View File

@@ -4,9 +4,9 @@
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>
<parent>
<groupId>com.tiesheng</groupId>
<groupId>com.tiesheng.springboot-parent</groupId>
<artifactId>springboot-parent</artifactId>
<version>0.2.0</version>
<version>1.0.1</version>
</parent>
<artifactId>springboot-login</artifactId>
@@ -27,12 +27,12 @@
</dependency>
<dependency>
<groupId>com.tiesheng</groupId>
<groupId>com.tiesheng.springboot-parent</groupId>
<artifactId>springboot-annotation</artifactId>
</dependency>
<dependency>
<groupId>com.tiesheng</groupId>
<groupId>com.tiesheng.springboot-parent</groupId>
<artifactId>springboot-platform</artifactId>
</dependency>

View File

@@ -1,6 +1,9 @@
package com.tiesheng.login.config.token;
import cn.hutool.core.util.ObjUtil;
import cn.hutool.core.util.StrUtil;
import com.tiesheng.annotation.token.TokenIgnore;
import com.tiesheng.util.ServletKit;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
@@ -46,7 +49,28 @@ public class TsTokenAspect {
@Before("methodArgs()")
public void before(JoinPoint joinPoint) {
// 过滤不要需要验证的接口
// 过滤不要需要验证的接口path
String requestURI = ServletKit.getRequest().getRequestURI();
String[] ignorePaths = tsTokenConfig.getIgnorePaths();
if (ObjUtil.isNotEmpty(ignorePaths)) {
for (String path : ignorePaths) {
if (path.contains("/**") &&
StrUtil.startWith(requestURI, path.replace("/**", ""))) {
// 通配路径
return;
} else if (requestURI.equals(path)) {
// 完整路径
return;
}
}
}
// 过滤不要需要验证的接口(注解)
Object aThis = joinPoint.getTarget();
TokenIgnore annotation = aThis.getClass().getAnnotation(TokenIgnore.class);
if (annotation != null) {
return;
}
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
Method method = signature.getMethod();
TokenIgnore apiTokenIgnore = method.getAnnotation(TokenIgnore.class);

View File

@@ -6,6 +6,7 @@ import cn.hutool.core.util.StrUtil;
import cn.hutool.extra.servlet.ServletUtil;
import cn.hutool.extra.spring.SpringUtil;
import cn.hutool.jwt.JWT;
import cn.hutool.jwt.JWTValidator;
import com.tiesheng.login.config.token.bean.TokenBean;
import com.tiesheng.util.ServletKit;
import com.tiesheng.util.exception.ApiException;
@@ -22,9 +23,10 @@ import java.util.Map;
@ConfigurationProperties("tiesheng.token")
public class TsTokenConfig {
private Map<String, TokenBean> ignores = MapUtil.newHashMap();
private Map<String, TokenBean> testMap = MapUtil.newHashMap();
private String encryptKey = "%kIp9frQCu";
private Integer expireHours = 48;
private String[] ignorePaths;
/**
@@ -55,11 +57,23 @@ public class TsTokenConfig {
* @param token
* @return
*/
public TokenBean isIgnored(String token) {
if (ignores == null) {
public TokenBean isTestToken(String token) {
if (testMap == null) {
return null;
}
return ignores.get(token);
return testMap.get(token);
}
/**
* 验证token
*
* @param thrExp
* @return
*/
public TokenBean validToken(boolean thrExp) {
String token = ServletUtil.getHeader(ServletKit.getRequest(), "token", "utf-8");
return validToken(token, thrExp);
}
@@ -68,31 +82,27 @@ public class TsTokenConfig {
*
* @return
*/
public TokenBean validToken(boolean thrExp) {
String token = ServletUtil.getHeader(ServletKit.getRequest(), "token", "utf-8");
TokenBean tokenBean = isIgnored(token);
public TokenBean validToken(String token, boolean thrExp) {
TokenBean tokenBean = isTestToken(token);
if (tokenBean != null) {
return tokenBean;
}
try {
JWT decode = JWT.of(token);
JWTValidator.of(decode).validateDate();
String id = decode.getPayload("id").toString();
String environmentType = decode.getPayload("environmentType").toString();
String service = decode.getPayload("service").toString();
String extra = decode.getPayload("extra").toString();
Long expireTime = decode.getPayloads().getLong("time");
if (expireTime != null && expireTime < System.currentTimeMillis()) {
throw new ApiException("登录过期,请重新登陆");
}
tokenBean = new TokenBean(id, environmentType, service);
tokenBean.setExtra(extra);
} catch (Exception ignored) {
}
if (tokenBean == null && thrExp) {
throw new ApiException(StrUtil.isEmpty(token) ? "请先登录" : "登录过期,请重新登陆");
throw new ApiException(StrUtil.isEmpty(token) ? 110 : 112,
StrUtil.isEmpty(token) ? "请先登录" : "登录过期,请重新登陆");
}
if (tokenBean == null) {
@@ -107,12 +117,12 @@ public class TsTokenConfig {
// setter\getter
///////////////////////////////////////////////////////////////////////////
public Map<String, TokenBean> getIgnores() {
return ignores;
public Map<String, TokenBean> getTestMap() {
return testMap;
}
public void setIgnores(Map<String, TokenBean> ignores) {
this.ignores = ignores;
public void setTestMap(Map<String, TokenBean> testMap) {
this.testMap = testMap;
}
public String getEncryptKey() {
@@ -130,4 +140,12 @@ public class TsTokenConfig {
public void setExpireHours(Integer expireHours) {
this.expireHours = expireHours;
}
public String[] getIgnorePaths() {
return ignorePaths;
}
public void setIgnorePaths(String[] ignorePaths) {
this.ignorePaths = ignorePaths;
}
}

View File

@@ -1,5 +1,6 @@
package com.tiesheng.login.config.token.bean;
import cn.hutool.core.date.DateUtil;
import cn.hutool.extra.spring.SpringUtil;
import cn.hutool.jwt.JWT;
import com.tiesheng.login.config.token.TsTokenConfig;
@@ -31,11 +32,11 @@ public class TokenBean {
public String toToken() {
TsTokenConfig tsTokenConfig = SpringUtil.getBean(TsTokenConfig.class);
return JWT.create()
.setExpiresAt(DateUtil.offsetHour(DateUtil.date(), tsTokenConfig.getExpireHours()))
.setPayload("id", getId())
.setPayload("environmentType", getEnvironmentType())
.setPayload("service", getService())
.setPayload("extra", getExtra())
.setPayload("time", System.currentTimeMillis() + tsTokenConfig.getExpireHours() * 1000 * 60 * 60)
.setKey(tsTokenConfig.getEncryptKey().getBytes())
.sign();
}

View File

@@ -1,94 +0,0 @@
package com.tiesheng.login.config.zust;
public class CasLoginDTO {
private String data;
/**
* 工号
*/
private String casUser;
/**
* 用户容器
*/
private String casUserContainerId;
/**
* 用户姓名
*/
private String casUserCn;
/**
* 用户别名
*/
private String casUserAlias;
/**
* 用户所在组
*/
private String casUserMemberOf;
/**
* 用户性别
*/
private String casUserGender;
///////////////////////////////////////////////////////////////////////////
// setter\getter
///////////////////////////////////////////////////////////////////////////
public String getData() {
return data;
}
public void setData(String data) {
this.data = data;
}
public String getCasUser() {
return casUser;
}
public void setCasUser(String casUser) {
this.casUser = casUser;
}
public String getCasUserContainerId() {
return casUserContainerId;
}
public void setCasUserContainerId(String casUserContainerId) {
this.casUserContainerId = casUserContainerId;
}
public String getCasUserCn() {
return casUserCn;
}
public void setCasUserCn(String casUserCn) {
this.casUserCn = casUserCn;
}
public String getCasUserAlias() {
return casUserAlias;
}
public void setCasUserAlias(String casUserAlias) {
this.casUserAlias = casUserAlias;
}
public String getCasUserMemberOf() {
return casUserMemberOf;
}
public void setCasUserMemberOf(String casUserMemberOf) {
this.casUserMemberOf = casUserMemberOf;
}
public String getCasUserGender() {
return casUserGender;
}
public void setCasUserGender(String casUserGender) {
this.casUserGender = casUserGender;
}
}

View File

@@ -9,11 +9,14 @@ import com.tiesheng.login.config.token.bean.TokenBean;
import com.tiesheng.login.pojos.CodeExtraDTO;
import com.tiesheng.login.pojos.DoLoginInfo;
import com.tiesheng.login.pojos.UniqueIndexDTO;
import com.tiesheng.login.pojos.WxminiLoginVo;
import com.tiesheng.login.service.TieshengLoginConfigurer;
import com.tiesheng.platform.config.ding.PlatformDingConfig;
import com.tiesheng.platform.config.ding.bean.DingJsapiSignature;
import com.tiesheng.platform.config.ding.bean.DingUserInfo;
import com.tiesheng.platform.config.wxmini.PlatformWxminiConfig;
import com.tiesheng.platform.config.wxmp.PlatformWxmpConfig;
import com.tiesheng.platform.config.wxmp.bean.WxConfigBean;
import com.tiesheng.platform.config.wxmp.bean.WxJsapiSignature;
import com.tiesheng.platform.config.wxmp.bean.WxUserInfo;
import com.tiesheng.util.config.GlobalConfig;
@@ -32,6 +35,7 @@ import java.util.Map;
*/
@RestController
@RequestMapping("/login")
@TokenIgnore
public class LoginController {
@@ -40,6 +44,8 @@ public class LoginController {
@Autowired
PlatformDingConfig platformDingConfig;
@Autowired
PlatformWxminiConfig platformWxminiConfig;
@Autowired
TieshengLoginConfigurer tieshengLoginConfigurer;
@Autowired
GlobalConfig globalConfig;
@@ -51,10 +57,9 @@ public class LoginController {
* @return
*/
@GetMapping("/unique/redirect")
@TokenIgnore
public void uniqueIndex(UniqueIndexDTO dto, HttpServletResponse response) {
TokenBean tokenBean = tieshengLoginConfigurer.doLogin(new DoLoginInfo("unique_index_web",
dto.getNo(), "web", dto.getTo(), dto.getInfo()));
TokenBean tokenBean = tieshengLoginConfigurer.doLogin(new DoLoginInfo("web_unique_redirect",
dto.getNo(), dto.getPlatform(), dto.getInfo()));
tieshengLoginConfigurer.onLoginRedirect(tokenBean, dto.getTo(), dto.getExtra(), response);
}
@@ -66,10 +71,9 @@ public class LoginController {
* @return
*/
@PostMapping("/unique/index")
@TokenIgnore
public ApiResp<String> uniqueIndex(@RequestBody UniqueIndexDTO dto) {
TokenBean tokenBean = tieshengLoginConfigurer.doLogin(new DoLoginInfo("unique_index_web",
dto.getNo(), "web", dto.getTo(), dto.getInfo()));
TokenBean tokenBean = tieshengLoginConfigurer.doLogin(new DoLoginInfo("web_unique_index",
dto.getNo(), dto.getPlatform(), dto.getInfo()));
if (tokenBean == null) {
throw new ApiException("登录失败");
}
@@ -89,7 +93,6 @@ public class LoginController {
* @param response
*/
@GetMapping("/ding/index/{service}")
@TokenIgnore
public void dingIndex(@PathVariable String service, String extra, HttpServletResponse response) {
if (StrUtil.isEmpty(extra)) {
extra = "";
@@ -113,13 +116,11 @@ public class LoginController {
* @param service
*/
@RequestMapping("/ding/oauth2/{service}")
@TokenIgnore
public void dingOauth2(@PathVariable String service, CodeExtraDTO dto, HttpServletResponse response) {
String ddUserId = platformDingConfig.getUserIdByCode(service, dto.getCode());
DingUserInfo dingUserInfo = platformDingConfig.topapiV2UserGet(service, ddUserId);
TokenBean tokenBean = tieshengLoginConfigurer.doLogin(new DoLoginInfo(dingUserInfo.getAppId(),
dingUserInfo.getUserid(), "ding", dto.getTo(),
JSON.toJSONString(dingUserInfo)));
dingUserInfo.getUserid(), "ding", JSON.toJSONString(dingUserInfo)));
tieshengLoginConfigurer.onLoginRedirect(tokenBean, dto.getTo(), dto.getExtra(), response);
}
@@ -131,7 +132,6 @@ public class LoginController {
* @return
*/
@GetMapping("/ding/jssdk/{service}")
@TokenIgnore
public ApiResp<DingJsapiSignature> dingJssdk(@PathVariable String service, String url) {
DingJsapiSignature jsapiSignature = platformDingConfig.createJsapiSignature(service, url);
return ApiResp.respOK(jsapiSignature);
@@ -149,7 +149,6 @@ public class LoginController {
* @return
*/
@RequestMapping("/wxmp/index/{service}")
@TokenIgnore
public void wxmpIndex(@PathVariable String service, String extra, HttpServletResponse response) throws IOException {
if (StrUtil.isEmpty(extra)) {
extra = "";
@@ -164,11 +163,10 @@ public class LoginController {
* 微信授权回调
*/
@RequestMapping("/wxmp/oauth2/{service}")
@TokenIgnore
public void wxmpOauth2(@PathVariable String service, CodeExtraDTO dto, HttpServletResponse response) {
WxUserInfo wxUserInfo = platformWxmpConfig.getOAuth2AccessToken(service, dto.getCode());
TokenBean tokenBean = tieshengLoginConfigurer.doLogin(new DoLoginInfo(wxUserInfo.getAppId(),
wxUserInfo.getOpenid(), "wxmp", dto.getTo(), JSON.toJSONString(wxUserInfo)));
wxUserInfo.getOpenid(), "wxmp", JSON.toJSONString(wxUserInfo)));
tieshengLoginConfigurer.onLoginRedirect(tokenBean, dto.getTo(), dto.getExtra(), response);
}
@@ -180,11 +178,34 @@ public class LoginController {
* @return
*/
@GetMapping("/wxmp/jssdk/{service}")
@TokenIgnore
public ApiResp<WxJsapiSignature> wxmpJssdk(@PathVariable String service, String url) {
WxJsapiSignature jsapiSignature = platformWxmpConfig.createJsapiSignature(service, url);
return ApiResp.respOK(jsapiSignature);
}
///////////////////////////////////////////////////////////////////////////
// 小程序相关
///////////////////////////////////////////////////////////////////////////
/**
* 微信小程序登录
*
* @return
*/
@RequestMapping("/wxmini/index/{service}")
public ApiResp<WxminiLoginVo> wxminiIndex(@PathVariable String service, String code) {
String openid = platformWxminiConfig.jscode2session(service, code);
WxConfigBean configBean = platformWxminiConfig.getConfigBean(service);
TokenBean tokenBean = tieshengLoginConfigurer.doLogin(new DoLoginInfo(configBean.getAppId(),
openid, "wxmini", "{}"));
WxminiLoginVo loginVo = new WxminiLoginVo();
loginVo.setOpenid(openid);
if (tokenBean != null) {
loginVo.setToken(tokenBean.toToken());
}
return ApiResp.respOK(loginVo);
}
}

View File

@@ -5,15 +5,13 @@ public class DoLoginInfo {
private String appId;
private String unique;
private String platform;
private String to;
private String info;
private String extra;
public DoLoginInfo(String appId, String unique, String platform, String to, String info) {
public DoLoginInfo(String appId, String unique, String platform, String info) {
this.appId = appId;
this.unique = unique;
this.platform = platform;
this.to = to;
this.info = info;
}
@@ -45,14 +43,6 @@ public class DoLoginInfo {
this.platform = platform;
}
public String getTo() {
return to;
}
public void setTo(String to) {
this.to = to;
}
public String getInfo() {
return info;
}

View File

@@ -7,6 +7,7 @@ public class UniqueIndexDTO extends LoginToInfo {
private String no;
private String extra;
private String info;
private String platform = "web";
///////////////////////////////////////////////////////////////////////////
// setter\getter
@@ -38,4 +39,12 @@ public class UniqueIndexDTO extends LoginToInfo {
public void setInfo(String info) {
this.info = info;
}
public String getPlatform() {
return platform;
}
public void setPlatform(String platform) {
this.platform = platform;
}
}

View File

@@ -0,0 +1,27 @@
package com.tiesheng.login.pojos;
public class WxminiLoginVo {
private String openid;
private String token;
///////////////////////////////////////////////////////////////////////////
// setter\getter
///////////////////////////////////////////////////////////////////////////
public String getOpenid() {
return openid;
}
public void setOpenid(String openid) {
this.openid = openid;
}
public String getToken() {
return token;
}
public void setToken(String token) {
this.token = token;
}
}

View File

@@ -23,7 +23,7 @@ public interface TieshengLoginConfigurer {
/**
* 授权登录回调
*
* @param tokenBean
* @param bean
*/
void onLoginRedirect(TokenBean bean, String to, String extra, HttpServletResponse response);

View File

@@ -4,9 +4,9 @@
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>
<parent>
<groupId>com.tiesheng</groupId>
<groupId>com.tiesheng.springboot-parent</groupId>
<artifactId>springboot-parent</artifactId>
<version>0.2.0</version>
<version>1.0.1</version>
</parent>
<artifactId>springboot-message</artifactId>
@@ -20,7 +20,7 @@
<dependencies>
<dependency>
<groupId>com.tiesheng</groupId>
<groupId>com.tiesheng.springboot-parent</groupId>
<artifactId>springboot-platform</artifactId>
</dependency>

View File

@@ -2,13 +2,13 @@ package com.tiesheng.message.config.aliyun;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.SecureUtil;
import cn.hutool.http.HttpUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.tiesheng.message.pojos.MessageReqResp;
import com.tiesheng.message.service.TieshengMessageConfigurer;
import org.springframework.beans.factory.annotation.Autowired;
import com.tiesheng.message.service.TieshengMessageSender;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;
@@ -22,16 +22,13 @@ import java.util.*;
*/
@Configuration
@ConfigurationProperties(prefix = "tiesheng.aliyun")
public class AliyunSmsConfig {
public class AliyunSmsSender implements TieshengMessageSender {
/**
* 请求地址
*/
private static final String ENDPOINT = "https://dysmsapi.aliyuncs.com";
@Autowired
TieshengMessageConfigurer tieshengMessageConfigurer;
private String accessKeyId;
private String accessKeySecret;
private String signName;
@@ -62,7 +59,7 @@ public class AliyunSmsConfig {
*/
public MessageReqResp sendSms(String phoneNumbers, String templateCode, JSONObject params) {
MessageReqResp reqResp = new MessageReqResp();
MessageReqResp reqResp = new MessageReqResp("阿里云短信");
reqResp.setTarget(phoneNumbers);
reqResp.setResult(1);
reqResp.setContent(JSONUtil.createObj()
@@ -115,11 +112,24 @@ public class AliyunSmsConfig {
reqResp.setToast(respObj.getStr("Message"));
}
tieshengMessageConfigurer.onMessageSend("阿里云短信", reqResp);
return reqResp;
}
@Override
public MessageReqResp send(String user, String title, Object body) {
return sendSms(user, title, (JSONObject) body);
}
@Override
public String getChannel() {
return "sms";
}
@Override
public boolean support() {
return StrUtil.isAllNotEmpty(accessKeyId, accessKeySecret, signName);
}
///////////////////////////////////////////////////////////////////////////
// setter\getter
///////////////////////////////////////////////////////////////////////////

View File

@@ -2,6 +2,8 @@ package com.tiesheng.message.pojos;
public class MessageReqResp {
private String type;
/**
* 发送对象
*/
@@ -28,10 +30,22 @@ public class MessageReqResp {
*/
private String toast;
public MessageReqResp(String type) {
this.type = type;
}
///////////////////////////////////////////////////////////////////////////
// setter\getter
///////////////////////////////////////////////////////////////////////////
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public String getTarget() {
return target;
}

View File

@@ -1,23 +0,0 @@
package com.tiesheng.message.service;
import cn.hutool.json.JSONUtil;
import cn.hutool.log.LogFactory;
import com.tiesheng.message.pojos.MessageReqResp;
/**
* @author hao
*/
public interface TieshengMessageConfigurer {
/**
* 消息发送后
*
* @param reqResp
*/
default void onMessageSend(String type, MessageReqResp reqResp) {
LogFactory.get().info(JSONUtil.toJsonStr(reqResp));
}
}

View File

@@ -0,0 +1,39 @@
package com.tiesheng.message.service;
import com.tiesheng.message.pojos.MessageReqResp;
/**
* @author hao
*/
public interface TieshengMessageSender {
/**
* 发送消息
*
* @param user
* @param title
* @param content
* @param body
* @param channel 消息通道,如果为空表示所有通道
* @return 返回的内容,如果为空表示发送成功
*/
MessageReqResp send(String user, String title, Object body);
/**
* 获取通道
*
* @return
*/
String getChannel();
/**
* 是否支持
*
* @return
*/
boolean support();
}

View File

@@ -1,11 +0,0 @@
package com.tiesheng.message.service.impl;
import com.tiesheng.message.service.TieshengMessageConfigurer;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.context.annotation.Configuration;
@Configuration
@ConditionalOnMissingBean(value = TieshengMessageConfigurer.class, ignored = DefaultMessageConfigurer.class)
public class DefaultMessageConfigurer implements TieshengMessageConfigurer {
}

View File

@@ -4,9 +4,9 @@
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>
<parent>
<groupId>com.tiesheng</groupId>
<groupId>com.tiesheng.springboot-parent</groupId>
<artifactId>springboot-parent</artifactId>
<version>0.2.0</version>
<version>1.0.1</version>
</parent>
<artifactId>springboot-platform</artifactId>
@@ -19,7 +19,7 @@
<dependencies>
<dependency>
<groupId>com.tiesheng</groupId>
<groupId>com.tiesheng.springboot-parent</groupId>
<artifactId>springboot-util</artifactId>
</dependency>
</dependencies>

View File

@@ -0,0 +1,95 @@
package com.tiesheng.platform.config.wxmini;
import cn.hutool.core.map.MapUtil;
import cn.hutool.http.HttpRequest;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.tiesheng.platform.config.wxmp.bean.WxConfigBean;
import com.tiesheng.util.exception.ApiException;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;
import java.util.Map;
/**
* @author hao
*/
@Configuration
@ConfigurationProperties(prefix = "platform.wxmini")
public class PlatformWxminiConfig {
private WxConfigBean global;
private Map<String, WxConfigBean> configs = MapUtil.newHashMap();
/**
* 获取一个DingConfigBean
*
* @param service
* @return
*/
public WxConfigBean getConfigBean(String service) {
WxConfigBean bean = configs.get(service);
if (bean == null) {
bean = global;
}
if (bean == null) {
throw new ApiException("该服务未配置微信小程序授权");
}
return bean;
}
///////////////////////////////////////////////////////////////////////////
// 业务逻辑
///////////////////////////////////////////////////////////////////////////
/**
* 通过code获取openid
*
* @return
*/
public String jscode2session(String service, String code) {
WxConfigBean configBean = getConfigBean(service);
String body = HttpRequest.get("https://api.weixin.qq.com/sns/jscode2session"
+ "?appid=" + configBean.getAppId()
+ "&secret=" + configBean.getAppSecret()
+ "&js_code=" + code + "&grant_type=authorization_code").execute().body();
JSONObject object = JSONUtil.parseObj(body);
return object.getStr("openid");
}
/**
* 获取access_token
*
* @return
*/
public String getAccessToken(String service) {
WxConfigBean configBean = getConfigBean(service);
String body = HttpRequest.get("https://api.weixin.qq.com/cgi-bin/token"
+ "?grant_type=client_credential&appid=" + configBean.getAppId()
+ "&secret=" + configBean.getAppSecret()).execute().body();
JSONObject object = JSONUtil.parseObj(body);
return object.getStr("access_token");
}
///////////////////////////////////////////////////////////////////////////
// setter\getter
///////////////////////////////////////////////////////////////////////////
public Map<String, WxConfigBean> getConfigs() {
return configs;
}
public void setConfigs(Map<String, WxConfigBean> configs) {
this.configs = configs;
}
public WxConfigBean getGlobal() {
return global;
}
public void setGlobal(WxConfigBean global) {
this.global = global;
}
}

View File

@@ -4,9 +4,9 @@
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>
<parent>
<groupId>com.tiesheng</groupId>
<groupId>com.tiesheng.springboot-parent</groupId>
<artifactId>springboot-parent</artifactId>
<version>0.2.0</version>
<version>1.0.1</version>
</parent>
<artifactId>springboot-poi</artifactId>
@@ -25,7 +25,7 @@
</dependency>
<dependency>
<groupId>com.tiesheng</groupId>
<groupId>com.tiesheng.springboot-parent</groupId>
<artifactId>springboot-util</artifactId>
</dependency>

View File

@@ -4,9 +4,9 @@
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>
<parent>
<groupId>com.tiesheng</groupId>
<groupId>com.tiesheng.springboot-parent</groupId>
<artifactId>springboot-parent</artifactId>
<version>0.2.0</version>
<version>1.0.1</version>
</parent>
<artifactId>springboot-util</artifactId>
@@ -25,18 +25,31 @@
<scope>compile</scope>
</dependency>
<dependency>
<groupId>com.tiesheng.springboot-parent</groupId>
<artifactId>springboot-annotation</artifactId>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.8.11</version>
<version>5.8.16</version>
</dependency>
<!-- fastJson -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.78</version>
<version>1.2.83</version>
</dependency>
<!-- 加解密 -->
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcprov-jdk15to18</artifactId>
<version>1.68</version>
</dependency>
</dependencies>
</project>

View File

@@ -0,0 +1,50 @@
package com.tiesheng.util;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.alibaba.fastjson.support.config.FastJsonConfig;
import com.tiesheng.util.config.DesensitizeValueFilter;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
public class CommonUtil {
/**
* FastJson配置
*
* @return
*/
public static FastJsonConfig fastJsonConfig() {
FastJsonConfig config = new FastJsonConfig();
config.setSerializerFeatures(SerializerFeature.WriteMapNullValue,
SerializerFeature.WriteNullStringAsEmpty,
SerializerFeature.WriteEnumUsingName,
SerializerFeature.DisableCircularReferenceDetect
);
config.setDateFormat("yyyy-MM-dd HH:mm:ss");
config.setSerializeFilters(new DesensitizeValueFilter());
return config;
}
/**
* 格式化数据
*
* @param value
* @return
* @throws IOException
*/
public static String writeJsonString(Object value) throws IOException {
FastJsonConfig fastJsonConfig = fastJsonConfig();
ByteArrayOutputStream outnew = new ByteArrayOutputStream();
JSON.writeJSONStringWithFastJsonConfig(outnew, fastJsonConfig.getCharset(),
value, fastJsonConfig.getSerializeConfig(),
fastJsonConfig.getSerializeFilters(),
fastJsonConfig.getDateFormat(), JSON.DEFAULT_GENERATE_FEATURE,
fastJsonConfig.getSerializerFeatures());
return outnew.toString();
}
}

View File

@@ -1,44 +0,0 @@
package com.tiesheng.util;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.SecureUtil;
import com.tiesheng.util.exception.ApiException;
public class PasswordUtils {
private static final int PREFIX_SIZE = 8;
/**
* 获取加密密码
*
* @param password
* @return
*/
public static String buildPassword(String password) {
String prefix = RandomUtil.randomString(PREFIX_SIZE);
return prefix + SecureUtil.sha1(password);
}
/**
* 验证密码
*
* @param userInput
* @param encrypted
* @return
*/
public static void verifyPassword(String userInput, String encrypted) {
String userEncrypted = buildPassword(userInput);
userEncrypted = StrUtil.subSuf(userEncrypted, PREFIX_SIZE);
encrypted = StrUtil.subSuf(encrypted, PREFIX_SIZE);
if (!StrUtil.equals(userEncrypted, encrypted)) {
throw new ApiException("账号或密码错误");
}
}
}

View File

@@ -20,5 +20,14 @@ public class ServletKit extends ServletUtil {
return attributes.getRequest();
}
/**
* 获取客户端IP
*
* @return
*/
public static String getClientIP() {
return getClientIP(getRequest());
}
}

View File

@@ -0,0 +1,37 @@
package com.tiesheng.util.config;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.ReflectUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.serializer.ValueFilter;
import com.tiesheng.annotation.desensitize.Desensitize;
import java.lang.reflect.Field;
/**
* 脱敏过滤类
*
* @author hao
*/
public class DesensitizeValueFilter implements ValueFilter {
@Override
public Object process(Object object, String name, Object value) {
if (ObjectUtil.isEmpty(value) || !(value instanceof String)) {
return value;
}
Field field = ReflectUtil.getField(object.getClass(), name);
if (ObjectUtil.isEmpty(field)) {
return value;
}
Desensitize desensitize = field.getAnnotation(Desensitize.class);
if (String.class != field.getType() || ObjectUtil.isEmpty(desensitize)) {
return value;
}
String originVal = String.valueOf(value);
return StrUtil.hide(originVal, desensitize.prefix(),
StrUtil.length(originVal) - desensitize.suffix());
}
}

View File

@@ -0,0 +1,136 @@
package com.tiesheng.util.config;
import cn.hutool.core.codec.Base64;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.SecureUtil;
import cn.hutool.crypto.SmUtil;
import cn.hutool.crypto.symmetric.SM4;
import com.tiesheng.util.ServletKit;
import com.tiesheng.util.TimedCacheHelper;
import com.tiesheng.util.exception.ApiException;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;
/**
* @author hao
*/
@Configuration
@ConfigurationProperties(prefix = "tiesheng.encrypt")
public class EncryptConfig {
/**
* 加解密对象
*/
private final SM4 sm4;
/**
* 加密密钥
*/
private String key = "WmdUzPJXbngVNiaSsQrihg==";
private Integer saltSize = 8;
public EncryptConfig() {
sm4 = SmUtil.sm4(Base64.decode(getKey()));
}
/**
* 加密
*
* @param content
* @return
*/
public String encrypt(String content) {
if (StrUtil.isEmpty(content)) {
return "";
}
return sm4.encryptBase64(content);
}
/**
* 解密
*
* @param base64
* @return
*/
public String decrypt(String base64) {
try {
return sm4.decryptStr(base64);
} catch (Exception ignore) {
}
return base64;
}
/**
* 创建密码
*
* @param inputPasswd
* @param salt 盐,不存将自动生成
* @return
*/
public String passwdCreate(String inputPasswd, String salt) {
if (StrUtil.isEmpty(salt)) {
salt = RandomUtil.randomString(saltSize);
}
if (!passwdComplexity(inputPasswd)) {
throw new ApiException("需要包含数字、大小写字母、特殊符号且长度不低于8位");
}
return encrypt(salt + SecureUtil.sha1(salt + inputPasswd));
}
/**
* 复杂度校验
*
* @param inputPasswd
* @return
*/
public boolean passwdComplexity(String inputPasswd) {
String password = "^(?![A-Za-z0-9]+$)(?![a-z0-9\\W]+$)(?![A-Za-z\\W]+$)(?![A-Z0-9\\W]+$)[a-zA-Z0-9\\W]{8,}$";
return inputPasswd.matches(password);
}
/**
* 密码校验
*
* @param inputPasswd
*/
public void passwdVerify(String inputPasswd, String encrypted) {
String salt = decrypt(encrypted).substring(0, saltSize);
String inputEncrypted = passwdCreate(inputPasswd, salt);
if (!StrUtil.equals(inputEncrypted, encrypted)) {
String clientIp = ServletKit.getClientIP();
int num = NumberUtil.parseInt(TimedCacheHelper.getTimedCache().get(clientIp, false));
if (num > 5) {
throw new ApiException("登录失败已达6次请10分钟后再试");
}
TimedCacheHelper.getTimedCache().put(clientIp, String.valueOf(num + 1), 10 * 60 * 1000);
throw new ApiException("账号或密码错误");
}
}
///////////////////////////////////////////////////////////////////////////
// setter\getter
///////////////////////////////////////////////////////////////////////////
public String getKey() {
return key;
}
public void setKey(String key) {
this.key = key;
}
public Integer getSaltSize() {
return saltSize;
}
public void setSaltSize(Integer saltSize) {
this.saltSize = saltSize;
}
}

View File

@@ -1,8 +1,11 @@
package com.tiesheng.util.config;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.comparator.VersionComparator;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.extra.spring.SpringUtil;
import cn.hutool.json.JSONUtil;
import cn.hutool.log.LogFactory;
import com.tiesheng.util.exception.ApiException;
import org.springframework.boot.context.properties.ConfigurationProperties;
@@ -11,7 +14,10 @@ import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
/**
* @author hao
@@ -23,6 +29,7 @@ public class GlobalConfig {
private String host;
private String service;
private String version;
private String uploadDir = System.getProperty("user.dir");
///////////////////////////////////////////////////////////////////////////
// 逻辑方法
@@ -61,15 +68,34 @@ public class GlobalConfig {
* @param route
*/
public void redirect(String htmlDir, String route, HttpServletResponse response) {
if (!StrUtil.endWith(htmlDir, "/")) {
htmlDir = htmlDir + "/";
}
PathMatchingResourcePatternResolver patternResolver = new PathMatchingResourcePatternResolver();
try {
Resource[] resources = patternResolver.getResources(String.format("classpath*:static/%s/*/index.html", htmlDir));
if (resources.length == 0) {
List<String> versions = new ArrayList<>();
// jar包中的资源
Resource[] resources = patternResolver.getResources(String.format("classpath*:static/%s*/index.html", htmlDir));
for (Resource resource : resources) {
String path = FileUtil.normalize(resource.getURL().getPath());
versions.add(StrUtil.subBetween(path, htmlDir, "/index.html"));
}
// 目录中的资源
String folder = String.format("%s/static/%s", System.getProperty("user.dir"), htmlDir);
if (FileUtil.exist(folder)) {
File[] files = FileUtil.ls(folder);
for (File file : files) {
versions.add(StrUtil.subAfter(file.getAbsolutePath(), htmlDir, true));
}
}
if (CollUtil.isEmpty(versions)) {
throw new ApiException("无法重定向,请检查资源");
}
String filename = resources[resources.length - 1].getURL().getPath();
filename = FileUtil.normalize(filename);
String path = buildPath(String.format("/%s%s#%s", htmlDir, StrUtil.subAfter(filename, htmlDir, true), route));
CollUtil.sort(versions, (o1, o2) -> -VersionComparator.INSTANCE.compare(o1, o2));
String path = buildPath(String.format("/%s%s/index.html#%s", htmlDir, versions.get(0), route));
response.sendRedirect(path);
} catch (IOException e) {
LogFactory.get().info(e);
@@ -80,6 +106,15 @@ public class GlobalConfig {
// setter\getter
///////////////////////////////////////////////////////////////////////////
public String getUploadDir() {
return uploadDir;
}
public void setUploadDir(String uploadDir) {
this.uploadDir = uploadDir;
}
public String getHost() {
return host;
}

View File

@@ -3,12 +3,11 @@ package com.tiesheng.util.config;
import cn.hutool.core.io.FileUtil;
import cn.hutool.http.HttpUtil;
import cn.hutool.log.LogFactory;
import com.tiesheng.util.ip2region.Searcher;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;
import javax.annotation.PostConstruct;
import java.io.FileNotFoundException;
import java.io.RandomAccessFile;
/**
* @author hao
@@ -17,8 +16,8 @@ import java.io.RandomAccessFile;
@ConfigurationProperties(prefix = "tiesheng.ip2region")
public class Ip2regionConfig {
private String dbUrl = "http://git.kepai365.com/zeng_wenhao/kepai-repo/raw/master/ipdb/ip2region.db";
private String dbPath = System.getProperty("user.dir") + "/ipdb/ip2region.db";
private String dbUrl = "http://git.kepai365.com/tiesheng/repository/raw/master/ipdb/ip2region.xdb";
private String dbPath = System.getProperty("user.dir") + "/runtime/ip2region/ip2region.xdb";
///////////////////////////////////////////////////////////////////////////
// 逻辑方法
@@ -35,15 +34,20 @@ public class Ip2regionConfig {
/**
* 获取db文件
* 搜索ip
*
* @param ip
* @return
*/
public RandomAccessFile getDbAccessFile() throws FileNotFoundException {
if (!FileUtil.exist(dbPath)) {
downloadDbFile();
public String search(String ip) {
String region = "";
try {
Searcher searcher = Searcher.newWithFileOnly(dbPath);
region = searcher.search(ip);
searcher.close();
} catch (Exception ignored) {
}
return new RandomAccessFile(dbPath, "r");
return region;
}
///////////////////////////////////////////////////////////////////////////

View File

@@ -1,76 +0,0 @@
package com.tiesheng.util.ip2region;
/**
* data block class
*
* @author chenxin<chenxin619315 @ gmail.com>
*/
public class DataBlock {
/**
* city id
*/
private int cityId;
/**
* region address
*/
private String region;
/**
* region ptr in the db file
*/
private int dataPtr;
/**
* construct method
*
* @param cityId
* @param region region string
* @param dataPtr data ptr
*/
public DataBlock(int cityId, String region, int dataPtr) {
this.cityId = cityId;
this.region = region;
this.dataPtr = dataPtr;
}
public DataBlock(int cityId, String region) {
this(cityId, region, 0);
}
public int getCityId() {
return cityId;
}
public DataBlock setCityId(int cityId) {
this.cityId = cityId;
return this;
}
public String getRegion() {
return region;
}
public DataBlock setRegion(String region) {
this.region = region;
return this;
}
public int getDataPtr() {
return dataPtr;
}
public DataBlock setDataPtr(int dataPtr) {
this.dataPtr = dataPtr;
return this;
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append(cityId).append('|').append(region).append('|').append(dataPtr);
return sb.toString();
}
}

View File

@@ -1,51 +0,0 @@
package com.tiesheng.util.ip2region;
/**
* database configuration class
*
* @author chenxin<chenxin619315 @ gmail.com>
*/
public class DbConfig {
/**
* total header data block size
*/
private int totalHeaderSize;
/**
* max index data block size
* u should always choice the fastest read block size
*/
private int indexBlockSize;
/**
* construct method
*
* @param totalHeaderSize
*/
public DbConfig(int totalHeaderSize) {
this.totalHeaderSize = totalHeaderSize;
this.indexBlockSize = 8192;
}
public DbConfig() {
this(8 * 2048);
}
public int getTotalHeaderSize() {
return totalHeaderSize;
}
public DbConfig setTotalHeaderSize(int totalHeaderSize) {
this.totalHeaderSize = totalHeaderSize;
return this;
}
public int getIndexBlockSize() {
return indexBlockSize;
}
public DbConfig setIndexBlockSize(int dataBlockSize) {
this.indexBlockSize = dataBlockSize;
return this;
}
}

View File

@@ -0,0 +1,34 @@
package com.tiesheng.util.ip2region;
/**
* @author hao
*/
public class Header {
public final int version;
public final int indexPolicy;
public final int createdAt;
public final int startIndexPtr;
public final int endIndexPtr;
public final byte[] buffer;
public Header(byte[] buff) {
assert buff.length >= 16;
version = Searcher.getInt2(buff, 0);
indexPolicy = Searcher.getInt2(buff, 2);
createdAt = Searcher.getInt(buff, 4);
startIndexPtr = Searcher.getInt(buff, 8);
endIndexPtr = Searcher.getInt(buff, 12);
buffer = buff;
}
@Override
public String toString() {
return "{" +
"Version: " + version + ',' +
"IndexPolicy: " + indexPolicy + ',' +
"CreatedAt: " + createdAt + ',' +
"StartIndexPtr: " + startIndexPtr + ',' +
"EndIndexPtr: " + endIndexPtr +
'}';
}
}

View File

@@ -1,102 +0,0 @@
package com.tiesheng.util.ip2region;
/**
* item index class
*
* @author chenxin<chenxin619315 @ gmail.com>
*/
public class IndexBlock {
private static int LENGTH = 12;
/**
* start ip address
*/
private long startIp;
/**
* end ip address
*/
private long endIp;
/**
* data ptr and data length
*/
private int dataPtr;
/**
* data length
*/
private int dataLen;
public IndexBlock(long startIp, long endIp, int dataPtr, int dataLen) {
this.startIp = startIp;
this.endIp = endIp;
this.dataPtr = dataPtr;
this.dataLen = dataLen;
}
public static int getIndexBlockLength() {
return LENGTH;
}
public long getStartIp() {
return startIp;
}
public IndexBlock setStartIp(long startIp) {
this.startIp = startIp;
return this;
}
public long getEndIp() {
return endIp;
}
public IndexBlock setEndIp(long endIp) {
this.endIp = endIp;
return this;
}
public int getDataPtr() {
return dataPtr;
}
public IndexBlock setDataPtr(int dataPtr) {
this.dataPtr = dataPtr;
return this;
}
public int getDataLen() {
return dataLen;
}
public IndexBlock setDataLen(int dataLen) {
this.dataLen = dataLen;
return this;
}
/**
* get the bytes for storage
*
* @return byte[]
*/
public byte[] getBytes() {
/*
* +------------+-----------+-----------+
* | 4bytes | 4bytes | 4bytes |
* +------------+-----------+-----------+
* start ip end ip data ptr + len
*/
byte[] b = new byte[12];
IpUtil.writeIntLong(b, 0, startIp); //start ip
IpUtil.writeIntLong(b, 4, endIp); //end ip
//write the data ptr and the length
long mix = dataPtr | ((dataLen << 24) & 0xFF000000L);
IpUtil.writeIntLong(b, 8, mix);
return b;
}
}

View File

@@ -1,416 +0,0 @@
package com.tiesheng.util.ip2region;
import cn.hutool.extra.spring.SpringUtil;
import com.tiesheng.util.config.Ip2regionConfig;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.nio.charset.StandardCharsets;
/**
* ip db searcher class (Not thread safe)
*
* @author chenxin<chenxin619315 @ gmail.com>
*/
public class Ip2Region {
private static Ip2Region ip2Region;
/**
* db config
*/
private final DbConfig dbConfig;
/**
* db file access handler
*/
private RandomAccessFile raf = null;
/**
* header blocks buffer
*/
private long[] headerSip = null;
private int[] headerPtr = null;
private int headerLength;
/**
* super blocks info
*/
private long firstIndexPtr = 0;
private long lastIndexPtr = 0;
private int totalIndexBlocks = 0;
/**
* for memory mode
* the original db binary string
*/
private byte[] dbBinStr = null;
/**
* construct class
*/
public Ip2Region() {
this.dbConfig = new DbConfig();
try {
Ip2regionConfig ip2regionConfig = SpringUtil.getBean(Ip2regionConfig.class);
raf = ip2regionConfig.getDbAccessFile();
} catch (Exception ignored) {
}
}
/**
* 获取单例
*
* @return
*/
public static Ip2Region getInstance() {
if (ip2Region == null) {
synchronized (Ip2Region.class) {
if (ip2Region == null) {
ip2Region = new Ip2Region();
}
}
}
return ip2Region;
}
/**
* get the region with an int ip address with memory binary search algorithm
*
* @param ip
* @throws IOException
*/
public DataBlock memorySearch(long ip) throws IOException {
int blen = IndexBlock.getIndexBlockLength();
if (dbBinStr == null) {
dbBinStr = new byte[(int) raf.length()];
raf.seek(0L);
raf.readFully(dbBinStr, 0, dbBinStr.length);
//initialize the global vars
firstIndexPtr = IpUtil.getIntLong(dbBinStr, 0);
lastIndexPtr = IpUtil.getIntLong(dbBinStr, 4);
totalIndexBlocks = (int) ((lastIndexPtr - firstIndexPtr) / blen) + 1;
}
//search the index blocks to define the data
int l = 0, h = totalIndexBlocks;
long sip, eip, dataptr = 0;
while (l <= h) {
int m = (l + h) >> 1;
int p = (int) (firstIndexPtr + m * blen);
sip = IpUtil.getIntLong(dbBinStr, p);
if (ip < sip) {
h = m - 1;
} else {
eip = IpUtil.getIntLong(dbBinStr, p + 4);
if (ip > eip) {
l = m + 1;
} else {
dataptr = IpUtil.getIntLong(dbBinStr, p + 8);
break;
}
}
}
//not matched
if (dataptr == 0) {
return null;
}
//get the data
int dataLen = (int) ((dataptr >> 24) & 0xFF);
int dataPtr = (int) ((dataptr & 0x00FFFFFF));
int cityId = (int) IpUtil.getIntLong(dbBinStr, dataPtr);
String region = new String(dbBinStr, dataPtr + 4, dataLen - 4, StandardCharsets.UTF_8);
return new DataBlock(cityId, region, dataPtr);
}
/**
* get the region throught the ip address with memory binary search algorithm
*
* @return DataBlock
* @throws IOException
*/
public DataBlock memorySearch() throws IOException {
return memorySearch(null);
}
/**
* get the region throught the ip address with memory binary search algorithm
*
* @param ip
* @return DataBlock
* @throws IOException
*/
public DataBlock memorySearch(String ip) throws IOException {
return memorySearch(IpUtil.ip2long(ip));
}
/**
* get by index ptr
*
* @param ptr
* @throws IOException
*/
public DataBlock getByIndexPtr(long ptr) throws IOException {
raf.seek(ptr);
byte[] buffer = new byte[12];
raf.readFully(buffer, 0, buffer.length);
long extra = IpUtil.getIntLong(buffer, 8);
int dataLen = (int) ((extra >> 24) & 0xFF);
int dataPtr = (int) ((extra & 0x00FFFFFF));
raf.seek(dataPtr);
byte[] data = new byte[dataLen];
raf.readFully(data, 0, data.length);
int cityId = (int) IpUtil.getIntLong(data, 0);
String region = new String(data, 4, data.length - 4, StandardCharsets.UTF_8);
return new DataBlock(cityId, region, dataPtr);
}
/**
* get the region with an int ip address with b-tree algorithm
*
* @param ip
* @throws IOException
*/
public DataBlock btreeSearch(long ip) throws IOException {
//check and load the header
if (headerSip == null) {
raf.seek(8L);
byte[] b = new byte[dbConfig.getTotalHeaderSize()];
raf.readFully(b, 0, b.length);
//fill the header
int len = b.length >> 3, idx = 0;
headerSip = new long[len];
headerPtr = new int[len];
long startIp, dataPtr;
for (int i = 0; i < b.length; i += 8) {
startIp = IpUtil.getIntLong(b, i);
dataPtr = IpUtil.getIntLong(b, i + 4);
if (dataPtr == 0) {
break;
}
headerSip[idx] = startIp;
headerPtr[idx] = (int) dataPtr;
idx++;
}
headerLength = idx;
}
//1. define the index block with the binary search
if (ip == headerSip[0]) {
return getByIndexPtr(headerPtr[0]);
} else if (ip == headerSip[headerLength - 1]) {
return getByIndexPtr(headerPtr[headerLength - 1]);
}
int l = 0, h = headerLength, sptr = 0, eptr = 0;
while (l <= h) {
int m = (l + h) >> 1;
//perfetc matched, just return it
if (ip == headerSip[m]) {
if (m > 0) {
sptr = headerPtr[m - 1];
eptr = headerPtr[m];
} else {
sptr = headerPtr[m];
eptr = headerPtr[m + 1];
}
break;
}
//less then the middle value
if (ip < headerSip[m]) {
if (m == 0) {
sptr = headerPtr[m];
eptr = headerPtr[m + 1];
break;
} else if (ip > headerSip[m - 1]) {
sptr = headerPtr[m - 1];
eptr = headerPtr[m];
break;
}
h = m - 1;
} else {
if (m == headerLength - 1) {
sptr = headerPtr[m - 1];
eptr = headerPtr[m];
break;
} else if (ip <= headerSip[m + 1]) {
sptr = headerPtr[m];
eptr = headerPtr[m + 1];
break;
}
l = m + 1;
}
}
//match nothing just stop it
if (sptr == 0) {
return null;
}
//2. search the index blocks to define the data
int blockLen = eptr - sptr, blen = IndexBlock.getIndexBlockLength();
//include the right border block
byte[] iBuffer = new byte[blockLen + blen];
raf.seek(sptr);
raf.readFully(iBuffer, 0, iBuffer.length);
l = 0;
h = blockLen / blen;
long sip, eip, dataptr = 0;
while (l <= h) {
int m = (l + h) >> 1;
int p = m * blen;
sip = IpUtil.getIntLong(iBuffer, p);
if (ip < sip) {
h = m - 1;
} else {
eip = IpUtil.getIntLong(iBuffer, p + 4);
if (ip > eip) {
l = m + 1;
} else {
dataptr = IpUtil.getIntLong(iBuffer, p + 8);
break;
}
}
}
//not matched
if (dataptr == 0) {
return null;
}
//3. get the data
int dataLen = (int) ((dataptr >> 24) & 0xFF);
int dataPtr = (int) ((dataptr & 0x00FFFFFF));
raf.seek(dataPtr);
byte[] data = new byte[dataLen];
raf.readFully(data, 0, data.length);
int cityId = (int) IpUtil.getIntLong(data, 0);
String region = new String(data, 4, data.length - 4, StandardCharsets.UTF_8);
return new DataBlock(cityId, region, dataPtr);
}
/**
* get the region throught the ip address with b-tree search algorithm
*
* @param ip
* @return DataBlock
* @throws IOException
*/
public DataBlock btreeSearch(String ip) {
try {
return btreeSearch(IpUtil.ip2long(ip));
} catch (IOException ignored) {
}
return new DataBlock(0, "未知IP");
}
/**
* get the region with a int ip address with binary search algorithm
*
* @param ip
* @throws IOException
*/
public DataBlock binarySearch(long ip) throws IOException {
int blen = IndexBlock.getIndexBlockLength();
if (totalIndexBlocks == 0) {
raf.seek(0L);
byte[] superBytes = new byte[8];
raf.readFully(superBytes, 0, superBytes.length);
//initialize the global vars
firstIndexPtr = IpUtil.getIntLong(superBytes, 0);
lastIndexPtr = IpUtil.getIntLong(superBytes, 4);
totalIndexBlocks = (int) ((lastIndexPtr - firstIndexPtr) / blen) + 1;
}
//search the index blocks to define the data
int l = 0, h = totalIndexBlocks;
byte[] buffer = new byte[blen];
long sip, eip, dataptr = 0;
while (l <= h) {
int m = (l + h) >> 1;
raf.seek(firstIndexPtr + m * blen);
raf.readFully(buffer, 0, buffer.length);
sip = IpUtil.getIntLong(buffer, 0);
if (ip < sip) {
h = m - 1;
} else {
eip = IpUtil.getIntLong(buffer, 4);
if (ip > eip) {
l = m + 1;
} else {
dataptr = IpUtil.getIntLong(buffer, 8);
break;
}
}
}
//not matched
if (dataptr == 0) {
return null;
}
//get the data
int dataLen = (int) ((dataptr >> 24) & 0xFF);
int dataPtr = (int) ((dataptr & 0x00FFFFFF));
raf.seek(dataPtr);
byte[] data = new byte[dataLen];
raf.readFully(data, 0, data.length);
int cityId = (int) IpUtil.getIntLong(data, 0);
String region = new String(data, 4, data.length - 4, StandardCharsets.UTF_8);
return new DataBlock(cityId, region, dataPtr);
}
/**
* get the region throught the ip address with binary search algorithm
*
* @param ip
* @return DataBlock
* @throws IOException
*/
public DataBlock binarySearch(String ip) throws IOException {
return binarySearch(IpUtil.ip2long(ip));
}
/**
* get the db config
*
* @return DbConfig
*/
public DbConfig getDbConfig() {
return dbConfig;
}
/**
* close the db
*
* @throws IOException
*/
public void close() throws IOException {
headerSip = null;
headerPtr = null;
dbBinStr = null;
if (raf != null) {
raf.close();
}
}
}

View File

@@ -1,117 +0,0 @@
package com.tiesheng.util.ip2region;
/**
* util class
*
* @author chenxin<chenxin619315 @ gmail.com>
*/
public class IpUtil {
/**
* write specfield bytes to a byte array start from offset
*
* @param b
* @param offset
* @param v
* @param bytes
*/
public static void write(byte[] b, int offset, long v, int bytes) {
for (int i = 0; i < bytes; i++) {
b[offset++] = (byte) ((v >>> (8 * i)) & 0xFF);
}
}
/**
* write a int to a byte array
*
* @param b
* @param offset
* @param v
*/
public static void writeIntLong(byte[] b, int offset, long v) {
b[offset++] = (byte) ((v >> 0) & 0xFF);
b[offset++] = (byte) ((v >> 8) & 0xFF);
b[offset++] = (byte) ((v >> 16) & 0xFF);
b[offset] = (byte) ((v >> 24) & 0xFF);
}
/**
* get a int from a byte array start from the specifiled offset
*
* @param b
* @param offset
*/
public static long getIntLong(byte[] b, int offset) {
return (
((b[offset++] & 0x000000FFL)) |
((b[offset++] << 8) & 0x0000FF00L) |
((b[offset++] << 16) & 0x00FF0000L) |
((b[offset] << 24) & 0xFF000000L)
);
}
/**
* get a int from a byte array start from the specifield offset
*
* @param b
* @param offset
*/
public static int getInt3(byte[] b, int offset) {
return (
(b[offset++] & 0x000000FF) |
(b[offset++] & 0x0000FF00) |
(b[offset] & 0x00FF0000)
);
}
public static int getInt2(byte[] b, int offset) {
return (
(b[offset++] & 0x000000FF) |
(b[offset] & 0x0000FF00)
);
}
public static int getInt1(byte[] b, int offset) {
return (
(b[offset] & 0x000000FF)
);
}
/**
* string ip to long ip
*
* @param ip
* @return long
*/
public static long ip2long(String ip) {
String[] p = ip.split("\\.");
if (p.length != 4) {
return 0;
}
int p1 = ((Integer.valueOf(p[0]) << 24) & 0xFF000000);
int p2 = ((Integer.valueOf(p[1]) << 16) & 0x00FF0000);
int p3 = ((Integer.valueOf(p[2]) << 8) & 0x0000FF00);
int p4 = ((Integer.valueOf(p[3]) << 0) & 0x000000FF);
return ((p1 | p2 | p3 | p4) & 0xFFFFFFFFL);
}
/**
* int to ip string
*
* @param ip
* @return string
*/
public static String long2ip(long ip) {
StringBuilder sb = new StringBuilder();
sb
.append((ip >> 24) & 0xFF).append('.')
.append((ip >> 16) & 0xFF).append('.')
.append((ip >> 8) & 0xFF).append('.')
.append((ip >> 0) & 0xFF);
return sb.toString();
}
}

View File

@@ -0,0 +1,258 @@
package com.tiesheng.util.ip2region;
import java.io.IOException;
import java.io.RandomAccessFile;
public class Searcher {
// constant defined copied from the xdb maker
public static final int HeaderInfoLength = 256;
public static final int VectorIndexRows = 256;
public static final int VectorIndexCols = 256;
public static final int VectorIndexSize = 8;
public static final int SegmentIndexSize = 14;
public static final byte[] shiftIndex = {24, 16, 8, 0};
// random access file handle for file based search
private final RandomAccessFile handle;
// vector index.
// use the byte[] instead of VectorIndex entry array to keep
// the minimal memory allocation.
private final byte[] vectorIndex;
// xdb content buffer, used for in-memory search
private final byte[] contentBuff;
// --- static method to create searchers
private int ioCount = 0;
public Searcher(String dbFile, byte[] vectorIndex, byte[] cBuff) throws IOException {
if (cBuff != null) {
this.handle = null;
this.vectorIndex = null;
this.contentBuff = cBuff;
} else {
this.handle = new RandomAccessFile(dbFile, "r");
this.vectorIndex = vectorIndex;
this.contentBuff = null;
}
}
public static Searcher newWithFileOnly(String dbPath) throws IOException {
return new Searcher(dbPath, null, null);
}
// --- End of creator
public static Searcher newWithVectorIndex(String dbPath, byte[] vectorIndex) throws IOException {
return new Searcher(dbPath, vectorIndex, null);
}
public static Searcher newWithBuffer(byte[] cBuff) throws IOException {
return new Searcher(null, null, cBuff);
}
public static Header loadHeader(RandomAccessFile handle) throws IOException {
handle.seek(0);
final byte[] buff = new byte[HeaderInfoLength];
handle.read(buff);
return new Header(buff);
}
public static Header loadHeaderFromFile(String dbPath) throws IOException {
final RandomAccessFile handle = new RandomAccessFile(dbPath, "r");
final Header header = loadHeader(handle);
handle.close();
return header;
}
public static byte[] loadVectorIndex(RandomAccessFile handle) throws IOException {
handle.seek(HeaderInfoLength);
int len = VectorIndexRows * VectorIndexCols * VectorIndexSize;
final byte[] buff = new byte[len];
int rLen = handle.read(buff);
if (rLen != len) {
throw new IOException("incomplete read: read bytes should be " + len);
}
return buff;
}
public static byte[] loadVectorIndexFromFile(String dbPath) throws IOException {
final RandomAccessFile handle = new RandomAccessFile(dbPath, "r");
final byte[] vIndex = loadVectorIndex(handle);
handle.close();
return vIndex;
}
// --- static cache util function
public static byte[] loadContent(RandomAccessFile handle) throws IOException {
handle.seek(0);
final byte[] buff = new byte[(int) handle.length()];
int rLen = handle.read(buff);
if (rLen != buff.length) {
throw new IOException("incomplete read: read bytes should be " + buff.length);
}
return buff;
}
public static byte[] loadContentFromFile(String dbPath) throws IOException {
final RandomAccessFile handle = new RandomAccessFile(dbPath, "r");
final byte[] content = loadContent(handle);
handle.close();
return content;
}
/* get an int from a byte array start from the specified offset */
public static long getIntLong(byte[] b, int offset) {
return (
((b[offset++] & 0x000000FFL)) |
((b[offset++] << 8) & 0x0000FF00L) |
((b[offset++] << 16) & 0x00FF0000L) |
((b[offset] << 24) & 0xFF000000L)
);
}
public static int getInt(byte[] b, int offset) {
return (
((b[offset++] & 0x000000FF)) |
((b[offset++] << 8) & 0x0000FF00) |
((b[offset++] << 16) & 0x00FF0000) |
((b[offset] << 24) & 0xFF000000)
);
}
public static int getInt2(byte[] b, int offset) {
return (
((b[offset++] & 0x000000FF)) |
((b[offset] << 8) & 0x0000FF00)
);
}
/* long int to ip string */
public static String long2ip(long ip) {
return String.valueOf((ip >> 24) & 0xFF) + '.' +
((ip >> 16) & 0xFF) + '.' + ((ip >> 8) & 0xFF) + '.' + ((ip) & 0xFF);
}
// --- End cache load util function
// --- static util method
/* check the specified ip address */
public static long checkIP(String ip) throws Exception {
String[] ps = ip.split("\\.");
if (ps.length != 4) {
throw new Exception("invalid ip address `" + ip + "`");
}
long ipDst = 0;
for (int i = 0; i < ps.length; i++) {
int val = Integer.parseInt(ps[i]);
if (val > 255) {
throw new Exception("ip part `" + ps[i] + "` should be less then 256");
}
ipDst |= ((long) val << shiftIndex[i]);
}
return ipDst & 0xFFFFFFFFL;
}
public void close() throws IOException {
if (this.handle != null) {
this.handle.close();
}
}
public int getIOCount() {
return ioCount;
}
public String search(String ipStr) throws Exception {
long ip = checkIP(ipStr);
return search(ip);
}
public String search(long ip) throws IOException {
// reset the global counter
this.ioCount = 0;
// locate the segment index block based on the vector index
int sPtr = 0, ePtr = 0;
int il0 = (int) ((ip >> 24) & 0xFF);
int il1 = (int) ((ip >> 16) & 0xFF);
int idx = il0 * VectorIndexCols * VectorIndexSize + il1 * VectorIndexSize;
// System.out.printf("il0: %d, il1: %d, idx: %d\n", il0, il1, idx);
if (vectorIndex != null) {
sPtr = getInt(vectorIndex, idx);
ePtr = getInt(vectorIndex, idx + 4);
} else if (contentBuff != null) {
sPtr = getInt(contentBuff, HeaderInfoLength + idx);
ePtr = getInt(contentBuff, HeaderInfoLength + idx + 4);
} else {
final byte[] buff = new byte[VectorIndexSize];
read(HeaderInfoLength + idx, buff);
sPtr = getInt(buff, 0);
ePtr = getInt(buff, 4);
}
// System.out.printf("sPtr: %d, ePtr: %d\n", sPtr, ePtr);
// binary search the segment index block to get the region info
final byte[] buff = new byte[SegmentIndexSize];
int dataLen = -1, dataPtr = -1;
int l = 0, h = (ePtr - sPtr) / SegmentIndexSize;
while (l <= h) {
int m = (l + h) >> 1;
int p = sPtr + m * SegmentIndexSize;
// read the segment index
read(p, buff);
long sip = getIntLong(buff, 0);
if (ip < sip) {
h = m - 1;
} else {
long eip = getIntLong(buff, 4);
if (ip > eip) {
l = m + 1;
} else {
dataLen = getInt2(buff, 8);
dataPtr = getInt(buff, 10);
break;
}
}
}
// empty match interception
// System.out.printf("dataLen: %d, dataPtr: %d\n", dataLen, dataPtr);
if (dataPtr < 0) {
return null;
}
// load and return the region data
final byte[] regionBuff = new byte[dataLen];
read(dataPtr, regionBuff);
return new String(regionBuff, "utf-8");
}
protected void read(int offset, byte[] buffer) throws IOException {
// check the in-memory buffer first
if (contentBuff != null) {
// @TODO: reduce data copying, directly decode the data ?
System.arraycopy(contentBuff, offset, buffer, 0, buffer.length);
return;
}
// read from the file handle
assert handle != null;
handle.seek(offset);
this.ioCount++;
int rLen = handle.read(buffer);
if (rLen != buffer.length) {
throw new IOException("incomplete read: read bytes should be " + buffer.length);
}
}
}

View File

@@ -129,6 +129,15 @@ public class ApiResp<T> {
}
/**
* 是否成功
*
* @return
*/
public boolean successful() {
return code == CODE_OK;
}
///////////////////////////////////////////////////////////////////////////
// setter\getter
///////////////////////////////////////////////////////////////////////////

View File

@@ -2,9 +2,12 @@ package com.tiesheng.util.pojos;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.CharUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.extra.spring.SpringUtil;
import cn.hutool.http.HttpUtil;
import com.tiesheng.util.config.GlobalConfig;
public class FileUploadPath {
@@ -29,19 +32,26 @@ public class FileUploadPath {
* @param fileName
* @return
*/
public static FileUploadPath get(String fileName) {
public static FileUploadPath file(String fileName) {
// 下载文件
fileName = downloadFile(fileName);
fileName = fileDownload(fileName);
FileUploadPath pathBean = new FileUploadPath();
String tempPath = fileName;
if (!StrUtil.startWith(tempPath, CharUtil.SLASH)) {
tempPath = CharUtil.SLASH + tempPath;
}
if (!StrUtil.startWith(tempPath, UPLOAD_FOLDER)) {
tempPath = UPLOAD_FOLDER + DateUtil.format(DateUtil.date(), "yyyy-MM") + "/" + fileName;
tempPath = UPLOAD_FOLDER + DateUtil.format(DateUtil.date(), "yyyy-MM") + CharUtil.SLASH + fileName;
}
pathBean.setHttpPath(tempPath);
pathBean.setAbsolutePath(String.format("%s/static%s", System.getProperty("user.dir"), tempPath));
String tempAbs = String.format("%s/static%s", SpringUtil.getBean(GlobalConfig.class).getUploadDir(), tempPath);
tempAbs = FileUtil.normalize(tempAbs);
pathBean.setAbsolutePath(tempAbs);
FileUtil.mkParentDirs(pathBean.getAbsolutePath());
return pathBean;
@@ -51,40 +61,33 @@ public class FileUploadPath {
/**
* 下载http文件
*
* @param fileName
* @param httpUrl
* @return
*/
public static String downloadFile(String fileName) {
if (!StrUtil.startWith(fileName, "http")) {
return fileName;
public static String fileDownload(String httpUrl) {
if (!StrUtil.startWith(httpUrl, "http")) {
return httpUrl;
}
String newFileName = UPLOAD_FOLDER + StrUtil.subAfter(fileName, UPLOAD_FOLDER, true);
FileUploadPath uploadPath = get(newFileName);
String newFileName = UPLOAD_FOLDER + StrUtil.subAfter(httpUrl, UPLOAD_FOLDER, true);
FileUploadPath uploadPath = file(newFileName);
if (!FileUtil.exist(uploadPath.getAbsolutePath())) {
HttpUtil.downloadFile(fileName, uploadPath.getAbsolutePath());
HttpUtil.downloadFile(httpUrl, uploadPath.getAbsolutePath());
}
return uploadPath.getHttpPath();
}
/**
* 随机生成一个文件路径
*
* @return
*/
public static FileUploadPath random() {
return get(IdUtil.simpleUUID());
}
/**
* 随机生成一个文件路径
*
* @return
*/
public static FileUploadPath random(String fileExt) {
return get(IdUtil.simpleUUID() + "." + fileExt);
String fileName = IdUtil.simpleUUID();
if (!StrUtil.isEmpty(fileExt)) {
fileName = fileName + "." + fileExt;
}
return file(fileName);
}
@@ -95,20 +98,9 @@ public class FileUploadPath {
* @return
*/
public static FileUploadPath folder(String folder) {
FileUploadPath pathBean = new FileUploadPath();
String tempFolder = folder;
if (!StrUtil.startWith(tempFolder, UPLOAD_FOLDER)) {
tempFolder = UPLOAD_FOLDER + tempFolder;
}
if (!StrUtil.endWith(folder, "/")) {
tempFolder = tempFolder + "/";
}
pathBean.setHttpPath(tempFolder);
pathBean.setAbsolutePath(String.format("%s/static%s", System.getProperty("user.dir"), tempFolder));
FileUtil.mkParentDirs(pathBean.getAbsolutePath());
return pathBean;
FileUploadPath file = file(folder);
FileUtil.mkdir(file.getAbsolutePath());
return file;
}

View File

@@ -0,0 +1,36 @@
package com.tiesheng.util.pojos;
public class IdName {
private String id;
private String name;
private String extra;
///////////////////////////////////////////////////////////////////////////
// setter\getter
///////////////////////////////////////////////////////////////////////////
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getExtra() {
return extra;
}
public void setExtra(String extra) {
this.extra = extra;
}
}

View File

@@ -4,9 +4,9 @@
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>
<parent>
<groupId>com.tiesheng</groupId>
<groupId>com.tiesheng.springboot-parent</groupId>
<artifactId>springboot-parent</artifactId>
<version>0.2.0</version>
<version>1.0.1</version>
</parent>
<artifactId>springboot-web</artifactId>
@@ -58,35 +58,35 @@
</dependency>
<dependency>
<groupId>com.tiesheng</groupId>
<groupId>com.tiesheng.springboot-parent</groupId>
<artifactId>springboot-util</artifactId>
</dependency>
<dependency>
<groupId>com.tiesheng</groupId>
<artifactId>springboot-db-migration</artifactId>
<groupId>com.tiesheng.springboot-parent</groupId>
<artifactId>springboot-database</artifactId>
</dependency>
<dependency>
<groupId>com.tiesheng</groupId>
<groupId>com.tiesheng.springboot-parent</groupId>
<artifactId>springboot-poi</artifactId>
</dependency>
<dependency>
<groupId>com.tiesheng</groupId>
<artifactId>springboot-annotation</artifactId>
</dependency>
<dependency>
<groupId>com.tiesheng</groupId>
<groupId>com.tiesheng.springboot-parent</groupId>
<artifactId>springboot-login</artifactId>
</dependency>
<dependency>
<groupId>com.tiesheng</groupId>
<groupId>com.tiesheng.springboot-parent</groupId>
<artifactId>springboot-message</artifactId>
</dependency>
<dependency>
<groupId>com.tiesheng.springboot-parent</groupId>
<artifactId>springboot-encrypt</artifactId>
</dependency>
</dependencies>
</project>

View File

@@ -1,9 +1,9 @@
package com.tiesheng.core;
import com.tiesheng.core.service.TieshengWebConfigurer;
import com.tiesheng.database.DatabaseAutoConfigurer;
import com.tiesheng.login.LoginAutoConfigurer;
import com.tiesheng.message.MessageAutoConfigurer;
import com.tiesheng.migration.MigrationAutoConfigurer;
import com.tiesheng.util.UtilAutoConfigurer;
import org.springframework.context.annotation.Import;
@@ -20,7 +20,7 @@ import java.lang.annotation.*;
MessageAutoConfigurer.class,
CoreAutoConfigurer.class,
LoginAutoConfigurer.class,
MigrationAutoConfigurer.class
DatabaseAutoConfigurer.class
})
public @interface EnableTieshengWeb {

View File

@@ -1,8 +1,7 @@
package com.tiesheng.core.config.json;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.alibaba.fastjson.support.config.FastJsonConfig;
import com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter;
import com.tiesheng.util.CommonUtil;
import org.springframework.boot.autoconfigure.http.HttpMessageConverters;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@@ -25,14 +24,9 @@ public class FastJsonMessageConverter {
*/
@Bean
public HttpMessageConverters fastJsonHttpMessageConverters() {
FastJsonConfig config = new FastJsonConfig();
config.setSerializerFeatures(SerializerFeature.WriteMapNullValue,
SerializerFeature.WriteNullStringAsEmpty,
SerializerFeature.WriteEnumUsingName);
config.setDateFormat("yyyy-MM-dd HH:mm:ss");
FastJsonHttpMessageConverter fastConverter = new FastJsonHttpMessageConverter();
fastConverter.setFastJsonConfig(config);
fastConverter.setFastJsonConfig(CommonUtil.fastJsonConfig());
fastConverter.setDefaultCharset(StandardCharsets.UTF_8);
List<MediaType> mediaTypes = new ArrayList<>();

View File

@@ -5,6 +5,7 @@ import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.StrUtil;
import com.tiesheng.annotation.operation.OperationLog;
import com.tiesheng.core.service.CoreLogService;
import com.tiesheng.util.ServletKit;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
@@ -13,6 +14,7 @@ import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;
@@ -35,7 +37,7 @@ public class OperationAspect {
CoreLogService coreLogService;
@Pointcut("@annotation(com.tiesheng.annotation.operation.OperationLog)")
@Pointcut("execution(* com..controller..*.*(..))")
public void methodArgs() {
}
@@ -48,11 +50,24 @@ public class OperationAspect {
*/
@Around("methodArgs()")
public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
// GET请求不处理
HttpServletRequest request = ServletKit.getRequest();
if (StrUtil.equalsIgnoreCase(request.getMethod(), "GET")) {
return joinPoint.proceed(joinPoint.getArgs());
}
String title = "", subject = "";
String insertKey = "";
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
Method method = signature.getMethod();
OperationLog operationLog = method.getAnnotation(OperationLog.class);
String subject = operationLog.subject();
String insertKey = operationLog.insertKey();
if (operationLog != null) {
title = operationLog.title();
subject = operationLog.subject();
insertKey = operationLog.insertKey();
}
Object reqObj = null;
Map<String, Object> allParams = new HashMap<>(16);
@@ -65,7 +80,6 @@ public class OperationAspect {
allParams.putAll(BeanUtil.beanToMap(response));
if (!StrUtil.isEmpty(subject)) {
// 添加、编辑关键字处理
if (!StrUtil.isEmpty(insertKey)) {
String insertVal = MapUtil.getStr(allParams, insertKey);
@@ -74,9 +88,12 @@ public class OperationAspect {
// 占位符处理
subject = StrUtil.format(subject, allParams);
} else {
title = method.getName();
subject = ServletKit.getRequest().getRequestURI();
}
coreLogService.addOperationLog(operationLog.title(), subject, reqObj);
coreLogService.addOperationLog(title, subject, reqObj);
return response;
}

View File

@@ -1,21 +1,26 @@
package com.tiesheng.core.controller;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.tiesheng.annotation.token.TokenIgnore;
import com.tiesheng.core.pojos.dao.CoreConfigEnum;
import com.tiesheng.core.pojos.dao.CoreConfigFunc;
import com.tiesheng.core.pojos.dao.CoreConfigSystem;
import com.tiesheng.core.pojos.dto.PageDTO;
import com.tiesheng.core.pojos.dto.config.ConfigFuncDTO;
import com.tiesheng.core.pojos.dto.config.ConfigSystemDTO;
import com.tiesheng.core.pojos.dto.config.EnumTypeDTO;
import com.tiesheng.core.service.CoreConfigService;
import com.tiesheng.core.service.TieshengWebConfigurer;
import com.tiesheng.util.exception.ApiException;
import com.tiesheng.util.pojos.ApiResp;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import javax.validation.Valid;
import java.util.List;
/**
@@ -27,6 +32,8 @@ public class ConfigController {
@Autowired
CoreConfigService coreConfigService;
@Autowired
TieshengWebConfigurer tieshengWebConfigurer;
/**
@@ -68,6 +75,8 @@ public class ConfigController {
configKey.setConfigVal(dto.getConfigVal());
configKey.setRemark(dto.getRemark());
configKey.setExtra(dto.getExtra());
tieshengWebConfigurer.configSystemCheck(configKey);
coreConfigService.updateById(configKey);
return ApiResp.respOK("");
@@ -95,4 +104,34 @@ public class ConfigController {
}
/**
* 功能点列表
*
* @return
*/
@GetMapping("/func/page")
public ApiResp<List<CoreConfigFunc>> funcList(Integer isUsed, PageDTO dto) {
QueryWrapper<CoreConfigFunc> queryWrapper = new QueryWrapper<CoreConfigFunc>().eq("is_deleted", 0);
if (isUsed != null) {
queryWrapper.eq("is_used", isUsed);
}
dto.likeColumns(queryWrapper, "name");
Page<CoreConfigFunc> page = dto.pageObj();
coreConfigService.getFuncMapper().selectPage(page, queryWrapper);
return ApiResp.respOK(page.getRecords(), page.getTotal());
}
/**
* 功能点更新
*
* @param dto
* @return
*/
@PostMapping("/func/update")
public ApiResp<String> funcUpdate(@Valid @RequestBody ConfigFuncDTO dto) {
CoreConfigFunc configFunc = BeanUtil.copyProperties(dto, CoreConfigFunc.class);
coreConfigService.getFuncMapper().updateById(configFunc);
return ApiResp.respOK("");
}
}

View File

@@ -0,0 +1,120 @@
package com.tiesheng.core.controller;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.tiesheng.core.pojos.dao.CoreJob;
import com.tiesheng.core.pojos.dto.IdDTO;
import com.tiesheng.core.pojos.dto.PageDTO;
import com.tiesheng.core.pojos.dto.job.JobUpdateDTO;
import com.tiesheng.core.pojos.dto.job.JobUpdateRxDTO;
import com.tiesheng.core.pojos.dto.job.JobUserAssignDTO;
import com.tiesheng.core.pojos.dto.job.JobUserOwner;
import com.tiesheng.core.service.CoreJobService;
import com.tiesheng.login.config.token.TsTokenConfig;
import com.tiesheng.util.exception.ApiException;
import com.tiesheng.util.pojos.ApiResp;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import javax.validation.Valid;
import java.util.List;
/**
* @author hao
*/
@RestController
@RequestMapping("/job")
public class JobController {
@Autowired
CoreJobService coreJobService;
/**
* 获取职位列表
*
* @return
*/
@GetMapping("/list")
public ApiResp<List<CoreJob>> list(PageDTO dto) {
QueryWrapper<CoreJob> queryWrapper = new QueryWrapper<CoreJob>().eq("is_deleted", 0);
dto.likeColumns(queryWrapper, "name");
List<CoreJob> jobList = coreJobService.list(queryWrapper);
return ApiResp.respOK(jobList);
}
/**
* 添加、编辑职位
*
* @return
*/
@PostMapping("/update")
public ApiResp<String> update(@Valid @RequestBody JobUpdateDTO dto) {
CoreJob job = BeanUtil.copyProperties(dto, CoreJob.class);
if (!StrUtil.isEmpty(job.getId())) {
CoreJob byId = coreJobService.getById(job.getId());
if (byId != null && byId.getIsSystem() == 1) {
throw new ApiException("系统配置,无法编辑");
}
}
coreJobService.saveOrUpdate(job);
return ApiResp.respOK("");
}
/**
* 获取关系
*
* @param dto
* @return
*/
@GetMapping("/func/rx")
public ApiResp<List<String>> funcRx(@Valid IdDTO dto) {
List<String> list = coreJobService.getBaseMapper().getJobFunc(dto.getId(), null);
return ApiResp.respOK(list);
}
/**
* 更新职位关系
*
* @return
*/
@PostMapping("/func/rx")
public ApiResp<String> updateJobRx(@Valid @RequestBody JobUpdateRxDTO dto) {
coreJobService.updateJobRx(dto.getJobId(), StrUtil.split(dto.getPoints(), ","));
return ApiResp.respOK("");
}
/**
* 用户职位分配
*
* @return
*/
@PostMapping("/user/assign")
public ApiResp<String> userAssign(@Valid @RequestBody JobUserAssignDTO dto) {
coreJobService.userAssign(dto.getUserId(), dto.getJobId());
return ApiResp.respOK("");
}
/**
* 获取用户自己的
*
* @return
*/
@GetMapping("/user/owner")
public ApiResp<List<JobUserOwner>> userOwner() {
List<JobUserOwner> coreJobUsers = coreJobService.getJobUserMapper().list(TsTokenConfig.get().getId());
coreJobUsers.forEach(it -> {
List<String> list = coreJobService.getBaseMapper().getJobFunc(it.getJobId(), 1);
it.setPoints(list);
});
return ApiResp.respOK(coreJobUsers);
}
}

View File

@@ -6,7 +6,9 @@ import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.tiesheng.core.pojos.dao.CoreLogLogin;
import com.tiesheng.core.pojos.dao.CoreLogMessage;
import com.tiesheng.core.pojos.dao.CoreLogOperation;
import com.tiesheng.core.pojos.dao.CoreLogProcess;
import com.tiesheng.core.pojos.dto.PageDTO;
import com.tiesheng.core.pojos.vo.ProcessDetailVo;
import com.tiesheng.core.service.CoreLogService;
import com.tiesheng.util.pojos.ApiResp;
import org.springframework.beans.factory.annotation.Autowired;
@@ -88,4 +90,36 @@ public class LogController {
return ApiResp.respOK(page.getRecords(), page.getTotal());
}
/**
* 过程日志列表
*
* @return
*/
@GetMapping("/process/page")
public ApiResp<List<CoreLogProcess>> processPage(String type, @Valid PageDTO dto) {
QueryWrapper<CoreLogProcess> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("is_deleted", 0);
if (!StrUtil.isEmpty(type)) {
queryWrapper.eq("type", type);
}
dto.likeColumns(queryWrapper, "title");
queryWrapper.orderByDesc("create_time");
Page<CoreLogProcess> page = dto.pageObj();
coreLogService.getCoreLogProcessMapper().selectPage(page, queryWrapper);
return ApiResp.respOK(page.getRecords(), page.getTotal());
}
/**
* 过程日志详情
*
* @return
*/
@GetMapping("/process/detail")
public ApiResp<ProcessDetailVo> processPage(String id) {
ProcessDetailVo processDetail = coreLogService.getProcessDetail(id);
return ApiResp.respOK(processDetail);
}
}

View File

@@ -4,6 +4,9 @@ package com.tiesheng.core.controller;
import cn.hutool.captcha.LineCaptcha;
import cn.hutool.core.util.IdUtil;
import com.tiesheng.annotation.token.TokenIgnore;
import com.tiesheng.core.pojos.dto.ChunkCheckDTO;
import com.tiesheng.core.pojos.dto.ChunkMergeDTO;
import com.tiesheng.core.pojos.dto.ChunkStartDTO;
import com.tiesheng.core.pojos.dto.ImageCodeDTO;
import com.tiesheng.core.pojos.vo.PicVerifyVo;
import com.tiesheng.core.service.FileUploadService;
@@ -68,8 +71,8 @@ public class ToolController {
*/
@TokenIgnore
@PostMapping(value = "/file/chunk_start")
public ApiResp<String> fileChunkStart(String fileExt) {
fileUploadService.chunkStart(fileExt);
public ApiResp<String> fileChunkStart(@RequestBody ChunkStartDTO dto) {
fileUploadService.chunkStart(dto.getFileExt());
return ApiResp.respOK("");
}
@@ -81,8 +84,8 @@ public class ToolController {
*/
@TokenIgnore
@PostMapping("/file/chunk_check")
public ApiResp<Boolean> fileChunkCheck(String fileMd5, Integer chunk) {
boolean exist = fileUploadService.chunkCheck(fileMd5, chunk);
public ApiResp<Boolean> fileChunkCheck(@RequestBody ChunkCheckDTO dto) {
boolean exist = fileUploadService.chunkCheck(dto.getFileMd5(), dto.getChunk());
return ApiResp.respOK(exist);
}
@@ -108,8 +111,8 @@ public class ToolController {
*/
@TokenIgnore
@PostMapping("/file/chunk_merge")
public ApiResp<String> fileChunkMerge(String fileMd5, String fileExt) {
String path = fileUploadService.chunkMerge(fileMd5, fileExt);
public ApiResp<String> fileChunkMerge(@RequestBody ChunkMergeDTO dto) {
String path = fileUploadService.chunkMerge(dto.getFileMd5(), dto.getFileExt());
return ApiResp.respOK(path);
}

View File

@@ -0,0 +1,11 @@
package com.tiesheng.core.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.tiesheng.core.pojos.dao.CoreConfigFunc;
import com.tiesheng.util.pojos.IdName;
import org.apache.ibatis.annotations.Param;
import java.util.List;
public interface CoreConfigFuncMapper extends BaseMapper<CoreConfigFunc> {
}

View File

@@ -0,0 +1,36 @@
package com.tiesheng.core.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.tiesheng.core.pojos.dao.CoreJob;
import com.tiesheng.util.pojos.IdName;
import org.apache.ibatis.annotations.Param;
import java.util.List;
public interface CoreJobMapper extends BaseMapper<CoreJob> {
/**
* 清除职位的关联关系
*
* @param jobId
*/
void clearJobFunc(@Param("jobId") String jobId);
/**
* 更新关联关系
*
* @param pointList
*/
void updateJobFunc(@Param("list") List<IdName> pointList);
/**
* 获取关联的func
*
* @param jobId
* @return
*/
List<String> getJobFunc(@Param("jobId") String jobId, @Param("isUsed") Integer isUsed);
}

View File

@@ -0,0 +1,18 @@
package com.tiesheng.core.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.tiesheng.core.pojos.dao.CoreJobUser;
import com.tiesheng.core.pojos.dto.job.JobUserOwner;
import org.apache.ibatis.annotations.Param;
import java.util.List;
public interface CoreJobUserMapper extends BaseMapper<CoreJobUser> {
/**
* 获取指定用户的职位和功能点
*
* @param userId
* @return
*/
List<JobUserOwner> list(@Param("userId") String userId);
}

View File

@@ -0,0 +1,7 @@
package com.tiesheng.core.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.tiesheng.core.pojos.dao.CoreLogProcess;
public interface CoreLogProcessMapper extends BaseMapper<CoreLogProcess> {
}

View File

@@ -1,6 +1,11 @@
package com.tiesheng.core.pojos;
public class CurrentWebUser {
/**
* 当前token的数据
*
* @author hao
*/
public class RequestUserInfo {
private String id;
private String name;

View File

@@ -0,0 +1,110 @@
package com.tiesheng.core.pojos.dao;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.tiesheng.core.pojos.DaoBase;
import java.util.Date;
/**
* 职位-功能点
*/
@TableName(value = "core_config_func")
public class CoreConfigFunc extends DaoBase {
/**
* 业务
*/
@TableField(value = "service")
private String service;
/**
* 名称
*/
@TableField(value = "`name`")
private String name;
/**
* 其他说明
*/
@TableField(value = "remark")
private String remark;
/**
* 是否启用
*/
@TableField(value = "is_used")
private Integer isUsed;
/**
* 获取业务
*
* @return service - 业务
*/
public String getService() {
return service;
}
/**
* 设置业务
*
* @param service 业务
*/
public void setService(String service) {
this.service = service;
}
/**
* 获取名称
*
* @return name - 名称
*/
public String getName() {
return name;
}
/**
* 设置名称
*
* @param name 名称
*/
public void setName(String name) {
this.name = name;
}
/**
* 获取其他说明
*
* @return remark - 其他说明
*/
public String getRemark() {
return remark;
}
/**
* 设置其他说明
*
* @param remark 其他说明
*/
public void setRemark(String remark) {
this.remark = remark;
}
/**
* 获取是否启用
*
* @return is_used - 是否启用
*/
public Integer getIsUsed() {
return isUsed;
}
/**
* 设置是否启用
*
* @param isUsed 是否启用
*/
public void setIsUsed(Integer isUsed) {
this.isUsed = isUsed;
}
}

View File

@@ -0,0 +1,86 @@
package com.tiesheng.core.pojos.dao;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.tiesheng.core.pojos.DaoBase;
import java.util.Date;
/**
* 职位
*/
@TableName(value = "core_job")
public class CoreJob extends DaoBase {
/**
* 名称
*/
@TableField(value = "`name`")
private String name;
/**
* 其他说明
*/
@TableField(value = "remark")
private String remark;
/**
* 是否系统
*/
@TableField(value = "is_system")
private Integer isSystem;
/**
* 获取名称
*
* @return name - 名称
*/
public String getName() {
return name;
}
/**
* 设置名称
*
* @param name 名称
*/
public void setName(String name) {
this.name = name;
}
/**
* 获取其他说明
*
* @return remark - 其他说明
*/
public String getRemark() {
return remark;
}
/**
* 设置其他说明
*
* @param remark 其他说明
*/
public void setRemark(String remark) {
this.remark = remark;
}
/**
* 获取是否系统
*
* @return is_system - 是否系统
*/
public Integer getIsSystem() {
return isSystem;
}
/**
* 设置是否系统
*
* @param isSystem 是否系统
*/
public void setIsSystem(Integer isSystem) {
this.isSystem = isSystem;
}
}

View File

@@ -0,0 +1,158 @@
package com.tiesheng.core.pojos.dao;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.tiesheng.core.pojos.DaoBase;
import java.util.Date;
/**
* 职位-用户
*/
@TableName(value = "core_job_user")
public class CoreJobUser extends DaoBase {
/**
* 用户id
*/
@TableField(value = "user_id")
private String userId;
/**
* 用户
*/
@TableField(value = "job_id")
private String jobId;
/**
* 扩展1
*/
@TableField(value = "ext1")
private String ext1;
/**
* 扩展2
*/
@TableField(value = "ext2")
private String ext2;
/**
* 扩展3
*/
@TableField(value = "ext3")
private String ext3;
/**
* 扩展文本
*/
@TableField(value = "ext_text")
private String extText;
/**
* 获取用户id
*
* @return user_id - 用户id
*/
public String getUserId() {
return userId;
}
/**
* 设置用户id
*
* @param userId 用户id
*/
public void setUserId(String userId) {
this.userId = userId;
}
/**
* 获取用户
*
* @return job_id - 用户
*/
public String getJobId() {
return jobId;
}
/**
* 设置用户
*
* @param jobId 用户
*/
public void setJobId(String jobId) {
this.jobId = jobId;
}
/**
* 获取扩展1
*
* @return ext1 - 扩展1
*/
public String getExt1() {
return ext1;
}
/**
* 设置扩展1
*
* @param ext1 扩展1
*/
public void setExt1(String ext1) {
this.ext1 = ext1;
}
/**
* 获取扩展2
*
* @return ext2 - 扩展2
*/
public String getExt2() {
return ext2;
}
/**
* 设置扩展2
*
* @param ext2 扩展2
*/
public void setExt2(String ext2) {
this.ext2 = ext2;
}
/**
* 获取扩展3
*
* @return ext3 - 扩展3
*/
public String getExt3() {
return ext3;
}
/**
* 设置扩展3
*
* @param ext3 扩展3
*/
public void setExt3(String ext3) {
this.ext3 = ext3;
}
/**
* 获取扩展文本
*
* @return ext_text - 扩展文本
*/
public String getExtText() {
return extText;
}
/**
* 设置扩展文本
*
* @param extText 扩展文本
*/
public void setExtText(String extText) {
this.extText = extText;
}
}

View File

@@ -0,0 +1,230 @@
package com.tiesheng.core.pojos.dao;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.tiesheng.core.pojos.DaoBase;
import java.util.Date;
/**
* 日志-过程
*/
@TableName(value = "core_log_process")
public class CoreLogProcess extends DaoBase {
/**
* 标题
*/
@TableField(value = "title")
private String title;
/**
* 总数
*/
@TableField(value = "total")
private Integer total;
/**
* 成功数
*/
@TableField(value = "success_num")
private Integer successNum;
/**
* 失败数
*/
@TableField(value = "fail_num")
private Integer failNum;
/**
* 类型import-导入sync-同步)
*/
@TableField(value = "`type`")
private String type;
/**
* 状态0-未完成1-已完成)
*/
@TableField(value = "`status`")
private Integer status;
/**
* 失败的文件
*/
@TableField(value = "fail_file")
private String failFile;
/**
* 异常说明
*/
@TableField(value = "error")
private String error;
/**
* 进度
*/
@TableField(value = "`process`")
private Integer process;
/**
* 获取标题
*
* @return title - 标题
*/
public String getTitle() {
return title;
}
/**
* 设置标题
*
* @param title 标题
*/
public void setTitle(String title) {
this.title = title;
}
/**
* 获取总数
*
* @return total - 总数
*/
public Integer getTotal() {
return total;
}
/**
* 设置总数
*
* @param total 总数
*/
public void setTotal(Integer total) {
this.total = total;
}
/**
* 获取成功数
*
* @return success_num - 成功数
*/
public Integer getSuccessNum() {
return successNum;
}
/**
* 设置成功数
*
* @param successNum 成功数
*/
public void setSuccessNum(Integer successNum) {
this.successNum = successNum;
}
/**
* 获取失败数
*
* @return fail_num - 失败数
*/
public Integer getFailNum() {
return failNum;
}
/**
* 设置失败数
*
* @param failNum 失败数
*/
public void setFailNum(Integer failNum) {
this.failNum = failNum;
}
/**
* 获取类型import-导入sync-同步)
*
* @return type - 类型import-导入sync-同步)
*/
public String getType() {
return type;
}
/**
* 设置类型import-导入sync-同步)
*
* @param type 类型import-导入sync-同步)
*/
public void setType(String type) {
this.type = type;
}
/**
* 获取状态0-未完成1-已完成)
*
* @return status - 状态0-未完成1-已完成)
*/
public Integer getStatus() {
return status;
}
/**
* 设置状态0-未完成1-已完成)
*
* @param status 状态0-未完成1-已完成)
*/
public void setStatus(Integer status) {
this.status = status;
}
/**
* 获取失败的文件
*
* @return fail_file - 失败的文件
*/
public String getFailFile() {
return failFile;
}
/**
* 设置失败的文件
*
* @param failFile 失败的文件
*/
public void setFailFile(String failFile) {
this.failFile = failFile;
}
/**
* 获取异常说明
*
* @return error - 异常说明
*/
public String getError() {
return error;
}
/**
* 设置异常说明
*
* @param error 异常说明
*/
public void setError(String error) {
this.error = error;
}
/**
* 获取进度
*
* @return process - 进度
*/
public Integer getProcess() {
return process;
}
/**
* 设置进度
*
* @param process 进度
*/
public void setProcess(Integer process) {
this.process = process;
}
}

View File

@@ -0,0 +1,30 @@
package com.tiesheng.core.pojos.dto;
/**
* @author hao
*/
public class ChunkCheckDTO {
private String fileMd5;
private Integer chunk;
///////////////////////////////////////////////////////////////////////////
// setter\getter
///////////////////////////////////////////////////////////////////////////
public String getFileMd5() {
return fileMd5;
}
public void setFileMd5(String fileMd5) {
this.fileMd5 = fileMd5;
}
public Integer getChunk() {
return chunk;
}
public void setChunk(Integer chunk) {
this.chunk = chunk;
}
}

View File

@@ -0,0 +1,30 @@
package com.tiesheng.core.pojos.dto;
/**
* @author hao
*/
public class ChunkMergeDTO {
private String fileMd5;
private String fileExt;
///////////////////////////////////////////////////////////////////////////
// setter\getter
///////////////////////////////////////////////////////////////////////////
public String getFileMd5() {
return fileMd5;
}
public void setFileMd5(String fileMd5) {
this.fileMd5 = fileMd5;
}
public String getFileExt() {
return fileExt;
}
public void setFileExt(String fileExt) {
this.fileExt = fileExt;
}
}

View File

@@ -0,0 +1,21 @@
package com.tiesheng.core.pojos.dto;
/**
* @author hao
*/
public class ChunkStartDTO {
private String fileExt;
///////////////////////////////////////////////////////////////////////////
// setter\getter
///////////////////////////////////////////////////////////////////////////
public String getFileExt() {
return fileExt;
}
public void setFileExt(String fileExt) {
this.fileExt = fileExt;
}
}

View File

@@ -0,0 +1,23 @@
package com.tiesheng.core.pojos.dto;
import javax.validation.constraints.NotEmpty;
public class IdDTO {
@NotEmpty(message = "需要ID")
private String id;
///////////////////////////////////////////////////////////////////////////
// setter\getter
///////////////////////////////////////////////////////////////////////////
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
}

View File

@@ -0,0 +1,45 @@
package com.tiesheng.core.pojos.dto.config;
public class ConfigFuncDTO {
private String id;
private String name;
private String remark;
private Integer isUsed;
///////////////////////////////////////////////////////////////////////////
// setter\getter
///////////////////////////////////////////////////////////////////////////
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getRemark() {
return remark;
}
public void setRemark(String remark) {
this.remark = remark;
}
public Integer getIsUsed() {
return isUsed;
}
public void setIsUsed(Integer isUsed) {
this.isUsed = isUsed;
}
}

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