Skip to content
Projects
Groups
Snippets
Help
Loading...
Sign in
Toggle navigation
O
online-edu-backend
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Redmine
Redmine
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
online-edu
online-edu-backend
Commits
7bbe84e0
Commit
7bbe84e0
authored
Apr 26, 2021
by
liuyang
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
init project
parents
Show whitespace changes
Inline
Side-by-side
Showing
127 changed files
with
6104 additions
and
0 deletions
+6104
-0
.gitignore
.gitignore
+132
-0
pom.xml
pom.xml
+325
-0
Dockerfile
src/main/docker/Dockerfile
+18
-0
docker-entrypoint.sh
src/main/docker/docker-entrypoint.sh
+3
-0
Application.java
src/main/java/com/qkdata/Application.java
+23
-0
AccountStatusEnum.java
src/main/java/com/qkdata/biz/enums/AccountStatusEnum.java
+17
-0
MenuTypeEnum.java
src/main/java/com/qkdata/biz/enums/MenuTypeEnum.java
+15
-0
SysConfigStatusEnum.java
src/main/java/com/qkdata/biz/enums/SysConfigStatusEnum.java
+17
-0
SysConfigController.java
...va/com/qkdata/biz/sys/controller/SysConfigController.java
+59
-0
SysLogController.java
.../java/com/qkdata/biz/sys/controller/SysLogController.java
+25
-0
SysLoginController.java
...ava/com/qkdata/biz/sys/controller/SysLoginController.java
+39
-0
SysMenuController.java
...java/com/qkdata/biz/sys/controller/SysMenuController.java
+108
-0
SysRoleController.java
...java/com/qkdata/biz/sys/controller/SysRoleController.java
+77
-0
SysUserController.java
...java/com/qkdata/biz/sys/controller/SysUserController.java
+110
-0
SysConfigPO.java
src/main/java/com/qkdata/biz/sys/entity/SysConfigPO.java
+15
-0
SysLogPO.java
src/main/java/com/qkdata/biz/sys/entity/SysLogPO.java
+18
-0
SysMenuPO.java
src/main/java/com/qkdata/biz/sys/entity/SysMenuPO.java
+34
-0
SysRoleMenuPO.java
src/main/java/com/qkdata/biz/sys/entity/SysRoleMenuPO.java
+14
-0
SysRolePO.java
src/main/java/com/qkdata/biz/sys/entity/SysRolePO.java
+12
-0
SysUserPO.java
src/main/java/com/qkdata/biz/sys/entity/SysUserPO.java
+27
-0
SysUserRolePO.java
src/main/java/com/qkdata/biz/sys/entity/SysUserRolePO.java
+15
-0
SysConfigMapper.java
src/main/java/com/qkdata/biz/sys/mapper/SysConfigMapper.java
+15
-0
SysLogMapper.java
src/main/java/com/qkdata/biz/sys/mapper/SysLogMapper.java
+15
-0
SysMenuMapper.java
src/main/java/com/qkdata/biz/sys/mapper/SysMenuMapper.java
+12
-0
SysRoleMapper.java
src/main/java/com/qkdata/biz/sys/mapper/SysRoleMapper.java
+15
-0
SysRoleMenuMapper.java
...ain/java/com/qkdata/biz/sys/mapper/SysRoleMenuMapper.java
+12
-0
SysUserMapper.java
src/main/java/com/qkdata/biz/sys/mapper/SysUserMapper.java
+20
-0
SysUserRoleMapper.java
...ain/java/com/qkdata/biz/sys/mapper/SysUserRoleMapper.java
+12
-0
ShiroService.java
src/main/java/com/qkdata/biz/sys/service/ShiroService.java
+84
-0
SysConfigService.java
...ain/java/com/qkdata/biz/sys/service/SysConfigService.java
+21
-0
SysLogService.java
src/main/java/com/qkdata/biz/sys/service/SysLogService.java
+21
-0
SysMenuService.java
src/main/java/com/qkdata/biz/sys/service/SysMenuService.java
+78
-0
SysRoleMenuService.java
...n/java/com/qkdata/biz/sys/service/SysRoleMenuService.java
+34
-0
SysRoleService.java
src/main/java/com/qkdata/biz/sys/service/SysRoleService.java
+62
-0
SysUserRoleService.java
...n/java/com/qkdata/biz/sys/service/SysUserRoleService.java
+38
-0
SysUserService.java
src/main/java/com/qkdata/biz/sys/service/SysUserService.java
+93
-0
LoginModel.java
src/main/java/com/qkdata/biz/sys/vo/LoginModel.java
+13
-0
LoginUserInfo.java
src/main/java/com/qkdata/biz/sys/vo/LoginUserInfo.java
+12
-0
PasswordModel.java
src/main/java/com/qkdata/biz/sys/vo/PasswordModel.java
+13
-0
QueryConfigModel.java
src/main/java/com/qkdata/biz/sys/vo/QueryConfigModel.java
+11
-0
QueryLogModel.java
src/main/java/com/qkdata/biz/sys/vo/QueryLogModel.java
+11
-0
QueryRoleModel.java
src/main/java/com/qkdata/biz/sys/vo/QueryRoleModel.java
+11
-0
QueryUserModel.java
src/main/java/com/qkdata/biz/sys/vo/QueryUserModel.java
+11
-0
SysNavModel.java
src/main/java/com/qkdata/biz/sys/vo/SysNavModel.java
+15
-0
SysRoleModel.java
src/main/java/com/qkdata/biz/sys/vo/SysRoleModel.java
+16
-0
SysUserModel.java
src/main/java/com/qkdata/biz/sys/vo/SysUserModel.java
+22
-0
ApiLimit.java
src/main/java/com/qkdata/common/annotation/ApiLimit.java
+19
-0
SysLog.java
src/main/java/com/qkdata/common/annotation/SysLog.java
+14
-0
ApiLimitAspect.java
src/main/java/com/qkdata/common/aspect/ApiLimitAspect.java
+77
-0
SysLogAspect.java
src/main/java/com/qkdata/common/aspect/SysLogAspect.java
+98
-0
BasePO.java
src/main/java/com/qkdata/common/base/entity/BasePO.java
+34
-0
CodeEnum.java
src/main/java/com/qkdata/common/base/enums/CodeEnum.java
+16
-0
BusinessException.java
...a/com/qkdata/common/base/exception/BusinessException.java
+33
-0
PageResult.java
src/main/java/com/qkdata/common/base/model/PageResult.java
+33
-0
Result.java
src/main/java/com/qkdata/common/base/model/Result.java
+42
-0
BaseServiceImpl.java
.../com/qkdata/common/base/service/impl/BaseServiceImpl.java
+10
-0
DateMetaObjectHandler.java
.../java/com/qkdata/common/config/DateMetaObjectHandler.java
+36
-0
FilterConfig.java
src/main/java/com/qkdata/common/config/FilterConfig.java
+25
-0
GlobalExceptionHandle.java
.../java/com/qkdata/common/config/GlobalExceptionHandle.java
+96
-0
HttpHeaderInterceptor.java
.../java/com/qkdata/common/config/HttpHeaderInterceptor.java
+42
-0
HttpTraceConfiguration.java
...java/com/qkdata/common/config/HttpTraceConfiguration.java
+25
-0
JacksonConfiguration.java
...n/java/com/qkdata/common/config/JacksonConfiguration.java
+34
-0
LogClientHttpRequestInterceptor.java
...qkdata/common/config/LogClientHttpRequestInterceptor.java
+21
-0
MybatisPlusAutoConfigure.java
...va/com/qkdata/common/config/MybatisPlusAutoConfigure.java
+31
-0
RedisConfig.java
src/main/java/com/qkdata/common/config/RedisConfig.java
+109
-0
RestTemplateConfig.java
...ain/java/com/qkdata/common/config/RestTemplateConfig.java
+35
-0
ShiroConfig.java
src/main/java/com/qkdata/common/config/ShiroConfig.java
+81
-0
Swagger2Config.java
src/main/java/com/qkdata/common/config/Swagger2Config.java
+72
-0
WebMvcConfiguration.java
...in/java/com/qkdata/common/config/WebMvcConfiguration.java
+68
-0
AddGroup.java
src/main/java/com/qkdata/common/constants/AddGroup.java
+4
-0
Constants.java
src/main/java/com/qkdata/common/constants/Constants.java
+12
-0
DateTimeFormatterPattern.java
...com/qkdata/common/constants/DateTimeFormatterPattern.java
+11
-0
Page.java
src/main/java/com/qkdata/common/constants/Page.java
+18
-0
UpdateGroup.java
src/main/java/com/qkdata/common/constants/UpdateGroup.java
+4
-0
ValidatorPattern.java
...in/java/com/qkdata/common/constants/ValidatorPattern.java
+8
-0
DateDeserializer.java
...in/java/com/qkdata/common/converter/DateDeserializer.java
+27
-0
DateSerializer.java
...main/java/com/qkdata/common/converter/DateSerializer.java
+21
-0
LocalDateDeserializer.java
...va/com/qkdata/common/converter/LocalDateDeserializer.java
+32
-0
LocalDateSerializer.java
...java/com/qkdata/common/converter/LocalDateSerializer.java
+24
-0
LocalDateTimeDeserializer.java
...om/qkdata/common/converter/LocalDateTimeDeserializer.java
+33
-0
LocalDateTimeSerializer.java
.../com/qkdata/common/converter/LocalDateTimeSerializer.java
+25
-0
StringToDateConverter.java
...va/com/qkdata/common/converter/StringToDateConverter.java
+30
-0
StringToLocalDateConverter.java
...m/qkdata/common/converter/StringToLocalDateConverter.java
+31
-0
StringToLocalDateTimeConverter.java
...data/common/converter/StringToLocalDateTimeConverter.java
+23
-0
JWTProperties.java
src/main/java/com/qkdata/common/jwt/JWTProperties.java
+38
-0
JWTService.java
src/main/java/com/qkdata/common/jwt/JWTService.java
+128
-0
AuthorizationResponseEnum.java
...va/com/qkdata/common/oauth/AuthorizationResponseEnum.java
+28
-0
AuthorizedUser.java
src/main/java/com/qkdata/common/oauth/AuthorizedUser.java
+10
-0
OAuthFilter.java
src/main/java/com/qkdata/common/oauth/OAuthFilter.java
+101
-0
OAuthRealm.java
src/main/java/com/qkdata/common/oauth/OAuthRealm.java
+93
-0
OAuthToken.java
src/main/java/com/qkdata/common/oauth/OAuthToken.java
+24
-0
HttpTraceLogFilter.java
...main/java/com/qkdata/common/trace/HttpTraceLogFilter.java
+144
-0
MdcThreadPoolTaskExecutor.java
...va/com/qkdata/common/trace/MdcThreadPoolTaskExecutor.java
+48
-0
TraceIdInterceptor.java
...main/java/com/qkdata/common/trace/TraceIdInterceptor.java
+23
-0
TraceLog.java
src/main/java/com/qkdata/common/trace/TraceLog.java
+61
-0
IContentProvider.java
src/main/java/com/qkdata/common/tree/IContentProvider.java
+41
-0
ILabelProvider.java
src/main/java/com/qkdata/common/tree/ILabelProvider.java
+101
-0
Tree.java
src/main/java/com/qkdata/common/tree/Tree.java
+76
-0
TreeNode.java
src/main/java/com/qkdata/common/tree/TreeNode.java
+193
-0
TreeTypeEnum.java
src/main/java/com/qkdata/common/tree/TreeTypeEnum.java
+39
-0
TreeView.java
src/main/java/com/qkdata/common/tree/TreeView.java
+140
-0
EncryptUtil.java
src/main/java/com/qkdata/common/util/EncryptUtil.java
+84
-0
HttpContextUtils.java
src/main/java/com/qkdata/common/util/HttpContextUtils.java
+31
-0
IPUtils.java
src/main/java/com/qkdata/common/util/IPUtils.java
+59
-0
Iterables.java
src/main/java/com/qkdata/common/util/Iterables.java
+20
-0
MD5Util.java
src/main/java/com/qkdata/common/util/MD5Util.java
+29
-0
RandomDigitGenerator.java
...ain/java/com/qkdata/common/util/RandomDigitGenerator.java
+46
-0
RequestUtil.java
src/main/java/com/qkdata/common/util/RequestUtil.java
+76
-0
ShareCodeUtils.java
src/main/java/com/qkdata/common/util/ShareCodeUtils.java
+116
-0
UserContext.java
src/main/java/com/qkdata/common/util/UserContext.java
+14
-0
WxMaConfiguration.java
.../java/com/qkdata/wx/miniapp/config/WxMaConfiguration.java
+147
-0
WxMaProperties.java
...ain/java/com/qkdata/wx/miniapp/config/WxMaProperties.java
+46
-0
WxPortalController.java
.../com/qkdata/wx/miniapp/controller/WxPortalController.java
+98
-0
application-dev.yml
src/main/resources/application-dev.yml
+20
-0
application.yml
src/main/resources/application.yml
+104
-0
V1.0.0__init.sql
src/main/resources/db/migration/V1.0.0__init.sql
+471
-0
logback-spring.xml
src/main/resources/logback-spring.xml
+58
-0
SysConfigMapper.xml
src/main/resources/mappers/SysConfigMapper.xml
+11
-0
SysLogMapper.xml
src/main/resources/mappers/SysLogMapper.xml
+12
-0
SysMenuMapper.xml
src/main/resources/mappers/SysMenuMapper.xml
+8
-0
SysRoleMapper.xml
src/main/resources/mappers/SysRoleMapper.xml
+14
-0
SysRoleMenuMapper.xml
src/main/resources/mappers/SysRoleMenuMapper.xml
+8
-0
SysUserMapper.xml
src/main/resources/mappers/SysUserMapper.xml
+25
-0
SysUserRoleMapper.xml
src/main/resources/mappers/SysUserRoleMapper.xml
+8
-0
CodeGenerator.java
src/test/java/com/qkdata/autogenerator/CodeGenerator.java
+153
-0
BaseTest.java
src/test/java/com/qkdata/test/BaseTest.java
+14
-0
Service.java.ftl
src/test/resources/templates/ftl/Service.java.ftl
+20
-0
No files found.
.gitignore
0 → 100644
View file @
7bbe84e0
# Created by https://www.gitignore.io/api/eclipse,intellij,maven
### Eclipse ###
.metadata
bin/
tmp/
*.tmp
*.bak
*.swp
*~.nib
local.properties
.settings/
.loadpath
.recommenders
# Eclipse Core
.project
# External tool builders
.externalToolBuilders/
# Locally stored "Eclipse launch configurations"
*.launch
# PyDev specific (Python IDE for Eclipse)
*.pydevproject
# CDT-specific (C/C++ Development Tooling)
.cproject
# JDT-specific (Eclipse Java Development Tools)
.classpath
# Java annotation processor (APT)
.factorypath
# PDT-specific (PHP Development Tools)
.buildpath
# sbteclipse plugin
.target
# Tern plugin
.tern-project
# TeXlipse plugin
.texlipse
# STS (Spring Tool Suite)
.springBeans
# Code Recommenders
.recommenders/
### Intellij ###
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and Webstorm
# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
# User-specific stuff:
.idea/**/workspace.xml
.idea/**/tasks.xml
# Sensitive or high-churn files:
.idea/**/dataSources/
.idea/**/dataSources.ids
.idea/**/dataSources.xml
.idea/**/dataSources.local.xml
.idea/**/sqlDataSources.xml
.idea/**/dynamic.xml
.idea/**/uiDesigner.xml
# Gradle:
.idea/**/gradle.xml
.idea/**/libraries
# Mongo Explorer plugin:
.idea/**/mongoSettings.xml
## File-based project format:
*.iws
## Plugin-specific files:
# IntelliJ
/out/
# mpeltonen/sbt-idea plugin
.idea_modules/
# JIRA plugin
atlassian-ide-plugin.xml
# Crashlytics plugin (for Android Studio and IntelliJ)
com_crashlytics_export_strings.xml
crashlytics.properties
crashlytics-build.properties
fabric.properties
### Intellij Patch ###
# Comment Reason: https://github.com/joeblau/gitignore.io/issues/186#issuecomment-215987721
.DS_Store
.idea
*.iml
# modules.xml
# .idea/misc.xml
# *.ipr
### Maven ###
pom.xml.tag
pom.xml.releaseBackup
pom.xml.versionsBackup
pom.xml.next
release.properties
dependency-reduced-pom.xml
buildNumber.properties
.mvn/timing.properties
### redis ###
*.rdb
#*.jpg
#*.png
# Exclude maven wrapper
!/.mvn/wrapper/maven-wrapper.jar
# End of https://www.gitignore.io/api/eclipse,intellij,maven
*.iml
*.class
target/*
pom.xml
0 → 100644
View file @
7bbe84e0
<?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>
<artifactId>
online-edu-backend
</artifactId>
<version>
1.0.0-SNAPSHOT
</version>
<packaging>
jar
</packaging>
<parent>
<groupId>
org.springframework.boot
</groupId>
<artifactId>
spring-boot-starter-parent
</artifactId>
<version>
2.1.3.RELEASE
</version>
</parent>
<properties>
<maven.compiler.source>
8
</maven.compiler.source>
<maven.compiler.target>
8
</maven.compiler.target>
<mysql.version>
5.1.47
</mysql.version>
<lombok.version>
1.18.2
</lombok.version>
<mybatis.plus.version>
3.3.1
</mybatis.plus.version>
<druid.springboot.version>
1.1.10
</druid.springboot.version>
<redis.springboot.version>
2.1.0.RELEASE
</redis.springboot.version>
<thumbnailator.coobird.version>
0.4.8
</thumbnailator.coobird.version>
<mybatis.typehandlers.jsr.version>
1.0.2
</mybatis.typehandlers.jsr.version>
<commons-lang3.version>
3.8.1
</commons-lang3.version>
<commons-codec.version>
1.11
</commons-codec.version>
<auth0.jwt.version>
3.4.1
</auth0.jwt.version>
<jackson.jsr310.version>
2.9.7
</jackson.jsr310.version>
<guava.version>
27.0-jre
</guava.version>
<xstream.version>
1.4.11.1
</xstream.version>
<httpclient.version>
4.5.6
</httpclient.version>
<sanselan.version>
0.97-incubator
</sanselan.version>
<jedis.version>
2.9.0
</jedis.version>
<org.bouncycastle.version>
1.60
</org.bouncycastle.version>
<google.zxing.version>
3.3.3
</google.zxing.version>
<common.io.version>
2.6
</common.io.version>
<java.jwt.version>
3.7.0
</java.jwt.version>
<product.version>
1.0.0-SNAPSHOT
</product.version>
<docker.plugin.version>
1.1.1
</docker.plugin.version>
<baidu.aip.version>
4.11.3
</baidu.aip.version>
<shiro.version>
1.4.0
</shiro.version>
<fastjson.version>
1.2.60
</fastjson.version>
<weixin-java.version>
3.6.0
</weixin-java.version>
<hutool.version>
5.3.5
</hutool.version>
</properties>
<dependencies>
<dependency>
<groupId>
org.springframework.boot
</groupId>
<artifactId>
spring-boot-starter
</artifactId>
</dependency>
<dependency>
<groupId>
org.springframework.boot
</groupId>
<artifactId>
spring-boot-autoconfigure
</artifactId>
</dependency>
<dependency>
<groupId>
org.springframework.boot
</groupId>
<artifactId>
spring-boot-starter-web
</artifactId>
</dependency>
<dependency>
<groupId>
org.springframework.boot
</groupId>
<artifactId>
spring-boot-starter-test
</artifactId>
</dependency>
<dependency>
<groupId>
org.springframework.boot
</groupId>
<artifactId>
spring-boot-configuration-processor
</artifactId>
<optional>
true
</optional>
</dependency>
<dependency>
<groupId>
org.springframework.boot
</groupId>
<artifactId>
spring-boot-starter-actuator
</artifactId>
</dependency>
<dependency>
<groupId>
org.springframework.boot
</groupId>
<artifactId>
spring-boot-starter-websocket
</artifactId>
</dependency>
<dependency>
<groupId>
org.springframework.boot
</groupId>
<artifactId>
spring-boot-starter-cache
</artifactId>
</dependency>
<dependency>
<groupId>
org.springframework.boot
</groupId>
<artifactId>
spring-boot-starter-aop
</artifactId>
</dependency>
<dependency>
<groupId>
org.springframework.retry
</groupId>
<artifactId>
spring-retry
</artifactId>
</dependency>
<!--shiro-->
<dependency>
<groupId>
org.apache.shiro
</groupId>
<artifactId>
shiro-spring
</artifactId>
<version>
${shiro.version}
</version>
</dependency>
<dependency>
<groupId>
org.flywaydb
</groupId>
<artifactId>
flyway-core
</artifactId>
</dependency>
<dependency>
<groupId>
org.projectlombok
</groupId>
<artifactId>
lombok
</artifactId>
<version>
${lombok.version}
</version>
<scope>
provided
</scope>
</dependency>
<dependency>
<groupId>
mysql
</groupId>
<artifactId>
mysql-connector-java
</artifactId>
<version>
${mysql.version}
</version>
</dependency>
<dependency>
<groupId>
com.baomidou
</groupId>
<artifactId>
mybatis-plus-boot-starter
</artifactId>
<version>
${mybatis.plus.version}
</version>
</dependency>
<dependency>
<groupId>
com.baomidou
</groupId>
<artifactId>
mybatis-plus-generator
</artifactId>
<version>
${mybatis.plus.version}
</version>
</dependency>
<dependency>
<groupId>
org.freemarker
</groupId>
<artifactId>
freemarker
</artifactId>
<version>
2.3.31
</version>
</dependency>
<dependency>
<groupId>
com.alibaba
</groupId>
<artifactId>
druid-spring-boot-starter
</artifactId>
<version>
${druid.springboot.version}
</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-data-redis -->
<dependency>
<groupId>
org.springframework.boot
</groupId>
<artifactId>
spring-boot-starter-data-redis
</artifactId>
<version>
${redis.springboot.version}
</version>
</dependency>
<dependency>
<groupId>
org.apache.commons
</groupId>
<artifactId>
commons-pool2
</artifactId>
</dependency>
<dependency>
<groupId>
org.mybatis
</groupId>
<artifactId>
mybatis-typehandlers-jsr310
</artifactId>
<version>
${mybatis.typehandlers.jsr.version}
</version>
</dependency>
<dependency>
<groupId>
org.apache.commons
</groupId>
<artifactId>
commons-lang3
</artifactId>
<version>
${commons-lang3.version}
</version>
</dependency>
<dependency>
<groupId>
commons-codec
</groupId>
<artifactId>
commons-codec
</artifactId>
<version>
${commons-codec.version}
</version>
</dependency>
<dependency>
<groupId>
commons-io
</groupId>
<artifactId>
commons-io
</artifactId>
<version>
${common.io.version}
</version>
</dependency>
<dependency>
<groupId>
com.auth0
</groupId>
<artifactId>
java-jwt
</artifactId>
<version>
${auth0.jwt.version}
</version>
</dependency>
<dependency>
<groupId>
com.fasterxml.jackson.datatype
</groupId>
<artifactId>
jackson-datatype-jsr310
</artifactId>
<version>
${jackson.jsr310.version}
</version>
</dependency>
<dependency>
<groupId>
com.google.guava
</groupId>
<artifactId>
guava
</artifactId>
<version>
${guava.version}
</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.apache.httpcomponents/httpclient -->
<dependency>
<groupId>
org.apache.httpcomponents
</groupId>
<artifactId>
httpclient
</artifactId>
<version>
${httpclient.version}
</version>
</dependency>
<dependency>
<groupId>
com.thoughtworks.xstream
</groupId>
<artifactId>
xstream
</artifactId>
<version>
${xstream.version}
</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.apache.sanselan/sanselan -->
<dependency>
<groupId>
org.apache.sanselan
</groupId>
<artifactId>
sanselan
</artifactId>
<version>
${sanselan.version}
</version>
</dependency>
<!-- <dependency>-->
<!-- <groupId>redis.clients</groupId>-->
<!-- <artifactId>jedis</artifactId>-->
<!-- <type>jar</type>-->
<!-- <version>${jedis.version}</version>-->
<!-- </dependency>-->
<!-- https://mvnrepository.com/artifact/org.bouncycastle/bcprov-jdk15on -->
<dependency>
<groupId>
io.springfox
</groupId>
<artifactId>
springfox-swagger2
</artifactId>
<version>
2.9.2
</version>
</dependency>
<dependency>
<groupId>
io.springfox
</groupId>
<artifactId>
springfox-swagger-ui
</artifactId>
<version>
2.9.2
</version>
</dependency>
<!-- <dependency>-->
<!-- <groupId>com.github.binarywang</groupId>-->
<!-- <artifactId>weixin-java-mp</artifactId>-->
<!-- <version>${weixin-java.version}</version>-->
<!-- </dependency>-->
<dependency>
<groupId>
com.github.binarywang
</groupId>
<artifactId>
weixin-java-miniapp
</artifactId>
<version>
3.7.0
</version>
<exclusions>
<exclusion>
<artifactId>
bcpkix-jdk15on
</artifactId>
<groupId>
org.bouncycastle
</groupId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>
com.alibaba
</groupId>
<artifactId>
fastjson
</artifactId>
<version>
1.2.61
</version>
</dependency>
<!-- 二维码图片 -->
<dependency>
<groupId>
com.google.zxing
</groupId>
<artifactId>
core
</artifactId>
<version>
3.3.0
</version>
</dependency>
<!-- excel tool -->
<dependency>
<groupId>
cn.hutool
</groupId>
<artifactId>
hutool-all
</artifactId>
<version>
${hutool.version}
</version>
</dependency>
<dependency>
<groupId>
org.apache.poi
</groupId>
<artifactId>
poi-ooxml
</artifactId>
<version>
4.1.2
</version>
</dependency>
<dependency>
<groupId>
org.bouncycastle
</groupId>
<artifactId>
bcprov-jdk15to18
</artifactId>
<version>
1.65
</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>
org.springframework.boot
</groupId>
<artifactId>
spring-boot-maven-plugin
</artifactId>
<version>
2.1.3.RELEASE
</version>
<configuration>
<layout>
ZIP
</layout>
<classifier>
all
</classifier>
</configuration>
<executions>
<execution>
<goals>
<goal>
repackage
</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>
com.spotify
</groupId>
<artifactId>
docker-maven-plugin
</artifactId>
<version>
${docker.plugin.version}
</version>
<configuration>
<imageName>
${project.artifactId}:${project.version}
</imageName>
<dockerDirectory>
${project.basedir}/src/main/docker
</dockerDirectory>
<resources>
<resource>
<targetPath>
/
</targetPath>
<directory>
${project.build.directory}
</directory>
<include>
*.jar
</include>
</resource>
</resources>
<buildArgs>
<JAR_FILE>
${project.build.finalName}-all.jar
</JAR_FILE>
</buildArgs>
</configuration>
<executions>
<execution>
<phase>
install
</phase>
<goals>
<goal>
build
</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
src/main/docker/Dockerfile
0 → 100644
View file @
7bbe84e0
FROM
anapsix/alpine-java:8u202b08_server-jre_unlimited
ARG
JAR_FILE
ADD
${JAR_FILE} $WORKDIR
RUN
mv
${
JAR_FILE
}
app.jar
COPY
docker-entrypoint.sh /usr/share/app/docker-entrypoint.sh
RUN
chmod
+x /usr/share/app/docker-entrypoint.sh
ENV
MYSQL_URL tcp://mysql:3306
ENV
WAIT_MYSQL_TIMEOUT 30s
ENV
JAVA_OPTIONS "-Xms256m -Xmx512m -Dfile.encoding=UTF-8"
ENV
OVERRIDE_PROP ""
ENTRYPOINT
["/usr/share/app/docker-entrypoint.sh"]
EXPOSE
80
src/main/docker/docker-entrypoint.sh
0 → 100644
View file @
7bbe84e0
#!/bin/bash
set
-ex
java
$JAVA_OPTIONS
-jar
app.jar
$OVERRIDE_PROP
src/main/java/com/qkdata/Application.java
0 → 100644
View file @
7bbe84e0
package
com
.
qkdata
;
import
org.springframework.boot.SpringApplication
;
import
org.springframework.boot.autoconfigure.SpringBootApplication
;
import
org.springframework.boot.web.servlet.ServletComponentScan
;
import
org.springframework.cache.annotation.EnableCaching
;
import
org.springframework.context.annotation.ComponentScan
;
import
org.springframework.retry.annotation.EnableRetry
;
@SpringBootApplication
@ComponentScan
(
basePackages
=
{
"com.qkdata"
})
@ServletComponentScan
@EnableCaching
@EnableRetry
public
class
Application
{
public
static
void
main
(
String
[]
args
)
{
SpringApplication
.
run
(
Application
.
class
,
args
);
}
}
src/main/java/com/qkdata/biz/enums/AccountStatusEnum.java
0 → 100644
View file @
7bbe84e0
package
com
.
qkdata
.
biz
.
enums
;
import
com.baomidou.mybatisplus.annotation.EnumValue
;
public
enum
AccountStatusEnum
{
DISABLE
(
0
,
"禁用"
),
ENABLE
(
1
,
"启用"
),
UNACTIVATE
(
2
,
"未激活"
);
@EnumValue
private
Integer
value
;
private
String
text
;
AccountStatusEnum
(
Integer
value
,
String
text
)
{
this
.
value
=
value
;
this
.
text
=
text
;
}
}
src/main/java/com/qkdata/biz/enums/MenuTypeEnum.java
0 → 100644
View file @
7bbe84e0
package
com
.
qkdata
.
biz
.
enums
;
import
com.baomidou.mybatisplus.annotation.EnumValue
;
public
enum
MenuTypeEnum
{
FOLDER
(
0
,
"目录"
),
MENU
(
1
,
"菜单"
),
BUTTON
(
3
,
"按扭"
);
MenuTypeEnum
(
Integer
value
,
String
text
){
this
.
value
=
value
;
this
.
text
=
text
;
}
@EnumValue
private
Integer
value
;
private
String
text
;
}
src/main/java/com/qkdata/biz/enums/SysConfigStatusEnum.java
0 → 100644
View file @
7bbe84e0
package
com
.
qkdata
.
biz
.
enums
;
import
com.baomidou.mybatisplus.annotation.EnumValue
;
public
enum
SysConfigStatusEnum
{
HIDDEN
(
0
,
"隐藏"
),
SHOW
(
1
,
"显示"
);
@EnumValue
private
Integer
value
;
private
String
text
;
SysConfigStatusEnum
(
Integer
value
,
String
text
)
{
this
.
value
=
value
;
this
.
text
=
text
;
}
}
src/main/java/com/qkdata/biz/sys/controller/SysConfigController.java
0 → 100644
View file @
7bbe84e0
package
com
.
qkdata
.
biz
.
sys
.
controller
;
import
com.qkdata.biz.sys.entity.SysConfigPO
;
import
com.qkdata.biz.sys.service.SysConfigService
;
import
com.qkdata.biz.sys.vo.QueryConfigModel
;
import
com.qkdata.common.annotation.SysLog
;
import
com.qkdata.common.base.model.PageResult
;
import
com.qkdata.common.base.model.Result
;
import
io.swagger.annotations.Api
;
import
io.swagger.annotations.ApiOperation
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.web.bind.annotation.*
;
import
java.util.Arrays
;
@Api
(
tags
=
"字典表"
)
@RestController
@RequestMapping
(
"/api/sys/config"
)
public
class
SysConfigController
{
@Autowired
private
SysConfigService
sysConfigService
;
@ApiOperation
(
"查询列表"
)
@PostMapping
(
"/list"
)
public
PageResult
<
SysConfigPO
>
list
(
@RequestBody
QueryConfigModel
queryConfigModel
){
return
sysConfigService
.
queryPageList
(
queryConfigModel
);
}
@ApiOperation
(
"获取单条信息"
)
@GetMapping
(
"/info/{id}"
)
public
Result
<
SysConfigPO
>
info
(
@PathVariable
Long
id
){
return
Result
.
succeed
(
sysConfigService
.
getById
(
id
));
}
@SysLog
(
"保存字典数据"
)
@ApiOperation
(
"保存"
)
@PostMapping
(
"/save"
)
public
Result
<
String
>
save
(
@RequestBody
SysConfigPO
sysConfigPO
){
sysConfigService
.
save
(
sysConfigPO
);
return
Result
.
succeed
(
"ok"
);
}
@SysLog
(
"修改字典数据"
)
@ApiOperation
(
"更新"
)
@PostMapping
(
"/update"
)
public
Result
<
String
>
update
(
@RequestBody
SysConfigPO
sysConfigPO
){
sysConfigService
.
updateById
(
sysConfigPO
);
return
Result
.
succeed
(
"ok"
);
}
@SysLog
(
"删除字典数据"
)
@ApiOperation
(
"删除"
)
@PostMapping
(
"/delete"
)
public
Result
<
String
>
delete
(
@RequestBody
Long
[]
ids
){
sysConfigService
.
removeByIds
(
Arrays
.
asList
(
ids
));
return
Result
.
succeed
(
"ok"
);
}
}
src/main/java/com/qkdata/biz/sys/controller/SysLogController.java
0 → 100644
View file @
7bbe84e0
package
com
.
qkdata
.
biz
.
sys
.
controller
;
import
com.qkdata.biz.sys.entity.SysLogPO
;
import
com.qkdata.biz.sys.service.SysLogService
;
import
com.qkdata.biz.sys.vo.QueryLogModel
;
import
com.qkdata.common.base.model.PageResult
;
import
io.swagger.annotations.Api
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.web.bind.annotation.PostMapping
;
import
org.springframework.web.bind.annotation.RequestBody
;
import
org.springframework.web.bind.annotation.RequestMapping
;
import
org.springframework.web.bind.annotation.RestController
;
@Api
(
tags
=
"审计日志"
)
@RestController
@RequestMapping
(
"/api/sys/log"
)
public
class
SysLogController
{
@Autowired
private
SysLogService
sysLogService
;
@PostMapping
(
"/list"
)
public
PageResult
<
SysLogPO
>
list
(
@RequestBody
QueryLogModel
queryLogModel
){
return
sysLogService
.
queryPageList
(
queryLogModel
);
}
}
src/main/java/com/qkdata/biz/sys/controller/SysLoginController.java
0 → 100644
View file @
7bbe84e0
package
com
.
qkdata
.
biz
.
sys
.
controller
;
import
com.fasterxml.jackson.core.JsonProcessingException
;
import
com.qkdata.biz.sys.service.ShiroService
;
import
com.qkdata.biz.sys.vo.LoginModel
;
import
com.qkdata.biz.sys.vo.LoginUserInfo
;
import
com.qkdata.common.annotation.SysLog
;
import
com.qkdata.common.base.model.Result
;
import
io.swagger.annotations.Api
;
import
io.swagger.annotations.ApiOperation
;
import
org.apache.shiro.SecurityUtils
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.web.bind.annotation.*
;
import
javax.validation.Valid
;
@Api
(
tags
=
"系统登陆"
)
@RestController
@RequestMapping
(
"/api/sys"
)
public
class
SysLoginController
{
@Autowired
private
ShiroService
shiroService
;
@ApiOperation
(
"登陆"
)
@SysLog
(
"登陆"
)
@PostMapping
(
"/login"
)
public
Result
<
LoginUserInfo
>
login
(
@RequestBody
@Valid
LoginModel
loginModel
)
throws
JsonProcessingException
{
return
Result
.
succeed
(
shiroService
.
login
(
loginModel
.
getUsername
(),
loginModel
.
getPassword
()));
}
@ApiOperation
(
"登出"
)
@SysLog
(
"登出"
)
@GetMapping
(
"/logout"
)
public
Result
<
String
>
logout
(){
SecurityUtils
.
getSubject
().
logout
();
return
Result
.
succeed
(
"ok"
);
}
}
src/main/java/com/qkdata/biz/sys/controller/SysMenuController.java
0 → 100644
View file @
7bbe84e0
package
com
.
qkdata
.
biz
.
sys
.
controller
;
import
com.qkdata.biz.sys.entity.SysMenuPO
;
import
com.qkdata.biz.sys.service.ShiroService
;
import
com.qkdata.biz.sys.service.SysMenuService
;
import
com.qkdata.biz.sys.vo.SysNavModel
;
import
com.qkdata.common.annotation.SysLog
;
import
com.qkdata.common.base.exception.BusinessException
;
import
com.qkdata.common.base.model.Result
;
import
com.qkdata.common.util.UserContext
;
import
io.swagger.annotations.Api
;
import
io.swagger.annotations.ApiOperation
;
import
org.apache.shiro.authz.annotation.RequiresPermissions
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.web.bind.annotation.*
;
import
java.util.List
;
import
java.util.Set
;
@Api
(
tags
=
"菜单管理"
)
@RestController
@RequestMapping
(
"/api/sys/menu"
)
public
class
SysMenuController
{
@Autowired
private
SysMenuService
sysMenuService
;
@Autowired
private
ShiroService
shiroService
;
@ApiOperation
(
"获取当前用户的菜单"
)
@GetMapping
(
"/nav"
)
public
Result
<
SysNavModel
>
nav
(){
List
<
SysMenuPO
>
menuList
=
sysMenuService
.
getUserMenuList
(
UserContext
.
getUserId
());
Set
<
String
>
permissions
=
shiroService
.
getUserPermissions
(
UserContext
.
getUserId
());
SysNavModel
navDTO
=
new
SysNavModel
(
menuList
,
permissions
);
return
Result
.
succeed
(
navDTO
);
}
@ApiOperation
(
"获取全部菜单列表"
)
@GetMapping
(
"/list"
)
@RequiresPermissions
(
"sys:menu:list"
)
public
Result
<
List
<
SysMenuPO
>>
list
(){
List
<
SysMenuPO
>
menuList
=
sysMenuService
.
list
();
for
(
SysMenuPO
menuPO
:
menuList
){
SysMenuPO
parentMenu
=
sysMenuService
.
getById
(
menuPO
.
getParentId
());
if
(
parentMenu
!=
null
){
menuPO
.
setParentName
(
parentMenu
.
getName
());
}
}
return
Result
.
succeed
(
menuList
);
}
@ApiOperation
(
"获取不包含按扭的全部菜单"
)
@GetMapping
(
"/select"
)
@RequiresPermissions
(
"sys:menu:select"
)
public
Result
<
List
<
SysMenuPO
>>
select
(){
List
<
SysMenuPO
>
menuList
=
sysMenuService
.
queryNotButtonList
();
//添加顶级菜单
SysMenuPO
root
=
new
SysMenuPO
();
root
.
setId
(
0L
);
root
.
setName
(
"一级菜单"
);
root
.
setParentId
(-
1L
);
root
.
setOpen
(
true
);
menuList
.
add
(
root
);
return
Result
.
succeed
(
menuList
);
}
@ApiOperation
(
"获取单个菜单详细信息"
)
@GetMapping
(
"/info/{id}"
)
@RequiresPermissions
(
"sys:menu:info"
)
public
Result
<
SysMenuPO
>
info
(
@PathVariable
Long
id
){
SysMenuPO
sysMenuPO
=
sysMenuService
.
getById
(
id
);
return
Result
.
succeed
(
sysMenuPO
);
}
@ApiOperation
(
"保存菜单信息"
)
@SysLog
(
"保存菜单信息"
)
@PostMapping
(
"/save"
)
@RequiresPermissions
(
"sys:menu:save"
)
public
Result
<
String
>
save
(
@RequestBody
SysMenuPO
sysMenuPO
){
sysMenuService
.
save
(
sysMenuPO
);
return
Result
.
succeed
(
"ok"
);
}
@ApiOperation
(
"修改菜单信息"
)
@SysLog
(
"修改菜单信息"
)
@PostMapping
(
"/update"
)
@RequiresPermissions
(
"sys:menu:update"
)
public
Result
<
String
>
update
(
@RequestBody
SysMenuPO
sysMenuPO
){
sysMenuService
.
updateById
(
sysMenuPO
);
return
Result
.
succeed
(
"ok"
);
}
@ApiOperation
(
"删除菜单"
)
@SysLog
(
"删除菜单"
)
@GetMapping
(
"/delete/{id}"
)
@RequiresPermissions
(
"sys:menu:delete"
)
public
Result
<
String
>
delete
(
@PathVariable
Long
id
){
if
(
id
<=
31
){
throw
new
BusinessException
(
"系统菜单不能删除"
);
}
//判断是否有子菜单或按钮
List
<
SysMenuPO
>
menuList
=
sysMenuService
.
queryListParentId
(
id
);
if
(
menuList
.
size
()
>
0
){
throw
new
BusinessException
(
"请先删除子菜单或按钮"
);
}
sysMenuService
.
removeById
(
id
);
return
Result
.
succeed
(
"ok"
);
}
}
src/main/java/com/qkdata/biz/sys/controller/SysRoleController.java
0 → 100644
View file @
7bbe84e0
package
com
.
qkdata
.
biz
.
sys
.
controller
;
import
com.qkdata.biz.sys.entity.SysRolePO
;
import
com.qkdata.biz.sys.service.SysRoleService
;
import
com.qkdata.biz.sys.vo.QueryRoleModel
;
import
com.qkdata.biz.sys.vo.SysRoleModel
;
import
com.qkdata.common.annotation.SysLog
;
import
com.qkdata.common.base.model.PageResult
;
import
com.qkdata.common.base.model.Result
;
import
io.swagger.annotations.Api
;
import
io.swagger.annotations.ApiOperation
;
import
org.apache.shiro.authz.annotation.RequiresPermissions
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.validation.annotation.Validated
;
import
org.springframework.web.bind.annotation.*
;
import
java.util.Arrays
;
import
java.util.List
;
@Api
(
tags
=
"角色管理"
)
@RestController
@RequestMapping
(
"/api/sys/role"
)
public
class
SysRoleController
{
@Autowired
private
SysRoleService
sysRoleService
;
/**
* 角色列表
*/
@ApiOperation
(
"获取全部角色列表"
)
@GetMapping
(
"/select"
)
@RequiresPermissions
(
"sys:role:select"
)
public
List
<
SysRolePO
>
select
(){
return
sysRoleService
.
list
();
}
@ApiOperation
(
"查询角色列表"
)
@PostMapping
(
"/list"
)
@RequiresPermissions
(
"sys:role:list"
)
public
PageResult
<
SysRolePO
>
list
(
@RequestBody
QueryRoleModel
queryRoleModel
){
return
sysRoleService
.
queryPageList
(
queryRoleModel
);
}
@ApiOperation
(
"获取某一角色信息"
)
@GetMapping
(
"/info/{id}"
)
@RequiresPermissions
(
"sys:role:info"
)
public
Result
<
SysRoleModel
>
info
(
@PathVariable
Long
id
){
return
Result
.
succeed
(
sysRoleService
.
getRoleInfo
(
id
));
}
@ApiOperation
(
"保存某一角色信息"
)
@SysLog
(
"保存某一角色信息"
)
@PostMapping
(
"/save"
)
@RequiresPermissions
(
"sys:role:save"
)
public
Result
<
String
>
save
(
@RequestBody
@Validated
SysRoleModel
sysRoleModel
){
sysRoleService
.
saveRole
(
sysRoleModel
);
return
Result
.
succeed
(
"ok"
);
}
@ApiOperation
(
"修改某一角色信息"
)
@SysLog
(
"修改某一角色信息"
)
@PostMapping
(
"/update"
)
@RequiresPermissions
(
"sys:role:update"
)
public
Result
<
String
>
update
(
@RequestBody
@Validated
SysRoleModel
sysRoleModel
){
sysRoleService
.
updateRole
(
sysRoleModel
);
return
Result
.
succeed
(
"ok"
);
}
@ApiOperation
(
"删除角色信息"
)
@SysLog
(
"删除角色信息"
)
@PostMapping
(
"/delete"
)
@RequiresPermissions
(
"sys:role:delete"
)
public
Result
<
String
>
delete
(
@RequestBody
Long
[]
ids
){
sysRoleService
.
removeByIds
(
Arrays
.
asList
(
ids
));
return
Result
.
succeed
(
"ok"
);
}
}
src/main/java/com/qkdata/biz/sys/controller/SysUserController.java
0 → 100644
View file @
7bbe84e0
package
com
.
qkdata
.
biz
.
sys
.
controller
;
import
com.qkdata.biz.sys.entity.SysUserPO
;
import
com.qkdata.biz.sys.service.SysUserService
;
import
com.qkdata.biz.sys.vo.PasswordModel
;
import
com.qkdata.biz.sys.vo.QueryUserModel
;
import
com.qkdata.biz.sys.vo.SysUserModel
;
import
com.qkdata.common.annotation.SysLog
;
import
com.qkdata.common.base.exception.BusinessException
;
import
com.qkdata.common.base.model.PageResult
;
import
com.qkdata.common.base.model.Result
;
import
com.qkdata.common.constants.AddGroup
;
import
com.qkdata.common.constants.UpdateGroup
;
import
com.qkdata.common.util.UserContext
;
import
io.swagger.annotations.Api
;
import
io.swagger.annotations.ApiOperation
;
import
org.apache.commons.lang3.ArrayUtils
;
import
org.apache.shiro.authz.annotation.RequiresPermissions
;
import
org.springframework.beans.BeanUtils
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.validation.annotation.Validated
;
import
org.springframework.web.bind.annotation.*
;
import
javax.validation.Valid
;
import
java.util.Arrays
;
@Api
(
tags
=
"用户管理"
)
@RestController
@RequestMapping
(
"/api/sys/user"
)
public
class
SysUserController
{
@Autowired
private
SysUserService
sysUserService
;
@ApiOperation
(
"查询用户列表"
)
@PostMapping
(
"/list"
)
@RequiresPermissions
(
"sys:user:list"
)
public
PageResult
<
SysUserModel
>
list
(
@RequestBody
QueryUserModel
queryUserModel
){
return
sysUserService
.
queryPageList
(
queryUserModel
);
}
@ApiOperation
(
"获取当前用户信息"
)
@GetMapping
(
"/info"
)
public
Result
<
SysUserModel
>
info
(){
SysUserPO
userPO
=
UserContext
.
getUser
();
SysUserModel
dto
=
new
SysUserModel
();
BeanUtils
.
copyProperties
(
userPO
,
dto
);
dto
.
setRoleIdList
(
sysUserService
.
queryRoleIdList
(
userPO
.
getId
()));
return
Result
.
succeed
(
dto
);
}
@ApiOperation
(
"获取某个用户信息"
)
@GetMapping
(
"/info/{id}"
)
@RequiresPermissions
(
"sys:user:info"
)
public
Result
<
SysUserModel
>
infoById
(
@PathVariable
Long
id
){
SysUserPO
sysUserPO
=
sysUserService
.
getById
(
id
);
SysUserModel
dto
=
new
SysUserModel
();
BeanUtils
.
copyProperties
(
sysUserPO
,
dto
);
dto
.
setRoleIdList
(
sysUserService
.
queryRoleIdList
(
id
));
return
Result
.
succeed
(
dto
);
}
@ApiOperation
(
"保存用户信息"
)
@SysLog
(
"保存用户信息"
)
@PostMapping
(
"/save"
)
@RequiresPermissions
(
"sys:user:save"
)
public
Result
<
String
>
save
(
@RequestBody
@Validated
(
AddGroup
.
class
)
SysUserModel
sysUserModel
){
sysUserService
.
saveUser
(
sysUserModel
);
return
Result
.
succeed
(
"ok"
);
}
@ApiOperation
(
"修改用户信息"
)
@SysLog
(
"修改用户信息"
)
@PostMapping
(
"/update"
)
@RequiresPermissions
(
"sys:user:update"
)
public
Result
<
String
>
update
(
@RequestBody
@Validated
(
UpdateGroup
.
class
)
SysUserModel
sysUserModel
){
sysUserService
.
updateUser
(
sysUserModel
);
return
Result
.
succeed
(
"ok"
);
}
/**
* 修改登录用户密码
*/
@SysLog
(
"修改当前用户密码"
)
@ApiOperation
(
"修改当前用户密码"
)
@PostMapping
(
"/password"
)
public
Result
<
String
>
password
(
@RequestBody
@Valid
PasswordModel
form
){
//更新密码
sysUserService
.
updatePassword
(
UserContext
.
getUser
(),
form
.
getPassword
(),
form
.
getNewPassword
());
return
Result
.
succeed
(
"ok"
);
}
/**
* 删除用户
*/
@ApiOperation
(
"删除用户"
)
@SysLog
(
"删除用户"
)
@PostMapping
(
"/delete"
)
@RequiresPermissions
(
"sys:user:delete"
)
public
Result
<
String
>
delete
(
@RequestBody
Long
[]
userIds
){
if
(
ArrayUtils
.
contains
(
userIds
,
1L
)){
throw
new
BusinessException
(
"系统管理员不能删除"
);
}
if
(
ArrayUtils
.
contains
(
userIds
,
UserContext
.
getUserId
())){
throw
new
BusinessException
(
"当前用户不能删除"
);
}
sysUserService
.
removeUsers
(
Arrays
.
asList
(
userIds
));
return
Result
.
succeed
(
"ok"
);
}
}
src/main/java/com/qkdata/biz/sys/entity/SysConfigPO.java
0 → 100644
View file @
7bbe84e0
package
com
.
qkdata
.
biz
.
sys
.
entity
;
import
com.baomidou.mybatisplus.annotation.TableName
;
import
com.qkdata.biz.enums.SysConfigStatusEnum
;
import
com.qkdata.common.base.entity.BasePO
;
import
lombok.Data
;
@Data
@TableName
(
"sys_config"
)
public
class
SysConfigPO
extends
BasePO
{
private
String
paramKey
;
private
String
paramValue
;
private
SysConfigStatusEnum
status
;
private
String
remark
;
}
src/main/java/com/qkdata/biz/sys/entity/SysLogPO.java
0 → 100644
View file @
7bbe84e0
package
com
.
qkdata
.
biz
.
sys
.
entity
;
import
com.baomidou.mybatisplus.annotation.TableName
;
import
com.qkdata.common.base.entity.BasePO
;
import
lombok.Data
;
@Data
@TableName
(
"sys_log"
)
public
class
SysLogPO
extends
BasePO
{
private
String
username
;
private
String
operation
;
private
String
method
;
private
String
params
;
private
String
ip
;
private
Long
time
;
}
src/main/java/com/qkdata/biz/sys/entity/SysMenuPO.java
0 → 100644
View file @
7bbe84e0
package
com
.
qkdata
.
biz
.
sys
.
entity
;
import
com.baomidou.mybatisplus.annotation.TableField
;
import
com.baomidou.mybatisplus.annotation.TableName
;
import
com.qkdata.biz.enums.MenuTypeEnum
;
import
com.qkdata.common.base.entity.BasePO
;
import
lombok.Data
;
import
java.util.List
;
@Data
@TableName
(
"sys_menu"
)
public
class
SysMenuPO
extends
BasePO
{
private
Long
parentId
;
/**
* 非数据库中字段
*/
@TableField
(
exist
=
false
)
private
String
parentName
;
private
String
name
;
private
String
url
;
private
String
perms
;
private
MenuTypeEnum
type
;
private
String
icon
;
private
Integer
orderNum
;
/**
* ztree属性
*/
@TableField
(
exist
=
false
)
private
Boolean
open
;
@TableField
(
exist
=
false
)
private
List
<?>
list
;
}
src/main/java/com/qkdata/biz/sys/entity/SysRoleMenuPO.java
0 → 100644
View file @
7bbe84e0
package
com
.
qkdata
.
biz
.
sys
.
entity
;
import
com.baomidou.mybatisplus.annotation.TableId
;
import
com.baomidou.mybatisplus.annotation.TableName
;
import
lombok.Data
;
@Data
@TableName
(
"sys_role_menu"
)
public
class
SysRoleMenuPO
{
@TableId
private
Long
id
;
private
Long
roleId
;
private
Long
menuId
;
}
src/main/java/com/qkdata/biz/sys/entity/SysRolePO.java
0 → 100644
View file @
7bbe84e0
package
com
.
qkdata
.
biz
.
sys
.
entity
;
import
com.baomidou.mybatisplus.annotation.TableName
;
import
com.qkdata.common.base.entity.BasePO
;
import
lombok.Data
;
@Data
@TableName
(
"sys_role"
)
public
class
SysRolePO
extends
BasePO
{
private
String
name
;
private
String
code
;
}
src/main/java/com/qkdata/biz/sys/entity/SysUserPO.java
0 → 100644
View file @
7bbe84e0
package
com
.
qkdata
.
biz
.
sys
.
entity
;
import
com.baomidou.mybatisplus.annotation.TableLogic
;
import
com.baomidou.mybatisplus.annotation.TableName
;
import
com.qkdata.biz.enums.AccountStatusEnum
;
import
com.qkdata.common.base.entity.BasePO
;
import
lombok.Data
;
import
lombok.EqualsAndHashCode
;
import
java.util.Date
;
@EqualsAndHashCode
(
callSuper
=
true
)
@Data
@TableName
(
"sys_user"
)
public
class
SysUserPO
extends
BasePO
{
private
String
username
;
private
String
password
;
private
String
salt
;
private
String
nickName
;
private
Date
lastLoginTime
;
private
Date
activateTime
;
private
AccountStatusEnum
status
;
@TableLogic
private
Boolean
isDel
;
}
src/main/java/com/qkdata/biz/sys/entity/SysUserRolePO.java
0 → 100644
View file @
7bbe84e0
package
com
.
qkdata
.
biz
.
sys
.
entity
;
import
com.baomidou.mybatisplus.annotation.TableId
;
import
com.baomidou.mybatisplus.annotation.TableName
;
import
lombok.Data
;
@Data
@TableName
(
"sys_user_role"
)
public
class
SysUserRolePO
{
@TableId
private
Long
id
;
private
Long
userId
;
private
Long
roleId
;
}
src/main/java/com/qkdata/biz/sys/mapper/SysConfigMapper.java
0 → 100644
View file @
7bbe84e0
package
com
.
qkdata
.
biz
.
sys
.
mapper
;
import
com.baomidou.mybatisplus.core.mapper.BaseMapper
;
import
com.baomidou.mybatisplus.extension.plugins.pagination.Page
;
import
com.qkdata.biz.sys.entity.SysConfigPO
;
import
com.qkdata.biz.sys.vo.QueryConfigModel
;
import
org.apache.ibatis.annotations.Mapper
;
import
org.apache.ibatis.annotations.Param
;
import
java.util.List
;
@Mapper
public
interface
SysConfigMapper
extends
BaseMapper
<
SysConfigPO
>
{
List
<
SysConfigPO
>
queryPageList
(
Page
<
SysConfigPO
>
page
,
@Param
(
"p"
)
QueryConfigModel
queryConfigModel
);
}
src/main/java/com/qkdata/biz/sys/mapper/SysLogMapper.java
0 → 100644
View file @
7bbe84e0
package
com
.
qkdata
.
biz
.
sys
.
mapper
;
import
com.baomidou.mybatisplus.core.mapper.BaseMapper
;
import
com.baomidou.mybatisplus.extension.plugins.pagination.Page
;
import
com.qkdata.biz.sys.entity.SysLogPO
;
import
com.qkdata.biz.sys.vo.QueryLogModel
;
import
org.apache.ibatis.annotations.Mapper
;
import
org.apache.ibatis.annotations.Param
;
import
java.util.List
;
@Mapper
public
interface
SysLogMapper
extends
BaseMapper
<
SysLogPO
>
{
List
<
SysLogPO
>
queryPageList
(
Page
<
SysLogPO
>
page
,
@Param
(
"p"
)
QueryLogModel
queryLogModel
);
}
src/main/java/com/qkdata/biz/sys/mapper/SysMenuMapper.java
0 → 100644
View file @
7bbe84e0
package
com
.
qkdata
.
biz
.
sys
.
mapper
;
import
com.baomidou.mybatisplus.core.mapper.BaseMapper
;
import
com.qkdata.biz.sys.entity.SysMenuPO
;
import
org.apache.ibatis.annotations.Mapper
;
import
java.util.List
;
@Mapper
public
interface
SysMenuMapper
extends
BaseMapper
<
SysMenuPO
>
{
List
<
SysMenuPO
>
queryNotButtonList
();
}
src/main/java/com/qkdata/biz/sys/mapper/SysRoleMapper.java
0 → 100644
View file @
7bbe84e0
package
com
.
qkdata
.
biz
.
sys
.
mapper
;
import
com.baomidou.mybatisplus.core.mapper.BaseMapper
;
import
com.baomidou.mybatisplus.extension.plugins.pagination.Page
;
import
com.qkdata.biz.sys.entity.SysRolePO
;
import
com.qkdata.biz.sys.vo.QueryRoleModel
;
import
org.apache.ibatis.annotations.Mapper
;
import
org.apache.ibatis.annotations.Param
;
import
java.util.List
;
@Mapper
public
interface
SysRoleMapper
extends
BaseMapper
<
SysRolePO
>
{
List
<
SysRolePO
>
queryPageList
(
Page
<
SysRolePO
>
page
,
@Param
(
"p"
)
QueryRoleModel
queryRoleModel
);
}
src/main/java/com/qkdata/biz/sys/mapper/SysRoleMenuMapper.java
0 → 100644
View file @
7bbe84e0
package
com
.
qkdata
.
biz
.
sys
.
mapper
;
import
com.baomidou.mybatisplus.core.mapper.BaseMapper
;
import
com.qkdata.biz.sys.entity.SysRoleMenuPO
;
import
org.apache.ibatis.annotations.Mapper
;
import
java.util.List
;
@Mapper
public
interface
SysRoleMenuMapper
extends
BaseMapper
<
SysRoleMenuPO
>
{
List
<
Long
>
selectMenuIdsByRoleId
(
Long
roleId
);
}
src/main/java/com/qkdata/biz/sys/mapper/SysUserMapper.java
0 → 100644
View file @
7bbe84e0
package
com
.
qkdata
.
biz
.
sys
.
mapper
;
import
com.baomidou.mybatisplus.core.mapper.BaseMapper
;
import
com.baomidou.mybatisplus.extension.plugins.pagination.Page
;
import
com.qkdata.biz.sys.entity.SysUserPO
;
import
com.qkdata.biz.sys.vo.QueryUserModel
;
import
com.qkdata.biz.sys.vo.SysUserModel
;
import
org.apache.ibatis.annotations.Mapper
;
import
org.apache.ibatis.annotations.Param
;
import
java.util.List
;
@Mapper
public
interface
SysUserMapper
extends
BaseMapper
<
SysUserPO
>
{
List
<
String
>
queryAllPerms
(
Long
userId
);
List
<
SysUserModel
>
queryPageList
(
Page
<
SysUserModel
>
page
,
@Param
(
"p"
)
QueryUserModel
queryUserModel
);
List
<
Long
>
queryAllMenuId
(
Long
userId
);
}
src/main/java/com/qkdata/biz/sys/mapper/SysUserRoleMapper.java
0 → 100644
View file @
7bbe84e0
package
com
.
qkdata
.
biz
.
sys
.
mapper
;
import
com.baomidou.mybatisplus.core.mapper.BaseMapper
;
import
com.qkdata.biz.sys.entity.SysUserRolePO
;
import
org.apache.ibatis.annotations.Mapper
;
import
java.util.List
;
@Mapper
public
interface
SysUserRoleMapper
extends
BaseMapper
<
SysUserRolePO
>
{
List
<
Long
>
queryRoleIdList
(
Long
userId
);
}
src/main/java/com/qkdata/biz/sys/service/ShiroService.java
0 → 100644
View file @
7bbe84e0
package
com
.
qkdata
.
biz
.
sys
.
service
;
import
com.fasterxml.jackson.core.JsonProcessingException
;
import
com.fasterxml.jackson.databind.ObjectMapper
;
import
com.google.common.collect.Maps
;
import
com.qkdata.biz.enums.AccountStatusEnum
;
import
com.qkdata.biz.sys.entity.SysMenuPO
;
import
com.qkdata.biz.sys.entity.SysUserPO
;
import
com.qkdata.biz.sys.vo.LoginUserInfo
;
import
com.qkdata.common.base.exception.BusinessException
;
import
com.qkdata.common.jwt.JWTService
;
import
com.qkdata.common.oauth.AuthorizedUser
;
import
org.apache.shiro.crypto.hash.Sha256Hash
;
import
org.springframework.beans.BeanUtils
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.stereotype.Service
;
import
org.springframework.util.StringUtils
;
import
java.util.*
;
@Service
public
class
ShiroService
{
@Autowired
private
SysUserService
sysUserService
;
@Autowired
private
SysMenuService
sysMenuService
;
@Autowired
private
ObjectMapper
objectMapper
;
@Autowired
private
JWTService
jwtService
;
public
Set
<
String
>
getUserPermissions
(
Long
userId
)
{
List
<
String
>
permsList
;
//系统管理员,拥有最高权限
if
(
userId
==
1
){
List
<
SysMenuPO
>
menuList
=
sysMenuService
.
list
();
permsList
=
new
ArrayList
<>(
menuList
.
size
());
for
(
SysMenuPO
menu
:
menuList
){
permsList
.
add
(
menu
.
getPerms
());
}
}
else
{
permsList
=
sysUserService
.
queryAllPerms
(
userId
);
}
//用户权限列表
Set
<
String
>
permsSet
=
new
HashSet
<>();
for
(
String
perms
:
permsList
){
if
(
StringUtils
.
isEmpty
(
perms
)){
continue
;
}
permsSet
.
addAll
(
Arrays
.
asList
(
perms
.
trim
().
split
(
","
)));
}
return
permsSet
;
}
public
LoginUserInfo
login
(
String
username
,
String
password
)
throws
JsonProcessingException
{
SysUserPO
userPO
=
getUserByUserName
(
username
);
if
(
userPO
==
null
||
!
userPO
.
getPassword
().
equals
(
new
Sha256Hash
(
password
,
userPO
.
getSalt
()).
toHex
()))
{
throw
new
BusinessException
(
"用户名或密码错误"
);
}
if
(
userPO
.
getStatus
()
==
AccountStatusEnum
.
DISABLE
){
throw
new
BusinessException
(
"帐号已禁用"
);
}
String
token
=
generatorToken
(
userPO
);
LoginUserInfo
loginUser
=
new
LoginUserInfo
();
BeanUtils
.
copyProperties
(
userPO
,
loginUser
);
loginUser
.
setAuthorization
(
token
);
return
loginUser
;
}
private
String
generatorToken
(
SysUserPO
userPO
)
throws
JsonProcessingException
{
AuthorizedUser
user
=
new
AuthorizedUser
();
user
.
setUserId
(
userPO
.
getId
());
user
.
setUsername
(
userPO
.
getUsername
());
String
userJson
=
objectMapper
.
writeValueAsString
(
user
);
Map
<
String
,
Object
>
userClaim
=
Maps
.
newConcurrentMap
();
userClaim
.
put
(
"user"
,
userJson
);
return
jwtService
.
createJWT
(
userClaim
);
}
public
SysUserPO
getUserByUserName
(
String
username
)
{
return
sysUserService
.
getByUsername
(
username
);
}
}
src/main/java/com/qkdata/biz/sys/service/SysConfigService.java
0 → 100644
View file @
7bbe84e0
package
com
.
qkdata
.
biz
.
sys
.
service
;
import
com.baomidou.mybatisplus.extension.plugins.pagination.Page
;
import
com.qkdata.biz.sys.entity.SysConfigPO
;
import
com.qkdata.biz.sys.mapper.SysConfigMapper
;
import
com.qkdata.biz.sys.vo.QueryConfigModel
;
import
com.qkdata.common.base.enums.CodeEnum
;
import
com.qkdata.common.base.model.PageResult
;
import
com.qkdata.common.base.service.impl.BaseServiceImpl
;
import
org.springframework.stereotype.Service
;
import
java.util.List
;
@Service
public
class
SysConfigService
extends
BaseServiceImpl
<
SysConfigMapper
,
SysConfigPO
>
{
public
PageResult
<
SysConfigPO
>
queryPageList
(
QueryConfigModel
queryConfigModel
)
{
Page
<
SysConfigPO
>
page
=
new
Page
<>(
queryConfigModel
.
getPageIndex
(),
queryConfigModel
.
getPageSize
());
List
<
SysConfigPO
>
pageList
=
baseMapper
.
queryPageList
(
page
,
queryConfigModel
);
return
PageResult
.<
SysConfigPO
>
builder
().
code
(
CodeEnum
.
SUCCESS
.
getCode
()).
count
(
page
.
getTotal
()).
data
(
pageList
).
build
();
}
}
src/main/java/com/qkdata/biz/sys/service/SysLogService.java
0 → 100644
View file @
7bbe84e0
package
com
.
qkdata
.
biz
.
sys
.
service
;
import
com.baomidou.mybatisplus.extension.plugins.pagination.Page
;
import
com.qkdata.biz.sys.entity.SysLogPO
;
import
com.qkdata.biz.sys.mapper.SysLogMapper
;
import
com.qkdata.biz.sys.vo.QueryLogModel
;
import
com.qkdata.common.base.enums.CodeEnum
;
import
com.qkdata.common.base.model.PageResult
;
import
com.qkdata.common.base.service.impl.BaseServiceImpl
;
import
org.springframework.stereotype.Service
;
import
java.util.List
;
@Service
public
class
SysLogService
extends
BaseServiceImpl
<
SysLogMapper
,
SysLogPO
>
{
public
PageResult
<
SysLogPO
>
queryPageList
(
QueryLogModel
queryLogModel
)
{
Page
<
SysLogPO
>
page
=
new
Page
<>(
queryLogModel
.
getPageIndex
(),
queryLogModel
.
getPageSize
());
List
<
SysLogPO
>
pageList
=
baseMapper
.
queryPageList
(
page
,
queryLogModel
);
return
PageResult
.<
SysLogPO
>
builder
().
code
(
CodeEnum
.
SUCCESS
.
getCode
()).
count
(
page
.
getTotal
()).
data
(
pageList
).
build
();
}
}
src/main/java/com/qkdata/biz/sys/service/SysMenuService.java
0 → 100644
View file @
7bbe84e0
package
com
.
qkdata
.
biz
.
sys
.
service
;
import
com.baomidou.mybatisplus.core.toolkit.Wrappers
;
import
com.google.common.collect.Lists
;
import
com.qkdata.biz.enums.MenuTypeEnum
;
import
com.qkdata.biz.sys.entity.SysMenuPO
;
import
com.qkdata.biz.sys.mapper.SysMenuMapper
;
import
com.qkdata.biz.sys.mapper.SysUserMapper
;
import
com.qkdata.common.base.service.impl.BaseServiceImpl
;
import
com.qkdata.common.constants.Constants
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.stereotype.Service
;
import
java.util.ArrayList
;
import
java.util.List
;
@Service
public
class
SysMenuService
extends
BaseServiceImpl
<
SysMenuMapper
,
SysMenuPO
>
{
@Autowired
private
SysUserMapper
sysUserMapper
;
public
List
<
SysMenuPO
>
getUserMenuList
(
Long
userId
)
{
List
<
SysMenuPO
>
userMenuList
=
Lists
.
newArrayList
();
//系统管理员,拥有最高权限
if
(
userId
==
Constants
.
SYS_ADMIN_ID
){
userMenuList
=
getAllMenuList
(
null
);
}
else
{
//用户菜单列表
List
<
Long
>
menuIdList
=
sysUserMapper
.
queryAllMenuId
(
userId
);
userMenuList
=
getAllMenuList
(
menuIdList
);
}
return
userMenuList
;
}
private
List
<
SysMenuPO
>
getAllMenuList
(
List
<
Long
>
menuIdList
)
{
//查询根菜单列表
List
<
SysMenuPO
>
menuList
=
queryListParentId
(
0L
,
menuIdList
);
//递归获取子菜单
getMenuTreeList
(
menuList
,
menuIdList
);
return
menuList
;
}
private
List
<
SysMenuPO
>
getMenuTreeList
(
List
<
SysMenuPO
>
menuList
,
List
<
Long
>
menuIdList
)
{
List
<
SysMenuPO
>
subMenuList
=
Lists
.
newArrayList
();
for
(
SysMenuPO
entity
:
menuList
){
//目录
if
(
entity
.
getType
()
==
MenuTypeEnum
.
FOLDER
){
entity
.
setList
(
getMenuTreeList
(
queryListParentId
(
entity
.
getId
(),
menuIdList
),
menuIdList
));
}
subMenuList
.
add
(
entity
);
}
return
subMenuList
;
}
private
List
<
SysMenuPO
>
queryListParentId
(
Long
parentId
,
List
<
Long
>
menuIdList
)
{
List
<
SysMenuPO
>
menuList
=
queryListParentId
(
parentId
);
if
(
menuIdList
==
null
){
return
menuList
;
}
List
<
SysMenuPO
>
userMenuList
=
new
ArrayList
<>();
for
(
SysMenuPO
menu
:
menuList
){
if
(
menuIdList
.
contains
(
menu
.
getId
())){
userMenuList
.
add
(
menu
);
}
}
return
userMenuList
;
}
public
List
<
SysMenuPO
>
queryListParentId
(
Long
parentId
)
{
return
list
(
Wrappers
.<
SysMenuPO
>
lambdaQuery
().
eq
(
SysMenuPO:
:
getParentId
,
parentId
));
}
public
List
<
SysMenuPO
>
queryNotButtonList
()
{
return
baseMapper
.
queryNotButtonList
();
}
}
src/main/java/com/qkdata/biz/sys/service/SysRoleMenuService.java
0 → 100644
View file @
7bbe84e0
package
com
.
qkdata
.
biz
.
sys
.
service
;
import
com.baomidou.mybatisplus.core.toolkit.Wrappers
;
import
com.qkdata.biz.sys.entity.SysRoleMenuPO
;
import
com.qkdata.biz.sys.mapper.SysRoleMenuMapper
;
import
com.qkdata.common.base.service.impl.BaseServiceImpl
;
import
org.springframework.stereotype.Service
;
import
org.springframework.util.CollectionUtils
;
import
java.util.List
;
@Service
public
class
SysRoleMenuService
extends
BaseServiceImpl
<
SysRoleMenuMapper
,
SysRoleMenuPO
>
{
public
List
<
Long
>
queryMenuIdList
(
Long
roleId
)
{
return
baseMapper
.
selectMenuIdsByRoleId
(
roleId
);
}
public
void
saveOrUpdateRoleMenu
(
Long
roleId
,
List
<
Long
>
menuIdList
)
{
deleteByRoleIds
(
new
Long
[]{
roleId
});
if
(
CollectionUtils
.
isEmpty
(
menuIdList
)){
return
;
}
for
(
Long
menuId
:
menuIdList
){
SysRoleMenuPO
po
=
new
SysRoleMenuPO
();
po
.
setRoleId
(
roleId
);
po
.
setMenuId
(
menuId
);
save
(
po
);
}
}
private
void
deleteByRoleIds
(
Long
[]
roleIds
)
{
baseMapper
.
delete
(
Wrappers
.<
SysRoleMenuPO
>
lambdaQuery
().
in
(
SysRoleMenuPO:
:
getRoleId
,
roleIds
));
}
}
src/main/java/com/qkdata/biz/sys/service/SysRoleService.java
0 → 100644
View file @
7bbe84e0
package
com
.
qkdata
.
biz
.
sys
.
service
;
import
com.baomidou.mybatisplus.extension.plugins.pagination.Page
;
import
com.qkdata.biz.sys.entity.SysRolePO
;
import
com.qkdata.biz.sys.mapper.SysRoleMapper
;
import
com.qkdata.biz.sys.vo.QueryRoleModel
;
import
com.qkdata.biz.sys.vo.SysRoleModel
;
import
com.qkdata.common.base.enums.CodeEnum
;
import
com.qkdata.common.base.exception.BusinessException
;
import
com.qkdata.common.base.model.PageResult
;
import
com.qkdata.common.base.service.impl.BaseServiceImpl
;
import
org.springframework.beans.BeanUtils
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.stereotype.Service
;
import
org.springframework.transaction.annotation.Transactional
;
import
java.util.List
;
@Service
public
class
SysRoleService
extends
BaseServiceImpl
<
SysRoleMapper
,
SysRolePO
>
{
@Autowired
private
SysRoleMenuService
sysRoleMenuService
;
public
PageResult
<
SysRolePO
>
queryPageList
(
QueryRoleModel
queryRoleModel
)
{
Page
<
SysRolePO
>
page
=
new
Page
<>(
queryRoleModel
.
getPageIndex
(),
queryRoleModel
.
getPageSize
());
List
<
SysRolePO
>
pageList
=
baseMapper
.
queryPageList
(
page
,
queryRoleModel
);
return
PageResult
.<
SysRolePO
>
builder
().
code
(
CodeEnum
.
SUCCESS
.
getCode
()).
count
(
page
.
getTotal
()).
data
(
pageList
).
build
();
}
public
SysRoleModel
getRoleInfo
(
Long
id
)
{
SysRolePO
po
=
getById
(
id
);
if
(
po
==
null
){
throw
new
BusinessException
(
"请求错误,未找到对应角色"
);
}
List
<
Long
>
menuIds
=
sysRoleMenuService
.
queryMenuIdList
(
po
.
getId
());
SysRoleModel
model
=
new
SysRoleModel
();
BeanUtils
.
copyProperties
(
po
,
model
);
model
.
setMenuIdList
(
menuIds
);
return
model
;
}
@Transactional
public
void
saveRole
(
SysRoleModel
sysRoleModel
)
{
SysRolePO
po
=
new
SysRolePO
();
BeanUtils
.
copyProperties
(
sysRoleModel
,
po
);
save
(
po
);
sysRoleMenuService
.
saveOrUpdateRoleMenu
(
po
.
getId
(),
sysRoleModel
.
getMenuIdList
());
}
@Transactional
public
void
updateRole
(
SysRoleModel
sysRoleModel
)
{
SysRolePO
po
=
getById
(
sysRoleModel
.
getId
());
if
(
po
==
null
){
throw
new
BusinessException
(
"请求错误,角色不存在"
);
}
po
.
setName
(
sysRoleModel
.
getName
());
po
.
setCode
(
sysRoleModel
.
getCode
());
updateById
(
po
);
sysRoleMenuService
.
saveOrUpdateRoleMenu
(
po
.
getId
(),
sysRoleModel
.
getMenuIdList
());
}
}
src/main/java/com/qkdata/biz/sys/service/SysUserRoleService.java
0 → 100644
View file @
7bbe84e0
package
com
.
qkdata
.
biz
.
sys
.
service
;
import
com.baomidou.mybatisplus.core.toolkit.Wrappers
;
import
com.qkdata.biz.sys.entity.SysUserRolePO
;
import
com.qkdata.biz.sys.mapper.SysUserRoleMapper
;
import
com.qkdata.common.base.service.impl.BaseServiceImpl
;
import
org.springframework.stereotype.Service
;
import
org.springframework.util.CollectionUtils
;
import
java.util.List
;
@Service
public
class
SysUserRoleService
extends
BaseServiceImpl
<
SysUserRoleMapper
,
SysUserRolePO
>
{
public
List
<
Long
>
queryRoleIdList
(
Long
userId
)
{
return
baseMapper
.
queryRoleIdList
(
userId
);
}
public
void
saveOrUpdateUserRole
(
Long
userId
,
List
<
Long
>
roleIdList
)
{
if
(!
CollectionUtils
.
isEmpty
(
roleIdList
)){
//先删除用户与角色关系
deleteByUserId
(
userId
);
//保存用户角色关系
for
(
Long
roleId
:
roleIdList
){
SysUserRolePO
po
=
new
SysUserRolePO
();
po
.
setUserId
(
userId
);
po
.
setRoleId
(
roleId
);
baseMapper
.
insert
(
po
);
}
}
}
public
void
deleteByUserId
(
Long
userId
){
baseMapper
.
delete
(
Wrappers
.<
SysUserRolePO
>
lambdaQuery
().
eq
(
SysUserRolePO:
:
getUserId
,
userId
));
}
public
void
deleteByUserIds
(
List
<
Long
>
userIds
)
{
baseMapper
.
delete
(
Wrappers
.<
SysUserRolePO
>
lambdaQuery
().
in
(
SysUserRolePO:
:
getUserId
,
userIds
));
}
}
src/main/java/com/qkdata/biz/sys/service/SysUserService.java
0 → 100644
View file @
7bbe84e0
package
com
.
qkdata
.
biz
.
sys
.
service
;
import
com.baomidou.mybatisplus.core.toolkit.Wrappers
;
import
com.baomidou.mybatisplus.extension.plugins.pagination.Page
;
import
com.qkdata.biz.sys.entity.SysUserPO
;
import
com.qkdata.biz.sys.mapper.SysUserMapper
;
import
com.qkdata.biz.sys.vo.QueryUserModel
;
import
com.qkdata.biz.sys.vo.SysUserModel
;
import
com.qkdata.common.base.enums.CodeEnum
;
import
com.qkdata.common.base.exception.BusinessException
;
import
com.qkdata.common.base.model.PageResult
;
import
com.qkdata.common.base.service.impl.BaseServiceImpl
;
import
com.qkdata.common.util.UserContext
;
import
org.apache.commons.lang3.RandomStringUtils
;
import
org.apache.shiro.crypto.hash.Sha256Hash
;
import
org.springframework.beans.BeanUtils
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.stereotype.Service
;
import
org.springframework.transaction.annotation.Transactional
;
import
org.springframework.util.StringUtils
;
import
java.util.List
;
@Service
public
class
SysUserService
extends
BaseServiceImpl
<
SysUserMapper
,
SysUserPO
>
{
@Autowired
private
SysUserRoleService
sysUserRoleService
;
public
SysUserPO
getByUsername
(
String
username
)
{
return
baseMapper
.
selectOne
(
Wrappers
.<
SysUserPO
>
lambdaQuery
().
eq
(
SysUserPO:
:
getUsername
,
username
));
}
public
List
<
String
>
queryAllPerms
(
Long
userId
)
{
return
baseMapper
.
queryAllPerms
(
userId
);
}
public
PageResult
<
SysUserModel
>
queryPageList
(
QueryUserModel
queryUserModel
)
{
Page
<
SysUserModel
>
page
=
new
Page
<>(
queryUserModel
.
getPageIndex
(),
queryUserModel
.
getPageSize
());
List
<
SysUserModel
>
pageList
=
baseMapper
.
queryPageList
(
page
,
queryUserModel
);
return
PageResult
.<
SysUserModel
>
builder
().
code
(
CodeEnum
.
SUCCESS
.
getCode
()).
count
(
page
.
getTotal
()).
data
(
pageList
).
build
();
}
public
List
<
Long
>
queryRoleIdList
(
Long
userId
)
{
return
sysUserRoleService
.
queryRoleIdList
(
userId
);
}
@Transactional
public
void
saveUser
(
SysUserModel
sysUserModel
)
{
SysUserPO
po
=
getByUsername
(
sysUserModel
.
getUsername
());
if
(
po
!=
null
){
throw
new
BusinessException
(
"帐号已存在"
);
}
po
=
new
SysUserPO
();
BeanUtils
.
copyProperties
(
sysUserModel
,
po
);
po
.
setSalt
(
RandomStringUtils
.
randomAlphanumeric
(
20
));
po
.
setPassword
(
new
Sha256Hash
(
sysUserModel
.
getPassword
(),
po
.
getSalt
()).
toHex
());
save
(
po
);
sysUserRoleService
.
saveOrUpdateUserRole
(
po
.
getId
(),
sysUserModel
.
getRoleIdList
());
}
@Transactional
public
void
updateUser
(
SysUserModel
sysUserModel
)
{
SysUserPO
po
=
getById
(
sysUserModel
.
getId
());
if
(
po
==
null
){
throw
new
BusinessException
(
"请求错误,用户不存在"
);
}
po
.
setUsername
(
sysUserModel
.
getUsername
());
if
(!
StringUtils
.
isEmpty
(
sysUserModel
.
getPassword
())){
po
.
setPassword
(
new
Sha256Hash
(
sysUserModel
.
getPassword
(),
po
.
getSalt
()).
toHex
());
}
po
.
setStatus
(
sysUserModel
.
getStatus
());
updateById
(
po
);
sysUserRoleService
.
saveOrUpdateUserRole
(
po
.
getId
(),
sysUserModel
.
getRoleIdList
());
}
public
void
updatePassword
(
SysUserPO
user
,
String
password
,
String
newPassword
)
{
//sha256加密
String
pwd
=
new
Sha256Hash
(
password
,
UserContext
.
getUser
().
getSalt
()).
toHex
();
if
(!
user
.
getPassword
().
equals
(
pwd
)){
throw
new
BusinessException
(
"密码错误"
);
}
//sha256加密
String
newPwd
=
new
Sha256Hash
(
newPassword
,
UserContext
.
getUser
().
getSalt
()).
toHex
();
user
.
setPassword
(
newPwd
);
updateById
(
user
);
}
@Transactional
public
void
removeUsers
(
List
<
Long
>
ids
)
{
removeByIds
(
ids
);
sysUserRoleService
.
deleteByUserIds
(
ids
);
}
}
src/main/java/com/qkdata/biz/sys/vo/LoginModel.java
0 → 100644
View file @
7bbe84e0
package
com
.
qkdata
.
biz
.
sys
.
vo
;
import
lombok.Data
;
import
javax.validation.constraints.NotBlank
;
@Data
public
class
LoginModel
{
@NotBlank
(
message
=
"请填写登陆帐号"
)
private
String
username
;
@NotBlank
(
message
=
"请填写密码"
)
private
String
password
;
}
src/main/java/com/qkdata/biz/sys/vo/LoginUserInfo.java
0 → 100644
View file @
7bbe84e0
package
com
.
qkdata
.
biz
.
sys
.
vo
;
import
lombok.Data
;
@Data
public
class
LoginUserInfo
{
private
Long
id
;
private
String
username
;
private
String
email
;
private
String
mobile
;
private
String
authorization
;
}
src/main/java/com/qkdata/biz/sys/vo/PasswordModel.java
0 → 100644
View file @
7bbe84e0
package
com
.
qkdata
.
biz
.
sys
.
vo
;
import
lombok.Data
;
import
javax.validation.constraints.NotBlank
;
@Data
public
class
PasswordModel
{
@NotBlank
(
message
=
"原密码不能为空"
)
private
String
password
;
@NotBlank
(
message
=
"新密码不能为空"
)
private
String
newPassword
;
}
src/main/java/com/qkdata/biz/sys/vo/QueryConfigModel.java
0 → 100644
View file @
7bbe84e0
package
com
.
qkdata
.
biz
.
sys
.
vo
;
import
com.qkdata.common.constants.Constants
;
import
lombok.Data
;
@Data
public
class
QueryConfigModel
{
private
Integer
pageIndex
=
Constants
.
DEFAULT_PAGE
;
private
Integer
pageSize
=
Constants
.
DEFAULT_PAGE_SIZE
;
private
String
paramKey
;
}
src/main/java/com/qkdata/biz/sys/vo/QueryLogModel.java
0 → 100644
View file @
7bbe84e0
package
com
.
qkdata
.
biz
.
sys
.
vo
;
import
com.qkdata.common.constants.Constants
;
import
lombok.Data
;
@Data
public
class
QueryLogModel
{
private
Integer
pageIndex
=
Constants
.
DEFAULT_PAGE
;
private
Integer
pageSize
=
Constants
.
DEFAULT_PAGE_SIZE
;
private
String
condition
;
}
src/main/java/com/qkdata/biz/sys/vo/QueryRoleModel.java
0 → 100644
View file @
7bbe84e0
package
com
.
qkdata
.
biz
.
sys
.
vo
;
import
com.qkdata.common.constants.Constants
;
import
lombok.Data
;
@Data
public
class
QueryRoleModel
{
private
Integer
pageIndex
=
Constants
.
DEFAULT_PAGE
;
private
Integer
pageSize
=
Constants
.
DEFAULT_PAGE_SIZE
;
private
String
name
;
}
src/main/java/com/qkdata/biz/sys/vo/QueryUserModel.java
0 → 100644
View file @
7bbe84e0
package
com
.
qkdata
.
biz
.
sys
.
vo
;
import
com.qkdata.common.constants.Constants
;
import
lombok.Data
;
@Data
public
class
QueryUserModel
{
private
Integer
pageIndex
=
Constants
.
DEFAULT_PAGE
;
private
Integer
pageSize
=
Constants
.
DEFAULT_PAGE_SIZE
;
private
String
username
;
}
src/main/java/com/qkdata/biz/sys/vo/SysNavModel.java
0 → 100644
View file @
7bbe84e0
package
com
.
qkdata
.
biz
.
sys
.
vo
;
import
com.qkdata.biz.sys.entity.SysMenuPO
;
import
lombok.AllArgsConstructor
;
import
lombok.Data
;
import
java.util.List
;
import
java.util.Set
;
@Data
@AllArgsConstructor
public
class
SysNavModel
{
private
List
<
SysMenuPO
>
menuList
;
private
Set
<
String
>
permissions
;
}
src/main/java/com/qkdata/biz/sys/vo/SysRoleModel.java
0 → 100644
View file @
7bbe84e0
package
com
.
qkdata
.
biz
.
sys
.
vo
;
import
lombok.Data
;
import
javax.validation.constraints.NotBlank
;
import
java.util.List
;
@Data
public
class
SysRoleModel
{
private
Long
id
;
@NotBlank
(
message
=
"角色名称不能为空"
)
private
String
name
;
@NotBlank
(
message
=
"角色代码不能为空"
)
private
String
code
;
private
List
<
Long
>
menuIdList
;
}
src/main/java/com/qkdata/biz/sys/vo/SysUserModel.java
0 → 100644
View file @
7bbe84e0
package
com
.
qkdata
.
biz
.
sys
.
vo
;
import
com.qkdata.biz.enums.AccountStatusEnum
;
import
com.qkdata.common.constants.AddGroup
;
import
com.qkdata.common.constants.UpdateGroup
;
import
lombok.Data
;
import
javax.validation.constraints.NotBlank
;
import
java.util.List
;
@Data
public
class
SysUserModel
{
private
Long
id
;
@NotBlank
(
message
=
"用户名不能为空"
,
groups
=
{
AddGroup
.
class
,
UpdateGroup
.
class
})
private
String
username
;
@NotBlank
(
message
=
"密码不能为空"
,
groups
=
AddGroup
.
class
)
private
String
password
;
private
String
email
;
private
String
mobile
;
private
AccountStatusEnum
status
;
private
List
<
Long
>
roleIdList
;
}
src/main/java/com/qkdata/common/annotation/ApiLimit.java
0 → 100644
View file @
7bbe84e0
package
com
.
qkdata
.
common
.
annotation
;
import
java.lang.annotation.*
;
@Target
(
ElementType
.
METHOD
)
@Retention
(
RetentionPolicy
.
RUNTIME
)
@Documented
public
@interface
ApiLimit
{
/**
* 限制某时间段内可以访问的次数,默认设置200
*/
int
limitCounts
()
default
200
;
/**
* @return
* @Description: 限制访问的某一个时间段,单位为秒,默认值10秒
*/
int
timeSecond
()
default
10
;
}
src/main/java/com/qkdata/common/annotation/SysLog.java
0 → 100644
View file @
7bbe84e0
package
com
.
qkdata
.
common
.
annotation
;
import
java.lang.annotation.*
;
@Target
(
ElementType
.
METHOD
)
@Retention
(
RetentionPolicy
.
RUNTIME
)
@Documented
public
@interface
SysLog
{
String
value
()
default
""
;
boolean
includeParam
()
default
true
;
}
src/main/java/com/qkdata/common/aspect/ApiLimitAspect.java
0 → 100644
View file @
7bbe84e0
package
com
.
qkdata
.
common
.
aspect
;
import
com.qkdata.common.annotation.ApiLimit
;
import
com.qkdata.common.base.exception.BusinessException
;
import
lombok.extern.slf4j.Slf4j
;
import
org.aspectj.lang.JoinPoint
;
import
org.aspectj.lang.ProceedingJoinPoint
;
import
org.aspectj.lang.Signature
;
import
org.aspectj.lang.annotation.Around
;
import
org.aspectj.lang.annotation.Aspect
;
import
org.aspectj.lang.annotation.Pointcut
;
import
org.aspectj.lang.reflect.MethodSignature
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.data.redis.core.RedisTemplate
;
import
org.springframework.data.redis.core.ValueOperations
;
import
org.springframework.stereotype.Component
;
import
java.lang.reflect.Method
;
import
java.util.concurrent.TimeUnit
;
@Aspect
@Component
@Slf4j
public
class
ApiLimitAspect
{
@Autowired
private
RedisTemplate
<
String
,
Object
>
redisTemplate
;
@Pointcut
(
"@annotation(com.qkdata.common.annotation.ApiLimit)"
)
public
void
logPointCut
()
{
}
@Around
(
"logPointCut()"
)
public
Object
around
(
ProceedingJoinPoint
point
)
throws
Throwable
{
ApiLimit
apiLimit
=
getAnnotation
(
point
);
return
dealLimit
(
point
,
apiLimit
,
false
);
}
private
Object
dealLimit
(
ProceedingJoinPoint
point
,
ApiLimit
apiLimit
,
boolean
flag
)
throws
Throwable
{
String
msgKey
=
getMsgKey
(
point
);
ValueOperations
<
String
,
Object
>
valueOperations
=
redisTemplate
.
opsForValue
();
long
methodCounts
=
valueOperations
.
increment
(
msgKey
,
1
);
// 如果该key不存在,则从0开始计算,并且当count为1的时候,设置过期时间
if
(
methodCounts
==
1
)
{
redisTemplate
.
expire
(
msgKey
,
apiLimit
.
timeSecond
(),
TimeUnit
.
SECONDS
);
}
// 如果redis中的count大于限制的次数,则等待10秒重试
if
(
methodCounts
>
apiLimit
.
limitCounts
())
{
if
(!
flag
)
{
//等待10秒后,第一次重试
Thread
.
sleep
(
10
*
1000
);
log
.
warn
(
"等待10秒后,第一次重试..."
);
// 递归,再次请求业务方法
return
dealLimit
(
point
,
apiLimit
,
true
);
}
else
{
//如果第一次请求被限制了,等待10秒后重试,如果再次失败,则抛出异常
throw
new
BusinessException
(
"请求超时"
);
}
}
else
{
return
point
.
proceed
();
}
}
private
ApiLimit
getAnnotation
(
JoinPoint
joinPoint
)
{
Signature
signature
=
joinPoint
.
getSignature
();
MethodSignature
methodSignature
=
(
MethodSignature
)
signature
;
Method
method
=
methodSignature
.
getMethod
();
return
method
.
getAnnotation
(
ApiLimit
.
class
);
}
private
String
getMsgKey
(
ProceedingJoinPoint
point
){
MethodSignature
signature
=
(
MethodSignature
)
point
.
getSignature
();
String
className
=
point
.
getTarget
().
getClass
().
getName
();
String
methodName
=
signature
.
getName
();
String
msgKey
=
className
+
"."
+
methodName
;
return
msgKey
;
}
}
src/main/java/com/qkdata/common/aspect/SysLogAspect.java
0 → 100644
View file @
7bbe84e0
package
com
.
qkdata
.
common
.
aspect
;
import
com.alibaba.fastjson.JSONArray
;
import
com.qkdata.biz.sys.entity.SysLogPO
;
import
com.qkdata.biz.sys.entity.SysUserPO
;
import
com.qkdata.biz.sys.service.SysLogService
;
import
com.qkdata.common.annotation.SysLog
;
import
com.qkdata.common.util.HttpContextUtils
;
import
com.qkdata.common.util.IPUtils
;
import
com.qkdata.common.util.UserContext
;
import
org.aspectj.lang.ProceedingJoinPoint
;
import
org.aspectj.lang.annotation.Around
;
import
org.aspectj.lang.annotation.Aspect
;
import
org.aspectj.lang.annotation.Pointcut
;
import
org.aspectj.lang.reflect.MethodSignature
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.stereotype.Component
;
import
javax.servlet.http.HttpServletRequest
;
import
java.lang.reflect.Method
;
@Aspect
@Component
public
class
SysLogAspect
{
@Autowired
private
SysLogService
sysLogService
;
@Pointcut
(
"@annotation(com.qkdata.common.annotation.SysLog)"
)
public
void
logPointCut
()
{
}
@Around
(
"logPointCut()"
)
public
Object
around
(
ProceedingJoinPoint
point
)
throws
Throwable
{
long
beginTime
=
System
.
currentTimeMillis
();
//执行方法
Object
result
=
null
;
try
{
result
=
point
.
proceed
();
//执行时长(毫秒)
long
time
=
System
.
currentTimeMillis
()
-
beginTime
;
//保存日志
saveSysLog
(
point
,
time
);
return
result
;
}
catch
(
Throwable
e
){
long
time
=
System
.
currentTimeMillis
()
-
beginTime
;
saveSysLog
(
point
,
time
);
throw
e
;
}
}
private
void
saveSysLog
(
ProceedingJoinPoint
joinPoint
,
long
time
)
{
MethodSignature
signature
=
(
MethodSignature
)
joinPoint
.
getSignature
();
Method
method
=
signature
.
getMethod
();
SysLogPO
sysLog
=
new
SysLogPO
();
SysLog
syslog
=
method
.
getAnnotation
(
SysLog
.
class
);
if
(
syslog
!=
null
){
//注解上的描述
sysLog
.
setOperation
(
syslog
.
value
());
}
//请求的方法名
String
className
=
joinPoint
.
getTarget
().
getClass
().
getName
();
String
methodName
=
signature
.
getName
();
sysLog
.
setMethod
(
className
+
"."
+
methodName
+
"()"
);
if
(
syslog
!=
null
&&
syslog
.
includeParam
()){
//请求的参数
Object
[]
args
=
joinPoint
.
getArgs
();
try
{
String
params
=
JSONArray
.
toJSONString
(
args
);
sysLog
.
setParams
(
params
);
}
catch
(
Exception
e
){
}
}
sysLog
.
setTime
(
time
);
//获取request
HttpServletRequest
request
=
HttpContextUtils
.
getHttpServletRequest
();
//设置IP地址
sysLog
.
setIp
(
IPUtils
.
getIpAddr
(
request
));
//用户名
SysUserPO
user
=
UserContext
.
getUser
();
if
(
user
!=
null
){
String
username
=
UserContext
.
getUser
().
getUsername
();
sysLog
.
setUsername
(
username
);
}
//保存系统日志
sysLogService
.
save
(
sysLog
);
}
}
src/main/java/com/qkdata/common/base/entity/BasePO.java
0 → 100644
View file @
7bbe84e0
package
com
.
qkdata
.
common
.
base
.
entity
;
import
com.baomidou.mybatisplus.annotation.FieldFill
;
import
com.baomidou.mybatisplus.annotation.TableField
;
import
com.baomidou.mybatisplus.annotation.TableId
;
import
com.baomidou.mybatisplus.extension.activerecord.Model
;
import
lombok.Data
;
import
java.io.Serializable
;
import
java.util.Date
;
@Data
public
class
BasePO
<
T
extends
Model
<?>>
extends
Model
<
T
>
{
/**
* 主键ID
*/
@TableId
private
Long
id
;
@TableField
(
fill
=
FieldFill
.
INSERT
)
private
Date
createTime
;
@TableField
(
fill
=
FieldFill
.
INSERT_UPDATE
)
private
Date
updateTime
;
@Override
protected
Serializable
pkVal
()
{
return
this
.
id
;
}
}
src/main/java/com/qkdata/common/base/enums/CodeEnum.java
0 → 100644
View file @
7bbe84e0
package
com
.
qkdata
.
common
.
base
.
enums
;
public
enum
CodeEnum
{
SUCCESS
(
200
),
ERROR
(
1000
);
private
Integer
code
;
CodeEnum
(
Integer
code
){
this
.
code
=
code
;
}
public
Integer
getCode
()
{
return
code
;
}
}
src/main/java/com/qkdata/common/base/exception/BusinessException.java
0 → 100644
View file @
7bbe84e0
package
com
.
qkdata
.
common
.
base
.
exception
;
import
lombok.Data
;
/**
* 业务异常
*/
@Data
public
class
BusinessException
extends
RuntimeException
{
/**
*
*/
private
static
final
long
serialVersionUID
=
4650570427238258122L
;
public
BusinessException
()
{
super
();
}
public
BusinessException
(
String
message
)
{
super
(
message
);
}
public
BusinessException
(
Throwable
cause
)
{
super
(
cause
);
}
public
BusinessException
(
String
message
,
Throwable
cause
)
{
super
(
message
,
cause
);
}
}
src/main/java/com/qkdata/common/base/model/PageResult.java
0 → 100644
View file @
7bbe84e0
package
com
.
qkdata
.
common
.
base
.
model
;
import
lombok.AllArgsConstructor
;
import
lombok.Builder
;
import
lombok.Data
;
import
lombok.NoArgsConstructor
;
import
java.io.Serializable
;
import
java.util.List
;
/**
* 分页实体类
*
*/
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public
class
PageResult
<
T
>
implements
Serializable
{
private
static
final
long
serialVersionUID
=
-
275582248840137389L
;
/**
* 总数
*/
private
Long
count
;
/**
* 是否成功:0 成功、1 失败
*/
private
int
code
;
/**
* 当前页结果集
*/
private
List
<
T
>
data
;
}
src/main/java/com/qkdata/common/base/model/Result.java
0 → 100644
View file @
7bbe84e0
package
com
.
qkdata
.
common
.
base
.
model
;
import
com.qkdata.common.base.enums.CodeEnum
;
import
lombok.AllArgsConstructor
;
import
lombok.Data
;
import
lombok.NoArgsConstructor
;
import
java.io.Serializable
;
@Data
@NoArgsConstructor
@AllArgsConstructor
public
class
Result
<
T
>
implements
Serializable
{
private
T
datas
;
private
Integer
resp_code
;
private
String
resp_msg
;
public
static
<
T
>
Result
<
T
>
succeed
(
String
msg
)
{
return
of
(
null
,
CodeEnum
.
SUCCESS
.
getCode
(),
msg
);
}
public
static
<
T
>
Result
<
T
>
succeed
(
T
model
,
String
msg
)
{
return
of
(
model
,
CodeEnum
.
SUCCESS
.
getCode
(),
msg
);
}
public
static
<
T
>
Result
<
T
>
succeed
(
T
model
)
{
return
of
(
model
,
CodeEnum
.
SUCCESS
.
getCode
(),
""
);
}
public
static
<
T
>
Result
<
T
>
of
(
T
datas
,
Integer
code
,
String
msg
)
{
return
new
Result
<>(
datas
,
code
,
msg
);
}
public
static
<
T
>
Result
<
T
>
failed
(
String
msg
)
{
return
of
(
null
,
CodeEnum
.
ERROR
.
getCode
(),
msg
);
}
public
static
<
T
>
Result
<
T
>
failed
(
T
model
,
String
msg
)
{
return
of
(
model
,
CodeEnum
.
ERROR
.
getCode
(),
msg
);
}
}
src/main/java/com/qkdata/common/base/service/impl/BaseServiceImpl.java
0 → 100644
View file @
7bbe84e0
package
com
.
qkdata
.
common
.
base
.
service
.
impl
;
import
com.baomidou.mybatisplus.core.mapper.BaseMapper
;
import
com.baomidou.mybatisplus.extension.service.impl.ServiceImpl
;
public
abstract
class
BaseServiceImpl
<
M
extends
BaseMapper
<
T
>,
T
>
extends
ServiceImpl
<
M
,
T
>
{
}
src/main/java/com/qkdata/common/config/DateMetaObjectHandler.java
0 → 100644
View file @
7bbe84e0
package
com
.
qkdata
.
common
.
config
;
import
cn.hutool.core.date.DateUtil
;
import
com.baomidou.mybatisplus.core.handlers.MetaObjectHandler
;
import
com.baomidou.mybatisplus.core.handlers.StrictFill
;
import
org.apache.ibatis.reflection.MetaObject
;
import
org.springframework.stereotype.Component
;
import
java.util.Collections
;
import
java.util.Date
;
/**
* 自定义填充公共字段
*
*/
@Component
public
class
DateMetaObjectHandler
implements
MetaObjectHandler
{
/**
* 插入填充,字段为空自动填充
*/
@Override
public
void
insertFill
(
MetaObject
metaObject
)
{
this
.
strictInsertFill
(
metaObject
,
"createTime"
,
Date
.
class
,
DateUtil
.
date
());
this
.
strictUpdateFill
(
metaObject
,
"updateTime"
,
Date
.
class
,
DateUtil
.
date
());
}
/**
* 更新填充
*/
@Override
public
void
updateFill
(
MetaObject
metaObject
)
{
setFieldValByName
(
"updateTime"
,
new
Date
(),
metaObject
);
}
}
\ No newline at end of file
src/main/java/com/qkdata/common/config/FilterConfig.java
0 → 100644
View file @
7bbe84e0
package
com
.
qkdata
.
common
.
config
;
import
org.springframework.boot.web.servlet.FilterRegistrationBean
;
import
org.springframework.context.annotation.Bean
;
import
org.springframework.context.annotation.Configuration
;
import
org.springframework.web.filter.DelegatingFilterProxy
;
@Configuration
public
class
FilterConfig
{
@Bean
public
FilterRegistrationBean
shiroFilterRegistration
()
{
FilterRegistrationBean
registration
=
new
FilterRegistrationBean
();
registration
.
setFilter
(
new
DelegatingFilterProxy
(
"shiroFilter"
));
//该值缺省为false,表示生命周期由SpringApplicationContext管理,设置为true则表示由ServletContainer管理
registration
.
addInitParameter
(
"targetFilterLifecycle"
,
"true"
);
registration
.
setEnabled
(
true
);
registration
.
setOrder
(
Integer
.
MAX_VALUE
-
1
);
registration
.
addUrlPatterns
(
"/api/*"
);
return
registration
;
}
}
src/main/java/com/qkdata/common/config/GlobalExceptionHandle.java
0 → 100644
View file @
7bbe84e0
package
com
.
qkdata
.
common
.
config
;
import
com.qkdata.common.base.exception.BusinessException
;
import
com.qkdata.common.base.model.Result
;
import
lombok.extern.slf4j.Slf4j
;
import
org.springframework.http.HttpStatus
;
import
org.springframework.http.ResponseEntity
;
import
org.springframework.http.converter.HttpMessageNotReadableException
;
import
org.springframework.validation.BindingResult
;
import
org.springframework.web.HttpMediaTypeNotSupportedException
;
import
org.springframework.web.HttpRequestMethodNotSupportedException
;
import
org.springframework.web.bind.MethodArgumentNotValidException
;
import
org.springframework.web.bind.MissingPathVariableException
;
import
org.springframework.web.bind.MissingServletRequestParameterException
;
import
org.springframework.web.bind.annotation.ExceptionHandler
;
import
org.springframework.web.bind.annotation.RestControllerAdvice
;
import
org.springframework.web.method.annotation.MethodArgumentTypeMismatchException
;
import
org.springframework.web.servlet.NoHandlerFoundException
;
import
javax.validation.ConstraintViolationException
;
@RestControllerAdvice
@Slf4j
public
class
GlobalExceptionHandle
{
@ExceptionHandler
(
value
=
MethodArgumentNotValidException
.
class
)
public
ResponseEntity
<
Result
>
bindExceptionHandler
(
MethodArgumentNotValidException
e
)
{
BindingResult
bindingResult
=
e
.
getBindingResult
();
String
message
=
bindingResult
.
getFieldError
().
getDefaultMessage
();
log
.
warn
(
"方法参数无效: {}"
,
message
);
return
ResponseEntity
.
status
(
HttpStatus
.
OK
).
body
(
Result
.
failed
(
message
));
}
@ExceptionHandler
(
value
=
HttpRequestMethodNotSupportedException
.
class
)
public
ResponseEntity
<
Result
>
httpRequestMethodNotSupportedExceptionHandler
(
HttpRequestMethodNotSupportedException
e
)
{
log
.
warn
(
"不支持的Method: {}"
,
e
.
getMessage
());
return
ResponseEntity
.
status
(
HttpStatus
.
NOT_FOUND
).
body
(
Result
.
failed
(
"不支持当前请求方法"
));
}
@ExceptionHandler
(
value
=
Exception
.
class
)
public
ResponseEntity
<
Result
>
handler
(
Exception
e
)
{
log
.
error
(
"服务器错误"
,
e
);
return
ResponseEntity
.
status
(
HttpStatus
.
INTERNAL_SERVER_ERROR
).
body
(
Result
.
failed
(
"服务器处理错误"
));
}
@ExceptionHandler
(
value
=
BusinessException
.
class
)
public
ResponseEntity
<
Result
>
businessExceptionhandler
(
BusinessException
e
)
{
log
.
warn
(
"业务异常, message: {}"
,
e
.
getMessage
());
return
ResponseEntity
.
status
(
HttpStatus
.
OK
).
body
(
Result
.
failed
(
e
.
getMessage
()));
}
@ExceptionHandler
(
value
=
HttpMessageNotReadableException
.
class
)
public
ResponseEntity
<
Result
>
httpMessageConvertExceptionHanlder
(
HttpMessageNotReadableException
e
)
{
log
.
warn
(
"无法解析请求参数: {}"
,
e
.
getMessage
());
return
ResponseEntity
.
badRequest
().
body
(
Result
.
failed
(
e
.
getMessage
()));
}
@ExceptionHandler
(
value
=
MissingPathVariableException
.
class
)
public
ResponseEntity
<
Result
>
missingPathVariableExceptionHanlder
(
MissingPathVariableException
e
)
{
log
.
warn
(
"请求链接缺少参数: {}"
,
e
.
getMessage
());
return
ResponseEntity
.
badRequest
().
body
(
Result
.
failed
(
e
.
getMessage
()));
}
@ExceptionHandler
(
value
=
MissingServletRequestParameterException
.
class
)
public
ResponseEntity
<
Result
>
requestParameterExceptionHandler
(
MissingServletRequestParameterException
e
)
{
log
.
warn
(
"缺少必需的请求参数: {}"
,
e
.
getMessage
());
return
ResponseEntity
.
badRequest
().
body
(
Result
.
failed
(
e
.
getMessage
()));
}
@ExceptionHandler
(
value
=
MethodArgumentTypeMismatchException
.
class
)
public
ResponseEntity
<
Result
>
methodArgumentTypeMismatchExceptionHandler
(
MethodArgumentTypeMismatchException
e
)
{
log
.
warn
(
"参数类别转换失败: {}"
,
e
.
getMessage
());
return
ResponseEntity
.
badRequest
().
body
(
Result
.
failed
(
e
.
getMessage
()));
}
@ExceptionHandler
(
value
=
ConstraintViolationException
.
class
)
public
ResponseEntity
<
Result
>
constraintViolationExceptionHandler
(
ConstraintViolationException
e
)
{
log
.
warn
(
"参数校验异常: {}"
,
e
.
getMessage
());
return
ResponseEntity
.
badRequest
().
body
(
Result
.
failed
(
e
.
getMessage
()));
}
@ExceptionHandler
(
value
=
HttpMediaTypeNotSupportedException
.
class
)
public
ResponseEntity
<
Result
>
httpMediaTypeNotSupportedExceptionHandler
(
HttpMediaTypeNotSupportedException
e
)
{
log
.
warn
(
"不支持MediaType: {}"
,
e
.
getMessage
());
return
ResponseEntity
.
badRequest
().
body
(
Result
.
failed
(
e
.
getMessage
()));
}
@ExceptionHandler
(
value
=
NoHandlerFoundException
.
class
)
public
ResponseEntity
<
Result
>
noHandlerFoundExceptionHandler
(
NoHandlerFoundException
e
)
{
log
.
warn
(
"no handler found: {}"
,
e
.
getMessage
());
return
ResponseEntity
.
status
(
HttpStatus
.
NOT_FOUND
).
body
(
Result
.
failed
(
e
.
getMessage
()));
}
}
src/main/java/com/qkdata/common/config/HttpHeaderInterceptor.java
0 → 100644
View file @
7bbe84e0
package
com
.
qkdata
.
common
.
config
;
import
org.springframework.http.HttpRequest
;
import
org.springframework.http.MediaType
;
import
org.springframework.http.client.ClientHttpRequestExecution
;
import
org.springframework.http.client.ClientHttpRequestInterceptor
;
import
org.springframework.http.client.ClientHttpResponse
;
import
java.io.IOException
;
import
java.nio.charset.Charset
;
public
class
HttpHeaderInterceptor
implements
ClientHttpRequestInterceptor
{
private
final
String
name
;
private
final
String
value
;
public
HttpHeaderInterceptor
(
String
name
,
String
value
)
{
// Assert.hasLength(name, "Name must not be empty");
// Assert.hasLength(value, "Value" + " must not be empty");
this
.
name
=
name
;
this
.
value
=
value
;
}
@Override
public
ClientHttpResponse
intercept
(
HttpRequest
request
,
byte
[]
body
,
ClientHttpRequestExecution
execution
)
throws
IOException
{
request
.
getHeaders
().
add
(
this
.
name
,
this
.
value
);
charsetToUTF8
(
request
);
return
execution
.
execute
(
request
,
body
);
}
private
void
charsetToUTF8
(
HttpRequest
request
)
{
MediaType
contentType
=
request
.
getHeaders
().
getContentType
();
if
(
contentType
.
getCharset
()
==
null
||
Charset
.
forName
(
"UTF-8"
)
!=
contentType
.
getCharset
())
{
contentType
=
new
MediaType
(
contentType
,
Charset
.
forName
(
"UTF-8"
));
request
.
getHeaders
().
setContentType
(
contentType
);
}
}
}
src/main/java/com/qkdata/common/config/HttpTraceConfiguration.java
0 → 100644
View file @
7bbe84e0
package
com
.
qkdata
.
common
.
config
;
import
com.fasterxml.jackson.databind.ObjectMapper
;
import
com.qkdata.common.trace.HttpTraceLogFilter
;
import
org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean
;
import
org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication
;
import
org.springframework.context.annotation.Bean
;
import
org.springframework.context.annotation.Configuration
;
@Configuration
@ConditionalOnWebApplication
public
class
HttpTraceConfiguration
{
@Configuration
@ConditionalOnWebApplication
(
type
=
ConditionalOnWebApplication
.
Type
.
SERVLET
)
static
class
ServletTraceFilterConfiguration
{
@Bean
@ConditionalOnMissingBean
public
HttpTraceLogFilter
httpTraceLogFilter
(
ObjectMapper
objectMapper
)
{
return
new
HttpTraceLogFilter
(
objectMapper
);
}
}
}
src/main/java/com/qkdata/common/config/JacksonConfiguration.java
0 → 100644
View file @
7bbe84e0
package
com
.
qkdata
.
common
.
config
;
import
com.fasterxml.jackson.databind.DeserializationFeature
;
import
com.fasterxml.jackson.databind.SerializationFeature
;
import
com.qkdata.common.converter.*
;
import
org.springframework.boot.autoconfigure.jackson.Jackson2ObjectMapperBuilderCustomizer
;
import
org.springframework.context.annotation.Bean
;
import
org.springframework.context.annotation.Configuration
;
import
java.time.LocalDate
;
import
java.time.LocalDateTime
;
import
java.util.Date
;
@Configuration
public
class
JacksonConfiguration
{
@Bean
public
Jackson2ObjectMapperBuilderCustomizer
objectMapper
()
{
return
builder
->
builder
.
failOnEmptyBeans
(
false
)
.
failOnUnknownProperties
(
false
)
.
createXmlMapper
(
false
)
// .serializationInclusion(JsonInclude.Include.NON_EMPTY)
// .serializationInclusion(JsonInclude.Include.NON_NULL)
.
serializerByType
(
Date
.
class
,
new
DateSerializer
())
.
deserializerByType
(
Date
.
class
,
new
DateDeserializer
())
.
serializerByType
(
LocalDate
.
class
,
new
LocalDateSerializer
())
.
deserializerByType
(
LocalDate
.
class
,
new
LocalDateDeserializer
())
.
serializerByType
(
LocalDateTime
.
class
,
new
LocalDateTimeSerializer
())
.
deserializerByType
(
LocalDateTime
.
class
,
new
LocalDateTimeDeserializer
())
.
featuresToDisable
(
DeserializationFeature
.
READ_ENUMS_USING_TO_STRING
)
.
featuresToDisable
(
SerializationFeature
.
WRITE_DATES_AS_TIMESTAMPS
);
}
}
src/main/java/com/qkdata/common/config/LogClientHttpRequestInterceptor.java
0 → 100644
View file @
7bbe84e0
package
com
.
qkdata
.
common
.
config
;
import
lombok.extern.slf4j.Slf4j
;
import
org.springframework.http.HttpRequest
;
import
org.springframework.http.client.ClientHttpRequestExecution
;
import
org.springframework.http.client.ClientHttpRequestInterceptor
;
import
org.springframework.http.client.ClientHttpResponse
;
import
java.io.IOException
;
@Slf4j
public
class
LogClientHttpRequestInterceptor
implements
ClientHttpRequestInterceptor
{
@Override
public
ClientHttpResponse
intercept
(
HttpRequest
request
,
byte
[]
body
,
ClientHttpRequestExecution
execution
)
throws
IOException
{
log
.
info
(
"restTemplate请求日志, uri: {}, method: {}, methodValue: {}, headers: {}"
,
request
.
getURI
(),
request
.
getMethod
(),
request
.
getMethodValue
(),
request
.
getHeaders
());
return
execution
.
execute
(
request
,
body
);
}
}
src/main/java/com/qkdata/common/config/MybatisPlusAutoConfigure.java
0 → 100644
View file @
7bbe84e0
package
com
.
qkdata
.
common
.
config
;
import
com.baomidou.mybatisplus.extension.plugins.PaginationInterceptor
;
import
com.baomidou.mybatisplus.extension.plugins.pagination.optimize.JsqlParserCountOptimize
;
import
org.mybatis.spring.annotation.MapperScan
;
import
org.springframework.context.annotation.Bean
;
import
org.springframework.context.annotation.Configuration
;
/**
* mybatis-plus自动配置
*
*/
@Configuration
public
class
MybatisPlusAutoConfigure
{
/**
* 分页插件,自动识别数据库类型
*/
@Bean
public
PaginationInterceptor
paginationInterceptor
()
{
PaginationInterceptor
paginationInterceptor
=
new
PaginationInterceptor
();
// 设置请求的页面大于最大页后操作, true调回到首页,false 继续请求 默认false
// paginationInterceptor.setOverflow(false);
// 设置最大单页限制数量,默认 500 条,-1 不受限制
// paginationInterceptor.setLimit(500);
// 开启 count 的 join 优化,只针对部分 left join
paginationInterceptor
.
setCountSqlParser
(
new
JsqlParserCountOptimize
(
true
));
return
paginationInterceptor
;
}
}
src/main/java/com/qkdata/common/config/RedisConfig.java
0 → 100644
View file @
7bbe84e0
package
com
.
qkdata
.
common
.
config
;
import
com.fasterxml.jackson.annotation.JsonAutoDetect
;
import
com.fasterxml.jackson.annotation.PropertyAccessor
;
import
com.fasterxml.jackson.databind.ObjectMapper
;
import
com.fasterxml.jackson.databind.module.SimpleModule
;
import
com.qkdata.common.converter.LocalDateTimeDeserializer
;
import
com.qkdata.common.converter.LocalDateTimeSerializer
;
import
lombok.extern.slf4j.Slf4j
;
import
org.springframework.boot.autoconfigure.AutoConfigureAfter
;
import
org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration
;
import
org.springframework.context.annotation.Bean
;
import
org.springframework.context.annotation.Configuration
;
import
org.springframework.data.redis.cache.RedisCacheConfiguration
;
import
org.springframework.data.redis.cache.RedisCacheManager
;
import
org.springframework.data.redis.cache.RedisCacheWriter
;
import
org.springframework.data.redis.connection.RedisConnectionFactory
;
import
org.springframework.data.redis.core.RedisTemplate
;
import
org.springframework.data.redis.listener.RedisMessageListenerContainer
;
import
org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer
;
import
org.springframework.data.redis.serializer.StringRedisSerializer
;
import
java.time.Duration
;
import
java.time.LocalDateTime
;
@Configuration
@Slf4j
@AutoConfigureAfter
(
RedisAutoConfiguration
.
class
)
public
class
RedisConfig
{
@Bean
public
RedisCacheManager
cacheManager
(
RedisConnectionFactory
redisConnectionFactory
)
{
RedisCacheConfiguration
defaultCacheConfig
=
RedisCacheConfiguration
.
defaultCacheConfig
()
.
entryTtl
(
Duration
.
ofSeconds
(
5
*
60
))
.
disableCachingNullValues
();
return
RedisCacheManager
.
builder
(
RedisCacheWriter
.
lockingRedisCacheWriter
(
redisConnectionFactory
)).
cacheDefaults
(
defaultCacheConfig
).
transactionAware
().
build
();
}
@Bean
(
value
=
"stringRedisTemplate"
)
public
RedisTemplate
stringRedisTemplate
(
RedisConnectionFactory
redisConnectionFactory
)
{
RedisTemplate
<
String
,
String
>
redisTemplate
=
new
RedisTemplate
<>();
redisTemplate
.
setConnectionFactory
(
redisConnectionFactory
);
redisTemplate
.
setKeySerializer
(
new
StringRedisSerializer
());
redisTemplate
.
setValueSerializer
(
new
StringRedisSerializer
());
redisTemplate
.
setHashKeySerializer
(
new
StringRedisSerializer
());
redisTemplate
.
setHashValueSerializer
(
new
StringRedisSerializer
());
return
redisTemplate
;
}
@Bean
(
value
=
"objectRedisTemplate"
)
public
RedisTemplate
objectRedisTemplate
(
RedisConnectionFactory
redisConnectionFactory
)
{
RedisTemplate
<
String
,
Object
>
template
=
new
RedisTemplate
<>();
template
.
setConnectionFactory
(
redisConnectionFactory
);
//使用Jackson2JsonRedisSerializer来序列化和反序列化redis的value值
Jackson2JsonRedisSerializer
serializer
=
new
Jackson2JsonRedisSerializer
(
Object
.
class
);
ObjectMapper
mapper
=
new
ObjectMapper
();
mapper
.
setVisibility
(
PropertyAccessor
.
ALL
,
JsonAutoDetect
.
Visibility
.
ANY
);
mapper
.
enableDefaultTyping
(
ObjectMapper
.
DefaultTyping
.
NON_FINAL
);
SimpleModule
module
=
new
SimpleModule
();
module
.
addDeserializer
(
LocalDateTime
.
class
,
new
LocalDateTimeDeserializer
());
module
.
addSerializer
(
LocalDateTime
.
class
,
new
LocalDateTimeSerializer
());
mapper
.
registerModule
(
module
);
serializer
.
setObjectMapper
(
mapper
);
template
.
setValueSerializer
(
serializer
);
//使用StringRedisSerializer来序列化和反序列化redis的key值
template
.
setKeySerializer
(
new
StringRedisSerializer
());
template
.
setHashKeySerializer
(
new
StringRedisSerializer
());
template
.
setHashValueSerializer
(
serializer
);
template
.
afterPropertiesSet
();
return
template
;
}
@Bean
RedisMessageListenerContainer
container
(
RedisConnectionFactory
connectionFactory
)
{
RedisMessageListenerContainer
container
=
new
RedisMessageListenerContainer
();
container
.
setConnectionFactory
(
connectionFactory
);
//订阅了一个叫chat 的通道
// container.addMessageListener(syncFriendListener(), new PatternTopic(Constants.topic_sync_friend));
// container.addMessageListener(syncRoomListener(),new PatternTopic(Constants.topic_sync_room));
// container.addMessageListener(syncMessageListener(),new PatternTopic(Constants.topic_sync_message));
//这个container 可以添加多个 messageListener
return
container
;
}
// @Bean
// public MessageListener syncMessageListener() {
//
// return new WxMessageListener();
// }
//
// @Bean
// public MessageListener syncRoomListener() {
// return new SyncRoomListener();
// }
//
// @Bean
// public MessageListener syncFriendListener() {
// return new SyncFriendListener();
// }
}
src/main/java/com/qkdata/common/config/RestTemplateConfig.java
0 → 100644
View file @
7bbe84e0
package
com
.
qkdata
.
common
.
config
;
import
org.springframework.beans.factory.config.ConfigurableBeanFactory
;
import
org.springframework.context.annotation.Bean
;
import
org.springframework.context.annotation.Configuration
;
import
org.springframework.context.annotation.Scope
;
import
org.springframework.http.client.ClientHttpRequestFactory
;
import
org.springframework.http.client.SimpleClientHttpRequestFactory
;
import
org.springframework.http.converter.StringHttpMessageConverter
;
import
org.springframework.web.client.RestTemplate
;
import
java.nio.charset.StandardCharsets
;
@Configuration
public
class
RestTemplateConfig
{
@Bean
@Scope
(
scopeName
=
ConfigurableBeanFactory
.
SCOPE_PROTOTYPE
)
public
RestTemplate
restTemplate
(
ClientHttpRequestFactory
factory
)
{
RestTemplate
restTemplate
=
new
RestTemplate
(
factory
);
restTemplate
.
getMessageConverters
().
set
(
1
,
new
StringHttpMessageConverter
(
StandardCharsets
.
UTF_8
));
return
restTemplate
;
}
@Bean
public
ClientHttpRequestFactory
simpleClientHttpRequestFactory
()
{
SimpleClientHttpRequestFactory
factory
=
new
SimpleClientHttpRequestFactory
();
factory
.
setReadTimeout
(
10000
);
//单位为ms
factory
.
setConnectTimeout
(
5000
);
//单位为ms
return
factory
;
}
}
\ No newline at end of file
src/main/java/com/qkdata/common/config/ShiroConfig.java
0 → 100644
View file @
7bbe84e0
package
com
.
qkdata
.
common
.
config
;
import
com.qkdata.common.jwt.JWTProperties
;
import
com.qkdata.common.oauth.OAuthFilter
;
import
com.qkdata.common.oauth.OAuthRealm
;
import
org.apache.shiro.mgt.DefaultSessionStorageEvaluator
;
import
org.apache.shiro.mgt.DefaultSubjectDAO
;
import
org.apache.shiro.mgt.SecurityManager
;
import
org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor
;
import
org.apache.shiro.spring.web.ShiroFilterFactoryBean
;
import
org.apache.shiro.web.mgt.DefaultWebSecurityManager
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.boot.context.properties.EnableConfigurationProperties
;
import
org.springframework.context.annotation.Bean
;
import
org.springframework.context.annotation.Configuration
;
import
javax.servlet.Filter
;
import
java.util.HashMap
;
import
java.util.LinkedHashMap
;
import
java.util.Map
;
@Configuration
@EnableConfigurationProperties
(
JWTProperties
.
class
)
public
class
ShiroConfig
{
@Autowired
private
JWTProperties
jwtProperties
;
@Bean
(
"securityManager"
)
public
SecurityManager
securityManager
(
OAuthRealm
oAuth2Realm
)
{
DefaultWebSecurityManager
securityManager
=
new
DefaultWebSecurityManager
();
securityManager
.
setRememberMeManager
(
null
);
DefaultSubjectDAO
subjectDAO
=
new
DefaultSubjectDAO
();
DefaultSessionStorageEvaluator
defaultSessionStorageEvaluator
=
new
DefaultSessionStorageEvaluator
();
defaultSessionStorageEvaluator
.
setSessionStorageEnabled
(
false
);
subjectDAO
.
setSessionStorageEvaluator
(
defaultSessionStorageEvaluator
);
securityManager
.
setSubjectDAO
(
subjectDAO
);
securityManager
.
setRealm
(
oAuth2Realm
);
return
securityManager
;
}
@Bean
(
"shiroFilter"
)
public
ShiroFilterFactoryBean
shiroFilter
(
SecurityManager
securityManager
)
{
ShiroFilterFactoryBean
shiroFilter
=
new
ShiroFilterFactoryBean
();
shiroFilter
.
setSecurityManager
(
securityManager
);
//oauth过滤
Map
<
String
,
Filter
>
filters
=
new
HashMap
<>();
filters
.
put
(
"oauth"
,
new
OAuthFilter
());
shiroFilter
.
setFilters
(
filters
);
Map
<
String
,
String
>
filterMap
=
new
LinkedHashMap
<>();
for
(
String
url
:
jwtProperties
.
getExcludeUrls
()){
filterMap
.
put
(
url
,
"anon"
);
}
for
(
String
url
:
jwtProperties
.
getIncludeUrls
()){
filterMap
.
put
(
url
,
"oauth"
);
}
shiroFilter
.
setFilterChainDefinitionMap
(
filterMap
);
return
shiroFilter
;
}
// @Bean("lifecycleBeanPostProcessor")
// public LifecycleBeanPostProcessor lifecycleBeanPostProcessor() {
// return new LifecycleBeanPostProcessor();
// }
@Bean
public
AuthorizationAttributeSourceAdvisor
authorizationAttributeSourceAdvisor
(
SecurityManager
securityManager
)
{
AuthorizationAttributeSourceAdvisor
advisor
=
new
AuthorizationAttributeSourceAdvisor
();
advisor
.
setSecurityManager
(
securityManager
);
return
advisor
;
}
}
src/main/java/com/qkdata/common/config/Swagger2Config.java
0 → 100644
View file @
7bbe84e0
package
com
.
qkdata
.
common
.
config
;
import
org.springframework.context.annotation.Bean
;
import
org.springframework.context.annotation.Configuration
;
import
org.springframework.http.HttpHeaders
;
import
springfox.documentation.builders.ApiInfoBuilder
;
import
springfox.documentation.builders.ParameterBuilder
;
import
springfox.documentation.builders.PathSelectors
;
import
springfox.documentation.builders.RequestHandlerSelectors
;
import
springfox.documentation.schema.ModelRef
;
import
springfox.documentation.service.*
;
import
springfox.documentation.spi.DocumentationType
;
import
springfox.documentation.spi.service.contexts.SecurityContext
;
import
springfox.documentation.spring.web.plugins.Docket
;
import
springfox.documentation.swagger2.annotations.EnableSwagger2
;
import
java.util.ArrayList
;
import
java.util.List
;
@Configuration
@EnableSwagger2
public
class
Swagger2Config
{
/**
* @return
*/
@Bean
public
Docket
createRestApi
()
{
// ParameterBuilder ticketPar = new ParameterBuilder();
// List<Parameter> pars = new ArrayList<>();
// ticketPar.name(HttpHeaders.AUTHORIZATION).description("user token")
// .modelRef(new ModelRef("string")).parameterType("header")
// .required(false).build();
// pars.add(ticketPar.build());
return
new
Docket
(
DocumentationType
.
SWAGGER_2
).
apiInfo
(
apiInfo
()).
select
()
.
apis
(
RequestHandlerSelectors
.
basePackage
(
"com.qkdata"
))
.
paths
(
PathSelectors
.
any
()).
build
()
.
securitySchemes
(
securitySchemes
()).
securityContexts
(
securityContexts
());
// .globalOperationParameters(pars);
}
private
List
<
ApiKey
>
securitySchemes
()
{
List
<
ApiKey
>
apiKeys
=
new
ArrayList
<>(
1
);
ApiKey
apiKey
=
new
ApiKey
(
"Authorization"
,
"Authorization"
,
"header"
);
apiKeys
.
add
(
apiKey
);
return
apiKeys
;
}
private
List
<
SecurityContext
>
securityContexts
()
{
List
<
SecurityContext
>
contexts
=
new
ArrayList
<>(
1
);
SecurityContext
securityContext
=
SecurityContext
.
builder
()
.
securityReferences
(
defaultAuth
())
//.forPaths(PathSelectors.regex("^(?!auth).*$"))
.
build
();
contexts
.
add
(
securityContext
);
return
contexts
;
}
private
List
<
SecurityReference
>
defaultAuth
()
{
AuthorizationScope
authorizationScope
=
new
AuthorizationScope
(
"global"
,
"accessEverything"
);
AuthorizationScope
[]
authorizationScopes
=
new
AuthorizationScope
[
1
];
authorizationScopes
[
0
]
=
authorizationScope
;
List
<
SecurityReference
>
references
=
new
ArrayList
<>(
1
);
references
.
add
(
new
SecurityReference
(
"Authorization"
,
authorizationScopes
));
return
references
;
}
/**
* @return
*/
private
ApiInfo
apiInfo
()
{
return
new
ApiInfoBuilder
().
title
(
"backend service API"
).
version
(
"1.0"
).
build
();
}
}
src/main/java/com/qkdata/common/config/WebMvcConfiguration.java
0 → 100644
View file @
7bbe84e0
package
com
.
qkdata
.
common
.
config
;
import
com.qkdata.common.converter.StringToDateConverter
;
import
com.qkdata.common.converter.StringToLocalDateConverter
;
import
com.qkdata.common.converter.StringToLocalDateTimeConverter
;
import
com.qkdata.common.trace.TraceIdInterceptor
;
import
org.springframework.context.annotation.Configuration
;
import
org.springframework.core.convert.converter.Converter
;
import
org.springframework.format.FormatterRegistry
;
import
org.springframework.web.servlet.HandlerInterceptor
;
import
org.springframework.web.servlet.config.annotation.CorsRegistry
;
import
org.springframework.web.servlet.config.annotation.InterceptorRegistry
;
import
org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry
;
import
org.springframework.web.servlet.config.annotation.WebMvcConfigurer
;
@Configuration
public
class
WebMvcConfiguration
implements
WebMvcConfigurer
{
@Override
public
void
addCorsMappings
(
CorsRegistry
registry
)
{
registry
.
addMapping
(
"/**"
)
.
allowedOrigins
(
"*"
)
.
allowedMethods
(
"*"
)
.
allowedOrigins
(
"*"
)
.
allowCredentials
(
true
)
.
maxAge
(
1800
);
}
@Override
public
void
addResourceHandlers
(
ResourceHandlerRegistry
registry
)
{
registry
.
addResourceHandler
(
"swagger-ui.html"
)
.
addResourceLocations
(
"classpath:/META-INF/resources/"
);
registry
.
addResourceHandler
(
"/webjars/**"
)
.
addResourceLocations
(
"classpath:/META-INF/resources/webjars/"
);
}
@Override
public
void
addFormatters
(
FormatterRegistry
registry
)
{
registry
.
addConverter
(
stringToLocalDateConverter
());
registry
.
addConverter
(
stringToLocalDateTimeConverter
());
registry
.
addConverter
(
stringToDateConverter
());
}
private
Converter
stringToDateConverter
()
{
return
new
StringToDateConverter
();
}
@Override
public
void
addInterceptors
(
InterceptorRegistry
registry
)
{
registry
.
addInterceptor
(
traceIdInterceptor
());
}
private
HandlerInterceptor
traceIdInterceptor
()
{
return
new
TraceIdInterceptor
();
}
private
Converter
stringToLocalDateConverter
()
{
return
new
StringToLocalDateConverter
();
}
private
Converter
stringToLocalDateTimeConverter
()
{
return
new
StringToLocalDateTimeConverter
();
}
}
src/main/java/com/qkdata/common/constants/AddGroup.java
0 → 100644
View file @
7bbe84e0
package
com
.
qkdata
.
common
.
constants
;
public
interface
AddGroup
{
}
src/main/java/com/qkdata/common/constants/Constants.java
0 → 100644
View file @
7bbe84e0
package
com
.
qkdata
.
common
.
constants
;
public
final
class
Constants
{
public
static
final
String
PSAAWORD
=
"123456"
;
public
static
final
Long
SYS_ADMIN_ID
=
1L
;
public
static
final
Integer
DEFAULT_PAGE
=
1
;
public
static
final
Integer
DEFAULT_PAGE_SIZE
=
10
;
}
src/main/java/com/qkdata/common/constants/DateTimeFormatterPattern.java
0 → 100644
View file @
7bbe84e0
package
com
.
qkdata
.
common
.
constants
;
public
final
class
DateTimeFormatterPattern
{
private
DateTimeFormatterPattern
()
{
}
public
static
final
String
YYYY_MM_DD
=
"yyyy-MM-dd"
;
public
static
final
String
YYYY_MM_DD_HH_MM_SS
=
"yyyy-MM-dd HH:mm:ss"
;
}
src/main/java/com/qkdata/common/constants/Page.java
0 → 100644
View file @
7bbe84e0
package
com
.
qkdata
.
common
.
constants
;
/**
* 分页常量
*/
public
final
class
Page
{
private
Page
()
{
}
public
static
final
String
CURRENT_PAGE_STR
=
"1"
;
public
static
final
Integer
CURRENT_PAGE_INT
=
1
;
public
static
final
String
PAGE_SIZE_STR
=
"10"
;
public
static
final
Integer
PAGE_SIZE_INT
=
10
;
}
src/main/java/com/qkdata/common/constants/UpdateGroup.java
0 → 100644
View file @
7bbe84e0
package
com
.
qkdata
.
common
.
constants
;
public
interface
UpdateGroup
{
}
src/main/java/com/qkdata/common/constants/ValidatorPattern.java
0 → 100644
View file @
7bbe84e0
package
com
.
qkdata
.
common
.
constants
;
public
final
class
ValidatorPattern
{
private
ValidatorPattern
(){}
public
static
final
String
MOBILE_PATTERN
=
"^(13|14|15|16|17|18|19)[0-9]{9}$"
;
}
src/main/java/com/qkdata/common/converter/DateDeserializer.java
0 → 100644
View file @
7bbe84e0
package
com
.
qkdata
.
common
.
converter
;
import
cn.hutool.core.date.DateUtil
;
import
com.fasterxml.jackson.core.JsonParser
;
import
com.fasterxml.jackson.core.JsonProcessingException
;
import
com.fasterxml.jackson.databind.DeserializationContext
;
import
com.fasterxml.jackson.databind.JsonDeserializer
;
import
com.qkdata.common.base.exception.BusinessException
;
import
lombok.extern.slf4j.Slf4j
;
import
java.io.IOException
;
import
java.util.Date
;
/**
* 用于@RequestBody中Date类型参数序列化与反序列化
*/
@Slf4j
public
class
DateDeserializer
extends
JsonDeserializer
<
Date
>
{
@Override
public
Date
deserialize
(
JsonParser
p
,
DeserializationContext
deserializationContext
)
throws
IOException
,
JsonProcessingException
{
try
{
return
DateUtil
.
parseDateTime
(
p
.
getValueAsString
());
}
catch
(
Exception
e
)
{
log
.
warn
(
"时间转换异常"
,
e
);
throw
new
BusinessException
(
"时间转换异常"
);
}
}
}
src/main/java/com/qkdata/common/converter/DateSerializer.java
0 → 100644
View file @
7bbe84e0
package
com
.
qkdata
.
common
.
converter
;
import
cn.hutool.core.date.DateUtil
;
import
com.fasterxml.jackson.core.JsonGenerator
;
import
com.fasterxml.jackson.databind.JsonSerializer
;
import
com.fasterxml.jackson.databind.SerializerProvider
;
import
java.io.IOException
;
import
java.util.Date
;
/**
* 用于@RequestBody中Date类型参数序列化与反序列化
*/
public
class
DateSerializer
extends
JsonSerializer
<
Date
>
{
@Override
public
void
serialize
(
Date
value
,
JsonGenerator
gen
,
SerializerProvider
serializerProvider
)
throws
IOException
{
if
(
value
==
null
)
{
return
;
}
gen
.
writeString
(
DateUtil
.
formatDateTime
(
value
));
}
}
src/main/java/com/qkdata/common/converter/LocalDateDeserializer.java
0 → 100644
View file @
7bbe84e0
package
com
.
qkdata
.
common
.
converter
;
import
com.fasterxml.jackson.core.JsonParser
;
import
com.fasterxml.jackson.core.JsonProcessingException
;
import
com.fasterxml.jackson.databind.DeserializationContext
;
import
com.fasterxml.jackson.databind.JsonDeserializer
;
import
com.qkdata.common.base.exception.BusinessException
;
import
lombok.extern.slf4j.Slf4j
;
import
java.io.IOException
;
import
java.time.Instant
;
import
java.time.LocalDate
;
import
java.time.ZoneId
;
/**
* 用于@RequestBody中LocalDate类型参数序列化与反序列化
*/
@Slf4j
public
class
LocalDateDeserializer
extends
JsonDeserializer
<
LocalDate
>
{
@Override
public
LocalDate
deserialize
(
JsonParser
p
,
DeserializationContext
ctxt
)
throws
IOException
,
JsonProcessingException
{
try
{
return
Instant
.
ofEpochMilli
(
p
.
getLongValue
()).
atZone
(
ZoneId
.
systemDefault
()).
toLocalDate
();
}
catch
(
Exception
e
)
{
log
.
warn
(
"时间转换异常"
,
e
);
throw
new
BusinessException
(
"时间转换异常"
);
}
}
}
src/main/java/com/qkdata/common/converter/LocalDateSerializer.java
0 → 100644
View file @
7bbe84e0
package
com
.
qkdata
.
common
.
converter
;
import
com.fasterxml.jackson.core.JsonGenerator
;
import
com.fasterxml.jackson.databind.JsonSerializer
;
import
com.fasterxml.jackson.databind.SerializerProvider
;
import
java.io.IOException
;
import
java.time.LocalDate
;
import
java.time.ZoneId
;
/**
* 用于@RequestBody中LocalDate类型参数序列化与反序列化
*/
public
class
LocalDateSerializer
extends
JsonSerializer
<
LocalDate
>
{
@Override
public
void
serialize
(
LocalDate
value
,
JsonGenerator
gen
,
SerializerProvider
serializers
)
throws
IOException
{
if
(
value
==
null
)
{
return
;
}
gen
.
writeNumber
(
value
.
atStartOfDay
(
ZoneId
.
systemDefault
()).
toInstant
().
toEpochMilli
());
}
}
src/main/java/com/qkdata/common/converter/LocalDateTimeDeserializer.java
0 → 100644
View file @
7bbe84e0
package
com
.
qkdata
.
common
.
converter
;
import
com.fasterxml.jackson.core.JsonParser
;
import
com.fasterxml.jackson.core.JsonProcessingException
;
import
com.fasterxml.jackson.databind.DeserializationContext
;
import
com.fasterxml.jackson.databind.JsonDeserializer
;
import
com.qkdata.common.base.exception.BusinessException
;
import
lombok.extern.slf4j.Slf4j
;
import
java.io.IOException
;
import
java.time.Instant
;
import
java.time.LocalDateTime
;
import
java.time.ZoneId
;
/**
* 用于@RequestBody中LocalDateTime参数序列化与反序列化
*/
@Slf4j
public
class
LocalDateTimeDeserializer
extends
JsonDeserializer
<
LocalDateTime
>
{
@Override
public
LocalDateTime
deserialize
(
JsonParser
p
,
DeserializationContext
ctxt
)
throws
IOException
,
JsonProcessingException
{
try
{
return
Instant
.
ofEpochMilli
(
p
.
getLongValue
()).
atZone
(
ZoneId
.
systemDefault
()).
toLocalDateTime
();
}
catch
(
Exception
e
)
{
log
.
warn
(
"时间转换异常"
,
e
);
throw
new
BusinessException
(
"时间转换异常"
);
}
}
}
src/main/java/com/qkdata/common/converter/LocalDateTimeSerializer.java
0 → 100644
View file @
7bbe84e0
package
com
.
qkdata
.
common
.
converter
;
import
com.fasterxml.jackson.core.JsonGenerator
;
import
com.fasterxml.jackson.databind.JsonSerializer
;
import
com.fasterxml.jackson.databind.SerializerProvider
;
import
java.io.IOException
;
import
java.time.LocalDateTime
;
import
java.time.ZoneOffset
;
/**
* 用于@RequestBody中LocalDateTime参数序列化与反序列化
*/
public
class
LocalDateTimeSerializer
extends
JsonSerializer
<
LocalDateTime
>
{
@Override
public
void
serialize
(
LocalDateTime
value
,
JsonGenerator
gen
,
SerializerProvider
serializers
)
throws
IOException
{
if
(
value
==
null
)
{
return
;
}
gen
.
writeNumber
(
value
.
toInstant
(
ZoneOffset
.
ofHours
(
8
)).
toEpochMilli
());
}
}
src/main/java/com/qkdata/common/converter/StringToDateConverter.java
0 → 100644
View file @
7bbe84e0
package
com
.
qkdata
.
common
.
converter
;
import
cn.hutool.core.date.DateUtil
;
import
com.qkdata.common.base.exception.BusinessException
;
import
lombok.extern.slf4j.Slf4j
;
import
org.springframework.core.convert.converter.Converter
;
import
org.springframework.util.StringUtils
;
import
java.util.Date
;
/**
* 用于QUERY参数转换成Date
*/
@Slf4j
public
class
StringToDateConverter
implements
Converter
<
String
,
Date
>
{
@Override
public
Date
convert
(
String
source
)
{
if
(
StringUtils
.
isEmpty
(
source
))
{
return
null
;
}
try
{
return
DateUtil
.
parseDateTime
(
source
);
}
catch
(
Exception
e
)
{
log
.
warn
(
"时间转换异常"
,
e
);
throw
new
BusinessException
(
"时间转换异常"
);
}
}
}
src/main/java/com/qkdata/common/converter/StringToLocalDateConverter.java
0 → 100644
View file @
7bbe84e0
package
com
.
qkdata
.
common
.
converter
;
import
com.qkdata.common.base.exception.BusinessException
;
import
lombok.extern.slf4j.Slf4j
;
import
org.springframework.core.convert.converter.Converter
;
import
org.springframework.util.StringUtils
;
import
java.time.Instant
;
import
java.time.LocalDate
;
import
java.time.ZoneId
;
/**
* 用于QUERY参数转换成LocalDate
*/
@Slf4j
public
class
StringToLocalDateConverter
implements
Converter
<
String
,
LocalDate
>
{
@Override
public
LocalDate
convert
(
String
source
)
{
if
(
StringUtils
.
isEmpty
(
source
))
{
return
null
;
}
try
{
return
Instant
.
ofEpochMilli
(
Long
.
valueOf
(
source
)).
atZone
(
ZoneId
.
systemDefault
()).
toLocalDate
();
}
catch
(
Exception
e
)
{
log
.
warn
(
"时间转换异常"
,
e
);
throw
new
BusinessException
(
"时间转换异常"
);
}
}
}
src/main/java/com/qkdata/common/converter/StringToLocalDateTimeConverter.java
0 → 100644
View file @
7bbe84e0
package
com
.
qkdata
.
common
.
converter
;
import
org.springframework.core.convert.converter.Converter
;
import
org.springframework.util.StringUtils
;
import
java.time.Instant
;
import
java.time.LocalDateTime
;
import
java.time.ZoneId
;
/**
* 用于QUERY参数转换成LocalDateTime
*/
public
class
StringToLocalDateTimeConverter
implements
Converter
<
String
,
LocalDateTime
>
{
@Override
public
LocalDateTime
convert
(
String
source
)
{
if
(
StringUtils
.
isEmpty
(
source
))
{
return
null
;
}
return
Instant
.
ofEpochMilli
(
Long
.
valueOf
(
source
)).
atZone
(
ZoneId
.
systemDefault
()).
toLocalDateTime
();
}
}
src/main/java/com/qkdata/common/jwt/JWTProperties.java
0 → 100644
View file @
7bbe84e0
package
com
.
qkdata
.
common
.
jwt
;
import
lombok.Data
;
import
org.springframework.boot.context.properties.ConfigurationProperties
;
import
java.util.Set
;
@Data
@ConfigurationProperties
(
prefix
=
"jwt"
)
public
class
JWTProperties
{
private
String
typ
=
"JWT"
;
private
String
alg
=
"HS256"
;
private
String
secret
;
private
String
iss
=
"qkdata"
;
private
String
aud
;
private
Integer
exp
=
2
;
/**
* 是否启用拦截器
*/
private
Boolean
enableInterceptor
=
Boolean
.
FALSE
;
/**
* 需要拦截的URL
*/
private
Set
<
String
>
includeUrls
;
/**
* 需要排除的URL
*/
private
Set
<
String
>
excludeUrls
;
}
src/main/java/com/qkdata/common/jwt/JWTService.java
0 → 100644
View file @
7bbe84e0
package
com
.
qkdata
.
common
.
jwt
;
import
com.auth0.jwt.JWT
;
import
com.auth0.jwt.JWTCreator
;
import
com.auth0.jwt.JWTVerifier
;
import
com.auth0.jwt.algorithms.Algorithm
;
import
com.auth0.jwt.interfaces.DecodedJWT
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.boot.context.properties.EnableConfigurationProperties
;
import
org.springframework.stereotype.Component
;
import
java.time.LocalDateTime
;
import
java.time.ZoneId
;
import
java.util.Date
;
import
java.util.HashMap
;
import
java.util.Map
;
@Component
@EnableConfigurationProperties
(
JWTProperties
.
class
)
public
class
JWTService
{
@Autowired
private
JWTProperties
jwtProperties
;
/**
* 头部信息
*
* @return
*/
private
void
buildHeader
(
JWTCreator
.
Builder
builder
)
{
Map
<
String
,
Object
>
header
=
new
HashMap
<>();
header
.
put
(
"typ"
,
jwtProperties
.
getTyp
());
header
.
put
(
"alg"
,
jwtProperties
.
getAlg
());
builder
.
withHeader
(
header
);
}
/**
* 载荷信息
*/
private
void
buildPayload
(
JWTCreator
.
Builder
builder
,
Map
<
String
,
Object
>
claims
)
{
LocalDateTime
now
=
LocalDateTime
.
now
();
builder
.
withIssuer
(
jwtProperties
.
getIss
())
.
withAudience
(
jwtProperties
.
getAud
())
.
withIssuedAt
(
issuedAt
((
now
)))
.
withExpiresAt
(
expiresAt
(
now
,
jwtProperties
.
getExp
()));
if
(
claims
!=
null
)
{
for
(
Map
.
Entry
<
String
,
Object
>
entry
:
claims
.
entrySet
())
{
Object
value
=
entry
.
getValue
();
if
(
value
instanceof
Boolean
)
{
builder
.
withClaim
(
entry
.
getKey
(),
(
Boolean
)
value
);
}
else
if
(
value
instanceof
Integer
)
{
builder
.
withClaim
(
entry
.
getKey
(),
(
Integer
)
value
);
}
else
if
(
value
instanceof
Long
)
{
builder
.
withClaim
(
entry
.
getKey
(),
(
Long
)
value
);
}
else
if
(
value
instanceof
String
)
{
builder
.
withClaim
(
entry
.
getKey
(),
(
String
)
value
);
}
else
if
(
value
instanceof
Double
)
{
builder
.
withClaim
(
entry
.
getKey
(),
(
Double
)
value
);
}
else
if
(
value
instanceof
Date
)
{
builder
.
withClaim
(
entry
.
getKey
(),
(
Date
)
value
);
}
else
{
throw
new
IllegalStateException
(
"jwt payload claims type mismatch"
);
}
}
}
}
/**
* 签名
*
* @param builder
* @return jwt字符串
*/
private
String
buildSignature
(
JWTCreator
.
Builder
builder
)
{
return
builder
.
sign
(
Algorithm
.
HMAC256
(
jwtProperties
.
getSecret
()));
}
/**
* 创建JWT
*
* @param claims 业务参数
* @return
*/
public
String
createJWT
(
Map
<
String
,
Object
>
claims
)
{
JWTCreator
.
Builder
builder
=
JWT
.
create
();
buildHeader
(
builder
);
buildPayload
(
builder
,
claims
);
return
buildSignature
(
builder
);
}
public
String
createJWT
()
{
return
createJWT
(
null
);
}
/**
* 签发时间
*
* @param issuedAt
* @return
*/
private
Date
issuedAt
(
LocalDateTime
issuedAt
)
{
return
Date
.
from
(
issuedAt
.
atZone
(
ZoneId
.
systemDefault
()).
toInstant
());
}
/**
* 过期时间
*
* @param issuedAt
* @param hours
* @return
*/
private
Date
expiresAt
(
LocalDateTime
issuedAt
,
Integer
hours
)
{
return
Date
.
from
(
issuedAt
.
plusHours
(
hours
).
atZone
(
ZoneId
.
systemDefault
()).
toInstant
());
}
/**
* 解码
*
* @param jwt
*/
public
DecodedJWT
decode
(
String
jwt
)
{
JWTVerifier
verifier
=
JWT
.
require
(
Algorithm
.
HMAC256
(
jwtProperties
.
getSecret
())).
build
();
return
verifier
.
verify
(
jwt
);
}
}
src/main/java/com/qkdata/common/oauth/AuthorizationResponseEnum.java
0 → 100644
View file @
7bbe84e0
package
com
.
qkdata
.
common
.
oauth
;
public
enum
AuthorizationResponseEnum
{
MISSING_TOKEN
(
"403"
,
"HEADER中不存在TOKEN"
),
INVALID_TOKEN
(
"403"
,
"校验TOKEN失败"
),
EXPIRED_TOKEN
(
"403"
,
"TOKEN已过期"
),
MISSING_CLAIMS
(
"403"
,
"不合法的TOKEN, 信息可能被篡改"
),
INVALID_CLAIM
(
"403"
,
"不合法的TOKEN, 系统中不存在资源"
);
private
String
value
;
private
String
text
;
AuthorizationResponseEnum
(
String
value
,
String
text
)
{
this
.
value
=
value
;
this
.
text
=
text
;
}
public
String
value
()
{
return
this
.
value
;
}
public
String
text
()
{
return
this
.
text
;
}
}
src/main/java/com/qkdata/common/oauth/AuthorizedUser.java
0 → 100644
View file @
7bbe84e0
package
com
.
qkdata
.
common
.
oauth
;
import
lombok.Data
;
@Data
public
class
AuthorizedUser
{
private
Long
userId
;
private
String
username
;
}
src/main/java/com/qkdata/common/oauth/OAuthFilter.java
0 → 100644
View file @
7bbe84e0
package
com
.
qkdata
.
common
.
oauth
;
import
com.fasterxml.jackson.databind.ObjectMapper
;
import
com.qkdata.common.base.model.Result
;
import
com.qkdata.common.util.HttpContextUtils
;
import
org.apache.shiro.authc.AuthenticationException
;
import
org.apache.shiro.authc.AuthenticationToken
;
import
org.apache.shiro.web.filter.authc.AuthenticatingFilter
;
import
org.springframework.http.HttpHeaders
;
import
org.springframework.util.StringUtils
;
import
org.springframework.web.bind.annotation.RequestMethod
;
import
javax.servlet.ServletRequest
;
import
javax.servlet.ServletResponse
;
import
javax.servlet.http.HttpServletRequest
;
import
javax.servlet.http.HttpServletResponse
;
import
java.io.IOException
;
public
class
OAuthFilter
extends
AuthenticatingFilter
{
private
ObjectMapper
mapper
=
new
ObjectMapper
();
@Override
protected
AuthenticationToken
createToken
(
ServletRequest
request
,
ServletResponse
response
)
throws
Exception
{
//获取请求token
String
token
=
getRequestToken
((
HttpServletRequest
)
request
);
if
(
StringUtils
.
isEmpty
(
token
)){
return
null
;
}
return
new
OAuthToken
(
token
);
}
@Override
protected
boolean
isAccessAllowed
(
ServletRequest
request
,
ServletResponse
response
,
Object
mappedValue
)
{
if
(((
HttpServletRequest
)
request
).
getMethod
().
equals
(
RequestMethod
.
OPTIONS
.
name
())){
return
true
;
}
return
false
;
}
@Override
protected
boolean
onAccessDenied
(
ServletRequest
request
,
ServletResponse
response
)
throws
Exception
{
//获取请求token,如果token不存在,直接返回403
String
token
=
getRequestToken
((
HttpServletRequest
)
request
);
if
(
StringUtils
.
isEmpty
(
token
)){
HttpServletResponse
httpResponse
=
(
HttpServletResponse
)
response
;
httpResponse
.
setContentType
(
"application/json;charset=utf-8"
);
httpResponse
.
setHeader
(
"Access-Control-Allow-Credentials"
,
"true"
);
httpResponse
.
setHeader
(
"Access-Control-Allow-Origin"
,
HttpContextUtils
.
getOrigin
());
Result
responseData
=
Result
.
failed
(
AuthorizationResponseEnum
.
MISSING_TOKEN
.
text
());
String
json
=
mapper
.
writeValueAsString
(
responseData
);
httpResponse
.
getWriter
().
print
(
json
);
return
false
;
}
return
executeLogin
(
request
,
response
);
}
@Override
protected
boolean
onLoginFailure
(
AuthenticationToken
token
,
AuthenticationException
e
,
ServletRequest
request
,
ServletResponse
response
)
{
HttpServletResponse
httpResponse
=
(
HttpServletResponse
)
response
;
httpResponse
.
setContentType
(
"application/json;charset=utf-8"
);
httpResponse
.
setHeader
(
"Access-Control-Allow-Credentials"
,
"true"
);
httpResponse
.
setHeader
(
"Access-Control-Allow-Origin"
,
HttpContextUtils
.
getOrigin
());
try
{
//处理登录失败的异常
Throwable
throwable
=
e
.
getCause
()
==
null
?
e
:
e
.
getCause
();
Result
rd
=
Result
.
failed
(
AuthorizationResponseEnum
.
INVALID_TOKEN
.
value
(),
e
.
getMessage
());
String
json
=
mapper
.
writeValueAsString
(
rd
);
httpResponse
.
getWriter
().
print
(
json
);
}
catch
(
IOException
e1
)
{
}
return
false
;
}
/**
* 获取请求的token
*/
private
String
getRequestToken
(
HttpServletRequest
httpRequest
){
//从header中获取token
String
token
=
httpRequest
.
getHeader
(
HttpHeaders
.
AUTHORIZATION
);
//如果header中不存在token,则从参数中获取token
if
(
StringUtils
.
isEmpty
(
token
)){
token
=
httpRequest
.
getParameter
(
HttpHeaders
.
AUTHORIZATION
);
}
return
token
;
}
}
src/main/java/com/qkdata/common/oauth/OAuthRealm.java
0 → 100644
View file @
7bbe84e0
package
com
.
qkdata
.
common
.
oauth
;
import
com.auth0.jwt.exceptions.*
;
import
com.auth0.jwt.interfaces.DecodedJWT
;
import
com.fasterxml.jackson.databind.ObjectMapper
;
import
com.qkdata.biz.sys.entity.SysUserPO
;
import
com.qkdata.biz.enums.AccountStatusEnum
;
import
com.qkdata.biz.sys.service.ShiroService
;
import
com.qkdata.common.jwt.JWTService
;
import
lombok.extern.slf4j.Slf4j
;
import
org.apache.shiro.authc.AuthenticationException
;
import
org.apache.shiro.authc.AuthenticationInfo
;
import
org.apache.shiro.authc.AuthenticationToken
;
import
org.apache.shiro.authc.SimpleAuthenticationInfo
;
import
org.apache.shiro.authz.AuthorizationInfo
;
import
org.apache.shiro.authz.SimpleAuthorizationInfo
;
import
org.apache.shiro.realm.AuthorizingRealm
;
import
org.apache.shiro.subject.PrincipalCollection
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.stereotype.Component
;
import
java.io.IOException
;
import
java.util.HashSet
;
import
java.util.Set
;
@Slf4j
@Component
public
class
OAuthRealm
extends
AuthorizingRealm
{
@Autowired
private
ShiroService
shiroService
;
@Autowired
private
JWTService
jwtService
;
private
ObjectMapper
mapper
=
new
ObjectMapper
();
private
DecodedJWT
decodedJWT
;
@Override
public
boolean
supports
(
AuthenticationToken
token
)
{
return
token
instanceof
OAuthToken
;
}
/**
* 授权(验证权限时调用)
*/
@Override
protected
AuthorizationInfo
doGetAuthorizationInfo
(
PrincipalCollection
principals
)
{
SysUserPO
user
=
(
SysUserPO
)
principals
.
getPrimaryPrincipal
();
Long
userId
=
user
.
getId
();
//用户权限列表
Set
<
String
>
permsSet
=
new
HashSet
<>();
permsSet
.
add
(
"all"
);
SimpleAuthorizationInfo
info
=
new
SimpleAuthorizationInfo
();
info
.
setStringPermissions
(
permsSet
);
return
info
;
}
/**
* 认证
*/
@Override
protected
AuthenticationInfo
doGetAuthenticationInfo
(
AuthenticationToken
token
)
throws
AuthenticationException
{
String
accessToken
=
(
String
)
token
.
getPrincipal
();
if
(
accessToken
==
null
)
{
throw
new
AuthenticationException
(
AuthorizationResponseEnum
.
MISSING_TOKEN
.
text
());
}
try
{
decodedJWT
=
jwtService
.
decode
(
accessToken
);
String
userJson
=
decodedJWT
.
getClaim
(
"user"
).
asString
();
AuthorizedUser
authUser
=
mapper
.
readValue
(
userJson
,
AuthorizedUser
.
class
);
SysUserPO
user
=
shiroService
.
getUserByUserName
(
authUser
.
getUsername
());
if
(
user
==
null
){
throw
new
AuthenticationException
(
AuthorizationResponseEnum
.
INVALID_CLAIM
.
text
());
}
if
(
user
.
getStatus
()
==
AccountStatusEnum
.
DISABLE
){
throw
new
AuthenticationException
(
"您已退出团队,不能登陆"
);
}
SimpleAuthenticationInfo
info
=
new
SimpleAuthenticationInfo
(
user
,
accessToken
,
getName
());
return
info
;
}
catch
(
JWTDecodeException
|
AlgorithmMismatchException
|
SignatureVerificationException
|
InvalidClaimException
e
)
{
log
.
warn
(
"校验TOKEN失败: {}, token: {}"
,
e
.
getMessage
(),
token
);
throw
new
AuthenticationException
(
AuthorizationResponseEnum
.
INVALID_TOKEN
.
text
());
}
catch
(
TokenExpiredException
e
)
{
log
.
warn
(
"TOKEN已过期: {}, token: {}"
,
e
.
getMessage
(),
token
);
throw
new
AuthenticationException
(
AuthorizationResponseEnum
.
EXPIRED_TOKEN
.
text
());
}
catch
(
IOException
e
)
{
throw
new
AuthenticationException
(
AuthorizationResponseEnum
.
INVALID_CLAIM
.
text
());
}
}
}
src/main/java/com/qkdata/common/oauth/OAuthToken.java
0 → 100644
View file @
7bbe84e0
package
com
.
qkdata
.
common
.
oauth
;
import
org.apache.shiro.authc.AuthenticationToken
;
public
class
OAuthToken
implements
AuthenticationToken
{
private
String
token
;
public
OAuthToken
(
String
token
){
this
.
token
=
token
;
}
@Override
public
String
getPrincipal
()
{
return
token
;
}
@Override
public
Object
getCredentials
()
{
return
token
;
}
}
src/main/java/com/qkdata/common/trace/HttpTraceLogFilter.java
0 → 100644
View file @
7bbe84e0
package
com
.
qkdata
.
common
.
trace
;
import
com.fasterxml.jackson.databind.ObjectMapper
;
import
lombok.extern.slf4j.Slf4j
;
import
org.apache.commons.io.IOUtils
;
import
org.slf4j.MDC
;
import
org.springframework.core.Ordered
;
import
org.springframework.http.HttpStatus
;
import
org.springframework.web.filter.OncePerRequestFilter
;
import
org.springframework.web.util.ContentCachingRequestWrapper
;
import
org.springframework.web.util.ContentCachingResponseWrapper
;
import
org.springframework.web.util.WebUtils
;
import
javax.servlet.FilterChain
;
import
javax.servlet.ServletException
;
import
javax.servlet.http.HttpServletRequest
;
import
javax.servlet.http.HttpServletResponse
;
import
java.io.IOException
;
import
java.net.URI
;
import
java.net.URISyntaxException
;
import
java.time.Instant
;
import
java.time.LocalDateTime
;
import
java.util.Enumeration
;
import
java.util.HashMap
;
import
java.util.Map
;
import
java.util.Objects
;
/**
* 记录请求参数、请求路径、响应数据、请求时间等信息
*
* @see org.springframework.boot.actuate.web.trace.servlet.HttpTraceFilter
*/
@Slf4j
public
class
HttpTraceLogFilter
extends
OncePerRequestFilter
implements
Ordered
{
private
int
order
=
Ordered
.
LOWEST_PRECEDENCE
-
10
;
private
ObjectMapper
objectMapper
;
public
HttpTraceLogFilter
(
ObjectMapper
objectMapper
)
{
this
.
objectMapper
=
objectMapper
;
}
@Override
public
int
getOrder
()
{
return
this
.
order
;
}
@Override
protected
void
doFilterInternal
(
HttpServletRequest
request
,
HttpServletResponse
response
,
FilterChain
filterChain
)
throws
ServletException
,
IOException
{
if
(!
isRequestValid
(
request
))
{
filterChain
.
doFilter
(
request
,
response
);
return
;
}
// request的stream只能被消费一次
if
(!(
request
instanceof
ContentCachingRequestWrapper
))
{
request
=
new
ContentCachingRequestWrapper
(
request
);
}
if
(!(
response
instanceof
ContentCachingResponseWrapper
))
{
response
=
new
ContentCachingResponseWrapper
(
response
);
}
int
status
=
HttpStatus
.
OK
.
value
();
long
startTime
=
Instant
.
now
().
toEpochMilli
();
try
{
filterChain
.
doFilter
(
request
,
response
);
status
=
response
.
getStatus
();
}
finally
{
long
timeTaken
=
Instant
.
now
().
toEpochMilli
()
-
startTime
;
TraceLog
traceLog
=
new
TraceLog
();
traceLog
.
setTraceId
(
MDC
.
get
(
TraceIdInterceptor
.
TRACE_ID_KEY
));
traceLog
.
setTimeTaken
(
timeTaken
);
traceLog
.
setCreateAt
(
LocalDateTime
.
now
());
traceLog
.
setMethod
(
request
.
getMethod
());
traceLog
.
setPath
(
request
.
getRequestURI
());
traceLog
.
setStatus
(
status
);
traceLog
.
setRequestBody
(
getRequestBody
(
request
));
traceLog
.
setResponseBody
(
getResponseBody
(
response
));
traceLog
.
setParameters
(
objectMapper
.
writeValueAsString
(
request
.
getParameterMap
()));
traceLog
.
setHeaders
(
objectMapper
.
writeValueAsString
(
getHeaders
(
request
)));
// log.info("Http Trace Log: {}", objectMapper.writeValueAsString(traceLog));
// 复原response,正常的返回数据
updateResponse
(
response
);
MDC
.
remove
(
TraceIdInterceptor
.
TRACE_ID_KEY
);
}
}
private
Map
<
String
,
Object
>
getHeaders
(
HttpServletRequest
request
)
{
Enumeration
<
String
>
headerNames
=
request
.
getHeaderNames
();
Map
<
String
,
Object
>
heads
=
new
HashMap
<>();
while
(
headerNames
.
hasMoreElements
())
{
String
name
=
headerNames
.
nextElement
();
String
value
=
request
.
getHeader
(
name
);
heads
.
put
(
name
,
value
);
}
return
heads
;
}
private
boolean
isRequestValid
(
HttpServletRequest
request
)
{
try
{
new
URI
(
request
.
getRequestURL
().
toString
());
return
true
;
}
catch
(
URISyntaxException
ex
)
{
return
false
;
}
}
private
String
getRequestBody
(
HttpServletRequest
request
)
{
String
requestBody
=
""
;
ContentCachingRequestWrapper
wrapper
=
WebUtils
.
getNativeRequest
(
request
,
ContentCachingRequestWrapper
.
class
);
if
(
wrapper
!=
null
)
{
try
{
requestBody
=
IOUtils
.
toString
(
wrapper
.
getContentAsByteArray
(),
wrapper
.
getCharacterEncoding
());
}
catch
(
IOException
e
)
{
// NOOP
}
}
return
requestBody
;
}
private
String
getResponseBody
(
HttpServletResponse
response
)
{
String
responseBody
=
""
;
ContentCachingResponseWrapper
wrapper
=
WebUtils
.
getNativeResponse
(
response
,
ContentCachingResponseWrapper
.
class
);
if
(
wrapper
!=
null
)
{
try
{
responseBody
=
IOUtils
.
toString
(
wrapper
.
getContentAsByteArray
(),
wrapper
.
getCharacterEncoding
());
}
catch
(
IOException
e
)
{
// NOOP
}
}
return
responseBody
;
}
private
void
updateResponse
(
HttpServletResponse
response
)
throws
IOException
{
ContentCachingResponseWrapper
responseWrapper
=
WebUtils
.
getNativeResponse
(
response
,
ContentCachingResponseWrapper
.
class
);
Objects
.
requireNonNull
(
responseWrapper
).
copyBodyToResponse
();
}
}
src/main/java/com/qkdata/common/trace/MdcThreadPoolTaskExecutor.java
0 → 100644
View file @
7bbe84e0
package
com
.
qkdata
.
common
.
trace
;
import
org.slf4j.MDC
;
import
org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor
;
import
java.util.Map
;
/**
* 这是{@link ThreadPoolTaskExecutor}的一个简单替换,可以在每个任务之前设置子线程的MDC数据。
* <p/>
* 在记录日志的时候,一般情况下我们会使用MDC来存储每个线程的特有参数,如身份信息等,以便更好的查询日志。
* 但是Logback在最新的版本中因为性能问题,不会自动的将MDC的内存传给子线程。所以Logback建议在执行异步线程前
* 先通过MDC.getCopyOfContextMap()方法将MDC内存获取出来,再传给线程。
* 并在子线程的执行的最开始调用MDC.setContextMap(context)方法将父线程的MDC内容传给子线程。
**/
public
class
MdcThreadPoolTaskExecutor
extends
ThreadPoolTaskExecutor
{
/**
* 所有线程都会委托给这个execute方法,在这个方法中我们把父线程的MDC内容赋值给子线程
* https://logback.qos.ch/manual/mdc.html#managedThreads
*
* @param runnable
*/
@Override
public
void
execute
(
Runnable
runnable
)
{
// 获取父线程MDC中的内容,必须在run方法之前,否则等异步线程执行的时候有可能MDC里面的值已经被清空了,这个时候就会返回null
Map
<
String
,
String
>
context
=
MDC
.
getCopyOfContextMap
();
super
.
execute
(()
->
run
(
runnable
,
context
));
}
/**
* 子线程委托的执行方法
*
* @param runnable {@link Runnable}
* @param context 父线程MDC内容
*/
private
void
run
(
Runnable
runnable
,
Map
<
String
,
String
>
context
)
{
// 将父线程的MDC内容传给子线程
MDC
.
setContextMap
(
context
);
try
{
// 执行异步操作
runnable
.
run
();
}
finally
{
// 清空MDC内容
MDC
.
clear
();
}
}
}
src/main/java/com/qkdata/common/trace/TraceIdInterceptor.java
0 → 100644
View file @
7bbe84e0
package
com
.
qkdata
.
common
.
trace
;
import
lombok.extern.slf4j.Slf4j
;
import
org.slf4j.MDC
;
import
org.springframework.web.servlet.HandlerInterceptor
;
import
javax.servlet.http.HttpServletRequest
;
import
javax.servlet.http.HttpServletResponse
;
import
java.util.UUID
;
@Slf4j
public
class
TraceIdInterceptor
implements
HandlerInterceptor
{
public
static
final
String
TRACE_ID_KEY
=
"traceId"
;
@Override
public
boolean
preHandle
(
HttpServletRequest
request
,
HttpServletResponse
response
,
Object
handler
)
throws
Exception
{
String
traceId
=
UUID
.
randomUUID
().
toString
().
replaceAll
(
"-"
,
""
);
MDC
.
put
(
TRACE_ID_KEY
,
traceId
);
return
true
;
}
}
src/main/java/com/qkdata/common/trace/TraceLog.java
0 → 100644
View file @
7bbe84e0
package
com
.
qkdata
.
common
.
trace
;
import
lombok.Data
;
import
java.io.Serializable
;
import
java.time.LocalDateTime
;
@Data
public
class
TraceLog
implements
Serializable
{
/**
* traceId
*/
private
String
traceId
;
/**
* 请求路径
*/
private
String
path
;
/**
* 请求方法
*/
private
String
method
;
/**
* 请求头信息
*/
private
String
headers
;
/**
* query请求参数
*/
private
String
parameters
;
/**
* 接口花费时间
*/
private
Long
timeTaken
;
/**
* 日志创建时间
*/
private
LocalDateTime
createAt
;
/**
* Response Status
*/
private
Integer
status
;
/**
* 请求Body
*/
private
String
requestBody
;
/**
* 响应Body
*/
private
String
responseBody
;
}
src/main/java/com/qkdata/common/tree/IContentProvider.java
0 → 100644
View file @
7bbe84e0
package
com
.
qkdata
.
common
.
tree
;
import
java.util.List
;
/**
* @author liu_yang
* 构造树结构时内容提供者接口
*
*/
public
interface
IContentProvider
{
/**
* 获取当前元素下的子元素.
*
* @param curElement 当前元素对象
* @param level 当前元素级别
* @param index 当前元素所在层级索引
* @return 子元素对象集合
* @throws ServiceException 抛出异常
*/
List
<?
extends
Object
>
getChildren
(
Object
curElement
,
final
int
level
,
final
int
index
);
/**
* 获取根元素.
*
* @param treeData 树结构所需数据
* @param level 当前级别
* @param index 当前索引
* @return 根元素对象集合
*/
List
<?
extends
Object
>
getRootElement
(
List
<?
extends
Object
>
treeData
,
final
int
level
,
final
int
index
);
/**
* 异步时需实现此方法,用于判断当前元素是否有子元素.
*
* @param curElement 当前元素对象
* @param level 当前元素级别
* @param index 当前元素所在层级索引
* @return true/false
*/
boolean
hasChild
(
Object
curElement
,
final
int
level
,
final
int
index
);
}
src/main/java/com/qkdata/common/tree/ILabelProvider.java
0 → 100644
View file @
7bbe84e0
package
com
.
qkdata
.
common
.
tree
;
import
java.util.Map
;
/**
* @author liu_yang
* 构造树结构时节点显示内容提供者接口
*
*/
public
interface
ILabelProvider
{
/**
* 获得当前元素类型Normal,Checkbox,Radio.
*
* @param curElement 当前元素对象
* @param level 级别
* @param index 索引
* @return TreeTypeEnum枚举
*/
TreeTypeEnum
getLabelType
(
final
Object
curElement
,
final
int
level
,
final
int
index
);
/**
* 获取当前元素显示名称.
*
* @param curElement 当前元素对象
* @param level 级别
* @param index 索引
* @return 节点名称
*/
String
getLabelName
(
final
Object
curElement
,
final
int
level
,
final
int
index
);
/**
* 获得当前元素的ID.
*
* @param curElement 当前元素
* @param level 级别
* @param index 索引
* @return 节点ID
*/
String
getLabelId
(
final
Object
curElement
,
final
int
level
,
final
int
index
);
/**
* 获取当前元素显示图标.如果不显示图标,返回null
*
* @param curElement 当前元素
* @param level 级别
* @param index 索引
* @return 节 点图标名称
*/
String
getIcon
(
final
Object
curElement
,
final
int
level
,
final
int
index
);
/**
* 获取当前元素是否显示默认图标.
*
* @param curElement 当前元素
* @param level 级别
* @param index 索引
* @return true/false
*/
boolean
isDefaultIcon
(
final
Object
curElement
,
final
int
level
,
final
int
index
);
/**
* 获取当前元素是否可以点击操作
*
* @param curElement 当前元素
* @param level 级别
* @param index 索引
* @return true/false
*/
boolean
isClick
(
final
Object
curElement
,
int
level
,
int
index
);
/**
* 如是单选或多选情况下会调用该方法,判断当前节点是否被选中.
*
* @param curElement 当前元素
* @param level 级别
* @param index 索引
* @return true/false
*/
boolean
isCheck
(
final
Object
curElement
,
int
level
,
int
index
);
/**
* 如是单选或多选情况下会调用该方法,获取节点选中时设置的值.
*
* @param curElement 当前元素
* @param level 级别
* @param index 索引
* @return 节点值
*/
String
getCheckId
(
final
Object
curElement
,
int
level
,
int
index
);
/**
* 获得当前元素的自定义属性.
*
* @param curElement 当前元素
* @param level 级别
* @param index 索引
* @return 自定义属性MAP
*/
Map
<
String
,
String
>
getAttributes
(
final
Object
curElement
,
int
level
,
int
index
);
}
src/main/java/com/qkdata/common/tree/Tree.java
0 → 100644
View file @
7bbe84e0
package
com
.
qkdata
.
common
.
tree
;
import
java.util.ArrayList
;
import
java.util.List
;
/**
* @author liu_yang
* 树对象
*
*/
public
class
Tree
{
/**
* <code>childs</code> - 树子节点.
*/
private
List
<
TreeNode
>
m_roots
=
new
ArrayList
<
TreeNode
>();
/**
* 树ID
*/
private
String
m_id
=
""
;
/**
* Constructors.
*
* @param id 树ID
*/
public
Tree
(
final
String
id
)
{
this
.
m_id
=
id
;
}
/**
* Constructors.
*
* @param id 树ID
* @param roots 子节点TreeNode
*/
public
Tree
(
final
String
id
,
final
List
<
TreeNode
>
roots
)
{
this
.
m_roots
=
roots
;
this
.
m_id
=
id
;
}
/**
* 添加子节点
*
* @param treeNode TreeNode节点对象
*/
public
void
addChild
(
final
TreeNode
treeNode
)
{
this
.
m_roots
.
add
(
treeNode
);
}
/**
* 获取List<TreeNode>树
*
* @return List<TreeNode>
*/
public
List
<
TreeNode
>
getRoots
()
{
return
this
.
m_roots
;
}
/**
* @return id - {return content description}
*/
public
String
getId
()
{
return
m_id
;
}
/**
* @param id - {parameter description}.
*/
public
void
setId
(
final
String
id
)
{
m_id
=
id
;
}
}
src/main/java/com/qkdata/common/tree/TreeNode.java
0 → 100644
View file @
7bbe84e0
package
com
.
qkdata
.
common
.
tree
;
import
java.util.ArrayList
;
import
java.util.List
;
import
java.util.Map
;
/**
* @author liu_yang
* 树节点类
*
*/
public
class
TreeNode
{
/**
* <code>id</code> - 节点ID.
*/
private
String
m_id
;
/**
* <code>m_lable</code> - 节点名称.
*/
private
String
m_name
;
/**
* <code>m_icon</code> - 图片.
*/
private
String
m_icon
;
/**
* <code>m_children</code> - 子节点.
*/
private
List
<
TreeNode
>
m_children
;
/**
* <code>m_isExpand</code> - 是否可展开.
*/
private
boolean
m_isExpand
;
/**
* <code>m_isClick</code> - 节点是否可点击.
*/
private
boolean
m_isClick
;
/**
* 节点是否被选中
*/
private
boolean
m_isCheck
;
/**
* <code>m_type</code> - 节点类型.
*/
private
String
m_type
;
/**
* <code>extProperty</code> - {description}.
*/
private
Map
<
String
,
String
>
m_extProperty
;
/**
* 构造方法.
*
* @param id 节点ID.
* @param values 节点属性集合.
*/
public
TreeNode
(
final
String
id
,
final
Map
<
String
,
String
>
values
)
{
this
.
m_id
=
id
;
this
.
m_extProperty
=
values
;
}
/**
* @return id - {return content description}
*/
public
String
getId
()
{
return
m_id
;
}
/**
* @param id - {parameter description}.
*/
public
void
setId
(
final
String
id
)
{
m_id
=
id
;
}
/**
* @return name - {return content description}
*/
public
String
getName
()
{
return
m_name
;
}
/**
* @param name - {parameter description}.
*/
public
void
setName
(
final
String
name
)
{
m_name
=
name
;
}
/**
* @return icon - {return content description}
*/
public
String
getIcon
()
{
return
m_icon
;
}
/**
* @param icon - {parameter description}.
*/
public
void
setIcon
(
final
String
icon
)
{
m_icon
=
icon
;
}
/**
* @return children - {return content description}
*/
public
List
<
TreeNode
>
getChildren
()
{
return
m_children
;
}
/**
* @param children - {parameter description}.
*/
public
void
setChilds
(
final
List
<
TreeNode
>
children
)
{
m_children
=
children
;
}
public
boolean
getIsCheck
()
{
return
m_isCheck
;
}
public
void
setIsCheck
(
boolean
isCheck
)
{
this
.
m_isCheck
=
isCheck
;
}
/**
* @return isExpand - {return content description}
*/
public
boolean
getIsExpand
()
{
return
m_isExpand
;
}
/**
* @param isExpand - {parameter description}.
*/
public
void
setIsExpand
(
final
boolean
isExpand
)
{
m_isExpand
=
isExpand
;
}
/**
* @return isClick - {return content description}
*/
public
boolean
getIsClick
()
{
return
m_isClick
;
}
/**
* @param isClick - {parameter description}.
*/
public
void
setIsClick
(
final
boolean
isClick
)
{
m_isClick
=
isClick
;
}
/**
* @return type - {return content description}
*/
public
String
getType
()
{
return
m_type
;
}
/**
* @param type - {parameter description}.
*/
public
void
setType
(
final
String
type
)
{
m_type
=
type
;
}
/**
* @return extProperty - {return content description}
*/
public
Map
<
String
,
String
>
getExtProperty
()
{
return
m_extProperty
;
}
/**
* @param extProperty - {parameter description}.
*/
public
void
setExtProperty
(
final
Map
<
String
,
String
>
extProperty
)
{
m_extProperty
=
extProperty
;
}
/**
* addChild.
*
* @param node node
*/
public
void
addChild
(
final
TreeNode
node
)
{
if
(
this
.
m_children
==
null
)
{
this
.
m_children
=
new
ArrayList
<
TreeNode
>();
}
m_children
.
add
(
node
);
}
}
src/main/java/com/qkdata/common/tree/TreeTypeEnum.java
0 → 100644
View file @
7bbe84e0
package
com
.
qkdata
.
common
.
tree
;
/**
* @author liu_yang
* 树类型枚举
*
*/
public
enum
TreeTypeEnum
{
/**
* 树节点可多选
*/
CHECKBOX
(
"checkbox"
),
/**
* 树节点可单选
*/
RADIO
(
"radio"
),
/**
* 树节点为普通节点
*/
NORMAL
(
"normal"
);
/**
* 类型值
*/
private
String
value
;
/**
* @param value
*/
private
TreeTypeEnum
(
final
String
value
)
{
this
.
value
=
value
;
}
/**
* @return
*/
public
String
value
()
{
return
this
.
value
;
}
}
src/main/java/com/qkdata/common/tree/TreeView.java
0 → 100644
View file @
7bbe84e0
package
com
.
qkdata
.
common
.
tree
;
import
java.util.ArrayList
;
import
java.util.List
;
/**
* @author liu_yang 生成树方法
*
*/
public
class
TreeView
{
/**
* <code>m_treeData</code> - 树内容原始对象.
*/
private
List
<?
extends
Object
>
m_treeData
;
/**
* <code>m_contentProvider</code> - 内容提供者.
*/
private
IContentProvider
m_contentProvider
;
/**
* <code>m_labelProvider</code> - 节点内容提供者.
*/
private
ILabelProvider
m_labelProvider
;
/**
* 生成树对象的构造方法
* @param treeData 生成树结构的数据
* @param contentProvider 树节点内容提供者
* @param labelProvider 树节点label显示内容提供者
*/
public
TreeView
(
List
<?
extends
Object
>
treeData
,
IContentProvider
contentProvider
,
ILabelProvider
labelProvider
){
this
.
m_treeData
=
treeData
;
this
.
m_contentProvider
=
contentProvider
;
this
.
m_labelProvider
=
labelProvider
;
}
/**
* 构造树.
*
* @param treeId
* Tree ID
* @return Tree对象
* @throws ServiceException
* Service异常
*/
public
Tree
buildTree
(
final
String
treeId
)
{
List
<
TreeNode
>
t_rootList
=
new
ArrayList
<
TreeNode
>();
TreeNode
t_treeNode
=
null
;
List
<?
extends
Object
>
t_rootObjectList
=
m_contentProvider
.
getRootElement
(
this
.
m_treeData
,
0
,
0
);
if
(
t_rootObjectList
!=
null
)
{
for
(
int
t_i
=
0
;
t_i
<
t_rootObjectList
.
size
();
t_i
++)
{
Object
t_rootObject
=
t_rootObjectList
.
get
(
t_i
);
t_treeNode
=
createTreeNode
(
t_rootObject
,
0
,
t_i
);
recursionNodes
(
this
.
m_contentProvider
.
getChildren
(
t_rootObject
,
0
,
t_i
),
t_treeNode
,
0
);
t_rootList
.
add
(
t_treeNode
);
}
}
Tree
t_tree
=
new
Tree
(
treeId
,
t_rootList
);
return
t_tree
;
}
/**
* 递归树节点.
*
* @param objectList
* 树原始对象集合
* @param parentTreeNode
* 父树节点
* @param level
* 树节点集合
* @throws ServiceException
* 异常
*/
private
void
recursionNodes
(
final
List
<?
extends
Object
>
objectList
,
final
TreeNode
parentTreeNode
,
final
int
level
)
{
int
t_level
=
level
+
1
;
TreeNode
t_treeNode
=
null
;
if
(
objectList
!=
null
)
{
for
(
int
t_i
=
0
;
t_i
<
objectList
.
size
();
t_i
++)
{
Object
t_childObject
=
objectList
.
get
(
t_i
);
t_treeNode
=
createTreeNode
(
t_childObject
,
t_level
,
t_i
);
parentTreeNode
.
addChild
(
t_treeNode
);
recursionNodes
(
this
.
m_contentProvider
.
getChildren
(
t_childObject
,
t_level
,
t_i
),
t_treeNode
,
t_level
);
}
}
}
/**
* 创建树节点.
*
* @param o
* 节点原始对象
* @param level
* 节点级别
* @param index
* 节点同级索引
* @return 创建的树节点
*/
private
TreeNode
createTreeNode
(
final
Object
o
,
final
int
level
,
final
int
index
)
{
TreeNode
t_treeNode
=
new
TreeNode
(
this
.
m_labelProvider
.
getLabelId
(
o
,
level
,
index
),
this
.
m_labelProvider
.
getAttributes
(
o
,
level
,
index
));
if
(
this
.
m_contentProvider
.
hasChild
(
o
,
level
,
index
))
{
t_treeNode
.
setIsExpand
(
true
);
}
else
{
t_treeNode
.
setIsExpand
(
false
);
}
t_treeNode
.
setName
(
this
.
m_labelProvider
.
getLabelName
(
o
,
level
,
index
));
t_treeNode
.
setIcon
(
this
.
m_labelProvider
.
getIcon
(
o
,
level
,
index
));
t_treeNode
.
setIsClick
(
this
.
m_labelProvider
.
isClick
(
o
,
level
,
index
));
t_treeNode
.
setIsCheck
(
this
.
m_labelProvider
.
isCheck
(
o
,
level
,
index
));
createTreeNodeType
(
o
,
level
,
index
,
t_treeNode
);
return
t_treeNode
;
}
/**
* 创建树节点类型.
*
* @param o
* Object
* @param level
* 级别
* @param index
* 索引
* @param treeNode
* 树节点
*/
private
void
createTreeNodeType
(
final
Object
o
,
final
int
level
,
final
int
index
,
final
TreeNode
treeNode
)
{
TreeTypeEnum
t_treeType
=
this
.
m_labelProvider
.
getLabelType
(
o
,
level
,
index
);
treeNode
.
setType
(
t_treeType
.
toString
());
}
}
src/main/java/com/qkdata/common/util/EncryptUtil.java
0 → 100644
View file @
7bbe84e0
package
com
.
qkdata
.
common
.
util
;
import
org.apache.commons.codec.DecoderException
;
import
org.apache.commons.codec.binary.Hex
;
import
org.apache.commons.lang3.Validate
;
import
java.security.MessageDigest
;
import
java.security.NoSuchAlgorithmException
;
import
java.security.SecureRandom
;
public
class
EncryptUtil
{
private
static
final
String
SHA1
=
"SHA-1"
;
private
static
final
String
MD5
=
"MD5"
;
private
static
final
SecureRandom
random
=
new
SecureRandom
();
public
static
String
getSalt
()
{
byte
[]
saltByte
=
generateSalt
(
8
);
String
salt
=
encodeHex
(
saltByte
);
return
salt
;
}
public
static
String
encryptPassword
(
String
password
,
String
salt
)
throws
NoSuchAlgorithmException
{
byte
[]
hashPassword
=
md5
(
password
.
getBytes
(),
salt
.
getBytes
(),
1024
);
return
encodeHex
(
hashPassword
);
}
/**
* Hex编码.
*/
public
static
String
encodeHex
(
byte
[]
input
)
{
return
Hex
.
encodeHexString
(
input
);
}
/**
* Hex解码.
* @throws DecoderException
*/
public
static
byte
[]
decodeHex
(
String
input
)
throws
DecoderException
{
return
Hex
.
decodeHex
(
input
.
toCharArray
());
}
public
static
byte
[]
sha1
(
byte
[]
input
,
byte
[]
salt
,
int
iterations
)
throws
NoSuchAlgorithmException
{
return
digest
(
input
,
SHA1
,
salt
,
iterations
);
}
public
static
byte
[]
md5
(
byte
[]
input
,
byte
[]
salt
,
int
iterations
)
throws
NoSuchAlgorithmException
{
return
digest
(
input
,
MD5
,
salt
,
iterations
);
}
/**
* 对字符串进行散列, 支持md5与sha1算法.
* @throws NoSuchAlgorithmException
*/
private
static
byte
[]
digest
(
byte
[]
input
,
String
algorithm
,
byte
[]
salt
,
int
iterations
)
throws
NoSuchAlgorithmException
{
MessageDigest
digest
=
MessageDigest
.
getInstance
(
algorithm
);
if
(
salt
!=
null
)
{
digest
.
update
(
salt
);
}
byte
[]
result
=
digest
.
digest
(
input
);
for
(
int
i
=
1
;
i
<
iterations
;
i
++)
{
digest
.
reset
();
result
=
digest
.
digest
(
result
);
}
return
result
;
}
/**
* 生成随机的Byte[]作为salt.
*
* @param numBytes byte数组的大小
*/
private
static
byte
[]
generateSalt
(
int
numBytes
)
{
Validate
.
isTrue
(
numBytes
>
0
,
"numBytes argument must be a positive integer (1 or larger)"
,
numBytes
);
byte
[]
bytes
=
new
byte
[
numBytes
];
random
.
nextBytes
(
bytes
);
return
bytes
;
}
}
src/main/java/com/qkdata/common/util/HttpContextUtils.java
0 → 100644
View file @
7bbe84e0
/**
* Copyright (c) 2016-2019 人人开源 All rights reserved.
*
*
* 版权所有,侵权必究!
*/
package
com
.
qkdata
.
common
.
util
;
import
org.springframework.web.context.request.RequestContextHolder
;
import
org.springframework.web.context.request.ServletRequestAttributes
;
import
javax.servlet.http.HttpServletRequest
;
public
class
HttpContextUtils
{
public
static
HttpServletRequest
getHttpServletRequest
()
{
return
((
ServletRequestAttributes
)
RequestContextHolder
.
getRequestAttributes
()).
getRequest
();
}
public
static
String
getDomain
(){
HttpServletRequest
request
=
getHttpServletRequest
();
StringBuffer
url
=
request
.
getRequestURL
();
return
url
.
delete
(
url
.
length
()
-
request
.
getRequestURI
().
length
(),
url
.
length
()).
toString
();
}
public
static
String
getOrigin
(){
HttpServletRequest
request
=
getHttpServletRequest
();
return
request
.
getHeader
(
"Origin"
);
}
}
src/main/java/com/qkdata/common/util/IPUtils.java
0 → 100644
View file @
7bbe84e0
/**
* Copyright (c) 2016-2019 人人开源 All rights reserved.
*
*
* 版权所有,侵权必究!
*/
package
com
.
qkdata
.
common
.
util
;
import
com.alibaba.druid.util.StringUtils
;
import
org.slf4j.Logger
;
import
org.slf4j.LoggerFactory
;
import
javax.servlet.http.HttpServletRequest
;
public
class
IPUtils
{
private
static
final
Logger
logger
=
LoggerFactory
.
getLogger
(
IPUtils
.
class
);
/**
* 获取IP地址
*
* 使用Nginx等反向代理软件, 则不能通过request.getRemoteAddr()获取IP地址
* 如果使用了多级反向代理的话,X-Forwarded-For的值并不止一个,而是一串IP地址,X-Forwarded-For中第一个非unknown的有效IP字符串,则为真实IP地址
*/
public
static
String
getIpAddr
(
HttpServletRequest
request
)
{
String
ip
=
null
;
try
{
ip
=
request
.
getHeader
(
"x-forwarded-for"
);
if
(
StringUtils
.
isEmpty
(
ip
)
||
"unknown"
.
equalsIgnoreCase
(
ip
))
{
ip
=
request
.
getHeader
(
"Proxy-Client-IP"
);
}
if
(
StringUtils
.
isEmpty
(
ip
)
||
ip
.
length
()
==
0
||
"unknown"
.
equalsIgnoreCase
(
ip
))
{
ip
=
request
.
getHeader
(
"WL-Proxy-Client-IP"
);
}
if
(
StringUtils
.
isEmpty
(
ip
)
||
"unknown"
.
equalsIgnoreCase
(
ip
))
{
ip
=
request
.
getHeader
(
"HTTP_CLIENT_IP"
);
}
if
(
StringUtils
.
isEmpty
(
ip
)
||
"unknown"
.
equalsIgnoreCase
(
ip
))
{
ip
=
request
.
getHeader
(
"HTTP_X_FORWARDED_FOR"
);
}
if
(
StringUtils
.
isEmpty
(
ip
)
||
"unknown"
.
equalsIgnoreCase
(
ip
))
{
ip
=
request
.
getRemoteAddr
();
}
}
catch
(
Exception
e
)
{
logger
.
error
(
"IPUtils ERROR "
,
e
);
}
// //使用代理,则获取第一个IP地址
// if(StringUtils.isEmpty(ip) && ip.length() > 15) {
// if(ip.indexOf(",") > 0) {
// ip = ip.substring(0, ip.indexOf(","));
// }
// }
return
ip
;
}
}
src/main/java/com/qkdata/common/util/Iterables.java
0 → 100644
View file @
7bbe84e0
package
com
.
qkdata
.
common
.
util
;
import
java.util.Objects
;
import
java.util.function.BiConsumer
;
/**
* 带索引的forEach方法
*/
public
class
Iterables
{
public
static
<
E
>
void
forEach
(
Iterable
<?
extends
E
>
elements
,
BiConsumer
<
Integer
,
?
super
E
>
action
)
{
Objects
.
requireNonNull
(
elements
);
Objects
.
requireNonNull
(
action
);
int
index
=
0
;
for
(
E
element
:
elements
)
{
action
.
accept
(
index
++,
element
);
}
}
}
src/main/java/com/qkdata/common/util/MD5Util.java
0 → 100644
View file @
7bbe84e0
package
com
.
qkdata
.
common
.
util
;
import
java.nio.charset.StandardCharsets
;
import
java.security.MessageDigest
;
/**
* @author songminghui
* @date 2018-12-17 下午6:00
* @email songminghui@shangweiec.com
* @description
*/
public
class
MD5Util
{
public
static
String
md5
(
String
str
)
{
try
{
MessageDigest
md
=
MessageDigest
.
getInstance
(
"MD5"
);
byte
[]
array
=
md
.
digest
(
str
.
getBytes
(
StandardCharsets
.
UTF_8
));
StringBuilder
sb
=
new
StringBuilder
();
for
(
byte
item
:
array
)
{
sb
.
append
(
Integer
.
toHexString
((
item
&
0xFF
)
|
0x100
),
1
,
3
);
}
return
sb
.
toString
().
toUpperCase
();
}
catch
(
Exception
e
)
{
e
.
printStackTrace
();
}
return
""
;
}
}
src/main/java/com/qkdata/common/util/RandomDigitGenerator.java
0 → 100644
View file @
7bbe84e0
package
com
.
qkdata
.
common
.
util
;
import
java.util.concurrent.ThreadLocalRandom
;
/**
* 随机数生成器
*/
public
final
class
RandomDigitGenerator
{
private
RandomDigitGenerator
()
{
}
private
static
final
int
DEFAULT_COUNT
=
6
;
private
static
final
ThreadLocalRandom
RANDOM
=
ThreadLocalRandom
.
current
();
private
static
final
int
ORIGIN
=
0
;
private
static
final
int
BOUND
=
10
;
/**
* 默认生成6位数字
*
* @return
*/
public
static
String
generate
()
{
return
generate
(
DEFAULT_COUNT
);
}
/**
* 生成指定长度的数字
*
* @param count 长度
* @return
*/
public
static
String
generate
(
int
count
)
{
if
(
count
<=
0
||
count
>
1000
)
{
return
""
;
}
return
RANDOM
.
ints
(
ORIGIN
,
BOUND
)
.
limit
(
count
)
.
collect
(
StringBuilder:
:
new
,
StringBuilder:
:
append
,
StringBuilder:
:
append
)
.
toString
();
}
}
src/main/java/com/qkdata/common/util/RequestUtil.java
0 → 100644
View file @
7bbe84e0
package
com
.
qkdata
.
common
.
util
;
import
com.fasterxml.jackson.databind.ObjectMapper
;
import
org.springframework.http.HttpMethod
;
import
org.springframework.util.StringUtils
;
import
org.springframework.web.context.request.RequestContextHolder
;
import
org.springframework.web.context.request.ServletRequestAttributes
;
import
javax.servlet.http.HttpServletRequest
;
import
java.io.BufferedReader
;
import
java.io.InputStreamReader
;
import
java.nio.charset.StandardCharsets
;
import
java.util.Map
;
/**
* @author songminghui
* @date 2018-11-26 下午6:52
* @email songminghui@shangweiec.com
* @description
*/
public
class
RequestUtil
{
private
RequestUtil
()
{
}
public
static
HttpServletRequest
getRequest
()
{
return
((
ServletRequestAttributes
)
RequestContextHolder
.
getRequestAttributes
()).
getRequest
();
}
public
static
String
getIpAddress
()
{
HttpServletRequest
request
=
RequestUtil
.
getRequest
();
String
ip
=
request
.
getHeader
(
"X-Real-IP"
);
if
(
StringUtils
.
isEmpty
(
ip
)
||
"unknown"
.
equalsIgnoreCase
(
ip
))
{
ip
=
request
.
getHeader
(
"x-forwarded-for"
);
}
if
(
StringUtils
.
isEmpty
(
ip
)
||
"unknown"
.
equalsIgnoreCase
(
ip
))
{
ip
=
request
.
getHeader
(
"Proxy-Client-IP"
);
}
if
(
StringUtils
.
isEmpty
(
ip
)
||
"unknown"
.
equalsIgnoreCase
(
ip
))
{
ip
=
request
.
getHeader
(
"WL-Proxy-Client-IP"
);
}
if
(
StringUtils
.
isEmpty
(
ip
)
||
"unknown"
.
equalsIgnoreCase
(
ip
))
{
ip
=
request
.
getHeader
(
"HTTP_CLIENT_IP"
);
}
if
(
StringUtils
.
isEmpty
(
ip
)
||
"unknown"
.
equalsIgnoreCase
(
ip
))
{
ip
=
request
.
getHeader
(
"HTTP_X_FORWARDED_FOR"
);
}
if
(
StringUtils
.
isEmpty
(
ip
)
||
"unknown"
.
equalsIgnoreCase
(
ip
))
{
ip
=
request
.
getRemoteAddr
();
}
return
ip
;
}
public
static
String
getParam
(
HttpServletRequest
request
)
{
BufferedReader
br
=
null
;
try
{
String
method
=
request
.
getMethod
();
if
(
HttpMethod
.
GET
.
matches
(
method
))
{
Map
<
String
,
String
[]>
parameterMap
=
request
.
getParameterMap
();
return
new
ObjectMapper
().
writeValueAsString
(
parameterMap
);
}
br
=
new
BufferedReader
(
new
InputStreamReader
(
request
.
getInputStream
(),
StandardCharsets
.
UTF_8
));
}
catch
(
Exception
e
)
{
}
String
line
=
null
;
StringBuilder
sb
=
new
StringBuilder
();
try
{
while
((
line
=
br
.
readLine
())
!=
null
)
{
sb
.
append
(
line
);
}
}
catch
(
Exception
e
)
{
}
return
sb
.
toString
();
}
}
src/main/java/com/qkdata/common/util/ShareCodeUtils.java
0 → 100644
View file @
7bbe84e0
package
com
.
qkdata
.
common
.
util
;
import
java.util.Random
;
public
class
ShareCodeUtils
{
/**
* 自定义进制(0,1没有加入,容易与o,l混淆),数组顺序可进行调整增加反推难度,A用来补位因此此数组不包含A,共31个字符。
*/
private
static
final
char
[]
BASE
=
new
char
[]{
'H'
,
'V'
,
'E'
,
'8'
,
'S'
,
'2'
,
'D'
,
'Z'
,
'X'
,
'9'
,
'C'
,
'7'
,
'P'
,
'5'
,
'I'
,
'K'
,
'3'
,
'M'
,
'J'
,
'U'
,
'F'
,
'R'
,
'4'
,
'W'
,
'Y'
,
'L'
,
'T'
,
'N'
,
'6'
,
'B'
,
'G'
,
'Q'
};
/**
* A补位字符,不能与自定义重复
*/
private
static
final
char
SUFFIX_CHAR
=
'A'
;
/**
* 进制长度
*/
private
static
final
int
BIN_LEN
=
BASE
.
length
;
/**
* 生成邀请码最小长度
*/
private
static
final
int
CODE_LEN
=
6
;
public
static
String
mobileToCode
(
String
mobile
){
Long
id
=
Long
.
parseLong
(
mobile
);
return
idToCode
(
id
);
}
public
static
String
codeToMobile
(
String
code
){
Long
id
=
codeToId
(
code
);
return
String
.
valueOf
(
id
);
}
/**
* ID转换为邀请码
*
* @param id
* @return
*/
private
static
String
idToCode
(
Long
id
)
{
char
[]
buf
=
new
char
[
BIN_LEN
];
int
charPos
=
BIN_LEN
;
// 当id除以数组长度结果大于0,则进行取模操作,并以取模的值作为数组的坐标获得对应的字符
while
(
id
/
BIN_LEN
>
0
)
{
int
index
=
(
int
)
(
id
%
BIN_LEN
);
buf
[--
charPos
]
=
BASE
[
index
];
id
/=
BIN_LEN
;
}
buf
[--
charPos
]
=
BASE
[(
int
)
(
id
%
BIN_LEN
)];
// 将字符数组转化为字符串
String
result
=
new
String
(
buf
,
charPos
,
BIN_LEN
-
charPos
);
// 长度不足指定长度则随机补全
int
len
=
result
.
length
();
if
(
len
<
CODE_LEN
)
{
StringBuilder
sb
=
new
StringBuilder
();
sb
.
append
(
SUFFIX_CHAR
);
Random
random
=
new
Random
();
// 去除SUFFIX_CHAR本身占位之后需要补齐的位数
for
(
int
i
=
0
;
i
<
CODE_LEN
-
len
-
1
;
i
++)
{
sb
.
append
(
BASE
[
random
.
nextInt
(
BIN_LEN
)]);
}
result
+=
sb
.
toString
();
}
return
result
;
}
/**
* 邀请码解析出ID<br/>
* 基本操作思路恰好与idToCode反向操作。
*
* @param code
* @return
*/
private
static
Long
codeToId
(
String
code
)
{
char
[]
charArray
=
code
.
toCharArray
();
long
result
=
0L
;
for
(
int
i
=
0
;
i
<
charArray
.
length
;
i
++)
{
int
index
=
0
;
for
(
int
j
=
0
;
j
<
BIN_LEN
;
j
++)
{
if
(
charArray
[
i
]
==
BASE
[
j
])
{
index
=
j
;
break
;
}
}
if
(
charArray
[
i
]
==
SUFFIX_CHAR
)
{
break
;
}
if
(
i
>
0
)
{
result
=
result
*
BIN_LEN
+
index
;
}
else
{
result
=
index
;
}
}
return
result
;
}
public
static
void
main
(
String
[]
args
)
{
String
mobile
=
"18678057587"
;
//Constants.ADMIN_MOBILE;
String
code
=
mobileToCode
(
mobile
);
System
.
out
.
println
(
code
);
String
str
=
codeToMobile
(
"MZTLU8J"
);
System
.
out
.
println
(
str
);
}
}
src/main/java/com/qkdata/common/util/UserContext.java
0 → 100644
View file @
7bbe84e0
package
com
.
qkdata
.
common
.
util
;
import
com.qkdata.biz.sys.entity.SysUserPO
;
import
org.apache.shiro.SecurityUtils
;
public
class
UserContext
{
public
static
SysUserPO
getUser
(){
SysUserPO
user
=
(
SysUserPO
)
SecurityUtils
.
getSubject
().
getPrincipal
();
return
user
;
}
public
static
Long
getUserId
(){
return
getUser
().
getId
();
}
}
src/main/java/com/qkdata/wx/miniapp/config/WxMaConfiguration.java
0 → 100644
View file @
7bbe84e0
package
com
.
qkdata
.
wx
.
miniapp
.
config
;
import
cn.binarywang.wx.miniapp.api.WxMaService
;
import
cn.binarywang.wx.miniapp.api.impl.WxMaServiceImpl
;
import
cn.binarywang.wx.miniapp.bean.WxMaKefuMessage
;
import
cn.binarywang.wx.miniapp.bean.WxMaTemplateData
;
import
cn.binarywang.wx.miniapp.bean.WxMaTemplateMessage
;
import
cn.binarywang.wx.miniapp.config.impl.WxMaDefaultConfigImpl
;
import
cn.binarywang.wx.miniapp.message.WxMaMessageHandler
;
import
cn.binarywang.wx.miniapp.message.WxMaMessageRouter
;
import
com.google.common.collect.Lists
;
import
com.google.common.collect.Maps
;
import
me.chanjar.weixin.common.bean.result.WxMediaUploadResult
;
import
me.chanjar.weixin.common.error.WxErrorException
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.boot.context.properties.EnableConfigurationProperties
;
import
org.springframework.context.annotation.Configuration
;
import
javax.annotation.PostConstruct
;
import
java.io.File
;
import
java.util.List
;
import
java.util.Map
;
import
java.util.stream.Collectors
;
/**
* @author <a href="https://github.com/binarywang">Binary Wang</a>
*/
@Configuration
@EnableConfigurationProperties
(
WxMaProperties
.
class
)
public
class
WxMaConfiguration
{
private
WxMaProperties
properties
;
private
static
Map
<
String
,
WxMaMessageRouter
>
routers
=
Maps
.
newHashMap
();
private
static
Map
<
String
,
WxMaService
>
maServices
=
Maps
.
newHashMap
();
@Autowired
public
WxMaConfiguration
(
WxMaProperties
properties
)
{
this
.
properties
=
properties
;
}
public
static
WxMaService
getMaService
(
String
appid
)
{
WxMaService
wxService
=
maServices
.
get
(
appid
);
if
(
wxService
==
null
)
{
throw
new
IllegalArgumentException
(
String
.
format
(
"未找到对应appid=[%s]的配置,请核实!"
,
appid
));
}
return
wxService
;
}
public
static
WxMaMessageRouter
getRouter
(
String
appid
)
{
return
routers
.
get
(
appid
);
}
@PostConstruct
public
void
init
()
{
List
<
WxMaProperties
.
Config
>
configs
=
this
.
properties
.
getConfigs
();
if
(
configs
==
null
)
{
throw
new
RuntimeException
(
"大哥,拜托先看下项目首页的说明(readme文件),添加下相关配置,注意别配错了!"
);
}
maServices
=
configs
.
stream
()
.
map
(
a
->
{
WxMaDefaultConfigImpl
config
=
new
WxMaDefaultConfigImpl
();
config
.
setAppid
(
a
.
getAppid
());
config
.
setSecret
(
a
.
getSecret
());
config
.
setToken
(
a
.
getToken
());
config
.
setAesKey
(
a
.
getAesKey
());
config
.
setMsgDataFormat
(
a
.
getMsgDataFormat
());
WxMaService
service
=
new
WxMaServiceImpl
();
service
.
setWxMaConfig
(
config
);
routers
.
put
(
a
.
getAppid
(),
this
.
newRouter
(
service
));
return
service
;
}).
collect
(
Collectors
.
toMap
(
s
->
s
.
getWxMaConfig
().
getAppid
(),
a
->
a
));
}
private
WxMaMessageRouter
newRouter
(
WxMaService
service
)
{
final
WxMaMessageRouter
router
=
new
WxMaMessageRouter
(
service
);
router
.
rule
().
handler
(
logHandler
).
next
()
.
rule
().
async
(
false
).
content
(
"模板"
).
handler
(
templateMsgHandler
).
end
()
.
rule
().
async
(
false
).
content
(
"文本"
).
handler
(
textHandler
).
end
()
.
rule
().
async
(
false
).
content
(
"图片"
).
handler
(
picHandler
).
end
()
.
rule
().
async
(
false
).
content
(
"二维码"
).
handler
(
qrcodeHandler
).
end
();
return
router
;
}
private
final
WxMaMessageHandler
templateMsgHandler
=
(
wxMessage
,
context
,
service
,
sessionManager
)
->
{
service
.
getMsgService
().
sendTemplateMsg
(
WxMaTemplateMessage
.
builder
()
.
templateId
(
"此处更换为自己的模板id"
)
.
formId
(
"自己替换可用的formid"
)
.
data
(
Lists
.
newArrayList
(
new
WxMaTemplateData
(
"keyword1"
,
"339208499"
,
"#173177"
)))
.
toUser
(
wxMessage
.
getFromUser
())
.
build
());
return
null
;
};
private
final
WxMaMessageHandler
logHandler
=
(
wxMessage
,
context
,
service
,
sessionManager
)
->
{
System
.
out
.
println
(
"收到消息:"
+
wxMessage
.
toString
());
service
.
getMsgService
().
sendKefuMsg
(
WxMaKefuMessage
.
newTextBuilder
().
content
(
"收到信息为:"
+
wxMessage
.
toJson
())
.
toUser
(
wxMessage
.
getFromUser
()).
build
());
return
null
;
};
private
final
WxMaMessageHandler
textHandler
=
(
wxMessage
,
context
,
service
,
sessionManager
)
->
{
service
.
getMsgService
().
sendKefuMsg
(
WxMaKefuMessage
.
newTextBuilder
().
content
(
"回复文本消息"
)
.
toUser
(
wxMessage
.
getFromUser
()).
build
());
return
null
;
};
private
final
WxMaMessageHandler
picHandler
=
(
wxMessage
,
context
,
service
,
sessionManager
)
->
{
try
{
WxMediaUploadResult
uploadResult
=
service
.
getMediaService
()
.
uploadMedia
(
"image"
,
"png"
,
ClassLoader
.
getSystemResourceAsStream
(
"tmp.png"
));
service
.
getMsgService
().
sendKefuMsg
(
WxMaKefuMessage
.
newImageBuilder
()
.
mediaId
(
uploadResult
.
getMediaId
())
.
toUser
(
wxMessage
.
getFromUser
())
.
build
());
}
catch
(
WxErrorException
e
)
{
e
.
printStackTrace
();
}
return
null
;
};
private
final
WxMaMessageHandler
qrcodeHandler
=
(
wxMessage
,
context
,
service
,
sessionManager
)
->
{
try
{
final
File
file
=
service
.
getQrcodeService
().
createQrcode
(
"123"
,
430
);
WxMediaUploadResult
uploadResult
=
service
.
getMediaService
().
uploadMedia
(
"image"
,
file
);
service
.
getMsgService
().
sendKefuMsg
(
WxMaKefuMessage
.
newImageBuilder
()
.
mediaId
(
uploadResult
.
getMediaId
())
.
toUser
(
wxMessage
.
getFromUser
())
.
build
());
}
catch
(
WxErrorException
e
)
{
e
.
printStackTrace
();
}
return
null
;
};
}
src/main/java/com/qkdata/wx/miniapp/config/WxMaProperties.java
0 → 100644
View file @
7bbe84e0
package
com
.
qkdata
.
wx
.
miniapp
.
config
;
import
java.util.List
;
import
org.springframework.boot.context.properties.ConfigurationProperties
;
import
lombok.Data
;
/**
* @author <a href="https://github.com/binarywang">Binary Wang</a>
*/
@Data
@ConfigurationProperties
(
prefix
=
"wx.miniapp"
)
public
class
WxMaProperties
{
private
List
<
Config
>
configs
;
@Data
public
static
class
Config
{
/**
* 设置微信小程序的appid
*/
private
String
appid
;
/**
* 设置微信小程序的Secret
*/
private
String
secret
;
/**
* 设置微信小程序消息服务器配置的token
*/
private
String
token
;
/**
* 设置微信小程序消息服务器配置的EncodingAESKey
*/
private
String
aesKey
;
/**
* 消息格式,XML或者JSON
*/
private
String
msgDataFormat
;
}
}
src/main/java/com/qkdata/wx/miniapp/controller/WxPortalController.java
0 → 100644
View file @
7bbe84e0
package
com
.
qkdata
.
wx
.
miniapp
.
controller
;
import
cn.binarywang.wx.miniapp.api.WxMaService
;
import
cn.binarywang.wx.miniapp.bean.WxMaMessage
;
import
cn.binarywang.wx.miniapp.constant.WxMaConstants
;
import
com.qkdata.wx.miniapp.config.WxMaConfiguration
;
import
org.apache.commons.lang3.StringUtils
;
import
org.slf4j.Logger
;
import
org.slf4j.LoggerFactory
;
import
org.springframework.web.bind.annotation.*
;
import
java.util.Objects
;
/**
* @author <a href="https://github.com/binarywang">Binary Wang</a>
*/
@RestController
@RequestMapping
(
"/wx/portal/{appid}"
)
public
class
WxPortalController
{
private
final
Logger
logger
=
LoggerFactory
.
getLogger
(
this
.
getClass
());
@GetMapping
(
produces
=
"text/plain;charset=utf-8"
)
public
String
authGet
(
@PathVariable
String
appid
,
@RequestParam
(
name
=
"signature"
,
required
=
false
)
String
signature
,
@RequestParam
(
name
=
"timestamp"
,
required
=
false
)
String
timestamp
,
@RequestParam
(
name
=
"nonce"
,
required
=
false
)
String
nonce
,
@RequestParam
(
name
=
"echostr"
,
required
=
false
)
String
echostr
)
{
this
.
logger
.
info
(
"\n接收到来自微信服务器的认证消息:signature = [{}], timestamp = [{}], nonce = [{}], echostr = [{}]"
,
signature
,
timestamp
,
nonce
,
echostr
);
if
(
StringUtils
.
isAnyBlank
(
signature
,
timestamp
,
nonce
,
echostr
))
{
throw
new
IllegalArgumentException
(
"请求参数非法,请核实!"
);
}
final
WxMaService
wxService
=
WxMaConfiguration
.
getMaService
(
appid
);
if
(
wxService
.
checkSignature
(
timestamp
,
nonce
,
signature
))
{
return
echostr
;
}
return
"非法请求"
;
}
@PostMapping
(
produces
=
"application/xml; charset=UTF-8"
)
public
String
post
(
@PathVariable
String
appid
,
@RequestBody
String
requestBody
,
@RequestParam
(
name
=
"msg_signature"
,
required
=
false
)
String
msgSignature
,
@RequestParam
(
name
=
"encrypt_type"
,
required
=
false
)
String
encryptType
,
@RequestParam
(
name
=
"signature"
,
required
=
false
)
String
signature
,
@RequestParam
(
"timestamp"
)
String
timestamp
,
@RequestParam
(
"nonce"
)
String
nonce
)
{
this
.
logger
.
info
(
"\n接收微信请求:[msg_signature=[{}], encrypt_type=[{}], signature=[{}],"
+
" timestamp=[{}], nonce=[{}], requestBody=[\n{}\n] "
,
msgSignature
,
encryptType
,
signature
,
timestamp
,
nonce
,
requestBody
);
final
WxMaService
wxService
=
WxMaConfiguration
.
getMaService
(
appid
);
final
boolean
isJson
=
Objects
.
equals
(
wxService
.
getWxMaConfig
().
getMsgDataFormat
(),
WxMaConstants
.
MsgDataFormat
.
JSON
);
if
(
StringUtils
.
isBlank
(
encryptType
))
{
// 明文传输的消息
WxMaMessage
inMessage
;
if
(
isJson
)
{
inMessage
=
WxMaMessage
.
fromJson
(
requestBody
);
}
else
{
//xml
inMessage
=
WxMaMessage
.
fromXml
(
requestBody
);
}
this
.
route
(
inMessage
,
appid
);
return
"success"
;
}
if
(
"aes"
.
equals
(
encryptType
))
{
// 是aes加密的消息
WxMaMessage
inMessage
;
if
(
isJson
)
{
inMessage
=
WxMaMessage
.
fromEncryptedJson
(
requestBody
,
wxService
.
getWxMaConfig
());
}
else
{
//xml
inMessage
=
WxMaMessage
.
fromEncryptedXml
(
requestBody
,
wxService
.
getWxMaConfig
(),
timestamp
,
nonce
,
msgSignature
);
}
this
.
route
(
inMessage
,
appid
);
return
"success"
;
}
throw
new
RuntimeException
(
"不可识别的加密类型:"
+
encryptType
);
}
private
void
route
(
WxMaMessage
message
,
String
appid
)
{
try
{
WxMaConfiguration
.
getRouter
(
appid
).
route
(
message
);
}
catch
(
Exception
e
)
{
this
.
logger
.
error
(
e
.
getMessage
(),
e
);
}
}
}
src/main/resources/application-dev.yml
0 → 100644
View file @
7bbe84e0
server
:
port
:
9090
spring
:
datasource
:
druid
:
url
:
jdbc:mysql://localhost:3306/online-edu?useUnicode=true&characterEncoding=UTF-8&allowMultiQueries=true&useSSL=false
username
:
root
password
:
123456
redis
:
host
:
localhost
port
:
6379
log
:
path
:
/Users/liuyang/work/argus_work/online-edu/data/logs
file
:
path
:
/Users/liuyang/work/argus_work/online-edu/data/files
#../data/files
src/main/resources/application.yml
0 → 100644
View file @
7bbe84e0
server
:
port
:
80
servlet
:
context-path
:
/online-edu-backend
multipart
:
enable
:
true
max-file-size
:
10M
# ssl:
# key-store: classpath:3275085_datahub.qiankundata.com.pfx
# key-store-password: cDU6D68N
connection-timeout
:
15000
tomcat
:
max-threads
:
1000
management
:
server
:
port
:
8080
ssl
:
enabled
:
false
# endpoint:
# health:
# show-details: always
spring
:
datasource
:
druid
:
url
:
jdbc:mysql://mysql:3306/framework?useUnicode=true&characterEncoding=UTF-8&allowMultiQueries=true&useSSL=false
username
:
root
password
:
qkdata
driver-class-name
:
com.mysql.jdbc.Driver
initialSize
:
50
minIdle
:
10
maxActive
:
200
maxWait
:
60000
timeBetweenEvictionRunsMillis
:
60000
minEvictableIdleTimeMillis
:
300000
validationQuery
:
SELECT 1 FROM DUAL
testWhileIdle
:
true
testOnBorrow
:
false
testOnReturn
:
false
poolPreparedStatements
:
false
maxPoolPreparedStatementPerConnectionSize
:
-1
filters
:
stat,slf4j,config
connectionProperties
:
druid.stat.mergeSql=true;druid.stat.slowSqlMil=3000
useGlobalDataSourceStat
:
true
filter
:
wall
:
config
:
multi-statement-allow
:
true
redis
:
host
:
redis
port
:
6379
database
:
0
lettuce
:
pool
:
max-active
:
200
max-idle
:
10
min-idle
:
0
mvc
:
throw-exception-if-no-handler-found
:
true
resources
:
add-mappings
:
true
main
:
allow-bean-definition-overriding
:
true
mybatis-plus
:
mapper-locations
:
classpath:/mappers/*Mapper.xml
#实体扫描,多个package用逗号或者分号分隔
typeAliasesPackage
:
com.qkdata.biz.sys.entity
typeEnumsPackage
:
com.qkdata.biz.enums
configuration
:
map-underscore-to-camel-case
:
true
global-config
:
db-config
:
id-type
:
auto
log
:
context
:
online-edu-backend
path
:
/data/logs
file
:
path
:
/data/files
downloadPath
:
/download/
#前台获取静态资源时的context
frontend
:
domain
:
https://qdytx888.cn
#前端访问的域名
jwt
:
secret
:
qkdata
enable-interceptor
:
true
include-urls
:
-
/api/**
exclude-urls
:
-
/api/wx/user/**
-
/api/sys/login
aud
:
qkdata
exp
:
720
#24*30 30天
wx
:
miniapp
:
configs
:
-
appid
:
wx4a74df8356c465a5
#微信小程序的appid
secret
:
415f8d52311eeb0e5eef32a5e41758ae
#微信小程序的Secret
token
:
#微信小程序消息服务器配置的token
aesKey
:
#微信小程序消息服务器配置的EncodingAESKey
msgDataFormat
:
JSON
sms
:
api
:
v3
:
http://sms-service/sms/api/v3
src/main/resources/db/migration/V1.0.0__init.sql
0 → 100644
View file @
7bbe84e0
-- ----------------------------
-- Table structure for allow_org_course
-- ----------------------------
DROP
TABLE
IF
EXISTS
`allow_org_course`
;
CREATE
TABLE
`allow_org_course`
(
`id`
bigint
(
20
)
NOT
NULL
AUTO_INCREMENT
COMMENT
'主键'
,
`course_id`
bigint
(
20
)
DEFAULT
NULL
COMMENT
'课程ID'
,
`org_id`
bigint
(
20
)
DEFAULT
NULL
COMMENT
'企业ID'
,
PRIMARY
KEY
(
`id`
)
)
ENGINE
=
InnoDB
DEFAULT
CHARSET
=
utf8mb4
COMMENT
=
'授权企业可见的课程'
;
-- ----------------------------
-- Table structure for course
-- ----------------------------
DROP
TABLE
IF
EXISTS
`course`
;
CREATE
TABLE
`course`
(
`id`
bigint
(
20
)
NOT
NULL
AUTO_INCREMENT
COMMENT
'主键'
,
`type`
varchar
(
20
)
DEFAULT
NULL
COMMENT
'课程类型(单集、系列)'
,
`name`
varchar
(
255
)
DEFAULT
NULL
COMMENT
'课程名称'
,
`introduce`
text
COMMENT
'课程简介'
,
`logo_url`
varchar
(
255
)
DEFAULT
NULL
COMMENT
'课程封面url'
,
`status`
varchar
(
10
)
DEFAULT
NULL
COMMENT
'状态(上架、下架)'
,
`teacher_id`
bigint
(
20
)
DEFAULT
NULL
COMMENT
'讲师ID'
,
`charge_model`
varchar
(
20
)
DEFAULT
NULL
COMMENT
'收费模式(免费、会员免费、付费点播)'
,
`price`
decimal
(
10
,
2
)
DEFAULT
NULL
COMMENT
'付费点播普通用户价'
,
`vip_price`
decimal
(
10
,
2
)
DEFAULT
NULL
COMMENT
'付费点播会员价'
,
`valid_period`
int
(
10
)
DEFAULT
NULL
COMMENT
'有效时间(小时)'
,
`model`
varchar
(
20
)
DEFAULT
NULL
COMMENT
'课程形态(点播、直播、一对一)'
,
`series_id`
bigint
(
20
)
DEFAULT
NULL
COMMENT
'系列ID'
,
`allow`
varchar
(
10
)
DEFAULT
NULL
COMMENT
'可见范围(全部、指定企业)'
,
`create_time`
datetime
DEFAULT
NULL
,
`update_time`
datetime
DEFAULT
NULL
,
`is_del`
tinyint
(
1
)
DEFAULT
NULL
COMMENT
'删除标识'
,
PRIMARY
KEY
(
`id`
)
)
ENGINE
=
InnoDB
DEFAULT
CHARSET
=
utf8mb4
COMMENT
=
'课程'
;
-- ----------------------------
-- Table structure for course_chapter
-- ----------------------------
DROP
TABLE
IF
EXISTS
`course_chapter`
;
CREATE
TABLE
`course_chapter`
(
`id`
bigint
(
20
)
NOT
NULL
AUTO_INCREMENT
COMMENT
'主键'
,
`course_id`
bigint
(
20
)
DEFAULT
NULL
COMMENT
'课程ID'
,
`resource_id`
bigint
(
20
)
DEFAULT
NULL
COMMENT
'视频ID'
,
`name`
varchar
(
255
)
DEFAULT
NULL
COMMENT
'章节标题'
,
`create_time`
datetime
DEFAULT
NULL
,
`update_time`
datetime
DEFAULT
NULL
,
PRIMARY
KEY
(
`id`
)
)
ENGINE
=
InnoDB
DEFAULT
CHARSET
=
utf8mb4
COMMENT
=
'课程章节'
;
-- ----------------------------
-- Table structure for course_consume_record
-- ----------------------------
DROP
TABLE
IF
EXISTS
`course_consume_record`
;
CREATE
TABLE
`course_consume_record`
(
`id`
bigint
(
20
)
NOT
NULL
AUTO_INCREMENT
COMMENT
'主键'
,
`user_id`
bigint
(
20
)
DEFAULT
NULL
COMMENT
'用户ID'
,
`watch_time`
bigint
(
20
)
DEFAULT
NULL
COMMENT
'观看时长(分钟)'
,
`course_id`
bigint
(
20
)
DEFAULT
NULL
COMMENT
'课程ID'
,
`chapter_id`
bigint
(
20
)
DEFAULT
NULL
COMMENT
'章节ID'
,
`video_id`
bigint
(
20
)
DEFAULT
NULL
COMMENT
'视频ID'
,
`create_time`
datetime
DEFAULT
NULL
,
`update_time`
datetime
DEFAULT
NULL
,
PRIMARY
KEY
(
`id`
)
)
ENGINE
=
InnoDB
DEFAULT
CHARSET
=
utf8mb4
COMMENT
=
'课程消耗记录'
;
-- ----------------------------
-- Table structure for course_series
-- ----------------------------
DROP
TABLE
IF
EXISTS
`course_series`
;
CREATE
TABLE
`course_series`
(
`id`
bigint
(
20
)
NOT
NULL
AUTO_INCREMENT
COMMENT
'主键'
,
`name`
varchar
(
255
)
DEFAULT
NULL
COMMENT
'系列名称'
,
`create_time`
datetime
DEFAULT
NULL
,
`update_time`
datetime
DEFAULT
NULL
,
PRIMARY
KEY
(
`id`
)
)
ENGINE
=
InnoDB
DEFAULT
CHARSET
=
utf8mb4
COMMENT
=
'课程系列'
;
-- ----------------------------
-- Table structure for course_tag
-- ----------------------------
DROP
TABLE
IF
EXISTS
`course_tag`
;
CREATE
TABLE
`course_tag`
(
`id`
bigint
(
20
)
NOT
NULL
AUTO_INCREMENT
COMMENT
'主键'
,
`name`
varchar
(
255
)
DEFAULT
NULL
COMMENT
'名称'
,
`create_time`
datetime
DEFAULT
NULL
,
`update_time`
datetime
DEFAULT
NULL
,
PRIMARY
KEY
(
`id`
)
)
ENGINE
=
InnoDB
DEFAULT
CHARSET
=
utf8mb4
COMMENT
=
'课程标签'
;
-- ----------------------------
-- Table structure for course_tag_rel
-- ----------------------------
DROP
TABLE
IF
EXISTS
`course_tag_rel`
;
CREATE
TABLE
`course_tag_rel`
(
`id`
bigint
(
20
)
NOT
NULL
AUTO_INCREMENT
COMMENT
'主键'
,
`course_id`
bigint
(
20
)
DEFAULT
NULL
COMMENT
'课程ID'
,
`tag_id`
bigint
(
20
)
DEFAULT
NULL
COMMENT
'标签ID'
,
PRIMARY
KEY
(
`id`
)
)
ENGINE
=
InnoDB
DEFAULT
CHARSET
=
utf8mb4
COMMENT
=
'课程与标签关联表'
;
-- ----------------------------
-- Table structure for exam
-- ----------------------------
DROP
TABLE
IF
EXISTS
`exam`
;
CREATE
TABLE
`exam`
(
`id`
bigint
(
20
)
NOT
NULL
AUTO_INCREMENT
COMMENT
'主键'
,
`name`
varchar
(
255
)
DEFAULT
NULL
COMMENT
'考试名称'
,
`limit`
int
(
11
)
DEFAULT
NULL
COMMENT
'考试限时(分钟)'
,
`description`
varchar
(
255
)
DEFAULT
NULL
COMMENT
'考试简述'
,
`question_ids_radio`
varchar
(
512
)
DEFAULT
NULL
COMMENT
'单选题ID集合,以逗号分隔'
,
`question_ids_check`
varchar
(
512
)
DEFAULT
NULL
COMMENT
'多选题ID集合,以逗号分隔'
,
`question_ids_judge`
varchar
(
512
)
DEFAULT
NULL
COMMENT
'判断题ID集合,以逗号分隔'
,
`score_radio`
int
(
11
)
DEFAULT
NULL
COMMENT
'当前考试每个单选题的分数'
,
`score_check`
int
(
11
)
DEFAULT
NULL
COMMENT
'当前考试每个多选题的分数'
,
`score_judge`
int
(
11
)
DEFAULT
NULL
COMMENT
'当前考试每个判断题的分数'
,
`create_time`
datetime
DEFAULT
NULL
,
`update_time`
datetime
DEFAULT
NULL
,
PRIMARY
KEY
(
`id`
)
)
ENGINE
=
InnoDB
DEFAULT
CHARSET
=
utf8mb4
COMMENT
=
'考试信息'
;
-- ----------------------------
-- Table structure for exam_question
-- ----------------------------
DROP
TABLE
IF
EXISTS
`exam_question`
;
CREATE
TABLE
`exam_question`
(
`id`
bigint
(
20
)
NOT
NULL
AUTO_INCREMENT
COMMENT
'主键'
,
`name`
text
COMMENT
'题目名称'
,
`type`
varchar
(
20
)
DEFAULT
NULL
COMMENT
'题目类型(单选、多选、判断)'
,
`option_ids`
varchar
(
255
)
DEFAULT
NULL
COMMENT
'选项ID集合,以逗号分隔'
,
`answer_ids`
varchar
(
255
)
DEFAULT
NULL
COMMENT
'签案ID集合,以逗号分隔'
,
`description`
text
COMMENT
'题目解析'
,
`create_time`
datetime
DEFAULT
NULL
,
`update_time`
datetime
DEFAULT
NULL
,
PRIMARY
KEY
(
`id`
)
)
ENGINE
=
InnoDB
DEFAULT
CHARSET
=
utf8mb4
COMMENT
=
'题目信息'
;
-- ----------------------------
-- Table structure for exam_question_option
-- ----------------------------
DROP
TABLE
IF
EXISTS
`exam_question_option`
;
CREATE
TABLE
`exam_question_option`
(
`id`
bigint
(
20
)
NOT
NULL
AUTO_INCREMENT
COMMENT
'主键'
,
`选项内容`
text
COMMENT
'选项内容'
,
`create_time`
datetime
DEFAULT
NULL
,
`update_time`
datetime
DEFAULT
NULL
,
PRIMARY
KEY
(
`id`
)
)
ENGINE
=
InnoDB
DEFAULT
CHARSET
=
utf8mb4
COMMENT
=
'题目选项'
;
-- ----------------------------
-- Table structure for exam_record
-- ----------------------------
DROP
TABLE
IF
EXISTS
`exam_record`
;
CREATE
TABLE
`exam_record`
(
`id`
bigint
(
20
)
NOT
NULL
AUTO_INCREMENT
COMMENT
'主键'
,
`user_id`
bigint
(
20
)
DEFAULT
NULL
COMMENT
'用户ID'
,
`exam_id`
bigint
(
20
)
DEFAULT
NULL
COMMENT
'考试ID'
,
`start_time`
datetime
DEFAULT
NULL
COMMENT
'考试时间'
,
`end_time`
datetime
DEFAULT
NULL
COMMENT
'完成时间'
,
`score`
int
(
11
)
DEFAULT
NULL
COMMENT
'得分'
,
`answer_ids`
varchar
(
512
)
DEFAULT
NULL
COMMENT
'答案ID集合,以逗号分隔'
,
`create_time`
datetime
DEFAULT
NULL
,
`update_time`
datetime
DEFAULT
NULL
,
PRIMARY
KEY
(
`id`
)
)
ENGINE
=
InnoDB
DEFAULT
CHARSET
=
utf8mb4
COMMENT
=
'考试记录'
;
-- ----------------------------
-- Table structure for org_buy_course_record
-- ----------------------------
DROP
TABLE
IF
EXISTS
`org_buy_course_record`
;
CREATE
TABLE
`org_buy_course_record`
(
`id`
bigint
(
20
)
NOT
NULL
AUTO_INCREMENT
COMMENT
'主键'
,
`org_id`
bigint
(
20
)
DEFAULT
NULL
COMMENT
'企业ID'
,
`course_id`
bigint
(
20
)
DEFAULT
NULL
COMMENT
'课程ID'
,
`count`
int
(
10
)
DEFAULT
NULL
COMMENT
'剩余份数'
,
`open`
tinyint
(
1
)
DEFAULT
NULL
COMMENT
'是否开放成员领取'
,
PRIMARY
KEY
(
`id`
)
)
ENGINE
=
InnoDB
DEFAULT
CHARSET
=
utf8mb4
COMMENT
=
'企业购买会员记录'
;
-- ----------------------------
-- Table structure for org_buy_vip_record
-- ----------------------------
DROP
TABLE
IF
EXISTS
`org_buy_vip_record`
;
CREATE
TABLE
`org_buy_vip_record`
(
`id`
bigint
(
20
)
NOT
NULL
AUTO_INCREMENT
COMMENT
'主键'
,
`org_id`
bigint
(
20
)
DEFAULT
NULL
COMMENT
'企业ID'
,
`vip_count`
int
(
11
)
DEFAULT
NULL
COMMENT
'会员剩余个数'
,
`open`
tinyint
(
1
)
DEFAULT
NULL
COMMENT
'是否开放成员领取'
,
`limit`
int
(
10
)
DEFAULT
NULL
COMMENT
'限制领取时长'
,
PRIMARY
KEY
(
`id`
)
)
ENGINE
=
InnoDB
DEFAULT
CHARSET
=
utf8mb4
COMMENT
=
'企业购买会员记录'
;
-- ----------------------------
-- Table structure for organization
-- ----------------------------
DROP
TABLE
IF
EXISTS
`organization`
;
CREATE
TABLE
`organization`
(
`id`
bigint
(
20
)
NOT
NULL
AUTO_INCREMENT
COMMENT
'主键'
,
`name`
varchar
(
100
)
DEFAULT
NULL
COMMENT
'组织名称'
,
`type`
varchar
(
20
)
DEFAULT
NULL
COMMENT
'组织类型(企业、培训机构)'
,
`contact_tel`
varchar
(
20
)
DEFAULT
NULL
COMMENT
'联系人电话'
,
`contact_name`
varchar
(
20
)
DEFAULT
NULL
COMMENT
'联系人名称'
,
`logo_url`
varchar
(
1000
)
DEFAULT
NULL
COMMENT
'企业LOG'
,
`province`
varchar
(
255
)
DEFAULT
NULL
COMMENT
'省份'
,
`city`
varchar
(
255
)
DEFAULT
NULL
COMMENT
'城市'
,
`address`
varchar
(
1000
)
DEFAULT
NULL
COMMENT
'详细地址'
,
`remark`
varchar
(
255
)
DEFAULT
NULL
COMMENT
'备注'
,
`create_time`
datetime
DEFAULT
NULL
COMMENT
'创建时间'
,
`update_time`
datetime
DEFAULT
NULL
COMMENT
'更新时间'
,
`is_del`
tinyint
(
1
)
DEFAULT
NULL
COMMENT
'删除标识'
,
PRIMARY
KEY
(
`id`
)
)
ENGINE
=
InnoDB
DEFAULT
CHARSET
=
utf8mb4
COMMENT
=
'组织'
;
-- ----------------------------
-- Table structure for recommend_config
-- ----------------------------
DROP
TABLE
IF
EXISTS
`recommend_config`
;
CREATE
TABLE
`recommend_config`
(
`id`
bigint
(
20
)
NOT
NULL
AUTO_INCREMENT
COMMENT
'主键'
,
`course_id`
bigint
(
20
)
DEFAULT
NULL
COMMENT
'课程ID'
,
`sort_no`
int
(
11
)
DEFAULT
NULL
COMMENT
'排序号'
,
`create_time`
datetime
DEFAULT
NULL
,
`update_time`
datetime
DEFAULT
NULL
,
PRIMARY
KEY
(
`id`
)
)
ENGINE
=
InnoDB
DEFAULT
CHARSET
=
utf8mb4
COMMENT
=
'推荐课程配置'
;
-- ----------------------------
-- Table structure for resource
-- ----------------------------
DROP
TABLE
IF
EXISTS
`resource`
;
CREATE
TABLE
`resource`
(
`id`
bigint
(
20
)
NOT
NULL
AUTO_INCREMENT
COMMENT
'主键'
,
`oss_id`
varchar
(
255
)
DEFAULT
NULL
COMMENT
'第三方存储ID'
,
`status`
varchar
(
20
)
DEFAULT
NULL
COMMENT
'状态(待上传、上传失败、上传成功)'
,
`size`
float
DEFAULT
NULL
COMMENT
'资源大小'
,
`video_duration`
float
DEFAULT
NULL
COMMENT
'视频时长'
,
`url`
varchar
(
255
)
DEFAULT
NULL
COMMENT
'访问url'
,
`name`
varchar
(
255
)
DEFAULT
NULL
COMMENT
'名称'
,
`create_time`
datetime
DEFAULT
NULL
,
`update_time`
datetime
DEFAULT
NULL
,
PRIMARY
KEY
(
`id`
)
)
ENGINE
=
InnoDB
DEFAULT
CHARSET
=
utf8mb4
COMMENT
=
'资源'
;
-- ----------------------------
-- Table structure for swiper_config
-- ----------------------------
DROP
TABLE
IF
EXISTS
`swiper_config`
;
CREATE
TABLE
`swiper_config`
(
`id`
bigint
(
20
)
NOT
NULL
AUTO_INCREMENT
COMMENT
'主键'
,
`image_url`
varchar
(
1000
)
DEFAULT
NULL
COMMENT
'封面图片url'
,
`course_id`
bigint
(
20
)
DEFAULT
NULL
COMMENT
'课程ID'
,
`sort_no`
int
(
11
)
DEFAULT
NULL
COMMENT
'排序号'
,
`create_time`
datetime
DEFAULT
NULL
,
`update_time`
datetime
DEFAULT
NULL
,
PRIMARY
KEY
(
`id`
)
)
ENGINE
=
InnoDB
DEFAULT
CHARSET
=
utf8mb4
COMMENT
=
'轮播图配置'
;
-- ----------------------------
-- Table structure for sys_log
-- ----------------------------
DROP
TABLE
IF
EXISTS
`sys_log`
;
CREATE
TABLE
`sys_log`
(
`id`
bigint
(
20
)
NOT
NULL
AUTO_INCREMENT
COMMENT
'主键'
,
`username`
varchar
(
20
)
DEFAULT
NULL
COMMENT
'用户名'
,
`operation`
varchar
(
255
)
DEFAULT
NULL
COMMENT
'用户操作'
,
`method`
varchar
(
255
)
DEFAULT
NULL
COMMENT
'请求方法'
,
`params`
text
COMMENT
'请求参数'
,
`time`
bigint
(
20
)
DEFAULT
NULL
COMMENT
'执行时长(毫秒)'
,
`ip`
varchar
(
64
)
DEFAULT
NULL
COMMENT
'IP地址'
,
`create_time`
datetime
DEFAULT
NULL
,
`update_time`
datetime
DEFAULT
NULL
,
PRIMARY
KEY
(
`id`
)
)
ENGINE
=
InnoDB
DEFAULT
CHARSET
=
utf8mb4
COMMENT
=
'系统操作日志'
;
-- ----------------------------
-- Table structure for sys_menu
-- ----------------------------
DROP
TABLE
IF
EXISTS
`sys_menu`
;
CREATE
TABLE
`sys_menu`
(
`id`
bigint
(
20
)
NOT
NULL
AUTO_INCREMENT
,
`parent_id`
bigint
(
20
)
DEFAULT
NULL
COMMENT
'父菜单ID,一级菜单为0'
,
`name`
varchar
(
50
)
COLLATE
utf8mb4_bin
DEFAULT
NULL
COMMENT
'菜单名称'
,
`url`
varchar
(
200
)
COLLATE
utf8mb4_bin
DEFAULT
NULL
COMMENT
'菜单URL'
,
`perms`
varchar
(
500
)
COLLATE
utf8mb4_bin
DEFAULT
NULL
COMMENT
'授权(多个用逗号分隔,如:user:list,user:create)'
,
`type`
int
(
11
)
DEFAULT
NULL
COMMENT
'类型 0:目录 1:菜单 2:按钮'
,
`icon`
varchar
(
50
)
COLLATE
utf8mb4_bin
DEFAULT
NULL
COMMENT
'菜单图标'
,
`order_num`
int
(
11
)
DEFAULT
NULL
COMMENT
'排序'
,
`create_time`
datetime
DEFAULT
NULL
,
`update_time`
datetime
DEFAULT
NULL
,
PRIMARY
KEY
(
`id`
)
USING
BTREE
)
ENGINE
=
InnoDB
AUTO_INCREMENT
=
108
DEFAULT
CHARSET
=
utf8mb4
COLLATE
=
utf8mb4_bin
ROW_FORMAT
=
DYNAMIC
COMMENT
=
'菜单管理'
;
-- ----------------------------
-- Table structure for sys_role
-- ----------------------------
DROP
TABLE
IF
EXISTS
`sys_role`
;
CREATE
TABLE
`sys_role`
(
`id`
bigint
(
20
)
NOT
NULL
AUTO_INCREMENT
COMMENT
'主键'
,
`code`
varchar
(
20
)
DEFAULT
NULL
COMMENT
'角色代码'
,
`name`
varchar
(
100
)
DEFAULT
NULL
COMMENT
'角色名称'
,
`create_time`
datetime
DEFAULT
NULL
COMMENT
'创建时间'
,
`update_time`
datetime
DEFAULT
NULL
COMMENT
'修改时间'
,
PRIMARY
KEY
(
`id`
)
)
ENGINE
=
InnoDB
AUTO_INCREMENT
=
6
DEFAULT
CHARSET
=
utf8mb4
COMMENT
=
'角色表'
;
-- ----------------------------
-- Records of sys_role
-- ----------------------------
INSERT
INTO
`sys_role`
VALUES
(
1
,
'ADMIN'
,
'系统管理员'
,
'2021-04-25 16:10:06'
,
'2021-04-25 16:10:06'
);
INSERT
INTO
`sys_role`
VALUES
(
2
,
'OPERATOR'
,
'运营人员'
,
'2021-04-25 16:10:06'
,
'2021-04-25 16:10:06'
);
INSERT
INTO
`sys_role`
VALUES
(
3
,
'ENTERPRISE_ADMIN'
,
'企业管理员'
,
'2021-04-25 16:10:06'
,
'2021-04-25 16:10:06'
);
INSERT
INTO
`sys_role`
VALUES
(
4
,
'INSTITUTION_ADMIN'
,
'培训机构管理员'
,
'2021-04-25 16:10:06'
,
'2021-04-25 16:10:06'
);
INSERT
INTO
`sys_role`
VALUES
(
5
,
'USER'
,
'普通用户'
,
'2021-04-25 16:10:06'
,
'2021-04-25 16:10:06'
);
-- ----------------------------
-- Table structure for sys_role_menu
-- ----------------------------
DROP
TABLE
IF
EXISTS
`sys_role_menu`
;
CREATE
TABLE
`sys_role_menu`
(
`id`
bigint
(
20
)
NOT
NULL
AUTO_INCREMENT
,
`role_id`
bigint
(
20
)
DEFAULT
NULL
COMMENT
'角色ID'
,
`menu_id`
bigint
(
20
)
DEFAULT
NULL
COMMENT
'菜单ID'
,
PRIMARY
KEY
(
`id`
)
USING
BTREE
)
ENGINE
=
InnoDB
DEFAULT
CHARSET
=
utf8mb4
COLLATE
=
utf8mb4_bin
ROW_FORMAT
=
DYNAMIC
COMMENT
=
'角色与菜单对应关系'
;
-- ----------------------------
-- Table structure for sys_config
-- ----------------------------
DROP
TABLE
IF
EXISTS
`sys_config`
;
CREATE
TABLE
`sys_config`
(
`id`
bigint
(
20
)
NOT
NULL
AUTO_INCREMENT
,
`param_key`
varchar
(
50
)
COLLATE
utf8mb4_bin
DEFAULT
NULL
COMMENT
'key'
,
`param_value`
varchar
(
2000
)
COLLATE
utf8mb4_bin
DEFAULT
NULL
COMMENT
'value'
,
`status`
tinyint
(
4
)
DEFAULT
'1'
COMMENT
'状态 0:隐藏 1:显示'
,
`remark`
varchar
(
500
)
COLLATE
utf8mb4_bin
DEFAULT
NULL
COMMENT
'备注'
,
`create_time`
datetime
DEFAULT
NULL
,
`update_time`
datetime
DEFAULT
NULL
,
PRIMARY
KEY
(
`id`
)
USING
BTREE
,
UNIQUE
KEY
`param_key`
(
`param_key`
)
USING
BTREE
)
ENGINE
=
InnoDB
DEFAULT
CHARSET
=
utf8mb4
COLLATE
=
utf8mb4_bin
ROW_FORMAT
=
DYNAMIC
COMMENT
=
'系统配置信息表'
;
-- ----------------------------
-- Table structure for sys_user
-- ----------------------------
DROP
TABLE
IF
EXISTS
`sys_user`
;
CREATE
TABLE
`sys_user`
(
`id`
bigint
(
20
)
NOT
NULL
AUTO_INCREMENT
COMMENT
'主键'
,
`username`
varchar
(
20
)
NOT
NULL
COMMENT
'手机号'
,
`password`
varchar
(
100
)
DEFAULT
NULL
COMMENT
'密码'
,
`salt`
varchar
(
20
)
DEFAULT
NULL
COMMENT
'盐'
,
`nick_name`
varchar
(
50
)
DEFAULT
NULL
COMMENT
'昵称'
,
`status`
tinyint
(
1
)
DEFAULT
NULL
COMMENT
'状态'
,
`create_time`
datetime
DEFAULT
NULL
COMMENT
'注册时间'
,
`last_login_time`
datetime
DEFAULT
NULL
COMMENT
'最后登录时间'
,
`activate_time`
datetime
DEFAULT
NULL
COMMENT
'激活时间'
,
`update_time`
datetime
DEFAULT
NULL
COMMENT
'修改时间'
,
`is_del`
tinyint
(
1
)
DEFAULT
NULL
COMMENT
'删除标识'
,
PRIMARY
KEY
(
`id`
)
)
ENGINE
=
InnoDB
AUTO_INCREMENT
=
2
DEFAULT
CHARSET
=
utf8mb4
COMMENT
=
'用户表'
;
-- ----------------------------
-- Records of sys_user
-- ----------------------------
INSERT
INTO
`sys_user`
VALUES
(
1
,
'13100000000'
,
'cdac762d0ba79875489f6a8b430fa8b5dfe0cdd81da38b80f02f33328af7fd4a'
,
'YzcmCZNvbXocrsz9dm8e'
,
'系管理员'
,
1
,
'2021-04-25 16:10:06'
,
NULL
,
NULL
,
'2021-04-25 16:10:06'
,
0
);
-- ----------------------------
-- Table structure for sys_user_role
-- ----------------------------
DROP
TABLE
IF
EXISTS
`sys_user_role`
;
CREATE
TABLE
`sys_user_role`
(
`id`
bigint
(
20
)
NOT
NULL
AUTO_INCREMENT
COMMENT
'主键'
,
`user_id`
bigint
(
20
)
NOT
NULL
COMMENT
'用户ID'
,
`role_id`
bigint
(
20
)
NOT
NULL
COMMENT
'角色ID'
,
PRIMARY
KEY
(
`id`
)
)
ENGINE
=
InnoDB
AUTO_INCREMENT
=
2
DEFAULT
CHARSET
=
utf8mb4
COMMENT
=
'用户角色关联表'
;
-- ----------------------------
-- Table structure for teacher
-- ----------------------------
DROP
TABLE
IF
EXISTS
`teacher`
;
CREATE
TABLE
`teacher`
(
`id`
bigint
(
20
)
NOT
NULL
AUTO_INCREMENT
COMMENT
'主键'
,
`code`
varchar
(
100
)
DEFAULT
NULL
COMMENT
'编号'
,
`name`
varchar
(
20
)
DEFAULT
NULL
COMMENT
'姓名'
,
`mobile`
varchar
(
20
)
DEFAULT
NULL
COMMENT
'电话'
,
`org_id`
bigint
(
20
)
DEFAULT
NULL
COMMENT
'所属机构ID'
,
`introduce`
text
COMMENT
'简介'
,
`avatar_url`
varchar
(
1000
)
DEFAULT
NULL
COMMENT
'头像'
,
`create_time`
datetime
DEFAULT
NULL
COMMENT
'创建时间'
,
`update_time`
datetime
DEFAULT
NULL
COMMENT
'更新时间'
,
`is_del`
tinyint
(
1
)
DEFAULT
NULL
COMMENT
'删除标识'
,
PRIMARY
KEY
(
`id`
)
)
ENGINE
=
InnoDB
DEFAULT
CHARSET
=
utf8mb4
COMMENT
=
'讲师'
;
-- ----------------------------
-- Table structure for user_ext
-- ----------------------------
DROP
TABLE
IF
EXISTS
`user_ext`
;
CREATE
TABLE
`user_ext`
(
`id`
bigint
(
20
)
NOT
NULL
AUTO_INCREMENT
COMMENT
'主键'
,
`user_id`
bigint
(
20
)
DEFAULT
NULL
COMMENT
'用户ID'
,
`name`
varchar
(
20
)
DEFAULT
NULL
COMMENT
'姓名'
,
`sex`
varchar
(
10
)
DEFAULT
NULL
COMMENT
'性别'
,
`age`
int
(
10
)
DEFAULT
NULL
COMMENT
'年龄'
,
`avatar_url`
varchar
(
1000
)
DEFAULT
NULL
COMMENT
'头像url'
,
`type`
varchar
(
20
)
DEFAULT
NULL
COMMENT
'用户类型(普通用户、会员、企业会员)'
,
`enterprise_id`
bigint
(
20
)
DEFAULT
NULL
COMMENT
'企业ID'
,
`vip_start_time`
datetime
DEFAULT
NULL
COMMENT
'会员生效时间'
,
`vip_end_time`
datetime
DEFAULT
NULL
COMMENT
'会员结束时间'
,
`create_time`
datetime
DEFAULT
NULL
COMMENT
'创建时间'
,
`update_time`
datetime
DEFAULT
NULL
COMMENT
'更新时间'
,
PRIMARY
KEY
(
`id`
)
)
ENGINE
=
InnoDB
AUTO_INCREMENT
=
2
DEFAULT
CHARSET
=
utf8mb4
COMMENT
=
'用户扩展表'
;
-- ----------------------------
-- Records of user_ext
-- ----------------------------
INSERT
INTO
`user_ext`
VALUES
(
1
,
1
,
'系统管理员'
,
NULL
,
NULL
,
NULL
,
NULL
,
NULL
,
NULL
,
NULL
,
'2021-04-25 16:10:06'
,
'2021-04-25 16:10:06'
);
-- ----------------------------
-- Table structure for user_favorites
-- ----------------------------
DROP
TABLE
IF
EXISTS
`user_favorites`
;
CREATE
TABLE
`user_favorites`
(
`id`
bigint
(
20
)
NOT
NULL
AUTO_INCREMENT
COMMENT
'主键'
,
`user_id`
bigint
(
10
)
DEFAULT
NULL
COMMENT
'用户ID'
,
`course_id`
bigint
(
20
)
DEFAULT
NULL
COMMENT
'课程ID'
,
`create_time`
datetime
DEFAULT
NULL
COMMENT
'创建时间'
,
`update_time`
datetime
DEFAULT
NULL
,
PRIMARY
KEY
(
`id`
)
)
ENGINE
=
InnoDB
DEFAULT
CHARSET
=
utf8mb4
COMMENT
=
'用户收藏课程'
;
-- ----------------------------
-- Table structure for user_get_vip_record
-- ----------------------------
DROP
TABLE
IF
EXISTS
`user_get_vip_record`
;
CREATE
TABLE
`user_get_vip_record`
(
`id`
bigint
(
20
)
NOT
NULL
AUTO_INCREMENT
COMMENT
'主键'
,
`create_time`
datetime
DEFAULT
NULL
COMMENT
'领取时间'
,
`update_time`
datetime
DEFAULT
NULL
,
`user_id`
bigint
(
20
)
DEFAULT
NULL
COMMENT
'用户ID'
,
`type`
varchar
(
20
)
DEFAULT
NULL
COMMENT
'领取类型(月卡、付费点播课程)'
,
`course_id`
bigint
(
20
)
DEFAULT
NULL
COMMENT
'课程ID'
,
`org_id`
bigint
(
20
)
DEFAULT
NULL
COMMENT
'企业ID'
,
PRIMARY
KEY
(
`id`
)
)
ENGINE
=
InnoDB
DEFAULT
CHARSET
=
utf8mb4
COMMENT
=
'企业会员领取记录'
;
src/main/resources/logback-spring.xml
0 → 100644
View file @
7bbe84e0
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<springProperty
scope=
"context"
name=
"LOG_PATH"
source=
"log.path"
/>
<springProperty
scope=
"context"
name=
"LOG_CONTEXT"
source=
"log.context"
/>
<property
name=
"PATTERN"
value=
"[%d{yyyy-MM-dd HH:mm:ss.SSS}] [%thread] [%X{traceId}] %-5level %logger{50} - %line %msg %n"
/>
<appender
name=
"console"
class=
"ch.qos.logback.core.ConsoleAppender"
>
<encoder>
<pattern>
${PATTERN}
</pattern>
<charset>
UTF-8
</charset>
</encoder>
</appender>
<appender
name=
"rollingFile"
class=
"ch.qos.logback.core.rolling.RollingFileAppender"
>
<File>
${LOG_PATH}/${LOG_CONTEXT}.log
</File>
<rollingPolicy
class=
"ch.qos.logback.core.rolling.TimeBasedRollingPolicy"
>
<fileNamePattern>
${LOG_PATH}/${LOG_CONTEXT}.log.%i.%d{yyyy-MM-dd}
</fileNamePattern>
<maxHistory>
30
</maxHistory>
<TimeBasedFileNamingAndTriggeringPolicy
class=
"ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP"
>
<maxFileSize>
30MB
</maxFileSize>
</TimeBasedFileNamingAndTriggeringPolicy>
</rollingPolicy>
<encoder>
<Pattern>
${PATTERN}
</Pattern>
<charset>
UTF-8
</charset>
</encoder>
</appender>
<appender
name=
"sql"
class=
"ch.qos.logback.core.rolling.RollingFileAppender"
>
<File>
${LOG_PATH}/${LOG_CONTEXT}-sql.log
</File>
<rollingPolicy
class=
"ch.qos.logback.core.rolling.TimeBasedRollingPolicy"
>
<fileNamePattern>
${LOG_PATH}/${LOG_CONTEXT}-sql.log.%i.%d{yyyy-MM-dd}
</fileNamePattern>
<maxHistory>
30
</maxHistory>
<TimeBasedFileNamingAndTriggeringPolicy
class=
"ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP"
>
<maxFileSize>
30MB
</maxFileSize>
</TimeBasedFileNamingAndTriggeringPolicy>
</rollingPolicy>
<encoder>
<Pattern>
${PATTERN}
</Pattern>
<charset>
UTF-8
</charset>
</encoder>
</appender>
<logger
name=
"com.qkdata"
level=
"DEBUG"
/>
<!-- <logger name="com.qkdata.biz.sys.repository" level="ERROR" additivity="false">-->
<!-- <appender-ref ref="sql" />-->
<!-- </logger>-->
<root
level=
"INFO"
>
<appender-ref
ref=
"console"
/>
<appender-ref
ref=
"rollingFile"
/>
</root>
</configuration>
\ No newline at end of file
src/main/resources/mappers/SysConfigMapper.xml
0 → 100644
View file @
7bbe84e0
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper
namespace=
"com.qkdata.biz.sys.mapper.SysConfigMapper"
>
<select
id=
"queryPageList"
resultType=
"com.qkdata.biz.sys.entity.SysConfigPO"
>
select * from sys_config where 1=1
<if
test=
"p.paramKey != null and p.paramKey != ''"
>
and param_key like concat('%',#{p.paramKey},'%')
</if>
</select>
</mapper>
\ No newline at end of file
src/main/resources/mappers/SysLogMapper.xml
0 → 100644
View file @
7bbe84e0
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper
namespace=
"com.qkdata.biz.sys.mapper.SysLogMapper"
>
<select
id=
"queryPageList"
resultType=
"com.qkdata.biz.sys.entity.SysLogPO"
>
select * from sys_log where 1=1
<if
test=
"p.condition != null and p.condition != ''"
>
and username like concat('%',#{p.condition},'%') or operation like concat('%',#{p.condition},'%')
</if>
order by create_time desc
</select>
</mapper>
\ No newline at end of file
src/main/resources/mappers/SysMenuMapper.xml
0 → 100644
View file @
7bbe84e0
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper
namespace=
"com.qkdata.biz.sys.mapper.SysMenuMapper"
>
<select
id=
"queryNotButtonList"
resultType=
"com.qkdata.biz.sys.entity.SysMenuPO"
>
select * from sys_menu where type != 2 order by order_num asc
</select>
</mapper>
\ No newline at end of file
src/main/resources/mappers/SysRoleMapper.xml
0 → 100644
View file @
7bbe84e0
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper
namespace=
"com.qkdata.biz.sys.mapper.SysRoleMapper"
>
<select
id=
"queryPageList"
resultType=
"com.qkdata.biz.sys.entity.SysRolePO"
>
select *
from sys_role
where 1=1
<if
test=
"p.name != null and p.name != ''"
>
and name like concat('%',#{p.name},'%')
</if>
order by id desc
</select>
</mapper>
\ No newline at end of file
src/main/resources/mappers/SysRoleMenuMapper.xml
0 → 100644
View file @
7bbe84e0
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper
namespace=
"com.qkdata.biz.sys.mapper.SysRoleMenuMapper"
>
<select
id=
"selectMenuIdsByRoleId"
resultType=
"java.lang.Long"
>
select menu_id from sys_role_menu where role_id = #{roleId}
</select>
</mapper>
\ No newline at end of file
src/main/resources/mappers/SysUserMapper.xml
0 → 100644
View file @
7bbe84e0
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper
namespace=
"com.qkdata.biz.sys.mapper.SysUserMapper"
>
<select
id=
"queryAllPerms"
resultType=
"java.lang.String"
>
select m.perms from sys_user_role ur
LEFT JOIN sys_role_menu rm on ur.role_id = rm.role_id
LEFT JOIN sys_menu m on rm.menu_id = m.id
where ur.user_id = #{userId}
</select>
<select
id=
"queryPageList"
resultType=
"com.qkdata.biz.sys.vo.SysUserModel"
>
select id,username,email,mobile,status
from sys_user
where 1=1
<if
test=
"p.username != null and p.username != ''"
>
and username like concat('%',#{p.username},'%')
</if>
order by create_time desc
</select>
<select
id=
"queryAllMenuId"
resultType=
"java.lang.Long"
>
select distinct rm.menu_id from sys_user_role ur
LEFT JOIN sys_role_menu rm on ur.role_id = rm.role_id
where ur.user_id = #{userId}
</select>
</mapper>
\ No newline at end of file
src/main/resources/mappers/SysUserRoleMapper.xml
0 → 100644
View file @
7bbe84e0
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper
namespace=
"com.qkdata.biz.sys.mapper.SysUserRoleMapper"
>
<select
id=
"queryRoleIdList"
resultType=
"java.lang.Long"
>
select role_id from sys_user_role where user_id = #{userId}
</select>
</mapper>
\ No newline at end of file
src/test/java/com/qkdata/autogenerator/CodeGenerator.java
0 → 100644
View file @
7bbe84e0
package
com
.
qkdata
.
autogenerator
;
import
cn.hutool.core.util.ArrayUtil
;
import
com.baomidou.mybatisplus.core.exceptions.MybatisPlusException
;
import
com.baomidou.mybatisplus.core.toolkit.StringPool
;
import
com.baomidou.mybatisplus.core.toolkit.StringUtils
;
import
com.baomidou.mybatisplus.generator.AutoGenerator
;
import
com.baomidou.mybatisplus.generator.InjectionConfig
;
import
com.baomidou.mybatisplus.generator.config.*
;
import
com.baomidou.mybatisplus.generator.config.po.TableInfo
;
import
com.baomidou.mybatisplus.generator.config.rules.NamingStrategy
;
import
com.baomidou.mybatisplus.generator.engine.FreemarkerTemplateEngine
;
import
java.util.ArrayList
;
import
java.util.List
;
import
java.util.Scanner
;
public
class
CodeGenerator
{
/**
* <p>
* 读取控制台内容
* </p>
*/
public
static
String
scanner
(
String
tip
)
{
Scanner
scanner
=
new
Scanner
(
System
.
in
);
StringBuilder
help
=
new
StringBuilder
();
help
.
append
(
"请输入"
+
tip
+
":"
);
System
.
out
.
println
(
help
.
toString
());
if
(
scanner
.
hasNext
())
{
String
ipt
=
scanner
.
next
();
if
(
StringUtils
.
isNotBlank
(
ipt
))
{
return
ipt
;
}
}
throw
new
MybatisPlusException
(
"请输入正确的"
+
tip
+
"!"
);
}
public
static
void
main
(
String
[]
args
)
{
// 代码生成器
AutoGenerator
mpg
=
new
AutoGenerator
();
// 全局配置
GlobalConfig
gc
=
new
GlobalConfig
();
String
projectPath
=
System
.
getProperty
(
"user.dir"
);
gc
.
setOutputDir
(
projectPath
+
"/src/main/java"
);
gc
.
setAuthor
(
"liuyang"
);
gc
.
setOpen
(
false
);
gc
.
setEntityName
(
"%sPO"
);
gc
.
setServiceName
(
"%sService"
);
// gc.setSwagger2(true); 实体属性 Swagger2 注解
mpg
.
setGlobalConfig
(
gc
);
// 数据源配置
DataSourceConfig
dsc
=
new
DataSourceConfig
();
dsc
.
setUrl
(
"jdbc:mysql://localhost:3306/online-edu?useUnicode=true&useSSL=false&characterEncoding=utf8"
);
// dsc.setSchemaName("public");
dsc
.
setDriverName
(
"com.mysql.jdbc.Driver"
);
dsc
.
setUsername
(
"root"
);
dsc
.
setPassword
(
"123456"
);
mpg
.
setDataSource
(
dsc
);
// 包配置
PackageConfig
pc
=
new
PackageConfig
();
pc
.
setModuleName
(
scanner
(
"模块名"
));
pc
.
setParent
(
"com.qkdata.biz"
);
mpg
.
setPackageInfo
(
pc
);
// 自定义配置
InjectionConfig
cfg
=
new
InjectionConfig
()
{
@Override
public
void
initMap
()
{
}
};
// 如果模板引擎是 freemarker
String
templatePath
=
"/templates/mapper.xml.ftl"
;
// 如果模板引擎是 velocity
// String templatePath = "/templates/mapper.xml.vm";
String
serviceTemplatePath
=
"/templates/ftl/Service.java.ftl"
;
// 自定义输出配置
List
<
FileOutConfig
>
focList
=
new
ArrayList
<>();
// 自定义配置会被优先输出
focList
.
add
(
new
FileOutConfig
(
templatePath
)
{
@Override
public
String
outputFile
(
TableInfo
tableInfo
)
{
// 自定义输出文件名 , 如果你 Entity 设置了前后缀、此处注意 xml 的名称会跟着发生变化!!
return
projectPath
+
"/src/main/resources/mappers/"
+
pc
.
getModuleName
()
+
"/"
+
tableInfo
.
getEntityName
()
+
"Mapper"
+
StringPool
.
DOT_XML
;
}
});
focList
.
add
(
new
FileOutConfig
(
serviceTemplatePath
)
{
@Override
public
String
outputFile
(
TableInfo
tableInfo
)
{
// 自定义输出文件名 , 如果你 Entity 设置了前后缀、此处注意 xml 的名称会跟着发生变化!!
return
projectPath
+
"src/main/java/"
+
pc
.
getModuleName
()
+
"/service/"
+
tableInfo
.
getEntityName
()
+
"Service"
+
StringPool
.
DOT_JAVA
;
}
});
/*
cfg.setFileCreate(new IFileCreate() {
@Override
public boolean isCreate(ConfigBuilder configBuilder, FileType fileType, String filePath) {
// 判断自定义文件夹是否需要创建
checkDir("调用默认方法创建的目录,自定义目录用");
if (fileType == FileType.MAPPER) {
// 已经生成 mapper 文件判断存在,不想重新生成返回 false
return !new File(filePath).exists();
}
// 允许生成模板文件
return true;
}
});
*/
cfg
.
setFileOutConfigList
(
focList
);
mpg
.
setCfg
(
cfg
);
// 配置模板
TemplateConfig
templateConfig
=
new
TemplateConfig
();
// 配置自定义输出模板
//指定自定义模板路径,注意不要带上.ftl/.vm, 会根据使用的模板引擎自动识别
// templateConfig.setEntity("templates/entity2.java");
templateConfig
.
setService
(
"templates/ftl/Service.java"
);
templateConfig
.
setServiceImpl
(
null
);
// templateConfig.setController();
templateConfig
.
setXml
(
null
);
mpg
.
setTemplate
(
templateConfig
);
// 策略配置
StrategyConfig
strategy
=
new
StrategyConfig
();
strategy
.
setNaming
(
NamingStrategy
.
underline_to_camel
);
strategy
.
setColumnNaming
(
NamingStrategy
.
underline_to_camel
);
strategy
.
setSuperEntityClass
(
"com.qkdata.common.base.entity.BasePO"
);
strategy
.
setEntityLombokModel
(
true
);
strategy
.
setRestControllerStyle
(
true
);
// 公共父类
// strategy.setSuperControllerClass("你自己的父类控制器,没有就不用设置!");
// 写于父类中的公共字段
strategy
.
setSuperEntityColumns
(
"id"
,
"create_time"
,
"update_time"
);
strategy
.
setInclude
(
scanner
(
"表名,多个英文逗号分割"
).
split
(
","
));
strategy
.
setControllerMappingHyphenStyle
(
true
);
strategy
.
setSuperServiceImplClass
(
"com.qkdata.common.base.service.impl.BaseServiceImpl"
);
// strategy.setTablePrefix(pc.getModuleName() + "_");
mpg
.
setStrategy
(
strategy
);
mpg
.
setTemplateEngine
(
new
FreemarkerTemplateEngine
());
mpg
.
execute
();
}
}
src/test/java/com/qkdata/test/BaseTest.java
0 → 100644
View file @
7bbe84e0
package
com
.
qkdata
.
test
;
import
com.qkdata.Application
;
import
org.junit.runner.RunWith
;
import
org.springframework.boot.test.context.SpringBootTest
;
import
org.springframework.test.context.ActiveProfiles
;
import
org.springframework.test.context.junit4.SpringRunner
;
@RunWith
(
SpringRunner
.
class
)
@SpringBootTest
(
classes
=
Application
.
class
,
webEnvironment
=
SpringBootTest
.
WebEnvironment
.
RANDOM_PORT
)
@ActiveProfiles
(
value
=
"dev"
)
public
class
BaseTest
{
}
src/test/resources/templates/ftl/Service.java.ftl
0 → 100644
View file @
7bbe84e0
package
${
package
.
Service
};
import
${
package
.
Entity
}.${
entity
};
import
${
package
.
Mapper
}.${
table
.
mapperName
};
import
${
superServiceImplClassPackage
};
import
org
.
springframework
.
stereotype
.
Service
;
/**
*
<
p
>
*
$
!{table.comment} 服务类
*
</
p
>
*
*
@
author
${
author
}
*
@
since
${
date
}
*/
@
Service
public
class
${
table
.
serviceName
}
extends
${
superServiceImplClass
}<${
table
.
mapperName
},
${
entity
}>
{
}
\ No newline at end of file
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment