mirror of
https://github.com/dromara/RuoYi-Vue-Plus.git
synced 2025-09-19 17:56:41 +08:00
Merge remote-tracking branch 'origin/dev'
# Conflicts: # README.md
This commit is contained in:
commit
85762f7c92
12
README.md
12
README.md
@ -4,16 +4,19 @@
|
|||||||
[](https://gitee.com/JavaLionLi/RuoYi-Vue-Plus/blob/master/LICENSE)
|
[](https://gitee.com/JavaLionLi/RuoYi-Vue-Plus/blob/master/LICENSE)
|
||||||
[](https://www.jetbrains.com/?from=RuoYi-Vue-Plus)
|
[](https://www.jetbrains.com/?from=RuoYi-Vue-Plus)
|
||||||
<br>
|
<br>
|
||||||
[](https://gitee.com/JavaLionLi/RuoYi-Vue-Plus)
|
[](https://gitee.com/JavaLionLi/RuoYi-Vue-Plus)
|
||||||
[]()
|
[]()
|
||||||
[]()
|
[]()
|
||||||
[]()
|
[]()
|
||||||
|
[]()
|
||||||
|
|
||||||
RuoYi-Vue-Plus 是基于 RuoYi-Vue 针对 `分布式集群` 场景升级(不兼容原框架)
|
RuoYi-Vue-Plus 是基于 RuoYi-Vue 针对 `分布式集群` 场景升级(不兼容原框架)
|
||||||
|
|
||||||
| 功能介绍 | 使用技术 | 文档地址 | 特性注意事项 |
|
| 功能介绍 | 使用技术 | 文档地址 | 特性注意事项 |
|
||||||
|---|---|---|---|
|
|---|---|---|---|
|
||||||
| 当前框架 | RuoYi-Vue-Plus | [RuoYi-Vue-Plus文档](https://gitee.com/JavaLionLi/RuoYi-Vue-Plus/wikis/pages) | 重写RuoYi-Vue全方位升级(不兼容原框架) |
|
| 当前框架 | RuoYi-Vue-Plus | [RuoYi-Vue-Plus文档](https://gitee.com/JavaLionLi/RuoYi-Vue-Plus/wikis/pages) | 重写RuoYi-Vue全方位升级(不兼容原框架) |
|
||||||
|
| satoken分支 | RuoYi-Vue-Plus-satoken | [satoken分支地址](https://gitee.com/JavaLionLi/RuoYi-Vue-Plus/tree/satoken/) | 使用satoken重构权限鉴权(仅供学习不推荐上生产) |
|
||||||
|
| 单体分支 | RuoYi-Vue-Plus-fast | [fast分支地址](https://gitee.com/JavaLionLi/RuoYi-Vue-Plus/tree/fast/) | 单体应用结构 |
|
||||||
| 原框架 | RuoYi-Vue | [RuoYi-Vue官网](http://ruoyi.vip/) | 定期同步需要的功能 |
|
| 原框架 | RuoYi-Vue | [RuoYi-Vue官网](http://ruoyi.vip/) | 定期同步需要的功能 |
|
||||||
| 前端开发框架 | Vue、Element UI | [Element UI官网](https://element.eleme.cn/#/zh-CN) | |
|
| 前端开发框架 | Vue、Element UI | [Element UI官网](https://element.eleme.cn/#/zh-CN) | |
|
||||||
| 后端开发框架 | SpringBoot | [SpringBoot官网](https://spring.io/projects/spring-boot/#learn) | |
|
| 后端开发框架 | SpringBoot | [SpringBoot官网](https://spring.io/projects/spring-boot/#learn) | |
|
||||||
@ -24,10 +27,12 @@ RuoYi-Vue-Plus 是基于 RuoYi-Vue 针对 `分布式集群` 场景升级(不兼
|
|||||||
| 数据库框架 | Mybatis-Plus | [Mybatis-Plus文档](https://baomidou.com/guide/) | 快速 CRUD 增加开发效率 |
|
| 数据库框架 | Mybatis-Plus | [Mybatis-Plus文档](https://baomidou.com/guide/) | 快速 CRUD 增加开发效率 |
|
||||||
| 数据库框架 | p6spy | [p6spy官网](https://p6spy.readthedocs.io/) | 更强劲的 SQL 分析 |
|
| 数据库框架 | p6spy | [p6spy官网](https://p6spy.readthedocs.io/) | 更强劲的 SQL 分析 |
|
||||||
| 多数据源框架 | dynamic-datasource | [dynamic-ds文档](https://www.kancloud.cn/tracy5546/dynamic-datasource/content) | 支持主从与多种类数据库异构 |
|
| 多数据源框架 | dynamic-datasource | [dynamic-ds文档](https://www.kancloud.cn/tracy5546/dynamic-datasource/content) | 支持主从与多种类数据库异构 |
|
||||||
| Redis客户端 | Redisson | [Redisson文档](https://github.com/redisson/redisson/wiki/%E7%9B%AE%E5%BD%95) | 性能强劲、API丰富 |
|
|
||||||
| 序列化框架 | Jackson | [Jackson官网](https://github.com/FasterXML/jackson) | 统一使用 jackson 高效可靠 |
|
| 序列化框架 | Jackson | [Jackson官网](https://github.com/FasterXML/jackson) | 统一使用 jackson 高效可靠 |
|
||||||
| 网络框架 | Feign、OkHttp3 | [Feign官网](https://github.com/OpenFeign/feign) | 接口化管理 HTTP 请求 |
|
| 网络框架 | Feign、OkHttp3 | [Feign官网](https://github.com/OpenFeign/feign) | 接口化管理 HTTP 请求 |
|
||||||
|
| Redis客户端 | Redisson | [Redisson文档](https://github.com/redisson/redisson/wiki/%E7%9B%AE%E5%BD%95) | 支持单机、集群配置 |
|
||||||
|
| 分布式限流 | Redisson | [Redisson文档](https://github.com/redisson/redisson/wiki/%E7%9B%AE%E5%BD%95) | 全局、请求IP、集群ID 多种限流 |
|
||||||
| 分布式锁 | Lock4j | [Lock4j官网](https://gitee.com/baomidou/lock4j) | 注解锁、工具锁 多种多样 |
|
| 分布式锁 | Lock4j | [Lock4j官网](https://gitee.com/baomidou/lock4j) | 注解锁、工具锁 多种多样 |
|
||||||
|
| 分布式幂等 | Lock4j | [Lock4j文档](https://gitee.com/baomidou/lock4j) | 基于分布式锁实现 |
|
||||||
| 文件存储 | Minio | [Minio文档](https://docs.min.io/) | 本地存储 |
|
| 文件存储 | Minio | [Minio文档](https://docs.min.io/) | 本地存储 |
|
||||||
| 文件存储 | 七牛、阿里、腾讯 | [OSS使用文档](https://gitee.com/JavaLionLi/RuoYi-Vue-Plus/wikis/pages?sort_id=4359146&doc_id=1469725) | 云存储 |
|
| 文件存储 | 七牛、阿里、腾讯 | [OSS使用文档](https://gitee.com/JavaLionLi/RuoYi-Vue-Plus/wikis/pages?sort_id=4359146&doc_id=1469725) | 云存储 |
|
||||||
| 监控框架 | SpringBoot-Admin | [SpringBoot-Admin文档](https://codecentric.github.io/spring-boot-admin/current/) | 全方位服务监控 |
|
| 监控框架 | SpringBoot-Admin | [SpringBoot-Admin文档](https://codecentric.github.io/spring-boot-admin/current/) | 全方位服务监控 |
|
||||||
@ -67,6 +72,7 @@ RuoYi-Vue-Plus 是基于 RuoYi-Vue 针对 `分布式集群` 场景升级(不兼
|
|||||||
* 同步升级 RuoYi-Vue
|
* 同步升级 RuoYi-Vue
|
||||||
* GitHub 地址 [RuoYi-Vue-Plus-github](https://github.com/JavaLionLi/RuoYi-Vue-Plus)
|
* GitHub 地址 [RuoYi-Vue-Plus-github](https://github.com/JavaLionLi/RuoYi-Vue-Plus)
|
||||||
* 单模块 fast 分支 [RuoYi-Vue-Plus-fast](https://gitee.com/JavaLionLi/RuoYi-Vue-Plus/tree/fast/)
|
* 单模块 fast 分支 [RuoYi-Vue-Plus-fast](https://gitee.com/JavaLionLi/RuoYi-Vue-Plus/tree/fast/)
|
||||||
|
* satoken 分支 [RuoYi-Vue-Plus-satoken](https://gitee.com/JavaLionLi/RuoYi-Vue-Plus/tree/satoken/)
|
||||||
* 用户扩展项目 [扩展项目列表](https://gitee.com/JavaLionLi/RuoYi-Vue-Plus/wikis/pages?sort_id=4478302&doc_id=1469725)
|
* 用户扩展项目 [扩展项目列表](https://gitee.com/JavaLionLi/RuoYi-Vue-Plus/wikis/pages?sort_id=4478302&doc_id=1469725)
|
||||||
|
|
||||||
## 加群与捐献
|
## 加群与捐献
|
||||||
|
@ -103,7 +103,7 @@ services:
|
|||||||
ipv4_address: 172.30.0.54
|
ipv4_address: 172.30.0.54
|
||||||
|
|
||||||
ruoyi-server1:
|
ruoyi-server1:
|
||||||
image: "ruoyi/ruoyi-server:3.1.0"
|
image: "ruoyi/ruoyi-server:3.2.0"
|
||||||
container_name: ruoyi-server1
|
container_name: ruoyi-server1
|
||||||
environment:
|
environment:
|
||||||
# 时区上海
|
# 时区上海
|
||||||
@ -118,7 +118,7 @@ services:
|
|||||||
ipv4_address: 172.30.0.60
|
ipv4_address: 172.30.0.60
|
||||||
|
|
||||||
ruoyi-server2:
|
ruoyi-server2:
|
||||||
image: "ruoyi/ruoyi-server:3.1.0"
|
image: "ruoyi/ruoyi-server:3.2.0"
|
||||||
container_name: ruoyi-server2
|
container_name: ruoyi-server2
|
||||||
environment:
|
environment:
|
||||||
# 时区上海
|
# 时区上海
|
||||||
@ -133,7 +133,7 @@ services:
|
|||||||
ipv4_address: 172.30.0.61
|
ipv4_address: 172.30.0.61
|
||||||
|
|
||||||
ruoyi-monitor-admin:
|
ruoyi-monitor-admin:
|
||||||
image: "ruoyi/ruoyi-monitor-admin:3.1.0"
|
image: "ruoyi/ruoyi-monitor-admin:3.2.0"
|
||||||
container_name: ruoyi-monitor-admin
|
container_name: ruoyi-monitor-admin
|
||||||
environment:
|
environment:
|
||||||
# 时区上海
|
# 时区上海
|
||||||
|
96
pom.xml
96
pom.xml
@ -6,40 +6,44 @@
|
|||||||
|
|
||||||
<groupId>com.ruoyi</groupId>
|
<groupId>com.ruoyi</groupId>
|
||||||
<artifactId>ruoyi-vue-plus</artifactId>
|
<artifactId>ruoyi-vue-plus</artifactId>
|
||||||
<version>3.1.0</version>
|
<version>3.2.0</version>
|
||||||
|
|
||||||
<name>RuoYi-Vue-Plus</name>
|
<name>RuoYi-Vue-Plus</name>
|
||||||
<url>https://gitee.com/JavaLionLi/RuoYi-Vue-Plus</url>
|
<url>https://gitee.com/JavaLionLi/RuoYi-Vue-Plus</url>
|
||||||
<description>RuoYi-Vue-Plus后台管理系统</description>
|
<description>RuoYi-Vue-Plus后台管理系统</description>
|
||||||
|
|
||||||
<properties>
|
<properties>
|
||||||
<ruoyi-vue-plus.version>3.1.0</ruoyi-vue-plus.version>
|
<ruoyi-vue-plus.version>3.2.0</ruoyi-vue-plus.version>
|
||||||
<spring-boot.version>2.5.4</spring-boot.version>
|
<spring-boot.version>2.5.5</spring-boot.version>
|
||||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||||
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
|
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
|
||||||
<java.version>1.8</java.version>
|
<java.version>1.8</java.version>
|
||||||
<maven-jar-plugin.version>3.2.0</maven-jar-plugin.version>
|
<maven-jar-plugin.version>3.2.0</maven-jar-plugin.version>
|
||||||
<druid.version>1.2.6</druid.version>
|
<druid.version>1.2.6</druid.version>
|
||||||
<knife4j.version>3.0.3</knife4j.version>
|
<knife4j.version>3.0.3</knife4j.version>
|
||||||
|
<swagger-annotations.version>1.5.22</swagger-annotations.version>
|
||||||
<poi.version>4.1.2</poi.version>
|
<poi.version>4.1.2</poi.version>
|
||||||
<easyexcel.version>2.2.10</easyexcel.version>
|
<easyexcel.version>2.2.11</easyexcel.version>
|
||||||
<velocity.version>1.7</velocity.version>
|
<velocity.version>1.7</velocity.version>
|
||||||
<jwt.version>0.9.1</jwt.version>
|
<jwt.version>0.9.1</jwt.version>
|
||||||
<mybatis-plus.version>3.4.3.3</mybatis-plus.version>
|
<mybatis-plus.version>3.4.3.4</mybatis-plus.version>
|
||||||
<p6spy.version>3.9.1</p6spy.version>
|
<p6spy.version>3.9.1</p6spy.version>
|
||||||
<hutool.version>5.7.11</hutool.version>
|
<hutool.version>5.7.13</hutool.version>
|
||||||
<feign.version>3.0.3</feign.version>
|
<feign.version>3.0.3</feign.version>
|
||||||
<feign-okhttp.version>11.6</feign-okhttp.version>
|
<feign-okhttp.version>11.6</feign-okhttp.version>
|
||||||
<okhttp.version>4.9.1</okhttp.version>
|
<okhttp.version>4.9.1</okhttp.version>
|
||||||
<spring-boot-admin.version>2.5.1</spring-boot-admin.version>
|
<spring-boot-admin.version>2.5.1</spring-boot-admin.version>
|
||||||
<redisson.version>3.16.2</redisson.version>
|
<redisson.version>3.16.3</redisson.version>
|
||||||
<lock4j.version>2.2.1</lock4j.version>
|
<lock4j.version>2.2.1</lock4j.version>
|
||||||
<dynamic-ds.version>3.4.1</dynamic-ds.version>
|
<dynamic-ds.version>3.4.1</dynamic-ds.version>
|
||||||
|
|
||||||
|
<!-- jdk11 缺失依赖 jaxb-->
|
||||||
|
<jaxb.version>3.0.1</jaxb.version>
|
||||||
|
|
||||||
<!-- OSS 配置 -->
|
<!-- OSS 配置 -->
|
||||||
<qiniu.version>7.8.0</qiniu.version>
|
<qiniu.version>7.8.0</qiniu.version>
|
||||||
<aliyun.oss.version>3.13.1</aliyun.oss.version>
|
<aliyun.oss.version>3.13.1</aliyun.oss.version>
|
||||||
<qcloud.cos.version>5.6.51</qcloud.cos.version>
|
<qcloud.cos.version>5.6.55</qcloud.cos.version>
|
||||||
<minio.version>8.3.0</minio.version>
|
<minio.version>8.3.0</minio.version>
|
||||||
|
|
||||||
<!-- docker 配置 -->
|
<!-- docker 配置 -->
|
||||||
@ -73,6 +77,18 @@
|
|||||||
<groupId>com.github.xiaoymin</groupId>
|
<groupId>com.github.xiaoymin</groupId>
|
||||||
<artifactId>knife4j-spring-boot-starter</artifactId>
|
<artifactId>knife4j-spring-boot-starter</artifactId>
|
||||||
<version>${knife4j.version}</version>
|
<version>${knife4j.version}</version>
|
||||||
|
<exclusions>
|
||||||
|
<exclusion>
|
||||||
|
<artifactId>swagger-annotations</artifactId>
|
||||||
|
<groupId>io.swagger</groupId>
|
||||||
|
</exclusion>
|
||||||
|
</exclusions>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>io.swagger</groupId>
|
||||||
|
<artifactId>swagger-annotations</artifactId>
|
||||||
|
<version>${swagger-annotations.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<!-- excel工具 -->
|
<!-- excel工具 -->
|
||||||
@ -86,6 +102,16 @@
|
|||||||
<groupId>com.alibaba</groupId>
|
<groupId>com.alibaba</groupId>
|
||||||
<artifactId>easyexcel</artifactId>
|
<artifactId>easyexcel</artifactId>
|
||||||
<version>${easyexcel.version}</version>
|
<version>${easyexcel.version}</version>
|
||||||
|
<exclusions>
|
||||||
|
<exclusion>
|
||||||
|
<groupId>org.apache.poi</groupId>
|
||||||
|
<artifactId>poi</artifactId>
|
||||||
|
</exclusion>
|
||||||
|
<exclusion>
|
||||||
|
<groupId>org.apache.poi</groupId>
|
||||||
|
<artifactId>poi-ooxml-schemas</artifactId>
|
||||||
|
</exclusion>
|
||||||
|
</exclusions>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<!-- velocity代码生成使用模板 -->
|
<!-- velocity代码生成使用模板 -->
|
||||||
@ -136,6 +162,12 @@
|
|||||||
<groupId>org.springframework.cloud</groupId>
|
<groupId>org.springframework.cloud</groupId>
|
||||||
<artifactId>spring-cloud-starter-openfeign</artifactId>
|
<artifactId>spring-cloud-starter-openfeign</artifactId>
|
||||||
<version>${feign.version}</version>
|
<version>${feign.version}</version>
|
||||||
|
<exclusions>
|
||||||
|
<exclusion>
|
||||||
|
<artifactId>feign-core</artifactId>
|
||||||
|
<groupId>io.github.openfeign</groupId>
|
||||||
|
</exclusion>
|
||||||
|
</exclusions>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
@ -239,7 +271,12 @@
|
|||||||
|
|
||||||
|
|
||||||
<dependencies>
|
<dependencies>
|
||||||
|
<!-- jdk11 缺失依赖 jaxb-->
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.sun.xml.bind</groupId>
|
||||||
|
<artifactId>jaxb-impl</artifactId>
|
||||||
|
<version>${jaxb.version}</version>
|
||||||
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
<build>
|
<build>
|
||||||
@ -318,48 +355,9 @@
|
|||||||
<properties>
|
<properties>
|
||||||
<profiles.active>prod</profiles.active>
|
<profiles.active>prod</profiles.active>
|
||||||
<logging.level>warn</logging.level>
|
<logging.level>warn</logging.level>
|
||||||
<endpoints.include>health,info</endpoints.include>
|
<endpoints.include>health, info, logfile</endpoints.include>
|
||||||
</properties>
|
</properties>
|
||||||
</profile>
|
</profile>
|
||||||
|
|
||||||
<!-- jdk多版本配置 -->
|
|
||||||
<profile>
|
|
||||||
<id>jdk8</id>
|
|
||||||
<activation>
|
|
||||||
<activeByDefault>true</activeByDefault>
|
|
||||||
<jdk>1.8</jdk>
|
|
||||||
</activation>
|
|
||||||
<properties>
|
|
||||||
<java.version>1.8</java.version>
|
|
||||||
</properties>
|
|
||||||
</profile>
|
|
||||||
<profile>
|
|
||||||
<id>jdk11</id>
|
|
||||||
<activation>
|
|
||||||
<jdk>11</jdk>
|
|
||||||
</activation>
|
|
||||||
<properties>
|
|
||||||
<java.version>11</java.version>
|
|
||||||
<jaxb.version>3.0.1</jaxb.version>
|
|
||||||
</properties>
|
|
||||||
<dependencyManagement>
|
|
||||||
<dependencies>
|
|
||||||
<!-- jdk11 缺失依赖 jaxb-->
|
|
||||||
<dependency>
|
|
||||||
<groupId>com.sun.xml.bind</groupId>
|
|
||||||
<artifactId>jaxb-impl</artifactId>
|
|
||||||
<version>${jaxb.version}</version>
|
|
||||||
</dependency>
|
|
||||||
</dependencies>
|
|
||||||
</dependencyManagement>
|
|
||||||
<dependencies>
|
|
||||||
<!--jaxb-->
|
|
||||||
<dependency>
|
|
||||||
<groupId>com.sun.xml.bind</groupId>
|
|
||||||
<artifactId>jaxb-impl</artifactId>
|
|
||||||
</dependency>
|
|
||||||
</dependencies>
|
|
||||||
</profile>
|
|
||||||
</profiles>
|
</profiles>
|
||||||
|
|
||||||
</project>
|
</project>
|
@ -5,7 +5,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<artifactId>ruoyi-vue-plus</artifactId>
|
<artifactId>ruoyi-vue-plus</artifactId>
|
||||||
<groupId>com.ruoyi</groupId>
|
<groupId>com.ruoyi</groupId>
|
||||||
<version>3.1.0</version>
|
<version>3.2.0</version>
|
||||||
</parent>
|
</parent>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
<packaging>jar</packaging>
|
<packaging>jar</packaging>
|
||||||
@ -36,6 +36,11 @@
|
|||||||
<artifactId>ruoyi-framework</artifactId>
|
<artifactId>ruoyi-framework</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.ruoyi</groupId>
|
||||||
|
<artifactId>ruoyi-system</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
<!-- 定时任务-->
|
<!-- 定时任务-->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.ruoyi</groupId>
|
<groupId>com.ruoyi</groupId>
|
||||||
@ -82,7 +87,7 @@
|
|||||||
<plugin>
|
<plugin>
|
||||||
<groupId>org.apache.maven.plugins</groupId>
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
<artifactId>maven-war-plugin</artifactId>
|
<artifactId>maven-war-plugin</artifactId>
|
||||||
<version>3.1.0</version>
|
<version>3.2.0</version>
|
||||||
<configuration>
|
<configuration>
|
||||||
<failOnMissingWebXml>false</failOnMissingWebXml>
|
<failOnMissingWebXml>false</failOnMissingWebXml>
|
||||||
<warName>${project.artifactId}</warName>
|
<warName>${project.artifactId}</warName>
|
||||||
|
@ -6,8 +6,8 @@ import com.ruoyi.common.core.domain.entity.SysMenu;
|
|||||||
import com.ruoyi.common.core.domain.entity.SysUser;
|
import com.ruoyi.common.core.domain.entity.SysUser;
|
||||||
import com.ruoyi.common.core.domain.model.LoginBody;
|
import com.ruoyi.common.core.domain.model.LoginBody;
|
||||||
import com.ruoyi.common.utils.SecurityUtils;
|
import com.ruoyi.common.utils.SecurityUtils;
|
||||||
import com.ruoyi.framework.web.service.SysLoginService;
|
import com.ruoyi.system.service.SysLoginService;
|
||||||
import com.ruoyi.framework.web.service.SysPermissionService;
|
import com.ruoyi.system.service.SysPermissionService;
|
||||||
import com.ruoyi.system.service.ISysMenuService;
|
import com.ruoyi.system.service.ISysMenuService;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.web.bind.annotation.GetMapping;
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
|
@ -25,14 +25,14 @@ import javax.validation.constraints.NotNull;
|
|||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 云存储配置Controller
|
* 对象存储配置Controller
|
||||||
*
|
*
|
||||||
* @author Lion Li
|
* @author Lion Li
|
||||||
* @author 孤舟烟雨
|
* @author 孤舟烟雨
|
||||||
* @date 2021-08-13
|
* @date 2021-08-13
|
||||||
*/
|
*/
|
||||||
@Validated
|
@Validated
|
||||||
@Api(value = "云存储配置控制器", tags = {"云存储配置管理"})
|
@Api(value = "对象存储配置控制器", tags = {"对象存储配置管理"})
|
||||||
@RequiredArgsConstructor(onConstructor_ = @Autowired)
|
@RequiredArgsConstructor(onConstructor_ = @Autowired)
|
||||||
@RestController
|
@RestController
|
||||||
@RequestMapping("/system/oss/config")
|
@RequestMapping("/system/oss/config")
|
||||||
@ -41,9 +41,9 @@ public class SysOssConfigController extends BaseController {
|
|||||||
private final ISysOssConfigService iSysOssConfigService;
|
private final ISysOssConfigService iSysOssConfigService;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 查询云存储配置列表
|
* 查询对象存储配置列表
|
||||||
*/
|
*/
|
||||||
@ApiOperation("查询云存储配置列表")
|
@ApiOperation("查询对象存储配置列表")
|
||||||
@PreAuthorize("@ss.hasPermi('system:oss:list')")
|
@PreAuthorize("@ss.hasPermi('system:oss:list')")
|
||||||
@GetMapping("/list")
|
@GetMapping("/list")
|
||||||
public TableDataInfo<SysOssConfigVo> list(@Validated(QueryGroup.class) SysOssConfigBo bo) {
|
public TableDataInfo<SysOssConfigVo> list(@Validated(QueryGroup.class) SysOssConfigBo bo) {
|
||||||
@ -51,9 +51,9 @@ public class SysOssConfigController extends BaseController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取云存储配置详细信息
|
* 获取对象存储配置详细信息
|
||||||
*/
|
*/
|
||||||
@ApiOperation("获取云存储配置详细信息")
|
@ApiOperation("获取对象存储配置详细信息")
|
||||||
@PreAuthorize("@ss.hasPermi('system:oss:query')")
|
@PreAuthorize("@ss.hasPermi('system:oss:query')")
|
||||||
@GetMapping("/{ossConfigId}")
|
@GetMapping("/{ossConfigId}")
|
||||||
public AjaxResult<SysOssConfigVo> getInfo(@NotNull(message = "主键不能为空")
|
public AjaxResult<SysOssConfigVo> getInfo(@NotNull(message = "主键不能为空")
|
||||||
@ -62,11 +62,11 @@ public class SysOssConfigController extends BaseController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 新增云存储配置
|
* 新增对象存储配置
|
||||||
*/
|
*/
|
||||||
@ApiOperation("新增云存储配置")
|
@ApiOperation("新增对象存储配置")
|
||||||
@PreAuthorize("@ss.hasPermi('system:oss:add')")
|
@PreAuthorize("@ss.hasPermi('system:oss:add')")
|
||||||
@Log(title = "云存储配置", businessType = BusinessType.INSERT)
|
@Log(title = "对象存储配置", businessType = BusinessType.INSERT)
|
||||||
@RepeatSubmit()
|
@RepeatSubmit()
|
||||||
@PostMapping()
|
@PostMapping()
|
||||||
public AjaxResult<Void> add(@Validated(AddGroup.class) @RequestBody SysOssConfigBo bo) {
|
public AjaxResult<Void> add(@Validated(AddGroup.class) @RequestBody SysOssConfigBo bo) {
|
||||||
@ -74,11 +74,11 @@ public class SysOssConfigController extends BaseController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 修改云存储配置
|
* 修改对象存储配置
|
||||||
*/
|
*/
|
||||||
@ApiOperation("修改云存储配置")
|
@ApiOperation("修改对象存储配置")
|
||||||
@PreAuthorize("@ss.hasPermi('system:oss:edit')")
|
@PreAuthorize("@ss.hasPermi('system:oss:edit')")
|
||||||
@Log(title = "云存储配置", businessType = BusinessType.UPDATE)
|
@Log(title = "对象存储配置", businessType = BusinessType.UPDATE)
|
||||||
@RepeatSubmit()
|
@RepeatSubmit()
|
||||||
@PutMapping()
|
@PutMapping()
|
||||||
public AjaxResult<Void> edit(@Validated(EditGroup.class) @RequestBody SysOssConfigBo bo) {
|
public AjaxResult<Void> edit(@Validated(EditGroup.class) @RequestBody SysOssConfigBo bo) {
|
||||||
@ -86,11 +86,11 @@ public class SysOssConfigController extends BaseController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 删除云存储配置
|
* 删除对象存储配置
|
||||||
*/
|
*/
|
||||||
@ApiOperation("删除云存储配置")
|
@ApiOperation("删除对象存储配置")
|
||||||
@PreAuthorize("@ss.hasPermi('system:oss:remove')")
|
@PreAuthorize("@ss.hasPermi('system:oss:remove')")
|
||||||
@Log(title = "云存储配置", businessType = BusinessType.DELETE)
|
@Log(title = "对象存储配置", businessType = BusinessType.DELETE)
|
||||||
@DeleteMapping("/{ossConfigIds}")
|
@DeleteMapping("/{ossConfigIds}")
|
||||||
public AjaxResult<Void> remove(@NotEmpty(message = "主键不能为空")
|
public AjaxResult<Void> remove(@NotEmpty(message = "主键不能为空")
|
||||||
@PathVariable Long[] ossConfigIds) {
|
@PathVariable Long[] ossConfigIds) {
|
||||||
@ -101,7 +101,7 @@ public class SysOssConfigController extends BaseController {
|
|||||||
* 状态修改
|
* 状态修改
|
||||||
*/
|
*/
|
||||||
@PreAuthorize("@ss.hasPermi('system:oss:edit')")
|
@PreAuthorize("@ss.hasPermi('system:oss:edit')")
|
||||||
@Log(title = "云存储状态修改", businessType = BusinessType.UPDATE)
|
@Log(title = "对象存储状态修改", businessType = BusinessType.UPDATE)
|
||||||
@PutMapping("/changeStatus")
|
@PutMapping("/changeStatus")
|
||||||
public AjaxResult changeStatus(@RequestBody SysOssConfigBo bo) {
|
public AjaxResult changeStatus(@RequestBody SysOssConfigBo bo) {
|
||||||
return toAjax(iSysOssConfigService.updateOssConfigStatus(bo));
|
return toAjax(iSysOssConfigService.updateOssConfigStatus(bo));
|
||||||
|
@ -3,6 +3,7 @@ package com.ruoyi.web.controller.system;
|
|||||||
|
|
||||||
import cn.hutool.core.convert.Convert;
|
import cn.hutool.core.convert.Convert;
|
||||||
import cn.hutool.core.util.ObjectUtil;
|
import cn.hutool.core.util.ObjectUtil;
|
||||||
|
import cn.hutool.http.HttpException;
|
||||||
import cn.hutool.http.HttpUtil;
|
import cn.hutool.http.HttpUtil;
|
||||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||||
import com.ruoyi.common.annotation.Log;
|
import com.ruoyi.common.annotation.Log;
|
||||||
@ -49,7 +50,7 @@ import java.util.Map;
|
|||||||
* @author Lion Li
|
* @author Lion Li
|
||||||
*/
|
*/
|
||||||
@Validated
|
@Validated
|
||||||
@Api(value = "OSS云存储控制器", tags = {"OSS云存储管理"})
|
@Api(value = "OSS对象存储控制器", tags = {"OSS对象存储管理"})
|
||||||
@RequiredArgsConstructor(onConstructor_ = @Autowired)
|
@RequiredArgsConstructor(onConstructor_ = @Autowired)
|
||||||
@RestController
|
@RestController
|
||||||
@RequestMapping("/system/oss")
|
@RequestMapping("/system/oss")
|
||||||
@ -59,9 +60,9 @@ public class SysOssController extends BaseController {
|
|||||||
private final ISysConfigService iSysConfigService;
|
private final ISysConfigService iSysConfigService;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 查询OSS云存储列表
|
* 查询OSS对象存储列表
|
||||||
*/
|
*/
|
||||||
@ApiOperation("查询OSS云存储列表")
|
@ApiOperation("查询OSS对象存储列表")
|
||||||
@PreAuthorize("@ss.hasPermi('system:oss:list')")
|
@PreAuthorize("@ss.hasPermi('system:oss:list')")
|
||||||
@GetMapping("/list")
|
@GetMapping("/list")
|
||||||
public TableDataInfo<SysOssVo> list(@Validated(QueryGroup.class) SysOssBo bo) {
|
public TableDataInfo<SysOssVo> list(@Validated(QueryGroup.class) SysOssBo bo) {
|
||||||
@ -69,14 +70,14 @@ public class SysOssController extends BaseController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 上传OSS云存储
|
* 上传OSS对象存储
|
||||||
*/
|
*/
|
||||||
@ApiOperation("上传OSS云存储")
|
@ApiOperation("上传OSS对象存储")
|
||||||
@ApiImplicitParams({
|
@ApiImplicitParams({
|
||||||
@ApiImplicitParam(name = "file", value = "文件", dataType = "java.io.File", required = true),
|
@ApiImplicitParam(name = "file", value = "文件", dataType = "java.io.File", required = true),
|
||||||
})
|
})
|
||||||
@PreAuthorize("@ss.hasPermi('system:oss:upload')")
|
@PreAuthorize("@ss.hasPermi('system:oss:upload')")
|
||||||
@Log(title = "OSS云存储", businessType = BusinessType.INSERT)
|
@Log(title = "OSS对象存储", businessType = BusinessType.INSERT)
|
||||||
@RepeatSubmit
|
@RepeatSubmit
|
||||||
@PostMapping("/upload")
|
@PostMapping("/upload")
|
||||||
public AjaxResult<Map<String, String>> upload(@RequestPart("file") MultipartFile file) {
|
public AjaxResult<Map<String, String>> upload(@RequestPart("file") MultipartFile file) {
|
||||||
@ -90,7 +91,7 @@ public class SysOssController extends BaseController {
|
|||||||
return AjaxResult.success(map);
|
return AjaxResult.success(map);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ApiOperation("下载OSS云存储")
|
@ApiOperation("下载OSS对象存储")
|
||||||
@PreAuthorize("@ss.hasPermi('system:oss:download')")
|
@PreAuthorize("@ss.hasPermi('system:oss:download')")
|
||||||
@GetMapping("/download/{ossId}")
|
@GetMapping("/download/{ossId}")
|
||||||
public void download(@PathVariable Long ossId, HttpServletResponse response) throws IOException {
|
public void download(@PathVariable Long ossId, HttpServletResponse response) throws IOException {
|
||||||
@ -101,18 +102,27 @@ public class SysOssController extends BaseController {
|
|||||||
response.reset();
|
response.reset();
|
||||||
response.addHeader("Access-Control-Allow-Origin", "*");
|
response.addHeader("Access-Control-Allow-Origin", "*");
|
||||||
response.addHeader("Access-Control-Expose-Headers", "Content-Disposition");
|
response.addHeader("Access-Control-Expose-Headers", "Content-Disposition");
|
||||||
FileUtils.setAttachmentResponseHeader(response, URLEncoder.encode(sysOss.getOriginalName(), StandardCharsets.UTF_8.toString()));
|
FileUtils.setAttachmentResponseHeader(response, sysOss.getOriginalName());
|
||||||
response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE + "; charset=UTF-8");
|
response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE + "; charset=UTF-8");
|
||||||
long data = HttpUtil.download(sysOss.getUrl(), response.getOutputStream(), false);
|
long data;
|
||||||
|
try {
|
||||||
|
data = HttpUtil.download(sysOss.getUrl(), response.getOutputStream(), false);
|
||||||
|
} catch (HttpException e) {
|
||||||
|
if (e.getMessage().contains("403")) {
|
||||||
|
throw new ServiceException("无读取权限, 请在对应的OSS开启'公有读'权限!");
|
||||||
|
} else {
|
||||||
|
throw new ServiceException(e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
response.setContentLength(Convert.toInt(data));
|
response.setContentLength(Convert.toInt(data));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 删除OSS云存储
|
* 删除OSS对象存储
|
||||||
*/
|
*/
|
||||||
@ApiOperation("删除OSS云存储")
|
@ApiOperation("删除OSS对象存储")
|
||||||
@PreAuthorize("@ss.hasPermi('system:oss:remove')")
|
@PreAuthorize("@ss.hasPermi('system:oss:remove')")
|
||||||
@Log(title = "OSS云存储" , businessType = BusinessType.DELETE)
|
@Log(title = "OSS对象存储" , businessType = BusinessType.DELETE)
|
||||||
@DeleteMapping("/{ossIds}")
|
@DeleteMapping("/{ossIds}")
|
||||||
public AjaxResult<Void> remove(@NotEmpty(message = "主键不能为空")
|
public AjaxResult<Void> remove(@NotEmpty(message = "主键不能为空")
|
||||||
@PathVariable Long[] ossIds) {
|
@PathVariable Long[] ossIds) {
|
||||||
@ -124,7 +134,7 @@ public class SysOssController extends BaseController {
|
|||||||
*/
|
*/
|
||||||
@ApiOperation("变更图片列表预览状态")
|
@ApiOperation("变更图片列表预览状态")
|
||||||
@PreAuthorize("@ss.hasPermi('system:oss:edit')")
|
@PreAuthorize("@ss.hasPermi('system:oss:edit')")
|
||||||
@Log(title = "OSS云存储" , businessType = BusinessType.UPDATE)
|
@Log(title = "OSS对象存储" , businessType = BusinessType.UPDATE)
|
||||||
@PutMapping("/changePreviewListResource")
|
@PutMapping("/changePreviewListResource")
|
||||||
public AjaxResult<Void> changePreviewListResource(@RequestBody String body) {
|
public AjaxResult<Void> changePreviewListResource(@RequestBody String body) {
|
||||||
Map<String, Boolean> map = JsonUtils.parseMap(body);
|
Map<String, Boolean> map = JsonUtils.parseMap(body);
|
||||||
|
@ -7,9 +7,9 @@ import com.ruoyi.common.core.domain.AjaxResult;
|
|||||||
import com.ruoyi.common.core.domain.entity.SysUser;
|
import com.ruoyi.common.core.domain.entity.SysUser;
|
||||||
import com.ruoyi.common.core.domain.model.LoginUser;
|
import com.ruoyi.common.core.domain.model.LoginUser;
|
||||||
import com.ruoyi.common.enums.BusinessType;
|
import com.ruoyi.common.enums.BusinessType;
|
||||||
|
import com.ruoyi.common.core.service.TokenService;
|
||||||
import com.ruoyi.common.utils.SecurityUtils;
|
import com.ruoyi.common.utils.SecurityUtils;
|
||||||
import com.ruoyi.common.utils.StringUtils;
|
import com.ruoyi.common.utils.StringUtils;
|
||||||
import com.ruoyi.framework.web.service.TokenService;
|
|
||||||
import com.ruoyi.system.domain.SysOss;
|
import com.ruoyi.system.domain.SysOss;
|
||||||
import com.ruoyi.system.service.ISysOssService;
|
import com.ruoyi.system.service.ISysOssService;
|
||||||
import com.ruoyi.system.service.ISysUserService;
|
import com.ruoyi.system.service.ISysUserService;
|
||||||
|
@ -4,7 +4,7 @@ import com.ruoyi.common.core.controller.BaseController;
|
|||||||
import com.ruoyi.common.core.domain.AjaxResult;
|
import com.ruoyi.common.core.domain.AjaxResult;
|
||||||
import com.ruoyi.common.core.domain.model.RegisterBody;
|
import com.ruoyi.common.core.domain.model.RegisterBody;
|
||||||
import com.ruoyi.common.utils.StringUtils;
|
import com.ruoyi.common.utils.StringUtils;
|
||||||
import com.ruoyi.framework.web.service.SysRegisterService;
|
import com.ruoyi.system.service.SysRegisterService;
|
||||||
import com.ruoyi.system.service.ISysConfigService;
|
import com.ruoyi.system.service.ISysConfigService;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.web.bind.annotation.PostMapping;
|
import org.springframework.web.bind.annotation.PostMapping;
|
||||||
|
@ -9,13 +9,13 @@ import com.ruoyi.common.core.domain.entity.SysUser;
|
|||||||
import com.ruoyi.common.core.domain.model.LoginUser;
|
import com.ruoyi.common.core.domain.model.LoginUser;
|
||||||
import com.ruoyi.common.core.page.TableDataInfo;
|
import com.ruoyi.common.core.page.TableDataInfo;
|
||||||
import com.ruoyi.common.enums.BusinessType;
|
import com.ruoyi.common.enums.BusinessType;
|
||||||
|
import com.ruoyi.common.core.service.TokenService;
|
||||||
import com.ruoyi.common.utils.StringUtils;
|
import com.ruoyi.common.utils.StringUtils;
|
||||||
import com.ruoyi.common.utils.poi.ExcelUtil;
|
import com.ruoyi.common.utils.poi.ExcelUtil;
|
||||||
import com.ruoyi.framework.web.service.SysPermissionService;
|
|
||||||
import com.ruoyi.framework.web.service.TokenService;
|
|
||||||
import com.ruoyi.system.domain.SysUserRole;
|
import com.ruoyi.system.domain.SysUserRole;
|
||||||
import com.ruoyi.system.service.ISysRoleService;
|
import com.ruoyi.system.service.ISysRoleService;
|
||||||
import com.ruoyi.system.service.ISysUserService;
|
import com.ruoyi.system.service.ISysUserService;
|
||||||
|
import com.ruoyi.system.service.SysPermissionService;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.security.access.prepost.PreAuthorize;
|
import org.springframework.security.access.prepost.PreAuthorize;
|
||||||
import org.springframework.validation.annotation.Validated;
|
import org.springframework.validation.annotation.Validated;
|
||||||
|
@ -70,7 +70,7 @@ spring:
|
|||||||
config:
|
config:
|
||||||
multi-statement-allow: true
|
multi-statement-allow: true
|
||||||
|
|
||||||
--- # redis 配置
|
--- # redis 单机配置(单机与集群只能开启一个另一个需要注释掉)
|
||||||
spring:
|
spring:
|
||||||
redis:
|
redis:
|
||||||
# 地址
|
# 地址
|
||||||
@ -118,6 +118,67 @@ redisson:
|
|||||||
# DNS监测时间间隔,单位:毫秒
|
# DNS监测时间间隔,单位:毫秒
|
||||||
dnsMonitoringInterval: 5000
|
dnsMonitoringInterval: 5000
|
||||||
|
|
||||||
|
#--- # redis 集群配置(单机与集群只能开启一个另一个需要注释掉)
|
||||||
|
#spring:
|
||||||
|
# redis:
|
||||||
|
# cluster:
|
||||||
|
# nodes:
|
||||||
|
# - 192.168.0.100:6379
|
||||||
|
# - 192.168.0.101:6379
|
||||||
|
# - 192.168.0.102:6379
|
||||||
|
# # 密码
|
||||||
|
# password:
|
||||||
|
# # 连接超时时间
|
||||||
|
# timeout: 10s
|
||||||
|
# # 是否开启ssl
|
||||||
|
# ssl: false
|
||||||
|
#
|
||||||
|
#redisson:
|
||||||
|
# # 线程池数量
|
||||||
|
# threads: 16
|
||||||
|
# # Netty线程池数量
|
||||||
|
# nettyThreads: 32
|
||||||
|
# # 传输模式
|
||||||
|
# transportMode: "NIO"
|
||||||
|
# # 集群配置
|
||||||
|
# clusterServersConfig:
|
||||||
|
# # 客户端名称
|
||||||
|
# clientName: ${ruoyi.name}
|
||||||
|
# # master最小空闲连接数
|
||||||
|
# masterConnectionMinimumIdleSize: 32
|
||||||
|
# # master连接池大小
|
||||||
|
# masterConnectionPoolSize: 64
|
||||||
|
# # slave最小空闲连接数
|
||||||
|
# slaveConnectionMinimumIdleSize: 32
|
||||||
|
# # slave连接池大小
|
||||||
|
# slaveConnectionPoolSize: 64
|
||||||
|
# # 连接空闲超时,单位:毫秒
|
||||||
|
# idleConnectionTimeout: 10000
|
||||||
|
# # ping连接间隔
|
||||||
|
# pingConnectionInterval: 1000
|
||||||
|
# # 命令等待超时,单位:毫秒
|
||||||
|
# timeout: 3000
|
||||||
|
# # 如果尝试在此限制之内发送成功,则开始启用 timeout 计时。
|
||||||
|
# retryAttempts: 3
|
||||||
|
# # 命令重试发送时间间隔,单位:毫秒
|
||||||
|
# retryInterval: 1500
|
||||||
|
# # 从可用服务器的内部列表中排除 Redis Slave 重新连接尝试的间隔。
|
||||||
|
# failedSlaveReconnectionInterval: 3000
|
||||||
|
# # 发布和订阅连接池最小空闲连接数
|
||||||
|
# subscriptionConnectionMinimumIdleSize: 1
|
||||||
|
# # 发布和订阅连接池大小
|
||||||
|
# subscriptionConnectionPoolSize: 50
|
||||||
|
# # 单个连接最大订阅数量
|
||||||
|
# subscriptionsPerConnection: 5
|
||||||
|
# # 扫描间隔
|
||||||
|
# scanInterval: 1000
|
||||||
|
# # DNS监测时间间隔,单位:毫秒
|
||||||
|
# dnsMonitoringInterval: 5000
|
||||||
|
# # 读取模式
|
||||||
|
# readMode: "SLAVE"
|
||||||
|
# # 订阅模式
|
||||||
|
# subscriptionMode: "MASTER"
|
||||||
|
|
||||||
--- # 监控配置
|
--- # 监控配置
|
||||||
spring:
|
spring:
|
||||||
boot:
|
boot:
|
||||||
|
@ -70,7 +70,7 @@ spring:
|
|||||||
config:
|
config:
|
||||||
multi-statement-allow: true
|
multi-statement-allow: true
|
||||||
|
|
||||||
--- # redis 配置
|
--- # redis 单机配置(单机与集群只能开启一个另一个需要注释掉)
|
||||||
spring:
|
spring:
|
||||||
redis:
|
redis:
|
||||||
# 地址
|
# 地址
|
||||||
@ -118,6 +118,67 @@ redisson:
|
|||||||
# DNS监测时间间隔,单位:毫秒
|
# DNS监测时间间隔,单位:毫秒
|
||||||
dnsMonitoringInterval: 5000
|
dnsMonitoringInterval: 5000
|
||||||
|
|
||||||
|
#--- # redis 集群配置(单机与集群只能开启一个另一个需要注释掉)
|
||||||
|
#spring:
|
||||||
|
# redis:
|
||||||
|
# cluster:
|
||||||
|
# nodes:
|
||||||
|
# - 192.168.0.100:6379
|
||||||
|
# - 192.168.0.101:6379
|
||||||
|
# - 192.168.0.102:6379
|
||||||
|
# # 密码
|
||||||
|
# password:
|
||||||
|
# # 连接超时时间
|
||||||
|
# timeout: 10s
|
||||||
|
# # 是否开启ssl
|
||||||
|
# ssl: false
|
||||||
|
#
|
||||||
|
#redisson:
|
||||||
|
# # 线程池数量
|
||||||
|
# threads: 16
|
||||||
|
# # Netty线程池数量
|
||||||
|
# nettyThreads: 32
|
||||||
|
# # 传输模式
|
||||||
|
# transportMode: "NIO"
|
||||||
|
# # 集群配置
|
||||||
|
# clusterServersConfig:
|
||||||
|
# # 客户端名称
|
||||||
|
# clientName: ${ruoyi.name}
|
||||||
|
# # master最小空闲连接数
|
||||||
|
# masterConnectionMinimumIdleSize: 32
|
||||||
|
# # master连接池大小
|
||||||
|
# masterConnectionPoolSize: 64
|
||||||
|
# # slave最小空闲连接数
|
||||||
|
# slaveConnectionMinimumIdleSize: 32
|
||||||
|
# # slave连接池大小
|
||||||
|
# slaveConnectionPoolSize: 64
|
||||||
|
# # 连接空闲超时,单位:毫秒
|
||||||
|
# idleConnectionTimeout: 10000
|
||||||
|
# # ping连接间隔
|
||||||
|
# pingConnectionInterval: 1000
|
||||||
|
# # 命令等待超时,单位:毫秒
|
||||||
|
# timeout: 3000
|
||||||
|
# # 如果尝试在此限制之内发送成功,则开始启用 timeout 计时。
|
||||||
|
# retryAttempts: 3
|
||||||
|
# # 命令重试发送时间间隔,单位:毫秒
|
||||||
|
# retryInterval: 1500
|
||||||
|
# # 从可用服务器的内部列表中排除 Redis Slave 重新连接尝试的间隔。
|
||||||
|
# failedSlaveReconnectionInterval: 3000
|
||||||
|
# # 发布和订阅连接池最小空闲连接数
|
||||||
|
# subscriptionConnectionMinimumIdleSize: 1
|
||||||
|
# # 发布和订阅连接池大小
|
||||||
|
# subscriptionConnectionPoolSize: 50
|
||||||
|
# # 单个连接最大订阅数量
|
||||||
|
# subscriptionsPerConnection: 5
|
||||||
|
# # 扫描间隔
|
||||||
|
# scanInterval: 1000
|
||||||
|
# # DNS监测时间间隔,单位:毫秒
|
||||||
|
# dnsMonitoringInterval: 5000
|
||||||
|
# # 读取模式
|
||||||
|
# readMode: "SLAVE"
|
||||||
|
# # 订阅模式
|
||||||
|
# subscriptionMode: "MASTER"
|
||||||
|
|
||||||
--- # 监控配置
|
--- # 监控配置
|
||||||
spring:
|
spring:
|
||||||
boot:
|
boot:
|
||||||
|
@ -106,10 +106,32 @@ token:
|
|||||||
# 令牌有效期(默认30分钟)
|
# 令牌有效期(默认30分钟)
|
||||||
expireTime: 30
|
expireTime: 30
|
||||||
|
|
||||||
|
# security配置
|
||||||
|
security:
|
||||||
|
# 登出路径
|
||||||
|
logout-url: /logout
|
||||||
|
# 匿名路径
|
||||||
|
anonymous:
|
||||||
|
- /login
|
||||||
|
- /register
|
||||||
|
- /captchaImage
|
||||||
|
# swagger 文档配置
|
||||||
|
- /doc.html
|
||||||
|
- /swagger-resources/**
|
||||||
|
- /webjars/**
|
||||||
|
- /*/api-docs
|
||||||
|
# druid 监控配置
|
||||||
|
- /druid/**
|
||||||
|
# actuator 监控配置
|
||||||
|
- /actuator
|
||||||
|
- /actuator/**
|
||||||
|
# 用户放行
|
||||||
|
permit-all:
|
||||||
|
|
||||||
# 重复提交
|
# 重复提交
|
||||||
repeat-submit:
|
repeat-submit:
|
||||||
# 全局间隔时间(毫秒)
|
# 全局间隔时间(毫秒)
|
||||||
intervalTime: 1000
|
interval: 5000
|
||||||
|
|
||||||
# MyBatisPlus配置
|
# MyBatisPlus配置
|
||||||
# https://baomidou.com/config/
|
# https://baomidou.com/config/
|
||||||
@ -221,6 +243,11 @@ swagger:
|
|||||||
name: Lion Li
|
name: Lion Li
|
||||||
email: crazylionli@163.com
|
email: crazylionli@163.com
|
||||||
url: https://gitee.com/JavaLionLi/RuoYi-Vue-Plus
|
url: https://gitee.com/JavaLionLi/RuoYi-Vue-Plus
|
||||||
|
groups:
|
||||||
|
- name: 演示案例
|
||||||
|
basePackage: com.ruoyi.demo
|
||||||
|
- name: 系统模块
|
||||||
|
basePackage: com.ruoyi.admin
|
||||||
|
|
||||||
# 防止XSS攻击
|
# 防止XSS攻击
|
||||||
xss:
|
xss:
|
||||||
@ -244,7 +271,7 @@ thread-pool:
|
|||||||
# 线程池维护线程所允许的空闲时间
|
# 线程池维护线程所允许的空闲时间
|
||||||
keepAliveSeconds: 300
|
keepAliveSeconds: 300
|
||||||
# 线程池对拒绝任务(无线程可用)的处理策略
|
# 线程池对拒绝任务(无线程可用)的处理策略
|
||||||
# CALLER_RUNS_POLICY 等待
|
# CALLER_RUNS_POLICY 调用方执行
|
||||||
# DISCARD_OLDEST_POLICY 放弃最旧的
|
# DISCARD_OLDEST_POLICY 放弃最旧的
|
||||||
# DISCARD_POLICY 丢弃
|
# DISCARD_POLICY 丢弃
|
||||||
# ABORT_POLICY 中止
|
# ABORT_POLICY 中止
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<artifactId>ruoyi-vue-plus</artifactId>
|
<artifactId>ruoyi-vue-plus</artifactId>
|
||||||
<groupId>com.ruoyi</groupId>
|
<groupId>com.ruoyi</groupId>
|
||||||
<version>3.1.0</version>
|
<version>3.2.0</version>
|
||||||
</parent>
|
</parent>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
@ -131,6 +131,11 @@
|
|||||||
<artifactId>knife4j-spring-boot-starter</artifactId>
|
<artifactId>knife4j-spring-boot-starter</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>io.swagger</groupId>
|
||||||
|
<artifactId>swagger-annotations</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.springframework.boot</groupId>
|
<groupId>org.springframework.boot</groupId>
|
||||||
<artifactId>spring-boot-starter-actuator</artifactId>
|
<artifactId>spring-boot-starter-actuator</artifactId>
|
||||||
@ -147,22 +152,10 @@
|
|||||||
<artifactId>redisson-spring-boot-starter</artifactId>
|
<artifactId>redisson-spring-boot-starter</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<!-- dynamic-datasource 多数据源-->
|
|
||||||
<dependency>
|
|
||||||
<groupId>com.baomidou</groupId>
|
|
||||||
<artifactId>dynamic-datasource-spring-boot-starter</artifactId>
|
|
||||||
</dependency>
|
|
||||||
<!-- sql性能分析插件 -->
|
|
||||||
<dependency>
|
|
||||||
<groupId>p6spy</groupId>
|
|
||||||
<artifactId>p6spy</artifactId>
|
|
||||||
</dependency>
|
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.baomidou</groupId>
|
<groupId>com.baomidou</groupId>
|
||||||
<artifactId>lock4j-redisson-spring-boot-starter</artifactId>
|
<artifactId>lock4j-redisson-spring-boot-starter</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
</project>
|
</project>
|
||||||
|
@ -38,4 +38,9 @@ public @interface Log
|
|||||||
* 是否保存请求的参数
|
* 是否保存请求的参数
|
||||||
*/
|
*/
|
||||||
public boolean isSaveRequestData() default true;
|
public boolean isSaveRequestData() default true;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 是否保存响应的参数
|
||||||
|
*/
|
||||||
|
public boolean isSaveResponseData() default true;
|
||||||
}
|
}
|
||||||
|
@ -20,10 +20,15 @@ import java.util.concurrent.TimeUnit;
|
|||||||
public @interface RepeatSubmit {
|
public @interface RepeatSubmit {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 默认使用全局配置
|
* 间隔时间(ms),小于此时间视为重复提交
|
||||||
*/
|
*/
|
||||||
int intervalTime() default 0;
|
int interval() default 5000;
|
||||||
|
|
||||||
TimeUnit timeUnit() default TimeUnit.MILLISECONDS;
|
TimeUnit timeUnit() default TimeUnit.MILLISECONDS;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 提示消息
|
||||||
|
*/
|
||||||
|
String message() default "不允许重复提交,请稍后再试";
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -44,16 +44,21 @@ public class GenConstants
|
|||||||
public static final String[] COLUMNTYPE_NUMBER = { "tinyint", "smallint", "mediumint", "int", "number", "integer",
|
public static final String[] COLUMNTYPE_NUMBER = { "tinyint", "smallint", "mediumint", "int", "number", "integer",
|
||||||
"bit", "bigint", "float", "double", "decimal" };
|
"bit", "bigint", "float", "double", "decimal" };
|
||||||
|
|
||||||
|
/** 页面不需要添加字段 */
|
||||||
|
public static final String[] COLUMNNAME_NOT_ADD = { "create_by", "create_time", "del_flag", "update_by",
|
||||||
|
"update_time", "version" };
|
||||||
|
|
||||||
/** 页面不需要编辑字段 */
|
/** 页面不需要编辑字段 */
|
||||||
public static final String[] COLUMNNAME_NOT_EDIT = { "id", "create_by", "create_time", "del_flag" };
|
public static final String[] COLUMNNAME_NOT_EDIT = { "create_by", "create_time", "del_flag", "update_by",
|
||||||
|
"update_time", "version" };
|
||||||
|
|
||||||
/** 页面不需要显示的列表字段 */
|
/** 页面不需要显示的列表字段 */
|
||||||
public static final String[] COLUMNNAME_NOT_LIST = { "id", "create_by", "create_time", "del_flag", "update_by",
|
public static final String[] COLUMNNAME_NOT_LIST = { "id", "create_by", "create_time", "del_flag", "update_by",
|
||||||
"update_time" };
|
"update_time", "version" };
|
||||||
|
|
||||||
/** 页面不需要查询字段 */
|
/** 页面不需要查询字段 */
|
||||||
public static final String[] COLUMNNAME_NOT_QUERY = { "id", "create_by", "create_time", "del_flag", "update_by",
|
public static final String[] COLUMNNAME_NOT_QUERY = { "id", "create_by", "create_time", "del_flag", "update_by",
|
||||||
"update_time", "remark" };
|
"update_time", "remark", "version" };
|
||||||
|
|
||||||
/** Entity基类字段 */
|
/** Entity基类字段 */
|
||||||
public static final String[] BASE_ENTITY = { "createBy", "createTime", "updateBy", "updateTime", "remark" };
|
public static final String[] BASE_ENTITY = { "createBy", "createTime", "updateBy", "updateTime", "remark" };
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
package com.ruoyi.common.core.domain;
|
package com.ruoyi.common.core.domain;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||||
import io.swagger.annotations.ApiModelProperty;
|
import io.swagger.annotations.ApiModelProperty;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import lombok.NoArgsConstructor;
|
import lombok.NoArgsConstructor;
|
||||||
@ -62,6 +63,7 @@ public class BaseEntity implements Serializable {
|
|||||||
/**
|
/**
|
||||||
* 请求参数
|
* 请求参数
|
||||||
*/
|
*/
|
||||||
|
@JsonIgnore
|
||||||
@ApiModelProperty(value = "请求参数")
|
@ApiModelProperty(value = "请求参数")
|
||||||
private Map<String, Object> params = new HashMap<>();
|
private Map<String, Object> params = new HashMap<>();
|
||||||
|
|
||||||
|
@ -0,0 +1,107 @@
|
|||||||
|
package com.ruoyi.common.core.domain.dto;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
import lombok.experimental.Accessors;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 操作日志记录表 oper_log
|
||||||
|
*
|
||||||
|
* @author ruoyi
|
||||||
|
*/
|
||||||
|
|
||||||
|
@Data
|
||||||
|
@NoArgsConstructor
|
||||||
|
@Accessors(chain = true)
|
||||||
|
public class OperLogDTO implements Serializable {
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 日志主键
|
||||||
|
*/
|
||||||
|
private Long operId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 操作模块
|
||||||
|
*/
|
||||||
|
private String title;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 业务类型(0其它 1新增 2修改 3删除)
|
||||||
|
*/
|
||||||
|
private Integer businessType;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 业务类型数组
|
||||||
|
*/
|
||||||
|
private Integer[] businessTypes;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 请求方法
|
||||||
|
*/
|
||||||
|
private String method;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 请求方式
|
||||||
|
*/
|
||||||
|
private String requestMethod;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 操作类别(0其它 1后台用户 2手机端用户)
|
||||||
|
*/
|
||||||
|
private Integer operatorType;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 操作人员
|
||||||
|
*/
|
||||||
|
private String operName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 部门名称
|
||||||
|
*/
|
||||||
|
private String deptName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 请求url
|
||||||
|
*/
|
||||||
|
private String operUrl;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 操作地址
|
||||||
|
*/
|
||||||
|
private String operIp;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 操作地点
|
||||||
|
*/
|
||||||
|
private String operLocation;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 请求参数
|
||||||
|
*/
|
||||||
|
private String operParam;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 返回参数
|
||||||
|
*/
|
||||||
|
private String jsonResult;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 操作状态(0正常 1异常)
|
||||||
|
*/
|
||||||
|
private Integer status;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 错误消息
|
||||||
|
*/
|
||||||
|
private String errorMsg;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 操作时间
|
||||||
|
*/
|
||||||
|
private Date operTime;
|
||||||
|
|
||||||
|
}
|
@ -90,7 +90,7 @@ public class SysDictData implements Serializable {
|
|||||||
* 状态(0正常 1停用)
|
* 状态(0正常 1停用)
|
||||||
*/
|
*/
|
||||||
@ExcelProperty(value = "状态", converter = ExcelDictConvert.class)
|
@ExcelProperty(value = "状态", converter = ExcelDictConvert.class)
|
||||||
@ExcelDictFormat(dictType = "sys_common_status")
|
@ExcelDictFormat(dictType = "sys_normal_disable")
|
||||||
private String status;
|
private String status;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -57,7 +57,7 @@ public class SysDictType implements Serializable {
|
|||||||
* 状态(0正常 1停用)
|
* 状态(0正常 1停用)
|
||||||
*/
|
*/
|
||||||
@ExcelProperty(value = "状态", converter = ExcelDictConvert.class)
|
@ExcelProperty(value = "状态", converter = ExcelDictConvert.class)
|
||||||
@ExcelDictFormat(dictType = "sys_common_status")
|
@ExcelDictFormat(dictType = "sys_normal_disable")
|
||||||
private String status;
|
private String status;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -66,6 +66,11 @@ public class SysMenu implements Serializable {
|
|||||||
@Size(min = 0, max = 200, message = "组件路径不能超过255个字符")
|
@Size(min = 0, max = 200, message = "组件路径不能超过255个字符")
|
||||||
private String component;
|
private String component;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 路由参数
|
||||||
|
*/
|
||||||
|
private String query;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 是否为外链(0是 1否)
|
* 是否为外链(0是 1否)
|
||||||
*/
|
*/
|
||||||
|
@ -91,11 +91,6 @@ public class SysUser implements Serializable {
|
|||||||
return password;
|
return password;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 盐加密
|
|
||||||
*/
|
|
||||||
private String salt;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 帐号状态(0正常 1停用)
|
* 帐号状态(0正常 1停用)
|
||||||
*/
|
*/
|
||||||
|
@ -1,260 +0,0 @@
|
|||||||
package com.ruoyi.common.core.redis;
|
|
||||||
|
|
||||||
import com.google.common.collect.Lists;
|
|
||||||
import org.redisson.api.*;
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
|
||||||
import org.springframework.stereotype.Component;
|
|
||||||
|
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Set;
|
|
||||||
import java.util.concurrent.TimeUnit;
|
|
||||||
import java.util.function.Consumer;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* spring redis 工具类
|
|
||||||
*
|
|
||||||
* @author shenxinquan
|
|
||||||
* @see com.ruoyi.common.utils.RedisUtils
|
|
||||||
* @deprecated 3.2.0 删除此类
|
|
||||||
**/
|
|
||||||
@SuppressWarnings(value = {"unchecked", "rawtypes"})
|
|
||||||
@Component
|
|
||||||
@Deprecated
|
|
||||||
public class RedisCache {
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private RedissonClient redissonClient;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 发布通道消息
|
|
||||||
*
|
|
||||||
* @param channelKey 通道key
|
|
||||||
* @param msg 发送数据
|
|
||||||
* @param consumer 自定义处理
|
|
||||||
*/
|
|
||||||
public <T> void publish(String channelKey, T msg, Consumer<T> consumer) {
|
|
||||||
RTopic topic = redissonClient.getTopic(channelKey);
|
|
||||||
topic.publish(msg);
|
|
||||||
consumer.accept(msg);
|
|
||||||
}
|
|
||||||
|
|
||||||
public <T> void publish(String channelKey, T msg) {
|
|
||||||
RTopic topic = redissonClient.getTopic(channelKey);
|
|
||||||
topic.publish(msg);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 订阅通道接收消息
|
|
||||||
*
|
|
||||||
* @param channelKey 通道key
|
|
||||||
* @param clazz 消息类型
|
|
||||||
* @param consumer 自定义处理
|
|
||||||
*/
|
|
||||||
public <T> void subscribe(String channelKey, Class<T> clazz, Consumer<T> consumer) {
|
|
||||||
RTopic topic = redissonClient.getTopic(channelKey);
|
|
||||||
topic.addListener(clazz, (channel, msg) -> consumer.accept(msg));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 缓存基本的对象,Integer、String、实体类等
|
|
||||||
*
|
|
||||||
* @param key 缓存的键值
|
|
||||||
* @param value 缓存的值
|
|
||||||
*/
|
|
||||||
public <T> void setCacheObject(final String key, final T value) {
|
|
||||||
redissonClient.getBucket(key).set(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 缓存基本的对象,Integer、String、实体类等
|
|
||||||
*
|
|
||||||
* @param key 缓存的键值
|
|
||||||
* @param value 缓存的值
|
|
||||||
* @param timeout 时间
|
|
||||||
* @param timeUnit 时间颗粒度
|
|
||||||
*/
|
|
||||||
public <T> void setCacheObject(final String key, final T value, final Integer timeout, final TimeUnit timeUnit) {
|
|
||||||
RBucket<T> result = redissonClient.getBucket(key);
|
|
||||||
result.set(value);
|
|
||||||
result.expire(timeout, timeUnit);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 设置有效时间
|
|
||||||
*
|
|
||||||
* @param key Redis键
|
|
||||||
* @param timeout 超时时间
|
|
||||||
* @return true=设置成功;false=设置失败
|
|
||||||
*/
|
|
||||||
public boolean expire(final String key, final long timeout) {
|
|
||||||
return expire(key, timeout, TimeUnit.SECONDS);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 设置有效时间
|
|
||||||
*
|
|
||||||
* @param key Redis键
|
|
||||||
* @param timeout 超时时间
|
|
||||||
* @param unit 时间单位
|
|
||||||
* @return true=设置成功;false=设置失败
|
|
||||||
*/
|
|
||||||
public boolean expire(final String key, final long timeout, final TimeUnit unit) {
|
|
||||||
RBucket rBucket = redissonClient.getBucket(key);
|
|
||||||
return rBucket.expire(timeout, unit);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获得缓存的基本对象。
|
|
||||||
*
|
|
||||||
* @param key 缓存键值
|
|
||||||
* @return 缓存键值对应的数据
|
|
||||||
*/
|
|
||||||
public <T> T getCacheObject(final String key) {
|
|
||||||
RBucket<T> rBucket = redissonClient.getBucket(key);
|
|
||||||
return rBucket.get();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 删除单个对象
|
|
||||||
*
|
|
||||||
* @param key
|
|
||||||
*/
|
|
||||||
public boolean deleteObject(final String key) {
|
|
||||||
return redissonClient.getBucket(key).delete();
|
|
||||||
}
|
|
||||||
|
|
||||||
/* */
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 删除集合对象
|
|
||||||
*
|
|
||||||
* @param collection 多个对象
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
public void deleteObject(final Collection collection) {
|
|
||||||
RBatch batch = redissonClient.createBatch();
|
|
||||||
collection.forEach(t->{
|
|
||||||
batch.getBucket(t.toString()).deleteAsync();
|
|
||||||
});
|
|
||||||
batch.execute();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 缓存List数据
|
|
||||||
*
|
|
||||||
* @param key 缓存的键值
|
|
||||||
* @param dataList 待缓存的List数据
|
|
||||||
* @return 缓存的对象
|
|
||||||
*/
|
|
||||||
public <T> boolean setCacheList(final String key, final List<T> dataList) {
|
|
||||||
RList<T> rList = redissonClient.getList(key);
|
|
||||||
return rList.addAll(dataList);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获得缓存的list对象
|
|
||||||
*
|
|
||||||
* @param key 缓存的键值
|
|
||||||
* @return 缓存键值对应的数据
|
|
||||||
*/
|
|
||||||
public <T> List<T> getCacheList(final String key) {
|
|
||||||
RList<T> rList = redissonClient.getList(key);
|
|
||||||
return rList.readAll();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 缓存Set
|
|
||||||
*
|
|
||||||
* @param key 缓存键值
|
|
||||||
* @param dataSet 缓存的数据
|
|
||||||
* @return 缓存数据的对象
|
|
||||||
*/
|
|
||||||
public <T> boolean setCacheSet(final String key, final Set<T> dataSet) {
|
|
||||||
RSet<T> rSet = redissonClient.getSet(key);
|
|
||||||
return rSet.addAll(dataSet);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获得缓存的set
|
|
||||||
*
|
|
||||||
* @param key
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
public <T> Set<T> getCacheSet(final String key) {
|
|
||||||
RSet<T> rSet = redissonClient.getSet(key);
|
|
||||||
return rSet.readAll();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 缓存Map
|
|
||||||
*
|
|
||||||
* @param key
|
|
||||||
* @param dataMap
|
|
||||||
*/
|
|
||||||
public <T> void setCacheMap(final String key, final Map<String, T> dataMap) {
|
|
||||||
if (dataMap != null) {
|
|
||||||
RMap<String, T> rMap = redissonClient.getMap(key);
|
|
||||||
rMap.putAll(dataMap);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获得缓存的Map
|
|
||||||
*
|
|
||||||
* @param key
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
public <T> Map<String, T> getCacheMap(final String key) {
|
|
||||||
RMap<String, T> rMap = redissonClient.getMap(key);
|
|
||||||
return rMap.getAll(rMap.keySet());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 往Hash中存入数据
|
|
||||||
*
|
|
||||||
* @param key Redis键
|
|
||||||
* @param hKey Hash键
|
|
||||||
* @param value 值
|
|
||||||
*/
|
|
||||||
public <T> void setCacheMapValue(final String key, final String hKey, final T value) {
|
|
||||||
RMap<String, T> rMap = redissonClient.getMap(key);
|
|
||||||
rMap.put(hKey, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取Hash中的数据
|
|
||||||
*
|
|
||||||
* @param key Redis键
|
|
||||||
* @param hKey Hash键
|
|
||||||
* @return Hash中的对象
|
|
||||||
*/
|
|
||||||
public <T> T getCacheMapValue(final String key, final String hKey) {
|
|
||||||
RMap<String, T> rMap = redissonClient.getMap(key);
|
|
||||||
return rMap.get(hKey);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取多个Hash中的数据
|
|
||||||
*
|
|
||||||
* @param key Redis键
|
|
||||||
* @param hKeys Hash键集合
|
|
||||||
* @return Hash对象集合
|
|
||||||
*/
|
|
||||||
public <K,V> Map<K,V> getMultiCacheMapValue(final String key, final Set<K> hKeys) {
|
|
||||||
RMap<K,V> rMap = redissonClient.getMap(key);
|
|
||||||
return rMap.getAll(hKeys);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获得缓存的基本对象列表
|
|
||||||
*
|
|
||||||
* @param pattern 字符串前缀
|
|
||||||
* @return 对象列表
|
|
||||||
*/
|
|
||||||
public Collection<String> keys(final String pattern) {
|
|
||||||
Iterable<String> iterable = redissonClient.getKeys().getKeysByPattern(pattern);
|
|
||||||
return Lists.newArrayList(iterable);
|
|
||||||
}
|
|
||||||
}
|
|
@ -0,0 +1,9 @@
|
|||||||
|
package com.ruoyi.common.core.service;
|
||||||
|
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
|
||||||
|
public interface LogininforService {
|
||||||
|
|
||||||
|
void recordLogininfor(String username, String status, String message,
|
||||||
|
HttpServletRequest request, Object... args);
|
||||||
|
}
|
@ -0,0 +1,9 @@
|
|||||||
|
package com.ruoyi.common.core.service;
|
||||||
|
|
||||||
|
import com.ruoyi.common.core.domain.dto.OperLogDTO;
|
||||||
|
import org.springframework.scheduling.annotation.Async;
|
||||||
|
|
||||||
|
public interface OperLogService {
|
||||||
|
@Async
|
||||||
|
void recordOper(OperLogDTO operLogDTO);
|
||||||
|
}
|
@ -0,0 +1,69 @@
|
|||||||
|
package com.ruoyi.common.core.service;
|
||||||
|
|
||||||
|
import com.ruoyi.common.core.domain.model.LoginUser;
|
||||||
|
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* token验证处理
|
||||||
|
*
|
||||||
|
* @author Lion Li
|
||||||
|
*/
|
||||||
|
public interface TokenService {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取用户身份信息
|
||||||
|
*
|
||||||
|
* @return 用户信息
|
||||||
|
*/
|
||||||
|
LoginUser getLoginUser(HttpServletRequest request);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置用户身份信息
|
||||||
|
*/
|
||||||
|
void setLoginUser(LoginUser loginUser);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除用户身份信息
|
||||||
|
*/
|
||||||
|
void delLoginUser(String token);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建令牌
|
||||||
|
*
|
||||||
|
* @param loginUser 用户信息
|
||||||
|
* @return 令牌
|
||||||
|
*/
|
||||||
|
String createToken(LoginUser loginUser);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 验证令牌有效期,相差不足20分钟,自动刷新缓存
|
||||||
|
*
|
||||||
|
* @param loginUser
|
||||||
|
* @return 令牌
|
||||||
|
*/
|
||||||
|
void verifyToken(LoginUser loginUser);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 刷新令牌有效期
|
||||||
|
*
|
||||||
|
* @param loginUser 登录信息
|
||||||
|
*/
|
||||||
|
void refreshToken(LoginUser loginUser);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置用户代理信息
|
||||||
|
*
|
||||||
|
* @param loginUser 登录信息
|
||||||
|
*/
|
||||||
|
void setUserAgent(LoginUser loginUser);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 从令牌中获取用户名
|
||||||
|
*
|
||||||
|
* @param token 令牌
|
||||||
|
* @return 用户名
|
||||||
|
*/
|
||||||
|
String getUsernameFromToken(String token);
|
||||||
|
|
||||||
|
}
|
@ -16,5 +16,10 @@ public enum LimitType
|
|||||||
/**
|
/**
|
||||||
* 根据请求者IP进行限流
|
* 根据请求者IP进行限流
|
||||||
*/
|
*/
|
||||||
IP
|
IP,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 实例限流(集群多后端实例)
|
||||||
|
*/
|
||||||
|
CLUSTER
|
||||||
}
|
}
|
||||||
|
@ -15,7 +15,7 @@ import java.util.concurrent.ThreadPoolExecutor;
|
|||||||
@AllArgsConstructor
|
@AllArgsConstructor
|
||||||
public enum ThreadPoolRejectedPolicy {
|
public enum ThreadPoolRejectedPolicy {
|
||||||
|
|
||||||
CALLER_RUNS_POLICY("等待", ThreadPoolExecutor.CallerRunsPolicy.class),
|
CALLER_RUNS_POLICY("调用方执行", ThreadPoolExecutor.CallerRunsPolicy.class),
|
||||||
DISCARD_OLDEST_POLICY("放弃最旧的", ThreadPoolExecutor.DiscardOldestPolicy.class),
|
DISCARD_OLDEST_POLICY("放弃最旧的", ThreadPoolExecutor.DiscardOldestPolicy.class),
|
||||||
DISCARD_POLICY("丢弃", ThreadPoolExecutor.DiscardPolicy.class),
|
DISCARD_POLICY("丢弃", ThreadPoolExecutor.DiscardPolicy.class),
|
||||||
ABORT_POLICY("中止", ThreadPoolExecutor.AbortPolicy.class);
|
ABORT_POLICY("中止", ThreadPoolExecutor.AbortPolicy.class);
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
package com.ruoyi.framework.config.properties;
|
package com.ruoyi.common.properties;
|
||||||
|
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
import org.springframework.boot.context.properties.ConfigurationProperties;
|
@ -25,6 +25,32 @@ public class RedisUtils {
|
|||||||
|
|
||||||
private static RedissonClient client = SpringUtils.getBean(RedissonClient.class);
|
private static RedissonClient client = SpringUtils.getBean(RedissonClient.class);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 限流
|
||||||
|
*
|
||||||
|
* @param key 限流key
|
||||||
|
* @param rateType 限流类型
|
||||||
|
* @param rate 速率
|
||||||
|
* @param rateInterval 速率间隔
|
||||||
|
* @return -1 表示失败
|
||||||
|
*/
|
||||||
|
public static long rateLimiter(String key, RateType rateType, int rate, int rateInterval) {
|
||||||
|
RRateLimiter rateLimiter = client.getRateLimiter(key);
|
||||||
|
rateLimiter.trySetRate(rateType, rate, rateInterval, RateIntervalUnit.SECONDS);
|
||||||
|
if (rateLimiter.tryAcquire()) {
|
||||||
|
return rateLimiter.availablePermits();
|
||||||
|
} else {
|
||||||
|
return -1L;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取实例id
|
||||||
|
*/
|
||||||
|
public static String getClientId() {
|
||||||
|
return client.getId();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 发布通道消息
|
* 发布通道消息
|
||||||
*
|
*
|
||||||
|
@ -35,6 +35,7 @@ public class FileUtils extends FileUtil
|
|||||||
.append(percentEncodedFileName);
|
.append(percentEncodedFileName);
|
||||||
|
|
||||||
response.setHeader("Content-disposition", contentDispositionValue.toString());
|
response.setHeader("Content-disposition", contentDispositionValue.toString());
|
||||||
|
response.setHeader("download-filename", percentEncodedFileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -27,6 +27,9 @@ public class AddressUtils {
|
|||||||
|
|
||||||
public static String getRealAddressByIP(String ip) {
|
public static String getRealAddressByIP(String ip) {
|
||||||
String address = UNKNOWN;
|
String address = UNKNOWN;
|
||||||
|
if (StringUtils.isBlank(ip)){
|
||||||
|
return address;
|
||||||
|
}
|
||||||
// 内网不查询
|
// 内网不查询
|
||||||
ip = "0:0:0:0:0:0:0:1".equals(ip) ? "127.0.0.1" : HtmlUtil.cleanHtmlTag(ip);
|
ip = "0:0:0:0:0:0:0:1".equals(ip) ? "127.0.0.1" : HtmlUtil.cleanHtmlTag(ip);
|
||||||
if (NetUtil.isInnerIP(ip)) {
|
if (NetUtil.isInnerIP(ip)) {
|
||||||
|
@ -46,7 +46,7 @@ public class ExcelUtil {
|
|||||||
response.reset();
|
response.reset();
|
||||||
response.addHeader("Access-Control-Allow-Origin", "*");
|
response.addHeader("Access-Control-Allow-Origin", "*");
|
||||||
response.addHeader("Access-Control-Expose-Headers", "Content-Disposition");
|
response.addHeader("Access-Control-Expose-Headers", "Content-Disposition");
|
||||||
FileUtils.setAttachmentResponseHeader(response, URLEncoder.encode(filename, StandardCharsets.UTF_8.toString()));
|
FileUtils.setAttachmentResponseHeader(response, filename);
|
||||||
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=UTF-8");
|
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=UTF-8");
|
||||||
ServletOutputStream os = response.getOutputStream();
|
ServletOutputStream os = response.getOutputStream();
|
||||||
EasyExcel.write(os, clazz)
|
EasyExcel.write(os, clazz)
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<artifactId>ruoyi-vue-plus</artifactId>
|
<artifactId>ruoyi-vue-plus</artifactId>
|
||||||
<groupId>com.ruoyi</groupId>
|
<groupId>com.ruoyi</groupId>
|
||||||
<version>3.1.0</version>
|
<version>3.2.0</version>
|
||||||
</parent>
|
</parent>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
@ -34,6 +34,9 @@ public class RedisCacheController {
|
|||||||
* 如果没有,就调用方法,然后把结果缓存起来
|
* 如果没有,就调用方法,然后把结果缓存起来
|
||||||
* 这个注解「一般用在查询方法上」
|
* 这个注解「一般用在查询方法上」
|
||||||
*
|
*
|
||||||
|
* 重点说明: 缓存注解严谨与其他筛选数据功能一起使用
|
||||||
|
* 例如: 数据权限注解 会造成 缓存击穿 与 数据不一致问题
|
||||||
|
*
|
||||||
* cacheNames 为配置文件内 groupId
|
* cacheNames 为配置文件内 groupId
|
||||||
*/
|
*/
|
||||||
@ApiOperation("测试 @Cacheable")
|
@ApiOperation("测试 @Cacheable")
|
||||||
|
@ -0,0 +1,58 @@
|
|||||||
|
package com.ruoyi.demo.controller;
|
||||||
|
|
||||||
|
import com.ruoyi.common.annotation.RateLimiter;
|
||||||
|
import com.ruoyi.common.core.domain.AjaxResult;
|
||||||
|
import com.ruoyi.common.enums.LimitType;
|
||||||
|
import io.swagger.annotations.Api;
|
||||||
|
import io.swagger.annotations.ApiOperation;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 测试分布式限流样例
|
||||||
|
*
|
||||||
|
* @author Lion Li
|
||||||
|
*/
|
||||||
|
@Api(value = "测试分布式限流样例", tags = {"测试分布式限流样例"})
|
||||||
|
@Slf4j
|
||||||
|
@RestController
|
||||||
|
@RequestMapping("/demo/rateLimiter")
|
||||||
|
public class RedisRateLimiterController {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 测试全局限流
|
||||||
|
* 全局影响
|
||||||
|
*/
|
||||||
|
@ApiOperation("测试全局限流")
|
||||||
|
@RateLimiter(count = 2, time = 10)
|
||||||
|
@GetMapping("/test")
|
||||||
|
public AjaxResult<String> test(String value){
|
||||||
|
return AjaxResult.success("操作成功",value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 测试请求IP限流
|
||||||
|
* 同一IP请求受影响
|
||||||
|
*/
|
||||||
|
@ApiOperation("测试请求IP限流")
|
||||||
|
@RateLimiter(count = 2, time = 10, limitType = LimitType.IP)
|
||||||
|
@GetMapping("/testip")
|
||||||
|
public AjaxResult<String> testip(String value){
|
||||||
|
return AjaxResult.success("操作成功",value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 测试集群实例限流
|
||||||
|
* 启动两个后端服务互不影响
|
||||||
|
*/
|
||||||
|
@ApiOperation("测试集群实例限流")
|
||||||
|
@RateLimiter(count = 2, time = 10, limitType = LimitType.CLUSTER)
|
||||||
|
@GetMapping("/testcluster")
|
||||||
|
public AjaxResult<String> testcluster(String value){
|
||||||
|
return AjaxResult.success("操作成功",value);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -96,7 +96,7 @@ public class TestDemoController extends BaseController {
|
|||||||
@ApiOperation("新增测试单表")
|
@ApiOperation("新增测试单表")
|
||||||
@PreAuthorize("@ss.hasPermi('demo:demo:add')")
|
@PreAuthorize("@ss.hasPermi('demo:demo:add')")
|
||||||
@Log(title = "测试单表", businessType = BusinessType.INSERT)
|
@Log(title = "测试单表", businessType = BusinessType.INSERT)
|
||||||
@RepeatSubmit(intervalTime = 2, timeUnit = TimeUnit.SECONDS)
|
@RepeatSubmit(interval = 2, timeUnit = TimeUnit.SECONDS, message = "不允许重复提交")
|
||||||
@PostMapping()
|
@PostMapping()
|
||||||
public AjaxResult<Void> add(@Validated(AddGroup.class) @RequestBody TestDemoBo bo) {
|
public AjaxResult<Void> add(@Validated(AddGroup.class) @RequestBody TestDemoBo bo) {
|
||||||
return toAjax(iTestDemoService.insertByBo(bo) ? 1 : 0);
|
return toAjax(iTestDemoService.insertByBo(bo) ? 1 : 0);
|
||||||
|
@ -75,7 +75,11 @@ public class TestDemoServiceImpl extends ServicePlusImpl<TestDemoMapper, TestDem
|
|||||||
public Boolean insertByBo(TestDemoBo bo) {
|
public Boolean insertByBo(TestDemoBo bo) {
|
||||||
TestDemo add = BeanUtil.toBean(bo, TestDemo.class);
|
TestDemo add = BeanUtil.toBean(bo, TestDemo.class);
|
||||||
validEntityBeforeSave(add);
|
validEntityBeforeSave(add);
|
||||||
return save(add);
|
boolean flag = save(add);
|
||||||
|
if (flag) {
|
||||||
|
bo.setId(add.getId());
|
||||||
|
}
|
||||||
|
return flag;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -54,7 +54,11 @@ public class TestTreeServiceImpl extends ServicePlusImpl<TestTreeMapper, TestTre
|
|||||||
public Boolean insertByBo(TestTreeBo bo) {
|
public Boolean insertByBo(TestTreeBo bo) {
|
||||||
TestTree add = BeanUtil.toBean(bo, TestTree.class);
|
TestTree add = BeanUtil.toBean(bo, TestTree.class);
|
||||||
validEntityBeforeSave(add);
|
validEntityBeforeSave(add);
|
||||||
return save(add);
|
boolean flag = save(add);
|
||||||
|
if (flag) {
|
||||||
|
bo.setId(add.getId());
|
||||||
|
}
|
||||||
|
return flag;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<artifactId>ruoyi-vue-plus</artifactId>
|
<artifactId>ruoyi-vue-plus</artifactId>
|
||||||
<groupId>com.ruoyi</groupId>
|
<groupId>com.ruoyi</groupId>
|
||||||
<version>3.1.0</version>
|
<version>3.2.0</version>
|
||||||
</parent>
|
</parent>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
<artifactId>ruoyi-extend</artifactId>
|
<artifactId>ruoyi-extend</artifactId>
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<artifactId>ruoyi-extend</artifactId>
|
<artifactId>ruoyi-extend</artifactId>
|
||||||
<groupId>com.ruoyi</groupId>
|
<groupId>com.ruoyi</groupId>
|
||||||
<version>3.1.0</version>
|
<version>3.2.0</version>
|
||||||
</parent>
|
</parent>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
<packaging>jar</packaging>
|
<packaging>jar</packaging>
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<artifactId>ruoyi-vue-plus</artifactId>
|
<artifactId>ruoyi-vue-plus</artifactId>
|
||||||
<groupId>com.ruoyi</groupId>
|
<groupId>com.ruoyi</groupId>
|
||||||
<version>3.1.0</version>
|
<version>3.2.0</version>
|
||||||
</parent>
|
</parent>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
@ -61,10 +61,21 @@
|
|||||||
<artifactId>druid-spring-boot-starter</artifactId>
|
<artifactId>druid-spring-boot-starter</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
<!-- dynamic-datasource 多数据源-->
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.baomidou</groupId>
|
||||||
|
<artifactId>dynamic-datasource-spring-boot-starter</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<!-- sql性能分析插件 -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>p6spy</groupId>
|
||||||
|
<artifactId>p6spy</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
<!-- 系统模块-->
|
<!-- 系统模块-->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.ruoyi</groupId>
|
<groupId>com.ruoyi</groupId>
|
||||||
<artifactId>ruoyi-system</artifactId>
|
<artifactId>ruoyi-common</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
@ -9,14 +9,10 @@ import com.ruoyi.common.utils.SecurityUtils;
|
|||||||
import com.ruoyi.common.utils.StringUtils;
|
import com.ruoyi.common.utils.StringUtils;
|
||||||
import com.ruoyi.common.utils.reflect.ReflectUtils;
|
import com.ruoyi.common.utils.reflect.ReflectUtils;
|
||||||
import org.aspectj.lang.JoinPoint;
|
import org.aspectj.lang.JoinPoint;
|
||||||
import org.aspectj.lang.Signature;
|
|
||||||
import org.aspectj.lang.annotation.Aspect;
|
import org.aspectj.lang.annotation.Aspect;
|
||||||
import org.aspectj.lang.annotation.Before;
|
import org.aspectj.lang.annotation.Before;
|
||||||
import org.aspectj.lang.annotation.Pointcut;
|
|
||||||
import org.aspectj.lang.reflect.MethodSignature;
|
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
import java.lang.reflect.Method;
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -58,23 +54,13 @@ public class DataScopeAspect {
|
|||||||
*/
|
*/
|
||||||
public static final String DATA_SCOPE = "dataScope";
|
public static final String DATA_SCOPE = "dataScope";
|
||||||
|
|
||||||
// 配置织入点
|
@Before("@annotation(controllerDataScope)")
|
||||||
@Pointcut("@annotation(com.ruoyi.common.annotation.DataScope)")
|
public void doBefore(JoinPoint point, DataScope controllerDataScope) throws Throwable {
|
||||||
public void dataScopePointCut() {
|
|
||||||
}
|
|
||||||
|
|
||||||
@Before("dataScopePointCut()")
|
|
||||||
public void doBefore(JoinPoint point) throws Throwable {
|
|
||||||
clearDataScope(point);
|
clearDataScope(point);
|
||||||
handleDataScope(point);
|
handleDataScope(point, controllerDataScope);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void handleDataScope(final JoinPoint joinPoint) {
|
protected void handleDataScope(final JoinPoint joinPoint, DataScope controllerDataScope) {
|
||||||
// 获得注解
|
|
||||||
DataScope controllerDataScope = getAnnotationLog(joinPoint);
|
|
||||||
if (controllerDataScope == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// 获取当前的用户
|
// 获取当前的用户
|
||||||
LoginUser loginUser = SecurityUtils.getLoginUser();
|
LoginUser loginUser = SecurityUtils.getLoginUser();
|
||||||
if (StringUtils.isNotNull(loginUser)) {
|
if (StringUtils.isNotNull(loginUser)) {
|
||||||
@ -133,20 +119,6 @@ public class DataScopeAspect {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 是否存在注解,如果存在就获取
|
|
||||||
*/
|
|
||||||
private DataScope getAnnotationLog(JoinPoint joinPoint) {
|
|
||||||
Signature signature = joinPoint.getSignature();
|
|
||||||
MethodSignature methodSignature = (MethodSignature) signature;
|
|
||||||
Method method = methodSignature.getMethod();
|
|
||||||
|
|
||||||
if (method != null) {
|
|
||||||
return method.getAnnotation(DataScope.class);
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 拼接权限sql前先清空params.dataScope参数防止注入
|
* 拼接权限sql前先清空params.dataScope参数防止注入
|
||||||
*/
|
*/
|
||||||
|
@ -6,33 +6,21 @@ import com.ruoyi.common.utils.StringUtils;
|
|||||||
import org.aspectj.lang.ProceedingJoinPoint;
|
import org.aspectj.lang.ProceedingJoinPoint;
|
||||||
import org.aspectj.lang.annotation.Around;
|
import org.aspectj.lang.annotation.Around;
|
||||||
import org.aspectj.lang.annotation.Aspect;
|
import org.aspectj.lang.annotation.Aspect;
|
||||||
import org.aspectj.lang.annotation.Pointcut;
|
|
||||||
import org.aspectj.lang.reflect.MethodSignature;
|
|
||||||
import org.springframework.core.annotation.AnnotationUtils;
|
|
||||||
import org.springframework.core.annotation.Order;
|
import org.springframework.core.annotation.Order;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
import java.util.Objects;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 多数据源处理
|
* 多数据源处理
|
||||||
*
|
*
|
||||||
* @author ruoyi
|
* @author Lion Li
|
||||||
*/
|
*/
|
||||||
@Aspect
|
@Aspect
|
||||||
@Order(-500)
|
@Order(-500)
|
||||||
@Component
|
@Component
|
||||||
public class DataSourceAspect {
|
public class DataSourceAspect {
|
||||||
|
|
||||||
@Pointcut("@annotation(com.ruoyi.common.annotation.DataSource)"
|
@Around("@annotation(dataSource) || @within(dataSource)")
|
||||||
+ "|| @within(com.ruoyi.common.annotation.DataSource)")
|
public Object around(ProceedingJoinPoint point, DataSource dataSource) throws Throwable {
|
||||||
public void dsPointCut() {
|
|
||||||
}
|
|
||||||
|
|
||||||
@Around("dsPointCut()")
|
|
||||||
public Object around(ProceedingJoinPoint point) throws Throwable {
|
|
||||||
DataSource dataSource = getDataSource(point);
|
|
||||||
|
|
||||||
if (StringUtils.isNotNull(dataSource)) {
|
if (StringUtils.isNotNull(dataSource)) {
|
||||||
DynamicDataSourceContextHolder.poll();
|
DynamicDataSourceContextHolder.poll();
|
||||||
String source = dataSource.value().getSource();
|
String source = dataSource.value().getSource();
|
||||||
@ -47,16 +35,4 @@ public class DataSourceAspect {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取需要切换的数据源
|
|
||||||
*/
|
|
||||||
public DataSource getDataSource(ProceedingJoinPoint point) {
|
|
||||||
MethodSignature signature = (MethodSignature) point.getSignature();
|
|
||||||
DataSource dataSource = AnnotationUtils.findAnnotation(signature.getMethod(), DataSource.class);
|
|
||||||
if (Objects.nonNull(dataSource)) {
|
|
||||||
return dataSource;
|
|
||||||
}
|
|
||||||
|
|
||||||
return AnnotationUtils.findAnnotation(signature.getDeclaringType(), DataSource.class);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,9 @@
|
|||||||
package com.ruoyi.framework.aspectj;
|
package com.ruoyi.framework.aspectj;
|
||||||
|
|
||||||
import com.ruoyi.common.annotation.Log;
|
import com.ruoyi.common.annotation.Log;
|
||||||
|
import com.ruoyi.common.core.domain.dto.OperLogDTO;
|
||||||
import com.ruoyi.common.core.domain.model.LoginUser;
|
import com.ruoyi.common.core.domain.model.LoginUser;
|
||||||
|
import com.ruoyi.common.core.service.OperLogService;
|
||||||
import com.ruoyi.common.enums.BusinessStatus;
|
import com.ruoyi.common.enums.BusinessStatus;
|
||||||
import com.ruoyi.common.enums.HttpMethod;
|
import com.ruoyi.common.enums.HttpMethod;
|
||||||
import com.ruoyi.common.utils.JsonUtils;
|
import com.ruoyi.common.utils.JsonUtils;
|
||||||
@ -9,17 +11,11 @@ import com.ruoyi.common.utils.SecurityUtils;
|
|||||||
import com.ruoyi.common.utils.ServletUtils;
|
import com.ruoyi.common.utils.ServletUtils;
|
||||||
import com.ruoyi.common.utils.StringUtils;
|
import com.ruoyi.common.utils.StringUtils;
|
||||||
import com.ruoyi.common.utils.spring.SpringUtils;
|
import com.ruoyi.common.utils.spring.SpringUtils;
|
||||||
import com.ruoyi.framework.web.service.AsyncService;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import com.ruoyi.system.domain.SysOperLog;
|
|
||||||
import org.aspectj.lang.JoinPoint;
|
import org.aspectj.lang.JoinPoint;
|
||||||
import org.aspectj.lang.Signature;
|
|
||||||
import org.aspectj.lang.annotation.AfterReturning;
|
import org.aspectj.lang.annotation.AfterReturning;
|
||||||
import org.aspectj.lang.annotation.AfterThrowing;
|
import org.aspectj.lang.annotation.AfterThrowing;
|
||||||
import org.aspectj.lang.annotation.Aspect;
|
import org.aspectj.lang.annotation.Aspect;
|
||||||
import org.aspectj.lang.annotation.Pointcut;
|
|
||||||
import org.aspectj.lang.reflect.MethodSignature;
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
import org.springframework.validation.BindingResult;
|
import org.springframework.validation.BindingResult;
|
||||||
import org.springframework.web.multipart.MultipartFile;
|
import org.springframework.web.multipart.MultipartFile;
|
||||||
@ -27,81 +23,58 @@ import org.springframework.web.servlet.HandlerMapping;
|
|||||||
|
|
||||||
import javax.servlet.http.HttpServletRequest;
|
import javax.servlet.http.HttpServletRequest;
|
||||||
import javax.servlet.http.HttpServletResponse;
|
import javax.servlet.http.HttpServletResponse;
|
||||||
import java.lang.reflect.Method;
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 操作日志记录处理
|
* 操作日志记录处理
|
||||||
*
|
*
|
||||||
* @author ruoyi
|
* @author Lion Li
|
||||||
*/
|
*/
|
||||||
|
@Slf4j
|
||||||
@Aspect
|
@Aspect
|
||||||
@Component
|
@Component
|
||||||
public class LogAspect
|
public class LogAspect {
|
||||||
{
|
|
||||||
private static final Logger log = LoggerFactory.getLogger(LogAspect.class);
|
|
||||||
|
|
||||||
// 配置织入点
|
|
||||||
@Pointcut("@annotation(com.ruoyi.common.annotation.Log)")
|
|
||||||
public void logPointCut()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 处理完请求后执行
|
* 处理完请求后执行
|
||||||
*
|
*
|
||||||
* @param joinPoint 切点
|
* @param joinPoint 切点
|
||||||
*/
|
*/
|
||||||
@AfterReturning(pointcut = "logPointCut()", returning = "jsonResult")
|
@AfterReturning(pointcut = "@annotation(controllerLog)", returning = "jsonResult")
|
||||||
public void doAfterReturning(JoinPoint joinPoint, Object jsonResult)
|
public void doAfterReturning(JoinPoint joinPoint, Log controllerLog, Object jsonResult) {
|
||||||
{
|
handleLog(joinPoint, controllerLog, null, jsonResult);
|
||||||
handleLog(joinPoint, null, jsonResult);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 拦截异常操作
|
* 拦截异常操作
|
||||||
*
|
*
|
||||||
* @param joinPoint 切点
|
* @param joinPoint 切点
|
||||||
* @param e 异常
|
* @param e 异常
|
||||||
*/
|
*/
|
||||||
@AfterThrowing(value = "logPointCut()", throwing = "e")
|
@AfterThrowing(value = "@annotation(controllerLog)", throwing = "e")
|
||||||
public void doAfterThrowing(JoinPoint joinPoint, Exception e)
|
public void doAfterThrowing(JoinPoint joinPoint, Log controllerLog, Exception e) {
|
||||||
{
|
handleLog(joinPoint, controllerLog, e, null);
|
||||||
handleLog(joinPoint, e, null);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void handleLog(final JoinPoint joinPoint, final Exception e, Object jsonResult)
|
protected void handleLog(final JoinPoint joinPoint, Log controllerLog, final Exception e, Object jsonResult) {
|
||||||
{
|
try {
|
||||||
try
|
|
||||||
{
|
|
||||||
// 获得注解
|
|
||||||
Log controllerLog = getAnnotationLog(joinPoint);
|
|
||||||
if (controllerLog == null)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 获取当前的用户
|
// 获取当前的用户
|
||||||
LoginUser loginUser = SecurityUtils.getLoginUser();
|
LoginUser loginUser = SecurityUtils.getLoginUser();
|
||||||
|
|
||||||
// *========数据库日志=========*//
|
// *========数据库日志=========*//
|
||||||
SysOperLog operLog = new SysOperLog();
|
OperLogDTO operLog = new OperLogDTO();
|
||||||
operLog.setStatus(BusinessStatus.SUCCESS.ordinal());
|
operLog.setStatus(BusinessStatus.SUCCESS.ordinal());
|
||||||
// 请求的地址
|
// 请求的地址
|
||||||
String ip = ServletUtils.getClientIP();
|
String ip = ServletUtils.getClientIP();
|
||||||
operLog.setOperIp(ip);
|
operLog.setOperIp(ip);
|
||||||
// 返回参数
|
|
||||||
operLog.setJsonResult(JsonUtils.toJsonString(jsonResult));
|
|
||||||
|
|
||||||
operLog.setOperUrl(ServletUtils.getRequest().getRequestURI());
|
operLog.setOperUrl(ServletUtils.getRequest().getRequestURI());
|
||||||
if (loginUser != null)
|
if (loginUser != null) {
|
||||||
{
|
|
||||||
operLog.setOperName(loginUser.getUsername());
|
operLog.setOperName(loginUser.getUsername());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (e != null)
|
if (e != null) {
|
||||||
{
|
|
||||||
operLog.setStatus(BusinessStatus.FAIL.ordinal());
|
operLog.setStatus(BusinessStatus.FAIL.ordinal());
|
||||||
operLog.setErrorMsg(StringUtils.substring(e.getMessage(), 0, 2000));
|
operLog.setErrorMsg(StringUtils.substring(e.getMessage(), 0, 2000));
|
||||||
}
|
}
|
||||||
@ -112,12 +85,10 @@ public class LogAspect
|
|||||||
// 设置请求方式
|
// 设置请求方式
|
||||||
operLog.setRequestMethod(ServletUtils.getRequest().getMethod());
|
operLog.setRequestMethod(ServletUtils.getRequest().getMethod());
|
||||||
// 处理设置注解上的参数
|
// 处理设置注解上的参数
|
||||||
getControllerMethodDescription(joinPoint, controllerLog, operLog);
|
getControllerMethodDescription(joinPoint, controllerLog, operLog, jsonResult);
|
||||||
// 保存数据库
|
// 保存数据库
|
||||||
SpringUtils.getBean(AsyncService.class).recordOper(operLog);
|
SpringUtils.getBean(OperLogService.class).recordOper(operLog);
|
||||||
}
|
} catch (Exception exp) {
|
||||||
catch (Exception exp)
|
|
||||||
{
|
|
||||||
// 记录本地异常日志
|
// 记录本地异常日志
|
||||||
log.error("==前置通知异常==");
|
log.error("==前置通知异常==");
|
||||||
log.error("异常信息:{}", exp.getMessage());
|
log.error("异常信息:{}", exp.getMessage());
|
||||||
@ -128,12 +99,11 @@ public class LogAspect
|
|||||||
/**
|
/**
|
||||||
* 获取注解中对方法的描述信息 用于Controller层注解
|
* 获取注解中对方法的描述信息 用于Controller层注解
|
||||||
*
|
*
|
||||||
* @param log 日志
|
* @param log 日志
|
||||||
* @param operLog 操作日志
|
* @param operLog 操作日志
|
||||||
* @throws Exception
|
* @throws Exception
|
||||||
*/
|
*/
|
||||||
public void getControllerMethodDescription(JoinPoint joinPoint, Log log, SysOperLog operLog) throws Exception
|
public void getControllerMethodDescription(JoinPoint joinPoint, Log log, OperLogDTO operLog, Object jsonResult) throws Exception {
|
||||||
{
|
|
||||||
// 设置action动作
|
// 设置action动作
|
||||||
operLog.setBusinessType(log.businessType().ordinal());
|
operLog.setBusinessType(log.businessType().ordinal());
|
||||||
// 设置标题
|
// 设置标题
|
||||||
@ -141,11 +111,14 @@ public class LogAspect
|
|||||||
// 设置操作人类别
|
// 设置操作人类别
|
||||||
operLog.setOperatorType(log.operatorType().ordinal());
|
operLog.setOperatorType(log.operatorType().ordinal());
|
||||||
// 是否需要保存request,参数和值
|
// 是否需要保存request,参数和值
|
||||||
if (log.isSaveRequestData())
|
if (log.isSaveRequestData()) {
|
||||||
{
|
|
||||||
// 获取参数的信息,传入到数据库中。
|
// 获取参数的信息,传入到数据库中。
|
||||||
setRequestValue(joinPoint, operLog);
|
setRequestValue(joinPoint, operLog);
|
||||||
}
|
}
|
||||||
|
// 是否需要保存response,参数和值
|
||||||
|
if (log.isSaveResponseData() && StringUtils.isNotNull(jsonResult)) {
|
||||||
|
operLog.setJsonResult(StringUtils.substring(JsonUtils.toJsonString(jsonResult), 0, 2000));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -154,50 +127,32 @@ public class LogAspect
|
|||||||
* @param operLog 操作日志
|
* @param operLog 操作日志
|
||||||
* @throws Exception 异常
|
* @throws Exception 异常
|
||||||
*/
|
*/
|
||||||
private void setRequestValue(JoinPoint joinPoint, SysOperLog operLog) throws Exception
|
private void setRequestValue(JoinPoint joinPoint, OperLogDTO operLog) throws Exception {
|
||||||
{
|
|
||||||
String requestMethod = operLog.getRequestMethod();
|
String requestMethod = operLog.getRequestMethod();
|
||||||
if (HttpMethod.PUT.name().equals(requestMethod) || HttpMethod.POST.name().equals(requestMethod))
|
if (HttpMethod.PUT.name().equals(requestMethod) || HttpMethod.POST.name().equals(requestMethod)) {
|
||||||
{
|
|
||||||
String params = argsArrayToString(joinPoint.getArgs());
|
String params = argsArrayToString(joinPoint.getArgs());
|
||||||
operLog.setOperParam(StringUtils.substring(params, 0, 2000));
|
operLog.setOperParam(StringUtils.substring(params, 0, 2000));
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
Map<?, ?> paramsMap = (Map<?, ?>) ServletUtils.getRequest().getAttribute(HandlerMapping.URI_TEMPLATE_VARIABLES_ATTRIBUTE);
|
Map<?, ?> paramsMap = (Map<?, ?>) ServletUtils.getRequest().getAttribute(HandlerMapping.URI_TEMPLATE_VARIABLES_ATTRIBUTE);
|
||||||
operLog.setOperParam(StringUtils.substring(paramsMap.toString(), 0, 2000));
|
operLog.setOperParam(StringUtils.substring(paramsMap.toString(), 0, 2000));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 是否存在注解,如果存在就获取
|
|
||||||
*/
|
|
||||||
private Log getAnnotationLog(JoinPoint joinPoint) throws Exception
|
|
||||||
{
|
|
||||||
Signature signature = joinPoint.getSignature();
|
|
||||||
MethodSignature methodSignature = (MethodSignature) signature;
|
|
||||||
Method method = methodSignature.getMethod();
|
|
||||||
|
|
||||||
if (method != null)
|
|
||||||
{
|
|
||||||
return method.getAnnotation(Log.class);
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 参数拼装
|
* 参数拼装
|
||||||
*/
|
*/
|
||||||
private String argsArrayToString(Object[] paramsArray)
|
private String argsArrayToString(Object[] paramsArray) {
|
||||||
{
|
|
||||||
StringBuilder params = new StringBuilder();
|
StringBuilder params = new StringBuilder();
|
||||||
if (paramsArray != null && paramsArray.length > 0)
|
if (paramsArray != null && paramsArray.length > 0) {
|
||||||
{
|
for (Object o : paramsArray) {
|
||||||
for (Object o : paramsArray) {
|
if (StringUtils.isNotNull(o) && !isFilterObject(o)) {
|
||||||
if (StringUtils.isNotNull(o) && !isFilterObject(o)) {
|
try {
|
||||||
params.append(JsonUtils.toJsonString(o)).append(" ");
|
params.append(JsonUtils.toJsonString(o)).append(" ");
|
||||||
}
|
} catch (Exception e) {
|
||||||
}
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return params.toString().trim();
|
return params.toString().trim();
|
||||||
}
|
}
|
||||||
@ -209,27 +164,21 @@ public class LogAspect
|
|||||||
* @return 如果是需要过滤的对象,则返回true;否则返回false。
|
* @return 如果是需要过滤的对象,则返回true;否则返回false。
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("rawtypes")
|
@SuppressWarnings("rawtypes")
|
||||||
public boolean isFilterObject(final Object o)
|
public boolean isFilterObject(final Object o) {
|
||||||
{
|
|
||||||
Class<?> clazz = o.getClass();
|
Class<?> clazz = o.getClass();
|
||||||
if (clazz.isArray())
|
if (clazz.isArray()) {
|
||||||
{
|
|
||||||
return clazz.getComponentType().isAssignableFrom(MultipartFile.class);
|
return clazz.getComponentType().isAssignableFrom(MultipartFile.class);
|
||||||
}
|
} else if (Collection.class.isAssignableFrom(clazz)) {
|
||||||
else if (Collection.class.isAssignableFrom(clazz))
|
|
||||||
{
|
|
||||||
Collection collection = (Collection) o;
|
Collection collection = (Collection) o;
|
||||||
for (Object value : collection) {
|
for (Object value : collection) {
|
||||||
return value instanceof MultipartFile;
|
return value instanceof MultipartFile;
|
||||||
}
|
}
|
||||||
}
|
} else if (Map.class.isAssignableFrom(clazz)) {
|
||||||
else if (Map.class.isAssignableFrom(clazz))
|
|
||||||
{
|
|
||||||
Map map = (Map) o;
|
Map map = (Map) o;
|
||||||
for (Object value : map.entrySet()) {
|
for (Object value : map.entrySet()) {
|
||||||
Map.Entry entry = (Map.Entry) value;
|
Map.Entry entry = (Map.Entry) value;
|
||||||
return entry.getValue() instanceof MultipartFile;
|
return entry.getValue() instanceof MultipartFile;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return o instanceof MultipartFile || o instanceof HttpServletRequest || o instanceof HttpServletResponse
|
return o instanceof MultipartFile || o instanceof HttpServletRequest || o instanceof HttpServletResponse
|
||||||
|| o instanceof BindingResult;
|
|| o instanceof BindingResult;
|
||||||
|
@ -3,114 +3,63 @@ package com.ruoyi.framework.aspectj;
|
|||||||
import com.ruoyi.common.annotation.RateLimiter;
|
import com.ruoyi.common.annotation.RateLimiter;
|
||||||
import com.ruoyi.common.enums.LimitType;
|
import com.ruoyi.common.enums.LimitType;
|
||||||
import com.ruoyi.common.exception.ServiceException;
|
import com.ruoyi.common.exception.ServiceException;
|
||||||
|
import com.ruoyi.common.utils.RedisUtils;
|
||||||
import com.ruoyi.common.utils.ServletUtils;
|
import com.ruoyi.common.utils.ServletUtils;
|
||||||
import com.ruoyi.common.utils.StringUtils;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.aspectj.lang.JoinPoint;
|
import org.aspectj.lang.JoinPoint;
|
||||||
import org.aspectj.lang.Signature;
|
|
||||||
import org.aspectj.lang.annotation.Aspect;
|
import org.aspectj.lang.annotation.Aspect;
|
||||||
import org.aspectj.lang.annotation.Before;
|
import org.aspectj.lang.annotation.Before;
|
||||||
import org.aspectj.lang.annotation.Pointcut;
|
|
||||||
import org.aspectj.lang.reflect.MethodSignature;
|
import org.aspectj.lang.reflect.MethodSignature;
|
||||||
import org.slf4j.Logger;
|
import org.redisson.api.RateType;
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
|
||||||
import org.springframework.data.redis.core.RedisTemplate;
|
|
||||||
import org.springframework.data.redis.core.script.RedisScript;
|
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 限流处理
|
* 限流处理
|
||||||
*
|
*
|
||||||
* @author ruoyi
|
* @author Lion Li
|
||||||
*/
|
*/
|
||||||
|
@Slf4j
|
||||||
@Aspect
|
@Aspect
|
||||||
@Component
|
@Component
|
||||||
public class RateLimiterAspect
|
public class RateLimiterAspect {
|
||||||
{
|
|
||||||
private static final Logger log = LoggerFactory.getLogger(RateLimiterAspect.class);
|
|
||||||
|
|
||||||
private RedisTemplate<Object, Object> redisTemplate;
|
@Before("@annotation(rateLimiter)")
|
||||||
|
public void doBefore(JoinPoint point, RateLimiter rateLimiter) throws Throwable {
|
||||||
private RedisScript<Long> limitScript;
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
public void setRedisTemplate1(RedisTemplate<Object, Object> redisTemplate)
|
|
||||||
{
|
|
||||||
this.redisTemplate = redisTemplate;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
public void setLimitScript(RedisScript<Long> limitScript)
|
|
||||||
{
|
|
||||||
this.limitScript = limitScript;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 配置织入点
|
|
||||||
@Pointcut("@annotation(com.ruoyi.common.annotation.RateLimiter)")
|
|
||||||
public void rateLimiterPointCut()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
@Before("rateLimiterPointCut()")
|
|
||||||
public void doBefore(JoinPoint point) throws Throwable
|
|
||||||
{
|
|
||||||
RateLimiter rateLimiter = getAnnotationRateLimiter(point);
|
|
||||||
String key = rateLimiter.key();
|
|
||||||
int time = rateLimiter.time();
|
int time = rateLimiter.time();
|
||||||
int count = rateLimiter.count();
|
int count = rateLimiter.count();
|
||||||
|
|
||||||
String combineKey = getCombineKey(rateLimiter, point);
|
String combineKey = getCombineKey(rateLimiter, point);
|
||||||
List<Object> keys = Collections.singletonList(combineKey);
|
try {
|
||||||
try
|
RateType rateType = RateType.OVERALL;
|
||||||
{
|
if (rateLimiter.limitType() == LimitType.CLUSTER) {
|
||||||
Long number = redisTemplate.execute(limitScript, keys, count, time);
|
rateType = RateType.PER_CLIENT;
|
||||||
if (StringUtils.isNull(number) || number.intValue() > count)
|
}
|
||||||
{
|
long number = RedisUtils.rateLimiter(combineKey, rateType, count, time);
|
||||||
|
if (number == -1) {
|
||||||
throw new ServiceException("访问过于频繁,请稍后再试");
|
throw new ServiceException("访问过于频繁,请稍后再试");
|
||||||
}
|
}
|
||||||
log.info("限制请求'{}',当前请求'{}',缓存key'{}'", count, number.intValue(), key);
|
log.info("限制令牌 => {}, 剩余令牌 => {}, 缓存key => '{}'", count, number, combineKey);
|
||||||
}
|
} catch (ServiceException e) {
|
||||||
catch (ServiceException e)
|
|
||||||
{
|
|
||||||
throw e;
|
throw e;
|
||||||
}
|
} catch (Exception e) {
|
||||||
catch (Exception e)
|
|
||||||
{
|
|
||||||
throw new RuntimeException("服务器限流异常,请稍后再试");
|
throw new RuntimeException("服务器限流异常,请稍后再试");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
public String getCombineKey(RateLimiter rateLimiter, JoinPoint point) {
|
||||||
* 是否存在注解,如果存在就获取
|
StringBuilder stringBuffer = new StringBuilder(rateLimiter.key());
|
||||||
*/
|
if (rateLimiter.limitType() == LimitType.IP) {
|
||||||
private RateLimiter getAnnotationRateLimiter(JoinPoint joinPoint)
|
// 获取请求ip
|
||||||
{
|
stringBuffer.append(ServletUtils.getClientIP()).append("-");
|
||||||
Signature signature = joinPoint.getSignature();
|
} else if (rateLimiter.limitType() == LimitType.CLUSTER){
|
||||||
MethodSignature methodSignature = (MethodSignature) signature;
|
// 获取客户端实例id
|
||||||
Method method = methodSignature.getMethod();
|
stringBuffer.append(RedisUtils.getClientId()).append("-");
|
||||||
|
|
||||||
if (method != null)
|
|
||||||
{
|
|
||||||
return method.getAnnotation(RateLimiter.class);
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getCombineKey(RateLimiter rateLimiter, JoinPoint point)
|
|
||||||
{
|
|
||||||
StringBuffer stringBuffer = new StringBuffer(rateLimiter.key());
|
|
||||||
if (rateLimiter.limitType() == LimitType.IP)
|
|
||||||
{
|
|
||||||
stringBuffer.append(ServletUtils.getClientIP());
|
|
||||||
}
|
}
|
||||||
MethodSignature signature = (MethodSignature) point.getSignature();
|
MethodSignature signature = (MethodSignature) point.getSignature();
|
||||||
Method method = signature.getMethod();
|
Method method = signature.getMethod();
|
||||||
Class<?> targetClass = method.getDeclaringClass();
|
Class<?> targetClass = method.getDeclaringClass();
|
||||||
stringBuffer.append("-").append(targetClass.getName()).append("- ").append(method.getName());
|
stringBuffer.append(targetClass.getName()).append("-").append(method.getName());
|
||||||
return stringBuffer.toString();
|
return stringBuffer.toString();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,69 @@
|
|||||||
|
package com.ruoyi.framework.aspectj;
|
||||||
|
|
||||||
|
import cn.hutool.core.util.StrUtil;
|
||||||
|
import cn.hutool.crypto.SecureUtil;
|
||||||
|
import com.baomidou.lock.LockInfo;
|
||||||
|
import com.baomidou.lock.LockTemplate;
|
||||||
|
import com.ruoyi.common.annotation.RepeatSubmit;
|
||||||
|
import com.ruoyi.common.constant.Constants;
|
||||||
|
import com.ruoyi.common.exception.ServiceException;
|
||||||
|
import com.ruoyi.common.properties.TokenProperties;
|
||||||
|
import com.ruoyi.common.utils.ServletUtils;
|
||||||
|
import com.ruoyi.common.utils.StringUtils;
|
||||||
|
import com.ruoyi.framework.config.properties.RepeatSubmitProperties;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.aspectj.lang.JoinPoint;
|
||||||
|
import org.aspectj.lang.annotation.Aspect;
|
||||||
|
import org.aspectj.lang.annotation.Before;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 防止重复提交
|
||||||
|
*
|
||||||
|
* @author Lion Li
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
@RequiredArgsConstructor(onConstructor_ = @Autowired)
|
||||||
|
@Aspect
|
||||||
|
@Component
|
||||||
|
public class RepeatSubmitAspect {
|
||||||
|
|
||||||
|
private final TokenProperties tokenProperties;
|
||||||
|
private final RepeatSubmitProperties repeatSubmitProperties;
|
||||||
|
private final LockTemplate lockTemplate;
|
||||||
|
|
||||||
|
@Before("@annotation(repeatSubmit)")
|
||||||
|
public void doBefore(JoinPoint point, RepeatSubmit repeatSubmit) throws Throwable {
|
||||||
|
// 如果注解不为0 则使用注解数值
|
||||||
|
long interval = repeatSubmitProperties.getInterval();
|
||||||
|
if (repeatSubmit.interval() > 0) {
|
||||||
|
interval = repeatSubmit.timeUnit().toMillis(repeatSubmit.interval());
|
||||||
|
}
|
||||||
|
if (interval < 1000) {
|
||||||
|
throw new ServiceException("重复提交间隔时间不能小于'1'秒");
|
||||||
|
}
|
||||||
|
HttpServletRequest request = ServletUtils.getRequest();
|
||||||
|
String nowParams = StrUtil.join(",", point.getArgs());
|
||||||
|
|
||||||
|
// 请求地址(作为存放cache的key值)
|
||||||
|
String url = request.getRequestURI();
|
||||||
|
|
||||||
|
// 唯一值(没有消息头则使用请求地址)
|
||||||
|
String submitKey = request.getHeader(tokenProperties.getHeader());
|
||||||
|
if (StringUtils.isEmpty(submitKey)) {
|
||||||
|
submitKey = url;
|
||||||
|
}
|
||||||
|
submitKey = SecureUtil.md5(submitKey + ":" + nowParams);
|
||||||
|
// 唯一标识(指定key + 消息头)
|
||||||
|
String cacheRepeatKey = Constants.REPEAT_SUBMIT_KEY + submitKey;
|
||||||
|
LockInfo lock = lockTemplate.lock(cacheRepeatKey, interval, interval / 2);
|
||||||
|
if (lock == null) {
|
||||||
|
throw new ServiceException(repeatSubmit.message());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -1,5 +1,6 @@
|
|||||||
package com.ruoyi.framework.config;
|
package com.ruoyi.framework.config;
|
||||||
|
|
||||||
|
import cn.hutool.core.util.ArrayUtil;
|
||||||
import com.ruoyi.common.exception.ServiceException;
|
import com.ruoyi.common.exception.ServiceException;
|
||||||
import org.springframework.aop.interceptor.AsyncUncaughtExceptionHandler;
|
import org.springframework.aop.interceptor.AsyncUncaughtExceptionHandler;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
@ -41,10 +42,13 @@ public class AsyncConfig extends AsyncConfigurerSupport {
|
|||||||
public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
|
public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
|
||||||
return (throwable, method, objects) -> {
|
return (throwable, method, objects) -> {
|
||||||
throwable.printStackTrace();
|
throwable.printStackTrace();
|
||||||
throw new ServiceException(
|
StringBuilder sb = new StringBuilder();
|
||||||
"Exception message - " + throwable.getMessage()
|
sb.append("Exception message - ").append(throwable.getMessage())
|
||||||
+ ", Method name - " + method.getName()
|
.append(", Method name - ").append(method.getName());
|
||||||
+ ", Parameter value - " + Arrays.toString(objects));
|
if (ArrayUtil.isNotEmpty(objects)) {
|
||||||
|
sb.append(", Parameter value - ").append(Arrays.toString(objects));
|
||||||
|
}
|
||||||
|
throw new ServiceException(sb.toString());
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
package com.ruoyi.framework.config;
|
package com.ruoyi.framework.config;
|
||||||
|
|
||||||
import cn.hutool.core.util.StrUtil;
|
import cn.hutool.core.util.ObjectUtil;
|
||||||
import com.ruoyi.common.utils.StringUtils;
|
import com.ruoyi.common.utils.StringUtils;
|
||||||
import com.ruoyi.framework.config.properties.RedissonProperties;
|
import com.ruoyi.framework.config.properties.RedissonProperties;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
@ -18,7 +18,6 @@ import org.springframework.cache.annotation.CachingConfigurerSupport;
|
|||||||
import org.springframework.cache.annotation.EnableCaching;
|
import org.springframework.cache.annotation.EnableCaching;
|
||||||
import org.springframework.context.annotation.Bean;
|
import org.springframework.context.annotation.Bean;
|
||||||
import org.springframework.context.annotation.Configuration;
|
import org.springframework.context.annotation.Configuration;
|
||||||
import org.springframework.data.redis.core.script.DefaultRedisScript;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
@ -58,23 +57,52 @@ public class RedisConfig extends CachingConfigurerSupport {
|
|||||||
.setTransportMode(redissonProperties.getTransportMode());
|
.setTransportMode(redissonProperties.getTransportMode());
|
||||||
|
|
||||||
RedissonProperties.SingleServerConfig singleServerConfig = redissonProperties.getSingleServerConfig();
|
RedissonProperties.SingleServerConfig singleServerConfig = redissonProperties.getSingleServerConfig();
|
||||||
// 使用单机模式
|
if (ObjectUtil.isNotNull(singleServerConfig)) {
|
||||||
config.useSingleServer()
|
// 使用单机模式
|
||||||
.setAddress(prefix + redisProperties.getHost() + ":" + redisProperties.getPort())
|
config.useSingleServer()
|
||||||
.setConnectTimeout(((Long) redisProperties.getTimeout().toMillis()).intValue())
|
.setAddress(prefix + redisProperties.getHost() + ":" + redisProperties.getPort())
|
||||||
.setDatabase(redisProperties.getDatabase())
|
.setConnectTimeout(((Long) redisProperties.getTimeout().toMillis()).intValue())
|
||||||
.setPassword(StringUtils.isNotBlank(redisProperties.getPassword()) ? redisProperties.getPassword() : null)
|
.setDatabase(redisProperties.getDatabase())
|
||||||
.setTimeout(singleServerConfig.getTimeout())
|
.setPassword(StringUtils.isNotBlank(redisProperties.getPassword()) ? redisProperties.getPassword() : null)
|
||||||
.setRetryAttempts(singleServerConfig.getRetryAttempts())
|
.setTimeout(singleServerConfig.getTimeout())
|
||||||
.setRetryInterval(singleServerConfig.getRetryInterval())
|
.setRetryAttempts(singleServerConfig.getRetryAttempts())
|
||||||
.setSubscriptionsPerConnection(singleServerConfig.getSubscriptionsPerConnection())
|
.setRetryInterval(singleServerConfig.getRetryInterval())
|
||||||
.setClientName(singleServerConfig.getClientName())
|
.setSubscriptionsPerConnection(singleServerConfig.getSubscriptionsPerConnection())
|
||||||
.setIdleConnectionTimeout(singleServerConfig.getIdleConnectionTimeout())
|
.setClientName(singleServerConfig.getClientName())
|
||||||
.setSubscriptionConnectionMinimumIdleSize(singleServerConfig.getSubscriptionConnectionMinimumIdleSize())
|
.setIdleConnectionTimeout(singleServerConfig.getIdleConnectionTimeout())
|
||||||
.setSubscriptionConnectionPoolSize(singleServerConfig.getSubscriptionConnectionPoolSize())
|
.setSubscriptionConnectionMinimumIdleSize(singleServerConfig.getSubscriptionConnectionMinimumIdleSize())
|
||||||
.setConnectionMinimumIdleSize(singleServerConfig.getConnectionMinimumIdleSize())
|
.setSubscriptionConnectionPoolSize(singleServerConfig.getSubscriptionConnectionPoolSize())
|
||||||
.setConnectionPoolSize(singleServerConfig.getConnectionPoolSize())
|
.setConnectionMinimumIdleSize(singleServerConfig.getConnectionMinimumIdleSize())
|
||||||
.setDnsMonitoringInterval(singleServerConfig.getDnsMonitoringInterval());
|
.setConnectionPoolSize(singleServerConfig.getConnectionPoolSize())
|
||||||
|
.setDnsMonitoringInterval(singleServerConfig.getDnsMonitoringInterval());
|
||||||
|
}
|
||||||
|
|
||||||
|
RedissonProperties.ClusterServersConfig clusterServersConfig = redissonProperties.getClusterServersConfig();
|
||||||
|
if (ObjectUtil.isNotNull(clusterServersConfig)) {
|
||||||
|
// 使用集群模式
|
||||||
|
config.useClusterServers()
|
||||||
|
.setConnectTimeout(((Long) redisProperties.getTimeout().toMillis()).intValue())
|
||||||
|
.setPassword(StringUtils.isNotBlank(redisProperties.getPassword()) ? redisProperties.getPassword() : null)
|
||||||
|
.setTimeout(clusterServersConfig.getTimeout())
|
||||||
|
.setRetryAttempts(clusterServersConfig.getRetryAttempts())
|
||||||
|
.setRetryInterval(clusterServersConfig.getRetryInterval())
|
||||||
|
.setSubscriptionsPerConnection(clusterServersConfig.getSubscriptionsPerConnection())
|
||||||
|
.setClientName(clusterServersConfig.getClientName())
|
||||||
|
.setIdleConnectionTimeout(clusterServersConfig.getIdleConnectionTimeout())
|
||||||
|
.setPingConnectionInterval(clusterServersConfig.getPingConnectionInterval())
|
||||||
|
.setSubscriptionConnectionMinimumIdleSize(clusterServersConfig.getSubscriptionConnectionMinimumIdleSize())
|
||||||
|
.setSubscriptionConnectionPoolSize(clusterServersConfig.getSubscriptionConnectionPoolSize())
|
||||||
|
.setMasterConnectionMinimumIdleSize(clusterServersConfig.getMasterConnectionMinimumIdleSize())
|
||||||
|
.setMasterConnectionPoolSize(clusterServersConfig.getMasterConnectionPoolSize())
|
||||||
|
.setSlaveConnectionMinimumIdleSize(clusterServersConfig.getSlaveConnectionMinimumIdleSize())
|
||||||
|
.setSlaveConnectionPoolSize(clusterServersConfig.getSlaveConnectionPoolSize())
|
||||||
|
.setDnsMonitoringInterval(clusterServersConfig.getDnsMonitoringInterval())
|
||||||
|
.setFailedSlaveReconnectionInterval(clusterServersConfig.getFailedSlaveReconnectionInterval())
|
||||||
|
.setScanInterval(clusterServersConfig.getScanInterval())
|
||||||
|
.setReadMode(clusterServersConfig.getReadMode())
|
||||||
|
.setSubscriptionMode(clusterServersConfig.getSubscriptionMode())
|
||||||
|
.setNodeAddresses(redisProperties.getCluster().getNodes());
|
||||||
|
}
|
||||||
RedissonClient redissonClient = Redisson.create(config);
|
RedissonClient redissonClient = Redisson.create(config);
|
||||||
log.info("初始化 redis 配置");
|
log.info("初始化 redis 配置");
|
||||||
return redissonClient;
|
return redissonClient;
|
||||||
@ -95,32 +123,4 @@ public class RedisConfig extends CachingConfigurerSupport {
|
|||||||
return new RedissonSpringCacheManager(redissonClient, config, JsonJacksonCodec.INSTANCE);
|
return new RedissonSpringCacheManager(redissonClient, config, JsonJacksonCodec.INSTANCE);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Bean
|
|
||||||
public DefaultRedisScript<Long> limitScript() {
|
|
||||||
DefaultRedisScript<Long> redisScript = new DefaultRedisScript<>();
|
|
||||||
redisScript.setScriptText(limitScriptText());
|
|
||||||
redisScript.setResultType(Long.class);
|
|
||||||
return redisScript;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 限流脚本
|
|
||||||
*/
|
|
||||||
private String limitScriptText() {
|
|
||||||
return StrUtil.builder()
|
|
||||||
.append("local key = KEYS[1]\n")
|
|
||||||
.append("local count = tonumber(ARGV[1])\n")
|
|
||||||
.append("local time = tonumber(ARGV[2])\n")
|
|
||||||
.append("local current = redis.call('get', key);\n")
|
|
||||||
.append("if current and tonumber(current) > count then\n")
|
|
||||||
.append(" return current;\n")
|
|
||||||
.append("end\n")
|
|
||||||
.append("current = redis.call('incr', key)\n")
|
|
||||||
.append("if tonumber(current) == 1 then\n")
|
|
||||||
.append(" redis.call('expire', key, time)\n")
|
|
||||||
.append("end\n")
|
|
||||||
.append("return current;")
|
|
||||||
.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,52 +1,35 @@
|
|||||||
package com.ruoyi.framework.config;
|
package com.ruoyi.framework.config;
|
||||||
|
|
||||||
import com.ruoyi.framework.interceptor.RepeatSubmitInterceptor;
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
|
||||||
import org.springframework.context.annotation.Bean;
|
import org.springframework.context.annotation.Bean;
|
||||||
import org.springframework.context.annotation.Configuration;
|
import org.springframework.context.annotation.Configuration;
|
||||||
import org.springframework.web.cors.CorsConfiguration;
|
import org.springframework.web.cors.CorsConfiguration;
|
||||||
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
|
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
|
||||||
import org.springframework.web.filter.CorsFilter;
|
import org.springframework.web.filter.CorsFilter;
|
||||||
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
|
|
||||||
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
|
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
|
||||||
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
|
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 通用配置
|
* 通用配置
|
||||||
*
|
*
|
||||||
* @author ruoyi
|
* @author Lion Li
|
||||||
*/
|
*/
|
||||||
@Configuration
|
@Configuration
|
||||||
public class ResourcesConfig implements WebMvcConfigurer
|
public class ResourcesConfig implements WebMvcConfigurer {
|
||||||
{
|
|
||||||
@Autowired
|
|
||||||
private RepeatSubmitInterceptor repeatSubmitInterceptor;
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void addResourceHandlers(ResourceHandlerRegistry registry)
|
public void addResourceHandlers(ResourceHandlerRegistry registry) {
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 自定义拦截规则
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public void addInterceptors(InterceptorRegistry registry)
|
|
||||||
{
|
|
||||||
registry.addInterceptor(repeatSubmitInterceptor).addPathPatterns("/**");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 跨域配置
|
* 跨域配置
|
||||||
*/
|
*/
|
||||||
@Bean
|
@Bean
|
||||||
public CorsFilter corsFilter()
|
public CorsFilter corsFilter() {
|
||||||
{
|
|
||||||
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
|
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
|
||||||
CorsConfiguration config = new CorsConfiguration();
|
CorsConfiguration config = new CorsConfiguration();
|
||||||
config.setAllowCredentials(true);
|
config.setAllowCredentials(true);
|
||||||
// 设置访问源地址
|
// 设置访问源地址
|
||||||
config.addAllowedOriginPattern("*");
|
config.addAllowedOriginPattern("*");
|
||||||
// 设置访问源请求头
|
// 设置访问源请求头
|
||||||
config.addAllowedHeader("*");
|
config.addAllowedHeader("*");
|
||||||
// 设置访问源请求方法
|
// 设置访问源请求方法
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
package com.ruoyi.framework.config;
|
package com.ruoyi.framework.config;
|
||||||
|
|
||||||
|
import com.ruoyi.framework.config.properties.SecurityProperties;
|
||||||
import com.ruoyi.framework.security.filter.JwtAuthenticationTokenFilter;
|
import com.ruoyi.framework.security.filter.JwtAuthenticationTokenFilter;
|
||||||
import com.ruoyi.framework.security.handle.AuthenticationEntryPointImpl;
|
import com.ruoyi.framework.security.handle.AuthenticationEntryPointImpl;
|
||||||
import com.ruoyi.framework.security.handle.LogoutSuccessHandlerImpl;
|
import com.ruoyi.framework.security.handle.LogoutSuccessHandlerImpl;
|
||||||
@ -56,6 +57,9 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter
|
|||||||
@Autowired
|
@Autowired
|
||||||
private CorsFilter corsFilter;
|
private CorsFilter corsFilter;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private SecurityProperties securityProperties;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 解决 无法直接注入 AuthenticationManager
|
* 解决 无法直接注入 AuthenticationManager
|
||||||
*
|
*
|
||||||
@ -96,8 +100,6 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter
|
|||||||
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and()
|
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and()
|
||||||
// 过滤请求
|
// 过滤请求
|
||||||
.authorizeRequests()
|
.authorizeRequests()
|
||||||
// 对于登录login 注册register 验证码captchaImage 允许匿名访问
|
|
||||||
.antMatchers("/login", "/register", "/captchaImage").anonymous()
|
|
||||||
.antMatchers(
|
.antMatchers(
|
||||||
HttpMethod.GET,
|
HttpMethod.GET,
|
||||||
"/",
|
"/",
|
||||||
@ -106,19 +108,13 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter
|
|||||||
"/**/*.css",
|
"/**/*.css",
|
||||||
"/**/*.js"
|
"/**/*.js"
|
||||||
).permitAll()
|
).permitAll()
|
||||||
.antMatchers("/doc.html").anonymous()
|
.antMatchers(securityProperties.getAnonymous()).anonymous()
|
||||||
.antMatchers("/swagger-resources/**").anonymous()
|
.antMatchers(securityProperties.getPermitAll()).permitAll()
|
||||||
.antMatchers("/webjars/**").anonymous()
|
|
||||||
.antMatchers("/*/api-docs").anonymous()
|
|
||||||
.antMatchers("/druid/**").anonymous()
|
|
||||||
// Spring Boot Actuator 的安全配置
|
|
||||||
.antMatchers("/actuator").anonymous()
|
|
||||||
.antMatchers("/actuator/**").anonymous()
|
|
||||||
// 除上面外的所有请求全部需要鉴权认证
|
// 除上面外的所有请求全部需要鉴权认证
|
||||||
.anyRequest().authenticated()
|
.anyRequest().authenticated()
|
||||||
.and()
|
.and()
|
||||||
.headers().frameOptions().disable();
|
.headers().frameOptions().disable();
|
||||||
httpSecurity.logout().logoutUrl("/logout").logoutSuccessHandler(logoutSuccessHandler);
|
httpSecurity.logout().logoutUrl(securityProperties.getLogoutUrl()).logoutSuccessHandler(logoutSuccessHandler);
|
||||||
// 添加JWT filter
|
// 添加JWT filter
|
||||||
httpSecurity.addFilterBefore(authenticationTokenFilter, UsernamePasswordAuthenticationFilter.class);
|
httpSecurity.addFilterBefore(authenticationTokenFilter, UsernamePasswordAuthenticationFilter.class);
|
||||||
// 添加CORS filter
|
// 添加CORS filter
|
||||||
|
@ -1,32 +0,0 @@
|
|||||||
package com.ruoyi.framework.config;
|
|
||||||
|
|
||||||
import javax.servlet.http.HttpServletRequest;
|
|
||||||
import org.springframework.stereotype.Component;
|
|
||||||
import com.ruoyi.common.utils.ServletUtils;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 服务相关配置
|
|
||||||
*
|
|
||||||
* @author ruoyi
|
|
||||||
*/
|
|
||||||
@Component
|
|
||||||
public class ServerConfig
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* 获取完整的请求路径,包括:域名,端口,上下文访问路径
|
|
||||||
*
|
|
||||||
* @return 服务地址
|
|
||||||
*/
|
|
||||||
public String getUrl()
|
|
||||||
{
|
|
||||||
HttpServletRequest request = ServletUtils.getRequest();
|
|
||||||
return getDomain(request);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static String getDomain(HttpServletRequest request)
|
|
||||||
{
|
|
||||||
StringBuffer url = request.getRequestURL();
|
|
||||||
String contextPath = request.getServletContext().getContextPath();
|
|
||||||
return url.delete(url.length() - request.getRequestURI().length(), url.length()).append(contextPath).toString();
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,11 +1,12 @@
|
|||||||
package com.ruoyi.framework.config;
|
package com.ruoyi.framework.config;
|
||||||
|
|
||||||
import com.github.xiaoymin.knife4j.spring.annotations.EnableKnife4j;
|
import com.github.xiaoymin.knife4j.spring.annotations.EnableKnife4j;
|
||||||
|
import com.ruoyi.common.properties.TokenProperties;
|
||||||
|
import com.ruoyi.common.utils.StringUtils;
|
||||||
|
import com.ruoyi.common.utils.spring.SpringUtils;
|
||||||
import com.ruoyi.framework.config.properties.SwaggerProperties;
|
import com.ruoyi.framework.config.properties.SwaggerProperties;
|
||||||
import io.swagger.annotations.ApiOperation;
|
|
||||||
import io.swagger.models.auth.In;
|
import io.swagger.models.auth.In;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.context.annotation.Bean;
|
|
||||||
import org.springframework.context.annotation.Configuration;
|
import org.springframework.context.annotation.Configuration;
|
||||||
import springfox.documentation.builders.ApiInfoBuilder;
|
import springfox.documentation.builders.ApiInfoBuilder;
|
||||||
import springfox.documentation.builders.PathSelectors;
|
import springfox.documentation.builders.PathSelectors;
|
||||||
@ -15,6 +16,7 @@ import springfox.documentation.spi.DocumentationType;
|
|||||||
import springfox.documentation.spi.service.contexts.SecurityContext;
|
import springfox.documentation.spi.service.contexts.SecurityContext;
|
||||||
import springfox.documentation.spring.web.plugins.Docket;
|
import springfox.documentation.spring.web.plugins.Docket;
|
||||||
|
|
||||||
|
import javax.annotation.PostConstruct;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@ -27,82 +29,92 @@ import java.util.List;
|
|||||||
@EnableKnife4j
|
@EnableKnife4j
|
||||||
public class SwaggerConfig {
|
public class SwaggerConfig {
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private SwaggerProperties swaggerProperties;
|
private SwaggerProperties swaggerProperties;
|
||||||
|
|
||||||
/**
|
@Autowired
|
||||||
* 创建API
|
private TokenProperties tokenProperties;
|
||||||
*/
|
|
||||||
@Bean
|
|
||||||
public Docket createRestApi() {
|
|
||||||
return new Docket(DocumentationType.OAS_30)
|
|
||||||
.enable(swaggerProperties.getEnabled())
|
|
||||||
// 用来创建该API的基本信息,展示在文档的页面中(自定义展示的信息)
|
|
||||||
.apiInfo(apiInfo())
|
|
||||||
// 设置哪些接口暴露给Swagger展示
|
|
||||||
.select()
|
|
||||||
// 扫描所有有注解的api,用这种方式更灵活
|
|
||||||
.apis(RequestHandlerSelectors.withMethodAnnotation(ApiOperation.class))
|
|
||||||
// 扫描指定包中的swagger注解
|
|
||||||
// .apis(RequestHandlerSelectors.basePackage("com.ruoyi.project.tool.swagger"))
|
|
||||||
// 扫描所有 .apis(RequestHandlerSelectors.any())
|
|
||||||
.paths(PathSelectors.any())
|
|
||||||
.build()
|
|
||||||
/* 设置安全模式,swagger可以设置访问token */
|
|
||||||
.securitySchemes(securitySchemes())
|
|
||||||
.securityContexts(securityContexts())
|
|
||||||
.pathMapping(swaggerProperties.getPathMapping());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 安全模式,这里指定token通过Authorization头请求头传递
|
* 创建API
|
||||||
*/
|
*/
|
||||||
private List<SecurityScheme> securitySchemes() {
|
@PostConstruct
|
||||||
List<SecurityScheme> apiKeyList = new ArrayList<SecurityScheme>();
|
public void createRestApi() {
|
||||||
apiKeyList.add(new ApiKey("Authorization", "Authorization", In.HEADER.toValue()));
|
for (SwaggerProperties.Groups group : swaggerProperties.getGroups()) {
|
||||||
return apiKeyList;
|
String basePackage = group.getBasePackage();
|
||||||
}
|
Docket docket = new Docket(DocumentationType.OAS_30)
|
||||||
|
.enable(swaggerProperties.getEnabled())
|
||||||
|
// 用来创建该API的基本信息,展示在文档的页面中(自定义展示的信息)
|
||||||
|
.apiInfo(apiInfo())
|
||||||
|
// 设置哪些接口暴露给Swagger展示
|
||||||
|
.select()
|
||||||
|
// 扫描所有有注解的api,用这种方式更灵活
|
||||||
|
//.apis(RequestHandlerSelectors.withMethodAnnotation(ApiOperation.class))
|
||||||
|
// 扫描指定包中的swagger注解
|
||||||
|
.apis(RequestHandlerSelectors.basePackage(basePackage))
|
||||||
|
// 扫描所有 .apis(RequestHandlerSelectors.any())
|
||||||
|
.paths(PathSelectors.any())
|
||||||
|
.build()
|
||||||
|
.groupName(group.getName())
|
||||||
|
// 设置安全模式,swagger可以设置访问token
|
||||||
|
.securitySchemes(securitySchemes())
|
||||||
|
.securityContexts(securityContexts())
|
||||||
|
.pathMapping(swaggerProperties.getPathMapping());
|
||||||
|
String beanName = StringUtils.substringAfterLast(basePackage, ".") + "Docket";
|
||||||
|
SpringUtils.registerBean(beanName, docket);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 安全上下文
|
* 安全模式,这里指定token通过Authorization头请求头传递
|
||||||
*/
|
*/
|
||||||
private List<SecurityContext> securityContexts() {
|
private List<SecurityScheme> securitySchemes() {
|
||||||
List<SecurityContext> securityContexts = new ArrayList<>();
|
List<SecurityScheme> apiKeyList = new ArrayList<SecurityScheme>();
|
||||||
securityContexts.add(
|
String header = tokenProperties.getHeader();
|
||||||
SecurityContext.builder()
|
apiKeyList.add(new ApiKey(header, header, In.HEADER.toValue()));
|
||||||
.securityReferences(defaultAuth())
|
return apiKeyList;
|
||||||
.operationSelector(o -> o.requestMappingPattern().matches("/.*"))
|
}
|
||||||
.build());
|
|
||||||
return securityContexts;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 默认的安全上引用
|
* 安全上下文
|
||||||
*/
|
*/
|
||||||
private List<SecurityReference> defaultAuth() {
|
private List<SecurityContext> securityContexts() {
|
||||||
AuthorizationScope authorizationScope = new AuthorizationScope("global", "accessEverything");
|
List<SecurityContext> securityContexts = new ArrayList<>();
|
||||||
AuthorizationScope[] authorizationScopes = new AuthorizationScope[1];
|
securityContexts.add(
|
||||||
authorizationScopes[0] = authorizationScope;
|
SecurityContext.builder()
|
||||||
List<SecurityReference> securityReferences = new ArrayList<>();
|
.securityReferences(defaultAuth())
|
||||||
securityReferences.add(new SecurityReference("Authorization", authorizationScopes));
|
.operationSelector(o -> o.requestMappingPattern().matches("/.*"))
|
||||||
return securityReferences;
|
.build());
|
||||||
}
|
return securityContexts;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 添加摘要信息
|
* 默认的安全上引用
|
||||||
*/
|
*/
|
||||||
private ApiInfo apiInfo() {
|
private List<SecurityReference> defaultAuth() {
|
||||||
// 用ApiInfoBuilder进行定制
|
AuthorizationScope authorizationScope = new AuthorizationScope("global", "accessEverything");
|
||||||
SwaggerProperties.Contact contact = swaggerProperties.getContact();
|
AuthorizationScope[] authorizationScopes = new AuthorizationScope[1];
|
||||||
return new ApiInfoBuilder()
|
authorizationScopes[0] = authorizationScope;
|
||||||
// 设置标题
|
List<SecurityReference> securityReferences = new ArrayList<>();
|
||||||
.title(swaggerProperties.getTitle())
|
securityReferences.add(new SecurityReference(tokenProperties.getHeader(), authorizationScopes));
|
||||||
// 描述
|
return securityReferences;
|
||||||
.description(swaggerProperties.getDescription())
|
}
|
||||||
// 作者信息
|
|
||||||
.contact(new Contact(contact.getName(), contact.getUrl(), contact.getEmail()))
|
/**
|
||||||
// 版本
|
* 添加摘要信息
|
||||||
.version(swaggerProperties.getVersion())
|
*/
|
||||||
.build();
|
private ApiInfo apiInfo() {
|
||||||
}
|
// 用ApiInfoBuilder进行定制
|
||||||
|
SwaggerProperties.Contact contact = swaggerProperties.getContact();
|
||||||
|
return new ApiInfoBuilder()
|
||||||
|
// 设置标题
|
||||||
|
.title(swaggerProperties.getTitle())
|
||||||
|
// 描述
|
||||||
|
.description(swaggerProperties.getDescription())
|
||||||
|
// 作者信息
|
||||||
|
.contact(new Contact(contact.getName(), contact.getUrl(), contact.getEmail()))
|
||||||
|
// 版本
|
||||||
|
.version(swaggerProperties.getVersion())
|
||||||
|
.build();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,8 @@ package com.ruoyi.framework.config.properties;
|
|||||||
|
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import lombok.NoArgsConstructor;
|
import lombok.NoArgsConstructor;
|
||||||
|
import org.redisson.config.ReadMode;
|
||||||
|
import org.redisson.config.SubscriptionMode;
|
||||||
import org.redisson.config.TransportMode;
|
import org.redisson.config.TransportMode;
|
||||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
@ -38,6 +40,11 @@ public class RedissonProperties {
|
|||||||
*/
|
*/
|
||||||
private SingleServerConfig singleServerConfig;
|
private SingleServerConfig singleServerConfig;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 集群服务配置
|
||||||
|
*/
|
||||||
|
private ClusterServersConfig clusterServersConfig;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 缓存组
|
* 缓存组
|
||||||
*/
|
*/
|
||||||
@ -104,6 +111,102 @@ public class RedissonProperties {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Data
|
||||||
|
@NoArgsConstructor
|
||||||
|
public static class ClusterServersConfig {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 客户端名称
|
||||||
|
*/
|
||||||
|
private String clientName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* master最小空闲连接数
|
||||||
|
*/
|
||||||
|
private int masterConnectionMinimumIdleSize;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* master连接池大小
|
||||||
|
*/
|
||||||
|
private int masterConnectionPoolSize;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* slave最小空闲连接数
|
||||||
|
*/
|
||||||
|
private int slaveConnectionMinimumIdleSize;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* slave连接池大小
|
||||||
|
*/
|
||||||
|
private int slaveConnectionPoolSize;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 连接空闲超时,单位:毫秒
|
||||||
|
*/
|
||||||
|
private int idleConnectionTimeout;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ping超时
|
||||||
|
*/
|
||||||
|
private int pingConnectionInterval;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 命令等待超时,单位:毫秒
|
||||||
|
*/
|
||||||
|
private int timeout;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 如果尝试在此限制之内发送成功,则开始启用 timeout 计时。
|
||||||
|
*/
|
||||||
|
private int retryAttempts;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 命令重试发送时间间隔,单位:毫秒
|
||||||
|
*/
|
||||||
|
private int retryInterval;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 错误重试次数
|
||||||
|
*/
|
||||||
|
private int failedSlaveReconnectionInterval;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 发布和订阅连接池最小空闲连接数
|
||||||
|
*/
|
||||||
|
private int subscriptionConnectionMinimumIdleSize;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 发布和订阅连接池大小
|
||||||
|
*/
|
||||||
|
private int subscriptionConnectionPoolSize;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 单个连接最大订阅数量
|
||||||
|
*/
|
||||||
|
private int subscriptionsPerConnection;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 扫描间隔
|
||||||
|
*/
|
||||||
|
private int scanInterval;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* DNS监测时间间隔,单位:毫秒
|
||||||
|
*/
|
||||||
|
private int dnsMonitoringInterval;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 读取模式
|
||||||
|
*/
|
||||||
|
private ReadMode readMode;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 订阅模式
|
||||||
|
*/
|
||||||
|
private SubscriptionMode subscriptionMode;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
@Data
|
@Data
|
||||||
@NoArgsConstructor
|
@NoArgsConstructor
|
||||||
public static class CacheGroup {
|
public static class CacheGroup {
|
||||||
|
@ -17,6 +17,6 @@ public class RepeatSubmitProperties {
|
|||||||
/**
|
/**
|
||||||
* 间隔时间(毫秒)
|
* 间隔时间(毫秒)
|
||||||
*/
|
*/
|
||||||
private int intervalTime;
|
private int interval;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,32 @@
|
|||||||
|
package com.ruoyi.framework.config.properties;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Security 配置属性
|
||||||
|
*
|
||||||
|
* @author Lion Li
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@Component
|
||||||
|
@ConfigurationProperties(prefix = "security")
|
||||||
|
public class SecurityProperties {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 退出登录url
|
||||||
|
*/
|
||||||
|
private String logoutUrl;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 匿名放行路径
|
||||||
|
*/
|
||||||
|
private String[] anonymous;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户任意访问放行路径
|
||||||
|
*/
|
||||||
|
private String[] permitAll;
|
||||||
|
|
||||||
|
}
|
@ -5,6 +5,8 @@ import lombok.NoArgsConstructor;
|
|||||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* swagger 配置属性
|
* swagger 配置属性
|
||||||
*
|
*
|
||||||
@ -41,23 +43,46 @@ public class SwaggerProperties {
|
|||||||
*/
|
*/
|
||||||
private Contact contact;
|
private Contact contact;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 组配置
|
||||||
|
*/
|
||||||
|
private List<Groups> groups;
|
||||||
|
|
||||||
@Data
|
@Data
|
||||||
@NoArgsConstructor
|
@NoArgsConstructor
|
||||||
public static class Contact{
|
public static class Contact {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 联系人
|
* 联系人
|
||||||
**/
|
*/
|
||||||
private String name;
|
private String name;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 联系人url
|
* 联系人url
|
||||||
**/
|
*/
|
||||||
private String url;
|
private String url;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 联系人email
|
* 联系人email
|
||||||
**/
|
*/
|
||||||
private String email;
|
private String email;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Data
|
||||||
|
@NoArgsConstructor
|
||||||
|
public static class Groups {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 组名
|
||||||
|
*/
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 基础包路径
|
||||||
|
*/
|
||||||
|
private String basePackage;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,50 +0,0 @@
|
|||||||
package com.ruoyi.framework.interceptor;
|
|
||||||
|
|
||||||
import com.ruoyi.common.annotation.RepeatSubmit;
|
|
||||||
import com.ruoyi.common.core.domain.AjaxResult;
|
|
||||||
import com.ruoyi.common.utils.JsonUtils;
|
|
||||||
import com.ruoyi.common.utils.ServletUtils;
|
|
||||||
import org.springframework.stereotype.Component;
|
|
||||||
import org.springframework.web.method.HandlerMethod;
|
|
||||||
import org.springframework.web.servlet.HandlerInterceptor;
|
|
||||||
|
|
||||||
import javax.servlet.http.HttpServletRequest;
|
|
||||||
import javax.servlet.http.HttpServletResponse;
|
|
||||||
import java.lang.reflect.Method;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 防止重复提交拦截器
|
|
||||||
*
|
|
||||||
* 移除继承 HandlerInterceptorAdapter 过期类
|
|
||||||
* 改为实现 HandlerInterceptor 接口(官方推荐写法)
|
|
||||||
*
|
|
||||||
* @author Lion Li
|
|
||||||
*/
|
|
||||||
@Component
|
|
||||||
public abstract class RepeatSubmitInterceptor implements HandlerInterceptor {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
|
|
||||||
throws Exception {
|
|
||||||
if (handler instanceof HandlerMethod) {
|
|
||||||
HandlerMethod handlerMethod = (HandlerMethod) handler;
|
|
||||||
Method method = handlerMethod.getMethod();
|
|
||||||
RepeatSubmit annotation = method.getAnnotation(RepeatSubmit.class);
|
|
||||||
if (annotation != null) {
|
|
||||||
if (this.isRepeatSubmit(annotation, request)) {
|
|
||||||
AjaxResult ajaxResult = AjaxResult.error("不允许重复提交,请稍后再试");
|
|
||||||
ServletUtils.renderString(response, JsonUtils.toJsonString(ajaxResult));
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
} else {
|
|
||||||
return HandlerInterceptor.super.preHandle(request, response, handler);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 验证是否重复提交由子类实现具体的防重复提交的规则
|
|
||||||
*/
|
|
||||||
public abstract boolean isRepeatSubmit(RepeatSubmit annotation, HttpServletRequest request);
|
|
||||||
}
|
|
@ -1,114 +0,0 @@
|
|||||||
package com.ruoyi.framework.interceptor.impl;
|
|
||||||
|
|
||||||
import cn.hutool.core.convert.Convert;
|
|
||||||
import cn.hutool.core.io.IoUtil;
|
|
||||||
import com.ruoyi.common.annotation.RepeatSubmit;
|
|
||||||
import com.ruoyi.common.constant.Constants;
|
|
||||||
import com.ruoyi.common.filter.RepeatedlyRequestWrapper;
|
|
||||||
import com.ruoyi.common.utils.JsonUtils;
|
|
||||||
import com.ruoyi.common.utils.RedisUtils;
|
|
||||||
import com.ruoyi.common.utils.StringUtils;
|
|
||||||
import com.ruoyi.framework.config.properties.RepeatSubmitProperties;
|
|
||||||
import com.ruoyi.framework.config.properties.TokenProperties;
|
|
||||||
import com.ruoyi.framework.interceptor.RepeatSubmitInterceptor;
|
|
||||||
import lombok.RequiredArgsConstructor;
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
|
||||||
import org.springframework.stereotype.Component;
|
|
||||||
|
|
||||||
import javax.servlet.http.HttpServletRequest;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.concurrent.TimeUnit;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 判断请求url和数据是否和上一次相同,
|
|
||||||
* 如果和上次相同,则是重复提交表单。
|
|
||||||
*
|
|
||||||
* @author Lion Li
|
|
||||||
*/
|
|
||||||
@Slf4j
|
|
||||||
@RequiredArgsConstructor(onConstructor_ = @Autowired)
|
|
||||||
@Component
|
|
||||||
public class SameUrlDataInterceptor extends RepeatSubmitInterceptor {
|
|
||||||
public final String REPEAT_PARAMS = "repeatParams";
|
|
||||||
|
|
||||||
public final String REPEAT_TIME = "repeatTime";
|
|
||||||
|
|
||||||
private final TokenProperties tokenProperties;
|
|
||||||
private final RepeatSubmitProperties repeatSubmitProperties;
|
|
||||||
|
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
@Override
|
|
||||||
public boolean isRepeatSubmit(RepeatSubmit repeatSubmit, HttpServletRequest request) {
|
|
||||||
// 如果注解不为0 则使用注解数值
|
|
||||||
long intervalTime = repeatSubmitProperties.getIntervalTime();
|
|
||||||
if (repeatSubmit.intervalTime() > 0) {
|
|
||||||
intervalTime = repeatSubmit.timeUnit().toMillis(repeatSubmit.intervalTime());
|
|
||||||
}
|
|
||||||
String nowParams = "";
|
|
||||||
if (request instanceof RepeatedlyRequestWrapper) {
|
|
||||||
RepeatedlyRequestWrapper repeatedlyRequest = (RepeatedlyRequestWrapper) request;
|
|
||||||
try {
|
|
||||||
nowParams = IoUtil.readUtf8(repeatedlyRequest.getInputStream());
|
|
||||||
} catch (IOException e) {
|
|
||||||
log.warn("读取流出现问题!");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// body参数为空,获取Parameter的数据
|
|
||||||
if (StringUtils.isEmpty(nowParams)) {
|
|
||||||
nowParams = JsonUtils.toJsonString(request.getParameterMap());
|
|
||||||
}
|
|
||||||
Map<String, Object> nowDataMap = new HashMap<String, Object>();
|
|
||||||
nowDataMap.put(REPEAT_PARAMS, nowParams);
|
|
||||||
nowDataMap.put(REPEAT_TIME, System.currentTimeMillis());
|
|
||||||
|
|
||||||
// 请求地址(作为存放cache的key值)
|
|
||||||
String url = request.getRequestURI();
|
|
||||||
|
|
||||||
// 唯一值(没有消息头则使用请求地址)
|
|
||||||
String submitKey = request.getHeader(tokenProperties.getHeader());
|
|
||||||
if (StringUtils.isEmpty(submitKey)) {
|
|
||||||
submitKey = url;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 唯一标识(指定key + 消息头)
|
|
||||||
String cacheRepeatKey = Constants.REPEAT_SUBMIT_KEY + submitKey;
|
|
||||||
|
|
||||||
Object sessionObj = RedisUtils.getCacheObject(cacheRepeatKey);
|
|
||||||
if (sessionObj != null) {
|
|
||||||
Map<String, Object> sessionMap = (Map<String, Object>) sessionObj;
|
|
||||||
if (sessionMap.containsKey(url)) {
|
|
||||||
Map<String, Object> preDataMap = (Map<String, Object>) sessionMap.get(url);
|
|
||||||
if (compareParams(nowDataMap, preDataMap) && compareTime(nowDataMap, preDataMap, intervalTime)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Map<String, Object> cacheMap = new HashMap<String, Object>();
|
|
||||||
cacheMap.put(url, nowDataMap);
|
|
||||||
RedisUtils.setCacheObject(cacheRepeatKey, cacheMap, Convert.toInt(intervalTime), TimeUnit.MILLISECONDS);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 判断参数是否相同
|
|
||||||
*/
|
|
||||||
private boolean compareParams(Map<String, Object> nowMap, Map<String, Object> preMap) {
|
|
||||||
String nowParams = (String) nowMap.get(REPEAT_PARAMS);
|
|
||||||
String preParams = (String) preMap.get(REPEAT_PARAMS);
|
|
||||||
return nowParams.equals(preParams);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 判断两次间隔时间
|
|
||||||
*/
|
|
||||||
private boolean compareTime(Map<String, Object> nowMap, Map<String, Object> preMap, long intervalTime) {
|
|
||||||
long time1 = (Long) nowMap.get(REPEAT_TIME);
|
|
||||||
long time2 = (Long) preMap.get(REPEAT_TIME);
|
|
||||||
return (time1 - time2) < intervalTime;
|
|
||||||
}
|
|
||||||
}
|
|
@ -57,7 +57,7 @@ public class CreateAndUpdateMetaObjectHandler implements MetaObjectHandler {
|
|||||||
try {
|
try {
|
||||||
loginUser = SecurityUtils.getLoginUser();
|
loginUser = SecurityUtils.getLoginUser();
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
log.error("自动注入警告 => 用户未登录");
|
log.warn("自动注入警告 => 用户未登录");
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
return loginUser.getUsername();
|
return loginUser.getUsername();
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
package com.ruoyi.framework.security.filter;
|
package com.ruoyi.framework.security.filter;
|
||||||
|
|
||||||
import com.ruoyi.common.core.domain.model.LoginUser;
|
import com.ruoyi.common.core.domain.model.LoginUser;
|
||||||
|
import com.ruoyi.common.core.service.TokenService;
|
||||||
import com.ruoyi.common.utils.SecurityUtils;
|
import com.ruoyi.common.utils.SecurityUtils;
|
||||||
import com.ruoyi.common.utils.StringUtils;
|
import com.ruoyi.common.utils.StringUtils;
|
||||||
import com.ruoyi.framework.web.service.TokenService;
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
|
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
|
||||||
import org.springframework.security.core.context.SecurityContextHolder;
|
import org.springframework.security.core.context.SecurityContextHolder;
|
||||||
@ -33,8 +33,7 @@ public class JwtAuthenticationTokenFilter extends OncePerRequestFilter
|
|||||||
throws ServletException, IOException
|
throws ServletException, IOException
|
||||||
{
|
{
|
||||||
LoginUser loginUser = tokenService.getLoginUser(request);
|
LoginUser loginUser = tokenService.getLoginUser(request);
|
||||||
if (StringUtils.isNotNull(loginUser) && StringUtils.isNull(SecurityUtils.getAuthentication()))
|
if (StringUtils.isNotNull(loginUser) && StringUtils.isNull(SecurityUtils.getAuthentication())) {
|
||||||
{
|
|
||||||
tokenService.verifyToken(loginUser);
|
tokenService.verifyToken(loginUser);
|
||||||
UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(loginUser, null, loginUser.getAuthorities());
|
UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(loginUser, null, loginUser.getAuthorities());
|
||||||
authenticationToken.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
|
authenticationToken.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
|
||||||
|
@ -4,11 +4,11 @@ import cn.hutool.http.HttpStatus;
|
|||||||
import com.ruoyi.common.constant.Constants;
|
import com.ruoyi.common.constant.Constants;
|
||||||
import com.ruoyi.common.core.domain.AjaxResult;
|
import com.ruoyi.common.core.domain.AjaxResult;
|
||||||
import com.ruoyi.common.core.domain.model.LoginUser;
|
import com.ruoyi.common.core.domain.model.LoginUser;
|
||||||
|
import com.ruoyi.common.core.service.LogininforService;
|
||||||
|
import com.ruoyi.common.core.service.TokenService;
|
||||||
import com.ruoyi.common.utils.JsonUtils;
|
import com.ruoyi.common.utils.JsonUtils;
|
||||||
import com.ruoyi.common.utils.ServletUtils;
|
import com.ruoyi.common.utils.ServletUtils;
|
||||||
import com.ruoyi.common.utils.StringUtils;
|
import com.ruoyi.common.utils.StringUtils;
|
||||||
import com.ruoyi.framework.web.service.AsyncService;
|
|
||||||
import com.ruoyi.framework.web.service.TokenService;
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.context.annotation.Configuration;
|
import org.springframework.context.annotation.Configuration;
|
||||||
import org.springframework.security.core.Authentication;
|
import org.springframework.security.core.Authentication;
|
||||||
@ -31,7 +31,7 @@ public class LogoutSuccessHandlerImpl implements LogoutSuccessHandler {
|
|||||||
private TokenService tokenService;
|
private TokenService tokenService;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private AsyncService asyncService;
|
private LogininforService asyncService;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 退出处理
|
* 退出处理
|
||||||
|
@ -1,97 +0,0 @@
|
|||||||
package com.ruoyi.framework.web.service;
|
|
||||||
|
|
||||||
import com.ruoyi.common.utils.StringUtils;
|
|
||||||
import cn.hutool.http.useragent.UserAgent;
|
|
||||||
import cn.hutool.http.useragent.UserAgentUtil;
|
|
||||||
import com.ruoyi.common.constant.Constants;
|
|
||||||
import com.ruoyi.common.utils.ServletUtils;
|
|
||||||
import com.ruoyi.common.utils.ip.AddressUtils;
|
|
||||||
import com.ruoyi.system.domain.SysLogininfor;
|
|
||||||
import com.ruoyi.system.domain.SysOperLog;
|
|
||||||
import com.ruoyi.system.service.ISysLogininforService;
|
|
||||||
import com.ruoyi.system.service.ISysOperLogService;
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
|
||||||
import org.springframework.scheduling.annotation.Async;
|
|
||||||
import org.springframework.stereotype.Component;
|
|
||||||
|
|
||||||
import javax.servlet.http.HttpServletRequest;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 异步工厂(产生任务用)
|
|
||||||
*
|
|
||||||
* @author Lion Li
|
|
||||||
*/
|
|
||||||
@Slf4j(topic = "sys-user")
|
|
||||||
@Async
|
|
||||||
@Component
|
|
||||||
public class AsyncService {
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private ISysLogininforService iSysLogininforService;
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private ISysOperLogService iSysOperLogService;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 记录登录信息
|
|
||||||
*
|
|
||||||
* @param username 用户名
|
|
||||||
* @param status 状态
|
|
||||||
* @param message 消息
|
|
||||||
* @param args 列表
|
|
||||||
*/
|
|
||||||
public void recordLogininfor(final String username, final String status, final String message,
|
|
||||||
HttpServletRequest request, final Object... args) {
|
|
||||||
final UserAgent userAgent = UserAgentUtil.parse(request.getHeader("User-Agent"));
|
|
||||||
final String ip = ServletUtils.getClientIP(request);
|
|
||||||
|
|
||||||
String address = AddressUtils.getRealAddressByIP(ip);
|
|
||||||
StringBuilder s = new StringBuilder();
|
|
||||||
s.append(getBlock(ip));
|
|
||||||
s.append(address);
|
|
||||||
s.append(getBlock(username));
|
|
||||||
s.append(getBlock(status));
|
|
||||||
s.append(getBlock(message));
|
|
||||||
// 打印信息到日志
|
|
||||||
log.info(s.toString(), args);
|
|
||||||
// 获取客户端操作系统
|
|
||||||
String os = userAgent.getOs().getName();
|
|
||||||
// 获取客户端浏览器
|
|
||||||
String browser = userAgent.getBrowser().getName();
|
|
||||||
// 封装对象
|
|
||||||
SysLogininfor logininfor = new SysLogininfor();
|
|
||||||
logininfor.setUserName(username);
|
|
||||||
logininfor.setIpaddr(ip);
|
|
||||||
logininfor.setLoginLocation(address);
|
|
||||||
logininfor.setBrowser(browser);
|
|
||||||
logininfor.setOs(os);
|
|
||||||
logininfor.setMsg(message);
|
|
||||||
// 日志状态
|
|
||||||
if (StringUtils.equalsAny(status, Constants.LOGIN_SUCCESS, Constants.LOGOUT, Constants.REGISTER)) {
|
|
||||||
logininfor.setStatus(Constants.SUCCESS);
|
|
||||||
} else if (Constants.LOGIN_FAIL.equals(status)) {
|
|
||||||
logininfor.setStatus(Constants.FAIL);
|
|
||||||
}
|
|
||||||
// 插入数据
|
|
||||||
iSysLogininforService.insertLogininfor(logininfor);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 操作日志记录
|
|
||||||
*
|
|
||||||
* @param operLog 操作日志信息
|
|
||||||
*/
|
|
||||||
public void recordOper(final SysOperLog operLog) {
|
|
||||||
// 远程查询操作地点
|
|
||||||
operLog.setOperLocation(AddressUtils.getRealAddressByIP(operLog.getOperIp()));
|
|
||||||
iSysOperLogService.insertOperlog(operLog);
|
|
||||||
}
|
|
||||||
|
|
||||||
private String getBlock(Object msg) {
|
|
||||||
if (msg == null) {
|
|
||||||
msg = "";
|
|
||||||
}
|
|
||||||
return "[" + msg.toString() + "]";
|
|
||||||
}
|
|
||||||
}
|
|
@ -5,7 +5,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<artifactId>ruoyi-vue-plus</artifactId>
|
<artifactId>ruoyi-vue-plus</artifactId>
|
||||||
<groupId>com.ruoyi</groupId>
|
<groupId>com.ruoyi</groupId>
|
||||||
<version>3.1.0</version>
|
<version>3.2.0</version>
|
||||||
</parent>
|
</parent>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
@ -33,8 +33,7 @@ public class GenUtils
|
|||||||
/**
|
/**
|
||||||
* 初始化列属性字段
|
* 初始化列属性字段
|
||||||
*/
|
*/
|
||||||
public static void initColumnField(GenTableColumn column, GenTable table)
|
public static void initColumnField(GenTableColumn column, GenTable table) {
|
||||||
{
|
|
||||||
String dataType = getDbType(column.getColumnType());
|
String dataType = getDbType(column.getColumnType());
|
||||||
String columnName = column.getColumnName();
|
String columnName = column.getColumnName();
|
||||||
column.setTableId(table.getTableId());
|
column.setTableId(table.getTableId());
|
||||||
@ -44,48 +43,48 @@ public class GenUtils
|
|||||||
// 设置默认类型
|
// 设置默认类型
|
||||||
column.setJavaType(GenConstants.TYPE_STRING);
|
column.setJavaType(GenConstants.TYPE_STRING);
|
||||||
|
|
||||||
if (arraysContains(GenConstants.COLUMNTYPE_STR, dataType) || arraysContains(GenConstants.COLUMNTYPE_TEXT, dataType))
|
if (arraysContains(GenConstants.COLUMNTYPE_STR, dataType) || arraysContains(GenConstants.COLUMNTYPE_TEXT, dataType)) {
|
||||||
{
|
|
||||||
// 字符串长度超过500设置为文本域
|
// 字符串长度超过500设置为文本域
|
||||||
Integer columnLength = getColumnLength(column.getColumnType());
|
Integer columnLength = getColumnLength(column.getColumnType());
|
||||||
String htmlType = columnLength >= 500 || arraysContains(GenConstants.COLUMNTYPE_TEXT, dataType) ? GenConstants.HTML_TEXTAREA : GenConstants.HTML_INPUT;
|
String htmlType = columnLength >= 500 || arraysContains(GenConstants.COLUMNTYPE_TEXT, dataType) ? GenConstants.HTML_TEXTAREA : GenConstants.HTML_INPUT;
|
||||||
column.setHtmlType(htmlType);
|
column.setHtmlType(htmlType);
|
||||||
}
|
} else if (arraysContains(GenConstants.COLUMNTYPE_TIME, dataType)) {
|
||||||
else if (arraysContains(GenConstants.COLUMNTYPE_TIME, dataType))
|
|
||||||
{
|
|
||||||
column.setJavaType(GenConstants.TYPE_DATE);
|
column.setJavaType(GenConstants.TYPE_DATE);
|
||||||
column.setHtmlType(GenConstants.HTML_DATETIME);
|
column.setHtmlType(GenConstants.HTML_DATETIME);
|
||||||
}
|
} else if (arraysContains(GenConstants.COLUMNTYPE_NUMBER, dataType)) {
|
||||||
else if (arraysContains(GenConstants.COLUMNTYPE_NUMBER, dataType))
|
|
||||||
{
|
|
||||||
column.setHtmlType(GenConstants.HTML_INPUT);
|
column.setHtmlType(GenConstants.HTML_INPUT);
|
||||||
|
|
||||||
// 如果是浮点型 统一用BigDecimal
|
// 如果是浮点型 统一用BigDecimal
|
||||||
String[] str = StringUtils.split(StringUtils.substringBetween(column.getColumnType(), "(", ")"), ",");
|
String[] str = StringUtils.split(StringUtils.substringBetween(column.getColumnType(), "(", ")"), ",");
|
||||||
if (str != null && str.length == 2 && Integer.parseInt(str[1]) > 0)
|
if (str != null && str.length == 2 && Integer.parseInt(str[1]) > 0) {
|
||||||
{
|
|
||||||
column.setJavaType(GenConstants.TYPE_BIGDECIMAL);
|
column.setJavaType(GenConstants.TYPE_BIGDECIMAL);
|
||||||
}
|
}
|
||||||
// 如果是整形
|
// 如果是整形
|
||||||
else if (str != null && str.length == 1 && Integer.parseInt(str[0]) <= 10)
|
else if (str != null && str.length == 1 && Integer.parseInt(str[0]) <= 10) {
|
||||||
{
|
|
||||||
column.setJavaType(GenConstants.TYPE_INTEGER);
|
column.setJavaType(GenConstants.TYPE_INTEGER);
|
||||||
}
|
}
|
||||||
// 长整形
|
// 长整形
|
||||||
else
|
else {
|
||||||
{
|
|
||||||
column.setJavaType(GenConstants.TYPE_LONG);
|
column.setJavaType(GenConstants.TYPE_LONG);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 插入字段(默认所有字段都需要插入)
|
// 插入字段(默认所有字段都需要插入)
|
||||||
column.setIsInsert(GenConstants.REQUIRE);
|
// 主键不需要添加
|
||||||
|
if (!arraysContains(GenConstants.COLUMNNAME_NOT_ADD, columnName) && !column.isPk()) {
|
||||||
|
column.setIsInsert(GenConstants.REQUIRE);
|
||||||
|
}
|
||||||
// 编辑字段
|
// 编辑字段
|
||||||
if (!arraysContains(GenConstants.COLUMNNAME_NOT_EDIT, columnName) && !column.isPk())
|
// 编辑需要主键
|
||||||
|
if (!arraysContains(GenConstants.COLUMNNAME_NOT_EDIT, columnName))
|
||||||
{
|
{
|
||||||
column.setIsEdit(GenConstants.REQUIRE);
|
column.setIsEdit(GenConstants.REQUIRE);
|
||||||
}
|
}
|
||||||
|
// 编辑需要的设置必选
|
||||||
|
if (!arraysContains(GenConstants.COLUMNNAME_NOT_EDIT, columnName))
|
||||||
|
{
|
||||||
|
column.setIsRequired(GenConstants.REQUIRE);
|
||||||
|
}
|
||||||
// 列表字段
|
// 列表字段
|
||||||
if (!arraysContains(GenConstants.COLUMNNAME_NOT_LIST, columnName) && !column.isPk())
|
if (!arraysContains(GenConstants.COLUMNNAME_NOT_LIST, columnName) && !column.isPk())
|
||||||
{
|
{
|
||||||
|
@ -61,6 +61,7 @@ public class VelocityUtils
|
|||||||
velocityContext.put("permissionPrefix", getPermissionPrefix(moduleName, businessName));
|
velocityContext.put("permissionPrefix", getPermissionPrefix(moduleName, businessName));
|
||||||
velocityContext.put("columns", genTable.getColumns());
|
velocityContext.put("columns", genTable.getColumns());
|
||||||
velocityContext.put("table", genTable);
|
velocityContext.put("table", genTable);
|
||||||
|
velocityContext.put("dicts", getDicts(genTable));
|
||||||
setMenuVelocityContext(velocityContext, genTable);
|
setMenuVelocityContext(velocityContext, genTable);
|
||||||
if (GenConstants.TPL_TREE.equals(tplCategory))
|
if (GenConstants.TPL_TREE.equals(tplCategory))
|
||||||
{
|
{
|
||||||
@ -273,6 +274,27 @@ public class VelocityUtils
|
|||||||
return importList;
|
return importList;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据列类型获取字典组
|
||||||
|
*
|
||||||
|
* @param genTable 业务表对象
|
||||||
|
* @return 返回字典组
|
||||||
|
*/
|
||||||
|
public static String getDicts(GenTable genTable)
|
||||||
|
{
|
||||||
|
List<GenTableColumn> columns = genTable.getColumns();
|
||||||
|
List<String> dicts = new ArrayList<String>();
|
||||||
|
for (GenTableColumn column : columns)
|
||||||
|
{
|
||||||
|
if (!column.isSuperColumn() && StringUtils.isNotEmpty(column.getDictType()) && StringUtils.equalsAny(
|
||||||
|
column.getHtmlType(), new String[] { GenConstants.HTML_SELECT, GenConstants.HTML_RADIO }))
|
||||||
|
{
|
||||||
|
dicts.add("'" + column.getDictType() + "'");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return StringUtils.join(dicts, ", ");
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取权限前缀
|
* 获取权限前缀
|
||||||
*
|
*
|
||||||
|
@ -2,8 +2,6 @@ package ${packageName}.mapper;
|
|||||||
|
|
||||||
import ${packageName}.domain.${ClassName};
|
import ${packageName}.domain.${ClassName};
|
||||||
import com.ruoyi.common.core.mybatisplus.core.BaseMapperPlus;
|
import com.ruoyi.common.core.mybatisplus.core.BaseMapperPlus;
|
||||||
import com.ruoyi.common.core.mybatisplus.cache.MybatisPlusRedisCache;
|
|
||||||
import org.apache.ibatis.annotations.CacheNamespace;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ${functionName}Mapper接口
|
* ${functionName}Mapper接口
|
||||||
|
@ -79,7 +79,12 @@ public class ${ClassName}ServiceImpl extends ServicePlusImpl<${ClassName}Mapper,
|
|||||||
public Boolean insertByBo(${ClassName}Bo bo) {
|
public Boolean insertByBo(${ClassName}Bo bo) {
|
||||||
${ClassName} add = BeanUtil.toBean(bo, ${ClassName}.class);
|
${ClassName} add = BeanUtil.toBean(bo, ${ClassName}.class);
|
||||||
validEntityBeforeSave(add);
|
validEntityBeforeSave(add);
|
||||||
return save(add);
|
boolean flag = save(add);
|
||||||
|
#set($pk=$pkColumn.javaField.substring(0,1).toUpperCase() + ${pkColumn.javaField.substring(1)})
|
||||||
|
if (flag) {
|
||||||
|
bo.set$pk(add.get$pk());
|
||||||
|
}
|
||||||
|
return flag;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -27,14 +27,8 @@ public class ${ClassName}Vo {
|
|||||||
|
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
/**
|
|
||||||
* $pkColumn.columnComment
|
|
||||||
*/
|
|
||||||
@ApiModelProperty("$pkColumn.columnComment")
|
|
||||||
private ${pkColumn.javaType} ${pkColumn.javaField};
|
|
||||||
|
|
||||||
#foreach ($column in $columns)
|
#foreach ($column in $columns)
|
||||||
#if($column.isList && $column.isPk!=1)
|
#if($column.isList)
|
||||||
/**
|
/**
|
||||||
* $column.columnComment
|
* $column.columnComment
|
||||||
*/
|
*/
|
||||||
|
@ -25,10 +25,10 @@
|
|||||||
<el-form-item label="${comment}" prop="${column.javaField}">
|
<el-form-item label="${comment}" prop="${column.javaField}">
|
||||||
<el-select v-model="queryParams.${column.javaField}" placeholder="请选择${comment}" clearable size="small">
|
<el-select v-model="queryParams.${column.javaField}" placeholder="请选择${comment}" clearable size="small">
|
||||||
<el-option
|
<el-option
|
||||||
v-for="dict in ${column.javaField}Options"
|
v-for="dict in dict.type.${dictType}"
|
||||||
:key="dict.dictValue"
|
:key="dict.value"
|
||||||
:label="dict.dictLabel"
|
:label="dict.label"
|
||||||
:value="dict.dictValue"
|
:value="dict.value"
|
||||||
/>
|
/>
|
||||||
</el-select>
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
@ -108,7 +108,7 @@
|
|||||||
#elseif($column.list && $column.dictType && "" != $column.dictType)
|
#elseif($column.list && $column.dictType && "" != $column.dictType)
|
||||||
<el-table-column label="${comment}" align="center" prop="${javaField}">
|
<el-table-column label="${comment}" align="center" prop="${javaField}">
|
||||||
<template slot-scope="scope">
|
<template slot-scope="scope">
|
||||||
<dict-tag :options="${javaField}Options" :value="scope.row.${javaField}"/>
|
<dict-tag :options="dict.type.${column.dictType}" :value="scope.row.${javaField}"/>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
#elseif($column.list && "" != $javaField)
|
#elseif($column.list && "" != $javaField)
|
||||||
@ -183,10 +183,10 @@
|
|||||||
<el-form-item label="${comment}" prop="${field}">
|
<el-form-item label="${comment}" prop="${field}">
|
||||||
<el-select v-model="form.${field}" placeholder="请选择${comment}">
|
<el-select v-model="form.${field}" placeholder="请选择${comment}">
|
||||||
<el-option
|
<el-option
|
||||||
v-for="dict in ${field}Options"
|
v-for="dict in dict.type.${dictType}"
|
||||||
:key="dict.dictValue"
|
:key="dict.value"
|
||||||
:label="dict.dictLabel"
|
:label="dict.label"
|
||||||
#if($column.javaType == "Integer" || $column.javaType == "Long"):value="parseInt(dict.dictValue)"#else:value="dict.dictValue"#end
|
#if($column.javaType == "Integer" || $column.javaType == "Long"):value="parseInt(dict.value)"#else:value="dict.value"#end
|
||||||
|
|
||||||
></el-option>
|
></el-option>
|
||||||
</el-select>
|
</el-select>
|
||||||
@ -201,10 +201,10 @@
|
|||||||
<el-form-item label="${comment}">
|
<el-form-item label="${comment}">
|
||||||
<el-checkbox-group v-model="form.${field}">
|
<el-checkbox-group v-model="form.${field}">
|
||||||
<el-checkbox
|
<el-checkbox
|
||||||
v-for="dict in ${field}Options"
|
v-for="dict in dict.type.${dictType}"
|
||||||
:key="dict.dictValue"
|
:key="dict.value"
|
||||||
:label="dict.dictValue">
|
:label="dict.value">
|
||||||
{{dict.dictLabel}}
|
{{dict.label}}
|
||||||
</el-checkbox>
|
</el-checkbox>
|
||||||
</el-checkbox-group>
|
</el-checkbox-group>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
@ -218,11 +218,11 @@
|
|||||||
<el-form-item label="${comment}">
|
<el-form-item label="${comment}">
|
||||||
<el-radio-group v-model="form.${field}">
|
<el-radio-group v-model="form.${field}">
|
||||||
<el-radio
|
<el-radio
|
||||||
v-for="dict in ${field}Options"
|
v-for="dict in dict.type.${dictType}"
|
||||||
:key="dict.dictValue"
|
:key="dict.value"
|
||||||
#if($column.javaType == "Integer" || $column.javaType == "Long"):label="parseInt(dict.dictValue)"#else:label="dict.dictValue"#end
|
#if($column.javaType == "Integer" || $column.javaType == "Long"):label="parseInt(dict.value)"#else:label="dict.value"#end
|
||||||
|
|
||||||
>{{dict.dictLabel}}</el-radio>
|
>{{dict.label}}</el-radio>
|
||||||
</el-radio-group>
|
</el-radio-group>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
#elseif($column.htmlType == "radio" && $dictType)
|
#elseif($column.htmlType == "radio" && $dictType)
|
||||||
@ -263,6 +263,9 @@ import "@riophae/vue-treeselect/dist/vue-treeselect.css";
|
|||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: "${BusinessName}",
|
name: "${BusinessName}",
|
||||||
|
#if(${dicts} != '')
|
||||||
|
dicts: [${dicts}],
|
||||||
|
#end
|
||||||
components: {
|
components: {
|
||||||
Treeselect
|
Treeselect
|
||||||
},
|
},
|
||||||
@ -283,16 +286,7 @@ export default {
|
|||||||
// 是否显示弹出层
|
// 是否显示弹出层
|
||||||
open: false,
|
open: false,
|
||||||
#foreach ($column in $columns)
|
#foreach ($column in $columns)
|
||||||
#set($parentheseIndex=$column.columnComment.indexOf("("))
|
#if($column.htmlType == "datetime" && $column.queryType == "BETWEEN")
|
||||||
#if($parentheseIndex != -1)
|
|
||||||
#set($comment=$column.columnComment.substring(0, $parentheseIndex))
|
|
||||||
#else
|
|
||||||
#set($comment=$column.columnComment)
|
|
||||||
#end
|
|
||||||
#if(${column.dictType} && ${column.dictType} != '')
|
|
||||||
// $comment字典
|
|
||||||
${column.javaField}Options: [],
|
|
||||||
#elseif($column.htmlType == "datetime" && $column.queryType == "BETWEEN")
|
|
||||||
#set($AttrName=$column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)})
|
#set($AttrName=$column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)})
|
||||||
// $comment时间范围
|
// $comment时间范围
|
||||||
daterange${AttrName}: [],
|
daterange${AttrName}: [],
|
||||||
@ -330,13 +324,6 @@ export default {
|
|||||||
},
|
},
|
||||||
created() {
|
created() {
|
||||||
this.getList();
|
this.getList();
|
||||||
#foreach ($column in $columns)
|
|
||||||
#if(${column.dictType} && ${column.dictType} != '')
|
|
||||||
this.getDicts("${column.dictType}").then(response => {
|
|
||||||
this.${column.javaField}Options = response.data;
|
|
||||||
});
|
|
||||||
#end
|
|
||||||
#end
|
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
/** 查询${functionName}列表 */
|
/** 查询${functionName}列表 */
|
||||||
@ -464,7 +451,7 @@ export default {
|
|||||||
#end
|
#end
|
||||||
if (this.form.${pkColumn.javaField} != null) {
|
if (this.form.${pkColumn.javaField} != null) {
|
||||||
update${BusinessName}(this.form).then(response => {
|
update${BusinessName}(this.form).then(response => {
|
||||||
this.msgSuccess("修改成功");
|
this.#[[$modal]]#.msgSuccess("修改成功");
|
||||||
this.open = false;
|
this.open = false;
|
||||||
this.getList();
|
this.getList();
|
||||||
}).finally(() => {
|
}).finally(() => {
|
||||||
@ -472,7 +459,7 @@ export default {
|
|||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
add${BusinessName}(this.form).then(response => {
|
add${BusinessName}(this.form).then(response => {
|
||||||
this.msgSuccess("新增成功");
|
this.#[[$modal]]#.msgSuccess("新增成功");
|
||||||
this.open = false;
|
this.open = false;
|
||||||
this.getList();
|
this.getList();
|
||||||
}).finally(() => {
|
}).finally(() => {
|
||||||
@ -484,19 +471,15 @@ export default {
|
|||||||
},
|
},
|
||||||
/** 删除按钮操作 */
|
/** 删除按钮操作 */
|
||||||
handleDelete(row) {
|
handleDelete(row) {
|
||||||
this.$confirm('是否确认删除${functionName}编号为"' + row.${pkColumn.javaField} + '"的数据项?', "警告", {
|
this.#[[$modal]]#.confirm('是否确认删除${functionName}编号为"' + row.${pkColumn.javaField} + '"的数据项?').then(() => {
|
||||||
confirmButtonText: "确定",
|
this.loading = true;
|
||||||
cancelButtonText: "取消",
|
return del${BusinessName}(row.${pkColumn.javaField});
|
||||||
type: "warning"
|
}).then(() => {
|
||||||
}).then(() => {
|
this.loading = false;
|
||||||
this.loading = true;
|
this.getList();
|
||||||
return del${BusinessName}(row.${pkColumn.javaField});
|
this.#[[$modal]]#.msgSuccess("删除成功");
|
||||||
}).then(() => {
|
|
||||||
this.loading = false;
|
|
||||||
this.getList();
|
|
||||||
this.msgSuccess("删除成功");
|
|
||||||
}).finally(() => {
|
}).finally(() => {
|
||||||
this.loading = false;
|
this.loading = false;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -25,10 +25,10 @@
|
|||||||
<el-form-item label="${comment}" prop="${column.javaField}">
|
<el-form-item label="${comment}" prop="${column.javaField}">
|
||||||
<el-select v-model="queryParams.${column.javaField}" placeholder="请选择${comment}" clearable size="small">
|
<el-select v-model="queryParams.${column.javaField}" placeholder="请选择${comment}" clearable size="small">
|
||||||
<el-option
|
<el-option
|
||||||
v-for="dict in ${column.javaField}Options"
|
v-for="dict in dict.type.${dictType}"
|
||||||
:key="dict.dictValue"
|
:key="dict.value"
|
||||||
:label="dict.dictLabel"
|
:label="dict.label"
|
||||||
:value="dict.dictValue"
|
:value="dict.value"
|
||||||
/>
|
/>
|
||||||
</el-select>
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
@ -137,7 +137,7 @@
|
|||||||
#elseif($column.list && $column.dictType && "" != $column.dictType)
|
#elseif($column.list && $column.dictType && "" != $column.dictType)
|
||||||
<el-table-column label="${comment}" align="center" prop="${javaField}">
|
<el-table-column label="${comment}" align="center" prop="${javaField}">
|
||||||
<template slot-scope="scope">
|
<template slot-scope="scope">
|
||||||
<dict-tag :options="${javaField}Options" :value="scope.row.${javaField}"/>
|
<dict-tag :options="dict.type.${column.dictType}" :value="scope.row.${javaField}"/>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
#elseif($column.list && "" != $javaField)
|
#elseif($column.list && "" != $javaField)
|
||||||
@ -205,10 +205,10 @@
|
|||||||
<el-form-item label="${comment}" prop="${field}">
|
<el-form-item label="${comment}" prop="${field}">
|
||||||
<el-select v-model="form.${field}" placeholder="请选择${comment}">
|
<el-select v-model="form.${field}" placeholder="请选择${comment}">
|
||||||
<el-option
|
<el-option
|
||||||
v-for="dict in ${field}Options"
|
v-for="dict in dict.type.${dictType}"
|
||||||
:key="dict.dictValue"
|
:key="dict.value"
|
||||||
:label="dict.dictLabel"
|
:label="dict.label"
|
||||||
#if($column.javaType == "Integer" || $column.javaType == "Long"):value="parseInt(dict.dictValue)"#else:value="dict.dictValue"#end
|
#if($column.javaType == "Integer" || $column.javaType == "Long"):value="parseInt(dict.value)"#else:value="dict.value"#end
|
||||||
|
|
||||||
></el-option>
|
></el-option>
|
||||||
</el-select>
|
</el-select>
|
||||||
@ -223,10 +223,10 @@
|
|||||||
<el-form-item label="${comment}">
|
<el-form-item label="${comment}">
|
||||||
<el-checkbox-group v-model="form.${field}">
|
<el-checkbox-group v-model="form.${field}">
|
||||||
<el-checkbox
|
<el-checkbox
|
||||||
v-for="dict in ${field}Options"
|
v-for="dict in dict.type.${dictType}"
|
||||||
:key="dict.dictValue"
|
:key="dict.value"
|
||||||
:label="dict.dictValue">
|
:label="dict.value">
|
||||||
{{dict.dictLabel}}
|
{{dict.label}}
|
||||||
</el-checkbox>
|
</el-checkbox>
|
||||||
</el-checkbox-group>
|
</el-checkbox-group>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
@ -240,11 +240,11 @@
|
|||||||
<el-form-item label="${comment}">
|
<el-form-item label="${comment}">
|
||||||
<el-radio-group v-model="form.${field}">
|
<el-radio-group v-model="form.${field}">
|
||||||
<el-radio
|
<el-radio
|
||||||
v-for="dict in ${field}Options"
|
v-for="dict in dict.type.${dictType}"
|
||||||
:key="dict.dictValue"
|
:key="dict.value"
|
||||||
#if($column.javaType == "Integer" || $column.javaType == "Long"):label="parseInt(dict.dictValue)"#else:label="dict.dictValue"#end
|
#if($column.javaType == "Integer" || $column.javaType == "Long"):label="parseInt(dict.value)"#else:label="dict.value"#end
|
||||||
|
|
||||||
>{{dict.dictLabel}}</el-radio>
|
>{{dict.label}}</el-radio>
|
||||||
</el-radio-group>
|
</el-radio-group>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
#elseif($column.htmlType == "radio" && $dictType)
|
#elseif($column.htmlType == "radio" && $dictType)
|
||||||
@ -315,6 +315,9 @@ import { list${BusinessName}, get${BusinessName}, del${BusinessName}, add${Busin
|
|||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: "${BusinessName}",
|
name: "${BusinessName}",
|
||||||
|
#if(${dicts} != '')
|
||||||
|
dicts: [${dicts}],
|
||||||
|
#end
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
// 按钮loading
|
// 按钮loading
|
||||||
@ -348,16 +351,7 @@ export default {
|
|||||||
// 是否显示弹出层
|
// 是否显示弹出层
|
||||||
open: false,
|
open: false,
|
||||||
#foreach ($column in $columns)
|
#foreach ($column in $columns)
|
||||||
#set($parentheseIndex=$column.columnComment.indexOf("("))
|
#if($column.htmlType == "datetime" && $column.queryType == "BETWEEN")
|
||||||
#if($parentheseIndex != -1)
|
|
||||||
#set($comment=$column.columnComment.substring(0, $parentheseIndex))
|
|
||||||
#else
|
|
||||||
#set($comment=$column.columnComment)
|
|
||||||
#end
|
|
||||||
#if(${column.dictType} && ${column.dictType} != '')
|
|
||||||
// $comment字典
|
|
||||||
${column.javaField}Options: [],
|
|
||||||
#elseif($column.htmlType == "datetime" && $column.queryType == "BETWEEN")
|
|
||||||
#set($AttrName=$column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)})
|
#set($AttrName=$column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)})
|
||||||
// $comment时间范围
|
// $comment时间范围
|
||||||
daterange${AttrName}: [],
|
daterange${AttrName}: [],
|
||||||
@ -397,13 +391,6 @@ export default {
|
|||||||
},
|
},
|
||||||
created() {
|
created() {
|
||||||
this.getList();
|
this.getList();
|
||||||
#foreach ($column in $columns)
|
|
||||||
#if(${column.dictType} && ${column.dictType} != '')
|
|
||||||
this.getDicts("${column.dictType}").then(response => {
|
|
||||||
this.${column.javaField}Options = response.data;
|
|
||||||
});
|
|
||||||
#end
|
|
||||||
#end
|
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
/** 查询${functionName}列表 */
|
/** 查询${functionName}列表 */
|
||||||
@ -519,7 +506,7 @@ export default {
|
|||||||
#end
|
#end
|
||||||
if (this.form.${pkColumn.javaField} != null) {
|
if (this.form.${pkColumn.javaField} != null) {
|
||||||
update${BusinessName}(this.form).then(response => {
|
update${BusinessName}(this.form).then(response => {
|
||||||
this.msgSuccess("修改成功");
|
this.#[[$modal]]#.msgSuccess("修改成功");
|
||||||
this.open = false;
|
this.open = false;
|
||||||
this.getList();
|
this.getList();
|
||||||
}).finally(() => {
|
}).finally(() => {
|
||||||
@ -527,7 +514,7 @@ export default {
|
|||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
add${BusinessName}(this.form).then(response => {
|
add${BusinessName}(this.form).then(response => {
|
||||||
this.msgSuccess("新增成功");
|
this.#[[$modal]]#.msgSuccess("新增成功");
|
||||||
this.open = false;
|
this.open = false;
|
||||||
this.getList();
|
this.getList();
|
||||||
}).finally(() => {
|
}).finally(() => {
|
||||||
@ -540,19 +527,15 @@ export default {
|
|||||||
/** 删除按钮操作 */
|
/** 删除按钮操作 */
|
||||||
handleDelete(row) {
|
handleDelete(row) {
|
||||||
const ${pkColumn.javaField}s = row.${pkColumn.javaField} || this.ids;
|
const ${pkColumn.javaField}s = row.${pkColumn.javaField} || this.ids;
|
||||||
this.$confirm('是否确认删除${functionName}编号为"' + ${pkColumn.javaField}s + '"的数据项?', "警告", {
|
this.#[[$modal]]#.confirm('是否确认删除${functionName}编号为"' + ${pkColumn.javaField}s + '"的数据项?').then(() => {
|
||||||
confirmButtonText: "确定",
|
this.loading = true;
|
||||||
cancelButtonText: "取消",
|
return del${BusinessName}(${pkColumn.javaField}s);
|
||||||
type: "warning"
|
}).then(() => {
|
||||||
}).then(() => {
|
this.loading = false;
|
||||||
this.loading = true;
|
this.getList();
|
||||||
return del${BusinessName}(${pkColumn.javaField}s);
|
this.#[[$modal]]#.msgSuccess("删除成功");
|
||||||
}).then(() => {
|
|
||||||
this.loading = false;
|
|
||||||
this.getList();
|
|
||||||
this.msgSuccess("删除成功");
|
|
||||||
}).finally(() => {
|
}).finally(() => {
|
||||||
this.loading = false;
|
this.loading = false;
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
#if($table.sub)
|
#if($table.sub)
|
||||||
@ -574,7 +557,7 @@ export default {
|
|||||||
/** ${subTable.functionName}删除按钮操作 */
|
/** ${subTable.functionName}删除按钮操作 */
|
||||||
handleDelete${subClassName}() {
|
handleDelete${subClassName}() {
|
||||||
if (this.checked${subClassName}.length == 0) {
|
if (this.checked${subClassName}.length == 0) {
|
||||||
this.msgError("请先选择要删除的${subTable.functionName}数据");
|
this.#[[$modal]]#.msgError("请先选择要删除的${subTable.functionName}数据");
|
||||||
} else {
|
} else {
|
||||||
const ${subclassName}List = this.${subclassName}List;
|
const ${subclassName}List = this.${subclassName}List;
|
||||||
const checked${subClassName} = this.checked${subClassName};
|
const checked${subClassName} = this.checked${subClassName};
|
||||||
@ -590,7 +573,7 @@ export default {
|
|||||||
#end
|
#end
|
||||||
/** 导出按钮操作 */
|
/** 导出按钮操作 */
|
||||||
handleExport() {
|
handleExport() {
|
||||||
this.downLoadExcel('/${moduleName}/${businessName}/export', this.queryParams);
|
this.#[[$download]]#.excel('/${moduleName}/${businessName}/export', this.queryParams);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<artifactId>ruoyi-vue-plus</artifactId>
|
<artifactId>ruoyi-vue-plus</artifactId>
|
||||||
<groupId>com.ruoyi</groupId>
|
<groupId>com.ruoyi</groupId>
|
||||||
<version>3.1.0</version>
|
<version>3.2.0</version>
|
||||||
</parent>
|
</parent>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
@ -4,7 +4,7 @@ import java.util.Arrays;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 云存储常量
|
* 对象存储常量
|
||||||
*
|
*
|
||||||
* @author Lion Li
|
* @author Lion Li
|
||||||
*/
|
*/
|
||||||
@ -16,7 +16,7 @@ public class CloudConstant {
|
|||||||
public static final String SYS_OSS_KEY = "sys_oss:";
|
public static final String SYS_OSS_KEY = "sys_oss:";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 云存储配置KEY
|
* 对象存储配置KEY
|
||||||
*/
|
*/
|
||||||
public static final String CLOUD_STORAGE_CONFIG_KEY = "CloudStorageConfig";
|
public static final String CLOUD_STORAGE_CONFIG_KEY = "CloudStorageConfig";
|
||||||
|
|
||||||
|
@ -9,7 +9,7 @@ import lombok.AllArgsConstructor;
|
|||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 云存储服务商枚举
|
* 对象存储服务商枚举
|
||||||
*
|
*
|
||||||
* @author Lion Li
|
* @author Lion Li
|
||||||
*/
|
*/
|
||||||
|
@ -5,7 +5,7 @@ import lombok.Data;
|
|||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* OSS云存储 配置属性
|
* OSS对象存储 配置属性
|
||||||
*
|
*
|
||||||
* @author Lion Li
|
* @author Lion Li
|
||||||
*/
|
*/
|
||||||
|
@ -5,7 +5,7 @@ import com.ruoyi.oss.entity.UploadResult;
|
|||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 云存储策略
|
* 对象存储策略
|
||||||
*
|
*
|
||||||
* @author Lion Li
|
* @author Lion Li
|
||||||
*/
|
*/
|
||||||
|
@ -11,7 +11,7 @@ import com.ruoyi.oss.service.ICloudStorageStrategy;
|
|||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 云存储策略(支持七牛、阿里云、腾讯云、minio)
|
* 对象存储策略(支持七牛、阿里云、腾讯云、minio)
|
||||||
*
|
*
|
||||||
* @author Lion Li
|
* @author Lion Li
|
||||||
*/
|
*/
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<artifactId>ruoyi-vue-plus</artifactId>
|
<artifactId>ruoyi-vue-plus</artifactId>
|
||||||
<groupId>com.ruoyi</groupId>
|
<groupId>com.ruoyi</groupId>
|
||||||
<version>3.1.0</version>
|
<version>3.2.0</version>
|
||||||
</parent>
|
</parent>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<artifactId>ruoyi-vue-plus</artifactId>
|
<artifactId>ruoyi-vue-plus</artifactId>
|
||||||
<groupId>com.ruoyi</groupId>
|
<groupId>com.ruoyi</groupId>
|
||||||
<version>3.1.0</version>
|
<version>3.2.0</version>
|
||||||
</parent>
|
</parent>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
@ -9,7 +9,7 @@ import java.io.Serializable;
|
|||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* OSS云存储对象
|
* OSS对象存储对象
|
||||||
*
|
*
|
||||||
* @author Lion Li
|
* @author Lion Li
|
||||||
*/
|
*/
|
||||||
@ -23,7 +23,7 @@ public class SysOss implements Serializable {
|
|||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 云存储主键
|
* 对象存储主键
|
||||||
*/
|
*/
|
||||||
@TableId(value = "oss_id", type = IdType.AUTO)
|
@TableId(value = "oss_id", type = IdType.AUTO)
|
||||||
private Long ossId;
|
private Long ossId;
|
||||||
|
@ -9,7 +9,7 @@ import java.util.Date;
|
|||||||
import java.math.BigDecimal;
|
import java.math.BigDecimal;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 云存储配置对象 sys_oss_config
|
* 对象存储配置对象 sys_oss_config
|
||||||
*
|
*
|
||||||
* @author ruoyi
|
* @author ruoyi
|
||||||
* @date 2021-08-11
|
* @date 2021-08-11
|
||||||
|
@ -7,13 +7,13 @@ import lombok.Data;
|
|||||||
import lombok.EqualsAndHashCode;
|
import lombok.EqualsAndHashCode;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* OSS云存储分页查询对象 sys_oss
|
* OSS对象存储分页查询对象 sys_oss
|
||||||
*
|
*
|
||||||
* @author Lion Li
|
* @author Lion Li
|
||||||
*/
|
*/
|
||||||
@Data
|
@Data
|
||||||
@EqualsAndHashCode(callSuper = true)
|
@EqualsAndHashCode(callSuper = true)
|
||||||
@ApiModel("OSS云存储分页查询对象")
|
@ApiModel("OSS对象存储分页查询对象")
|
||||||
public class SysOssBo extends BaseEntity {
|
public class SysOssBo extends BaseEntity {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -13,7 +13,7 @@ import javax.validation.constraints.NotNull;
|
|||||||
import javax.validation.constraints.Size;
|
import javax.validation.constraints.Size;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 云存储配置业务对象 sys_oss_config
|
* 对象存储配置业务对象 sys_oss_config
|
||||||
*
|
*
|
||||||
* @author Lion Li
|
* @author Lion Li
|
||||||
* @author 孤舟烟雨
|
* @author 孤舟烟雨
|
||||||
@ -22,7 +22,7 @@ import javax.validation.constraints.Size;
|
|||||||
|
|
||||||
@Data
|
@Data
|
||||||
@EqualsAndHashCode(callSuper = true)
|
@EqualsAndHashCode(callSuper = true)
|
||||||
@ApiModel("云存储配置业务对象")
|
@ApiModel("对象存储配置业务对象")
|
||||||
public class SysOssConfigBo extends BaseEntity {
|
public class SysOssConfigBo extends BaseEntity {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -41,6 +41,11 @@ public class RouterVo {
|
|||||||
*/
|
*/
|
||||||
private String component;
|
private String component;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 路由参数:如 {"id": 1, "name": "ry"}
|
||||||
|
*/
|
||||||
|
private String query;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 当你一个路由下面的 children 声明的路由大于1个时,自动会变成嵌套的模式--如组件页面
|
* 当你一个路由下面的 children 声明的路由大于1个时,自动会变成嵌套的模式--如组件页面
|
||||||
*/
|
*/
|
||||||
|
@ -8,14 +8,14 @@ import lombok.Data;
|
|||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 云存储配置视图对象 sys_oss_config
|
* 对象存储配置视图对象 sys_oss_config
|
||||||
*
|
*
|
||||||
* @author Lion Li
|
* @author Lion Li
|
||||||
* @author 孤舟烟雨
|
* @author 孤舟烟雨
|
||||||
* @date 2021-08-13
|
* @date 2021-08-13
|
||||||
*/
|
*/
|
||||||
@Data
|
@Data
|
||||||
@ApiModel("云存储配置视图对象")
|
@ApiModel("对象存储配置视图对象")
|
||||||
@ExcelIgnoreUnannotated
|
@ExcelIgnoreUnannotated
|
||||||
public class SysOssConfigVo {
|
public class SysOssConfigVo {
|
||||||
|
|
||||||
|
@ -7,20 +7,20 @@ import lombok.Data;
|
|||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* OSS云存储视图对象 sys_oss
|
* OSS对象存储视图对象 sys_oss
|
||||||
*
|
*
|
||||||
* @author Lion Li
|
* @author Lion Li
|
||||||
*/
|
*/
|
||||||
@Data
|
@Data
|
||||||
@ApiModel("OSS云存储视图对象")
|
@ApiModel("OSS对象存储视图对象")
|
||||||
public class SysOssVo {
|
public class SysOssVo {
|
||||||
|
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 云存储主键
|
* 对象存储主键
|
||||||
*/
|
*/
|
||||||
@ApiModelProperty("云存储主键")
|
@ApiModelProperty("对象存储主键")
|
||||||
private Long ossId;
|
private Long ossId;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -4,7 +4,7 @@ import com.ruoyi.common.core.mybatisplus.core.BaseMapperPlus;
|
|||||||
import com.ruoyi.system.domain.SysOssConfig;
|
import com.ruoyi.system.domain.SysOssConfig;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 云存储配置Mapper接口
|
* 对象存储配置Mapper接口
|
||||||
*
|
*
|
||||||
* @author Lion Li
|
* @author Lion Li
|
||||||
* @author 孤舟烟雨
|
* @author 孤舟烟雨
|
||||||
|
@ -9,7 +9,7 @@ import com.ruoyi.system.domain.vo.SysOssConfigVo;
|
|||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 云存储配置Service接口
|
* 对象存储配置Service接口
|
||||||
*
|
*
|
||||||
* @author Lion Li
|
* @author Lion Li
|
||||||
* @author 孤舟烟雨
|
* @author 孤舟烟雨
|
||||||
@ -29,15 +29,15 @@ public interface ISysOssConfigService extends IServicePlus<SysOssConfig, SysOssC
|
|||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 根据新增业务对象插入云存储配置
|
* 根据新增业务对象插入对象存储配置
|
||||||
* @param bo 云存储配置新增业务对象
|
* @param bo 对象存储配置新增业务对象
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
Boolean insertByBo(SysOssConfigBo bo);
|
Boolean insertByBo(SysOssConfigBo bo);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 根据编辑业务对象修改云存储配置
|
* 根据编辑业务对象修改对象存储配置
|
||||||
* @param bo 云存储配置编辑业务对象
|
* @param bo 对象存储配置编辑业务对象
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
Boolean updateByBo(SysOssConfigBo bo);
|
Boolean updateByBo(SysOssConfigBo bo);
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
package com.ruoyi.framework.web.service;
|
package com.ruoyi.system.service;
|
||||||
|
|
||||||
import com.ruoyi.common.core.domain.entity.SysRole;
|
import com.ruoyi.common.core.domain.entity.SysRole;
|
||||||
import com.ruoyi.common.core.domain.model.LoginUser;
|
import com.ruoyi.common.core.domain.model.LoginUser;
|
||||||
@ -15,12 +15,15 @@ import java.util.Set;
|
|||||||
* @author ruoyi
|
* @author ruoyi
|
||||||
*/
|
*/
|
||||||
@Service("ss")
|
@Service("ss")
|
||||||
public class PermissionService
|
public class PermissionService {
|
||||||
{
|
/**
|
||||||
/** 所有权限标识 */
|
* 所有权限标识
|
||||||
|
*/
|
||||||
private static final String ALL_PERMISSION = "*:*:*";
|
private static final String ALL_PERMISSION = "*:*:*";
|
||||||
|
|
||||||
/** 管理员角色权限标识 */
|
/**
|
||||||
|
* 管理员角色权限标识
|
||||||
|
*/
|
||||||
private static final String SUPER_ADMIN = "admin";
|
private static final String SUPER_ADMIN = "admin";
|
||||||
|
|
||||||
private static final String ROLE_DELIMETER = ",";
|
private static final String ROLE_DELIMETER = ",";
|
||||||
@ -33,15 +36,12 @@ public class PermissionService
|
|||||||
* @param permission 权限字符串
|
* @param permission 权限字符串
|
||||||
* @return 用户是否具备某权限
|
* @return 用户是否具备某权限
|
||||||
*/
|
*/
|
||||||
public boolean hasPermi(String permission)
|
public boolean hasPermi(String permission) {
|
||||||
{
|
if (StringUtils.isEmpty(permission)) {
|
||||||
if (StringUtils.isEmpty(permission))
|
|
||||||
{
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
LoginUser loginUser = SecurityUtils.getLoginUser();
|
LoginUser loginUser = SecurityUtils.getLoginUser();
|
||||||
if (StringUtils.isNull(loginUser) || CollectionUtils.isEmpty(loginUser.getPermissions()))
|
if (StringUtils.isNull(loginUser) || CollectionUtils.isEmpty(loginUser.getPermissions())) {
|
||||||
{
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return hasPermissions(loginUser.getPermissions(), permission);
|
return hasPermissions(loginUser.getPermissions(), permission);
|
||||||
@ -53,8 +53,7 @@ public class PermissionService
|
|||||||
* @param permission 权限字符串
|
* @param permission 权限字符串
|
||||||
* @return 用户是否不具备某权限
|
* @return 用户是否不具备某权限
|
||||||
*/
|
*/
|
||||||
public boolean lacksPermi(String permission)
|
public boolean lacksPermi(String permission) {
|
||||||
{
|
|
||||||
return hasPermi(permission) != true;
|
return hasPermi(permission) != true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -64,22 +63,17 @@ public class PermissionService
|
|||||||
* @param permissions 以 PERMISSION_NAMES_DELIMETER 为分隔符的权限列表
|
* @param permissions 以 PERMISSION_NAMES_DELIMETER 为分隔符的权限列表
|
||||||
* @return 用户是否具有以下任意一个权限
|
* @return 用户是否具有以下任意一个权限
|
||||||
*/
|
*/
|
||||||
public boolean hasAnyPermi(String permissions)
|
public boolean hasAnyPermi(String permissions) {
|
||||||
{
|
if (StringUtils.isEmpty(permissions)) {
|
||||||
if (StringUtils.isEmpty(permissions))
|
|
||||||
{
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
LoginUser loginUser = SecurityUtils.getLoginUser();
|
LoginUser loginUser = SecurityUtils.getLoginUser();
|
||||||
if (StringUtils.isNull(loginUser) || CollectionUtils.isEmpty(loginUser.getPermissions()))
|
if (StringUtils.isNull(loginUser) || CollectionUtils.isEmpty(loginUser.getPermissions())) {
|
||||||
{
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
Set<String> authorities = loginUser.getPermissions();
|
Set<String> authorities = loginUser.getPermissions();
|
||||||
for (String permission : permissions.split(PERMISSION_DELIMETER))
|
for (String permission : permissions.split(PERMISSION_DELIMETER)) {
|
||||||
{
|
if (permission != null && hasPermissions(authorities, permission)) {
|
||||||
if (permission != null && hasPermissions(authorities, permission))
|
|
||||||
{
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -92,22 +86,17 @@ public class PermissionService
|
|||||||
* @param role 角色字符串
|
* @param role 角色字符串
|
||||||
* @return 用户是否具备某角色
|
* @return 用户是否具备某角色
|
||||||
*/
|
*/
|
||||||
public boolean hasRole(String role)
|
public boolean hasRole(String role) {
|
||||||
{
|
if (StringUtils.isEmpty(role)) {
|
||||||
if (StringUtils.isEmpty(role))
|
|
||||||
{
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
LoginUser loginUser = SecurityUtils.getLoginUser();
|
LoginUser loginUser = SecurityUtils.getLoginUser();
|
||||||
if (StringUtils.isNull(loginUser) || CollectionUtils.isEmpty(loginUser.getUser().getRoles()))
|
if (StringUtils.isNull(loginUser) || CollectionUtils.isEmpty(loginUser.getUser().getRoles())) {
|
||||||
{
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
for (SysRole sysRole : loginUser.getUser().getRoles())
|
for (SysRole sysRole : loginUser.getUser().getRoles()) {
|
||||||
{
|
|
||||||
String roleKey = sysRole.getRoleKey();
|
String roleKey = sysRole.getRoleKey();
|
||||||
if (SUPER_ADMIN.equals(roleKey) || roleKey.equals(StringUtils.trim(role)))
|
if (SUPER_ADMIN.equals(roleKey) || roleKey.equals(StringUtils.trim(role))) {
|
||||||
{
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -120,8 +109,7 @@ public class PermissionService
|
|||||||
* @param role 角色名称
|
* @param role 角色名称
|
||||||
* @return 用户是否不具备某角色
|
* @return 用户是否不具备某角色
|
||||||
*/
|
*/
|
||||||
public boolean lacksRole(String role)
|
public boolean lacksRole(String role) {
|
||||||
{
|
|
||||||
return hasRole(role) != true;
|
return hasRole(role) != true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -131,21 +119,16 @@ public class PermissionService
|
|||||||
* @param roles 以 ROLE_NAMES_DELIMETER 为分隔符的角色列表
|
* @param roles 以 ROLE_NAMES_DELIMETER 为分隔符的角色列表
|
||||||
* @return 用户是否具有以下任意一个角色
|
* @return 用户是否具有以下任意一个角色
|
||||||
*/
|
*/
|
||||||
public boolean hasAnyRoles(String roles)
|
public boolean hasAnyRoles(String roles) {
|
||||||
{
|
if (StringUtils.isEmpty(roles)) {
|
||||||
if (StringUtils.isEmpty(roles))
|
|
||||||
{
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
LoginUser loginUser = SecurityUtils.getLoginUser();
|
LoginUser loginUser = SecurityUtils.getLoginUser();
|
||||||
if (StringUtils.isNull(loginUser) || CollectionUtils.isEmpty(loginUser.getUser().getRoles()))
|
if (StringUtils.isNull(loginUser) || CollectionUtils.isEmpty(loginUser.getUser().getRoles())) {
|
||||||
{
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
for (String role : roles.split(ROLE_DELIMETER))
|
for (String role : roles.split(ROLE_DELIMETER)) {
|
||||||
{
|
if (hasRole(role)) {
|
||||||
if (hasRole(role))
|
|
||||||
{
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -156,11 +139,10 @@ public class PermissionService
|
|||||||
* 判断是否包含权限
|
* 判断是否包含权限
|
||||||
*
|
*
|
||||||
* @param permissions 权限列表
|
* @param permissions 权限列表
|
||||||
* @param permission 权限字符串
|
* @param permission 权限字符串
|
||||||
* @return 用户是否具备某权限
|
* @return 用户是否具备某权限
|
||||||
*/
|
*/
|
||||||
private boolean hasPermissions(Set<String> permissions, String permission)
|
private boolean hasPermissions(Set<String> permissions, String permission) {
|
||||||
{
|
|
||||||
return permissions.contains(ALL_PERMISSION) || permissions.contains(StringUtils.trim(permission));
|
return permissions.contains(ALL_PERMISSION) || permissions.contains(StringUtils.trim(permission));
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,8 +1,10 @@
|
|||||||
package com.ruoyi.framework.web.service;
|
package com.ruoyi.system.service;
|
||||||
|
|
||||||
import com.ruoyi.common.constant.Constants;
|
import com.ruoyi.common.constant.Constants;
|
||||||
import com.ruoyi.common.core.domain.entity.SysUser;
|
import com.ruoyi.common.core.domain.entity.SysUser;
|
||||||
import com.ruoyi.common.core.domain.model.LoginUser;
|
import com.ruoyi.common.core.domain.model.LoginUser;
|
||||||
|
import com.ruoyi.common.core.service.LogininforService;
|
||||||
|
import com.ruoyi.common.core.service.TokenService;
|
||||||
import com.ruoyi.common.exception.ServiceException;
|
import com.ruoyi.common.exception.ServiceException;
|
||||||
import com.ruoyi.common.exception.user.CaptchaException;
|
import com.ruoyi.common.exception.user.CaptchaException;
|
||||||
import com.ruoyi.common.exception.user.CaptchaExpireException;
|
import com.ruoyi.common.exception.user.CaptchaExpireException;
|
||||||
@ -11,14 +13,12 @@ import com.ruoyi.common.utils.DateUtils;
|
|||||||
import com.ruoyi.common.utils.MessageUtils;
|
import com.ruoyi.common.utils.MessageUtils;
|
||||||
import com.ruoyi.common.utils.RedisUtils;
|
import com.ruoyi.common.utils.RedisUtils;
|
||||||
import com.ruoyi.common.utils.ServletUtils;
|
import com.ruoyi.common.utils.ServletUtils;
|
||||||
import com.ruoyi.system.service.ISysConfigService;
|
|
||||||
import com.ruoyi.system.service.ISysUserService;
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.security.authentication.AuthenticationManager;
|
import org.springframework.security.authentication.AuthenticationManager;
|
||||||
import org.springframework.security.authentication.BadCredentialsException;
|
import org.springframework.security.authentication.BadCredentialsException;
|
||||||
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
|
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
|
||||||
import org.springframework.security.core.Authentication;
|
import org.springframework.security.core.Authentication;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
import javax.annotation.Resource;
|
import javax.annotation.Resource;
|
||||||
import javax.servlet.http.HttpServletRequest;
|
import javax.servlet.http.HttpServletRequest;
|
||||||
@ -28,66 +28,57 @@ import javax.servlet.http.HttpServletRequest;
|
|||||||
*
|
*
|
||||||
* @author ruoyi
|
* @author ruoyi
|
||||||
*/
|
*/
|
||||||
@Component
|
@Service
|
||||||
public class SysLoginService
|
public class SysLoginService {
|
||||||
{
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private TokenService tokenService;
|
private TokenService tokenService;
|
||||||
|
|
||||||
@Resource
|
@Resource
|
||||||
private AuthenticationManager authenticationManager;
|
private AuthenticationManager authenticationManager;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private ISysUserService userService;
|
private ISysUserService userService;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private ISysConfigService configService;
|
private ISysConfigService configService;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private AsyncService asyncService;
|
private LogininforService asyncService;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 登录验证
|
* 登录验证
|
||||||
*
|
*
|
||||||
* @param username 用户名
|
* @param username 用户名
|
||||||
* @param password 密码
|
* @param password 密码
|
||||||
* @param code 验证码
|
* @param code 验证码
|
||||||
* @param uuid 唯一标识
|
* @param uuid 唯一标识
|
||||||
* @return 结果
|
* @return 结果
|
||||||
*/
|
*/
|
||||||
public String login(String username, String password, String code, String uuid)
|
public String login(String username, String password, String code, String uuid) {
|
||||||
{
|
HttpServletRequest request = ServletUtils.getRequest();
|
||||||
HttpServletRequest request = ServletUtils.getRequest();
|
boolean captchaOnOff = configService.selectCaptchaOnOff();
|
||||||
boolean captchaOnOff = configService.selectCaptchaOnOff();
|
|
||||||
// 验证码开关
|
// 验证码开关
|
||||||
if (captchaOnOff)
|
if (captchaOnOff) {
|
||||||
{
|
|
||||||
validateCaptcha(username, code, uuid, request);
|
validateCaptcha(username, code, uuid, request);
|
||||||
}
|
}
|
||||||
// 用户验证
|
// 用户验证
|
||||||
Authentication authentication = null;
|
Authentication authentication = null;
|
||||||
try
|
try {
|
||||||
{
|
|
||||||
// 该方法会去调用UserDetailsServiceImpl.loadUserByUsername
|
// 该方法会去调用UserDetailsServiceImpl.loadUserByUsername
|
||||||
authentication = authenticationManager
|
authentication = authenticationManager
|
||||||
.authenticate(new UsernamePasswordAuthenticationToken(username, password));
|
.authenticate(new UsernamePasswordAuthenticationToken(username, password));
|
||||||
}
|
} catch (Exception e) {
|
||||||
catch (Exception e)
|
if (e instanceof BadCredentialsException) {
|
||||||
{
|
asyncService.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("user.password.not.match"), request);
|
||||||
if (e instanceof BadCredentialsException)
|
|
||||||
{
|
|
||||||
asyncService.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("user.password.not.match"), request);
|
|
||||||
throw new UserPasswordNotMatchException();
|
throw new UserPasswordNotMatchException();
|
||||||
}
|
} else {
|
||||||
else
|
asyncService.recordLogininfor(username, Constants.LOGIN_FAIL, e.getMessage(), request);
|
||||||
{
|
|
||||||
asyncService.recordLogininfor(username, Constants.LOGIN_FAIL, e.getMessage(), request);
|
|
||||||
throw new ServiceException(e.getMessage());
|
throw new ServiceException(e.getMessage());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
asyncService.recordLogininfor(username, Constants.LOGIN_SUCCESS, MessageUtils.message("user.login.success"), request);
|
asyncService.recordLogininfor(username, Constants.LOGIN_SUCCESS, MessageUtils.message("user.login.success"), request);
|
||||||
LoginUser loginUser = (LoginUser) authentication.getPrincipal();
|
LoginUser loginUser = (LoginUser) authentication.getPrincipal();
|
||||||
recordLoginInfo(loginUser.getUser());
|
recordLoginInfo(loginUser.getUserId());
|
||||||
// 生成token
|
// 生成token
|
||||||
return tokenService.createToken(loginUser);
|
return tokenService.createToken(loginUser);
|
||||||
}
|
}
|
||||||
@ -96,32 +87,34 @@ public class SysLoginService
|
|||||||
* 校验验证码
|
* 校验验证码
|
||||||
*
|
*
|
||||||
* @param username 用户名
|
* @param username 用户名
|
||||||
* @param code 验证码
|
* @param code 验证码
|
||||||
* @param uuid 唯一标识
|
* @param uuid 唯一标识
|
||||||
* @return 结果
|
* @return 结果
|
||||||
*/
|
*/
|
||||||
public void validateCaptcha(String username, String code, String uuid, HttpServletRequest request) {
|
public void validateCaptcha(String username, String code, String uuid, HttpServletRequest request) {
|
||||||
String verifyKey = Constants.CAPTCHA_CODE_KEY + uuid;
|
String verifyKey = Constants.CAPTCHA_CODE_KEY + uuid;
|
||||||
String captcha = RedisUtils.getCacheObject(verifyKey);
|
String captcha = RedisUtils.getCacheObject(verifyKey);
|
||||||
RedisUtils.deleteObject(verifyKey);
|
RedisUtils.deleteObject(verifyKey);
|
||||||
if (captcha == null) {
|
if (captcha == null) {
|
||||||
asyncService.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("user.jcaptcha.expire"), request);
|
asyncService.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("user.jcaptcha.expire"), request);
|
||||||
throw new CaptchaExpireException();
|
throw new CaptchaExpireException();
|
||||||
}
|
}
|
||||||
if (!code.equalsIgnoreCase(captcha)) {
|
if (!code.equalsIgnoreCase(captcha)) {
|
||||||
asyncService.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("user.jcaptcha.error"), request);
|
asyncService.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("user.jcaptcha.error"), request);
|
||||||
throw new CaptchaException();
|
throw new CaptchaException();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 记录登录信息
|
* 记录登录信息
|
||||||
|
*
|
||||||
|
* @param userId 用户ID
|
||||||
*/
|
*/
|
||||||
public void recordLoginInfo(SysUser user)
|
public void recordLoginInfo(Long userId) {
|
||||||
{
|
SysUser sysUser = new SysUser();
|
||||||
user.setLoginIp(ServletUtils.getClientIP());
|
sysUser.setUserId(userId);
|
||||||
user.setLoginDate(DateUtils.getNowDate());
|
sysUser.setLoginIp(ServletUtils.getClientIP());
|
||||||
user.setUpdateBy(user.getUserName());
|
sysUser.setLoginDate(DateUtils.getNowDate());
|
||||||
userService.updateUserProfile(user);
|
userService.updateUserProfile(sysUser);
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,21 +1,20 @@
|
|||||||
package com.ruoyi.framework.web.service;
|
package com.ruoyi.system.service;
|
||||||
|
|
||||||
|
import com.ruoyi.common.core.domain.entity.SysUser;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
|
||||||
import org.springframework.stereotype.Component;
|
|
||||||
import com.ruoyi.common.core.domain.entity.SysUser;
|
|
||||||
import com.ruoyi.system.service.ISysMenuService;
|
|
||||||
import com.ruoyi.system.service.ISysRoleService;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 用户权限处理
|
* 用户权限处理
|
||||||
*
|
*
|
||||||
* @author ruoyi
|
* @author ruoyi
|
||||||
*/
|
*/
|
||||||
@Component
|
@Service
|
||||||
public class SysPermissionService
|
public class SysPermissionService {
|
||||||
{
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private ISysRoleService roleService;
|
private ISysRoleService roleService;
|
||||||
|
|
||||||
@ -28,16 +27,12 @@ public class SysPermissionService
|
|||||||
* @param user 用户信息
|
* @param user 用户信息
|
||||||
* @return 角色权限信息
|
* @return 角色权限信息
|
||||||
*/
|
*/
|
||||||
public Set<String> getRolePermission(SysUser user)
|
public Set<String> getRolePermission(SysUser user) {
|
||||||
{
|
|
||||||
Set<String> roles = new HashSet<String>();
|
Set<String> roles = new HashSet<String>();
|
||||||
// 管理员拥有所有权限
|
// 管理员拥有所有权限
|
||||||
if (user.isAdmin())
|
if (user.isAdmin()) {
|
||||||
{
|
|
||||||
roles.add("admin");
|
roles.add("admin");
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
roles.addAll(roleService.selectRolePermissionByUserId(user.getUserId()));
|
roles.addAll(roleService.selectRolePermissionByUserId(user.getUserId()));
|
||||||
}
|
}
|
||||||
return roles;
|
return roles;
|
||||||
@ -49,16 +44,12 @@ public class SysPermissionService
|
|||||||
* @param user 用户信息
|
* @param user 用户信息
|
||||||
* @return 菜单权限信息
|
* @return 菜单权限信息
|
||||||
*/
|
*/
|
||||||
public Set<String> getMenuPermission(SysUser user)
|
public Set<String> getMenuPermission(SysUser user) {
|
||||||
{
|
|
||||||
Set<String> perms = new HashSet<String>();
|
Set<String> perms = new HashSet<String>();
|
||||||
// 管理员拥有所有权限
|
// 管理员拥有所有权限
|
||||||
if (user.isAdmin())
|
if (user.isAdmin()) {
|
||||||
{
|
|
||||||
perms.add("*:*:*");
|
perms.add("*:*:*");
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
perms.addAll(menuService.selectMenuPermsByUserId(user.getUserId()));
|
perms.addAll(menuService.selectMenuPermsByUserId(user.getUserId()));
|
||||||
}
|
}
|
||||||
return perms;
|
return perms;
|
@ -1,84 +1,67 @@
|
|||||||
package com.ruoyi.framework.web.service;
|
package com.ruoyi.system.service;
|
||||||
|
|
||||||
import com.ruoyi.common.constant.Constants;
|
import com.ruoyi.common.constant.Constants;
|
||||||
import com.ruoyi.common.constant.UserConstants;
|
import com.ruoyi.common.constant.UserConstants;
|
||||||
import com.ruoyi.common.core.domain.entity.SysUser;
|
import com.ruoyi.common.core.domain.entity.SysUser;
|
||||||
import com.ruoyi.common.core.domain.model.RegisterBody;
|
import com.ruoyi.common.core.domain.model.RegisterBody;
|
||||||
|
import com.ruoyi.common.core.service.LogininforService;
|
||||||
import com.ruoyi.common.exception.user.CaptchaException;
|
import com.ruoyi.common.exception.user.CaptchaException;
|
||||||
import com.ruoyi.common.exception.user.CaptchaExpireException;
|
import com.ruoyi.common.exception.user.CaptchaExpireException;
|
||||||
import com.ruoyi.common.utils.*;
|
import com.ruoyi.common.utils.*;
|
||||||
import com.ruoyi.system.service.ISysConfigService;
|
|
||||||
import com.ruoyi.system.service.ISysUserService;
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 注册校验方法
|
* 注册校验方法
|
||||||
*
|
*
|
||||||
* @author ruoyi
|
* @author ruoyi
|
||||||
*/
|
*/
|
||||||
@Component
|
@Service
|
||||||
public class SysRegisterService
|
public class SysRegisterService {
|
||||||
{
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private ISysUserService userService;
|
private ISysUserService userService;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private ISysConfigService configService;
|
private ISysConfigService configService;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private AsyncService asyncService;
|
private LogininforService asyncService;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 注册
|
* 注册
|
||||||
*/
|
*/
|
||||||
public String register(RegisterBody registerBody)
|
public String register(RegisterBody registerBody) {
|
||||||
{
|
|
||||||
String msg = "", username = registerBody.getUsername(), password = registerBody.getPassword();
|
String msg = "", username = registerBody.getUsername(), password = registerBody.getPassword();
|
||||||
|
|
||||||
boolean captchaOnOff = configService.selectCaptchaOnOff();
|
boolean captchaOnOff = configService.selectCaptchaOnOff();
|
||||||
// 验证码开关
|
// 验证码开关
|
||||||
if (captchaOnOff)
|
if (captchaOnOff) {
|
||||||
{
|
|
||||||
validateCaptcha(username, registerBody.getCode(), registerBody.getUuid());
|
validateCaptcha(username, registerBody.getCode(), registerBody.getUuid());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (StringUtils.isEmpty(username))
|
if (StringUtils.isEmpty(username)) {
|
||||||
{
|
|
||||||
msg = "用户名不能为空";
|
msg = "用户名不能为空";
|
||||||
}
|
} else if (StringUtils.isEmpty(password)) {
|
||||||
else if (StringUtils.isEmpty(password))
|
|
||||||
{
|
|
||||||
msg = "用户密码不能为空";
|
msg = "用户密码不能为空";
|
||||||
}
|
} else if (username.length() < UserConstants.USERNAME_MIN_LENGTH
|
||||||
else if (username.length() < UserConstants.USERNAME_MIN_LENGTH
|
|| username.length() > UserConstants.USERNAME_MAX_LENGTH) {
|
||||||
|| username.length() > UserConstants.USERNAME_MAX_LENGTH)
|
|
||||||
{
|
|
||||||
msg = "账户长度必须在2到20个字符之间";
|
msg = "账户长度必须在2到20个字符之间";
|
||||||
}
|
} else if (password.length() < UserConstants.PASSWORD_MIN_LENGTH
|
||||||
else if (password.length() < UserConstants.PASSWORD_MIN_LENGTH
|
|| password.length() > UserConstants.PASSWORD_MAX_LENGTH) {
|
||||||
|| password.length() > UserConstants.PASSWORD_MAX_LENGTH)
|
|
||||||
{
|
|
||||||
msg = "密码长度必须在5到20个字符之间";
|
msg = "密码长度必须在5到20个字符之间";
|
||||||
}
|
} else if (UserConstants.NOT_UNIQUE.equals(userService.checkUserNameUnique(username))) {
|
||||||
else if (UserConstants.NOT_UNIQUE.equals(userService.checkUserNameUnique(username)))
|
|
||||||
{
|
|
||||||
msg = "保存用户'" + username + "'失败,注册账号已存在";
|
msg = "保存用户'" + username + "'失败,注册账号已存在";
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
SysUser sysUser = new SysUser();
|
SysUser sysUser = new SysUser();
|
||||||
sysUser.setUserName(username);
|
sysUser.setUserName(username);
|
||||||
sysUser.setNickName(username);
|
sysUser.setNickName(username);
|
||||||
sysUser.setPassword(SecurityUtils.encryptPassword(registerBody.getPassword()));
|
sysUser.setPassword(SecurityUtils.encryptPassword(registerBody.getPassword()));
|
||||||
boolean regFlag = userService.registerUser(sysUser);
|
boolean regFlag = userService.registerUser(sysUser);
|
||||||
if (!regFlag)
|
if (!regFlag) {
|
||||||
{
|
|
||||||
msg = "注册失败,请联系系统管理人员";
|
msg = "注册失败,请联系系统管理人员";
|
||||||
}
|
} else {
|
||||||
else
|
asyncService.recordLogininfor(username, Constants.REGISTER,
|
||||||
{
|
|
||||||
asyncService.recordLogininfor(username, Constants.REGISTER,
|
|
||||||
MessageUtils.message("user.register.success"), ServletUtils.getRequest());
|
MessageUtils.message("user.register.success"), ServletUtils.getRequest());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -89,21 +72,18 @@ public class SysRegisterService
|
|||||||
* 校验验证码
|
* 校验验证码
|
||||||
*
|
*
|
||||||
* @param username 用户名
|
* @param username 用户名
|
||||||
* @param code 验证码
|
* @param code 验证码
|
||||||
* @param uuid 唯一标识
|
* @param uuid 唯一标识
|
||||||
* @return 结果
|
* @return 结果
|
||||||
*/
|
*/
|
||||||
public void validateCaptcha(String username, String code, String uuid)
|
public void validateCaptcha(String username, String code, String uuid) {
|
||||||
{
|
|
||||||
String verifyKey = Constants.CAPTCHA_CODE_KEY + uuid;
|
String verifyKey = Constants.CAPTCHA_CODE_KEY + uuid;
|
||||||
String captcha = RedisUtils.getCacheObject(verifyKey);
|
String captcha = RedisUtils.getCacheObject(verifyKey);
|
||||||
RedisUtils.deleteObject(verifyKey);
|
RedisUtils.deleteObject(verifyKey);
|
||||||
if (captcha == null)
|
if (captcha == null) {
|
||||||
{
|
|
||||||
throw new CaptchaExpireException();
|
throw new CaptchaExpireException();
|
||||||
}
|
}
|
||||||
if (!code.equalsIgnoreCase(captcha))
|
if (!code.equalsIgnoreCase(captcha)) {
|
||||||
{
|
|
||||||
throw new CaptchaException();
|
throw new CaptchaException();
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,15 +1,24 @@
|
|||||||
package com.ruoyi.system.service.impl;
|
package com.ruoyi.system.service.impl;
|
||||||
|
|
||||||
|
import cn.hutool.http.useragent.UserAgent;
|
||||||
|
import cn.hutool.http.useragent.UserAgentUtil;
|
||||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||||
|
import com.ruoyi.common.constant.Constants;
|
||||||
import com.ruoyi.common.core.mybatisplus.core.ServicePlusImpl;
|
import com.ruoyi.common.core.mybatisplus.core.ServicePlusImpl;
|
||||||
import com.ruoyi.common.core.page.TableDataInfo;
|
import com.ruoyi.common.core.page.TableDataInfo;
|
||||||
|
import com.ruoyi.common.core.service.LogininforService;
|
||||||
import com.ruoyi.common.utils.PageUtils;
|
import com.ruoyi.common.utils.PageUtils;
|
||||||
|
import com.ruoyi.common.utils.ServletUtils;
|
||||||
import com.ruoyi.common.utils.StringUtils;
|
import com.ruoyi.common.utils.StringUtils;
|
||||||
|
import com.ruoyi.common.utils.ip.AddressUtils;
|
||||||
import com.ruoyi.system.domain.SysLogininfor;
|
import com.ruoyi.system.domain.SysLogininfor;
|
||||||
import com.ruoyi.system.mapper.SysLogininforMapper;
|
import com.ruoyi.system.mapper.SysLogininforMapper;
|
||||||
import com.ruoyi.system.service.ISysLogininforService;
|
import com.ruoyi.system.service.ISysLogininforService;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.scheduling.annotation.Async;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@ -20,8 +29,62 @@ import java.util.Map;
|
|||||||
*
|
*
|
||||||
* @author ruoyi
|
* @author ruoyi
|
||||||
*/
|
*/
|
||||||
|
@Slf4j
|
||||||
@Service
|
@Service
|
||||||
public class SysLogininforServiceImpl extends ServicePlusImpl<SysLogininforMapper, SysLogininfor, SysLogininfor> implements ISysLogininforService {
|
public class SysLogininforServiceImpl extends ServicePlusImpl<SysLogininforMapper, SysLogininfor, SysLogininfor> implements ISysLogininforService, LogininforService {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 记录登录信息
|
||||||
|
*
|
||||||
|
* @param username 用户名
|
||||||
|
* @param status 状态
|
||||||
|
* @param message 消息
|
||||||
|
* @param args 列表
|
||||||
|
*/
|
||||||
|
@Async
|
||||||
|
@Override
|
||||||
|
public void recordLogininfor(final String username, final String status, final String message,
|
||||||
|
HttpServletRequest request, final Object... args) {
|
||||||
|
final UserAgent userAgent = UserAgentUtil.parse(request.getHeader("User-Agent"));
|
||||||
|
final String ip = ServletUtils.getClientIP(request);
|
||||||
|
|
||||||
|
String address = AddressUtils.getRealAddressByIP(ip);
|
||||||
|
StringBuilder s = new StringBuilder();
|
||||||
|
s.append(getBlock(ip));
|
||||||
|
s.append(address);
|
||||||
|
s.append(getBlock(username));
|
||||||
|
s.append(getBlock(status));
|
||||||
|
s.append(getBlock(message));
|
||||||
|
// 打印信息到日志
|
||||||
|
log.info(s.toString(), args);
|
||||||
|
// 获取客户端操作系统
|
||||||
|
String os = userAgent.getOs().getName();
|
||||||
|
// 获取客户端浏览器
|
||||||
|
String browser = userAgent.getBrowser().getName();
|
||||||
|
// 封装对象
|
||||||
|
SysLogininfor logininfor = new SysLogininfor();
|
||||||
|
logininfor.setUserName(username);
|
||||||
|
logininfor.setIpaddr(ip);
|
||||||
|
logininfor.setLoginLocation(address);
|
||||||
|
logininfor.setBrowser(browser);
|
||||||
|
logininfor.setOs(os);
|
||||||
|
logininfor.setMsg(message);
|
||||||
|
// 日志状态
|
||||||
|
if (StringUtils.equalsAny(status, Constants.LOGIN_SUCCESS, Constants.LOGOUT, Constants.REGISTER)) {
|
||||||
|
logininfor.setStatus(Constants.SUCCESS);
|
||||||
|
} else if (Constants.LOGIN_FAIL.equals(status)) {
|
||||||
|
logininfor.setStatus(Constants.FAIL);
|
||||||
|
}
|
||||||
|
// 插入数据
|
||||||
|
insertLogininfor(logininfor);
|
||||||
|
}
|
||||||
|
|
||||||
|
private String getBlock(Object msg) {
|
||||||
|
if (msg == null) {
|
||||||
|
msg = "";
|
||||||
|
}
|
||||||
|
return "[" + msg.toString() + "]";
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public TableDataInfo<SysLogininfor> selectPageLogininforList(SysLogininfor logininfor) {
|
public TableDataInfo<SysLogininfor> selectPageLogininforList(SysLogininfor logininfor) {
|
||||||
|
@ -135,6 +135,7 @@ public class SysMenuServiceImpl extends ServicePlusImpl<SysMenuMapper, SysMenu,
|
|||||||
router.setName(getRouteName(menu));
|
router.setName(getRouteName(menu));
|
||||||
router.setPath(getRouterPath(menu));
|
router.setPath(getRouterPath(menu));
|
||||||
router.setComponent(getComponent(menu));
|
router.setComponent(getComponent(menu));
|
||||||
|
router.setQuery(menu.getQuery());
|
||||||
router.setMeta(new MetaVo(menu.getMenuName(), menu.getIcon(), StringUtils.equals("1", menu.getIsCache()), menu.getPath()));
|
router.setMeta(new MetaVo(menu.getMenuName(), menu.getIcon(), StringUtils.equals("1", menu.getIsCache()), menu.getPath()));
|
||||||
List<SysMenu> cMenus = menu.getChildren();
|
List<SysMenu> cMenus = menu.getChildren();
|
||||||
if (!cMenus.isEmpty() && UserConstants.TYPE_DIR.equals(menu.getMenuType())) {
|
if (!cMenus.isEmpty() && UserConstants.TYPE_DIR.equals(menu.getMenuType())) {
|
||||||
|
@ -1,14 +1,19 @@
|
|||||||
package com.ruoyi.system.service.impl;
|
package com.ruoyi.system.service.impl;
|
||||||
|
|
||||||
|
import cn.hutool.core.bean.BeanUtil;
|
||||||
import cn.hutool.core.util.ArrayUtil;
|
import cn.hutool.core.util.ArrayUtil;
|
||||||
import com.ruoyi.common.utils.StringUtils;
|
|
||||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||||
import com.ruoyi.common.core.mybatisplus.core.ServicePlusImpl;
|
import com.ruoyi.common.core.mybatisplus.core.ServicePlusImpl;
|
||||||
import com.ruoyi.common.core.page.TableDataInfo;
|
import com.ruoyi.common.core.page.TableDataInfo;
|
||||||
|
import com.ruoyi.common.core.service.OperLogService;
|
||||||
|
import com.ruoyi.common.core.domain.dto.OperLogDTO;
|
||||||
import com.ruoyi.common.utils.PageUtils;
|
import com.ruoyi.common.utils.PageUtils;
|
||||||
|
import com.ruoyi.common.utils.StringUtils;
|
||||||
|
import com.ruoyi.common.utils.ip.AddressUtils;
|
||||||
import com.ruoyi.system.domain.SysOperLog;
|
import com.ruoyi.system.domain.SysOperLog;
|
||||||
import com.ruoyi.system.mapper.SysOperLogMapper;
|
import com.ruoyi.system.mapper.SysOperLogMapper;
|
||||||
import com.ruoyi.system.service.ISysOperLogService;
|
import com.ruoyi.system.service.ISysOperLogService;
|
||||||
|
import org.springframework.scheduling.annotation.Async;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
@ -22,7 +27,21 @@ import java.util.Map;
|
|||||||
* @author ruoyi
|
* @author ruoyi
|
||||||
*/
|
*/
|
||||||
@Service
|
@Service
|
||||||
public class SysOperLogServiceImpl extends ServicePlusImpl<SysOperLogMapper, SysOperLog, SysOperLog> implements ISysOperLogService {
|
public class SysOperLogServiceImpl extends ServicePlusImpl<SysOperLogMapper, SysOperLog, SysOperLog> implements ISysOperLogService, OperLogService {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 操作日志记录
|
||||||
|
*
|
||||||
|
* @param operLogDTO 操作日志信息
|
||||||
|
*/
|
||||||
|
@Async
|
||||||
|
@Override
|
||||||
|
public void recordOper(final OperLogDTO operLogDTO) {
|
||||||
|
SysOperLog operLog = BeanUtil.toBean(operLogDTO, SysOperLog.class);
|
||||||
|
// 远程查询操作地点
|
||||||
|
operLog.setOperLocation(AddressUtils.getRealAddressByIP(operLog.getOperIp()));
|
||||||
|
insertOperlog(operLog);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public TableDataInfo<SysOperLog> selectPageOperLogList(SysOperLog operLog) {
|
public TableDataInfo<SysOperLog> selectPageOperLogList(SysOperLog operLog) {
|
||||||
|
@ -31,7 +31,7 @@ import java.util.Collection;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 云存储配置Service业务层处理
|
* 对象存储配置Service业务层处理
|
||||||
*
|
*
|
||||||
* @author Lion Li
|
* @author Lion Li
|
||||||
* @author 孤舟烟雨
|
* @author 孤舟烟雨
|
||||||
|
@ -1,20 +1,21 @@
|
|||||||
package com.ruoyi.framework.web.service;
|
package com.ruoyi.system.service.impl;
|
||||||
|
|
||||||
import cn.hutool.core.util.IdUtil;
|
import cn.hutool.core.util.IdUtil;
|
||||||
import cn.hutool.http.useragent.UserAgent;
|
import cn.hutool.http.useragent.UserAgent;
|
||||||
import cn.hutool.http.useragent.UserAgentUtil;
|
import cn.hutool.http.useragent.UserAgentUtil;
|
||||||
import com.ruoyi.common.constant.Constants;
|
import com.ruoyi.common.constant.Constants;
|
||||||
import com.ruoyi.common.core.domain.model.LoginUser;
|
import com.ruoyi.common.core.domain.model.LoginUser;
|
||||||
|
import com.ruoyi.common.core.service.TokenService;
|
||||||
|
import com.ruoyi.common.properties.TokenProperties;
|
||||||
import com.ruoyi.common.utils.RedisUtils;
|
import com.ruoyi.common.utils.RedisUtils;
|
||||||
import com.ruoyi.common.utils.ServletUtils;
|
import com.ruoyi.common.utils.ServletUtils;
|
||||||
import com.ruoyi.common.utils.StringUtils;
|
import com.ruoyi.common.utils.StringUtils;
|
||||||
import com.ruoyi.common.utils.ip.AddressUtils;
|
import com.ruoyi.common.utils.ip.AddressUtils;
|
||||||
import com.ruoyi.framework.config.properties.TokenProperties;
|
|
||||||
import io.jsonwebtoken.Claims;
|
import io.jsonwebtoken.Claims;
|
||||||
import io.jsonwebtoken.Jwts;
|
import io.jsonwebtoken.Jwts;
|
||||||
import io.jsonwebtoken.SignatureAlgorithm;
|
import io.jsonwebtoken.SignatureAlgorithm;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
import javax.servlet.http.HttpServletRequest;
|
import javax.servlet.http.HttpServletRequest;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
@ -26,8 +27,8 @@ import java.util.concurrent.TimeUnit;
|
|||||||
*
|
*
|
||||||
* @author Lion Li
|
* @author Lion Li
|
||||||
*/
|
*/
|
||||||
@Component
|
@Service
|
||||||
public class TokenService {
|
public class TokenServiceImpl implements TokenService {
|
||||||
|
|
||||||
protected static final long MILLIS_SECOND = 1000;
|
protected static final long MILLIS_SECOND = 1000;
|
||||||
|
|
||||||
@ -43,6 +44,7 @@ public class TokenService {
|
|||||||
*
|
*
|
||||||
* @return 用户信息
|
* @return 用户信息
|
||||||
*/
|
*/
|
||||||
|
@Override
|
||||||
public LoginUser getLoginUser(HttpServletRequest request) {
|
public LoginUser getLoginUser(HttpServletRequest request) {
|
||||||
// 获取请求携带的令牌
|
// 获取请求携带的令牌
|
||||||
String token = getToken(request);
|
String token = getToken(request);
|
||||||
@ -64,6 +66,7 @@ public class TokenService {
|
|||||||
/**
|
/**
|
||||||
* 设置用户身份信息
|
* 设置用户身份信息
|
||||||
*/
|
*/
|
||||||
|
@Override
|
||||||
public void setLoginUser(LoginUser loginUser) {
|
public void setLoginUser(LoginUser loginUser) {
|
||||||
if (StringUtils.isNotNull(loginUser) && StringUtils.isNotEmpty(loginUser.getToken())) {
|
if (StringUtils.isNotNull(loginUser) && StringUtils.isNotEmpty(loginUser.getToken())) {
|
||||||
refreshToken(loginUser);
|
refreshToken(loginUser);
|
||||||
@ -73,6 +76,7 @@ public class TokenService {
|
|||||||
/**
|
/**
|
||||||
* 删除用户身份信息
|
* 删除用户身份信息
|
||||||
*/
|
*/
|
||||||
|
@Override
|
||||||
public void delLoginUser(String token) {
|
public void delLoginUser(String token) {
|
||||||
if (StringUtils.isNotEmpty(token)) {
|
if (StringUtils.isNotEmpty(token)) {
|
||||||
String userKey = getTokenKey(token);
|
String userKey = getTokenKey(token);
|
||||||
@ -86,6 +90,7 @@ public class TokenService {
|
|||||||
* @param loginUser 用户信息
|
* @param loginUser 用户信息
|
||||||
* @return 令牌
|
* @return 令牌
|
||||||
*/
|
*/
|
||||||
|
@Override
|
||||||
public String createToken(LoginUser loginUser) {
|
public String createToken(LoginUser loginUser) {
|
||||||
String token = IdUtil.fastUUID();
|
String token = IdUtil.fastUUID();
|
||||||
loginUser.setToken(token);
|
loginUser.setToken(token);
|
||||||
@ -103,6 +108,7 @@ public class TokenService {
|
|||||||
* @param loginUser
|
* @param loginUser
|
||||||
* @return 令牌
|
* @return 令牌
|
||||||
*/
|
*/
|
||||||
|
@Override
|
||||||
public void verifyToken(LoginUser loginUser) {
|
public void verifyToken(LoginUser loginUser) {
|
||||||
long expireTime = loginUser.getExpireTime();
|
long expireTime = loginUser.getExpireTime();
|
||||||
long currentTime = System.currentTimeMillis();
|
long currentTime = System.currentTimeMillis();
|
||||||
@ -116,6 +122,7 @@ public class TokenService {
|
|||||||
*
|
*
|
||||||
* @param loginUser 登录信息
|
* @param loginUser 登录信息
|
||||||
*/
|
*/
|
||||||
|
@Override
|
||||||
public void refreshToken(LoginUser loginUser) {
|
public void refreshToken(LoginUser loginUser) {
|
||||||
loginUser.setLoginTime(System.currentTimeMillis());
|
loginUser.setLoginTime(System.currentTimeMillis());
|
||||||
loginUser.setExpireTime(loginUser.getLoginTime() + tokenProperties.getExpireTime() * MILLIS_MINUTE);
|
loginUser.setExpireTime(loginUser.getLoginTime() + tokenProperties.getExpireTime() * MILLIS_MINUTE);
|
||||||
@ -129,6 +136,7 @@ public class TokenService {
|
|||||||
*
|
*
|
||||||
* @param loginUser 登录信息
|
* @param loginUser 登录信息
|
||||||
*/
|
*/
|
||||||
|
@Override
|
||||||
public void setUserAgent(LoginUser loginUser) {
|
public void setUserAgent(LoginUser loginUser) {
|
||||||
UserAgent userAgent = UserAgentUtil.parse(ServletUtils.getRequest().getHeader("User-Agent"));
|
UserAgent userAgent = UserAgentUtil.parse(ServletUtils.getRequest().getHeader("User-Agent"));
|
||||||
String ip = ServletUtils.getClientIP();
|
String ip = ServletUtils.getClientIP();
|
||||||
@ -170,6 +178,7 @@ public class TokenService {
|
|||||||
* @param token 令牌
|
* @param token 令牌
|
||||||
* @return 用户名
|
* @return 用户名
|
||||||
*/
|
*/
|
||||||
|
@Override
|
||||||
public String getUsernameFromToken(String token) {
|
public String getUsernameFromToken(String token) {
|
||||||
Claims claims = parseToken(token);
|
Claims claims = parseToken(token);
|
||||||
return claims.getSubject();
|
return claims.getSubject();
|
@ -1,28 +1,27 @@
|
|||||||
package com.ruoyi.framework.web.service;
|
package com.ruoyi.system.service.impl;
|
||||||
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
|
||||||
import org.springframework.security.core.userdetails.UserDetails;
|
|
||||||
import org.springframework.security.core.userdetails.UserDetailsService;
|
|
||||||
import org.springframework.security.core.userdetails.UsernameNotFoundException;
|
|
||||||
import org.springframework.stereotype.Service;
|
|
||||||
import com.ruoyi.common.core.domain.entity.SysUser;
|
import com.ruoyi.common.core.domain.entity.SysUser;
|
||||||
import com.ruoyi.common.core.domain.model.LoginUser;
|
import com.ruoyi.common.core.domain.model.LoginUser;
|
||||||
import com.ruoyi.common.enums.UserStatus;
|
import com.ruoyi.common.enums.UserStatus;
|
||||||
import com.ruoyi.common.exception.ServiceException;
|
import com.ruoyi.common.exception.ServiceException;
|
||||||
import com.ruoyi.common.utils.StringUtils;
|
import com.ruoyi.common.utils.StringUtils;
|
||||||
import com.ruoyi.system.service.ISysUserService;
|
import com.ruoyi.system.service.ISysUserService;
|
||||||
|
import com.ruoyi.system.service.SysPermissionService;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.security.core.userdetails.UserDetails;
|
||||||
|
import org.springframework.security.core.userdetails.UserDetailsService;
|
||||||
|
import org.springframework.security.core.userdetails.UsernameNotFoundException;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 用户验证处理
|
* 用户验证处理
|
||||||
*
|
*
|
||||||
* @author ruoyi
|
* @author ruoyi
|
||||||
*/
|
*/
|
||||||
|
@Slf4j
|
||||||
@Service
|
@Service
|
||||||
public class UserDetailsServiceImpl implements UserDetailsService
|
public class UserDetailsServiceImpl implements UserDetailsService {
|
||||||
{
|
|
||||||
private static final Logger log = LoggerFactory.getLogger(UserDetailsServiceImpl.class);
|
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private ISysUserService userService;
|
private ISysUserService userService;
|
||||||
@ -31,21 +30,15 @@ public class UserDetailsServiceImpl implements UserDetailsService
|
|||||||
private SysPermissionService permissionService;
|
private SysPermissionService permissionService;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException
|
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
|
||||||
{
|
|
||||||
SysUser user = userService.selectUserByUserName(username);
|
SysUser user = userService.selectUserByUserName(username);
|
||||||
if (StringUtils.isNull(user))
|
if (StringUtils.isNull(user)) {
|
||||||
{
|
|
||||||
log.info("登录用户:{} 不存在.", username);
|
log.info("登录用户:{} 不存在.", username);
|
||||||
throw new ServiceException("登录用户:" + username + " 不存在");
|
throw new ServiceException("登录用户:" + username + " 不存在");
|
||||||
}
|
} else if (UserStatus.DELETED.getCode().equals(user.getDelFlag())) {
|
||||||
else if (UserStatus.DELETED.getCode().equals(user.getDelFlag()))
|
|
||||||
{
|
|
||||||
log.info("登录用户:{} 已被删除.", username);
|
log.info("登录用户:{} 已被删除.", username);
|
||||||
throw new ServiceException("对不起,您的账号:" + username + " 已被删除");
|
throw new ServiceException("对不起,您的账号:" + username + " 已被删除");
|
||||||
}
|
} else if (UserStatus.DISABLE.getCode().equals(user.getStatus())) {
|
||||||
else if (UserStatus.DISABLE.getCode().equals(user.getStatus()))
|
|
||||||
{
|
|
||||||
log.info("登录用户:{} 已被停用.", username);
|
log.info("登录用户:{} 已被停用.", username);
|
||||||
throw new ServiceException("对不起,您的账号:" + username + " 已停用");
|
throw new ServiceException("对不起,您的账号:" + username + " 已停用");
|
||||||
}
|
}
|
||||||
@ -53,8 +46,7 @@ public class UserDetailsServiceImpl implements UserDetailsService
|
|||||||
return createLoginUser(user);
|
return createLoginUser(user);
|
||||||
}
|
}
|
||||||
|
|
||||||
public UserDetails createLoginUser(SysUser user)
|
public UserDetails createLoginUser(SysUser user) {
|
||||||
{
|
|
||||||
return new LoginUser(user.getUserId(), user.getDeptId(), user, permissionService.getMenuPermission(user));
|
return new LoginUser(user.getUserId(), user.getDeptId(), user, permissionService.getMenuPermission(user));
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -12,7 +12,8 @@
|
|||||||
<result property="orderNum" column="order_num"/>
|
<result property="orderNum" column="order_num"/>
|
||||||
<result property="path" column="path"/>
|
<result property="path" column="path"/>
|
||||||
<result property="component" column="component"/>
|
<result property="component" column="component"/>
|
||||||
<result property="isFrame" column="is_frame"/>
|
<result property="query" column="query"/>
|
||||||
|
<result property="isFrame" column="is_frame"/>
|
||||||
<result property="isCache" column="is_cache"/>
|
<result property="isCache" column="is_cache"/>
|
||||||
<result property="menuType" column="menu_type"/>
|
<result property="menuType" column="menu_type"/>
|
||||||
<result property="visible" column="visible"/>
|
<result property="visible" column="visible"/>
|
||||||
@ -33,6 +34,7 @@
|
|||||||
order_num,
|
order_num,
|
||||||
path,
|
path,
|
||||||
component,
|
component,
|
||||||
|
query,
|
||||||
is_frame,
|
is_frame,
|
||||||
is_cache,
|
is_cache,
|
||||||
menu_type,
|
menu_type,
|
||||||
@ -51,7 +53,8 @@
|
|||||||
m.menu_name,
|
m.menu_name,
|
||||||
m.path,
|
m.path,
|
||||||
m.component,
|
m.component,
|
||||||
m.visible,
|
m.query,
|
||||||
|
m.visible,
|
||||||
m.status,
|
m.status,
|
||||||
ifnull(m.perms, '') as perms,
|
ifnull(m.perms, '') as perms,
|
||||||
m.is_frame,
|
m.is_frame,
|
||||||
@ -67,7 +70,7 @@
|
|||||||
</select>
|
</select>
|
||||||
|
|
||||||
<select id="selectMenuListByUserId" parameterType="SysMenu" resultMap="SysMenuResult">
|
<select id="selectMenuListByUserId" parameterType="SysMenu" resultMap="SysMenuResult">
|
||||||
select distinct m.menu_id, m.parent_id, m.menu_name, m.path, m.component, m.visible, m.status,
|
select distinct m.menu_id, m.parent_id, m.menu_name, m.path, m.component, m.query, m.visible, m.status,
|
||||||
ifnull(m.perms,'') as perms, m.is_frame, m.is_cache, m.menu_type, m.icon, m.order_num, m.create_time
|
ifnull(m.perms,'') as perms, m.is_frame, m.is_cache, m.menu_type, m.icon, m.order_num, m.create_time
|
||||||
from sys_menu m
|
from sys_menu m
|
||||||
left join sys_role_menu rm on m.menu_id = rm.menu_id
|
left join sys_role_menu rm on m.menu_id = rm.menu_id
|
||||||
@ -92,6 +95,7 @@
|
|||||||
m.menu_name,
|
m.menu_name,
|
||||||
m.path,
|
m.path,
|
||||||
m.component,
|
m.component,
|
||||||
|
m.query,
|
||||||
m.visible,
|
m.visible,
|
||||||
m.status,
|
m.status,
|
||||||
ifnull(m.perms, '') as perms,
|
ifnull(m.perms, '') as perms,
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user