Skip to content
Projects
Groups
Snippets
Help
Loading...
Sign in
Toggle navigation
B
backend-java
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
other-project
backend-java
Commits
7409526c
Commit
7409526c
authored
Jan 16, 2020
by
liuyang
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
init project
parents
Hide whitespace changes
Inline
Side-by-side
Showing
98 changed files
with
4545 additions
and
0 deletions
+4545
-0
.gitignore
.gitignore
+132
-0
pom.xml
pom.xml
+324
-0
Dockerfile
src/main/docker/Dockerfile
+21
-0
docker-entrypoint.sh
src/main/docker/docker-entrypoint.sh
+3
-0
Application.java
src/main/java/com/qkdata/Application.java
+24
-0
Constants.java
src/main/java/com/qkdata/biz/base/constants/Constants.java
+9
-0
ResultEnum.java
src/main/java/com/qkdata/biz/base/constants/ResultEnum.java
+34
-0
AccountStatusEnum.java
...ain/java/com/qkdata/biz/base/enums/AccountStatusEnum.java
+27
-0
MenuTypeEnum.java
src/main/java/com/qkdata/biz/base/enums/MenuTypeEnum.java
+23
-0
SysConfigStatusEnum.java
...n/java/com/qkdata/biz/base/enums/SysConfigStatusEnum.java
+27
-0
SysLoginController.java
...ava/com/qkdata/biz/sys/controller/SysLoginController.java
+33
-0
UserController.java
...in/java/com/qkdata/biz/sys/controller/UserController.java
+25
-0
SysConfigPO.java
src/main/java/com/qkdata/biz/sys/entity/SysConfigPO.java
+18
-0
SysMenuPO.java
src/main/java/com/qkdata/biz/sys/entity/SysMenuPO.java
+20
-0
SysOssPO.java
src/main/java/com/qkdata/biz/sys/entity/SysOssPO.java
+13
-0
SysRoleMenuPO.java
src/main/java/com/qkdata/biz/sys/entity/SysRoleMenuPO.java
+13
-0
SysRolePO.java
src/main/java/com/qkdata/biz/sys/entity/SysRolePO.java
+13
-0
SysUserPO.java
src/main/java/com/qkdata/biz/sys/entity/SysUserPO.java
+28
-0
SysUserRolePO.java
src/main/java/com/qkdata/biz/sys/entity/SysUserRolePO.java
+13
-0
LoginModel.java
src/main/java/com/qkdata/biz/sys/model/LoginModel.java
+13
-0
LoginUserInfo.java
src/main/java/com/qkdata/biz/sys/model/LoginUserInfo.java
+12
-0
SysConfigMapper.java
...n/java/com/qkdata/biz/sys/repository/SysConfigMapper.java
+7
-0
SysMenuMapper.java
...ain/java/com/qkdata/biz/sys/repository/SysMenuMapper.java
+7
-0
SysOssMapper.java
...main/java/com/qkdata/biz/sys/repository/SysOssMapper.java
+7
-0
SysRoleMapper.java
...ain/java/com/qkdata/biz/sys/repository/SysRoleMapper.java
+7
-0
SysRoleMenuMapper.java
...java/com/qkdata/biz/sys/repository/SysRoleMenuMapper.java
+7
-0
SysUserMapper.java
...ain/java/com/qkdata/biz/sys/repository/SysUserMapper.java
+10
-0
SysUserRoleMapper.java
...java/com/qkdata/biz/sys/repository/SysUserRoleMapper.java
+7
-0
ShiroService.java
src/main/java/com/qkdata/biz/sys/service/ShiroService.java
+95
-0
WSMessageController.java
...ava/com/qkdata/biz/wsMessage/api/WSMessageController.java
+25
-0
MyPrincipal.java
...ain/java/com/qkdata/biz/wsMessage/config/MyPrincipal.java
+14
-0
WebSocketConfig.java
...java/com/qkdata/biz/wsMessage/config/WebSocketConfig.java
+130
-0
WxLoginMsg.java
src/main/java/com/qkdata/biz/wsMessage/model/WxLoginMsg.java
+12
-0
WSMessageService.java
...va/com/qkdata/biz/wsMessage/service/WSMessageService.java
+24
-0
BasePO.java
src/main/java/com/qkdata/common/base/entity/BasePO.java
+29
-0
BasePOEnum.java
src/main/java/com/qkdata/common/base/enums/BasePOEnum.java
+75
-0
BaseResponseEnum.java
...n/java/com/qkdata/common/base/enums/BaseResponseEnum.java
+8
-0
DeletedEnum.java
src/main/java/com/qkdata/common/base/enums/DeletedEnum.java
+31
-0
SystemResponseEnum.java
...java/com/qkdata/common/base/enums/SystemResponseEnum.java
+32
-0
BusinessException.java
...a/com/qkdata/common/base/exception/BusinessException.java
+46
-0
IdDTO.java
src/main/java/com/qkdata/common/base/model/IdDTO.java
+23
-0
PageDTO.java
src/main/java/com/qkdata/common/base/model/PageDTO.java
+44
-0
ResponseData.java
src/main/java/com/qkdata/common/base/model/ResponseData.java
+40
-0
BaseService.java
...main/java/com/qkdata/common/base/service/BaseService.java
+56
-0
BaseServiceImpl.java
.../com/qkdata/common/base/service/impl/BaseServiceImpl.java
+47
-0
CustomEnumTypeHandler.java
.../java/com/qkdata/common/config/CustomEnumTypeHandler.java
+78
-0
FilterConfig.java
src/main/java/com/qkdata/common/config/FilterConfig.java
+25
-0
GlobalExceptionHandle.java
.../java/com/qkdata/common/config/GlobalExceptionHandle.java
+104
-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
RedisConfig.java
src/main/java/com/qkdata/common/config/RedisConfig.java
+102
-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
+47
-0
WebMvcConfiguration.java
...in/java/com/qkdata/common/config/WebMvcConfiguration.java
+70
-0
DateTimeFormatterPattern.java
...com/qkdata/common/constants/DateTimeFormatterPattern.java
+11
-0
Page.java
src/main/java/com/qkdata/common/constants/Page.java
+18
-0
ValidatorPattern.java
...in/java/com/qkdata/common/constants/ValidatorPattern.java
+8
-0
LocalDateDeserializer.java
...va/com/qkdata/common/converter/LocalDateDeserializer.java
+33
-0
LocalDateSerializer.java
...java/com/qkdata/common/converter/LocalDateSerializer.java
+24
-0
LocalDateTimeDeserializer.java
...om/qkdata/common/converter/LocalDateTimeDeserializer.java
+34
-0
LocalDateTimeSerializer.java
.../com/qkdata/common/converter/LocalDateTimeSerializer.java
+25
-0
StringToCommonEnumConverterFactory.java
.../common/converter/StringToCommonEnumConverterFactory.java
+35
-0
StringToLocalDateConverter.java
...m/qkdata/common/converter/StringToLocalDateConverter.java
+32
-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
AuthorizationException.java
.../java/com/qkdata/common/oauth/AuthorizationException.java
+24
-0
AuthorizationResponseEnum.java
...va/com/qkdata/common/oauth/AuthorizationResponseEnum.java
+32
-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
+108
-0
OAuthRealm.java
src/main/java/com/qkdata/common/oauth/OAuthRealm.java
+92
-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
Iterables.java
src/main/java/com/qkdata/common/util/Iterables.java
+20
-0
MD5Util.java
src/main/java/com/qkdata/common/util/MD5Util.java
+28
-0
RandomDigitGenerator.java
...ain/java/com/qkdata/common/util/RandomDigitGenerator.java
+46
-0
RequestUtil.java
src/main/java/com/qkdata/common/util/RequestUtil.java
+75
-0
application-dev.yml
src/main/resources/application-dev.yml
+19
-0
application.yml
src/main/resources/application.yml
+76
-0
V1.0.0__init.sql
src/main/resources/db/migration/V1.0.0__init.sql
+158
-0
logback-spring.xml
src/main/resources/logback-spring.xml
+58
-0
SysUserMapper.xml
src/main/resources/mappers/SysUserMapper.xml
+16
-0
index.html
src/main/resources/static/index.html
+83
-0
BaseTest.java
src/test/java/com/qkdata/test/BaseTest.java
+14
-0
No files found.
.gitignore
0 → 100644
View file @
7409526c
# 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 @
7409526c
<?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>
backend-java
</artifactId>
<version>
1.0.0
</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.springboot.version>
1.3.2
</mybatis.springboot.version>
<mybatis.tk.springboot.version>
2.0.4
</mybatis.tk.springboot.version>
<druid.springboot.version>
1.1.10
</druid.springboot.version>
<pagehelper.springboot.version>
1.2.9
</pagehelper.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>
<docker.registry>
fywlsoft.cn:57802
</docker.registry>
<docker.image.prefix>
argus
</docker.image.prefix>
<baidu.aip.version>
4.11.3
</baidu.aip.version>
<shiro.version>
1.4.0
</shiro.version>
<fastjson.version>
1.2.60
</fastjson.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>
<!--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>
org.mybatis.spring.boot
</groupId>
<artifactId>
mybatis-spring-boot-starter
</artifactId>
<version>
${mybatis.springboot.version}
</version>
</dependency>
<dependency>
<groupId>
tk.mybatis
</groupId>
<artifactId>
mapper-spring-boot-starter
</artifactId>
<version>
${mybatis.tk.springboot.version}
</version>
<exclusions>
<exclusion>
<groupId>
com.zaxxer
</groupId>
<artifactId>
HikariCP
</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>
com.alibaba
</groupId>
<artifactId>
druid-spring-boot-starter
</artifactId>
<version>
${druid.springboot.version}
</version>
</dependency>
<dependency>
<groupId>
com.github.pagehelper
</groupId>
<artifactId>
pagehelper-spring-boot-starter
</artifactId>
<version>
${pagehelper.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.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>
org.bouncycastle
</groupId>
<artifactId>
bcprov-jdk15on
</artifactId>
<version>
${org.bouncycastle.version}
</version>
</dependency>
<dependency>
<groupId>
io.springfox
</groupId>
<artifactId>
springfox-swagger2
</artifactId>
<version>
2.4.0
</version>
</dependency>
<dependency>
<groupId>
io.springfox
</groupId>
<artifactId>
springfox-swagger-ui
</artifactId>
<version>
2.4.0
</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>
org.springframework.boot
</groupId>
<artifactId>
spring-boot-maven-plugin
</artifactId>
<version>
2.1.3.RELEASE
</version>
<configuration>
<mainClass>
${start-class}
</mainClass>
<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>
<serverId>
harbor
</serverId>
<registryUrl>
http://${docker.registry}/v2/
</registryUrl>
<imageName>
${docker.image.prefix}/${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>
<execution>
<id>
tag-image
</id>
<phase>
install
</phase>
<goals>
<goal>
tag
</goal>
</goals>
<configuration>
<image>
${docker.image.prefix}/${project.artifactId}:${project.version}
</image>
<newName>
${docker.registry}/${docker.image.prefix}/${project.artifactId}:${project.version}
</newName>
</configuration>
</execution>
<!--<execution>-->
<!--<id>push-image</id>-->
<!--<phase>install</phase>-->
<!--<goals>-->
<!--<goal>push</goal>-->
<!--</goals>-->
<!--<configuration>-->
<!--<imageName>${docker.registry}/${docker.image.prefix}/${project.artifactId}:${project.version}</imageName>-->
<!--</configuration>-->
<!--</execution>-->
<execution>
<id>
remove-image
</id>
<phase>
install
</phase>
<goals>
<goal>
removeImage
</goal>
</goals>
<configuration>
<imageName>
${docker.image.prefix}/${project.artifactId}:${project.version}
</imageName>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
src/main/docker/Dockerfile
0 → 100644
View file @
7409526c
FROM
fywlsoft.cn:57802/library/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
HEALTHCHECK
--timeout=5s --start-period=60s \
CMD curl -f http://localhost/wx-monitor-server/actuator/health || exit 1
src/main/docker/docker-entrypoint.sh
0 → 100644
View file @
7409526c
#!/bin/bash
set
-ex
java
$JAVA_OPTIONS
-jar
app.jar
$OVERRIDE_PROP
src/main/java/com/qkdata/Application.java
0 → 100644
View file @
7409526c
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
tk.mybatis.spring.annotation.MapperScan
;
@SpringBootApplication
@ComponentScan
(
basePackages
=
{
"com.qkdata"
})
@MapperScan
(
"com.qkdata.**.repository"
)
@ServletComponentScan
@EnableCaching
public
class
Application
{
public
static
void
main
(
String
[]
args
)
{
SpringApplication
.
run
(
Application
.
class
,
args
);
}
}
src/main/java/com/qkdata/biz/base/constants/Constants.java
0 → 100644
View file @
7409526c
package
com
.
qkdata
.
biz
.
base
.
constants
;
public
final
class
Constants
{
public
static
final
String
PSAAWORD
=
"123456"
;
}
src/main/java/com/qkdata/biz/base/constants/ResultEnum.java
0 → 100644
View file @
7409526c
package
com
.
qkdata
.
biz
.
base
.
constants
;
import
com.qkdata.common.base.enums.BaseResponseEnum
;
public
enum
ResultEnum
implements
BaseResponseEnum
{
ACCOUNT_OFF
(
"14000"
,
"账号已被禁止登录"
),
TOKEN_TIME_OUT
(
"14001"
,
"登录失效,请重新登录"
),
TOKEN_ERROR
(
"14002"
,
"token验证失败"
),
CAPTCHA_ERROR
(
"14004"
,
"验证码错误"
),
MOBILE_ERROR
(
"14005"
,
"手机号不存在"
),
SMS_ERROR
(
"14007"
,
"短信发送失败"
),
ACCOUNT_NOT_EXIST
(
"14008"
,
"帐号不存在"
),
PWD_ERROR
(
"14009"
,
"密码错误"
);
private
String
value
;
private
String
text
;
ResultEnum
(
String
value
,
String
text
)
{
this
.
value
=
value
;
this
.
text
=
text
;
}
public
String
value
()
{
return
value
;
}
public
String
text
()
{
return
text
;
}
}
src/main/java/com/qkdata/biz/base/enums/AccountStatusEnum.java
0 → 100644
View file @
7409526c
package
com
.
qkdata
.
biz
.
base
.
enums
;
import
com.fasterxml.jackson.annotation.JsonCreator
;
import
com.qkdata.common.base.enums.BasePOEnum
;
public
enum
AccountStatusEnum
implements
BasePOEnum
{
DISABLE
(
0
,
"禁用"
),
ENABLE
(
1
,
"启用"
);
private
Integer
value
;
private
String
text
;
AccountStatusEnum
(
Integer
value
,
String
text
)
{
this
.
value
=
value
;
this
.
text
=
text
;
}
@Override
public
int
value
()
{
return
value
;
}
@JsonCreator
public
static
AccountStatusEnum
valueOf
(
Integer
value
)
{
return
BasePOEnum
.
valueOf
(
AccountStatusEnum
.
class
,
value
);
}
}
src/main/java/com/qkdata/biz/base/enums/MenuTypeEnum.java
0 → 100644
View file @
7409526c
package
com
.
qkdata
.
biz
.
base
.
enums
;
import
com.fasterxml.jackson.annotation.JsonCreator
;
import
com.qkdata.common.base.enums.BasePOEnum
;
public
enum
MenuTypeEnum
implements
BasePOEnum
{
FOLDER
(
0
,
"目录"
),
MENU
(
1
,
"菜单"
),
BUTTON
(
3
,
"按扭"
);
MenuTypeEnum
(
Integer
value
,
String
text
){
this
.
value
=
value
;
this
.
text
=
text
;
}
private
Integer
value
;
private
String
text
;
@Override
public
int
value
()
{
return
value
;
}
@JsonCreator
public
static
MenuTypeEnum
valueOf
(
Integer
value
)
{
return
BasePOEnum
.
valueOf
(
MenuTypeEnum
.
class
,
value
);
}
}
src/main/java/com/qkdata/biz/base/enums/SysConfigStatusEnum.java
0 → 100644
View file @
7409526c
package
com
.
qkdata
.
biz
.
base
.
enums
;
import
com.fasterxml.jackson.annotation.JsonCreator
;
import
com.qkdata.common.base.enums.BasePOEnum
;
public
enum
SysConfigStatusEnum
implements
BasePOEnum
{
HIDDEN
(
0
,
"隐藏"
),
SHOW
(
1
,
"显示"
);
private
Integer
value
;
private
String
text
;
SysConfigStatusEnum
(
Integer
value
,
String
text
)
{
this
.
value
=
value
;
this
.
text
=
text
;
}
@Override
public
int
value
()
{
return
value
;
}
@JsonCreator
public
static
SysConfigStatusEnum
valueOf
(
Integer
value
)
{
return
BasePOEnum
.
valueOf
(
SysConfigStatusEnum
.
class
,
value
);
}
}
src/main/java/com/qkdata/biz/sys/controller/SysLoginController.java
0 → 100644
View file @
7409526c
package
com
.
qkdata
.
biz
.
sys
.
controller
;
import
com.fasterxml.jackson.core.JsonProcessingException
;
import
com.qkdata.biz.sys.model.LoginModel
;
import
com.qkdata.biz.sys.model.LoginUserInfo
;
import
com.qkdata.biz.sys.service.ShiroService
;
import
io.swagger.annotations.Api
;
import
org.apache.shiro.SecurityUtils
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.http.HttpStatus
;
import
org.springframework.web.bind.annotation.*
;
import
javax.validation.Valid
;
@RestController
@RequestMapping
(
"/api/sys"
)
@Api
public
class
SysLoginController
{
@Autowired
private
ShiroService
shiroService
;
@PostMapping
(
"/login"
)
public
LoginUserInfo
login
(
@RequestBody
@Valid
LoginModel
loginModel
)
throws
JsonProcessingException
{
return
shiroService
.
login
(
loginModel
.
getUsername
(),
loginModel
.
getPassword
());
}
@GetMapping
(
"/logout"
)
@ResponseStatus
(
HttpStatus
.
NO_CONTENT
)
public
void
logout
(){
SecurityUtils
.
getSubject
().
logout
();
}
}
src/main/java/com/qkdata/biz/sys/controller/UserController.java
0 → 100644
View file @
7409526c
package
com
.
qkdata
.
biz
.
sys
.
controller
;
import
com.google.common.collect.Lists
;
import
com.qkdata.biz.sys.entity.SysUserPO
;
import
io.swagger.annotations.Api
;
import
org.apache.shiro.SecurityUtils
;
import
org.apache.shiro.authz.annotation.RequiresPermissions
;
import
org.springframework.web.bind.annotation.GetMapping
;
import
org.springframework.web.bind.annotation.RequestMapping
;
import
org.springframework.web.bind.annotation.RestController
;
import
java.util.List
;
@Api
@RestController
@RequestMapping
(
"/api/sys/user"
)
public
class
UserController
{
@GetMapping
(
"/list"
)
// @RequiresPermissions("sys:user:list")
public
List
<
SysUserPO
>
list
(){
SysUserPO
user
=
(
SysUserPO
)
SecurityUtils
.
getSubject
().
getPrincipal
();
return
Lists
.
newArrayList
();
}
}
src/main/java/com/qkdata/biz/sys/entity/SysConfigPO.java
0 → 100644
View file @
7409526c
package
com
.
qkdata
.
biz
.
sys
.
entity
;
import
com.qkdata.biz.base.enums.SysConfigStatusEnum
;
import
com.qkdata.common.base.entity.BasePO
;
import
lombok.Data
;
import
javax.persistence.Column
;
import
javax.persistence.Table
;
@Data
@Table
(
name
=
"sys_config"
)
public
class
SysConfigPO
extends
BasePO
{
private
String
paramKey
;
private
String
paramValue
;
@Column
(
name
=
"status"
)
private
SysConfigStatusEnum
status
;
private
String
remark
;
}
src/main/java/com/qkdata/biz/sys/entity/SysMenuPO.java
0 → 100644
View file @
7409526c
package
com
.
qkdata
.
biz
.
sys
.
entity
;
import
com.qkdata.biz.base.enums.MenuTypeEnum
;
import
com.qkdata.common.base.entity.BasePO
;
import
lombok.Data
;
import
javax.persistence.Table
;
@Data
@Table
(
name
=
"sys_menu"
)
public
class
SysMenuPO
extends
BasePO
{
private
Integer
parentId
;
private
String
name
;
private
String
url
;
private
String
perms
;
private
MenuTypeEnum
type
;
private
String
icon
;
private
Integer
orderNum
;
}
src/main/java/com/qkdata/biz/sys/entity/SysOssPO.java
0 → 100644
View file @
7409526c
package
com
.
qkdata
.
biz
.
sys
.
entity
;
import
com.qkdata.common.base.entity.BasePO
;
import
lombok.Data
;
import
javax.persistence.Table
;
@Data
@Table
(
name
=
"sys_oss"
)
public
class
SysOssPO
extends
BasePO
{
private
String
url
;
}
src/main/java/com/qkdata/biz/sys/entity/SysRoleMenuPO.java
0 → 100644
View file @
7409526c
package
com
.
qkdata
.
biz
.
sys
.
entity
;
import
com.qkdata.common.base.entity.BasePO
;
import
lombok.Data
;
import
javax.persistence.Table
;
@Data
@Table
(
name
=
"sys_role_menu"
)
public
class
SysRoleMenuPO
extends
BasePO
{
private
Integer
roleId
;
private
Integer
menuId
;
}
src/main/java/com/qkdata/biz/sys/entity/SysRolePO.java
0 → 100644
View file @
7409526c
package
com
.
qkdata
.
biz
.
sys
.
entity
;
import
com.qkdata.common.base.entity.BasePO
;
import
lombok.Data
;
import
javax.persistence.Table
;
@Data
@Table
(
name
=
"sys_role"
)
public
class
SysRolePO
extends
BasePO
{
private
String
name
;
private
String
remark
;
}
src/main/java/com/qkdata/biz/sys/entity/SysUserPO.java
0 → 100644
View file @
7409526c
package
com
.
qkdata
.
biz
.
sys
.
entity
;
import
com.qkdata.biz.base.enums.AccountStatusEnum
;
import
com.qkdata.common.base.entity.BasePO
;
import
lombok.Data
;
import
javax.persistence.Column
;
import
javax.persistence.Table
;
import
java.time.LocalDateTime
;
@Data
@Table
(
name
=
"sys_user"
)
public
class
SysUserPO
extends
BasePO
{
private
String
username
;
private
String
password
;
private
String
salt
;
private
String
email
;
private
String
mobile
;
@Column
(
name
=
"status"
)
private
AccountStatusEnum
status
;
/**
* 创建时间
*/
@Column
(
name
=
"create_at"
)
private
LocalDateTime
createAt
;
}
src/main/java/com/qkdata/biz/sys/entity/SysUserRolePO.java
0 → 100644
View file @
7409526c
package
com
.
qkdata
.
biz
.
sys
.
entity
;
import
lombok.Data
;
import
javax.persistence.Table
;
@Data
@Table
(
name
=
"sys_user_role"
)
public
class
SysUserRolePO
{
private
Long
userId
;
private
Long
roleId
;
}
src/main/java/com/qkdata/biz/sys/model/LoginModel.java
0 → 100644
View file @
7409526c
package
com
.
qkdata
.
biz
.
sys
.
model
;
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/model/LoginUserInfo.java
0 → 100644
View file @
7409526c
package
com
.
qkdata
.
biz
.
sys
.
model
;
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/repository/SysConfigMapper.java
0 → 100644
View file @
7409526c
package
com
.
qkdata
.
biz
.
sys
.
repository
;
import
com.qkdata.biz.sys.entity.SysConfigPO
;
import
tk.mybatis.mapper.common.Mapper
;
public
interface
SysConfigMapper
extends
Mapper
<
SysConfigPO
>
{
}
src/main/java/com/qkdata/biz/sys/repository/SysMenuMapper.java
0 → 100644
View file @
7409526c
package
com
.
qkdata
.
biz
.
sys
.
repository
;
import
com.qkdata.biz.sys.entity.SysMenuPO
;
import
tk.mybatis.mapper.common.Mapper
;
public
interface
SysMenuMapper
extends
Mapper
<
SysMenuPO
>
{
}
src/main/java/com/qkdata/biz/sys/repository/SysOssMapper.java
0 → 100644
View file @
7409526c
package
com
.
qkdata
.
biz
.
sys
.
repository
;
import
com.qkdata.biz.sys.entity.SysOssPO
;
import
tk.mybatis.mapper.common.Mapper
;
public
interface
SysOssMapper
extends
Mapper
<
SysOssPO
>
{
}
src/main/java/com/qkdata/biz/sys/repository/SysRoleMapper.java
0 → 100644
View file @
7409526c
package
com
.
qkdata
.
biz
.
sys
.
repository
;
import
com.qkdata.biz.sys.entity.SysRolePO
;
import
tk.mybatis.mapper.common.Mapper
;
public
interface
SysRoleMapper
extends
Mapper
<
SysRolePO
>
{
}
src/main/java/com/qkdata/biz/sys/repository/SysRoleMenuMapper.java
0 → 100644
View file @
7409526c
package
com
.
qkdata
.
biz
.
sys
.
repository
;
import
com.qkdata.biz.sys.entity.SysRoleMenuPO
;
import
tk.mybatis.mapper.common.Mapper
;
public
interface
SysRoleMenuMapper
extends
Mapper
<
SysRoleMenuPO
>
{
}
src/main/java/com/qkdata/biz/sys/repository/SysUserMapper.java
0 → 100644
View file @
7409526c
package
com
.
qkdata
.
biz
.
sys
.
repository
;
import
com.qkdata.biz.sys.entity.SysUserPO
;
import
tk.mybatis.mapper.common.Mapper
;
import
java.util.List
;
public
interface
SysUserMapper
extends
Mapper
<
SysUserPO
>
{
List
<
String
>
queryAllPerms
(
Long
userId
);
}
src/main/java/com/qkdata/biz/sys/repository/SysUserRoleMapper.java
0 → 100644
View file @
7409526c
package
com
.
qkdata
.
biz
.
sys
.
repository
;
import
com.qkdata.biz.sys.entity.SysUserRolePO
;
import
tk.mybatis.mapper.common.Mapper
;
public
interface
SysUserRoleMapper
extends
Mapper
<
SysUserRolePO
>
{
}
src/main/java/com/qkdata/biz/sys/service/ShiroService.java
0 → 100644
View file @
7409526c
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.base.constants.ResultEnum
;
import
com.qkdata.biz.base.enums.AccountStatusEnum
;
import
com.qkdata.common.base.exception.BusinessException
;
import
com.qkdata.common.jwt.JWTService
;
import
com.qkdata.common.oauth.AuthorizedUser
;
import
com.qkdata.biz.sys.entity.SysMenuPO
;
import
com.qkdata.biz.sys.entity.SysUserPO
;
import
com.qkdata.biz.sys.model.LoginUserInfo
;
import
com.qkdata.biz.sys.repository.SysMenuMapper
;
import
com.qkdata.biz.sys.repository.SysUserMapper
;
import
org.apache.shiro.crypto.hash.Sha256Hash
;
import
org.springframework.beans.BeanUtils
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.cache.annotation.Cacheable
;
import
org.springframework.stereotype.Service
;
import
org.springframework.transaction.annotation.Transactional
;
import
org.springframework.util.StringUtils
;
import
java.util.*
;
@Service
@Transactional
(
readOnly
=
true
)
public
class
ShiroService
{
@Autowired
private
SysUserMapper
sysUserMapper
;
@Autowired
private
SysMenuMapper
sysMenuMapper
;
@Autowired
private
JWTService
jwtService
;
private
ObjectMapper
mapper
=
new
ObjectMapper
();
@Cacheable
(
cacheNames
=
"userPerm_userId"
,
unless
=
"#result == null"
)
public
Set
<
String
>
getUserPermissions
(
Long
userId
)
{
List
<
String
>
permsList
;
//系统管理员,拥有最高权限
if
(
userId
==
1
){
List
<
SysMenuPO
>
menuList
=
sysMenuMapper
.
selectAll
();
permsList
=
new
ArrayList
<>(
menuList
.
size
());
for
(
SysMenuPO
menu
:
menuList
){
permsList
.
add
(
menu
.
getPerms
());
}
}
else
{
permsList
=
sysUserMapper
.
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
;
}
@Cacheable
(
cacheNames
=
"user_username"
,
unless
=
"#result == null"
)
public
SysUserPO
getUserByUserName
(
String
username
)
{
SysUserPO
query
=
new
SysUserPO
();
query
.
setUsername
(
username
);
return
sysUserMapper
.
selectOne
(
query
);
}
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
(
ResultEnum
.
ACCOUNT_NOT_EXIST
);
}
if
(
userPO
.
getStatus
()
==
AccountStatusEnum
.
DISABLE
){
throw
new
BusinessException
(
ResultEnum
.
ACCOUNT_OFF
);
}
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
=
mapper
.
writeValueAsString
(
user
);
Map
<
String
,
Object
>
userClaim
=
Maps
.
newConcurrentMap
();
userClaim
.
put
(
"user"
,
userJson
);
return
jwtService
.
createJWT
(
userClaim
);
}
}
src/main/java/com/qkdata/biz/wsMessage/api/WSMessageController.java
0 → 100644
View file @
7409526c
package
com
.
qkdata
.
biz
.
wsMessage
.
api
;
import
com.qkdata.biz.wsMessage.service.WSMessageService
;
import
io.swagger.annotations.Api
;
import
io.swagger.annotations.ApiOperation
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.http.HttpStatus
;
import
org.springframework.web.bind.annotation.*
;
@Api
(
description
=
"测试websocket"
)
@RestController
@RequestMapping
(
"/api/v1/testWebsocket"
)
public
class
WSMessageController
{
@Autowired
private
WSMessageService
wsMessageService
;
@ApiOperation
(
"给指定用户发消息"
)
@GetMapping
(
"/sendToUser"
)
@ResponseStatus
(
HttpStatus
.
NO_CONTENT
)
public
void
sendMessageToUser
(
@RequestParam
String
user
,
@RequestParam
String
message
){
// wsMessageService.sendRoomChatMsgToUser(user,message);
}
}
src/main/java/com/qkdata/biz/wsMessage/config/MyPrincipal.java
0 → 100644
View file @
7409526c
package
com
.
qkdata
.
biz
.
wsMessage
.
config
;
import
java.security.Principal
;
public
class
MyPrincipal
implements
Principal
{
private
String
name
;
public
MyPrincipal
(
String
name
){
this
.
name
=
name
;
}
@Override
public
String
getName
()
{
return
this
.
name
;
}
}
src/main/java/com/qkdata/biz/wsMessage/config/WebSocketConfig.java
0 → 100644
View file @
7409526c
package
com
.
qkdata
.
biz
.
wsMessage
.
config
;
import
com.auth0.jwt.interfaces.DecodedJWT
;
import
com.fasterxml.jackson.databind.ObjectMapper
;
import
com.qkdata.common.oauth.AuthorizationException
;
import
com.qkdata.common.oauth.AuthorizationResponseEnum
;
import
com.qkdata.common.jwt.JWTService
;
import
com.qkdata.common.oauth.AuthorizedUser
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.context.annotation.Configuration
;
import
org.springframework.context.annotation.Lazy
;
import
org.springframework.http.server.ServerHttpRequest
;
import
org.springframework.http.server.ServerHttpResponse
;
import
org.springframework.http.server.ServletServerHttpRequest
;
import
org.springframework.messaging.simp.config.MessageBrokerRegistry
;
import
org.springframework.util.StringUtils
;
import
org.springframework.web.socket.WebSocketHandler
;
import
org.springframework.web.socket.config.annotation.EnableWebSocketMessageBroker
;
import
org.springframework.web.socket.config.annotation.StompEndpointRegistry
;
import
org.springframework.web.socket.config.annotation.WebSocketMessageBrokerConfigurer
;
import
org.springframework.web.socket.server.HandshakeInterceptor
;
import
org.springframework.web.socket.server.support.DefaultHandshakeHandler
;
import
java.io.IOException
;
import
java.security.Principal
;
import
java.util.Map
;
@Configuration
@EnableWebSocketMessageBroker
public
class
WebSocketConfig
implements
WebSocketMessageBrokerConfigurer
{
@Autowired
@Lazy
private
JWTService
jwtService
;
@Autowired
@Lazy
private
ObjectMapper
objectMapper
;
//注册STOMP协议节点并映射url
public
void
registerStompEndpoints
(
StompEndpointRegistry
registry
)
{
registry
.
addEndpoint
(
"/websocket"
)
//注册一个 /websocket 的 websocket 节点
.
addInterceptors
(
myHandshakeInterceptor
())
//添加 websocket握手拦截器
.
setHandshakeHandler
(
myDefaultHandshakeHandler
())
//添加 websocket握手处理器
.
setAllowedOrigins
(
"*"
)
//设置允许可跨域的域名
.
withSockJS
();
//指定使用SockJS协议
}
/**
* WebSocket 握手拦截器
* 可做一些用户认证拦截处理
*/
private
HandshakeInterceptor
myHandshakeInterceptor
(){
return
new
HandshakeInterceptor
()
{
/**
* websocket握手连接
* @return 返回是否同意握手
*/
@Override
public
boolean
beforeHandshake
(
ServerHttpRequest
request
,
ServerHttpResponse
response
,
WebSocketHandler
wsHandler
,
Map
<
String
,
Object
>
attributes
)
throws
Exception
{
ServletServerHttpRequest
req
=
(
ServletServerHttpRequest
)
request
;
//通过url的query参数获取认证参数
String
token
=
req
.
getServletRequest
().
getParameter
(
"token"
);
//根据token认证用户,不通过返回拒绝握手
if
(
token
==
null
){
return
false
;
}
Principal
user
=
authenticate
(
token
);
if
(
user
==
null
){
return
false
;
}
//保存认证用户
attributes
.
put
(
"user"
,
user
);
return
true
;
}
@Override
public
void
afterHandshake
(
ServerHttpRequest
request
,
ServerHttpResponse
response
,
WebSocketHandler
wsHandler
,
Exception
exception
)
{
}
};
}
//WebSocket 握手处理器
private
DefaultHandshakeHandler
myDefaultHandshakeHandler
(){
return
new
DefaultHandshakeHandler
(){
@Override
protected
Principal
determineUser
(
ServerHttpRequest
request
,
WebSocketHandler
wsHandler
,
Map
<
String
,
Object
>
attributes
)
{
//设置认证通过的用户到当前会话中
return
(
Principal
)
attributes
.
get
(
"user"
);
}
};
}
/**
* 定义一些消息连接规范(也可不设置)
* @param registry
*/
@Override
public
void
configureMessageBroker
(
MessageBrokerRegistry
registry
)
{
//设置客户端接收消息地址的前缀(可不设置)
registry
.
enableSimpleBroker
(
"/topic/room"
,
"/topic/login"
);
//设置客户端接收点对点消息地址的前缀,默认为 /user
registry
.
setUserDestinationPrefix
(
"/user"
);
//设置客户端向服务器发送消息的地址前缀(可不设置)
registry
.
setApplicationDestinationPrefixes
(
"/app"
);
}
/**
* 根据token认证授权
* @param token
*/
private
Principal
authenticate
(
String
token
){
//用户信息需继承 Principal 并实现 getName() 方法,返回全局唯一值
DecodedJWT
jwtToken
=
jwtService
.
decode
(
token
);
String
userJson
=
jwtToken
.
getClaim
(
"user"
).
asString
();
if
(
StringUtils
.
isEmpty
(
userJson
))
{
return
null
;
}
try
{
AuthorizedUser
authorizedUser
=
objectMapper
.
readValue
(
userJson
,
AuthorizedUser
.
class
);
return
new
MyPrincipal
(
authorizedUser
.
getUsername
());
}
catch
(
IOException
e
)
{
throw
new
AuthorizationException
(
AuthorizationResponseEnum
.
INVALID_CLAIM
);
}
}
}
src/main/java/com/qkdata/biz/wsMessage/model/WxLoginMsg.java
0 → 100644
View file @
7409526c
package
com
.
qkdata
.
biz
.
wsMessage
.
model
;
import
lombok.AllArgsConstructor
;
import
lombok.Data
;
@Data
@AllArgsConstructor
public
class
WxLoginMsg
{
private
String
type
;
//qrcode|login_result
private
String
content
;
}
src/main/java/com/qkdata/biz/wsMessage/service/WSMessageService.java
0 → 100644
View file @
7409526c
package
com
.
qkdata
.
biz
.
wsMessage
.
service
;
import
lombok.extern.slf4j.Slf4j
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.messaging.simp.SimpMessagingTemplate
;
import
org.springframework.stereotype.Service
;
@Slf4j
@Service
public
class
WSMessageService
{
@Autowired
private
SimpMessagingTemplate
template
;
// public void sendRoomChatMsgToUser(String user,String message){
// log.debug("WSMessageService sendRoomChatMsgToUser user:"+user);
// template.convertAndSendToUser(user,"/topic/room",message);
// }
// public void sendLoginMsgToUser(String user, WxLoginMsg msg){
// log.debug("WSMessageService sendLoginMsgToUser,user={}",user);
// template.convertAndSendToUser(user,"/topic/login", JSONObject.toJSONString(msg));
// }
}
src/main/java/com/qkdata/common/base/entity/BasePO.java
0 → 100644
View file @
7409526c
package
com
.
qkdata
.
common
.
base
.
entity
;
import
com.qkdata.common.base.enums.DeletedEnum
;
import
lombok.Data
;
import
javax.persistence.Column
;
import
javax.persistence.GeneratedValue
;
import
javax.persistence.Id
;
import
java.io.Serializable
;
import
java.time.LocalDateTime
;
@Data
public
class
BasePO
implements
Serializable
{
private
static
final
long
serialVersionUID
=
-
5785859031130509619L
;
/**
* 主键
*/
@Id
@Column
(
name
=
"id"
)
@GeneratedValue
(
generator
=
"JDBC"
)
protected
Long
id
;
}
src/main/java/com/qkdata/common/base/enums/BasePOEnum.java
0 → 100644
View file @
7409526c
package
com
.
qkdata
.
common
.
base
.
enums
;
import
com.fasterxml.jackson.annotation.JsonValue
;
import
java.util.HashMap
;
import
java.util.Map
;
/**
* 所有Entity中枚举类型的基础, 主要用于数据库中存储枚举的value和SpringMVC参数直接转换成Enum
*
* @author chenjiahai
* @date 17/8/3
*/
public
interface
BasePOEnum
{
/**
* JsonValue用于serializer
*
* @return
*/
@JsonValue
int
value
();
/**
* 获取枚举值对应的枚举
*
* @param enumClass 枚举类
* @param enumValue 枚举值
* @return 枚举
*/
static
<
E
extends
BasePOEnum
>
E
getEnum
(
final
Class
<
E
>
enumClass
,
final
Integer
enumValue
)
{
if
(
enumValue
==
null
)
{
return
null
;
}
try
{
return
valueOf
(
enumClass
,
enumValue
);
}
catch
(
final
IllegalArgumentException
ex
)
{
return
null
;
}
}
/**
* 获取枚举值对应的枚举
*
* @param enumClass 枚举类
* @param enumValue 枚举值
* @return 枚举
*/
static
<
E
extends
BasePOEnum
>
E
valueOf
(
Class
<
E
>
enumClass
,
Integer
enumValue
)
{
if
(
enumValue
==
null
)
{
return
null
;
}
return
getEnumMap
(
enumClass
).
get
(
enumValue
);
}
/**
* 获取枚举键值对
*
* @param enumClass 枚举类型
* @return 键值对
*/
static
<
E
extends
BasePOEnum
>
Map
<
Integer
,
E
>
getEnumMap
(
Class
<
E
>
enumClass
)
{
E
[]
enums
=
enumClass
.
getEnumConstants
();
if
(
enums
==
null
)
{
throw
new
IllegalArgumentException
(
enumClass
.
getSimpleName
()
+
" does not represent an enum type."
);
}
Map
<
Integer
,
E
>
map
=
new
HashMap
<>();
for
(
E
t
:
enums
)
{
map
.
put
(
t
.
value
(),
t
);
}
return
map
;
}
}
src/main/java/com/qkdata/common/base/enums/BaseResponseEnum.java
0 → 100644
View file @
7409526c
package
com
.
qkdata
.
common
.
base
.
enums
;
public
interface
BaseResponseEnum
{
String
value
();
String
text
();
}
src/main/java/com/qkdata/common/base/enums/DeletedEnum.java
0 → 100644
View file @
7409526c
package
com
.
qkdata
.
common
.
base
.
enums
;
import
com.fasterxml.jackson.annotation.JsonCreator
;
/**
* 删除标志枚举
*/
public
enum
DeletedEnum
implements
BasePOEnum
{
DELETED
(
1
,
"已删除"
),
NOT_DELETED
(
2
,
"未删除"
);
private
Integer
value
;
private
String
text
;
DeletedEnum
(
Integer
value
,
String
text
)
{
this
.
value
=
value
;
this
.
text
=
text
;
}
@Override
public
int
value
()
{
return
value
;
}
@JsonCreator
public
static
DeletedEnum
valueOf
(
Integer
value
)
{
return
BasePOEnum
.
valueOf
(
DeletedEnum
.
class
,
value
);
}
}
src/main/java/com/qkdata/common/base/enums/SystemResponseEnum.java
0 → 100644
View file @
7409526c
package
com
.
qkdata
.
common
.
base
.
enums
;
public
enum
SystemResponseEnum
implements
BaseResponseEnum
{
ERROR
(
"500"
,
"服务器繁忙, 请稍后再试"
),
INVALID_TIMESTAMP
(
"400"
,
"不合法的时间格式"
),
MESSAGE_NOT_READABLE
(
"400"
,
"无法解析请求参数"
),
MISSING_PATH_VARIABLE
(
"400"
,
"请求链接缺少参数"
),
MISSING_REQUEST_PARAM
(
"400"
,
"缺少必需的请求参数"
),
ARGUMENT_TYPE_MISMATCH
(
"400"
,
"参数类别转换失败"
),
CONSTRAINT_VIOLATION
(
"400"
,
"参数校验失败"
),
METHOD_NOT_SUPPORTED
(
"400"
,
"不支持该请求方法"
),
MEDIA_TYPE_NOT_SUPPORTED
(
"400"
,
"不支持该请求参数类型"
),
NO_HANDLER_NOT_FOUND
(
"404"
,
"请求资源不存在"
);
private
String
value
;
private
String
text
;
SystemResponseEnum
(
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/base/exception/BusinessException.java
0 → 100644
View file @
7409526c
package
com
.
qkdata
.
common
.
base
.
exception
;
import
com.qkdata.common.base.enums.BaseResponseEnum
;
import
lombok.Data
;
/**
* 业务异常
*/
@Data
public
class
BusinessException
extends
RuntimeException
{
/**
*
*/
private
static
final
long
serialVersionUID
=
4650570427238258122L
;
private
String
code
;
private
String
message
;
public
BusinessException
(
BaseResponseEnum
responseEnum
)
{
this
.
code
=
responseEnum
.
value
();
this
.
message
=
responseEnum
.
text
();
}
public
BusinessException
(
String
code
,
String
message
)
{
this
.
code
=
code
;
this
.
message
=
message
;
}
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/IdDTO.java
0 → 100644
View file @
7409526c
package
com
.
qkdata
.
common
.
base
.
model
;
import
lombok.AllArgsConstructor
;
import
lombok.Data
;
import
lombok.NoArgsConstructor
;
import
java.io.Serializable
;
/**
* @author songminghui
* @date 2018-11-15 上午11:11
* @email songminghui@shangweiec.com
* @description
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
public
class
IdDTO
implements
Serializable
{
private
static
final
long
serialVersionUID
=
-
1524848284951435773L
;
private
Long
id
;
}
src/main/java/com/qkdata/common/base/model/PageDTO.java
0 → 100644
View file @
7409526c
package
com
.
qkdata
.
common
.
base
.
model
;
import
com.github.pagehelper.PageInfo
;
import
lombok.Data
;
import
lombok.NoArgsConstructor
;
import
org.springframework.util.CollectionUtils
;
import
java.io.Serializable
;
import
java.util.ArrayList
;
import
java.util.List
;
@Data
@NoArgsConstructor
public
class
PageDTO
<
T
>
implements
Serializable
{
/**
*
*/
private
static
final
long
serialVersionUID
=
-
3506803903226539566L
;
/**
* 总条数
*/
private
Long
total
=
0L
;
/**
* 数据
*/
private
List
<?>
result
=
new
ArrayList
<>();
public
PageDTO
(
PageInfo
<
T
>
pageInfo
)
{
this
.
total
=
pageInfo
.
getTotal
();
List
<
T
>
list
=
pageInfo
.
getList
();
if
(!
CollectionUtils
.
isEmpty
(
list
))
this
.
result
=
pageInfo
.
getList
();
}
public
PageDTO
(
PageInfo
<
T
>
pageInfo
,
List
<
T
>
result
)
{
this
.
total
=
pageInfo
.
getTotal
();
if
(!
CollectionUtils
.
isEmpty
(
result
))
this
.
result
=
result
;
}
}
src/main/java/com/qkdata/common/base/model/ResponseData.java
0 → 100644
View file @
7409526c
package
com
.
qkdata
.
common
.
base
.
model
;
import
com.fasterxml.jackson.annotation.JsonInclude
;
import
com.qkdata.common.base.enums.BaseResponseEnum
;
import
lombok.Data
;
import
java.io.Serializable
;
@SuppressWarnings
(
"deprecation"
)
@JsonInclude
(
content
=
JsonInclude
.
Include
.
NON_NULL
,
value
=
JsonInclude
.
Include
.
NON_EMPTY
)
@Data
public
class
ResponseData
implements
Serializable
{
private
static
final
long
serialVersionUID
=
645306359281445009L
;
private
String
code
;
private
String
message
;
private
Object
data
;
public
ResponseData
()
{
}
public
ResponseData
(
BaseResponseEnum
responseEnum
)
{
this
.
code
=
responseEnum
.
value
();
this
.
message
=
responseEnum
.
text
();
}
public
ResponseData
(
Object
data
)
{
this
.
data
=
data
;
}
public
ResponseData
(
String
code
,
String
message
)
{
this
.
code
=
code
;
this
.
message
=
message
;
}
}
src/main/java/com/qkdata/common/base/service/BaseService.java
0 → 100644
View file @
7409526c
package
com
.
qkdata
.
common
.
base
.
service
;
import
java.util.List
;
/**
* service基础类
*/
public
interface
BaseService
<
T
,
Serializable
>
{
/**
* 根据主键ID查询
*
* @param id
* @return
*/
T
getById
(
Serializable
id
);
/**
* 保存
*
* @param entity
*/
void
save
(
T
entity
);
/**
* 根据主键ID更新
*
* @param entity
*/
void
updateById
(
T
entity
);
/**
* 根据指定条件查询列表
*
* @param entity
* @return
*/
List
<
T
>
listByCondition
(
T
entity
);
/**
* 根据指定条件查询单个实体
*
* @param entity
* @return
*/
T
getByCondition
(
T
entity
);
/**
* 根据指定条件查询数量
* @param entity
* @return
*/
int
countByCondition
(
T
entity
);
void
deleteById
(
Serializable
id
);
}
src/main/java/com/qkdata/common/base/service/impl/BaseServiceImpl.java
0 → 100644
View file @
7409526c
package
com
.
qkdata
.
common
.
base
.
service
.
impl
;
import
com.qkdata.common.base.service.BaseService
;
import
tk.mybatis.mapper.common.Mapper
;
import
java.util.List
;
public
abstract
class
BaseServiceImpl
<
T
,
Serializable
>
implements
BaseService
<
T
,
Serializable
>
{
protected
abstract
Mapper
<
T
>
getMapper
();
@Override
public
T
getById
(
Serializable
id
)
{
return
getMapper
().
selectByPrimaryKey
(
id
);
}
@Override
public
void
save
(
T
entity
)
{
getMapper
().
insertSelective
(
entity
);
}
@Override
public
void
updateById
(
T
entity
)
{
getMapper
().
updateByPrimaryKeySelective
(
entity
);
}
@Override
public
List
<
T
>
listByCondition
(
T
entity
)
{
return
getMapper
().
select
(
entity
);
}
@Override
public
T
getByCondition
(
T
entity
)
{
return
getMapper
().
selectOne
(
entity
);
}
@Override
public
int
countByCondition
(
T
entity
)
{
return
getMapper
().
selectCount
(
entity
);
}
@Override
public
void
deleteById
(
Serializable
id
)
{
getMapper
().
deleteByPrimaryKey
(
id
);
}
}
src/main/java/com/qkdata/common/config/CustomEnumTypeHandler.java
0 → 100644
View file @
7409526c
package
com
.
qkdata
.
common
.
config
;
import
com.qkdata.biz.base.enums.AccountStatusEnum
;
import
com.qkdata.common.base.enums.BasePOEnum
;
import
com.qkdata.common.base.enums.DeletedEnum
;
import
org.apache.ibatis.type.BaseTypeHandler
;
import
org.apache.ibatis.type.JdbcType
;
import
org.apache.ibatis.type.MappedTypes
;
import
java.sql.CallableStatement
;
import
java.sql.PreparedStatement
;
import
java.sql.ResultSet
;
import
java.sql.SQLException
;
@MappedTypes
(
value
=
{
DeletedEnum
.
class
,
AccountStatusEnum
.
class
})
public
class
CustomEnumTypeHandler
<
E
extends
BasePOEnum
>
extends
BaseTypeHandler
<
E
>
{
// org.apache.ibatis.type.TypeHandlerRegistry#register(TypeHandler<T> typeHandler)#Line:292
private
Class
<
E
>
type
;
public
CustomEnumTypeHandler
(
Class
<
E
>
type
)
{
if
(
type
==
null
)
{
throw
new
IllegalArgumentException
(
"Type argument cannot be null"
);
}
this
.
type
=
type
;
}
@Override
public
void
setNonNullParameter
(
PreparedStatement
ps
,
int
i
,
E
parameter
,
JdbcType
jdbcType
)
throws
SQLException
{
ps
.
setInt
(
i
,
parameter
.
value
());
}
@Override
public
E
getNullableResult
(
ResultSet
rs
,
String
columnName
)
throws
SQLException
{
int
i
=
rs
.
getInt
(
columnName
);
if
(
rs
.
wasNull
())
{
return
null
;
}
else
{
try
{
return
BasePOEnum
.
getEnum
(
type
,
i
);
}
catch
(
Exception
ex
)
{
throw
new
IllegalArgumentException
(
"Cannot convert "
+
i
+
" to "
+
type
.
getSimpleName
()
+
" by int value."
,
ex
);
}
}
}
@Override
public
E
getNullableResult
(
ResultSet
rs
,
int
columnIndex
)
throws
SQLException
{
int
i
=
rs
.
getInt
(
columnIndex
);
if
(
rs
.
wasNull
())
{
return
null
;
}
else
{
try
{
return
BasePOEnum
.
getEnum
(
type
,
i
);
}
catch
(
Exception
ex
)
{
throw
new
IllegalArgumentException
(
"Cannot convert "
+
i
+
" to "
+
type
.
getSimpleName
()
+
" by int value."
,
ex
);
}
}
}
@Override
public
E
getNullableResult
(
CallableStatement
cs
,
int
columnIndex
)
throws
SQLException
{
int
i
=
cs
.
getInt
(
columnIndex
);
if
(
cs
.
wasNull
())
{
return
null
;
}
else
{
try
{
return
BasePOEnum
.
getEnum
(
type
,
i
);
}
catch
(
Exception
ex
)
{
throw
new
IllegalArgumentException
(
"Cannot convert "
+
i
+
" to "
+
type
.
getSimpleName
()
+
" by int value."
,
ex
);
}
}
}
}
\ No newline at end of file
src/main/java/com/qkdata/common/config/FilterConfig.java
0 → 100644
View file @
7409526c
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 @
7409526c
package
com
.
qkdata
.
common
.
config
;
import
com.qkdata.common.oauth.AuthorizationException
;
import
com.qkdata.common.base.enums.SystemResponseEnum
;
import
com.qkdata.common.base.exception.BusinessException
;
import
com.qkdata.common.base.model.ResponseData
;
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.ConstraintViolation
;
import
javax.validation.ConstraintViolationException
;
@RestControllerAdvice
@Slf4j
public
class
GlobalExceptionHandle
{
@ExceptionHandler
(
value
=
MethodArgumentNotValidException
.
class
)
public
ResponseEntity
<
ResponseData
>
bindExceptionHandler
(
MethodArgumentNotValidException
e
)
{
BindingResult
bindingResult
=
e
.
getBindingResult
();
String
message
=
bindingResult
.
getFieldError
().
getDefaultMessage
();
log
.
warn
(
"方法参数无效: {}"
,
message
);
return
ResponseEntity
.
badRequest
().
body
(
new
ResponseData
(
"70000"
,
message
));
}
@ExceptionHandler
(
value
=
HttpRequestMethodNotSupportedException
.
class
)
public
ResponseEntity
<
ResponseData
>
httpRequestMethodNotSupportedExceptionHandler
(
HttpRequestMethodNotSupportedException
e
)
{
log
.
warn
(
"不支持的Method: {}"
,
e
.
getMessage
());
return
ResponseEntity
.
status
(
HttpStatus
.
NOT_FOUND
).
body
(
new
ResponseData
(
SystemResponseEnum
.
METHOD_NOT_SUPPORTED
));
}
@ExceptionHandler
(
value
=
Exception
.
class
)
public
ResponseEntity
<
ResponseData
>
handler
(
Exception
e
)
{
log
.
error
(
"服务器错误"
,
e
);
return
ResponseEntity
.
status
(
HttpStatus
.
INTERNAL_SERVER_ERROR
).
body
(
new
ResponseData
(
SystemResponseEnum
.
ERROR
));
}
@ExceptionHandler
(
value
=
BusinessException
.
class
)
public
ResponseEntity
<
ResponseData
>
businessExceptionhandler
(
BusinessException
e
)
{
log
.
warn
(
"业务异常, code: {}, message: {}"
,
e
.
getCode
(),
e
.
getMessage
());
// TODO 从BusinessException获取responseEnum, 不能直接打印e.getMessage()
return
ResponseEntity
.
badRequest
().
body
(
new
ResponseData
(
e
.
getCode
(),
e
.
getMessage
()));
}
@ExceptionHandler
(
value
=
HttpMessageNotReadableException
.
class
)
public
ResponseEntity
<
ResponseData
>
httpMessageConvertExceptionHanlder
(
HttpMessageNotReadableException
e
)
{
log
.
warn
(
"无法解析请求参数: {}"
,
e
.
getMessage
());
return
ResponseEntity
.
badRequest
().
body
(
new
ResponseData
(
SystemResponseEnum
.
MESSAGE_NOT_READABLE
));
}
@ExceptionHandler
(
value
=
MissingPathVariableException
.
class
)
public
ResponseEntity
<
ResponseData
>
missingPathVariableExceptionHanlder
(
MissingPathVariableException
e
)
{
log
.
warn
(
"请求链接缺少参数: {}"
,
e
.
getMessage
());
return
ResponseEntity
.
badRequest
().
body
(
new
ResponseData
(
SystemResponseEnum
.
MISSING_PATH_VARIABLE
));
}
@ExceptionHandler
(
value
=
MissingServletRequestParameterException
.
class
)
public
ResponseEntity
<
ResponseData
>
requestParameterExceptionHandler
(
MissingServletRequestParameterException
e
)
{
log
.
warn
(
"缺少必需的请求参数: {}"
,
e
.
getMessage
());
return
ResponseEntity
.
badRequest
().
body
(
new
ResponseData
(
SystemResponseEnum
.
MISSING_REQUEST_PARAM
));
}
@ExceptionHandler
(
value
=
MethodArgumentTypeMismatchException
.
class
)
public
ResponseEntity
<
ResponseData
>
methodArgumentTypeMismatchExceptionHandler
(
MethodArgumentTypeMismatchException
e
)
{
log
.
warn
(
"参数类别转换失败: {}"
,
e
.
getMessage
());
return
ResponseEntity
.
badRequest
().
body
(
new
ResponseData
(
SystemResponseEnum
.
ARGUMENT_TYPE_MISMATCH
));
}
@ExceptionHandler
(
value
=
ConstraintViolationException
.
class
)
public
ResponseEntity
<
ResponseData
>
constraintViolationExceptionHandler
(
ConstraintViolationException
e
)
{
log
.
warn
(
"参数校验异常: {}"
,
e
.
getMessage
());
return
ResponseEntity
.
badRequest
().
body
(
new
ResponseData
(
SystemResponseEnum
.
CONSTRAINT_VIOLATION
.
value
(),
e
.
getConstraintViolations
().
stream
().
map
(
ConstraintViolation:
:
getMessage
).
findFirst
().
get
()));
}
@ExceptionHandler
(
value
=
HttpMediaTypeNotSupportedException
.
class
)
public
ResponseEntity
<
ResponseData
>
httpMediaTypeNotSupportedExceptionHandler
(
HttpMediaTypeNotSupportedException
e
)
{
log
.
warn
(
"不支持MediaType: {}"
,
e
.
getMessage
());
return
ResponseEntity
.
badRequest
().
body
(
new
ResponseData
(
SystemResponseEnum
.
MEDIA_TYPE_NOT_SUPPORTED
));
}
@ExceptionHandler
(
value
=
NoHandlerFoundException
.
class
)
public
ResponseEntity
<
ResponseData
>
noHandlerFoundExceptionHandler
(
NoHandlerFoundException
e
)
{
log
.
warn
(
"no handler found: {}"
,
e
.
getMessage
());
return
ResponseEntity
.
status
(
HttpStatus
.
NOT_FOUND
).
body
(
new
ResponseData
(
SystemResponseEnum
.
NO_HANDLER_NOT_FOUND
));
}
@ExceptionHandler
(
value
=
AuthorizationException
.
class
)
public
ResponseEntity
<
ResponseData
>
authorizationExceptionHandler
(
AuthorizationException
e
)
{
return
ResponseEntity
.
status
(
HttpStatus
.
UNAUTHORIZED
).
body
(
new
ResponseData
(
e
.
responseEnum
()));
}
}
src/main/java/com/qkdata/common/config/HttpHeaderInterceptor.java
0 → 100644
View file @
7409526c
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 @
7409526c
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 @
7409526c
package
com
.
qkdata
.
common
.
config
;
import
com.fasterxml.jackson.databind.DeserializationFeature
;
import
com.fasterxml.jackson.databind.SerializationFeature
;
import
com.qkdata.common.converter.LocalDateDeserializer
;
import
com.qkdata.common.converter.LocalDateSerializer
;
import
com.qkdata.common.converter.LocalDateTimeDeserializer
;
import
com.qkdata.common.converter.LocalDateTimeSerializer
;
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
;
@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
(
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 @
7409526c
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/RedisConfig.java
0 → 100644
View file @
7409526c
//package com.qkdata.common.config;
//
//import com.fasterxml.jackson.annotation.JsonAutoDetect;
//import com.fasterxml.jackson.annotation.PropertyAccessor;
//import com.fasterxml.jackson.databind.ObjectMapper;
//import lombok.extern.slf4j.Slf4j;
//import org.springframework.boot.autoconfigure.AutoConfigureAfter;
//import org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration;
//import org.springframework.cache.annotation.EnableCaching;
//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;
//
//@Configuration
//@EnableCaching
//@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);
// 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 @
7409526c
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
(
5000
);
//单位为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 @
7409526c
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 @
7409526c
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.ApiInfo
;
import
springfox.documentation.service.Parameter
;
import
springfox.documentation.spi.DocumentationType
;
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
().
globalOperationParameters
(
pars
);
}
/**
* @return
*/
private
ApiInfo
apiInfo
()
{
return
new
ApiInfoBuilder
().
title
(
"wx monitor service API"
).
version
(
"1.0"
).
build
();
}
}
src/main/java/com/qkdata/common/config/WebMvcConfiguration.java
0 → 100644
View file @
7409526c
package
com
.
qkdata
.
common
.
config
;
import
com.qkdata.common.converter.StringToCommonEnumConverterFactory
;
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.core.convert.converter.ConverterFactory
;
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
(
"/api/**"
)
.
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
.
addConverterFactory
(
stringToEnumConverterFactory
());
registry
.
addConverter
(
stringToLocalDateConverter
());
registry
.
addConverter
(
stringToLocalDateTimeConverter
());
}
@Override
public
void
addInterceptors
(
InterceptorRegistry
registry
)
{
registry
.
addInterceptor
(
traceIdInterceptor
());
}
private
HandlerInterceptor
traceIdInterceptor
()
{
return
new
TraceIdInterceptor
();
}
private
ConverterFactory
stringToEnumConverterFactory
()
{
return
new
StringToCommonEnumConverterFactory
();
}
private
Converter
stringToLocalDateConverter
()
{
return
new
StringToLocalDateConverter
();
}
private
Converter
stringToLocalDateTimeConverter
()
{
return
new
StringToLocalDateTimeConverter
();
}
}
src/main/java/com/qkdata/common/constants/DateTimeFormatterPattern.java
0 → 100644
View file @
7409526c
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 @
7409526c
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/ValidatorPattern.java
0 → 100644
View file @
7409526c
package
com
.
qkdata
.
common
.
constants
;
public
final
class
ValidatorPattern
{
private
ValidatorPattern
(){}
public
static
final
String
MOBILE_PATTERN
=
"^(13|14|15|17|18|19)[0-9]{9}$"
;
}
src/main/java/com/qkdata/common/converter/LocalDateDeserializer.java
0 → 100644
View file @
7409526c
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.enums.SystemResponseEnum
;
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
(
SystemResponseEnum
.
INVALID_TIMESTAMP
);
}
}
}
src/main/java/com/qkdata/common/converter/LocalDateSerializer.java
0 → 100644
View file @
7409526c
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 @
7409526c
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.enums.SystemResponseEnum
;
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
(
SystemResponseEnum
.
INVALID_TIMESTAMP
);
}
}
}
src/main/java/com/qkdata/common/converter/LocalDateTimeSerializer.java
0 → 100644
View file @
7409526c
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/StringToCommonEnumConverterFactory.java
0 → 100644
View file @
7409526c
package
com
.
qkdata
.
common
.
converter
;
import
com.qkdata.common.base.enums.BasePOEnum
;
import
org.springframework.core.convert.converter.Converter
;
import
org.springframework.core.convert.converter.ConverterFactory
;
import
org.springframework.util.StringUtils
;
/**
* 用于QUERY参数转换成对应枚举类型
*/
public
class
StringToCommonEnumConverterFactory
implements
ConverterFactory
<
String
,
BasePOEnum
>
{
@Override
public
<
T
extends
BasePOEnum
>
Converter
<
String
,
T
>
getConverter
(
Class
<
T
>
targetType
)
{
return
new
StringToEnum
<>(
targetType
);
}
private
static
class
StringToEnum
<
T
extends
BasePOEnum
>
implements
Converter
<
String
,
T
>
{
private
final
Class
<
T
>
enumType
;
public
StringToEnum
(
Class
<
T
>
enumType
)
{
this
.
enumType
=
enumType
;
}
@Override
public
T
convert
(
String
source
)
{
if
(
StringUtils
.
isEmpty
(
source
))
{
return
null
;
}
return
BasePOEnum
.
getEnum
(
enumType
,
Integer
.
valueOf
(
source
.
trim
()));
}
}
}
src/main/java/com/qkdata/common/converter/StringToLocalDateConverter.java
0 → 100644
View file @
7409526c
package
com
.
qkdata
.
common
.
converter
;
import
com.qkdata.common.base.enums.SystemResponseEnum
;
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
(
SystemResponseEnum
.
INVALID_TIMESTAMP
);
}
}
}
src/main/java/com/qkdata/common/converter/StringToLocalDateTimeConverter.java
0 → 100644
View file @
7409526c
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 @
7409526c
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 @
7409526c
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/AuthorizationException.java
0 → 100644
View file @
7409526c
package
com
.
qkdata
.
common
.
oauth
;
import
com.qkdata.common.base.enums.BaseResponseEnum
;
public
class
AuthorizationException
extends
RuntimeException
{
private
String
message
;
private
BaseResponseEnum
responseEnum
;
public
AuthorizationException
(
BaseResponseEnum
responseEnum
)
{
this
.
responseEnum
=
responseEnum
;
}
public
AuthorizationException
(
String
message
,
BaseResponseEnum
responseEnum
)
{
this
.
message
=
message
;
this
.
responseEnum
=
responseEnum
;
}
public
BaseResponseEnum
responseEnum
()
{
return
responseEnum
;
}
}
src/main/java/com/qkdata/common/oauth/AuthorizationResponseEnum.java
0 → 100644
View file @
7409526c
package
com
.
qkdata
.
common
.
oauth
;
import
com.qkdata.common.base.enums.BaseResponseEnum
;
public
enum
AuthorizationResponseEnum
implements
BaseResponseEnum
{
MISSING_TOKEN
(
"401"
,
"HEADER中不存在TOKEN"
),
INVALID_TOKEN
(
"401"
,
"校验TOKEN失败"
),
EXPIRED_TOKEN
(
"401"
,
"TOKEN已过期"
),
MISSING_CLAIMS
(
"401"
,
"不合法的TOKEN, 信息可能被篡改"
),
INVALID_CLAIM
(
"401"
,
"不合法的TOKEN, 系统中不存在资源"
);
private
String
value
;
private
String
text
;
AuthorizationResponseEnum
(
String
value
,
String
text
)
{
this
.
value
=
value
;
this
.
text
=
text
;
}
@Override
public
String
value
()
{
return
this
.
value
;
}
@Override
public
String
text
()
{
return
this
.
text
;
}
}
src/main/java/com/qkdata/common/oauth/AuthorizedUser.java
0 → 100644
View file @
7409526c
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 @
7409526c
/**
* Copyright (c) 2016-2019 人人开源 All rights reserved.
*
*
* 版权所有,侵权必究!
*/
package
com
.
qkdata
.
common
.
oauth
;
import
com.fasterxml.jackson.databind.ObjectMapper
;
import
com.qkdata.common.base.model.ResponseData
;
import
com.qkdata.common.util.HttpContextUtils
;
import
org.apache.http.HttpStatus
;
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不存在,直接返回401
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
());
ResponseData
responseData
=
new
ResponseData
(
AuthorizationResponseEnum
.
MISSING_TOKEN
);
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
();
ResponseData
rd
=
new
ResponseData
(
"401"
,
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 @
7409526c
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.base.enums.AccountStatusEnum
;
import
com.qkdata.biz.sys.entity.SysUserPO
;
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.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
=
shiroService
.
getUserPermissions
(
userId
);
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
AuthorizationException
(
"request header中没有token"
,
AuthorizationResponseEnum
.
MISSING_TOKEN
);
}
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 @
7409526c
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 @
7409526c
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 @
7409526c
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 @
7409526c
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 @
7409526c
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 @
7409526c
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 @
7409526c
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 @
7409526c
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 @
7409526c
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 @
7409526c
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 @
7409526c
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 @
7409526c
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
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 @
7409526c
/**
* 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/Iterables.java
0 → 100644
View file @
7409526c
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 @
7409526c
package
com
.
qkdata
.
common
.
util
;
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
(
"UTF-8"
));
StringBuilder
sb
=
new
StringBuilder
();
for
(
byte
item
:
array
)
{
sb
.
append
(
Integer
.
toHexString
((
item
&
0xFF
)
|
0x100
).
substring
(
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 @
7409526c
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 @
7409526c
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.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
(),
"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/resources/application-dev.yml
0 → 100644
View file @
7409526c
server
:
port
:
8080
spring
:
datasource
:
druid
:
url
:
jdbc:mysql://localhost:3306/framework?useUnicode=true&characterEncoding=UTF-8&allowMultiQueries=true&useSSL=false
username
:
root
password
:
123456
# redis:
# host: localhost
log
:
path
:
../data/logs
file
:
rootPath
:
../data/files
src/main/resources/application.yml
0 → 100644
View file @
7409526c
server
:
port
:
80
servlet
:
context-path
:
/backend-java
management
:
endpoint
:
health
:
show-details
:
always
spring
:
datasource
:
druid
:
url
:
jdbc:mysql://mysql:3306/wx_monitor?useUnicode=true&characterEncoding=UTF-8&allowMultiQueries=true&useSSL=false
username
:
root
password
:
123456
driver-class-name
:
com.mysql.jdbc.Driver
initialSize
:
5
minIdle
:
5
maxActive
:
30
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
# timeout: 2s
# jedis:
# pool:
# max-active: 20
# max-wait: -1ms
# max-idle: 20
# min-idle: 0
# database: 0
mvc
:
throw-exception-if-no-handler-found
:
true
resources
:
add-mappings
:
true
main
:
allow-bean-definition-overriding
:
true
# flyway:
# baseline-on-migrate: true
# placeholder-replacement: false
mybatis
:
mapper-locations
:
classpath*:mappers/*.xml
type-handlers-package
:
com.qkdata.common.config
configuration
:
map-underscore-to-camel-case
:
true
log
:
context
:
backend-java
path
:
/data/logs
jwt
:
secret
:
backend-java-prod
enable-interceptor
:
true
include-urls
:
-
/api/**
exclude-urls
:
-
/api/sys/login
aud
:
backend-java
exp
:
24
file
:
rootPath
:
/data/files
src/main/resources/db/migration/V1.0.0__init.sql
0 → 100644
View file @
7409526c
-- ----------------------------
-- 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
)
NULL
DEFAULT
NULL
COMMENT
'key'
,
`param_value`
varchar
(
2000
)
NULL
DEFAULT
NULL
COMMENT
'value'
,
`status`
tinyint
(
4
)
NULL
DEFAULT
1
COMMENT
'状态 0:隐藏 1:显示'
,
`remark`
varchar
(
500
)
NULL
DEFAULT
NULL
COMMENT
'备注'
,
PRIMARY
KEY
(
`id`
)
USING
BTREE
,
UNIQUE
INDEX
`param_key`
(
`param_key`
)
USING
BTREE
)
ENGINE
=
InnoDB
AUTO_INCREMENT
=
2
COMMENT
=
'系统配置信息表'
ROW_FORMAT
=
Dynamic
;
-- ----------------------------
-- Records of sys_config
-- ----------------------------
INSERT
INTO
`sys_config`
VALUES
(
1
,
'CLOUD_STORAGE_CONFIG_KEY'
,
'{
\"
type
\"
:3,
\"
qiniuDomain
\"
:
\"\"
,
\"
qiniuPrefix
\"
:
\"\"
,
\"
qiniuAccessKey
\"
:
\"\"
,
\"
qiniuSecretKey
\"
:
\"\"
,
\"
qiniuBucketName
\"
:
\"\"
,
\"
aliyunDomain
\"
:
\"\"
,
\"
aliyunPrefix
\"
:
\"\"
,
\"
aliyunEndPoint
\"
:
\"\"
,
\"
aliyunAccessKeyId
\"
:
\"\"
,
\"
aliyunAccessKeySecret
\"
:
\"\"
,
\"
aliyunBucketName
\"
:
\"\"
,
\"
qcloudDomain
\"
:
\"\"
,
\"
qcloudPrefix
\"
:
\"\"
,
\"
qcloudAppId
\"
:1254964270,
\"
qcloudSecretId
\"
:
\"\"
,
\"
qcloudSecretKey
\"
:
\"\"
,
\"
qcloudBucketName
\"
:
\"
wx-1254964270
\"
,
\"
qcloudRegion
\"
:
\"
ap-guangzhou
\"
}'
,
0
,
'云存储配置信息'
);
-- ----------------------------
-- 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
)
NULL
DEFAULT
NULL
COMMENT
'父菜单ID,一级菜单为0'
,
`name`
varchar
(
50
)
NULL
DEFAULT
NULL
COMMENT
'菜单名称'
,
`url`
varchar
(
200
)
NULL
DEFAULT
NULL
COMMENT
'菜单URL'
,
`perms`
varchar
(
500
)
NULL
DEFAULT
NULL
COMMENT
'授权(多个用逗号分隔,如:user:list,user:create)'
,
`type`
int
(
11
)
NULL
DEFAULT
NULL
COMMENT
'类型 0:目录 1:菜单 2:按钮'
,
`icon`
varchar
(
50
)
NULL
DEFAULT
NULL
COMMENT
'菜单图标'
,
`order_num`
int
(
11
)
NULL
DEFAULT
NULL
COMMENT
'排序'
,
PRIMARY
KEY
(
`id`
)
USING
BTREE
)
ENGINE
=
InnoDB
AUTO_INCREMENT
=
108
COMMENT
=
'菜单管理'
ROW_FORMAT
=
Dynamic
;
-- ----------------------------
-- Records of sys_menu
-- ----------------------------
INSERT
INTO
`sys_menu`
VALUES
(
1
,
0
,
'系统管理'
,
NULL
,
NULL
,
0
,
'el-icon-s-tools'
,
0
);
INSERT
INTO
`sys_menu`
VALUES
(
2
,
1
,
'管理员列表'
,
'sys/user'
,
NULL
,
1
,
'admin'
,
1
);
INSERT
INTO
`sys_menu`
VALUES
(
3
,
1
,
'角色管理'
,
'sys/role'
,
NULL
,
1
,
'role'
,
2
);
INSERT
INTO
`sys_menu`
VALUES
(
4
,
1
,
'菜单管理'
,
'sys/menu'
,
NULL
,
1
,
'menu'
,
3
);
INSERT
INTO
`sys_menu`
VALUES
(
6
,
0
,
'微信管理'
,
NULL
,
NULL
,
0
,
'el-icon-s-promotion'
,
1
);
INSERT
INTO
`sys_menu`
VALUES
(
7
,
0
,
'内容管理'
,
''
,
''
,
0
,
'el-icon-document-copy'
,
2
);
INSERT
INTO
`sys_menu`
VALUES
(
9
,
0
,
'日志报表'
,
''
,
''
,
0
,
'el-icon-s-order'
,
4
);
INSERT
INTO
`sys_menu`
VALUES
(
15
,
2
,
'查看'
,
NULL
,
'sys:user:list,sys:user:info'
,
2
,
NULL
,
0
);
INSERT
INTO
`sys_menu`
VALUES
(
16
,
2
,
'新增'
,
NULL
,
'sys:user:save,sys:role:select'
,
2
,
NULL
,
0
);
INSERT
INTO
`sys_menu`
VALUES
(
17
,
2
,
'修改'
,
NULL
,
'sys:user:update,sys:role:select'
,
2
,
NULL
,
0
);
INSERT
INTO
`sys_menu`
VALUES
(
18
,
2
,
'删除'
,
NULL
,
'sys:user:delete'
,
2
,
NULL
,
0
);
INSERT
INTO
`sys_menu`
VALUES
(
19
,
3
,
'查看'
,
NULL
,
'sys:role:list,sys:role:info'
,
2
,
NULL
,
0
);
INSERT
INTO
`sys_menu`
VALUES
(
20
,
3
,
'新增'
,
NULL
,
'sys:role:save,sys:menu:list'
,
2
,
NULL
,
0
);
INSERT
INTO
`sys_menu`
VALUES
(
21
,
3
,
'修改'
,
NULL
,
'sys:role:update,sys:menu:list'
,
2
,
NULL
,
0
);
INSERT
INTO
`sys_menu`
VALUES
(
22
,
3
,
'删除'
,
NULL
,
'sys:role:delete'
,
2
,
NULL
,
0
);
INSERT
INTO
`sys_menu`
VALUES
(
23
,
4
,
'查看'
,
NULL
,
'sys:menu:list,sys:menu:info'
,
2
,
NULL
,
0
);
INSERT
INTO
`sys_menu`
VALUES
(
24
,
4
,
'新增'
,
NULL
,
'sys:menu:save,sys:menu:select'
,
2
,
NULL
,
0
);
INSERT
INTO
`sys_menu`
VALUES
(
25
,
4
,
'修改'
,
NULL
,
'sys:menu:update,sys:menu:select'
,
2
,
NULL
,
0
);
INSERT
INTO
`sys_menu`
VALUES
(
26
,
4
,
'删除'
,
NULL
,
'sys:menu:delete'
,
2
,
NULL
,
0
);
INSERT
INTO
`sys_menu`
VALUES
(
27
,
1
,
'参数管理'
,
'sys/config'
,
'sys:config:list,sys:config:info,sys:config:save,sys:config:update,sys:config:delete'
,
1
,
'config'
,
6
);
INSERT
INTO
`sys_menu`
VALUES
(
29
,
9
,
'系统日志'
,
'sys/log'
,
'sys:log:list'
,
1
,
'log'
,
7
);
INSERT
INTO
`sys_menu`
VALUES
(
30
,
1
,
'文件上传'
,
'oss/oss'
,
'sys:oss:all'
,
1
,
'oss'
,
6
);
INSERT
INTO
`sys_menu`
VALUES
(
32
,
6
,
'公众号菜单'
,
'wx/wx-menu'
,
''
,
1
,
'log'
,
0
);
INSERT
INTO
`sys_menu`
VALUES
(
33
,
6
,
'图文素材'
,
'wx/material-news'
,
''
,
1
,
'log'
,
0
);
INSERT
INTO
`sys_menu`
VALUES
(
34
,
6
,
'媒体素材'
,
'wx/material-file'
,
NULL
,
1
,
'log'
,
0
);
INSERT
INTO
`sys_menu`
VALUES
(
35
,
34
,
'新增'
,
''
,
'wx:material:save'
,
2
,
''
,
0
);
INSERT
INTO
`sys_menu`
VALUES
(
41
,
7
,
'文章公告'
,
'wx/article'
,
NULL
,
1
,
'config'
,
6
);
INSERT
INTO
`sys_menu`
VALUES
(
42
,
41
,
'查看'
,
NULL
,
'wx:article:list,wx:article:info'
,
2
,
NULL
,
6
);
INSERT
INTO
`sys_menu`
VALUES
(
43
,
41
,
'新增'
,
NULL
,
'wx:article:save'
,
2
,
NULL
,
6
);
INSERT
INTO
`sys_menu`
VALUES
(
44
,
41
,
'修改'
,
NULL
,
'wx:article:update'
,
2
,
NULL
,
6
);
INSERT
INTO
`sys_menu`
VALUES
(
45
,
41
,
'删除'
,
NULL
,
'wx:article:delete'
,
2
,
NULL
,
6
);
INSERT
INTO
`sys_menu`
VALUES
(
66
,
6
,
'自动回复规则'
,
'wx/msgreplyrule'
,
NULL
,
1
,
'config'
,
6
);
INSERT
INTO
`sys_menu`
VALUES
(
67
,
66
,
'查看'
,
NULL
,
'wx:msgreplyrule:list,wx:msgreplyrule:info'
,
2
,
NULL
,
6
);
INSERT
INTO
`sys_menu`
VALUES
(
68
,
66
,
'新增'
,
NULL
,
'wx:msgreplyrule:save'
,
2
,
NULL
,
6
);
INSERT
INTO
`sys_menu`
VALUES
(
69
,
66
,
'修改'
,
NULL
,
'wx:msgreplyrule:update'
,
2
,
NULL
,
6
);
INSERT
INTO
`sys_menu`
VALUES
(
70
,
66
,
'删除'
,
NULL
,
'wx:msgreplyrule:delete'
,
2
,
NULL
,
6
);
INSERT
INTO
`sys_menu`
VALUES
(
71
,
6
,
'消息模板'
,
'wx/msgtemplate'
,
NULL
,
1
,
'config'
,
6
);
INSERT
INTO
`sys_menu`
VALUES
(
72
,
71
,
'查看'
,
NULL
,
'wx:msgtemplate:list,wx:msgtemplate:info'
,
2
,
NULL
,
6
);
INSERT
INTO
`sys_menu`
VALUES
(
73
,
71
,
'新增'
,
NULL
,
'wx:msgtemplate:save'
,
2
,
NULL
,
6
);
INSERT
INTO
`sys_menu`
VALUES
(
74
,
71
,
'修改'
,
NULL
,
'wx:msgtemplate:update'
,
2
,
NULL
,
6
);
INSERT
INTO
`sys_menu`
VALUES
(
75
,
71
,
'删除'
,
NULL
,
'wx:msgtemplate:delete'
,
2
,
NULL
,
6
);
INSERT
INTO
`sys_menu`
VALUES
(
81
,
9
,
'模版消息发送记录'
,
'wx/templatemsglog'
,
NULL
,
1
,
'config'
,
6
);
INSERT
INTO
`sys_menu`
VALUES
(
82
,
81
,
'查看'
,
NULL
,
'wx:templatemsglog:list,wx:templatemsglog:info'
,
2
,
NULL
,
6
);
INSERT
INTO
`sys_menu`
VALUES
(
83
,
81
,
'新增'
,
NULL
,
'wx:templatemsglog:save'
,
2
,
NULL
,
6
);
INSERT
INTO
`sys_menu`
VALUES
(
84
,
81
,
'修改'
,
NULL
,
'wx:templatemsglog:update'
,
2
,
NULL
,
6
);
INSERT
INTO
`sys_menu`
VALUES
(
85
,
81
,
'删除'
,
NULL
,
'wx:templatemsglog:delete'
,
2
,
NULL
,
6
);
INSERT
INTO
`sys_menu`
VALUES
(
99
,
32
,
'更新公众号菜单'
,
''
,
'wx:menu:save'
,
2
,
''
,
0
);
INSERT
INTO
`sys_menu`
VALUES
(
100
,
33
,
'图文素材-查看'
,
''
,
'wx:material:list'
,
2
,
''
,
0
);
INSERT
INTO
`sys_menu`
VALUES
(
101
,
33
,
'图文素材-新增'
,
''
,
'wx:material:save'
,
2
,
''
,
0
);
INSERT
INTO
`sys_menu`
VALUES
(
102
,
34
,
'多媒体素材-查看'
,
''
,
'wx:material:save'
,
2
,
''
,
0
);
INSERT
INTO
`sys_menu`
VALUES
(
103
,
6
,
'带参二维码'
,
'wx/wxqrcode'
,
NULL
,
1
,
'config'
,
6
);
INSERT
INTO
`sys_menu`
VALUES
(
104
,
103
,
'查看'
,
NULL
,
'wx:wxqrcode:list,wx:wxqrcode:info'
,
2
,
NULL
,
6
);
INSERT
INTO
`sys_menu`
VALUES
(
105
,
103
,
'新增'
,
NULL
,
'wx:wxqrcode:save'
,
2
,
NULL
,
6
);
INSERT
INTO
`sys_menu`
VALUES
(
107
,
103
,
'删除'
,
NULL
,
'wx:wxqrcode:delete'
,
2
,
NULL
,
6
);
-- ----------------------------
-- Table structure for sys_oss
-- ----------------------------
DROP
TABLE
IF
EXISTS
`sys_oss`
;
CREATE
TABLE
`sys_oss`
(
`id`
bigint
(
20
)
NOT
NULL
AUTO_INCREMENT
,
`url`
varchar
(
200
)
NULL
DEFAULT
NULL
COMMENT
'URL地址'
,
PRIMARY
KEY
(
`id`
)
USING
BTREE
)
ENGINE
=
InnoDB
AUTO_INCREMENT
=
6
COMMENT
=
'文件上传'
ROW_FORMAT
=
Dynamic
;
-- ----------------------------
-- Table structure for sys_role
-- ----------------------------
DROP
TABLE
IF
EXISTS
`sys_role`
;
CREATE
TABLE
`sys_role`
(
`id`
bigint
(
20
)
NOT
NULL
AUTO_INCREMENT
,
`name`
varchar
(
100
)
NULL
DEFAULT
NULL
COMMENT
'角色名称'
,
`remark`
varchar
(
100
)
NULL
DEFAULT
NULL
COMMENT
'备注'
,
PRIMARY
KEY
(
`id`
)
USING
BTREE
)
ENGINE
=
InnoDB
AUTO_INCREMENT
=
1
COMMENT
=
'角色'
ROW_FORMAT
=
Dynamic
;
-- ----------------------------
-- 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
)
NULL
DEFAULT
NULL
COMMENT
'角色ID'
,
`menu_id`
bigint
(
20
)
NULL
DEFAULT
NULL
COMMENT
'菜单ID'
,
PRIMARY
KEY
(
`id`
)
USING
BTREE
)
ENGINE
=
InnoDB
AUTO_INCREMENT
=
1
COMMENT
=
'角色与菜单对应关系'
ROW_FORMAT
=
Dynamic
;
-- ----------------------------
-- Table structure for sys_user
-- ----------------------------
DROP
TABLE
IF
EXISTS
`sys_user`
;
CREATE
TABLE
`sys_user`
(
`id`
bigint
(
20
)
NOT
NULL
AUTO_INCREMENT
,
`username`
varchar
(
50
)
NOT
NULL
COMMENT
'用户名'
,
`password`
varchar
(
100
)
NULL
DEFAULT
NULL
COMMENT
'密码'
,
`salt`
varchar
(
20
)
NULL
DEFAULT
NULL
COMMENT
'盐'
,
`email`
varchar
(
100
)
NULL
DEFAULT
NULL
COMMENT
'邮箱'
,
`mobile`
varchar
(
100
)
NULL
DEFAULT
NULL
COMMENT
'手机号'
,
`status`
tinyint
(
4
)
NULL
DEFAULT
NULL
COMMENT
'状态 0:禁用 1:正常'
,
`create_at`
datetime
(
0
)
NULL
DEFAULT
NULL
COMMENT
'创建时间'
,
PRIMARY
KEY
(
`id`
)
USING
BTREE
,
UNIQUE
INDEX
`username`
(
`username`
)
USING
BTREE
)
ENGINE
=
InnoDB
AUTO_INCREMENT
=
2
COMMENT
=
'系统用户'
ROW_FORMAT
=
Dynamic
;
-- ----------------------------
-- Records of sys_user
-- ----------------------------
INSERT
INTO
`sys_user`
VALUES
(
1
,
'admin'
,
'cdac762d0ba79875489f6a8b430fa8b5dfe0cdd81da38b80f02f33328af7fd4a'
,
'YzcmCZNvbXocrsz9dm8e'
,
'niefy@qq.com'
,
'16666666666'
,
1
,
'2016-11-11 11:11:11'
);
-- ----------------------------
-- 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
,
`user_id`
bigint
(
20
)
NULL
DEFAULT
NULL
COMMENT
'用户ID'
,
`role_id`
bigint
(
20
)
NULL
DEFAULT
NULL
COMMENT
'角色ID'
,
PRIMARY
KEY
(
`id`
)
USING
BTREE
)
ENGINE
=
InnoDB
AUTO_INCREMENT
=
1
COMMENT
=
'用户与角色对应关系'
ROW_FORMAT
=
Dynamic
;
src/main/resources/logback-spring.xml
0 → 100644
View file @
7409526c
<?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.brandKeyword.repository" level="DEBUG" 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/SysUserMapper.xml
0 → 100644
View file @
7409526c
<?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.repository.SysUserMapper"
>
<!-- 查询用户的所有权限 -->
<select
id=
"queryAllPerms"
resultType=
"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.menu_id
where ur.user_id = #{userId}
</select>
</mapper>
\ No newline at end of file
src/main/resources/static/index.html
0 → 100644
View file @
7409526c
<!DOCTYPE html>
<html
xmlns:th=
"http://www.thymeleaf.org"
>
<head>
<meta
charset=
"UTF-8"
/>
<title>
Spring Boot+WebSocket+广播式
</title>
</head>
<body
onload=
"disconnect()"
>
<noscript><h2
style=
"color: #ff0000"
>
貌似你的浏览器不支持websocket
</h2>
</noscript>
<div>
<div>
<button
id=
"connect"
onclick=
"connect();"
>
连接
</button>
<button
id=
"disconnect"
disabled=
"disabled"
onclick=
"disconnect();"
>
断开连接
</button>
</div>
<div
id=
"conversationDiv"
>
<label>
输入你的名字
</label><input
type=
"text"
id=
"name"
/>
<button
id=
"sendName"
onclick=
"sendName();"
>
发送
</button>
<p
id=
"response"
></p>
<p
id=
"response1"
></p>
</div>
</div>
<!--<script th:src="@{sockjs.min.js}"></script>
<script th:src="@{stomp.min.js}"></script>
<script th:src="@{jquery.js}"></script>-->
<script
src=
"https://cdn.bootcss.com/sockjs-client/1.1.4/sockjs.min.js"
>
</script>
<script
src=
"https://cdn.bootcss.com/stomp.js/2.3.3/stomp.min.js"
></script>
<script
src=
"https://cdn.bootcss.com/jquery/3.2.1/jquery.min.js"
></script>
<script
th:inline=
"javascript"
>
var
stompClient
=
null
;
//此值有服务端传递给前端,实现方式没有要求
var
userId
=
'admin'
;
function
setConnected
(
connected
)
{
document
.
getElementById
(
'connect'
).
disabled
=
connected
;
document
.
getElementById
(
'disconnect'
).
disabled
=
!
connected
;
document
.
getElementById
(
'conversationDiv'
).
style
.
visibility
=
connected
?
'visible'
:
'hidden'
;
$
(
'#response'
).
html
();
}
function
connect
()
{
var
socket
=
new
SockJS
(
'/wx-monitor-server/websocket?token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJ3eC1tb25pdG9yLXNlcnZlciIsImlzcyI6InNoYW5nd2VpIiwiZXhwIjoxNTk0ODc5NDI3LCJpYXQiOjE1NjMzNDM0MjcsInVzZXIiOiJ7XCJ1c2VySWRcIjoyLFwiYWNjb3VudFwiOlwiYWRtaW5cIixcInJvbGVcIjoxfSJ9.WTb5VhEoPgCcGKKH9eIE8m5fsfPW3PXT7a8hWDHnTr0'
);
//1连接SockJS的endpoint是“endpointWisely”,与后台代码中注册的endpoint要一样。
stompClient
=
Stomp
.
over
(
socket
);
//2创建STOMP协议的webSocket客户端。
stompClient
.
connect
({},
function
(
frame
)
{
//3连接webSocket的服务端。
setConnected
(
true
);
console
.
log
(
'开始进行连接Connected: '
+
frame
);
stompClient
.
subscribe
(
'/user/topic/room'
,
function
(
respnose
){
console
.
log
(
respnose
);
});
stompClient
.
subscribe
(
'/user/topic/login'
,
function
(
respnose
){
console
.
log
(
respnose
);
});
});
}
function
disconnect
()
{
if
(
stompClient
!=
null
)
{
stompClient
.
disconnect
();
}
setConnected
(
false
);
console
.
log
(
"Disconnected"
);
}
function
sendName
()
{
var
name
=
$
(
'#name'
).
val
();
//通过stompClient.send()向地址为"/welcome"的服务器地址发起请求,与@MessageMapping里的地址对应。因为我们配置了registry.setApplicationDestinationPrefixes(Constant.WEBSOCKETPATHPERFIX);所以需要增加前缀/ws-push/
stompClient
.
send
(
"/ws-push/welcome"
,
{},
JSON
.
stringify
({
'name'
:
name
}));
}
function
showResponse
(
message
)
{
var
response
=
$
(
"#response"
);
response
.
html
(
message
);
}
function
showResponse1
(
message
)
{
var
response
=
$
(
"#response1"
);
response
.
html
(
message
);
}
</script>
</body>
</html>
src/test/java/com/qkdata/test/BaseTest.java
0 → 100644
View file @
7409526c
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
{
}
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