commit
07a0553e03
@ -0,0 +1 @@
|
|||||||
|
*.sql linguist-language=java
|
@ -0,0 +1,51 @@
|
|||||||
|
######################################################################
|
||||||
|
# Build Tools
|
||||||
|
|
||||||
|
.gradle
|
||||||
|
/build/
|
||||||
|
!gradle/wrapper/gradle-wrapper.jar
|
||||||
|
|
||||||
|
target/
|
||||||
|
!.mvn/wrapper/maven-wrapper.jar
|
||||||
|
|
||||||
|
######################################################################
|
||||||
|
# IDE
|
||||||
|
|
||||||
|
### STS ###
|
||||||
|
.apt_generated
|
||||||
|
.classpath
|
||||||
|
.factorypath
|
||||||
|
.project
|
||||||
|
.settings
|
||||||
|
.springBeans
|
||||||
|
|
||||||
|
### IntelliJ IDEA ###
|
||||||
|
.idea
|
||||||
|
*.iws
|
||||||
|
*.iml
|
||||||
|
*.ipr
|
||||||
|
|
||||||
|
### NetBeans ###
|
||||||
|
nbproject/private/
|
||||||
|
build/*
|
||||||
|
nbbuild/
|
||||||
|
dist/
|
||||||
|
nbdist/
|
||||||
|
.nb-gradle/
|
||||||
|
|
||||||
|
######################################################################
|
||||||
|
# Others
|
||||||
|
*.log
|
||||||
|
*.xml.versionsBackup
|
||||||
|
*.swp
|
||||||
|
|
||||||
|
!*/build/*.java
|
||||||
|
!*/build/*.html
|
||||||
|
!*/build/*.xml
|
||||||
|
|
||||||
|
### JRebel ###
|
||||||
|
rebel.xml
|
||||||
|
|
||||||
|
application-my.yaml
|
||||||
|
|
||||||
|
/yunxi-ui-app/unpackage/
|
@ -0,0 +1,60 @@
|
|||||||
|
#!groovy
|
||||||
|
pipeline {
|
||||||
|
|
||||||
|
agent any
|
||||||
|
|
||||||
|
parameters {
|
||||||
|
string(name: 'TAG_NAME', defaultValue: '', description: '')
|
||||||
|
}
|
||||||
|
|
||||||
|
environment {
|
||||||
|
// DockerHub 凭证 ID(登录您的 DockerHub)
|
||||||
|
DOCKER_CREDENTIAL_ID = 'dockerhub-id'
|
||||||
|
// GitHub 凭证 ID (推送 tag 到 GitHub 仓库)
|
||||||
|
GITHUB_CREDENTIAL_ID = 'github-id'
|
||||||
|
// kubeconfig 凭证 ID (访问接入正在运行的 Kubernetes 集群)
|
||||||
|
KUBECONFIG_CREDENTIAL_ID = 'demo-kubeconfig'
|
||||||
|
// 镜像的推送
|
||||||
|
REGISTRY = 'docker.io'
|
||||||
|
// DockerHub 账号名
|
||||||
|
DOCKERHUB_NAMESPACE = 'docker_username'
|
||||||
|
// GitHub 账号名
|
||||||
|
GITHUB_ACCOUNT = 'https://gitee.com/zhijiantianya/ruoyi-vue-pro'
|
||||||
|
// 应用名称
|
||||||
|
APP_NAME = 'yunxi-server'
|
||||||
|
// 应用部署路径
|
||||||
|
APP_DEPLOY_BASE_DIR = '/media/pi/KINGTON/data/work/projects/'
|
||||||
|
}
|
||||||
|
|
||||||
|
stages {
|
||||||
|
stage('检出') {
|
||||||
|
steps {
|
||||||
|
git url: "https://gitee.com/will-we/ruoyi-vue-pro.git",
|
||||||
|
branch: "devops"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
stage('构建') {
|
||||||
|
steps {
|
||||||
|
// TODO 解决多环境链接、密码不同配置临时方案
|
||||||
|
sh 'if [ ! -d "' + "${env.HOME}" + '/resources" ];then\n' +
|
||||||
|
' echo "配置文件不存在无需修改"\n' +
|
||||||
|
'else\n' +
|
||||||
|
' cp -rf ' + "${env.HOME}" + '/resources/*.yaml ' + "${env.APP_NAME}" + '/src/main/resources\n' +
|
||||||
|
' echo "配置文件替换"\n' +
|
||||||
|
'fi'
|
||||||
|
sh 'mvn clean package -Dmaven.test.skip=true'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
stage('部署') {
|
||||||
|
steps {
|
||||||
|
sh 'cp -f ' + ' bin/deploy.sh ' + "${env.APP_DEPLOY_BASE_DIR}" + "${env.APP_NAME}"
|
||||||
|
sh 'cp -f ' + "${env.APP_NAME}" + '/target/*.jar ' + "${env.APP_DEPLOY_BASE_DIR}" + "${env.APP_NAME}" +'/build/'
|
||||||
|
archiveArtifacts "${env.APP_NAME}" + '/target/*.jar'
|
||||||
|
sh 'chmod +x ' + "${env.APP_DEPLOY_BASE_DIR}" + "${env.APP_NAME}" + '/deploy.sh'
|
||||||
|
sh 'bash ' + "${env.APP_DEPLOY_BASE_DIR}" + "${env.APP_NAME}" + '/deploy.sh'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,20 @@
|
|||||||
|
The MIT License (MIT)
|
||||||
|
|
||||||
|
Copyright (c) 2021 ruoyi-vue-pro
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||||
|
this software and associated documentation files (the "Software"), to deal in
|
||||||
|
the Software without restriction, including without limitation the rights to
|
||||||
|
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||||
|
the Software, and to permit persons to whom the Software is furnished to do so,
|
||||||
|
subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||||
|
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||||
|
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||||
|
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
@ -0,0 +1,84 @@
|
|||||||
|
version: "3.4"
|
||||||
|
|
||||||
|
name: yunxi-system
|
||||||
|
|
||||||
|
services:
|
||||||
|
mysql:
|
||||||
|
container_name: yunxi-mysql
|
||||||
|
image: mysql:8
|
||||||
|
restart: unless-stopped
|
||||||
|
tty: true
|
||||||
|
ports:
|
||||||
|
- "3306:3306"
|
||||||
|
environment:
|
||||||
|
MYSQL_DATABASE: ${MYSQL_DATABASE:-ruoyi-vue-pro}
|
||||||
|
MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD:-123456}
|
||||||
|
volumes:
|
||||||
|
- mysql:/var/lib/mysql/
|
||||||
|
- ./sql/mysql/ruoyi-vue-pro.sql:/docker-entrypoint-initdb.d/ruoyi-vue-pro.sql:ro
|
||||||
|
|
||||||
|
redis:
|
||||||
|
container_name: yunxi-redis
|
||||||
|
image: redis:6-alpine
|
||||||
|
restart: unless-stopped
|
||||||
|
ports:
|
||||||
|
- "6379:6379"
|
||||||
|
volumes:
|
||||||
|
- redis:/data
|
||||||
|
|
||||||
|
server:
|
||||||
|
container_name: yunxi-server
|
||||||
|
build:
|
||||||
|
context: ./yunxi-server/
|
||||||
|
image: yunxi-server
|
||||||
|
restart: unless-stopped
|
||||||
|
ports:
|
||||||
|
- "48080:48080"
|
||||||
|
environment:
|
||||||
|
# https://github.com/polovyivan/docker-pass-configs-to-container
|
||||||
|
SPRING_PROFILES_ACTIVE: local
|
||||||
|
JAVA_OPTS:
|
||||||
|
${JAVA_OPTS:-
|
||||||
|
-Xms512m
|
||||||
|
-Xmx512m
|
||||||
|
-Djava.security.egd=file:/dev/./urandom
|
||||||
|
}
|
||||||
|
ARGS:
|
||||||
|
--spring.datasource.dynamic.datasource.master.url=${MASTER_DATASOURCE_URL:-jdbc:mysql://yunxi-mysql:3306/ruoyi-vue-pro?useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true&nullCatalogMeansCurrent=true}
|
||||||
|
--spring.datasource.dynamic.datasource.master.username=${MASTER_DATASOURCE_USERNAME:-root}
|
||||||
|
--spring.datasource.dynamic.datasource.master.password=${MASTER_DATASOURCE_PASSWORD:-123456}
|
||||||
|
--spring.datasource.dynamic.datasource.slave.url=${SLAVE_DATASOURCE_URL:-jdbc:mysql://yunxi-mysql:3306/ruoyi-vue-pro?useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true&nullCatalogMeansCurrent=true}
|
||||||
|
--spring.datasource.dynamic.datasource.slave.username=${SLAVE_DATASOURCE_USERNAME:-root}
|
||||||
|
--spring.datasource.dynamic.datasource.slave.password=${SLAVE_DATASOURCE_PASSWORD:-123456}
|
||||||
|
--spring.redis.host=${REDIS_HOST:-yunxi-redis}
|
||||||
|
depends_on:
|
||||||
|
- mysql
|
||||||
|
- redis
|
||||||
|
|
||||||
|
admin:
|
||||||
|
container_name: yunxi-admin
|
||||||
|
build:
|
||||||
|
context: ./yunxi-ui-admin
|
||||||
|
args:
|
||||||
|
NODE_ENV:
|
||||||
|
ENV=${NODE_ENV:-production}
|
||||||
|
PUBLIC_PATH=${PUBLIC_PATH:-/}
|
||||||
|
VUE_APP_TITLE=${VUE_APP_TITLE:-云息供应链管理平台}
|
||||||
|
VUE_APP_BASE_API=${VUE_APP_BASE_API:-/prod-api}
|
||||||
|
VUE_APP_APP_NAME=${VUE_APP_APP_NAME:-/}
|
||||||
|
VUE_APP_TENANT_ENABLE=${VUE_APP_TENANT_ENABLE:-true}
|
||||||
|
VUE_APP_CAPTCHA_ENABLE=${VUE_APP_CAPTCHA_ENABLE:-true}
|
||||||
|
VUE_APP_DOC_ENABLE=${VUE_APP_DOC_ENABLE:-true}
|
||||||
|
VUE_APP_BAIDU_CODE=${VUE_APP_BAIDU_CODE:-fadc1bd5db1a1d6f581df60a1807f8ab}
|
||||||
|
image: yunxi-admin
|
||||||
|
restart: unless-stopped
|
||||||
|
ports:
|
||||||
|
- "8080:80"
|
||||||
|
depends_on:
|
||||||
|
- server
|
||||||
|
|
||||||
|
volumes:
|
||||||
|
mysql:
|
||||||
|
driver: local
|
||||||
|
redis:
|
||||||
|
driver: local
|
@ -0,0 +1,25 @@
|
|||||||
|
## mysql
|
||||||
|
MYSQL_DATABASE=ruoyi-vue-pro
|
||||||
|
MYSQL_ROOT_PASSWORD=123456
|
||||||
|
|
||||||
|
## server
|
||||||
|
JAVA_OPTS=-Xms512m -Xmx512m -Djava.security.egd=file:/dev/./urandom
|
||||||
|
|
||||||
|
MASTER_DATASOURCE_URL=jdbc:mysql://yunxi-mysql:3306/${MYSQL_DATABASE}?useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true&nullCatalogMeansCurrent=true
|
||||||
|
MASTER_DATASOURCE_USERNAME=root
|
||||||
|
MASTER_DATASOURCE_PASSWORD=${MYSQL_ROOT_PASSWORD}
|
||||||
|
SLAVE_DATASOURCE_URL=${MASTER_DATASOURCE_URL}
|
||||||
|
SLAVE_DATASOURCE_USERNAME=${MASTER_DATASOURCE_USERNAME}
|
||||||
|
SLAVE_DATASOURCE_PASSWORD=${MASTER_DATASOURCE_PASSWORD}
|
||||||
|
REDIS_HOST=yunxi-redis
|
||||||
|
|
||||||
|
## admin
|
||||||
|
NODE_ENV=production
|
||||||
|
PUBLIC_PATH=/
|
||||||
|
VUE_APP_TITLE=云息供应链管理平台
|
||||||
|
VUE_APP_BASE_API=/prod-api
|
||||||
|
VUE_APP_APP_NAME=/
|
||||||
|
VUE_APP_TENANT_ENABLE=true
|
||||||
|
VUE_APP_CAPTCHA_ENABLE=true
|
||||||
|
VUE_APP_DOC_ENABLE=true
|
||||||
|
VUE_APP_BAIDU_CODE=fadc1bd5db1a1d6f581df60a1807f8ab
|
@ -0,0 +1,20 @@
|
|||||||
|
{
|
||||||
|
"local": {
|
||||||
|
"baseUrl": "http://127.0.0.1:48080/admin-api",
|
||||||
|
"token": "test1",
|
||||||
|
"adminTenentId": "1",
|
||||||
|
|
||||||
|
"appApi": "http://127.0.0.1:48080/app-api",
|
||||||
|
"appToken": "test247",
|
||||||
|
"appTenentId": "1"
|
||||||
|
},
|
||||||
|
"gateway": {
|
||||||
|
"baseUrl": "http://127.0.0.1:8888/admin-api",
|
||||||
|
"token": "test1",
|
||||||
|
"adminTenentId": "1",
|
||||||
|
|
||||||
|
"appApi": "http://127.0.0.1:8888/app-api",
|
||||||
|
"appToken": "test1",
|
||||||
|
"appTenantId": "1"
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,4 @@
|
|||||||
|
config.stopBubbling = true
|
||||||
|
lombok.tostring.callsuper=CALL
|
||||||
|
lombok.equalsandhashcode.callsuper=CALL
|
||||||
|
lombok.accessors.chain=true
|
@ -0,0 +1,113 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
<groupId>com.yunxi.scm</groupId>
|
||||||
|
<artifactId>yunxi</artifactId>
|
||||||
|
<version>${revision}</version>
|
||||||
|
<packaging>pom</packaging>
|
||||||
|
<modules>
|
||||||
|
<module>yunxi-dependencies</module>
|
||||||
|
<module>yunxi-framework</module>
|
||||||
|
<!-- Server 主项目 -->
|
||||||
|
<module>yunxi-server</module>
|
||||||
|
<!-- 各种 module 拓展 -->
|
||||||
|
<module>yunxi-module-member</module>
|
||||||
|
<module>yunxi-module-system</module>
|
||||||
|
<module>yunxi-module-infra</module>
|
||||||
|
<!-- <module>yunxi-module-pay</module>-->
|
||||||
|
<!-- <module>yunxi-module-bpm</module>-->
|
||||||
|
<!-- <module>yunxi-module-report</module>-->
|
||||||
|
<!-- <module>yunxi-module-mp</module>-->
|
||||||
|
<!-- <module>yunxi-module-mall</module>-->
|
||||||
|
<!-- 示例项目 -->
|
||||||
|
<module>yunxi-example</module>
|
||||||
|
</modules>
|
||||||
|
|
||||||
|
<name>${project.artifactId}</name>
|
||||||
|
<description>芋道项目基础脚手架</description>
|
||||||
|
<url>https://github.com/YunaiV/ruoyi-vue-pro</url>
|
||||||
|
|
||||||
|
<properties>
|
||||||
|
<revision>1.8.0-snapshot</revision>
|
||||||
|
<!-- Maven 相关 -->
|
||||||
|
<java.version>1.8</java.version>
|
||||||
|
<maven.compiler.source>${java.version}</maven.compiler.source>
|
||||||
|
<maven.compiler.target>${java.version}</maven.compiler.target>
|
||||||
|
<maven-surefire-plugin.version>3.0.0-M5</maven-surefire-plugin.version>
|
||||||
|
<maven-compiler-plugin.version>3.8.1</maven-compiler-plugin.version>
|
||||||
|
<!-- 看看咋放到 bom 里 -->
|
||||||
|
<lombok.version>1.18.28</lombok.version>
|
||||||
|
<spring.boot.version>2.7.13</spring.boot.version>
|
||||||
|
<mapstruct.version>1.5.5.Final</mapstruct.version>
|
||||||
|
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||||
|
</properties>
|
||||||
|
|
||||||
|
<dependencyManagement>
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.yunxi.scm</groupId>
|
||||||
|
<artifactId>yunxi-dependencies</artifactId>
|
||||||
|
<version>${revision}</version>
|
||||||
|
<type>pom</type>
|
||||||
|
<scope>import</scope>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
</dependencyManagement>
|
||||||
|
|
||||||
|
<build>
|
||||||
|
<pluginManagement>
|
||||||
|
<plugins>
|
||||||
|
<!-- maven-surefire-plugin 插件,用于运行单元测试。 -->
|
||||||
|
<!-- 注意,需要使用 3.0.X+,因为要支持 Junit 5 版本 -->
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-surefire-plugin</artifactId>
|
||||||
|
<version>${maven-surefire-plugin.version}</version>
|
||||||
|
</plugin>
|
||||||
|
<!-- maven-compiler-plugin 插件,解决 spring-boot-configuration-processor + Lombok + MapStruct 组合 -->
|
||||||
|
<!-- https://stackoverflow.com/questions/33483697/re-run-spring-boot-configuration-annotation-processor-to-update-generated-metada -->
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-compiler-plugin</artifactId>
|
||||||
|
<version>${maven-compiler-plugin.version}</version>
|
||||||
|
<configuration>
|
||||||
|
<annotationProcessorPaths>
|
||||||
|
<path>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-configuration-processor</artifactId>
|
||||||
|
<version>${spring.boot.version}</version>
|
||||||
|
</path>
|
||||||
|
<path>
|
||||||
|
<groupId>org.projectlombok</groupId>
|
||||||
|
<artifactId>lombok</artifactId>
|
||||||
|
<version>${lombok.version}</version>
|
||||||
|
</path>
|
||||||
|
<path>
|
||||||
|
<groupId>org.mapstruct</groupId>
|
||||||
|
<artifactId>mapstruct-processor</artifactId>
|
||||||
|
<version>${mapstruct.version}</version>
|
||||||
|
</path>
|
||||||
|
</annotationProcessorPaths>
|
||||||
|
</configuration>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
</pluginManagement>
|
||||||
|
</build>
|
||||||
|
|
||||||
|
<!-- 使用 huawei / aliyun 的 Maven 源,提升下载速度 -->
|
||||||
|
<repositories>
|
||||||
|
<repository>
|
||||||
|
<id>huaweicloud</id>
|
||||||
|
<name>huawei</name>
|
||||||
|
<url>https://mirrors.huaweicloud.com/repository/maven/</url>
|
||||||
|
</repository>
|
||||||
|
<repository>
|
||||||
|
<id>aliyunmaven</id>
|
||||||
|
<name>aliyun</name>
|
||||||
|
<url>https://maven.aliyun.com/repository/public</url>
|
||||||
|
</repository>
|
||||||
|
</repositories>
|
||||||
|
|
||||||
|
</project>
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,648 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
<groupId>com.yunxi.scm</groupId>
|
||||||
|
<artifactId>yunxi-dependencies</artifactId>
|
||||||
|
<version>${revision}</version>
|
||||||
|
<packaging>pom</packaging>
|
||||||
|
|
||||||
|
<name>${project.artifactId}</name>
|
||||||
|
<description>基础 bom 文件,管理整个项目的依赖版本</description>
|
||||||
|
<url>https://github.com/YunaiV/ruoyi-vue-pro</url>
|
||||||
|
|
||||||
|
<properties>
|
||||||
|
<revision>1.8.0-snapshot</revision>
|
||||||
|
<!-- 统一依赖管理 -->
|
||||||
|
<spring.boot.version>2.7.13</spring.boot.version>
|
||||||
|
<!-- Web 相关 -->
|
||||||
|
<springdoc.version>1.6.15</springdoc.version>
|
||||||
|
<knife4j.version>4.1.0</knife4j.version>
|
||||||
|
<servlet.versoin>2.5</servlet.versoin>
|
||||||
|
<!-- DB 相关 -->
|
||||||
|
<druid.version>1.2.18</druid.version>
|
||||||
|
<mybatis-plus.version>3.5.3.1</mybatis-plus.version>
|
||||||
|
<mybatis-plus-generator.version>3.5.3.1</mybatis-plus-generator.version>
|
||||||
|
<dynamic-datasource.version>3.6.1</dynamic-datasource.version>
|
||||||
|
<mybatis-plus-join-boot-starter.version>1.4.5</mybatis-plus-join-boot-starter.version>
|
||||||
|
<redisson.version>3.18.0</redisson.version>
|
||||||
|
<dm8.jdbc.version>8.1.2.141</dm8.jdbc.version>
|
||||||
|
<!-- 服务保障相关 -->
|
||||||
|
<lock4j.version>2.2.3</lock4j.version>
|
||||||
|
<resilience4j.version>1.7.1</resilience4j.version>
|
||||||
|
<!-- 监控相关 -->
|
||||||
|
<skywalking.version>8.12.0</skywalking.version>
|
||||||
|
<spring-boot-admin.version>2.7.10</spring-boot-admin.version>
|
||||||
|
<opentracing.version>0.33.0</opentracing.version>
|
||||||
|
<!-- Test 测试相关 -->
|
||||||
|
<podam.version>7.2.11.RELEASE</podam.version>
|
||||||
|
<jedis-mock.version>1.0.7</jedis-mock.version>
|
||||||
|
<mockito-inline.version>4.11.0</mockito-inline.version>
|
||||||
|
<!-- Bpm 工作流相关 -->
|
||||||
|
<flowable.version>6.8.0</flowable.version>
|
||||||
|
<!-- 工具类相关 -->
|
||||||
|
<captcha-plus.version>1.0.5</captcha-plus.version>
|
||||||
|
<jsoup.version>1.15.4</jsoup.version>
|
||||||
|
<lombok.version>1.18.28</lombok.version>
|
||||||
|
<mapstruct.version>1.5.5.Final</mapstruct.version>
|
||||||
|
<hutool.version>5.8.20</hutool.version>
|
||||||
|
<easyexcel.verion>3.3.2</easyexcel.verion>
|
||||||
|
<velocity.version>2.3</velocity.version>
|
||||||
|
<screw.version>1.0.5</screw.version>
|
||||||
|
<fastjson.version>1.2.83</fastjson.version>
|
||||||
|
<guava.version>32.0.1-jre</guava.version>
|
||||||
|
<guice.version>5.1.0</guice.version>
|
||||||
|
<transmittable-thread-local.version>2.14.2</transmittable-thread-local.version>
|
||||||
|
<commons-net.version>3.9.0</commons-net.version>
|
||||||
|
<jsch.version>0.1.55</jsch.version>
|
||||||
|
<tika-core.version>2.7.0</tika-core.version>
|
||||||
|
<netty-all.version>4.1.90.Final</netty-all.version>
|
||||||
|
<ip2region.version>2.7.0</ip2region.version>
|
||||||
|
<!-- 三方云服务相关 -->
|
||||||
|
<okio.version>3.0.0</okio.version>
|
||||||
|
<okhttp3.version>4.10.0</okhttp3.version>
|
||||||
|
<commons-io.version>2.11.0</commons-io.version>
|
||||||
|
<minio.version>8.5.4</minio.version>
|
||||||
|
<aliyun-java-sdk-core.version>4.6.3</aliyun-java-sdk-core.version>
|
||||||
|
<aliyun-java-sdk-dysmsapi.version>2.2.1</aliyun-java-sdk-dysmsapi.version>
|
||||||
|
<tencentcloud-sdk-java.version>3.1.758</tencentcloud-sdk-java.version>
|
||||||
|
<justauth.version>1.0.1</justauth.version>
|
||||||
|
<jimureport.version>1.5.8</jimureport.version>
|
||||||
|
<xercesImpl.version>2.12.2</xercesImpl.version>
|
||||||
|
<weixin-java.version>4.5.0</weixin-java.version>
|
||||||
|
</properties>
|
||||||
|
|
||||||
|
<dependencyManagement>
|
||||||
|
<dependencies>
|
||||||
|
<!-- 统一依赖管理 -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-dependencies</artifactId>
|
||||||
|
<version>${spring.boot.version}</version>
|
||||||
|
<type>pom</type>
|
||||||
|
<scope>import</scope>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<!-- 业务组件 -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.yunxi.scm</groupId>
|
||||||
|
<artifactId>yunxi-spring-boot-starter-banner</artifactId>
|
||||||
|
<version>${revision}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.yunxi.scm</groupId>
|
||||||
|
<artifactId>yunxi-spring-boot-starter-biz-operatelog</artifactId>
|
||||||
|
<version>${revision}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.yunxi.scm</groupId>
|
||||||
|
<artifactId>yunxi-spring-boot-starter-biz-trade</artifactId>
|
||||||
|
<version>${revision}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.yunxi.scm</groupId>
|
||||||
|
<artifactId>yunxi-spring-boot-starter-biz-dict</artifactId>
|
||||||
|
<version>${revision}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.yunxi.scm</groupId>
|
||||||
|
<artifactId>yunxi-spring-boot-starter-biz-sms</artifactId>
|
||||||
|
<version>${revision}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.yunxi.scm</groupId>
|
||||||
|
<artifactId>yunxi-spring-boot-starter-biz-pay</artifactId>
|
||||||
|
<version>${revision}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.yunxi.scm</groupId>
|
||||||
|
<artifactId>yunxi-spring-boot-starter-biz-weixin</artifactId>
|
||||||
|
<version>${revision}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.yunxi.scm</groupId>
|
||||||
|
<artifactId>yunxi-spring-boot-starter-biz-tenant</artifactId>
|
||||||
|
<version>${revision}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.yunxi.scm</groupId>
|
||||||
|
<artifactId>yunxi-spring-boot-starter-biz-data-permission</artifactId>
|
||||||
|
<version>${revision}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.yunxi.scm</groupId>
|
||||||
|
<artifactId>yunxi-spring-boot-starter-biz-social</artifactId>
|
||||||
|
<version>${revision}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.yunxi.scm</groupId>
|
||||||
|
<artifactId>yunxi-spring-boot-starter-biz-error-code</artifactId>
|
||||||
|
<version>${revision}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.yunxi.scm</groupId>
|
||||||
|
<artifactId>yunxi-spring-boot-starter-biz-ip</artifactId>
|
||||||
|
<version>${revision}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.yunxi.scm</groupId>
|
||||||
|
<artifactId>yunxi-spring-boot-starter-captcha</artifactId>
|
||||||
|
<version>${revision}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.yunxi.scm</groupId>
|
||||||
|
<artifactId>yunxi-spring-boot-starter-desensitize</artifactId>
|
||||||
|
<version>${revision}</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<!-- Spring 核心 -->
|
||||||
|
<dependency>
|
||||||
|
<!-- 用于生成自定义的 Spring @ConfigurationProperties 配置类的说明文件 -->
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-configuration-processor</artifactId>
|
||||||
|
<version>${spring.boot.version}</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<!-- Web 相关 -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.yunxi.scm</groupId>
|
||||||
|
<artifactId>yunxi-spring-boot-starter-web</artifactId>
|
||||||
|
<version>${revision}</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.yunxi.scm</groupId>
|
||||||
|
<artifactId>yunxi-spring-boot-starter-security</artifactId>
|
||||||
|
<version>${revision}</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.github.xiaoymin</groupId>
|
||||||
|
<artifactId>knife4j-openapi3-spring-boot-starter</artifactId>
|
||||||
|
<version>${knife4j.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springdoc</groupId>
|
||||||
|
<artifactId>springdoc-openapi-ui</artifactId>
|
||||||
|
<version>${springdoc.version}</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<!-- DB 相关 -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.yunxi.scm</groupId>
|
||||||
|
<artifactId>yunxi-spring-boot-starter-mybatis</artifactId>
|
||||||
|
<version>${revision}</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.alibaba</groupId>
|
||||||
|
<artifactId>druid-spring-boot-starter</artifactId>
|
||||||
|
<version>${druid.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.baomidou</groupId>
|
||||||
|
<artifactId>mybatis-plus-boot-starter</artifactId>
|
||||||
|
<version>${mybatis-plus.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.baomidou</groupId>
|
||||||
|
<artifactId>mybatis-plus-generator</artifactId> <!-- 代码生成器,使用它解析表结构 -->
|
||||||
|
<version>${mybatis-plus-generator.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.baomidou</groupId>
|
||||||
|
<artifactId>dynamic-datasource-spring-boot-starter</artifactId> <!-- 多数据源 -->
|
||||||
|
<version>${dynamic-datasource.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.github.yulichang</groupId>
|
||||||
|
<artifactId>mybatis-plus-join-boot-starter</artifactId> <!-- MyBatis 联表查询 -->
|
||||||
|
<version>${mybatis-plus-join-boot-starter.version}</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.yunxi.scm</groupId>
|
||||||
|
<artifactId>yunxi-spring-boot-starter-redis</artifactId>
|
||||||
|
<version>${revision}</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.redisson</groupId>
|
||||||
|
<artifactId>redisson-spring-boot-starter</artifactId>
|
||||||
|
<version>${redisson.version}</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.dameng</groupId>
|
||||||
|
<artifactId>DmJdbcDriver18</artifactId>
|
||||||
|
<version>${dm8.jdbc.version}</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<!-- Job 定时任务相关 -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.yunxi.scm</groupId>
|
||||||
|
<artifactId>yunxi-spring-boot-starter-job</artifactId>
|
||||||
|
<version>${revision}</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<!-- 消息队列相关 -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.yunxi.scm</groupId>
|
||||||
|
<artifactId>yunxi-spring-boot-starter-mq</artifactId>
|
||||||
|
<version>${revision}</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<!-- 服务保障相关 -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.yunxi.scm</groupId>
|
||||||
|
<artifactId>yunxi-spring-boot-starter-protection</artifactId>
|
||||||
|
<version>${revision}</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.baomidou</groupId>
|
||||||
|
<artifactId>lock4j-redisson-spring-boot-starter</artifactId>
|
||||||
|
<version>${lock4j.version}</version>
|
||||||
|
<exclusions>
|
||||||
|
<exclusion>
|
||||||
|
<artifactId>redisson-spring-boot-starter</artifactId>
|
||||||
|
<groupId>org.redisson</groupId>
|
||||||
|
</exclusion>
|
||||||
|
</exclusions>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>io.github.resilience4j</groupId>
|
||||||
|
<artifactId>resilience4j-ratelimiter</artifactId>
|
||||||
|
<version>${resilience4j.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>io.github.resilience4j</groupId>
|
||||||
|
<artifactId>resilience4j-spring-boot2</artifactId>
|
||||||
|
<version>${resilience4j.version}</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<!-- 监控相关 -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.yunxi.scm</groupId>
|
||||||
|
<artifactId>yunxi-spring-boot-starter-monitor</artifactId>
|
||||||
|
<version>${revision}</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.skywalking</groupId>
|
||||||
|
<artifactId>apm-toolkit-trace</artifactId>
|
||||||
|
<version>${skywalking.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.skywalking</groupId>
|
||||||
|
<artifactId>apm-toolkit-logback-1.x</artifactId>
|
||||||
|
<version>${skywalking.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.skywalking</groupId>
|
||||||
|
<artifactId>apm-toolkit-opentracing</artifactId>
|
||||||
|
<version>${skywalking.version}</version>
|
||||||
|
<!-- <exclusions>-->
|
||||||
|
<!-- <exclusion>-->
|
||||||
|
<!-- <artifactId>opentracing-api</artifactId>-->
|
||||||
|
<!-- <groupId>io.opentracing</groupId>-->
|
||||||
|
<!-- </exclusion>-->
|
||||||
|
<!-- <exclusion>-->
|
||||||
|
<!-- <artifactId>opentracing-util</artifactId>-->
|
||||||
|
<!-- <groupId>io.opentracing</groupId>-->
|
||||||
|
<!-- </exclusion>-->
|
||||||
|
<!-- </exclusions>-->
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>io.opentracing</groupId>
|
||||||
|
<artifactId>opentracing-api</artifactId>
|
||||||
|
<version>${opentracing.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>io.opentracing</groupId>
|
||||||
|
<artifactId>opentracing-util</artifactId>
|
||||||
|
<version>${opentracing.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>io.opentracing</groupId>
|
||||||
|
<artifactId>opentracing-noop</artifactId>
|
||||||
|
<version>${opentracing.version}</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>de.codecentric</groupId>
|
||||||
|
<artifactId>spring-boot-admin-starter-server</artifactId> <!-- 实现 Spring Boot Admin Server 服务端 -->
|
||||||
|
<version>${spring-boot-admin.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>de.codecentric</groupId>
|
||||||
|
<artifactId>spring-boot-admin-starter-client</artifactId> <!-- 实现 Spring Boot Admin Server 服务端 -->
|
||||||
|
<version>${spring-boot-admin.version}</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<!-- Test 测试相关 -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.yunxi.scm</groupId>
|
||||||
|
<artifactId>yunxi-spring-boot-starter-test</artifactId>
|
||||||
|
<version>${revision}</version>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.mockito</groupId>
|
||||||
|
<artifactId>mockito-inline</artifactId>
|
||||||
|
<version>${mockito-inline.version}</version> <!-- 支持 Mockito 的 final 类与 static 方法的 mock -->
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-test</artifactId>
|
||||||
|
<version>${spring.boot.version}</version>
|
||||||
|
<exclusions>
|
||||||
|
<exclusion>
|
||||||
|
<artifactId>asm</artifactId>
|
||||||
|
<groupId>org.ow2.asm</groupId>
|
||||||
|
</exclusion>
|
||||||
|
<exclusion>
|
||||||
|
<groupId>org.mockito</groupId>
|
||||||
|
<artifactId>mockito-core</artifactId>
|
||||||
|
</exclusion>
|
||||||
|
</exclusions>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.github.fppt</groupId> <!-- 单元测试,我们采用内嵌的 Redis 数据库 -->
|
||||||
|
<artifactId>jedis-mock</artifactId>
|
||||||
|
<version>${jedis-mock.version}</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>uk.co.jemos.podam</groupId> <!-- 单元测试,随机生成 POJO 类 -->
|
||||||
|
<artifactId>podam</artifactId>
|
||||||
|
<version>${podam.version}</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<!-- 工作流相关 -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.yunxi.scm</groupId>
|
||||||
|
<artifactId>yunxi-spring-boot-starter-flowable</artifactId>
|
||||||
|
<version>${revision}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.flowable</groupId>
|
||||||
|
<artifactId>flowable-spring-boot-starter-process</artifactId>
|
||||||
|
<version>${flowable.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.flowable</groupId>
|
||||||
|
<artifactId>flowable-spring-boot-starter-actuator</artifactId>
|
||||||
|
<version>${flowable.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<!-- 工作流相关结束 -->
|
||||||
|
|
||||||
|
<!-- 工具类相关 -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.yunxi.scm</groupId>
|
||||||
|
<artifactId>yunxi-common</artifactId>
|
||||||
|
<version>${revision}</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.yunxi.scm</groupId>
|
||||||
|
<artifactId>yunxi-spring-boot-starter-excel</artifactId>
|
||||||
|
<version>${revision}</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.projectlombok</groupId>
|
||||||
|
<artifactId>lombok</artifactId>
|
||||||
|
<version>${lombok.version}</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.mapstruct</groupId>
|
||||||
|
<artifactId>mapstruct</artifactId> <!-- use mapstruct-jdk8 for Java 8 or higher -->
|
||||||
|
<version>${mapstruct.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.mapstruct</groupId>
|
||||||
|
<artifactId>mapstruct-jdk8</artifactId>
|
||||||
|
<version>${mapstruct.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.mapstruct</groupId>
|
||||||
|
<artifactId>mapstruct-processor</artifactId>
|
||||||
|
<version>${mapstruct.version}</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>cn.hutool</groupId>
|
||||||
|
<artifactId>hutool-all</artifactId>
|
||||||
|
<version>${hutool.version}</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.alibaba</groupId>
|
||||||
|
<artifactId>easyexcel</artifactId>
|
||||||
|
<version>${easyexcel.verion}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>commons-io</groupId>
|
||||||
|
<artifactId>commons-io</artifactId>
|
||||||
|
<version>${commons-io.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.tika</groupId>
|
||||||
|
<artifactId>tika-core</artifactId> <!-- 文件类型的识别 -->
|
||||||
|
<version>${tika-core.version}</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.velocity</groupId>
|
||||||
|
<artifactId>velocity-engine-core</artifactId>
|
||||||
|
<version>${velocity.version}</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.alibaba</groupId>
|
||||||
|
<artifactId>fastjson</artifactId>
|
||||||
|
<version>${fastjson.version}</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>cn.smallbun.screw</groupId>
|
||||||
|
<artifactId>screw-core</artifactId> <!-- 实现数据库文档 -->
|
||||||
|
<version>${screw.version}</version>
|
||||||
|
<exclusions>
|
||||||
|
<exclusion>
|
||||||
|
<groupId>org.freemarker</groupId>
|
||||||
|
<artifactId>freemarker</artifactId> <!-- 移除 Freemarker 依赖,采用 Velocity 作为模板引擎 -->
|
||||||
|
</exclusion>
|
||||||
|
<exclusion>
|
||||||
|
<groupId>com.alibaba</groupId>
|
||||||
|
<artifactId>fastjson</artifactId> <!-- 最新版screw-core1.0.5依赖fastjson1.2.73存在漏洞,移除。 -->
|
||||||
|
</exclusion>
|
||||||
|
</exclusions>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.google.guava</groupId>
|
||||||
|
<artifactId>guava</artifactId>
|
||||||
|
<version>${guava.version}</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.google.inject</groupId>
|
||||||
|
<artifactId>guice</artifactId>
|
||||||
|
<version>${guice.version}</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.alibaba</groupId>
|
||||||
|
<artifactId>transmittable-thread-local</artifactId> <!-- 解决 ThreadLocal 父子线程的传值问题 -->
|
||||||
|
<version>${transmittable-thread-local.version}</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>commons-net</groupId>
|
||||||
|
<artifactId>commons-net</artifactId> <!-- 解决 ftp 连接 -->
|
||||||
|
<version>${commons-net.version}</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.jcraft</groupId>
|
||||||
|
<artifactId>jsch</artifactId> <!-- 解决 sftp 连接 -->
|
||||||
|
<version>${jsch.version}</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>io.netty</groupId>
|
||||||
|
<artifactId>netty-all</artifactId>
|
||||||
|
<version>${netty-all.version}</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.xingyuv</groupId>
|
||||||
|
<artifactId>spring-boot-starter-captcha-plus</artifactId>
|
||||||
|
<version>${captcha-plus.version}</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.lionsoul</groupId>
|
||||||
|
<artifactId>ip2region</artifactId>
|
||||||
|
<version>${ip2region.version}</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.jsoup</groupId>
|
||||||
|
<artifactId>jsoup</artifactId>
|
||||||
|
<version>${jsoup.version}</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<!-- 三方云服务相关 -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.squareup.okio</groupId>
|
||||||
|
<artifactId>okio</artifactId>
|
||||||
|
<version>${okio.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.squareup.okhttp3</groupId>
|
||||||
|
<artifactId>okhttp</artifactId>
|
||||||
|
<version>${okhttp3.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.yunxi.scm</groupId>
|
||||||
|
<artifactId>yunxi-spring-boot-starter-file</artifactId>
|
||||||
|
<version>${revision}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>io.minio</groupId>
|
||||||
|
<artifactId>minio</artifactId>
|
||||||
|
<version>${minio.version}</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<!-- SMS SDK begin -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.aliyun</groupId>
|
||||||
|
<artifactId>aliyun-java-sdk-core</artifactId>
|
||||||
|
<version>${aliyun-java-sdk-core.version}</version>
|
||||||
|
<exclusions>
|
||||||
|
<exclusion>
|
||||||
|
<artifactId>opentracing-api</artifactId>
|
||||||
|
<groupId>io.opentracing</groupId>
|
||||||
|
</exclusion>
|
||||||
|
<exclusion>
|
||||||
|
<artifactId>opentracing-util</artifactId>
|
||||||
|
<groupId>io.opentracing</groupId>
|
||||||
|
</exclusion>
|
||||||
|
</exclusions>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.aliyun</groupId>
|
||||||
|
<artifactId>aliyun-java-sdk-dysmsapi</artifactId>
|
||||||
|
<version>${aliyun-java-sdk-dysmsapi.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.tencentcloudapi</groupId>
|
||||||
|
<artifactId>tencentcloud-sdk-java-sms</artifactId>
|
||||||
|
<version>${tencentcloud-sdk-java.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<!-- SMS SDK end -->
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.xingyuv</groupId>
|
||||||
|
<artifactId>spring-boot-starter-justauth</artifactId> <!-- 社交登陆(例如说,个人微信、企业微信等等) -->
|
||||||
|
<version>${justauth.version}</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.github.binarywang</groupId>
|
||||||
|
<artifactId>weixin-java-pay</artifactId>
|
||||||
|
<version>${weixin-java.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.github.binarywang</groupId>
|
||||||
|
<artifactId>weixin-java-mp</artifactId>
|
||||||
|
<version>${weixin-java.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.github.binarywang</groupId>
|
||||||
|
<artifactId>wx-java-mp-spring-boot-starter</artifactId>
|
||||||
|
<version>${weixin-java.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.github.binarywang</groupId>
|
||||||
|
<artifactId>wx-java-miniapp-spring-boot-starter</artifactId>
|
||||||
|
<version>${weixin-java.version}</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<!-- 积木报表-->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.jeecgframework.jimureport</groupId>
|
||||||
|
<artifactId>jimureport-spring-boot-starter</artifactId>
|
||||||
|
<version>${jimureport.version}</version>
|
||||||
|
<exclusions>
|
||||||
|
<exclusion>
|
||||||
|
<groupId>com.alibaba</groupId>
|
||||||
|
<artifactId>druid</artifactId>
|
||||||
|
</exclusion>
|
||||||
|
</exclusions>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>xerces</groupId>
|
||||||
|
<artifactId>xercesImpl</artifactId>
|
||||||
|
<version>${xercesImpl.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<!-- SpringBoot Websocket -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-websocket</artifactId>
|
||||||
|
<version>${spring.boot.version}</version>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
</dependencyManagement>
|
||||||
|
|
||||||
|
</project>
|
@ -0,0 +1,65 @@
|
|||||||
|
<?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>
|
||||||
|
|
||||||
|
<!-- 由于方便大家拷贝,使用不使用 yunxi 作为 Maven parent -->
|
||||||
|
|
||||||
|
<groupId>com.yunxi.scm</groupId>
|
||||||
|
<artifactId>yunxi-sso-demo-by-code</artifactId>
|
||||||
|
<version>1.0.0-snapshot</version>
|
||||||
|
<packaging>jar</packaging>
|
||||||
|
|
||||||
|
<name>${project.artifactId}</name>
|
||||||
|
<description>基于授权码模式,如何实现 SSO 单点登录?</description>
|
||||||
|
<url>https://github.com/YunaiV/ruoyi-vue-pro</url>
|
||||||
|
|
||||||
|
<properties>
|
||||||
|
<!-- Maven 相关 -->
|
||||||
|
<maven.compiler.source>8</maven.compiler.source>
|
||||||
|
<maven.compiler.target>8</maven.compiler.target>
|
||||||
|
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||||
|
<!-- 统一依赖管理 -->
|
||||||
|
<spring.boot.version>2.7.13</spring.boot.version>
|
||||||
|
</properties>
|
||||||
|
|
||||||
|
<dependencyManagement>
|
||||||
|
<dependencies>
|
||||||
|
<!-- 统一依赖管理 -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-dependencies</artifactId>
|
||||||
|
<version>${spring.boot.version}</version>
|
||||||
|
<type>pom</type>
|
||||||
|
<scope>import</scope>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
</dependencyManagement>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
<!-- Web 相关 -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-web</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-security</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>cn.hutool</groupId>
|
||||||
|
<artifactId>hutool-all</artifactId>
|
||||||
|
<version>5.8.20</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.projectlombok</groupId>
|
||||||
|
<artifactId>lombok</artifactId>
|
||||||
|
<optional>true</optional>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
|
||||||
|
</project>
|
@ -0,0 +1,13 @@
|
|||||||
|
package com.yunxi.scm.ssodemo;
|
||||||
|
|
||||||
|
import org.springframework.boot.SpringApplication;
|
||||||
|
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||||
|
|
||||||
|
@SpringBootApplication
|
||||||
|
public class SSODemoApplication {
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
SpringApplication.run(SSODemoApplication.class, args);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,97 @@
|
|||||||
|
package com.yunxi.scm.ssodemo.client.dto.user;
|
||||||
|
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获得用户基本信息 Response dto
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@NoArgsConstructor
|
||||||
|
@AllArgsConstructor
|
||||||
|
public class UserInfoRespDTO {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户编号
|
||||||
|
*/
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户账号
|
||||||
|
*/
|
||||||
|
private String username;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户昵称
|
||||||
|
*/
|
||||||
|
private String nickname;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户邮箱
|
||||||
|
*/
|
||||||
|
private String email;
|
||||||
|
/**
|
||||||
|
* 手机号码
|
||||||
|
*/
|
||||||
|
private String mobile;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户性别
|
||||||
|
*/
|
||||||
|
private Integer sex;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户头像
|
||||||
|
*/
|
||||||
|
private String avatar;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 所在部门
|
||||||
|
*/
|
||||||
|
private Dept dept;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 所属岗位数组
|
||||||
|
*/
|
||||||
|
private List<Post> posts;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 部门
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public static class Dept {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 部门编号
|
||||||
|
*/
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 部门名称
|
||||||
|
*/
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 岗位
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public static class Post {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 岗位编号
|
||||||
|
*/
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 岗位名称
|
||||||
|
*/
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,35 @@
|
|||||||
|
package com.yunxi.scm.ssodemo.client.dto.user;
|
||||||
|
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 更新用户基本信息 Request DTO
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@NoArgsConstructor
|
||||||
|
@AllArgsConstructor
|
||||||
|
public class UserUpdateReqDTO {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户昵称
|
||||||
|
*/
|
||||||
|
private String nickname;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户邮箱
|
||||||
|
*/
|
||||||
|
private String email;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 手机号码
|
||||||
|
*/
|
||||||
|
private String mobile;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户性别
|
||||||
|
*/
|
||||||
|
private Integer sex;
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,52 @@
|
|||||||
|
package com.yunxi.scm.ssodemo.framework.config;
|
||||||
|
|
||||||
|
import com.yunxi.scm.ssodemo.framework.core.filter.TokenAuthenticationFilter;
|
||||||
|
import com.yunxi.scm.ssodemo.framework.core.handler.AccessDeniedHandlerImpl;
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
import org.springframework.http.HttpMethod;
|
||||||
|
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
||||||
|
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
|
||||||
|
import org.springframework.security.web.AuthenticationEntryPoint;
|
||||||
|
import org.springframework.security.web.SecurityFilterChain;
|
||||||
|
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
|
||||||
|
|
||||||
|
import javax.annotation.Resource;
|
||||||
|
|
||||||
|
@Configuration(proxyBeanMethods = false)
|
||||||
|
@EnableWebSecurity
|
||||||
|
public class SecurityConfiguration{
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private TokenAuthenticationFilter tokenAuthenticationFilter;
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private AccessDeniedHandlerImpl accessDeniedHandler;
|
||||||
|
@Resource
|
||||||
|
private AuthenticationEntryPoint authenticationEntryPoint;
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
protected SecurityFilterChain filterChain(HttpSecurity httpSecurity) throws Exception {
|
||||||
|
// 设置 URL 安全权限
|
||||||
|
httpSecurity.csrf().disable() // 禁用 CSRF 保护
|
||||||
|
.authorizeRequests()
|
||||||
|
// 1. 静态资源,可匿名访问
|
||||||
|
.antMatchers(HttpMethod.GET, "/*.html", "/**/*.html", "/**/*.css", "/**/*.js").permitAll()
|
||||||
|
// 2. 登录相关的接口,可匿名访问
|
||||||
|
.antMatchers("/auth/login-by-code").permitAll()
|
||||||
|
.antMatchers("/auth/refresh-token").permitAll()
|
||||||
|
.antMatchers("/auth/logout").permitAll()
|
||||||
|
// last. 兜底规则,必须认证
|
||||||
|
.and().authorizeRequests()
|
||||||
|
.anyRequest().authenticated();
|
||||||
|
|
||||||
|
// 设置处理器
|
||||||
|
httpSecurity.exceptionHandling().accessDeniedHandler(accessDeniedHandler)
|
||||||
|
.authenticationEntryPoint(authenticationEntryPoint);
|
||||||
|
|
||||||
|
// 添加 Token Filter
|
||||||
|
httpSecurity.addFilterBefore(tokenAuthenticationFilter, UsernamePasswordAuthenticationFilter.class);
|
||||||
|
return httpSecurity.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,37 @@
|
|||||||
|
package com.yunxi.scm.ssodemo.framework.core;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 登录用户信息
|
||||||
|
*
|
||||||
|
* @author 芋道源码
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class LoginUser {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户编号
|
||||||
|
*/
|
||||||
|
private Long id;
|
||||||
|
/**
|
||||||
|
* 用户类型
|
||||||
|
*/
|
||||||
|
private Integer userType;
|
||||||
|
/**
|
||||||
|
* 租户编号
|
||||||
|
*/
|
||||||
|
private Long tenantId;
|
||||||
|
/**
|
||||||
|
* 授权范围
|
||||||
|
*/
|
||||||
|
private List<String> scopes;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 访问令牌
|
||||||
|
*/
|
||||||
|
private String accessToken;
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,2 @@
|
|||||||
|
server:
|
||||||
|
port: 18080
|
@ -0,0 +1,65 @@
|
|||||||
|
<?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>
|
||||||
|
|
||||||
|
<!-- 由于方便大家拷贝,使用不使用 yunxi 作为 Maven parent -->
|
||||||
|
|
||||||
|
<groupId>com.yunxi.scm</groupId>
|
||||||
|
<artifactId>yunxi-sso-demo-by-password</artifactId>
|
||||||
|
<version>1.0.0-snapshot</version>
|
||||||
|
<packaging>jar</packaging>
|
||||||
|
|
||||||
|
<name>${project.artifactId}</name>
|
||||||
|
<description>基于密码模式,如何实现 SSO 单点登录?</description>
|
||||||
|
<url>https://github.com/YunaiV/ruoyi-vue-pro</url>
|
||||||
|
|
||||||
|
<properties>
|
||||||
|
<!-- Maven 相关 -->
|
||||||
|
<maven.compiler.source>8</maven.compiler.source>
|
||||||
|
<maven.compiler.target>8</maven.compiler.target>
|
||||||
|
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||||
|
<!-- 统一依赖管理 -->
|
||||||
|
<spring.boot.version>2.7.13</spring.boot.version>
|
||||||
|
</properties>
|
||||||
|
|
||||||
|
<dependencyManagement>
|
||||||
|
<dependencies>
|
||||||
|
<!-- 统一依赖管理 -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-dependencies</artifactId>
|
||||||
|
<version>${spring.boot.version}</version>
|
||||||
|
<type>pom</type>
|
||||||
|
<scope>import</scope>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
</dependencyManagement>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
<!-- Web 相关 -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-web</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-security</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>cn.hutool</groupId>
|
||||||
|
<artifactId>hutool-all</artifactId>
|
||||||
|
<version>5.8.20</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.projectlombok</groupId>
|
||||||
|
<artifactId>lombok</artifactId>
|
||||||
|
<optional>true</optional>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
|
||||||
|
</project>
|
@ -0,0 +1,13 @@
|
|||||||
|
package com.yunxi.scm.ssodemo;
|
||||||
|
|
||||||
|
import org.springframework.boot.SpringApplication;
|
||||||
|
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||||
|
|
||||||
|
@SpringBootApplication
|
||||||
|
public class SSODemoApplication {
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
SpringApplication.run(SSODemoApplication.class, args);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,97 @@
|
|||||||
|
package com.yunxi.scm.ssodemo.client.dto.user;
|
||||||
|
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获得用户基本信息 Response dto
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@NoArgsConstructor
|
||||||
|
@AllArgsConstructor
|
||||||
|
public class UserInfoRespDTO {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户编号
|
||||||
|
*/
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户账号
|
||||||
|
*/
|
||||||
|
private String username;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户昵称
|
||||||
|
*/
|
||||||
|
private String nickname;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户邮箱
|
||||||
|
*/
|
||||||
|
private String email;
|
||||||
|
/**
|
||||||
|
* 手机号码
|
||||||
|
*/
|
||||||
|
private String mobile;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户性别
|
||||||
|
*/
|
||||||
|
private Integer sex;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户头像
|
||||||
|
*/
|
||||||
|
private String avatar;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 所在部门
|
||||||
|
*/
|
||||||
|
private Dept dept;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 所属岗位数组
|
||||||
|
*/
|
||||||
|
private List<Post> posts;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 部门
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public static class Dept {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 部门编号
|
||||||
|
*/
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 部门名称
|
||||||
|
*/
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 岗位
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public static class Post {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 岗位编号
|
||||||
|
*/
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 岗位名称
|
||||||
|
*/
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,35 @@
|
|||||||
|
package com.yunxi.scm.ssodemo.client.dto.user;
|
||||||
|
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 更新用户基本信息 Request DTO
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@NoArgsConstructor
|
||||||
|
@AllArgsConstructor
|
||||||
|
public class UserUpdateReqDTO {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户昵称
|
||||||
|
*/
|
||||||
|
private String nickname;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户邮箱
|
||||||
|
*/
|
||||||
|
private String email;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 手机号码
|
||||||
|
*/
|
||||||
|
private String mobile;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户性别
|
||||||
|
*/
|
||||||
|
private Integer sex;
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,52 @@
|
|||||||
|
package com.yunxi.scm.ssodemo.framework.config;
|
||||||
|
|
||||||
|
import com.yunxi.scm.ssodemo.framework.core.filter.TokenAuthenticationFilter;
|
||||||
|
import com.yunxi.scm.ssodemo.framework.core.handler.AccessDeniedHandlerImpl;
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
import org.springframework.http.HttpMethod;
|
||||||
|
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
||||||
|
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
|
||||||
|
import org.springframework.security.web.AuthenticationEntryPoint;
|
||||||
|
import org.springframework.security.web.SecurityFilterChain;
|
||||||
|
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
|
||||||
|
|
||||||
|
import javax.annotation.Resource;
|
||||||
|
|
||||||
|
@Configuration(proxyBeanMethods = false)
|
||||||
|
@EnableWebSecurity
|
||||||
|
public class SecurityConfiguration {
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private TokenAuthenticationFilter tokenAuthenticationFilter;
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private AccessDeniedHandlerImpl accessDeniedHandler;
|
||||||
|
@Resource
|
||||||
|
private AuthenticationEntryPoint authenticationEntryPoint;
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
protected SecurityFilterChain filterChain(HttpSecurity httpSecurity) throws Exception {
|
||||||
|
// 设置 URL 安全权限
|
||||||
|
httpSecurity.csrf().disable() // 禁用 CSRF 保护
|
||||||
|
.authorizeRequests()
|
||||||
|
// 1. 静态资源,可匿名访问
|
||||||
|
.antMatchers(HttpMethod.GET, "/*.html", "/**/*.html", "/**/*.css", "/**/*.js").permitAll()
|
||||||
|
// 2. 登录相关的接口,可匿名访问
|
||||||
|
.antMatchers("/auth/login-by-code").permitAll()
|
||||||
|
.antMatchers("/auth/refresh-token").permitAll()
|
||||||
|
.antMatchers("/auth/logout").permitAll()
|
||||||
|
// last. 兜底规则,必须认证
|
||||||
|
.and().authorizeRequests()
|
||||||
|
.anyRequest().authenticated();
|
||||||
|
|
||||||
|
// 设置处理器
|
||||||
|
httpSecurity.exceptionHandling().accessDeniedHandler(accessDeniedHandler)
|
||||||
|
.authenticationEntryPoint(authenticationEntryPoint);
|
||||||
|
|
||||||
|
// 添加 Token Filter
|
||||||
|
httpSecurity.addFilterBefore(tokenAuthenticationFilter, UsernamePasswordAuthenticationFilter.class);
|
||||||
|
return httpSecurity.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,37 @@
|
|||||||
|
package com.yunxi.scm.ssodemo.framework.core;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 登录用户信息
|
||||||
|
*
|
||||||
|
* @author 芋道源码
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class LoginUser {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户编号
|
||||||
|
*/
|
||||||
|
private Long id;
|
||||||
|
/**
|
||||||
|
* 用户类型
|
||||||
|
*/
|
||||||
|
private Integer userType;
|
||||||
|
/**
|
||||||
|
* 租户编号
|
||||||
|
*/
|
||||||
|
private Long tenantId;
|
||||||
|
/**
|
||||||
|
* 授权范围
|
||||||
|
*/
|
||||||
|
private List<String> scopes;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 访问令牌
|
||||||
|
*/
|
||||||
|
private String accessToken;
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,2 @@
|
|||||||
|
server:
|
||||||
|
port: 18080
|
@ -0,0 +1,15 @@
|
|||||||
|
package com.yunxi.scm.framework.common.core;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 可生成 Int 数组的接口
|
||||||
|
*
|
||||||
|
* @author 芋道源码
|
||||||
|
*/
|
||||||
|
public interface IntArrayValuable {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return int 数组
|
||||||
|
*/
|
||||||
|
int[] array();
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,20 @@
|
|||||||
|
package com.yunxi.scm.framework.common.core;
|
||||||
|
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Key Value 的键值对
|
||||||
|
*
|
||||||
|
* @author 芋道源码
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@NoArgsConstructor
|
||||||
|
@AllArgsConstructor
|
||||||
|
public class KeyValue<K, V> {
|
||||||
|
|
||||||
|
private K key;
|
||||||
|
private V value;
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,37 @@
|
|||||||
|
package com.yunxi.scm.framework.common.enums;
|
||||||
|
|
||||||
|
import com.yunxi.scm.framework.common.core.IntArrayValuable;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Getter;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 通用状态枚举
|
||||||
|
*
|
||||||
|
* @author 芋道源码
|
||||||
|
*/
|
||||||
|
@Getter
|
||||||
|
@AllArgsConstructor
|
||||||
|
public enum CommonStatusEnum implements IntArrayValuable {
|
||||||
|
|
||||||
|
ENABLE(0, "开启"),
|
||||||
|
DISABLE(1, "关闭");
|
||||||
|
|
||||||
|
public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(CommonStatusEnum::getStatus).toArray();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 状态值
|
||||||
|
*/
|
||||||
|
private final Integer status;
|
||||||
|
/**
|
||||||
|
* 状态名
|
||||||
|
*/
|
||||||
|
private final String name;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int[] array() {
|
||||||
|
return ARRAYS;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,21 @@
|
|||||||
|
package com.yunxi.scm.framework.common.enums;
|
||||||
|
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Getter;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 文档地址
|
||||||
|
*
|
||||||
|
* @author 芋道源码
|
||||||
|
*/
|
||||||
|
@Getter
|
||||||
|
@AllArgsConstructor
|
||||||
|
public enum DocumentEnum {
|
||||||
|
|
||||||
|
REDIS_INSTALL("https://gitee.com/zhijiantianya/ruoyi-vue-pro/issues/I4VCSJ", "Redis 安装文档"),
|
||||||
|
TENANT("https://doc.iocoder.cn", "SaaS 多租户文档");
|
||||||
|
|
||||||
|
private final String url;
|
||||||
|
private final String memo;
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,40 @@
|
|||||||
|
package com.yunxi.scm.framework.common.enums;
|
||||||
|
|
||||||
|
import com.yunxi.scm.framework.common.core.IntArrayValuable;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 终端的枚举
|
||||||
|
*
|
||||||
|
* @author 芋道源码
|
||||||
|
*/
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
@Getter
|
||||||
|
public enum TerminalEnum implements IntArrayValuable {
|
||||||
|
|
||||||
|
WECHAT_MINI_PROGRAM(10, "微信小程序"),
|
||||||
|
WECHAT_WAP(11, "微信公众号"),
|
||||||
|
H5(20, "H5 网页"),
|
||||||
|
IOS(31, "苹果 App"),
|
||||||
|
ANDROID(32, "安卓 App"),
|
||||||
|
;
|
||||||
|
|
||||||
|
public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(TerminalEnum::getTerminal).toArray();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 终端
|
||||||
|
*/
|
||||||
|
private final Integer terminal;
|
||||||
|
/**
|
||||||
|
* 终端名
|
||||||
|
*/
|
||||||
|
private final String name;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int[] array() {
|
||||||
|
return ARRAYS;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,39 @@
|
|||||||
|
package com.yunxi.scm.framework.common.enums;
|
||||||
|
|
||||||
|
import cn.hutool.core.util.ArrayUtil;
|
||||||
|
import com.yunxi.scm.framework.common.core.IntArrayValuable;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Getter;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 全局用户类型枚举
|
||||||
|
*/
|
||||||
|
@AllArgsConstructor
|
||||||
|
@Getter
|
||||||
|
public enum UserTypeEnum implements IntArrayValuable {
|
||||||
|
|
||||||
|
MEMBER(1, "会员"), // 面向 c 端,普通用户
|
||||||
|
ADMIN(2, "管理员"); // 面向 b 端,管理后台
|
||||||
|
|
||||||
|
public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(UserTypeEnum::getValue).toArray();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 类型
|
||||||
|
*/
|
||||||
|
private final Integer value;
|
||||||
|
/**
|
||||||
|
* 类型名
|
||||||
|
*/
|
||||||
|
private final String name;
|
||||||
|
|
||||||
|
public static UserTypeEnum valueOf(Integer value) {
|
||||||
|
return ArrayUtil.firstMatch(userType -> userType.getValue().equals(value), UserTypeEnum.values());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int[] array() {
|
||||||
|
return ARRAYS;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,29 @@
|
|||||||
|
package com.yunxi.scm.framework.common.pojo;
|
||||||
|
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import javax.validation.constraints.Min;
|
||||||
|
import javax.validation.constraints.Max;
|
||||||
|
import javax.validation.constraints.NotNull;
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
@Schema(description="分页参数")
|
||||||
|
@Data
|
||||||
|
public class PageParam implements Serializable {
|
||||||
|
|
||||||
|
private static final Integer PAGE_NO = 1;
|
||||||
|
private static final Integer PAGE_SIZE = 10;
|
||||||
|
|
||||||
|
@Schema(description = "页码,从 1 开始", requiredMode = Schema.RequiredMode.REQUIRED,example = "1")
|
||||||
|
@NotNull(message = "页码不能为空")
|
||||||
|
@Min(value = 1, message = "页码最小值为 1")
|
||||||
|
private Integer pageNo = PAGE_NO;
|
||||||
|
|
||||||
|
@Schema(description = "每页条数,最大值为 100", requiredMode = Schema.RequiredMode.REQUIRED, example = "10")
|
||||||
|
@NotNull(message = "每页条数不能为空")
|
||||||
|
@Min(value = 1, message = "每页条数最小值为 1")
|
||||||
|
@Max(value = 100, message = "每页条数最大值为 100")
|
||||||
|
private Integer pageSize = PAGE_SIZE;
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,41 @@
|
|||||||
|
package com.yunxi.scm.framework.common.pojo;
|
||||||
|
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Schema(description = "分页结果")
|
||||||
|
@Data
|
||||||
|
public final class PageResult<T> implements Serializable {
|
||||||
|
|
||||||
|
@Schema(description = "数据", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||||
|
private List<T> list;
|
||||||
|
|
||||||
|
@Schema(description = "总量", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||||
|
private Long total;
|
||||||
|
|
||||||
|
public PageResult() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public PageResult(List<T> list, Long total) {
|
||||||
|
this.list = list;
|
||||||
|
this.total = total;
|
||||||
|
}
|
||||||
|
|
||||||
|
public PageResult(Long total) {
|
||||||
|
this.list = new ArrayList<>();
|
||||||
|
this.total = total;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <T> PageResult<T> empty() {
|
||||||
|
return new PageResult<>(0L);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <T> PageResult<T> empty(Long total) {
|
||||||
|
return new PageResult<>(total);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,25 @@
|
|||||||
|
package com.yunxi.scm.framework.common.util.cache;
|
||||||
|
|
||||||
|
import com.google.common.cache.CacheBuilder;
|
||||||
|
import com.google.common.cache.CacheLoader;
|
||||||
|
import com.google.common.cache.LoadingCache;
|
||||||
|
|
||||||
|
import java.time.Duration;
|
||||||
|
import java.util.concurrent.Executors;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Cache 工具类
|
||||||
|
*
|
||||||
|
* @author 芋道源码
|
||||||
|
*/
|
||||||
|
public class CacheUtils {
|
||||||
|
|
||||||
|
public static <K, V> LoadingCache<K, V> buildAsyncReloadingCache(Duration duration, CacheLoader<K, V> loader) {
|
||||||
|
return CacheBuilder.newBuilder()
|
||||||
|
// 只阻塞当前数据加载线程,其他线程返回旧值
|
||||||
|
.refreshAfterWrite(duration)
|
||||||
|
// 通过 asyncReloading 实现全异步加载,包括 refreshAfterWrite 被阻塞的加载线程
|
||||||
|
.build(CacheLoader.asyncReloading(loader, Executors.newCachedThreadPool())); // TODO 芋艿:可能要思考下,未来要不要做成可配置
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,58 @@
|
|||||||
|
package com.yunxi.scm.framework.common.util.collection;
|
||||||
|
|
||||||
|
import cn.hutool.core.collection.CollectionUtil;
|
||||||
|
import cn.hutool.core.collection.IterUtil;
|
||||||
|
import cn.hutool.core.util.ArrayUtil;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.function.Consumer;
|
||||||
|
import java.util.function.Function;
|
||||||
|
|
||||||
|
import static com.yunxi.scm.framework.common.util.collection.CollectionUtils.convertList;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Array 工具类
|
||||||
|
*
|
||||||
|
* @author 芋道源码
|
||||||
|
*/
|
||||||
|
public class ArrayUtils {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 将 object 和 newElements 合并成一个数组
|
||||||
|
*
|
||||||
|
* @param object 对象
|
||||||
|
* @param newElements 数组
|
||||||
|
* @param <T> 泛型
|
||||||
|
* @return 结果数组
|
||||||
|
*/
|
||||||
|
@SafeVarargs
|
||||||
|
public static <T> Consumer<T>[] append(Consumer<T> object, Consumer<T>... newElements) {
|
||||||
|
if (object == null) {
|
||||||
|
return newElements;
|
||||||
|
}
|
||||||
|
Consumer<T>[] result = ArrayUtil.newArray(Consumer.class, 1 + newElements.length);
|
||||||
|
result[0] = object;
|
||||||
|
System.arraycopy(newElements, 0, result, 1, newElements.length);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <T, V> V[] toArray(Collection<T> from, Function<T, V> mapper) {
|
||||||
|
return toArray(convertList(from, mapper));
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
public static <T> T[] toArray(Collection<T> from) {
|
||||||
|
if (CollectionUtil.isEmpty(from)) {
|
||||||
|
return (T[]) (new Object[0]);
|
||||||
|
}
|
||||||
|
return ArrayUtil.toArray(from, (Class<T>) IterUtil.getElementType(from.iterator()));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <T> T get(T[] array, int index) {
|
||||||
|
if (null == array || index >= array.length) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return array[index];
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,204 @@
|
|||||||
|
package com.yunxi.scm.framework.common.util.collection;
|
||||||
|
|
||||||
|
import cn.hutool.core.collection.CollUtil;
|
||||||
|
import cn.hutool.core.collection.CollectionUtil;
|
||||||
|
import com.google.common.collect.ImmutableMap;
|
||||||
|
|
||||||
|
import java.util.*;
|
||||||
|
import java.util.function.BinaryOperator;
|
||||||
|
import java.util.function.Function;
|
||||||
|
import java.util.function.Predicate;
|
||||||
|
import java.util.function.Supplier;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Collection 工具类
|
||||||
|
*
|
||||||
|
* @author 芋道源码
|
||||||
|
*/
|
||||||
|
public class CollectionUtils {
|
||||||
|
|
||||||
|
public static boolean containsAny(Object source, Object... targets) {
|
||||||
|
return Arrays.asList(targets).contains(source);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean isAnyEmpty(Collection<?>... collections) {
|
||||||
|
return Arrays.stream(collections).anyMatch(CollectionUtil::isEmpty);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <T> List<T> filterList(Collection<T> from, Predicate<T> predicate) {
|
||||||
|
if (CollUtil.isEmpty(from)) {
|
||||||
|
return new ArrayList<>();
|
||||||
|
}
|
||||||
|
return from.stream().filter(predicate).collect(Collectors.toList());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <T, R> List<T> distinct(Collection<T> from, Function<T, R> keyMapper) {
|
||||||
|
if (CollUtil.isEmpty(from)) {
|
||||||
|
return new ArrayList<>();
|
||||||
|
}
|
||||||
|
return distinct(from, keyMapper, (t1, t2) -> t1);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <T, R> List<T> distinct(Collection<T> from, Function<T, R> keyMapper, BinaryOperator<T> cover) {
|
||||||
|
if (CollUtil.isEmpty(from)) {
|
||||||
|
return new ArrayList<>();
|
||||||
|
}
|
||||||
|
return new ArrayList<>(convertMap(from, keyMapper, Function.identity(), cover).values());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <T, U> List<U> convertList(Collection<T> from, Function<T, U> func) {
|
||||||
|
if (CollUtil.isEmpty(from)) {
|
||||||
|
return new ArrayList<>();
|
||||||
|
}
|
||||||
|
return from.stream().map(func).filter(Objects::nonNull).collect(Collectors.toList());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <T, U> List<U> convertList(Collection<T> from, Function<T, U> func, Predicate<T> filter) {
|
||||||
|
if (CollUtil.isEmpty(from)) {
|
||||||
|
return new ArrayList<>();
|
||||||
|
}
|
||||||
|
return from.stream().filter(filter).map(func).filter(Objects::nonNull).collect(Collectors.toList());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <T, U> Set<U> convertSet(Collection<T> from, Function<T, U> func) {
|
||||||
|
if (CollUtil.isEmpty(from)) {
|
||||||
|
return new HashSet<>();
|
||||||
|
}
|
||||||
|
return from.stream().map(func).filter(Objects::nonNull).collect(Collectors.toSet());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <T, U> Set<U> convertSet(Collection<T> from, Function<T, U> func, Predicate<T> filter) {
|
||||||
|
if (CollUtil.isEmpty(from)) {
|
||||||
|
return new HashSet<>();
|
||||||
|
}
|
||||||
|
return from.stream().filter(filter).map(func).filter(Objects::nonNull).collect(Collectors.toSet());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <T, K> Map<K, T> convertMap(Collection<T> from, Function<T, K> keyFunc) {
|
||||||
|
if (CollUtil.isEmpty(from)) {
|
||||||
|
return new HashMap<>();
|
||||||
|
}
|
||||||
|
return convertMap(from, keyFunc, Function.identity());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <T, K> Map<K, T> convertMap(Collection<T> from, Function<T, K> keyFunc, Supplier<? extends Map<K, T>> supplier) {
|
||||||
|
if (CollUtil.isEmpty(from)) {
|
||||||
|
return supplier.get();
|
||||||
|
}
|
||||||
|
return convertMap(from, keyFunc, Function.identity(), supplier);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <T, K, V> Map<K, V> convertMap(Collection<T> from, Function<T, K> keyFunc, Function<T, V> valueFunc) {
|
||||||
|
if (CollUtil.isEmpty(from)) {
|
||||||
|
return new HashMap<>();
|
||||||
|
}
|
||||||
|
return convertMap(from, keyFunc, valueFunc, (v1, v2) -> v1);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <T, K, V> Map<K, V> convertMap(Collection<T> from, Function<T, K> keyFunc, Function<T, V> valueFunc, BinaryOperator<V> mergeFunction) {
|
||||||
|
if (CollUtil.isEmpty(from)) {
|
||||||
|
return new HashMap<>();
|
||||||
|
}
|
||||||
|
return convertMap(from, keyFunc, valueFunc, mergeFunction, HashMap::new);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <T, K, V> Map<K, V> convertMap(Collection<T> from, Function<T, K> keyFunc, Function<T, V> valueFunc, Supplier<? extends Map<K, V>> supplier) {
|
||||||
|
if (CollUtil.isEmpty(from)) {
|
||||||
|
return supplier.get();
|
||||||
|
}
|
||||||
|
return convertMap(from, keyFunc, valueFunc, (v1, v2) -> v1, supplier);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <T, K, V> Map<K, V> convertMap(Collection<T> from, Function<T, K> keyFunc, Function<T, V> valueFunc, BinaryOperator<V> mergeFunction, Supplier<? extends Map<K, V>> supplier) {
|
||||||
|
if (CollUtil.isEmpty(from)) {
|
||||||
|
return new HashMap<>();
|
||||||
|
}
|
||||||
|
return from.stream().collect(Collectors.toMap(keyFunc, valueFunc, mergeFunction, supplier));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <T, K> Map<K, List<T>> convertMultiMap(Collection<T> from, Function<T, K> keyFunc) {
|
||||||
|
if (CollUtil.isEmpty(from)) {
|
||||||
|
return new HashMap<>();
|
||||||
|
}
|
||||||
|
return from.stream().collect(Collectors.groupingBy(keyFunc, Collectors.mapping(t -> t, Collectors.toList())));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <T, K, V> Map<K, List<V>> convertMultiMap(Collection<T> from, Function<T, K> keyFunc, Function<T, V> valueFunc) {
|
||||||
|
if (CollUtil.isEmpty(from)) {
|
||||||
|
return new HashMap<>();
|
||||||
|
}
|
||||||
|
return from.stream()
|
||||||
|
.collect(Collectors.groupingBy(keyFunc, Collectors.mapping(valueFunc, Collectors.toList())));
|
||||||
|
}
|
||||||
|
|
||||||
|
// 暂时没想好名字,先以 2 结尾噶
|
||||||
|
public static <T, K, V> Map<K, Set<V>> convertMultiMap2(Collection<T> from, Function<T, K> keyFunc, Function<T, V> valueFunc) {
|
||||||
|
if (CollUtil.isEmpty(from)) {
|
||||||
|
return new HashMap<>();
|
||||||
|
}
|
||||||
|
return from.stream().collect(Collectors.groupingBy(keyFunc, Collectors.mapping(valueFunc, Collectors.toSet())));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <T, K> Map<K, T> convertImmutableMap(Collection<T> from, Function<T, K> keyFunc) {
|
||||||
|
if (CollUtil.isEmpty(from)) {
|
||||||
|
return Collections.emptyMap();
|
||||||
|
}
|
||||||
|
ImmutableMap.Builder<K, T> builder = ImmutableMap.builder();
|
||||||
|
from.forEach(item -> builder.put(keyFunc.apply(item), item));
|
||||||
|
return builder.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean containsAny(Collection<?> source, Collection<?> candidates) {
|
||||||
|
return org.springframework.util.CollectionUtils.containsAny(source, candidates);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <T> T getFirst(List<T> from) {
|
||||||
|
return !CollectionUtil.isEmpty(from) ? from.get(0) : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <T> T findFirst(List<T> from, Predicate<T> predicate) {
|
||||||
|
if (CollUtil.isEmpty(from)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return from.stream().filter(predicate).findFirst().orElse(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <T, V extends Comparable<? super V>> V getMaxValue(Collection<T> from, Function<T, V> valueFunc) {
|
||||||
|
if (CollUtil.isEmpty(from)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
assert from.size() > 0; // 断言,避免告警
|
||||||
|
T t = from.stream().max(Comparator.comparing(valueFunc)).get();
|
||||||
|
return valueFunc.apply(t);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <T, V extends Comparable<? super V>> V getMinValue(List<T> from, Function<T, V> valueFunc) {
|
||||||
|
if (CollUtil.isEmpty(from)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
assert from.size() > 0; // 断言,避免告警
|
||||||
|
T t = from.stream().min(Comparator.comparing(valueFunc)).get();
|
||||||
|
return valueFunc.apply(t);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <T, V extends Comparable<? super V>> V getSumValue(List<T> from, Function<T, V> valueFunc, BinaryOperator<V> accumulator) {
|
||||||
|
if (CollUtil.isEmpty(from)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
assert from.size() > 0; // 断言,避免告警
|
||||||
|
return from.stream().map(valueFunc).reduce(accumulator).get();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <T> void addIfNotNull(Collection<T> coll, T item) {
|
||||||
|
if (item == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
coll.add(item);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <T> Collection<T> singleton(T deptId) {
|
||||||
|
return deptId == null ? Collections.emptyList() : Collections.singleton(deptId);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,19 @@
|
|||||||
|
package com.yunxi.scm.framework.common.util.collection;
|
||||||
|
|
||||||
|
import cn.hutool.core.collection.CollUtil;
|
||||||
|
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set 工具类
|
||||||
|
*
|
||||||
|
* @author 芋道源码
|
||||||
|
*/
|
||||||
|
public class SetUtils {
|
||||||
|
|
||||||
|
@SafeVarargs
|
||||||
|
public static <T> Set<T> asSet(T... objs) {
|
||||||
|
return CollUtil.newHashSet(objs);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,16 @@
|
|||||||
|
package com.yunxi.scm.framework.common.util.object;
|
||||||
|
|
||||||
|
import com.yunxi.scm.framework.common.pojo.PageParam;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@link com.yunxi.scm.framework.common.pojo.PageParam} 工具类
|
||||||
|
*
|
||||||
|
* @author 芋道源码
|
||||||
|
*/
|
||||||
|
public class PageUtils {
|
||||||
|
|
||||||
|
public static int getStart(PageParam pageParam) {
|
||||||
|
return (pageParam.getPageNo() - 1) * pageParam.getPageSize();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,46 @@
|
|||||||
|
package com.yunxi.scm.framework.common.util.spring;
|
||||||
|
|
||||||
|
import cn.hutool.core.bean.BeanUtil;
|
||||||
|
import org.springframework.aop.framework.AdvisedSupport;
|
||||||
|
import org.springframework.aop.framework.AopProxy;
|
||||||
|
import org.springframework.aop.support.AopUtils;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Spring AOP 工具类
|
||||||
|
*
|
||||||
|
* 参考波克尔 http://www.bubuko.com/infodetail-3471885.html 实现
|
||||||
|
*/
|
||||||
|
public class SpringAopUtils {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取代理的目标对象
|
||||||
|
*
|
||||||
|
* @param proxy 代理对象
|
||||||
|
* @return 目标对象
|
||||||
|
*/
|
||||||
|
public static Object getTarget(Object proxy) throws Exception {
|
||||||
|
// 不是代理对象
|
||||||
|
if (!AopUtils.isAopProxy(proxy)) {
|
||||||
|
return proxy;
|
||||||
|
}
|
||||||
|
// Jdk 代理
|
||||||
|
if (AopUtils.isJdkDynamicProxy(proxy)) {
|
||||||
|
return getJdkDynamicProxyTargetObject(proxy);
|
||||||
|
}
|
||||||
|
// Cglib 代理
|
||||||
|
return getCglibProxyTargetObject(proxy);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Object getCglibProxyTargetObject(Object proxy) throws Exception {
|
||||||
|
Object dynamicAdvisedInterceptor = BeanUtil.getFieldValue(proxy, "CGLIB$CALLBACK_0");
|
||||||
|
AdvisedSupport advisedSupport = (AdvisedSupport) BeanUtil.getFieldValue(dynamicAdvisedInterceptor, "advised");
|
||||||
|
return advisedSupport.getTargetSource().getTarget();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Object getJdkDynamicProxyTargetObject(Object proxy) throws Exception {
|
||||||
|
AopProxy aopProxy = (AopProxy) BeanUtil.getFieldValue(proxy, "h");
|
||||||
|
AdvisedSupport advisedSupport = (AdvisedSupport) BeanUtil.getFieldValue(aopProxy, "advised");
|
||||||
|
return advisedSupport.getTargetSource().getTarget();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,53 @@
|
|||||||
|
package com.yunxi.scm.framework.common.util.string;
|
||||||
|
|
||||||
|
import cn.hutool.core.util.ArrayUtil;
|
||||||
|
import cn.hutool.core.util.StrUtil;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 字符串工具类
|
||||||
|
*
|
||||||
|
* @author 芋道源码
|
||||||
|
*/
|
||||||
|
public class StrUtils {
|
||||||
|
|
||||||
|
public static String maxLength(CharSequence str, int maxLength) {
|
||||||
|
return StrUtil.maxLength(str, maxLength - 3); // -3 的原因,是该方法会补充 ... 恰好
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 给定字符串是否以任何一个字符串开始
|
||||||
|
* 给定字符串和数组为空都返回 false
|
||||||
|
*
|
||||||
|
* @param str 给定字符串
|
||||||
|
* @param prefixes 需要检测的开始字符串
|
||||||
|
* @since 3.0.6
|
||||||
|
*/
|
||||||
|
public static boolean startWithAny(String str, Collection<String> prefixes) {
|
||||||
|
if (StrUtil.isEmpty(str) || ArrayUtil.isEmpty(prefixes)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (CharSequence suffix : prefixes) {
|
||||||
|
if (StrUtil.startWith(str, suffix, false)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static List<Long> splitToLong(String value, CharSequence separator) {
|
||||||
|
long[] longs = StrUtil.splitToLong(value, separator);
|
||||||
|
return Arrays.stream(longs).boxed().collect(Collectors.toList());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static List<Integer> splitToInteger(String value, CharSequence separator) {
|
||||||
|
int[] integers = StrUtil.splitToInt(value, separator);
|
||||||
|
return Arrays.stream(integers).boxed().collect(Collectors.toList());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,55 @@
|
|||||||
|
package com.yunxi.scm.framework.common.util.validation;
|
||||||
|
|
||||||
|
import cn.hutool.core.collection.CollUtil;
|
||||||
|
import cn.hutool.core.lang.Assert;
|
||||||
|
import org.springframework.util.StringUtils;
|
||||||
|
|
||||||
|
import javax.validation.ConstraintViolation;
|
||||||
|
import javax.validation.ConstraintViolationException;
|
||||||
|
import javax.validation.Validation;
|
||||||
|
import javax.validation.Validator;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 校验工具类
|
||||||
|
*
|
||||||
|
* @author 芋道源码
|
||||||
|
*/
|
||||||
|
public class ValidationUtils {
|
||||||
|
|
||||||
|
private static final Pattern PATTERN_MOBILE = Pattern.compile("^(?:(?:\\+|00)86)?1(?:(?:3[\\d])|(?:4[0,1,4-9])|(?:5[0-3,5-9])|(?:6[2,5-7])|(?:7[0-8])|(?:8[\\d])|(?:9[0-3,5-9]))\\d{8}$");
|
||||||
|
|
||||||
|
private static final Pattern PATTERN_URL = Pattern.compile("^(https?|ftp|file)://[-a-zA-Z0-9+&@#/%?=~_|!:,.;]*[-a-zA-Z0-9+&@#/%=~_|]");
|
||||||
|
|
||||||
|
private static final Pattern PATTERN_XML_NCNAME = Pattern.compile("[a-zA-Z_][\\-_.0-9_a-zA-Z$]*");
|
||||||
|
|
||||||
|
public static boolean isMobile(String mobile) {
|
||||||
|
return StringUtils.hasText(mobile)
|
||||||
|
&& PATTERN_MOBILE.matcher(mobile).matches();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean isURL(String url) {
|
||||||
|
return StringUtils.hasText(url)
|
||||||
|
&& PATTERN_URL.matcher(url).matches();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean isXmlNCName(String str) {
|
||||||
|
return StringUtils.hasText(str)
|
||||||
|
&& PATTERN_XML_NCNAME.matcher(str).matches();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void validate(Object object, Class<?>... groups) {
|
||||||
|
Validator validator = Validation.buildDefaultValidatorFactory().getValidator();
|
||||||
|
Assert.notNull(validator);
|
||||||
|
validate(validator, object, groups);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void validate(Validator validator, Object object, Class<?>... groups) {
|
||||||
|
Set<ConstraintViolation<Object>> constraintViolations = validator.validate(object, groups);
|
||||||
|
if (CollUtil.isNotEmpty(constraintViolations)) {
|
||||||
|
throw new ConstraintViolationException(constraintViolations);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,35 @@
|
|||||||
|
package com.yunxi.scm.framework.common.validation;
|
||||||
|
|
||||||
|
import com.yunxi.scm.framework.common.core.IntArrayValuable;
|
||||||
|
|
||||||
|
import javax.validation.Constraint;
|
||||||
|
import javax.validation.Payload;
|
||||||
|
import java.lang.annotation.*;
|
||||||
|
|
||||||
|
@Target({
|
||||||
|
ElementType.METHOD,
|
||||||
|
ElementType.FIELD,
|
||||||
|
ElementType.ANNOTATION_TYPE,
|
||||||
|
ElementType.CONSTRUCTOR,
|
||||||
|
ElementType.PARAMETER,
|
||||||
|
ElementType.TYPE_USE
|
||||||
|
})
|
||||||
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
@Documented
|
||||||
|
@Constraint(
|
||||||
|
validatedBy = InEnumValidator.class
|
||||||
|
)
|
||||||
|
public @interface InEnum {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return 实现 EnumValuable 接口的
|
||||||
|
*/
|
||||||
|
Class<? extends IntArrayValuable> value();
|
||||||
|
|
||||||
|
String message() default "必须在指定范围 {value}";
|
||||||
|
|
||||||
|
Class<?>[] groups() default {};
|
||||||
|
|
||||||
|
Class<? extends Payload>[] payload() default {};
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,44 @@
|
|||||||
|
package com.yunxi.scm.framework.common.validation;
|
||||||
|
|
||||||
|
import com.yunxi.scm.framework.common.core.IntArrayValuable;
|
||||||
|
|
||||||
|
import javax.validation.ConstraintValidator;
|
||||||
|
import javax.validation.ConstraintValidatorContext;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
public class InEnumValidator implements ConstraintValidator<InEnum, Integer> {
|
||||||
|
|
||||||
|
private List<Integer> values;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void initialize(InEnum annotation) {
|
||||||
|
IntArrayValuable[] values = annotation.value().getEnumConstants();
|
||||||
|
if (values.length == 0) {
|
||||||
|
this.values = Collections.emptyList();
|
||||||
|
} else {
|
||||||
|
this.values = Arrays.stream(values[0].array()).boxed().collect(Collectors.toList());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isValid(Integer value, ConstraintValidatorContext context) {
|
||||||
|
// 为空时,默认不校验,即认为通过
|
||||||
|
if (value == null) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
// 校验通过
|
||||||
|
if (values.contains(value)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
// 校验不通过,自定义提示语句(因为,注解上的 value 是枚举类,无法获得枚举类的实际值)
|
||||||
|
context.disableDefaultConstraintViolation(); // 禁用默认的 message 的值
|
||||||
|
context.buildConstraintViolationWithTemplate(context.getDefaultConstraintMessageTemplate()
|
||||||
|
.replaceAll("\\{value}", values.toString())).addConstraintViolation(); // 重新添加错误提示语句
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in new issue