Compare commits
31 Commits
bd237fcf08
...
future/6.X
| Author | SHA1 | Date | |
|---|---|---|---|
| bb68d9e227 | |||
| b177620e66 | |||
| bd57356912 | |||
| d50631575a | |||
| 0cab98bc8a | |||
| 415a72b7c6 | |||
| 4498b9c9d5 | |||
| 0b37392a8f | |||
| fc43e368b7 | |||
| e38e99b7f8 | |||
| 83eb74c56d | |||
| a87dcea74b | |||
| 060da45f84 | |||
| 1cb5d841d9 | |||
| 00a1c1037c | |||
| 9e192f5197 | |||
| 4875594bcb | |||
| 90f8142d0b | |||
| 3a6d62d695 | |||
| 14f96acd60 | |||
| 0ca43166d2 | |||
| c64fb7a16a | |||
| 9e21304dbf | |||
| 9888150523 | |||
| 02cf3546fb | |||
| 2d4d7b6fb1 | |||
| e08160afb6 | |||
| f52bb99419 | |||
| d20e03ea61 | |||
| 8c36b41072 | |||
| 94d7cd3489 |
@@ -50,3 +50,6 @@ nbdist/
|
|||||||
!*/build/*.xml
|
!*/build/*.xml
|
||||||
|
|
||||||
.flattened-pom.xml
|
.flattened-pom.xml
|
||||||
|
|
||||||
|
application-local.yml
|
||||||
|
application-ga.yml
|
||||||
|
|||||||
@@ -0,0 +1,13 @@
|
|||||||
|
<component name="ProjectRunConfigurationManager">
|
||||||
|
<configuration default="false" name="ruoyi-snailai-server" type="docker-deploy" factoryName="dockerfile"
|
||||||
|
server-name="Docker">
|
||||||
|
<deployment type="dockerfile">
|
||||||
|
<settings>
|
||||||
|
<option name="imageTag" value="ruoyi/ruoyi-snailai-server:5.5.3"/>
|
||||||
|
<option name="buildOnly" value="true"/>
|
||||||
|
<option name="sourceFilePath" value="ruoyi-extend/ruoyi-snailai-server/Dockerfile"/>
|
||||||
|
</settings>
|
||||||
|
</deployment>
|
||||||
|
<method v="2"/>
|
||||||
|
</configuration>
|
||||||
|
</component>
|
||||||
@@ -22,8 +22,7 @@
|
|||||||
|
|
||||||
> 系统演示: [传送门](https://plus-doc.dromara.org/#/common/demo_system)
|
> 系统演示: [传送门](https://plus-doc.dromara.org/#/common/demo_system)
|
||||||
|
|
||||||
>
|
> 官方前端项目地址: [gitee](https://gitee.com/JavaLionLi/plus-ui) - [github](https://github.com/CrazyLionCat/plus-ui) - [gitcode](https://gitcode.com/dromara/plus-ui)<br>
|
||||||
官方前端项目地址: [gitee](https://gitee.com/JavaLionLi/plus-ui) - [github](https://github.com/CrazyLionCat/plus-ui) - [gitcode](https://gitcode.com/dromara/plus-ui)<br>
|
|
||||||
> 成员前端项目地址: 基于vben5 [ruoyi-plus-vben5](https://github.com/imdap/ruoyi-plus-vben5)<br>
|
> 成员前端项目地址: 基于vben5 [ruoyi-plus-vben5](https://github.com/imdap/ruoyi-plus-vben5)<br>
|
||||||
> 成员前端项目地址: 基于soybean [ruoyi-plus-soybean](https://gitee.com/xlsea/ruoyi-plus-soybean)<br>
|
> 成员前端项目地址: 基于soybean [ruoyi-plus-soybean](https://gitee.com/xlsea/ruoyi-plus-soybean)<br>
|
||||||
> 成员项目地址: 删除多租户与工作流 [RuoYi-Vue-Plus-Single](https://gitee.com/ColorDreams/RuoYi-Vue-Plus-Single)<br>
|
> 成员项目地址: 删除多租户与工作流 [RuoYi-Vue-Plus-Single](https://gitee.com/ColorDreams/RuoYi-Vue-Plus-Single)<br>
|
||||||
|
|||||||
@@ -10,34 +10,34 @@
|
|||||||
|
|
||||||
<name>RuoYi-Vue-Plus</name>
|
<name>RuoYi-Vue-Plus</name>
|
||||||
<url>https://gitee.com/dromara/RuoYi-Vue-Plus</url>
|
<url>https://gitee.com/dromara/RuoYi-Vue-Plus</url>
|
||||||
<description>Dromara RuoYi-Vue-Plus管理系统</description>
|
<description>Dromara RuoYi-Vue-Plus后台管理系统</description>
|
||||||
|
|
||||||
<properties>
|
<properties>
|
||||||
<revision>5.5.3</revision>
|
<revision>5.5.3</revision>
|
||||||
<spring-boot.version>4.0.6</spring-boot.version>
|
<spring-boot.version>4.1.0</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>21</java.version>
|
<java.version>21</java.version>
|
||||||
<mybatis.version>3.5.19</mybatis.version>
|
<mybatis.version>3.5.19</mybatis.version>
|
||||||
<springdoc.version>3.0.2</springdoc.version>
|
<springdoc.version>3.0.3</springdoc.version>
|
||||||
<therapi-javadoc.version>0.15.0</therapi-javadoc.version>
|
<therapi-javadoc.version>0.15.0</therapi-javadoc.version>
|
||||||
<fesod.version>2.0.1-incubating</fesod.version>
|
<fesod.version>2.0.2-incubating</fesod.version>
|
||||||
<velocity.version>2.4.1</velocity.version>
|
<velocity.version>2.4.1</velocity.version>
|
||||||
<satoken.version>1.45.0</satoken.version>
|
<satoken.version>1.45.0</satoken.version>
|
||||||
<mybatis-plus.version>3.5.16</mybatis-plus.version>
|
<mybatis-plus.version>3.5.16</mybatis-plus.version>
|
||||||
<mybatis-plus-join.version>1.5.6</mybatis-plus-join.version>
|
<mybatis-plus-join.version>1.5.6</mybatis-plus-join.version>
|
||||||
<p6spy.version>3.9.1</p6spy.version>
|
<p6spy.version>3.9.1</p6spy.version>
|
||||||
<hutool.version>5.8.44</hutool.version>
|
<hutool.version>5.8.46</hutool.version>
|
||||||
<spring-boot-admin.version>4.0.4</spring-boot-admin.version>
|
<spring-boot-admin.version>4.0.4</spring-boot-admin.version>
|
||||||
<redisson.version>4.4.0</redisson.version>
|
<redisson.version>4.5.0</redisson.version>
|
||||||
<lock4j.version>2.2.7</lock4j.version>
|
<lock4j.version>2.2.7</lock4j.version>
|
||||||
<dynamic-ds.version>4.5.0</dynamic-ds.version>
|
<dynamic-ds.version>4.5.0</dynamic-ds.version>
|
||||||
<snailjob.version>2.0.0</snailjob.version>
|
<snailjob.version>2.0.0</snailjob.version>
|
||||||
<snailai.version>0.0.3</snailai.version>
|
<snailai.version>0.0.4</snailai.version>
|
||||||
<mapstruct-plus.version>1.5.0</mapstruct-plus.version>
|
<mapstruct-plus.version>1.5.0</mapstruct-plus.version>
|
||||||
<mapstruct-plus.lombok.version>0.2.0</mapstruct-plus.lombok.version>
|
<mapstruct-plus.lombok.version>0.2.0</mapstruct-plus.lombok.version>
|
||||||
<lombok.version>1.18.42</lombok.version>
|
<lombok.version>1.18.42</lombok.version>
|
||||||
<bouncycastle.version>1.83</bouncycastle.version>
|
<bouncycastle.version>1.84</bouncycastle.version>
|
||||||
<justauth.version>1.16.7</justauth.version>
|
<justauth.version>1.16.7</justauth.version>
|
||||||
<!-- 离线IP地址定位库 -->
|
<!-- 离线IP地址定位库 -->
|
||||||
<ip2region.version>3.3.6</ip2region.version>
|
<ip2region.version>3.3.6</ip2region.version>
|
||||||
@@ -52,7 +52,7 @@
|
|||||||
<!-- 工作流配置 -->
|
<!-- 工作流配置 -->
|
||||||
<warm-flow.version>1.8.7</warm-flow.version>
|
<warm-flow.version>1.8.7</warm-flow.version>
|
||||||
<!-- mqtt客户端 -->
|
<!-- mqtt客户端 -->
|
||||||
<mica-mqtt.version>2.5.12</mica-mqtt.version>
|
<mica-mqtt.version>2.6.5</mica-mqtt.version>
|
||||||
<easy-es.version>3.0.2</easy-es.version>
|
<easy-es.version>3.0.2</easy-es.version>
|
||||||
<elasticsearch-client.version>7.17.28</elasticsearch-client.version>
|
<elasticsearch-client.version>7.17.28</elasticsearch-client.version>
|
||||||
<!-- Spring AI 2.0 预览版,正式版发布后仅需调整此版本号 -->
|
<!-- Spring AI 2.0 预览版,正式版发布后仅需调整此版本号 -->
|
||||||
@@ -66,7 +66,7 @@
|
|||||||
<!-- 统一版本号管理:Maven3.X需要,Maven4.0之后已原生支持 -->
|
<!-- 统一版本号管理:Maven3.X需要,Maven4.0之后已原生支持 -->
|
||||||
<flatten-maven-plugin.version>1.7.3</flatten-maven-plugin.version>
|
<flatten-maven-plugin.version>1.7.3</flatten-maven-plugin.version>
|
||||||
<!-- 打包默认跳过测试 -->
|
<!-- 打包默认跳过测试 -->
|
||||||
<skipTests>true</skipTests>
|
<maven.test.skip>true</maven.test.skip>
|
||||||
</properties>
|
</properties>
|
||||||
|
|
||||||
<profiles>
|
<profiles>
|
||||||
|
|||||||
@@ -11,18 +11,20 @@ RUN mkdir -p /ruoyi/server/logs \
|
|||||||
|
|
||||||
WORKDIR /ruoyi/server
|
WORKDIR /ruoyi/server
|
||||||
|
|
||||||
ENV SERVER_PORT=8080 SNAIL_PORT=28080 LANG=C.UTF-8 LC_ALL=C.UTF-8 JAVA_OPTS=""
|
ENV SERVER_PORT=8080 SNAIL_JOB_PORT=28080 SNAIL_AI_PORT=38080 LANG=C.UTF-8 LC_ALL=C.UTF-8 JAVA_OPTS=""
|
||||||
|
|
||||||
EXPOSE ${SERVER_PORT}
|
EXPOSE ${SERVER_PORT}
|
||||||
# 暴露 snail job 客户端端口 用于定时任务调度中心通信
|
# 暴露 snail 客户端端口 用于定时任务调度中心通信
|
||||||
EXPOSE ${SNAIL_PORT}
|
EXPOSE ${SNAIL_JOB_PORT}
|
||||||
|
EXPOSE ${SNAIL_AI_PORT}
|
||||||
|
|
||||||
ADD ./target/ruoyi-admin.jar ./app.jar
|
ADD ./target/ruoyi-admin.jar ./app.jar
|
||||||
|
|
||||||
SHELL ["/bin/bash", "-c"]
|
SHELL ["/bin/bash", "-c"]
|
||||||
|
|
||||||
ENTRYPOINT java -Djava.security.egd=file:/dev/./urandom -Dserver.port=${SERVER_PORT} \
|
ENTRYPOINT java -Djava.security.egd=file:/dev/./urandom -Dserver.port=${SERVER_PORT} \
|
||||||
-Dsnail-job.port=${SNAIL_PORT} \
|
-Dsnail-job.port=${SNAIL_JOB_PORT} \
|
||||||
|
-Dsnail-ai.port=${SNAIL_AI_PORT} \
|
||||||
# 应用名称 如果想区分集群节点监控 改成不同的名称即可
|
# 应用名称 如果想区分集群节点监控 改成不同的名称即可
|
||||||
#-Dskywalking.agent.service_name=ruoyi-server \
|
#-Dskywalking.agent.service_name=ruoyi-server \
|
||||||
#-javaagent:/ruoyi/skywalking/agent/skywalking-agent.jar \
|
#-javaagent:/ruoyi/skywalking/agent/skywalking-agent.jar \
|
||||||
|
|||||||
@@ -17,30 +17,6 @@
|
|||||||
|
|
||||||
<dependencies>
|
<dependencies>
|
||||||
|
|
||||||
<!-- ruoyi-admin 同时引入 SnailJob Client 与 SnailAI Agent,SnailAI Agent 0.0.3 需要 protobuf 4.x -->
|
|
||||||
<dependency>
|
|
||||||
<groupId>com.google.protobuf</groupId>
|
|
||||||
<artifactId>protobuf-java</artifactId>
|
|
||||||
<version>4.35.0</version>
|
|
||||||
</dependency>
|
|
||||||
|
|
||||||
<!-- 局部提升 ruoyi-admin 的 gRPC 运行时,避免被 SnailJob Client 的 1.76.0 抢先选中 -->
|
|
||||||
<dependency>
|
|
||||||
<groupId>io.grpc</groupId>
|
|
||||||
<artifactId>grpc-protobuf</artifactId>
|
|
||||||
<version>1.81.0</version>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>io.grpc</groupId>
|
|
||||||
<artifactId>grpc-stub</artifactId>
|
|
||||||
<version>1.81.0</version>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>io.grpc</groupId>
|
|
||||||
<artifactId>grpc-netty-shaded</artifactId>
|
|
||||||
<version>1.81.0</version>
|
|
||||||
</dependency>
|
|
||||||
|
|
||||||
<!-- Mysql驱动包 -->
|
<!-- Mysql驱动包 -->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.mysql</groupId>
|
<groupId>com.mysql</groupId>
|
||||||
|
|||||||
@@ -58,7 +58,7 @@ public class CaptchaController {
|
|||||||
* @param phoneNumber 用户手机号
|
* @param phoneNumber 用户手机号
|
||||||
* @return 操作结果
|
* @return 操作结果
|
||||||
*/
|
*/
|
||||||
@RateLimiter(key = "#phonenumber", time = 60, count = 1)
|
@RateLimiter(key = "#phoneNumber", time = 60, count = 1)
|
||||||
@GetMapping("/resource/sms/code")
|
@GetMapping("/resource/sms/code")
|
||||||
public R<Void> smsCode(@NotBlank(message = "{user.phonenumber.not.blank}") String phoneNumber) {
|
public R<Void> smsCode(@NotBlank(message = "{user.phonenumber.not.blank}") String phoneNumber) {
|
||||||
if (!RegexValidator.isMobile(phoneNumber)) {
|
if (!RegexValidator.isMobile(phoneNumber)) {
|
||||||
@@ -66,7 +66,6 @@ public class CaptchaController {
|
|||||||
}
|
}
|
||||||
String key = GlobalConstants.CAPTCHA_CODE_KEY + phoneNumber;
|
String key = GlobalConstants.CAPTCHA_CODE_KEY + phoneNumber;
|
||||||
String code = RandomUtil.randomNumbers(4);
|
String code = RandomUtil.randomNumbers(4);
|
||||||
RedisUtils.setCacheObject(key, code, Duration.ofMinutes(Constants.CAPTCHA_EXPIRATION));
|
|
||||||
// 验证码模板id 自行处理 (查数据库或写死均可)
|
// 验证码模板id 自行处理 (查数据库或写死均可)
|
||||||
String templateId = "";
|
String templateId = "";
|
||||||
LinkedHashMap<String, String> map = new LinkedHashMap<>(1);
|
LinkedHashMap<String, String> map = new LinkedHashMap<>(1);
|
||||||
@@ -75,8 +74,10 @@ public class CaptchaController {
|
|||||||
SmsResponse smsResponse = smsBlend.sendMessage(phoneNumber, templateId, map);
|
SmsResponse smsResponse = smsBlend.sendMessage(phoneNumber, templateId, map);
|
||||||
if (!smsResponse.isSuccess()) {
|
if (!smsResponse.isSuccess()) {
|
||||||
log.error("验证码短信发送异常 => {}", smsResponse);
|
log.error("验证码短信发送异常 => {}", smsResponse);
|
||||||
return R.fail(smsResponse.getData().toString());
|
Object data = smsResponse.getData();
|
||||||
|
return R.fail(data == null ? "验证码短信发送失败" : data.toString());
|
||||||
}
|
}
|
||||||
|
RedisUtils.setCacheObject(key, code, Duration.ofMinutes(Constants.CAPTCHA_EXPIRATION));
|
||||||
return R.ok();
|
return R.ok();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -107,13 +108,13 @@ public class CaptchaController {
|
|||||||
public void emailCodeImpl(String email) {
|
public void emailCodeImpl(String email) {
|
||||||
String key = GlobalConstants.CAPTCHA_CODE_KEY + email;
|
String key = GlobalConstants.CAPTCHA_CODE_KEY + email;
|
||||||
String code = RandomUtil.randomNumbers(4);
|
String code = RandomUtil.randomNumbers(4);
|
||||||
RedisUtils.setCacheObject(key, code, Duration.ofMinutes(Constants.CAPTCHA_EXPIRATION));
|
|
||||||
try {
|
try {
|
||||||
MailBuilder.of()
|
MailBuilder.of()
|
||||||
.to(email)
|
.to(email)
|
||||||
.subject("登录验证码")
|
.subject("登录验证码")
|
||||||
.text("您本次验证码为:" + code + ",有效性为" + Constants.CAPTCHA_EXPIRATION + "分钟,请尽快填写。")
|
.text("您本次验证码为:" + code + ",有效性为" + Constants.CAPTCHA_EXPIRATION + "分钟,请尽快填写。")
|
||||||
.send();
|
.send();
|
||||||
|
RedisUtils.setCacheObject(key, code, Duration.ofMinutes(Constants.CAPTCHA_EXPIRATION));
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
log.error("验证码短信发送异常 => {}", e.getMessage());
|
log.error("验证码短信发送异常 => {}", e.getMessage());
|
||||||
throw new ServiceException(e.getMessage());
|
throw new ServiceException(e.getMessage());
|
||||||
|
|||||||
@@ -97,7 +97,7 @@ public class SysLoginService {
|
|||||||
sysSocialService.insertByBo(bo);
|
sysSocialService.insertByBo(bo);
|
||||||
} else {
|
} else {
|
||||||
// 更新用户信息
|
// 更新用户信息
|
||||||
bo.setId(list.get(0).getId());
|
bo.setId(list.getFirst().getId());
|
||||||
sysSocialService.updateByBo(bo);
|
sysSocialService.updateByBo(bo);
|
||||||
// 如果要绑定的平台账号已经被绑定过了 是否抛异常自行决断
|
// 如果要绑定的平台账号已经被绑定过了 是否抛异常自行决断
|
||||||
// throw new ServiceException("此平台账号已经被绑定!");
|
// throw new ServiceException("此平台账号已经被绑定!");
|
||||||
|
|||||||
@@ -68,7 +68,7 @@ public class SocialAuthStrategy implements IAuthStrategy {
|
|||||||
if (CollUtil.isEmpty(list)) {
|
if (CollUtil.isEmpty(list)) {
|
||||||
throw new ServiceException("你还没有绑定第三方账号,绑定后才可以登录!");
|
throw new ServiceException("你还没有绑定第三方账号,绑定后才可以登录!");
|
||||||
}
|
}
|
||||||
SysUserVo user = loadUser(list.get(0).getUserId());
|
SysUserVo user = loadUser(list.getFirst().getUserId());
|
||||||
// 此处可根据登录用户的数据不同 自行创建 loginUser 属性不够用继承扩展就行了
|
// 此处可根据登录用户的数据不同 自行创建 loginUser 属性不够用继承扩展就行了
|
||||||
LoginUser loginUser = loginService.buildLoginUser(user);
|
LoginUser loginUser = loginService.buildLoginUser(user);
|
||||||
loginUser.setClientKey(client.getClientKey());
|
loginUser.setClientKey(client.getClientKey());
|
||||||
|
|||||||
@@ -137,7 +137,7 @@ spring.data:
|
|||||||
# 数据库索引
|
# 数据库索引
|
||||||
database: 0
|
database: 0
|
||||||
# redis 密码必须配置
|
# redis 密码必须配置
|
||||||
password: ruoyi123
|
# password: ruoyi123
|
||||||
# 连接超时时间
|
# 连接超时时间
|
||||||
timeout: 10s
|
timeout: 10s
|
||||||
# 是否开启ssl
|
# 是否开启ssl
|
||||||
|
|||||||
@@ -161,7 +161,7 @@ springdoc:
|
|||||||
enabled: true
|
enabled: true
|
||||||
info:
|
info:
|
||||||
# 标题
|
# 标题
|
||||||
title: '标题:RuoYi-Vue-Plus管理系统_接口文档'
|
title: '标题:RuoYi-Vue-Plus后台管理系统_接口文档'
|
||||||
# 描述
|
# 描述
|
||||||
description: '描述:用于管理集团旗下公司的人员信息,具体包括XXX,XXX模块...'
|
description: '描述:用于管理集团旗下公司的人员信息,具体包括XXX,XXX模块...'
|
||||||
# 版本
|
# 版本
|
||||||
@@ -191,6 +191,7 @@ xss:
|
|||||||
# 排除链接
|
# 排除链接
|
||||||
excludeUrls:
|
excludeUrls:
|
||||||
- /system/notice
|
- /system/notice
|
||||||
|
- /warm-flow/save-json
|
||||||
|
|
||||||
--- # 分布式锁 lock4j 全局配置
|
--- # 分布式锁 lock4j 全局配置
|
||||||
lock4j:
|
lock4j:
|
||||||
@@ -262,8 +263,8 @@ mqtt.client:
|
|||||||
timeout: 5
|
timeout: 5
|
||||||
# 重连时间,默认 5000 毫秒
|
# 重连时间,默认 5000 毫秒
|
||||||
re-interval: 5000
|
re-interval: 5000
|
||||||
# mqtt 协议版本,可选 MQTT_3_1、mqtt_3_1_1、mqtt_5,默认:mqtt_3_1_1
|
# mqtt 协议版本,可选 MQTT_3_1、mqtt_3_1_1、mqtt_5,默认:mqtt_5
|
||||||
version: mqtt_3_1_1
|
version: mqtt_5
|
||||||
# 接收数据的 buffer size,默认:8k
|
# 接收数据的 buffer size,默认:8k
|
||||||
read-buffer-size: 8KB
|
read-buffer-size: 8KB
|
||||||
# 消息解析最大 bytes 长度,默认:10M
|
# 消息解析最大 bytes 长度,默认:10M
|
||||||
|
|||||||
+1
-2
@@ -98,9 +98,8 @@ public class ThreadPoolConfig {
|
|||||||
* @param t 任务执行过程中抛出的异常
|
* @param t 任务执行过程中抛出的异常
|
||||||
*/
|
*/
|
||||||
public static void printException(Runnable r, Throwable t) {
|
public static void printException(Runnable r, Throwable t) {
|
||||||
if (t == null && r instanceof Future<?>) {
|
if (t == null && r instanceof Future<?> future) {
|
||||||
try {
|
try {
|
||||||
Future<?> future = (Future<?>) r;
|
|
||||||
if (future.isDone()) {
|
if (future.isDone()) {
|
||||||
future.get();
|
future.get();
|
||||||
}
|
}
|
||||||
|
|||||||
-152
@@ -1,152 +0,0 @@
|
|||||||
package org.dromara.common.core.enums;
|
|
||||||
|
|
||||||
import lombok.AllArgsConstructor;
|
|
||||||
import lombok.Getter;
|
|
||||||
import org.dromara.common.core.utils.StringUtils;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* 日期格式
|
|
||||||
* "yyyy":4位数的年份,例如:2023年表示为"2023"。
|
|
||||||
* "yy":2位数的年份,例如:2023年表示为"23"。
|
|
||||||
* "MM":2位数的月份,取值范围为01到12,例如:7月表示为"07"。
|
|
||||||
* "M":不带前导零的月份,取值范围为1到12,例如:7月表示为"7"。
|
|
||||||
* "dd":2位数的日期,取值范围为01到31,例如:22日表示为"22"。
|
|
||||||
* "d":不带前导零的日期,取值范围为1到31,例如:22日表示为"22"。
|
|
||||||
* "EEEE":星期的全名,例如:星期三表示为"Wednesday"。
|
|
||||||
* "E":星期的缩写,例如:星期三表示为"Wed"。
|
|
||||||
* "DDD" 或 "D":一年中的第几天,取值范围为001到366,例如:第200天表示为"200"。
|
|
||||||
* 时间格式
|
|
||||||
* "HH":24小时制的小时数,取值范围为00到23,例如:下午5点表示为"17"。
|
|
||||||
* "hh":12小时制的小时数,取值范围为01到12,例如:下午5点表示为"05"。
|
|
||||||
* "mm":分钟数,取值范围为00到59,例如:30分钟表示为"30"。
|
|
||||||
* "ss":秒数,取值范围为00到59,例如:45秒表示为"45"。
|
|
||||||
* "SSS":毫秒数,取值范围为000到999,例如:123毫秒表示为"123"。
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 日期格式与时间格式枚举
|
|
||||||
*/
|
|
||||||
@Getter
|
|
||||||
@AllArgsConstructor
|
|
||||||
public enum FormatsType {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 例如:2023年表示为"23"
|
|
||||||
*/
|
|
||||||
YY("yy"),
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 例如:2023年表示为"2023"
|
|
||||||
*/
|
|
||||||
YYYY("yyyy"),
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 例例如,2023年7月可以表示为 "2023-07"
|
|
||||||
*/
|
|
||||||
YYYY_MM("yyyy-MM"),
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 例如,日期 "2023年7月22日" 可以表示为 "2023-07-22"
|
|
||||||
*/
|
|
||||||
YYYY_MM_DD("yyyy-MM-dd"),
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 例如,当前时间如果是 "2023年7月22日下午3点30分",则可以表示为 "2023-07-22 15:30"
|
|
||||||
*/
|
|
||||||
YYYY_MM_DD_HH_MM("yyyy-MM-dd HH:mm"),
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 例如,当前时间如果是 "2023年7月22日下午3点30分45秒",则可以表示为 "2023-07-22 15:30:45"
|
|
||||||
*/
|
|
||||||
YYYY_MM_DD_HH_MM_SS("yyyy-MM-dd HH:mm:ss"),
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 例如:下午3点30分45秒,表示为 "15:30:45"
|
|
||||||
*/
|
|
||||||
HH_MM_SS("HH:mm:ss"),
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 例例如,2023年7月可以表示为 "2023/07"
|
|
||||||
*/
|
|
||||||
YYYY_MM_SLASH("yyyy/MM"),
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 例如,日期 "2023年7月22日" 可以表示为 "2023/07/22"
|
|
||||||
*/
|
|
||||||
YYYY_MM_DD_SLASH("yyyy/MM/dd"),
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 例如,当前时间如果是 "2023年7月22日下午3点30分45秒",则可以表示为 "2023/07/22 15:30:45"
|
|
||||||
*/
|
|
||||||
YYYY_MM_DD_HH_MM_SLASH("yyyy/MM/dd HH:mm"),
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 例如,当前时间如果是 "2023年7月22日下午3点30分45秒",则可以表示为 "2023/07/22 15:30:45"
|
|
||||||
*/
|
|
||||||
YYYY_MM_DD_HH_MM_SS_SLASH("yyyy/MM/dd HH:mm:ss"),
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 例例如,2023年7月可以表示为 "2023.07"
|
|
||||||
*/
|
|
||||||
YYYY_MM_DOT("yyyy.MM"),
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 例如,日期 "2023年7月22日" 可以表示为 "2023.07.22"
|
|
||||||
*/
|
|
||||||
YYYY_MM_DD_DOT("yyyy.MM.dd"),
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 例如,当前时间如果是 "2023年7月22日下午3点30分",则可以表示为 "2023.07.22 15:30"
|
|
||||||
*/
|
|
||||||
YYYY_MM_DD_HH_MM_DOT("yyyy.MM.dd HH:mm"),
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 例如,当前时间如果是 "2023年7月22日下午3点30分45秒",则可以表示为 "2023.07.22 15:30:45"
|
|
||||||
*/
|
|
||||||
YYYY_MM_DD_HH_MM_SS_DOT("yyyy.MM.dd HH:mm:ss"),
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 例如,2023年7月可以表示为 "202307"
|
|
||||||
*/
|
|
||||||
YYYYMM("yyyyMM"),
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 例如,2023年7月22日可以表示为 "20230722"
|
|
||||||
*/
|
|
||||||
YYYYMMDD("yyyyMMdd"),
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 例如,2023年7月22日下午3点可以表示为 "2023072215"
|
|
||||||
*/
|
|
||||||
YYYYMMDDHH("yyyyMMddHH"),
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 例如,2023年7月22日下午3点30分可以表示为 "202307221530"
|
|
||||||
*/
|
|
||||||
YYYYMMDDHHMM("yyyyMMddHHmm"),
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 例如,2023年7月22日下午3点30分45秒可以表示为 "20230722153045"
|
|
||||||
*/
|
|
||||||
YYYYMMDDHHMMSS("yyyyMMddHHmmss");
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 时间格式
|
|
||||||
*/
|
|
||||||
private final String timeFormat;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 根据字符串内容匹配时间格式类型。
|
|
||||||
*
|
|
||||||
* @param str 字符串内容
|
|
||||||
* @return 时间格式类型
|
|
||||||
*/
|
|
||||||
public static FormatsType getFormatsType(String str) {
|
|
||||||
for (FormatsType value : values()) {
|
|
||||||
if (StringUtils.contains(str, value.getTimeFormat())) {
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
throw new RuntimeException("'FormatsType' not found By " + str);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
+2
-2
@@ -1,11 +1,11 @@
|
|||||||
package org.dromara.common.core.exception.base;
|
package org.dromara.common.core.exception.base;
|
||||||
|
|
||||||
import lombok.AllArgsConstructor;
|
import lombok.AllArgsConstructor;
|
||||||
import org.dromara.common.core.utils.MessageUtils;
|
|
||||||
import org.dromara.common.core.utils.StringUtils;
|
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import lombok.EqualsAndHashCode;
|
import lombok.EqualsAndHashCode;
|
||||||
import lombok.NoArgsConstructor;
|
import lombok.NoArgsConstructor;
|
||||||
|
import org.dromara.common.core.utils.MessageUtils;
|
||||||
|
import org.dromara.common.core.utils.StringUtils;
|
||||||
|
|
||||||
import java.io.Serial;
|
import java.io.Serial;
|
||||||
|
|
||||||
|
|||||||
+68
-320
@@ -1,347 +1,96 @@
|
|||||||
package org.dromara.common.core.utils;
|
package org.dromara.common.core.utils;
|
||||||
|
|
||||||
|
import cn.hutool.core.convert.Convert;
|
||||||
|
import cn.hutool.core.date.BetweenFormatter;
|
||||||
import cn.hutool.core.date.DateUnit;
|
import cn.hutool.core.date.DateUnit;
|
||||||
import cn.hutool.core.date.DateUtil;
|
import cn.hutool.core.date.DateUtil;
|
||||||
import org.apache.commons.lang3.time.DateFormatUtils;
|
import cn.hutool.core.lang.Assert;
|
||||||
import org.dromara.common.core.enums.FormatsType;
|
import lombok.AccessLevel;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
import org.dromara.common.core.exception.ServiceException;
|
import org.dromara.common.core.exception.ServiceException;
|
||||||
|
|
||||||
import java.lang.management.ManagementFactory;
|
|
||||||
import java.text.ParseException;
|
|
||||||
import java.text.SimpleDateFormat;
|
|
||||||
import java.time.*;
|
|
||||||
import java.time.format.DateTimeFormatter;
|
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 时间工具类
|
* 时间工具类
|
||||||
*
|
*
|
||||||
* @author ruoyi
|
* @author AprilWind
|
||||||
*/
|
*/
|
||||||
public class DateUtils extends org.apache.commons.lang3.time.DateUtils {
|
@NoArgsConstructor(access = AccessLevel.PRIVATE)
|
||||||
/**
|
public class DateUtils extends DateUtil {
|
||||||
* 日期解析格式集合。
|
|
||||||
*/
|
|
||||||
private static final String[] PARSE_PATTERNS = {
|
|
||||||
"yyyy-MM-dd", "yyyy-MM-dd HH:mm:ss", "yyyy-MM-dd HH:mm", "yyyy-MM",
|
|
||||||
"yyyy/MM/dd", "yyyy/MM/dd HH:mm:ss", "yyyy/MM/dd HH:mm", "yyyy/MM",
|
|
||||||
"yyyy.MM.dd", "yyyy.MM.dd HH:mm:ss", "yyyy.MM.dd HH:mm", "yyyy.MM"};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 工具类不允许实例化。
|
* 计算时间差并格式化(精确到秒)
|
||||||
*/
|
|
||||||
@Deprecated
|
|
||||||
private DateUtils() {
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取当前日期和时间
|
|
||||||
*
|
*
|
||||||
* @return 当前日期和时间的 Date 对象表示
|
* @param start 开始时间(支持 Date/LocalDateTime)
|
||||||
|
* @param end 结束时间(支持 Date/LocalDateTime)
|
||||||
|
* @return 时分秒格式时间差
|
||||||
*/
|
*/
|
||||||
public static Date getNowDate() {
|
public static String formatBetweenBySecond(Object start, Object end) {
|
||||||
return new Date();
|
return formatTimeBetween(start, end, BetweenFormatter.Level.SECOND);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取当前日期的字符串表示,格式为YYYY-MM-DD
|
* 通用时间差格式化
|
||||||
*
|
|
||||||
* @return 当前日期的字符串表示
|
|
||||||
*/
|
|
||||||
public static String getDate() {
|
|
||||||
return dateTimeNow(FormatsType.YYYY_MM_DD);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取当前日期的字符串表示,格式为yyyyMMdd
|
|
||||||
*
|
|
||||||
* @return 当前日期的字符串表示
|
|
||||||
*/
|
|
||||||
public static String getCurrentDate() {
|
|
||||||
return DateFormatUtils.format(new Date(), FormatsType.YYYYMMDD.getTimeFormat());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取当前日期的路径格式字符串,格式为"yyyy/MM/dd"
|
|
||||||
*
|
|
||||||
* @return 当前日期的路径格式字符串
|
|
||||||
*/
|
|
||||||
public static String datePath() {
|
|
||||||
Date now = new Date();
|
|
||||||
return DateFormatUtils.format(now, FormatsType.YYYY_MM_DD_SLASH.getTimeFormat());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取当前时间的字符串表示,格式为YYYY-MM-DD HH:MM:SS
|
|
||||||
*
|
|
||||||
* @return 当前时间的字符串表示
|
|
||||||
*/
|
|
||||||
public static String getTime() {
|
|
||||||
return dateTimeNow(FormatsType.YYYY_MM_DD_HH_MM_SS);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取当前时间的字符串表示,格式为 "HH:MM:SS"
|
|
||||||
*
|
|
||||||
* @return 当前时间的字符串表示,格式为 "HH:MM:SS"
|
|
||||||
*/
|
|
||||||
public static String getTimeWithHourMinuteSecond() {
|
|
||||||
return dateTimeNow(FormatsType.HH_MM_SS);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取当前日期和时间的字符串表示,格式为YYYYMMDDHHMMSS
|
|
||||||
*
|
|
||||||
* @return 当前日期和时间的字符串表示
|
|
||||||
*/
|
|
||||||
public static String dateTimeNow() {
|
|
||||||
return dateTimeNow(FormatsType.YYYYMMDDHHMMSS);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取当前日期和时间的指定格式的字符串表示
|
|
||||||
*
|
|
||||||
* @param format 日期时间格式,例如"YYYY-MM-DD HH:MM:SS"
|
|
||||||
* @return 当前日期和时间的字符串表示
|
|
||||||
*/
|
|
||||||
public static String dateTimeNow(final FormatsType format) {
|
|
||||||
return parseDateToStr(format, new Date());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 将指定日期格式化为 YYYY-MM-DD 格式的字符串
|
|
||||||
*
|
|
||||||
* @param date 要格式化的日期对象
|
|
||||||
* @return 格式化后的日期字符串
|
|
||||||
*/
|
|
||||||
public static String formatDate(final Date date) {
|
|
||||||
return parseDateToStr(FormatsType.YYYY_MM_DD, date);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 将指定日期格式化为 YYYY-MM-DD HH:MM:SS 格式的字符串
|
|
||||||
*
|
|
||||||
* @param date 要格式化的日期对象
|
|
||||||
* @return 格式化后的日期时间字符串
|
|
||||||
*/
|
|
||||||
public static String formatDateTime(final Date date) {
|
|
||||||
return parseDateToStr(FormatsType.YYYY_MM_DD_HH_MM_SS, date);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 将 LocalDateTime 格式化为 YYYY-MM-DD HH:MM:SS 格式的字符串
|
|
||||||
*
|
|
||||||
* @param dateTime 要格式化的 LocalDateTime 对象
|
|
||||||
* @return 格式化后的日期时间字符串
|
|
||||||
*/
|
|
||||||
public static String formatDateTime(final LocalDateTime dateTime) {
|
|
||||||
return dateTime.format(DateTimeFormatter.ofPattern(FormatsType.YYYY_MM_DD_HH_MM_SS.getTimeFormat()));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 将指定日期按照指定格式进行格式化
|
|
||||||
*
|
|
||||||
* @param format 要使用的日期时间格式,例如"YYYY-MM-DD HH:MM:SS"
|
|
||||||
* @param date 要格式化的日期对象
|
|
||||||
* @return 格式化后的日期时间字符串
|
|
||||||
*/
|
|
||||||
public static String parseDateToStr(final FormatsType format, final Date date) {
|
|
||||||
return new SimpleDateFormat(format.getTimeFormat()).format(date);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 将指定格式的日期时间字符串转换为 Date 对象
|
|
||||||
*
|
|
||||||
* @param format 要解析的日期时间格式,例如"YYYY-MM-DD HH:MM:SS"
|
|
||||||
* @param ts 要解析的日期时间字符串
|
|
||||||
* @return 解析后的 Date 对象
|
|
||||||
* @throws RuntimeException 如果解析过程中发生异常
|
|
||||||
*/
|
|
||||||
public static Date parseDateTime(final FormatsType format, final String ts) {
|
|
||||||
try {
|
|
||||||
return new SimpleDateFormat(format.getTimeFormat()).parse(ts);
|
|
||||||
} catch (ParseException e) {
|
|
||||||
throw new ServiceException("日期时间解析失败:" + ts, e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 将对象转换为日期对象
|
|
||||||
*
|
|
||||||
* @param str 要转换的对象,通常是字符串
|
|
||||||
* @return 转换后的日期对象,如果转换失败或输入为null,则返回null
|
|
||||||
*/
|
|
||||||
public static Date parseDate(Object str) {
|
|
||||||
if (str == null) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
return parseDate(str.toString(), PARSE_PATTERNS);
|
|
||||||
} catch (ParseException e) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取服务器启动时间
|
|
||||||
*
|
|
||||||
* @return 服务器启动时间的 Date 对象表示
|
|
||||||
*/
|
|
||||||
public static Date getServerStartDate() {
|
|
||||||
long time = ManagementFactory.getRuntimeMXBean().getStartTime();
|
|
||||||
return new Date(time);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 计算两个时间之间的时间差,并以指定单位返回(绝对值)
|
|
||||||
*
|
|
||||||
* @param start 起始时间
|
|
||||||
* @param end 结束时间
|
|
||||||
* @param unit 所需返回的时间单位(DAYS、HOURS、MINUTES、SECONDS、MILLISECONDS、MICROSECONDS、NANOSECONDS)
|
|
||||||
* @return 时间差的绝对值,以指定单位表示
|
|
||||||
*/
|
|
||||||
public static long difference(Date start, Date end, TimeUnit unit) {
|
|
||||||
// 计算时间差,单位为毫秒,取绝对值避免负数
|
|
||||||
long diffInMillis = Math.abs(end.getTime() - start.getTime());
|
|
||||||
|
|
||||||
// 根据目标单位转换时间差
|
|
||||||
return switch (unit) {
|
|
||||||
case DAYS -> diffInMillis / TimeUnit.DAYS.toMillis(1);
|
|
||||||
case HOURS -> diffInMillis / TimeUnit.HOURS.toMillis(1);
|
|
||||||
case MINUTES -> diffInMillis / TimeUnit.MINUTES.toMillis(1);
|
|
||||||
case SECONDS -> diffInMillis / TimeUnit.SECONDS.toMillis(1);
|
|
||||||
case MILLISECONDS -> diffInMillis;
|
|
||||||
case MICROSECONDS -> TimeUnit.MILLISECONDS.toMicros(diffInMillis);
|
|
||||||
case NANOSECONDS -> TimeUnit.MILLISECONDS.toNanos(diffInMillis);
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 计算两个日期之间的时间差,并以天、小时和分钟的格式返回
|
|
||||||
*
|
|
||||||
* @param endDate 结束日期
|
|
||||||
* @param nowDate 当前日期
|
|
||||||
* @return 表示时间差的字符串,格式为"天 小时 分钟"
|
|
||||||
*/
|
|
||||||
public static String getDatePoor(Date endDate, Date nowDate) {
|
|
||||||
long diffInMillis = endDate.getTime() - nowDate.getTime();
|
|
||||||
long day = TimeUnit.MILLISECONDS.toDays(diffInMillis);
|
|
||||||
long hour = TimeUnit.MILLISECONDS.toHours(diffInMillis) % 24;
|
|
||||||
long min = TimeUnit.MILLISECONDS.toMinutes(diffInMillis) % 60;
|
|
||||||
return String.format("%d天 %d小时 %d分钟", day, hour, min);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 计算两个时间点的差值(天、小时、分钟、秒),当值为0时不显示该单位
|
|
||||||
*
|
*
|
||||||
|
* @param startDate 开始时间
|
||||||
* @param endDate 结束时间
|
* @param endDate 结束时间
|
||||||
* @param nowDate 当前时间
|
* @param level 精度级别
|
||||||
* @return 时间差字符串,格式为 "x天 x小时 x分钟 x秒",若为 0 则不显示
|
* @return 格式化时长
|
||||||
*/
|
*/
|
||||||
public static String getTimeDifference(Date endDate, Date nowDate) {
|
public static String formatTimeBetween(Object startDate, Object endDate, BetweenFormatter.Level level) {
|
||||||
long diffInMillis = endDate.getTime() - nowDate.getTime();
|
// 非空校验
|
||||||
long day = TimeUnit.MILLISECONDS.toDays(diffInMillis);
|
Assert.notNull(startDate, "开始时间不能为空");
|
||||||
long hour = TimeUnit.MILLISECONDS.toHours(diffInMillis) % 24;
|
Assert.notNull(endDate, "结束时间不能为空");
|
||||||
long min = TimeUnit.MILLISECONDS.toMinutes(diffInMillis) % 60;
|
Assert.notNull(level, "时间精度级别不能为空");
|
||||||
long sec = TimeUnit.MILLISECONDS.toSeconds(diffInMillis) % 60;
|
|
||||||
// 构建时间差字符串,条件是值不为0才显示
|
// 统一转为Date并校验格式合法性
|
||||||
StringBuilder result = new StringBuilder();
|
Date start = Convert.toDate(startDate);
|
||||||
if (day > 0) {
|
Date end = Convert.toDate(endDate);
|
||||||
result.append(String.format("%d天 ", day));
|
Assert.notNull(start, "开始时间格式错误,无法解析为时间");
|
||||||
}
|
Assert.notNull(end, "结束时间格式错误,无法解析为时间");
|
||||||
if (hour > 0) {
|
|
||||||
result.append(String.format("%d小时 ", hour));
|
long diffMillis = Math.abs(end.getTime() - start.getTime());
|
||||||
}
|
return formatBetween(diffMillis, level);
|
||||||
if (min > 0) {
|
|
||||||
result.append(String.format("%d分钟 ", min));
|
|
||||||
}
|
|
||||||
if (sec > 0) {
|
|
||||||
result.append(String.format("%d秒", sec));
|
|
||||||
}
|
|
||||||
return !result.isEmpty() ? result.toString().trim() : "0秒";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 计算两个 LocalDateTime 时间点的差值(天、小时、分钟、秒),当值为0时不显示该单位
|
* 校验日期范围及最大时间跨度
|
||||||
*
|
|
||||||
* @param endDate 结束时间
|
|
||||||
* @param nowDate 当前时间
|
|
||||||
* @return 时间差字符串,格式为 "x天 x小时 x分钟 x秒",若为 0 则不显示
|
|
||||||
*/
|
|
||||||
public static String getTimeDifference(LocalDateTime endDate, LocalDateTime nowDate) {
|
|
||||||
long diffInMillis = java.time.Duration.between(nowDate, endDate).toMillis();
|
|
||||||
long day = TimeUnit.MILLISECONDS.toDays(diffInMillis);
|
|
||||||
long hour = TimeUnit.MILLISECONDS.toHours(diffInMillis) % 24;
|
|
||||||
long min = TimeUnit.MILLISECONDS.toMinutes(diffInMillis) % 60;
|
|
||||||
long sec = TimeUnit.MILLISECONDS.toSeconds(diffInMillis) % 60;
|
|
||||||
StringBuilder result = new StringBuilder();
|
|
||||||
if (day > 0) {
|
|
||||||
result.append(String.format("%d天 ", day));
|
|
||||||
}
|
|
||||||
if (hour > 0) {
|
|
||||||
result.append(String.format("%d小时 ", hour));
|
|
||||||
}
|
|
||||||
if (min > 0) {
|
|
||||||
result.append(String.format("%d分钟 ", min));
|
|
||||||
}
|
|
||||||
if (sec > 0) {
|
|
||||||
result.append(String.format("%d秒", sec));
|
|
||||||
}
|
|
||||||
return !result.isEmpty() ? result.toString().trim() : "0秒";
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 将 LocalDateTime 对象转换为 Date 对象
|
|
||||||
*
|
|
||||||
* @param temporalAccessor 要转换的 LocalDateTime 对象
|
|
||||||
* @return 转换后的 Date 对象
|
|
||||||
*/
|
|
||||||
public static Date toDate(LocalDateTime temporalAccessor) {
|
|
||||||
ZonedDateTime zdt = temporalAccessor.atZone(ZoneId.systemDefault());
|
|
||||||
return Date.from(zdt.toInstant());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 将 LocalDate 对象转换为 Date 对象
|
|
||||||
*
|
|
||||||
* @param temporalAccessor 要转换的 LocalDate 对象
|
|
||||||
* @return 转换后的 Date 对象
|
|
||||||
*/
|
|
||||||
public static Date toDate(LocalDate temporalAccessor) {
|
|
||||||
LocalDateTime localDateTime = LocalDateTime.of(temporalAccessor, LocalTime.of(0, 0, 0));
|
|
||||||
ZonedDateTime zdt = localDateTime.atZone(ZoneId.systemDefault());
|
|
||||||
return Date.from(zdt.toInstant());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 校验日期范围
|
|
||||||
*
|
*
|
||||||
* @param startDate 开始日期
|
* @param startDate 开始日期
|
||||||
* @param endDate 结束日期
|
* @param endDate 结束日期
|
||||||
* @param maxValue 最大时间跨度的限制值
|
* @param maxValue 最大时间跨度限制值
|
||||||
* @param unit 时间跨度的单位,可选择 "DAYS"、"HOURS" 或 "MINUTES"
|
* @param unit 时间单位
|
||||||
*/
|
*/
|
||||||
public static void validateDateRange(Date startDate, Date endDate, int maxValue, TimeUnit unit) {
|
public static void validateDateRange(Object startDate, Object endDate, int maxValue, TimeUnit unit) {
|
||||||
// 校验结束日期不能早于开始日期
|
// 基础非空校验
|
||||||
if (endDate.before(startDate)) {
|
Assert.notNull(startDate, "开始日期不能为空");
|
||||||
|
Assert.notNull(endDate, "结束日期不能为空");
|
||||||
|
Assert.notNull(unit, "时间单位不能为空");
|
||||||
|
|
||||||
|
// 统一转换并校验时间合法性
|
||||||
|
Date start = Convert.toDate(startDate);
|
||||||
|
Date end = Convert.toDate(endDate);
|
||||||
|
Assert.notNull(start, "开始日期格式错误,无法解析为时间");
|
||||||
|
Assert.notNull(end, "结束日期格式错误,无法解析为时间");
|
||||||
|
|
||||||
|
// 校验结束时间不能早于开始时间
|
||||||
|
if (end.before(start)) {
|
||||||
throw new ServiceException("结束日期不能早于开始日期");
|
throw new ServiceException("结束日期不能早于开始日期");
|
||||||
}
|
}
|
||||||
|
|
||||||
// 计算时间跨度
|
long diffMillis = end.getTime() - start.getTime();
|
||||||
long diffInMillis = endDate.getTime() - startDate.getTime();
|
|
||||||
|
|
||||||
// 根据单位转换时间跨度
|
|
||||||
long diff = switch (unit) {
|
long diff = switch (unit) {
|
||||||
case DAYS -> TimeUnit.MILLISECONDS.toDays(diffInMillis);
|
case DAYS -> TimeUnit.MILLISECONDS.toDays(diffMillis);
|
||||||
case HOURS -> TimeUnit.MILLISECONDS.toHours(diffInMillis);
|
case HOURS -> TimeUnit.MILLISECONDS.toHours(diffMillis);
|
||||||
case MINUTES -> TimeUnit.MILLISECONDS.toMinutes(diffInMillis);
|
case MINUTES -> TimeUnit.MILLISECONDS.toMinutes(diffMillis);
|
||||||
default -> throw new IllegalArgumentException("不支持的时间单位");
|
default -> throw new IllegalArgumentException("不支持的时间单位:" + unit.name());
|
||||||
};
|
};
|
||||||
|
|
||||||
// 校验时间跨度不超过最大限制
|
|
||||||
if (diff > maxValue) {
|
if (diff > maxValue) {
|
||||||
throw new ServiceException("最大时间跨度为 {} {}", maxValue, unit.toString().toLowerCase());
|
String msg = String.format("最大时间跨度为 %d %s", maxValue, unit.name().toLowerCase());
|
||||||
|
throw new ServiceException(msg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -352,7 +101,7 @@ public class DateUtils extends org.apache.commons.lang3.time.DateUtils {
|
|||||||
* @return 时间段描述
|
* @return 时间段描述
|
||||||
*/
|
*/
|
||||||
public static String getTodayHour(Date date) {
|
public static String getTodayHour(Date date) {
|
||||||
int hour = DateUtil.hour(date, true);
|
int hour = hour(date, true);
|
||||||
if (hour <= 6) {
|
if (hour <= 6) {
|
||||||
return "凌晨";
|
return "凌晨";
|
||||||
} else if (hour < 12) {
|
} else if (hour < 12) {
|
||||||
@@ -387,38 +136,37 @@ public class DateUtils extends org.apache.commons.lang3.time.DateUtils {
|
|||||||
if (date == null) {
|
if (date == null) {
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
Date now = DateUtil.date();
|
Date now = new Date();
|
||||||
|
|
||||||
// 未来时间或非今年
|
// 未来时间或非今年
|
||||||
if (date.after(now) || DateUtil.year(date) != DateUtil.year(now)) {
|
if (date.after(now) || year(date) != year(now)) {
|
||||||
return parseDateToStr(FormatsType.YYYY_MM_DD_HH_MM, date);
|
return formatDateTime(now);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 今天
|
// 今天
|
||||||
if (DateUtil.isSameDay(date, now)) {
|
if (isSameDay(date, now)) {
|
||||||
long minutes = DateUtil.between(date, now, DateUnit.MINUTE);
|
long minutes = between(date, now, DateUnit.MINUTE);
|
||||||
if (minutes < 1) {
|
if (minutes < 1) {
|
||||||
return "刚刚";
|
return "刚刚";
|
||||||
}
|
}
|
||||||
if (minutes < 60) {
|
if (minutes < 60) {
|
||||||
return minutes + "分钟前";
|
return minutes + "分钟前";
|
||||||
}
|
}
|
||||||
return getTodayHour(date) + " " + DateUtil.format(date, "HH:mm");
|
return getTodayHour(date) + " " + format(date, "HH:mm");
|
||||||
}
|
}
|
||||||
|
|
||||||
// 昨天
|
// 昨天
|
||||||
if (DateUtil.isSameDay(date, DateUtil.yesterday())) {
|
if (isSameDay(date, yesterday())) {
|
||||||
return "昨天 " + DateUtil.format(date, "HH:mm");
|
return "昨天 " + format(date, "HH:mm");
|
||||||
}
|
}
|
||||||
|
|
||||||
// 本周
|
// 本周
|
||||||
if (DateUtil.isSameWeek(date, now, true)) {
|
if (isSameWeek(date, now, true)) {
|
||||||
return DateUtil.dayOfWeekEnum(date).toChinese("周")
|
return dayOfWeekEnum(date).toChinese("周") + " " + format(date, "HH:mm");
|
||||||
+ " " + DateUtil.format(date, "HH:mm");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 今年内其它时间
|
// 今年内其它时间
|
||||||
return DateUtil.format(date, "MM-dd HH:mm");
|
return format(date, "MM-dd HH:mm");
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
-1
@@ -14,7 +14,6 @@ import java.util.Map;
|
|||||||
* Mapstruct 工具类
|
* Mapstruct 工具类
|
||||||
* <p>参考文档:<a href="https://mapstruct.plus/introduction/quick-start.html">mapstruct-plus</a></p>
|
* <p>参考文档:<a href="https://mapstruct.plus/introduction/quick-start.html">mapstruct-plus</a></p>
|
||||||
*
|
*
|
||||||
*
|
|
||||||
* @author Michelle.Chung
|
* @author Michelle.Chung
|
||||||
*/
|
*/
|
||||||
@NoArgsConstructor(access = AccessLevel.PRIVATE)
|
@NoArgsConstructor(access = AccessLevel.PRIVATE)
|
||||||
|
|||||||
+1
@@ -179,6 +179,7 @@ public class StreamUtils {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取 map 中的数据作为新 Map 的 value ,key 不变
|
* 获取 map 中的数据作为新 Map 的 value ,key 不变
|
||||||
|
*
|
||||||
* @param map 需要处理的map
|
* @param map 需要处理的map
|
||||||
* @param take 取值函数
|
* @param take 取值函数
|
||||||
* @param <K> map中的key类型
|
* @param <K> map中的key类型
|
||||||
|
|||||||
+3
@@ -23,6 +23,8 @@ public class StringUtils extends org.apache.commons.lang3.StringUtils {
|
|||||||
|
|
||||||
public static final String SLASH = "/";
|
public static final String SLASH = "/";
|
||||||
|
|
||||||
|
public static final String COLON = ":";
|
||||||
|
|
||||||
private static final AntPathMatcher ANT_PATH_MATCHER = new AntPathMatcher();
|
private static final AntPathMatcher ANT_PATH_MATCHER = new AntPathMatcher();
|
||||||
|
|
||||||
@Deprecated
|
@Deprecated
|
||||||
@@ -363,6 +365,7 @@ public class StringUtils extends org.apache.commons.lang3.StringUtils {
|
|||||||
return input;
|
return input;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 将可迭代对象中的元素使用逗号拼接成字符串
|
* 将可迭代对象中的元素使用逗号拼接成字符串
|
||||||
*
|
*
|
||||||
|
|||||||
+4
-1
@@ -6,7 +6,10 @@ import lombok.NoArgsConstructor;
|
|||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.concurrent.*;
|
import java.util.concurrent.ExecutionException;
|
||||||
|
import java.util.concurrent.ExecutorService;
|
||||||
|
import java.util.concurrent.Executors;
|
||||||
|
import java.util.concurrent.Future;
|
||||||
import java.util.function.Supplier;
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
+1
-1
@@ -64,7 +64,7 @@ public class TreeBuildUtils extends TreeUtil {
|
|||||||
if (CollUtil.isEmpty(list)) {
|
if (CollUtil.isEmpty(list)) {
|
||||||
return CollUtil.newArrayList();
|
return CollUtil.newArrayList();
|
||||||
}
|
}
|
||||||
K k = ReflectUtils.invokeGetter(list.get(0), "parentId");
|
K k = ReflectUtils.invokeGetter(list.getFirst(), "parentId");
|
||||||
return TreeUtil.build(list, k, DEFAULT_CONFIG, nodeParser);
|
return TreeUtil.build(list, k, DEFAULT_CONFIG, nodeParser);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+3
@@ -26,6 +26,9 @@ public class ValidatorUtils {
|
|||||||
* @throws ConstraintViolationException 如果校验不通过,则抛出参数校验异常
|
* @throws ConstraintViolationException 如果校验不通过,则抛出参数校验异常
|
||||||
*/
|
*/
|
||||||
public static <T> void validate(T object, Class<?>... groups) {
|
public static <T> void validate(T object, Class<?>... groups) {
|
||||||
|
if (object == null) {
|
||||||
|
throw new RuntimeException("请求参数不能为空");
|
||||||
|
}
|
||||||
Set<ConstraintViolation<T>> validate = VALID.validate(object, groups);
|
Set<ConstraintViolation<T>> validate = VALID.validate(object, groups);
|
||||||
if (!validate.isEmpty()) {
|
if (!validate.isEmpty()) {
|
||||||
throw new ConstraintViolationException("参数校验异常", validate);
|
throw new ConstraintViolationException("参数校验异常", validate);
|
||||||
|
|||||||
+61
-16
@@ -1,60 +1,64 @@
|
|||||||
package org.dromara.common.core.utils.file;
|
package org.dromara.common.core.utils.file;
|
||||||
|
|
||||||
|
import cn.hutool.core.util.StrUtil;
|
||||||
|
import lombok.AccessLevel;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 媒体类型工具类
|
* 媒体类型工具类
|
||||||
*
|
*
|
||||||
* @author ruoyi
|
* @author ruoyi
|
||||||
*/
|
*/
|
||||||
|
@NoArgsConstructor(access = AccessLevel.PRIVATE)
|
||||||
public class MimeTypeUtils {
|
public class MimeTypeUtils {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* PNG 图片 MIME 类型。
|
* PNG 图片 MIME 类型
|
||||||
*/
|
*/
|
||||||
public static final String IMAGE_PNG = "image/png";
|
public static final String IMAGE_PNG = "image/png";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* JPG 图片 MIME 类型。
|
* JPG 图片 MIME 类型
|
||||||
*/
|
*/
|
||||||
public static final String IMAGE_JPG = "image/jpg";
|
public static final String IMAGE_JPG = "image/jpg";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* JPEG 图片 MIME 类型。
|
* JPEG 图片 MIME 类型
|
||||||
*/
|
*/
|
||||||
public static final String IMAGE_JPEG = "image/jpeg";
|
public static final String IMAGE_JPEG = "image/jpeg";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* BMP 图片 MIME 类型。
|
* BMP 图片 MIME 类型
|
||||||
*/
|
*/
|
||||||
public static final String IMAGE_BMP = "image/bmp";
|
public static final String IMAGE_BMP = "image/bmp";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* GIF 图片 MIME 类型。
|
* GIF 图片 MIME 类型
|
||||||
*/
|
*/
|
||||||
public static final String IMAGE_GIF = "image/gif";
|
public static final String IMAGE_GIF = "image/gif";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 图片扩展名集合。
|
* 图片扩展名数组
|
||||||
*/
|
*/
|
||||||
public static final String[] IMAGE_EXTENSION = {"bmp", "gif", "jpg", "jpeg", "png"};
|
public static final String[] IMAGE_EXTENSION = {"bmp", "gif", "jpg", "jpeg", "png"};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Flash 扩展名集合。
|
* Flash 文件扩展名数组
|
||||||
*/
|
*/
|
||||||
public static final String[] FLASH_EXTENSION = {"swf", "flv"};
|
public static final String[] FLASH_EXTENSION = {"swf", "flv"};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 媒体扩展名集合。
|
* 视频文件扩展名数组
|
||||||
*/
|
|
||||||
public static final String[] MEDIA_EXTENSION = {"swf", "flv", "mp3", "wav", "wma", "wmv", "mid", "avi", "mpg",
|
|
||||||
"asf", "rm", "rmvb"};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 视频扩展名集合。
|
|
||||||
*/
|
*/
|
||||||
public static final String[] VIDEO_EXTENSION = {"mp4", "avi", "rmvb"};
|
public static final String[] VIDEO_EXTENSION = {"mp4", "avi", "rmvb"};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 默认允许上传扩展名集合。
|
* 媒体文件扩展名数组(音频+视频+Flash)
|
||||||
|
*/
|
||||||
|
public static final String[] MEDIA_EXTENSION = {"swf", "flv", "mp3", "wav", "wma", "wmv", "mid", "avi", "mpg", "asf", "rm", "rmvb"};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 默认允许上传的文件扩展名数组
|
||||||
*/
|
*/
|
||||||
public static final String[] DEFAULT_ALLOWED_EXTENSION = {
|
public static final String[] DEFAULT_ALLOWED_EXTENSION = {
|
||||||
// 图片
|
// 图片
|
||||||
@@ -66,6 +70,47 @@ public class MimeTypeUtils {
|
|||||||
// 视频格式
|
// 视频格式
|
||||||
"mp4", "avi", "rmvb",
|
"mp4", "avi", "rmvb",
|
||||||
// pdf
|
// pdf
|
||||||
"pdf"};
|
"pdf"
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 判断文件扩展名是否为图片格式(忽略大小写)
|
||||||
|
*
|
||||||
|
* @param extension 文件扩展名
|
||||||
|
* @return 是图片返回 true,否则返回 false
|
||||||
|
*/
|
||||||
|
public static boolean isImage(String extension) {
|
||||||
|
return StrUtil.equalsAnyIgnoreCase(extension, IMAGE_EXTENSION);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 判断文件扩展名是否为视频格式(忽略大小写)
|
||||||
|
*
|
||||||
|
* @param extension 文件扩展名
|
||||||
|
* @return 是视频返回 true,否则返回 false
|
||||||
|
*/
|
||||||
|
public static boolean isVideo(String extension) {
|
||||||
|
return StrUtil.equalsAnyIgnoreCase(extension, VIDEO_EXTENSION);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 判断文件扩展名是否为媒体格式(忽略大小写)
|
||||||
|
*
|
||||||
|
* @param extension 文件扩展名
|
||||||
|
* @return 是媒体返回 true,否则返回 false
|
||||||
|
*/
|
||||||
|
public static boolean isMedia(String extension) {
|
||||||
|
return StrUtil.equalsAnyIgnoreCase(extension, MEDIA_EXTENSION);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 判断文件扩展名是否在默认允许上传范围内(忽略大小写)
|
||||||
|
*
|
||||||
|
* @param extension 文件扩展名
|
||||||
|
* @return 允许返回 true,不允许返回 false
|
||||||
|
*/
|
||||||
|
public static boolean isDefaultAllowed(String extension) {
|
||||||
|
return StrUtil.equalsAnyIgnoreCase(extension, DEFAULT_ALLOWED_EXTENSION);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+3
@@ -1,6 +1,8 @@
|
|||||||
package org.dromara.common.core.utils.ip;
|
package org.dromara.common.core.utils.ip;
|
||||||
|
|
||||||
import cn.hutool.core.io.resource.ResourceUtil;
|
import cn.hutool.core.io.resource.ResourceUtil;
|
||||||
|
import lombok.AccessLevel;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.dromara.common.core.exception.ServiceException;
|
import org.dromara.common.core.exception.ServiceException;
|
||||||
import org.dromara.common.core.utils.StringUtils;
|
import org.dromara.common.core.utils.StringUtils;
|
||||||
@@ -19,6 +21,7 @@ import java.time.Duration;
|
|||||||
* @author 秋辞未寒
|
* @author 秋辞未寒
|
||||||
*/
|
*/
|
||||||
@Slf4j
|
@Slf4j
|
||||||
|
@NoArgsConstructor(access = AccessLevel.PRIVATE)
|
||||||
public class RegionUtils {
|
public class RegionUtils {
|
||||||
|
|
||||||
// 默认IPv4地址库文件路径
|
// 默认IPv4地址库文件路径
|
||||||
|
|||||||
+1
-2
@@ -1,9 +1,9 @@
|
|||||||
package org.dromara.common.core.utils.reflect;
|
package org.dromara.common.core.utils.reflect;
|
||||||
|
|
||||||
import cn.hutool.core.util.ReflectUtil;
|
import cn.hutool.core.util.ReflectUtil;
|
||||||
import org.dromara.common.core.utils.StringUtils;
|
|
||||||
import lombok.AccessLevel;
|
import lombok.AccessLevel;
|
||||||
import lombok.NoArgsConstructor;
|
import lombok.NoArgsConstructor;
|
||||||
|
import org.dromara.common.core.utils.StringUtils;
|
||||||
|
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
|
|
||||||
@@ -12,7 +12,6 @@ import java.lang.reflect.Method;
|
|||||||
*
|
*
|
||||||
* @author Lion Li
|
* @author Lion Li
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("rawtypes")
|
|
||||||
@NoArgsConstructor(access = AccessLevel.PRIVATE)
|
@NoArgsConstructor(access = AccessLevel.PRIVATE)
|
||||||
public class ReflectUtils extends ReflectUtil {
|
public class ReflectUtils extends ReflectUtil {
|
||||||
|
|
||||||
|
|||||||
+3
@@ -2,6 +2,8 @@ package org.dromara.common.core.utils.regex;
|
|||||||
|
|
||||||
|
|
||||||
import cn.hutool.core.util.ReUtil;
|
import cn.hutool.core.util.ReUtil;
|
||||||
|
import lombok.AccessLevel;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
import org.dromara.common.core.constant.RegexConstants;
|
import org.dromara.common.core.constant.RegexConstants;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -9,6 +11,7 @@ import org.dromara.common.core.constant.RegexConstants;
|
|||||||
*
|
*
|
||||||
* @author AprilWind
|
* @author AprilWind
|
||||||
*/
|
*/
|
||||||
|
@NoArgsConstructor(access = AccessLevel.PRIVATE)
|
||||||
public final class RegexUtils extends ReUtil {
|
public final class RegexUtils extends ReUtil {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
+3
@@ -2,6 +2,8 @@ package org.dromara.common.core.utils.regex;
|
|||||||
|
|
||||||
import cn.hutool.core.exceptions.ValidateException;
|
import cn.hutool.core.exceptions.ValidateException;
|
||||||
import cn.hutool.core.lang.Validator;
|
import cn.hutool.core.lang.Validator;
|
||||||
|
import lombok.AccessLevel;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
import org.dromara.common.core.factory.RegexPatternPoolFactory;
|
import org.dromara.common.core.factory.RegexPatternPoolFactory;
|
||||||
|
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
@@ -12,6 +14,7 @@ import java.util.regex.Pattern;
|
|||||||
*
|
*
|
||||||
* @author AprilWind
|
* @author AprilWind
|
||||||
*/
|
*/
|
||||||
|
@NoArgsConstructor(access = AccessLevel.PRIVATE)
|
||||||
public class RegexValidator extends Validator {
|
public class RegexValidator extends Validator {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
+4
-1
@@ -3,7 +3,10 @@ package org.dromara.common.core.validate.enums;
|
|||||||
import jakarta.validation.Constraint;
|
import jakarta.validation.Constraint;
|
||||||
import jakarta.validation.Payload;
|
import jakarta.validation.Payload;
|
||||||
|
|
||||||
import java.lang.annotation.*;
|
import java.lang.annotation.Documented;
|
||||||
|
import java.lang.annotation.Repeatable;
|
||||||
|
import java.lang.annotation.Retention;
|
||||||
|
import java.lang.annotation.Target;
|
||||||
|
|
||||||
import static java.lang.annotation.ElementType.*;
|
import static java.lang.annotation.ElementType.*;
|
||||||
import static java.lang.annotation.RetentionPolicy.RUNTIME;
|
import static java.lang.annotation.RetentionPolicy.RUNTIME;
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ package org.dromara.common.core.xss;
|
|||||||
|
|
||||||
import jakarta.validation.Constraint;
|
import jakarta.validation.Constraint;
|
||||||
import jakarta.validation.Payload;
|
import jakarta.validation.Payload;
|
||||||
|
|
||||||
import java.lang.annotation.ElementType;
|
import java.lang.annotation.ElementType;
|
||||||
import java.lang.annotation.Retention;
|
import java.lang.annotation.Retention;
|
||||||
import java.lang.annotation.RetentionPolicy;
|
import java.lang.annotation.RetentionPolicy;
|
||||||
|
|||||||
+1
-1
@@ -6,9 +6,9 @@ import io.swagger.v3.oas.models.info.Info;
|
|||||||
import io.swagger.v3.oas.models.security.SecurityRequirement;
|
import io.swagger.v3.oas.models.security.SecurityRequirement;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import org.dromara.common.core.utils.StringUtils;
|
import org.dromara.common.core.utils.StringUtils;
|
||||||
|
import org.dromara.common.doc.config.properties.SpringDocProperties;
|
||||||
import org.dromara.common.doc.core.customizer.ClassTagOperationCustomizer;
|
import org.dromara.common.doc.core.customizer.ClassTagOperationCustomizer;
|
||||||
import org.dromara.common.doc.core.customizer.JavadocOperationCustomizer;
|
import org.dromara.common.doc.core.customizer.JavadocOperationCustomizer;
|
||||||
import org.dromara.common.doc.config.properties.SpringDocProperties;
|
|
||||||
import org.dromara.common.doc.core.resolver.JavadocResolver;
|
import org.dromara.common.doc.core.resolver.JavadocResolver;
|
||||||
import org.dromara.common.doc.core.resolver.SaTokenAnnotationMetadataJavadocResolver;
|
import org.dromara.common.doc.core.resolver.SaTokenAnnotationMetadataJavadocResolver;
|
||||||
import org.springdoc.core.configuration.SpringDocConfiguration;
|
import org.springdoc.core.configuration.SpringDocConfiguration;
|
||||||
|
|||||||
+1
-1
@@ -56,7 +56,7 @@ public class SpringDocProperties {
|
|||||||
* </p>
|
* </p>
|
||||||
*
|
*
|
||||||
* @see io.swagger.v3.oas.models.info.Info
|
* @see io.swagger.v3.oas.models.info.Info
|
||||||
*
|
* <p>
|
||||||
* 为了 springboot 自动生产配置提示信息,所以这里复制一个类出来
|
* 为了 springboot 自动生产配置提示信息,所以这里复制一个类出来
|
||||||
*/
|
*/
|
||||||
@Data
|
@Data
|
||||||
|
|||||||
+1
-7
@@ -18,13 +18,7 @@ import org.springframework.util.CollectionUtils;
|
|||||||
import org.springframework.web.method.HandlerMethod;
|
import org.springframework.web.method.HandlerMethod;
|
||||||
|
|
||||||
import java.io.StringReader;
|
import java.io.StringReader;
|
||||||
import java.util.ArrayList;
|
import java.util.*;
|
||||||
import java.util.List;
|
|
||||||
import java.util.Locale;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Objects;
|
|
||||||
import java.util.Optional;
|
|
||||||
import java.util.Set;
|
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
import java.util.stream.Stream;
|
import java.util.stream.Stream;
|
||||||
|
|||||||
+11
@@ -82,6 +82,7 @@ public abstract class AbstractMetadataJavadocResolver<M> implements JavadocResol
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 执行解析并返回解析到的 Javadoc 内容
|
* 执行解析并返回解析到的 Javadoc 内容
|
||||||
|
*
|
||||||
* @param handlerMethod 处理器方法
|
* @param handlerMethod 处理器方法
|
||||||
* @param operation Swagger Operation实例
|
* @param operation Swagger Operation实例
|
||||||
* @param metadata 元信息
|
* @param metadata 元信息
|
||||||
@@ -91,6 +92,7 @@ public abstract class AbstractMetadataJavadocResolver<M> implements JavadocResol
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 检查处理器方法所属的类上是否存在注解
|
* 检查处理器方法所属的类上是否存在注解
|
||||||
|
*
|
||||||
* @param handlerMethod 处理器方法
|
* @param handlerMethod 处理器方法
|
||||||
* @param annotationClass 注解类
|
* @param annotationClass 注解类
|
||||||
* @return 是否存在注解
|
* @return 是否存在注解
|
||||||
@@ -101,6 +103,7 @@ public abstract class AbstractMetadataJavadocResolver<M> implements JavadocResol
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 检查处理器方法所属的类上是否存在注解
|
* 检查处理器方法所属的类上是否存在注解
|
||||||
|
*
|
||||||
* @param handlerMethod 处理器方法
|
* @param handlerMethod 处理器方法
|
||||||
* @param annotationTypeName 注解类名称
|
* @param annotationTypeName 注解类名称
|
||||||
* @return 是否存在注解
|
* @return 是否存在注解
|
||||||
@@ -111,6 +114,7 @@ public abstract class AbstractMetadataJavadocResolver<M> implements JavadocResol
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 检查处理器方法上是否存在注解
|
* 检查处理器方法上是否存在注解
|
||||||
|
*
|
||||||
* @param handlerMethod 处理器方法
|
* @param handlerMethod 处理器方法
|
||||||
* @param annotationClass 注解类
|
* @param annotationClass 注解类
|
||||||
* @return 是否存在注解
|
* @return 是否存在注解
|
||||||
@@ -121,6 +125,7 @@ public abstract class AbstractMetadataJavadocResolver<M> implements JavadocResol
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 检查处理器方法上是否存在注解
|
* 检查处理器方法上是否存在注解
|
||||||
|
*
|
||||||
* @param handlerMethod 处理器方法
|
* @param handlerMethod 处理器方法
|
||||||
* @param annotationTypeName 注解类名称
|
* @param annotationTypeName 注解类名称
|
||||||
* @return 是否存在注解
|
* @return 是否存在注解
|
||||||
@@ -131,6 +136,7 @@ public abstract class AbstractMetadataJavadocResolver<M> implements JavadocResol
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 检查处理器方法上是否存在注解
|
* 检查处理器方法上是否存在注解
|
||||||
|
*
|
||||||
* @param handlerMethod 处理器方法
|
* @param handlerMethod 处理器方法
|
||||||
* @param annotationClass 注解类
|
* @param annotationClass 注解类
|
||||||
* @return 是否存在注解
|
* @return 是否存在注解
|
||||||
@@ -141,6 +147,7 @@ public abstract class AbstractMetadataJavadocResolver<M> implements JavadocResol
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 检查处理器方法上是否存在注解
|
* 检查处理器方法上是否存在注解
|
||||||
|
*
|
||||||
* @param handlerMethod 处理器方法
|
* @param handlerMethod 处理器方法
|
||||||
* @param annotationTypeName 注解类名称
|
* @param annotationTypeName 注解类名称
|
||||||
* @return 是否存在注解
|
* @return 是否存在注解
|
||||||
@@ -151,6 +158,7 @@ public abstract class AbstractMetadataJavadocResolver<M> implements JavadocResol
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取处理器方法所属类上的注解的值
|
* 获取处理器方法所属类上的注解的值
|
||||||
|
*
|
||||||
* @param handlerMethod 处理器方法
|
* @param handlerMethod 处理器方法
|
||||||
* @param annotationClass 注解类
|
* @param annotationClass 注解类
|
||||||
* @return 注解的值
|
* @return 注解的值
|
||||||
@@ -161,6 +169,7 @@ public abstract class AbstractMetadataJavadocResolver<M> implements JavadocResol
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取处理器方法所属类上的注解的值
|
* 获取处理器方法所属类上的注解的值
|
||||||
|
*
|
||||||
* @param handlerMethod 处理器方法
|
* @param handlerMethod 处理器方法
|
||||||
* @param annotationClassName 注解类名称
|
* @param annotationClassName 注解类名称
|
||||||
* @return 注解的值
|
* @return 注解的值
|
||||||
@@ -173,6 +182,7 @@ public abstract class AbstractMetadataJavadocResolver<M> implements JavadocResol
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取处理器方法上的注解的值
|
* 获取处理器方法上的注解的值
|
||||||
|
*
|
||||||
* @param handlerMethod 处理器方法
|
* @param handlerMethod 处理器方法
|
||||||
* @param annotationClass 注解类
|
* @param annotationClass 注解类
|
||||||
* @return 注解的值
|
* @return 注解的值
|
||||||
@@ -183,6 +193,7 @@ public abstract class AbstractMetadataJavadocResolver<M> implements JavadocResol
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取处理器方法所属类上的注解的值
|
* 获取处理器方法所属类上的注解的值
|
||||||
|
*
|
||||||
* @param handlerMethod 处理器方法
|
* @param handlerMethod 处理器方法
|
||||||
* @param annotationClassName 注解类名称
|
* @param annotationClassName 注解类名称
|
||||||
* @return 注解的值
|
* @return 注解的值
|
||||||
|
|||||||
+1
-1
@@ -1,8 +1,8 @@
|
|||||||
package org.dromara.common.encrypt.core;
|
package org.dromara.common.encrypt.core;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
import org.dromara.common.encrypt.enums.AlgorithmType;
|
import org.dromara.common.encrypt.enums.AlgorithmType;
|
||||||
import org.dromara.common.encrypt.enums.EncodeType;
|
import org.dromara.common.encrypt.enums.EncodeType;
|
||||||
import lombok.Data;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 加密上下文 用于encryptor传递必要的参数。
|
* 加密上下文 用于encryptor传递必要的参数。
|
||||||
|
|||||||
+1
-1
@@ -21,6 +21,6 @@ public enum EncodeType {
|
|||||||
/**
|
/**
|
||||||
* 16进制编码
|
* 16进制编码
|
||||||
*/
|
*/
|
||||||
HEX;
|
HEX
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+1
@@ -5,6 +5,7 @@ import org.springframework.boot.context.properties.ConfigurationProperties;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* api解密属性配置类
|
* api解密属性配置类
|
||||||
|
*
|
||||||
* @author wdhcr
|
* @author wdhcr
|
||||||
*/
|
*/
|
||||||
@Data
|
@Data
|
||||||
|
|||||||
+1
-1
@@ -1,8 +1,8 @@
|
|||||||
package org.dromara.common.encrypt.properties;
|
package org.dromara.common.encrypt.properties;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
import org.dromara.common.encrypt.enums.AlgorithmType;
|
import org.dromara.common.encrypt.enums.AlgorithmType;
|
||||||
import org.dromara.common.encrypt.enums.EncodeType;
|
import org.dromara.common.encrypt.enums.EncodeType;
|
||||||
import lombok.Data;
|
|
||||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
+1
-1
@@ -6,7 +6,7 @@ import java.lang.annotation.*;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* excel 列单元格合并(合并列相同项)
|
* excel 列单元格合并(合并列相同项)
|
||||||
*
|
* <p>
|
||||||
* 需搭配 {@link CellMergeStrategy} 策略使用
|
* 需搭配 {@link CellMergeStrategy} 策略使用
|
||||||
*
|
*
|
||||||
* @author Lion Li
|
* @author Lion Li
|
||||||
|
|||||||
+1
@@ -7,6 +7,7 @@ import java.lang.annotation.Target;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 批注 此注解仅用于单表头 不支持多层级表头
|
* 批注 此注解仅用于单表头 不支持多层级表头
|
||||||
|
*
|
||||||
* @author guzhouyanyu
|
* @author guzhouyanyu
|
||||||
*/
|
*/
|
||||||
@Target({ElementType.FIELD})
|
@Target({ElementType.FIELD})
|
||||||
|
|||||||
+1
@@ -9,6 +9,7 @@ import java.lang.annotation.Target;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 是否必填 此注解仅用于单表头 不支持多层级表头
|
* 是否必填 此注解仅用于单表头 不支持多层级表头
|
||||||
|
*
|
||||||
* @author guzhouyanyu
|
* @author guzhouyanyu
|
||||||
*/
|
*/
|
||||||
@Target({ElementType.FIELD})
|
@Target({ElementType.FIELD})
|
||||||
|
|||||||
+1
-1
@@ -3,6 +3,7 @@ package org.dromara.common.excel.convert;
|
|||||||
import cn.hutool.core.annotation.AnnotationUtil;
|
import cn.hutool.core.annotation.AnnotationUtil;
|
||||||
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 lombok.extern.slf4j.Slf4j;
|
||||||
import org.apache.fesod.sheet.converters.Converter;
|
import org.apache.fesod.sheet.converters.Converter;
|
||||||
import org.apache.fesod.sheet.enums.CellDataTypeEnum;
|
import org.apache.fesod.sheet.enums.CellDataTypeEnum;
|
||||||
import org.apache.fesod.sheet.metadata.GlobalConfiguration;
|
import org.apache.fesod.sheet.metadata.GlobalConfiguration;
|
||||||
@@ -11,7 +12,6 @@ import org.apache.fesod.sheet.metadata.data.WriteCellData;
|
|||||||
import org.apache.fesod.sheet.metadata.property.ExcelContentProperty;
|
import org.apache.fesod.sheet.metadata.property.ExcelContentProperty;
|
||||||
import org.dromara.common.core.utils.reflect.ReflectUtils;
|
import org.dromara.common.core.utils.reflect.ReflectUtils;
|
||||||
import org.dromara.common.excel.annotation.ExcelEnumFormat;
|
import org.dromara.common.excel.annotation.ExcelEnumFormat;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
|
||||||
|
|
||||||
import java.lang.reflect.Field;
|
import java.lang.reflect.Field;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
|||||||
+2
-2
@@ -3,10 +3,10 @@ package org.dromara.common.excel.core;
|
|||||||
import cn.hutool.core.collection.CollUtil;
|
import cn.hutool.core.collection.CollUtil;
|
||||||
import cn.hutool.core.util.ReflectUtil;
|
import cn.hutool.core.util.ReflectUtil;
|
||||||
import cn.hutool.core.util.StrUtil;
|
import cn.hutool.core.util.StrUtil;
|
||||||
|
import lombok.SneakyThrows;
|
||||||
import org.apache.fesod.sheet.annotation.ExcelIgnore;
|
import org.apache.fesod.sheet.annotation.ExcelIgnore;
|
||||||
import org.apache.fesod.sheet.annotation.ExcelIgnoreUnannotated;
|
import org.apache.fesod.sheet.annotation.ExcelIgnoreUnannotated;
|
||||||
import org.apache.fesod.sheet.annotation.ExcelProperty;
|
import org.apache.fesod.sheet.annotation.ExcelProperty;
|
||||||
import lombok.SneakyThrows;
|
|
||||||
import org.apache.poi.ss.util.CellRangeAddress;
|
import org.apache.poi.ss.util.CellRangeAddress;
|
||||||
import org.dromara.common.core.utils.reflect.ReflectUtils;
|
import org.dromara.common.core.utils.reflect.ReflectUtils;
|
||||||
import org.dromara.common.excel.annotation.CellMerge;
|
import org.dromara.common.excel.annotation.CellMerge;
|
||||||
@@ -66,7 +66,7 @@ public class CellMergeHandler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 获取有合并注解的字段
|
// 获取有合并注解的字段
|
||||||
Map<Field, FieldColumnIndex> mergeFields = getFieldColumnIndexMap(rows.get(0).getClass());
|
Map<Field, FieldColumnIndex> mergeFields = getFieldColumnIndexMap(rows.getFirst().getClass());
|
||||||
// 如果没有需要合并的字段则返回空集
|
// 如果没有需要合并的字段则返回空集
|
||||||
if (CollUtil.isEmpty(mergeFields)) {
|
if (CollUtil.isEmpty(mergeFields)) {
|
||||||
return Collections.emptyList();
|
return Collections.emptyList();
|
||||||
|
|||||||
+4
-4
@@ -1,6 +1,10 @@
|
|||||||
package org.dromara.common.excel.core;
|
package org.dromara.common.excel.core;
|
||||||
|
|
||||||
import cn.hutool.core.util.StrUtil;
|
import cn.hutool.core.util.StrUtil;
|
||||||
|
import jakarta.validation.ConstraintViolation;
|
||||||
|
import jakarta.validation.ConstraintViolationException;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.apache.fesod.sheet.context.AnalysisContext;
|
import org.apache.fesod.sheet.context.AnalysisContext;
|
||||||
import org.apache.fesod.sheet.event.AnalysisEventListener;
|
import org.apache.fesod.sheet.event.AnalysisEventListener;
|
||||||
import org.apache.fesod.sheet.exception.ExcelAnalysisException;
|
import org.apache.fesod.sheet.exception.ExcelAnalysisException;
|
||||||
@@ -8,10 +12,6 @@ import org.apache.fesod.sheet.exception.ExcelDataConvertException;
|
|||||||
import org.dromara.common.core.utils.StreamUtils;
|
import org.dromara.common.core.utils.StreamUtils;
|
||||||
import org.dromara.common.core.utils.ValidatorUtils;
|
import org.dromara.common.core.utils.ValidatorUtils;
|
||||||
import org.dromara.common.json.utils.JsonUtils;
|
import org.dromara.common.json.utils.JsonUtils;
|
||||||
import jakarta.validation.ConstraintViolation;
|
|
||||||
import jakarta.validation.ConstraintViolationException;
|
|
||||||
import lombok.NoArgsConstructor;
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
|
||||||
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|||||||
+31
-5
@@ -25,27 +25,35 @@ import java.util.stream.Collectors;
|
|||||||
@NoArgsConstructor
|
@NoArgsConstructor
|
||||||
@SuppressWarnings("unused")
|
@SuppressWarnings("unused")
|
||||||
public class DropDownOptions {
|
public class DropDownOptions {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 一级下拉所在列index,从0开始算
|
* 一级下拉所在列index,从0开始算
|
||||||
*/
|
*/
|
||||||
private int index = 0;
|
private int index = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 二级下拉所在的index,从0开始算,不能与一级相同
|
* 二级下拉所在的index,从0开始算,不能与一级相同
|
||||||
*/
|
*/
|
||||||
private int nextIndex = 0;
|
private int nextIndex = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 一级下拉所包含的数据
|
* 一级下拉所包含的数据
|
||||||
*/
|
*/
|
||||||
private List<String> options = new ArrayList<>();
|
private List<String> options = new ArrayList<>();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 二级下拉所包含的数据Map
|
* 二级下拉所包含的数据Map
|
||||||
* <p>以每一个一级选项值为Key,每个一级选项对应的二级数据为Value</p>
|
* <p>以每一个一级选项值为Key,每个一级选项对应的二级数据为Value</p>
|
||||||
*/
|
*/
|
||||||
private Map<String, List<String>> nextOptions = new HashMap<>();
|
private Map<String, List<String>> nextOptions = new HashMap<>();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 分隔符
|
* 分隔符
|
||||||
*/
|
*/
|
||||||
private static final String DELIMITER = "_";
|
private static final String DELIMITER = "_";
|
||||||
|
private static final String OPTION_PART_REGEX = "^[A-Za-z0-9\\u4e00-\\u9fa5]+$";
|
||||||
|
private static final String EXCEL_NAME_REGEX = "^[A-Za-z_\\u4e00-\\u9fa5][A-Za-z0-9_\\u4e00-\\u9fa5]*$";
|
||||||
|
private static final String CELL_REFERENCE_REGEX = "^[A-Za-z]{1,3}[1-9][0-9]*$";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 创建只有一级的下拉选
|
* 创建只有一级的下拉选
|
||||||
@@ -64,10 +72,9 @@ public class DropDownOptions {
|
|||||||
*/
|
*/
|
||||||
public static String createOptionValue(Object... vars) {
|
public static String createOptionValue(Object... vars) {
|
||||||
StringBuilder stringBuffer = new StringBuilder();
|
StringBuilder stringBuffer = new StringBuilder();
|
||||||
String regex = "^[\\S\\d\\u4e00-\\u9fa5]+$";
|
|
||||||
for (int i = 0; i < vars.length; i++) {
|
for (int i = 0; i < vars.length; i++) {
|
||||||
String var = StrUtil.trimToEmpty(Convert.toStr(vars[i]));
|
String var = StrUtil.trimToEmpty(Convert.toStr(vars[i]));
|
||||||
if (!var.matches(regex)) {
|
if (!var.matches(OPTION_PART_REGEX)) {
|
||||||
throw new ServiceException("选项数据不符合规则,仅允许使用中英文字符以及数字");
|
throw new ServiceException("选项数据不符合规则,仅允许使用中英文字符以及数字");
|
||||||
}
|
}
|
||||||
stringBuffer.append(var);
|
stringBuffer.append(var);
|
||||||
@@ -76,10 +83,29 @@ public class DropDownOptions {
|
|||||||
stringBuffer.append(DELIMITER);
|
stringBuffer.append(DELIMITER);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (stringBuffer.toString().matches("^\\d_*$")) {
|
String optionValue = stringBuffer.toString();
|
||||||
|
validateOptionValue(optionValue);
|
||||||
|
return optionValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 校验级联下拉选项值是否可作为 Excel 名称管理器名称。
|
||||||
|
*
|
||||||
|
* @param optionValue 选项值
|
||||||
|
*/
|
||||||
|
public static void validateOptionValue(String optionValue) {
|
||||||
|
if (StrUtil.isBlank(optionValue)) {
|
||||||
|
throw new ServiceException("选项数据不能为空");
|
||||||
|
}
|
||||||
|
if (optionValue.matches("^[0-9].*")) {
|
||||||
throw new ServiceException("禁止以数字开头");
|
throw new ServiceException("禁止以数字开头");
|
||||||
}
|
}
|
||||||
return stringBuffer.toString();
|
if (!optionValue.matches(EXCEL_NAME_REGEX)) {
|
||||||
|
throw new ServiceException("选项数据不符合Excel名称规则,仅允许中英文、数字或下划线,且不能以数字开头");
|
||||||
|
}
|
||||||
|
if (optionValue.matches(CELL_REFERENCE_REGEX)) {
|
||||||
|
throw new ServiceException("选项数据不能为Excel单元格引用");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -128,7 +154,7 @@ public class DropDownOptions {
|
|||||||
sonList.forEach(everySon -> {
|
sonList.forEach(everySon -> {
|
||||||
if (parentGroupByIdMap.containsKey(sonHowToGetParentIdFunction.apply(everySon))) {
|
if (parentGroupByIdMap.containsKey(sonHowToGetParentIdFunction.apply(everySon))) {
|
||||||
// 找到对应的上级
|
// 找到对应的上级
|
||||||
T parentObj = parentGroupByIdMap.get(sonHowToGetParentIdFunction.apply(everySon)).get(0);
|
T parentObj = parentGroupByIdMap.get(sonHowToGetParentIdFunction.apply(everySon)).getFirst();
|
||||||
// 提取名称和ID作为Key
|
// 提取名称和ID作为Key
|
||||||
String key = howToBuildEveryOption.apply(parentObj);
|
String key = howToBuildEveryOption.apply(parentObj);
|
||||||
// Key对应的Value
|
// Key对应的Value
|
||||||
|
|||||||
+16
-2
@@ -202,6 +202,7 @@ public class ExcelDownHandler implements SheetWriteHandler {
|
|||||||
if (CollUtil.isEmpty(firstOptions)) {
|
if (CollUtil.isEmpty(firstOptions)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
validateLinkedOptionNames(firstOptions);
|
||||||
Map<String, List<String>> secoundOptionsMap = new HashMap<>();
|
Map<String, List<String>> secoundOptionsMap = new HashMap<>();
|
||||||
options.getNextOptions().forEach((k, v) -> secoundOptionsMap.put(k, new ArrayList<>(v)));
|
options.getNextOptions().forEach((k, v) -> secoundOptionsMap.put(k, new ArrayList<>(v)));
|
||||||
|
|
||||||
@@ -281,10 +282,10 @@ public class ExcelDownHandler implements SheetWriteHandler {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
// 取第一个
|
// 取第一个
|
||||||
String str = data.get(0);
|
String str = data.getFirst();
|
||||||
rowData.add(str);
|
rowData.add(str);
|
||||||
// 通过移除的方式避免重复
|
// 通过移除的方式避免重复
|
||||||
data.remove(0);
|
data.removeFirst();
|
||||||
// 设置可以继续
|
// 设置可以继续
|
||||||
flag = true;
|
flag = true;
|
||||||
}
|
}
|
||||||
@@ -313,6 +314,19 @@ public class ExcelDownHandler implements SheetWriteHandler {
|
|||||||
currentLinkedOptionsSheetIndex++;
|
currentLinkedOptionsSheetIndex++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 校验级联下拉一级选项可作为 Excel 名称,且不能重复。
|
||||||
|
*/
|
||||||
|
private void validateLinkedOptionNames(List<String> firstOptions) {
|
||||||
|
Set<String> names = new HashSet<>();
|
||||||
|
for (String firstOption : firstOptions) {
|
||||||
|
DropDownOptions.validateOptionValue(firstOption);
|
||||||
|
if (!names.add(firstOption)) {
|
||||||
|
throw new ServiceException("级联下拉一级选项重复:" + firstOption);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <h2>额外表格形式的普通下拉框</h2>
|
* <h2>额外表格形式的普通下拉框</h2>
|
||||||
* 由于下拉框可选值数量过多,为提升Excel打开效率,使用额外表格形式做下拉
|
* 由于下拉框可选值数量过多,为提升Excel打开效率,使用额外表格形式做下拉
|
||||||
|
|||||||
+2
-11
@@ -25,19 +25,10 @@ import org.apache.fesod.sheet.write.style.row.SimpleRowHeightStyleStrategy;
|
|||||||
import org.dromara.common.core.utils.StringUtils;
|
import org.dromara.common.core.utils.StringUtils;
|
||||||
import org.dromara.common.core.utils.file.FileUtils;
|
import org.dromara.common.core.utils.file.FileUtils;
|
||||||
import org.dromara.common.excel.convert.ExcelBigNumberConvert;
|
import org.dromara.common.excel.convert.ExcelBigNumberConvert;
|
||||||
import org.dromara.common.excel.core.CellMergeStrategy;
|
import org.dromara.common.excel.core.*;
|
||||||
import org.dromara.common.excel.core.DefaultExcelListener;
|
|
||||||
import org.dromara.common.excel.core.DropDownOptions;
|
|
||||||
import org.dromara.common.excel.core.ExcelDownHandler;
|
|
||||||
import org.dromara.common.excel.core.ExcelListener;
|
|
||||||
import org.dromara.common.excel.core.ExcelResult;
|
|
||||||
import org.dromara.common.excel.handler.DataWriteHandler;
|
import org.dromara.common.excel.handler.DataWriteHandler;
|
||||||
|
|
||||||
import java.io.ByteArrayOutputStream;
|
import java.io.*;
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.InputStream;
|
|
||||||
import java.io.OutputStream;
|
|
||||||
import java.io.UnsupportedEncodingException;
|
|
||||||
import java.net.URLEncoder;
|
import java.net.URLEncoder;
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
|||||||
-6
@@ -125,8 +125,6 @@ public record ExcelWriterWrapper<T>(ExcelWriter excelWriter) {
|
|||||||
return new ExcelWriterWrapper<>(excelWriter);
|
return new ExcelWriterWrapper<>(excelWriter);
|
||||||
}
|
}
|
||||||
|
|
||||||
// -------------------------------- sheet start
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 创建工作表。
|
* 创建工作表。
|
||||||
*
|
*
|
||||||
@@ -207,10 +205,6 @@ public record ExcelWriterWrapper<T>(ExcelWriter excelWriter) {
|
|||||||
return FesodSheet.writerSheet();
|
return FesodSheet.writerSheet();
|
||||||
}
|
}
|
||||||
|
|
||||||
// -------------------------------- sheet end
|
|
||||||
|
|
||||||
// -------------------------------- table start
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 创建表格。
|
* 创建表格。
|
||||||
*
|
*
|
||||||
|
|||||||
+7
-3
@@ -109,17 +109,21 @@ public class JsonValueEnhancer {
|
|||||||
* @param visited 已访问对象集合,用于避免循环引用
|
* @param visited 已访问对象集合,用于避免循环引用
|
||||||
*/
|
*/
|
||||||
private void collectValue(Object value, JsonEnhancementContext context, IdentityHashMap<Object, Boolean> visited) {
|
private void collectValue(Object value, JsonEnhancementContext context, IdentityHashMap<Object, Boolean> visited) {
|
||||||
if (value == null) {
|
switch (value) {
|
||||||
|
case null -> {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (value instanceof Map<?, ?> map) {
|
case Map<?, ?> map -> {
|
||||||
map.values().forEach(child -> collectValue(child, context, visited));
|
map.values().forEach(child -> collectValue(child, context, visited));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (value instanceof Iterable<?> iterable) {
|
case Iterable<?> iterable -> {
|
||||||
iterable.forEach(child -> collectValue(child, context, visited));
|
iterable.forEach(child -> collectValue(child, context, visited));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
default -> {
|
||||||
|
}
|
||||||
|
}
|
||||||
if (value.getClass().isArray()) {
|
if (value.getClass().isArray()) {
|
||||||
int length = Array.getLength(value);
|
int length = Array.getLength(value);
|
||||||
for (int i = 0; i < length; i++) {
|
for (int i = 0; i < length; i++) {
|
||||||
|
|||||||
+4
-5
@@ -13,6 +13,10 @@ import tools.jackson.databind.ser.jdk.NumberSerializer;
|
|||||||
@JacksonStdImpl
|
@JacksonStdImpl
|
||||||
public class BigNumberSerializer extends NumberSerializer {
|
public class BigNumberSerializer extends NumberSerializer {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 提供实例
|
||||||
|
*/
|
||||||
|
public static final BigNumberSerializer INSTANCE = new BigNumberSerializer(Number.class);
|
||||||
/**
|
/**
|
||||||
* 根据 JS Number.MAX_SAFE_INTEGER 与 Number.MIN_SAFE_INTEGER 得来
|
* 根据 JS Number.MAX_SAFE_INTEGER 与 Number.MIN_SAFE_INTEGER 得来
|
||||||
*/
|
*/
|
||||||
@@ -22,11 +26,6 @@ public class BigNumberSerializer extends NumberSerializer {
|
|||||||
*/
|
*/
|
||||||
private static final long MIN_SAFE_INTEGER = -9007199254740991L;
|
private static final long MIN_SAFE_INTEGER = -9007199254740991L;
|
||||||
|
|
||||||
/**
|
|
||||||
* 提供实例
|
|
||||||
*/
|
|
||||||
public static final BigNumberSerializer INSTANCE = new BigNumberSerializer(Number.class);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 构造大数字序列化器。
|
* 构造大数字序列化器。
|
||||||
*
|
*
|
||||||
|
|||||||
+1
-1
@@ -9,9 +9,9 @@ import jakarta.servlet.http.HttpServletResponse;
|
|||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.apache.commons.lang3.time.StopWatch;
|
import org.apache.commons.lang3.time.StopWatch;
|
||||||
import org.aspectj.lang.JoinPoint;
|
import org.aspectj.lang.JoinPoint;
|
||||||
import org.aspectj.lang.annotation.Aspect;
|
|
||||||
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.dromara.common.core.constant.SystemConstants;
|
import org.dromara.common.core.constant.SystemConstants;
|
||||||
import org.dromara.common.core.utils.ServletUtils;
|
import org.dromara.common.core.utils.ServletUtils;
|
||||||
import org.dromara.common.core.utils.SpringUtils;
|
import org.dromara.common.core.utils.SpringUtils;
|
||||||
|
|||||||
+1
-2
@@ -1,8 +1,7 @@
|
|||||||
package org.dromara.common.log.event;
|
package org.dromara.common.log.event;
|
||||||
|
|
||||||
import lombok.Data;
|
|
||||||
|
|
||||||
import jakarta.servlet.http.HttpServletRequest;
|
import jakarta.servlet.http.HttpServletRequest;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
import java.io.Serial;
|
import java.io.Serial;
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
|
|||||||
+3
-3
@@ -1,5 +1,8 @@
|
|||||||
package org.dromara.common.mqtt.config;
|
package org.dromara.common.mqtt.config;
|
||||||
|
|
||||||
|
import net.dreamlu.mica.net.utils.thread.ThreadUtils;
|
||||||
|
import net.dreamlu.mica.net.utils.thread.pool.SynThreadPoolExecutor;
|
||||||
|
import net.dreamlu.mica.net.utils.thread.pool.TioCallerRunsPolicy;
|
||||||
import org.dromara.common.mqtt.listener.MqttClientConnectListener;
|
import org.dromara.common.mqtt.listener.MqttClientConnectListener;
|
||||||
import org.dromara.common.mqtt.listener.MqttClientGlobalMessageListener;
|
import org.dromara.common.mqtt.listener.MqttClientGlobalMessageListener;
|
||||||
import org.dromara.mica.mqtt.core.client.MqttClientCreator;
|
import org.dromara.mica.mqtt.core.client.MqttClientCreator;
|
||||||
@@ -8,9 +11,6 @@ import org.springframework.boot.autoconfigure.AutoConfiguration;
|
|||||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||||
import org.springframework.context.annotation.Bean;
|
import org.springframework.context.annotation.Bean;
|
||||||
import org.springframework.core.task.VirtualThreadTaskExecutor;
|
import org.springframework.core.task.VirtualThreadTaskExecutor;
|
||||||
import org.tio.utils.thread.ThreadUtils;
|
|
||||||
import org.tio.utils.thread.pool.SynThreadPoolExecutor;
|
|
||||||
import org.tio.utils.thread.pool.TioCallerRunsPolicy;
|
|
||||||
|
|
||||||
import java.util.concurrent.LinkedBlockingQueue;
|
import java.util.concurrent.LinkedBlockingQueue;
|
||||||
import java.util.concurrent.ThreadFactory;
|
import java.util.concurrent.ThreadFactory;
|
||||||
|
|||||||
+1
-1
@@ -1,9 +1,9 @@
|
|||||||
package org.dromara.common.mqtt.listener;
|
package org.dromara.common.mqtt.listener;
|
||||||
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import net.dreamlu.mica.net.core.ChannelContext;
|
||||||
import org.dromara.mica.mqtt.core.client.IMqttClientConnectListener;
|
import org.dromara.mica.mqtt.core.client.IMqttClientConnectListener;
|
||||||
import org.dromara.mica.mqtt.core.client.MqttClientCreator;
|
import org.dromara.mica.mqtt.core.client.MqttClientCreator;
|
||||||
import org.tio.core.ChannelContext;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 客户端连接状态监听
|
* 客户端连接状态监听
|
||||||
|
|||||||
+1
-1
@@ -1,9 +1,9 @@
|
|||||||
package org.dromara.common.mqtt.listener;
|
package org.dromara.common.mqtt.listener;
|
||||||
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import net.dreamlu.mica.net.core.ChannelContext;
|
||||||
import org.dromara.mica.mqtt.codec.message.MqttPublishMessage;
|
import org.dromara.mica.mqtt.codec.message.MqttPublishMessage;
|
||||||
import org.dromara.mica.mqtt.core.client.IMqttClientGlobalMessageListener;
|
import org.dromara.mica.mqtt.core.client.IMqttClientGlobalMessageListener;
|
||||||
import org.tio.core.ChannelContext;
|
|
||||||
|
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
|
|
||||||
|
|||||||
+2
@@ -122,6 +122,7 @@ public class LambdaCrudChainWrapper<T, V> extends AbstractLambdaWrapper<T, Lambd
|
|||||||
* @param columns 查询字段
|
* @param columns 查询字段
|
||||||
* @return this
|
* @return this
|
||||||
*/
|
*/
|
||||||
|
@Override
|
||||||
@SafeVarargs
|
@SafeVarargs
|
||||||
public final LambdaCrudChainWrapper<T, V> select(SFunction<T, ?>... columns) {
|
public final LambdaCrudChainWrapper<T, V> select(SFunction<T, ?>... columns) {
|
||||||
return select(true, CollectionUtils.toList(columns));
|
return select(true, CollectionUtils.toList(columns));
|
||||||
@@ -134,6 +135,7 @@ public class LambdaCrudChainWrapper<T, V> extends AbstractLambdaWrapper<T, Lambd
|
|||||||
* @param columns 查询字段
|
* @param columns 查询字段
|
||||||
* @return this
|
* @return this
|
||||||
*/
|
*/
|
||||||
|
@Override
|
||||||
@SafeVarargs
|
@SafeVarargs
|
||||||
public final LambdaCrudChainWrapper<T, V> select(boolean condition, SFunction<T, ?>... columns) {
|
public final LambdaCrudChainWrapper<T, V> select(boolean condition, SFunction<T, ?>... columns) {
|
||||||
return select(condition, CollectionUtils.toList(columns));
|
return select(condition, CollectionUtils.toList(columns));
|
||||||
|
|||||||
+3
-6
@@ -5,6 +5,8 @@ import com.baomidou.mybatisplus.core.toolkit.Constants;
|
|||||||
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
|
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
|
||||||
import com.baomidou.mybatisplus.core.toolkit.support.LambdaMeta;
|
import com.baomidou.mybatisplus.core.toolkit.support.LambdaMeta;
|
||||||
import com.baomidou.mybatisplus.core.toolkit.support.SFunction;
|
import com.baomidou.mybatisplus.core.toolkit.support.SFunction;
|
||||||
|
import lombok.AccessLevel;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
import org.apache.ibatis.reflection.property.PropertyNamer;
|
import org.apache.ibatis.reflection.property.PropertyNamer;
|
||||||
|
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
@@ -14,6 +16,7 @@ import java.util.regex.Pattern;
|
|||||||
*
|
*
|
||||||
* @author Lion Li
|
* @author Lion Li
|
||||||
*/
|
*/
|
||||||
|
@NoArgsConstructor(access = AccessLevel.PRIVATE)
|
||||||
public final class AggregateSelectUtils {
|
public final class AggregateSelectUtils {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -21,12 +24,6 @@ public final class AggregateSelectUtils {
|
|||||||
*/
|
*/
|
||||||
private static final Pattern ALIAS_PATTERN = Pattern.compile("[A-Za-z_][A-Za-z0-9_]*");
|
private static final Pattern ALIAS_PATTERN = Pattern.compile("[A-Za-z_][A-Za-z0-9_]*");
|
||||||
|
|
||||||
/**
|
|
||||||
* 工具类不允许实例化。
|
|
||||||
*/
|
|
||||||
private AggregateSelectUtils() {
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 追加查询字段 SQL。
|
* 追加查询字段 SQL。
|
||||||
*
|
*
|
||||||
|
|||||||
+19
-3
@@ -400,6 +400,7 @@ public final class LambdaQueryBuilder<T> implements LambdaQueryCondition<T, Lamb
|
|||||||
* @param value 条件值
|
* @param value 条件值
|
||||||
* @return 当前查询构造辅助对象
|
* @return 当前查询构造辅助对象
|
||||||
*/
|
*/
|
||||||
|
@Override
|
||||||
public LambdaQueryBuilder<T> eq(boolean condition, SFunction<T, ?> column, Object value) {
|
public LambdaQueryBuilder<T> eq(boolean condition, SFunction<T, ?> column, Object value) {
|
||||||
wrapper.eq(condition, column, value);
|
wrapper.eq(condition, column, value);
|
||||||
return this;
|
return this;
|
||||||
@@ -425,6 +426,7 @@ public final class LambdaQueryBuilder<T> implements LambdaQueryCondition<T, Lamb
|
|||||||
* @param value 条件值
|
* @param value 条件值
|
||||||
* @return 当前查询构造辅助对象
|
* @return 当前查询构造辅助对象
|
||||||
*/
|
*/
|
||||||
|
@Override
|
||||||
public LambdaQueryBuilder<T> ne(boolean condition, SFunction<T, ?> column, Object value) {
|
public LambdaQueryBuilder<T> ne(boolean condition, SFunction<T, ?> column, Object value) {
|
||||||
wrapper.ne(condition, column, value);
|
wrapper.ne(condition, column, value);
|
||||||
return this;
|
return this;
|
||||||
@@ -450,6 +452,7 @@ public final class LambdaQueryBuilder<T> implements LambdaQueryCondition<T, Lamb
|
|||||||
* @param value 条件值
|
* @param value 条件值
|
||||||
* @return 当前查询构造辅助对象
|
* @return 当前查询构造辅助对象
|
||||||
*/
|
*/
|
||||||
|
@Override
|
||||||
public LambdaQueryBuilder<T> gt(boolean condition, SFunction<T, ?> column, Object value) {
|
public LambdaQueryBuilder<T> gt(boolean condition, SFunction<T, ?> column, Object value) {
|
||||||
wrapper.gt(condition, column, value);
|
wrapper.gt(condition, column, value);
|
||||||
return this;
|
return this;
|
||||||
@@ -475,6 +478,7 @@ public final class LambdaQueryBuilder<T> implements LambdaQueryCondition<T, Lamb
|
|||||||
* @param value 条件值
|
* @param value 条件值
|
||||||
* @return 当前查询构造辅助对象
|
* @return 当前查询构造辅助对象
|
||||||
*/
|
*/
|
||||||
|
@Override
|
||||||
public LambdaQueryBuilder<T> ge(boolean condition, SFunction<T, ?> column, Object value) {
|
public LambdaQueryBuilder<T> ge(boolean condition, SFunction<T, ?> column, Object value) {
|
||||||
wrapper.ge(condition, column, value);
|
wrapper.ge(condition, column, value);
|
||||||
return this;
|
return this;
|
||||||
@@ -500,6 +504,7 @@ public final class LambdaQueryBuilder<T> implements LambdaQueryCondition<T, Lamb
|
|||||||
* @param value 条件值
|
* @param value 条件值
|
||||||
* @return 当前查询构造辅助对象
|
* @return 当前查询构造辅助对象
|
||||||
*/
|
*/
|
||||||
|
@Override
|
||||||
public LambdaQueryBuilder<T> lt(boolean condition, SFunction<T, ?> column, Object value) {
|
public LambdaQueryBuilder<T> lt(boolean condition, SFunction<T, ?> column, Object value) {
|
||||||
wrapper.lt(condition, column, value);
|
wrapper.lt(condition, column, value);
|
||||||
return this;
|
return this;
|
||||||
@@ -525,6 +530,7 @@ public final class LambdaQueryBuilder<T> implements LambdaQueryCondition<T, Lamb
|
|||||||
* @param value 条件值
|
* @param value 条件值
|
||||||
* @return 当前查询构造辅助对象
|
* @return 当前查询构造辅助对象
|
||||||
*/
|
*/
|
||||||
|
@Override
|
||||||
public LambdaQueryBuilder<T> le(boolean condition, SFunction<T, ?> column, Object value) {
|
public LambdaQueryBuilder<T> le(boolean condition, SFunction<T, ?> column, Object value) {
|
||||||
wrapper.le(condition, column, value);
|
wrapper.le(condition, column, value);
|
||||||
return this;
|
return this;
|
||||||
@@ -550,6 +556,7 @@ public final class LambdaQueryBuilder<T> implements LambdaQueryCondition<T, Lamb
|
|||||||
* @param value 条件值
|
* @param value 条件值
|
||||||
* @return 当前查询构造辅助对象
|
* @return 当前查询构造辅助对象
|
||||||
*/
|
*/
|
||||||
|
@Override
|
||||||
public LambdaQueryBuilder<T> like(boolean condition, SFunction<T, ?> column, Object value) {
|
public LambdaQueryBuilder<T> like(boolean condition, SFunction<T, ?> column, Object value) {
|
||||||
wrapper.like(condition, column, value);
|
wrapper.like(condition, column, value);
|
||||||
return this;
|
return this;
|
||||||
@@ -575,6 +582,7 @@ public final class LambdaQueryBuilder<T> implements LambdaQueryCondition<T, Lamb
|
|||||||
* @param value 条件值
|
* @param value 条件值
|
||||||
* @return 当前查询构造辅助对象
|
* @return 当前查询构造辅助对象
|
||||||
*/
|
*/
|
||||||
|
@Override
|
||||||
public LambdaQueryBuilder<T> notLike(boolean condition, SFunction<T, ?> column, Object value) {
|
public LambdaQueryBuilder<T> notLike(boolean condition, SFunction<T, ?> column, Object value) {
|
||||||
wrapper.notLike(condition, column, value);
|
wrapper.notLike(condition, column, value);
|
||||||
return this;
|
return this;
|
||||||
@@ -600,6 +608,7 @@ public final class LambdaQueryBuilder<T> implements LambdaQueryCondition<T, Lamb
|
|||||||
* @param value 条件值
|
* @param value 条件值
|
||||||
* @return 当前查询构造辅助对象
|
* @return 当前查询构造辅助对象
|
||||||
*/
|
*/
|
||||||
|
@Override
|
||||||
public LambdaQueryBuilder<T> likeLeft(boolean condition, SFunction<T, ?> column, Object value) {
|
public LambdaQueryBuilder<T> likeLeft(boolean condition, SFunction<T, ?> column, Object value) {
|
||||||
wrapper.likeLeft(condition, column, value);
|
wrapper.likeLeft(condition, column, value);
|
||||||
return this;
|
return this;
|
||||||
@@ -625,6 +634,7 @@ public final class LambdaQueryBuilder<T> implements LambdaQueryCondition<T, Lamb
|
|||||||
* @param value 条件值
|
* @param value 条件值
|
||||||
* @return 当前查询构造辅助对象
|
* @return 当前查询构造辅助对象
|
||||||
*/
|
*/
|
||||||
|
@Override
|
||||||
public LambdaQueryBuilder<T> likeRight(boolean condition, SFunction<T, ?> column, Object value) {
|
public LambdaQueryBuilder<T> likeRight(boolean condition, SFunction<T, ?> column, Object value) {
|
||||||
wrapper.likeRight(condition, column, value);
|
wrapper.likeRight(condition, column, value);
|
||||||
return this;
|
return this;
|
||||||
@@ -652,6 +662,7 @@ public final class LambdaQueryBuilder<T> implements LambdaQueryCondition<T, Lamb
|
|||||||
* @param end 结束值
|
* @param end 结束值
|
||||||
* @return 当前查询构造辅助对象
|
* @return 当前查询构造辅助对象
|
||||||
*/
|
*/
|
||||||
|
@Override
|
||||||
public LambdaQueryBuilder<T> between(boolean condition, SFunction<T, ?> column, Object begin, Object end) {
|
public LambdaQueryBuilder<T> between(boolean condition, SFunction<T, ?> column, Object begin, Object end) {
|
||||||
wrapper.between(condition, column, begin, end);
|
wrapper.between(condition, column, begin, end);
|
||||||
return this;
|
return this;
|
||||||
@@ -679,6 +690,7 @@ public final class LambdaQueryBuilder<T> implements LambdaQueryCondition<T, Lamb
|
|||||||
* @param end 结束值
|
* @param end 结束值
|
||||||
* @return 当前查询构造辅助对象
|
* @return 当前查询构造辅助对象
|
||||||
*/
|
*/
|
||||||
|
@Override
|
||||||
public LambdaQueryBuilder<T> notBetween(boolean condition, SFunction<T, ?> column, Object begin, Object end) {
|
public LambdaQueryBuilder<T> notBetween(boolean condition, SFunction<T, ?> column, Object begin, Object end) {
|
||||||
wrapper.notBetween(condition, column, begin, end);
|
wrapper.notBetween(condition, column, begin, end);
|
||||||
return this;
|
return this;
|
||||||
@@ -718,7 +730,7 @@ public final class LambdaQueryBuilder<T> implements LambdaQueryCondition<T, Lamb
|
|||||||
* @return 当前查询构造辅助对象
|
* @return 当前查询构造辅助对象
|
||||||
*/
|
*/
|
||||||
public LambdaQueryBuilder<T> allEq(BiPredicate<SFunction<T, ?>, Object> filter, Map<?, ?> params, boolean null2IsNull) {
|
public LambdaQueryBuilder<T> allEq(BiPredicate<SFunction<T, ?>, Object> filter, Map<?, ?> params, boolean null2IsNull) {
|
||||||
wrapper.allEq(true, (BiPredicate) filter, (Map) params, null2IsNull);
|
wrapper.allEq(true, filter, (Map) params, null2IsNull);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -732,7 +744,7 @@ public final class LambdaQueryBuilder<T> implements LambdaQueryCondition<T, Lamb
|
|||||||
* @return 当前查询构造辅助对象
|
* @return 当前查询构造辅助对象
|
||||||
*/
|
*/
|
||||||
public LambdaQueryBuilder<T> allEq(boolean condition, BiPredicate<SFunction<T, ?>, Object> filter, Map<?, ?> params, boolean null2IsNull) {
|
public LambdaQueryBuilder<T> allEq(boolean condition, BiPredicate<SFunction<T, ?>, Object> filter, Map<?, ?> params, boolean null2IsNull) {
|
||||||
wrapper.allEq(condition, (BiPredicate) filter, (Map) params, null2IsNull);
|
wrapper.allEq(condition, filter, (Map) params, null2IsNull);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -802,6 +814,7 @@ public final class LambdaQueryBuilder<T> implements LambdaQueryCondition<T, Lamb
|
|||||||
* @param values 条件值集合
|
* @param values 条件值集合
|
||||||
* @return 当前查询构造辅助对象
|
* @return 当前查询构造辅助对象
|
||||||
*/
|
*/
|
||||||
|
@Override
|
||||||
public LambdaQueryBuilder<T> in(boolean condition, SFunction<T, ?> column, Collection<?> values) {
|
public LambdaQueryBuilder<T> in(boolean condition, SFunction<T, ?> column, Collection<?> values) {
|
||||||
wrapper.in(condition, column, values);
|
wrapper.in(condition, column, values);
|
||||||
return this;
|
return this;
|
||||||
@@ -827,6 +840,7 @@ public final class LambdaQueryBuilder<T> implements LambdaQueryCondition<T, Lamb
|
|||||||
* @param values 条件值数组
|
* @param values 条件值数组
|
||||||
* @return 当前查询构造辅助对象
|
* @return 当前查询构造辅助对象
|
||||||
*/
|
*/
|
||||||
|
@Override
|
||||||
public LambdaQueryBuilder<T> in(boolean condition, SFunction<T, ?> column, Object... values) {
|
public LambdaQueryBuilder<T> in(boolean condition, SFunction<T, ?> column, Object... values) {
|
||||||
wrapper.in(condition, column, values);
|
wrapper.in(condition, column, values);
|
||||||
return this;
|
return this;
|
||||||
@@ -852,6 +866,7 @@ public final class LambdaQueryBuilder<T> implements LambdaQueryCondition<T, Lamb
|
|||||||
* @param values 条件值集合
|
* @param values 条件值集合
|
||||||
* @return 当前查询构造辅助对象
|
* @return 当前查询构造辅助对象
|
||||||
*/
|
*/
|
||||||
|
@Override
|
||||||
public LambdaQueryBuilder<T> notIn(boolean condition, SFunction<T, ?> column, Collection<?> values) {
|
public LambdaQueryBuilder<T> notIn(boolean condition, SFunction<T, ?> column, Collection<?> values) {
|
||||||
wrapper.notIn(condition, column, values);
|
wrapper.notIn(condition, column, values);
|
||||||
return this;
|
return this;
|
||||||
@@ -877,6 +892,7 @@ public final class LambdaQueryBuilder<T> implements LambdaQueryCondition<T, Lamb
|
|||||||
* @param values 条件值数组
|
* @param values 条件值数组
|
||||||
* @return 当前查询构造辅助对象
|
* @return 当前查询构造辅助对象
|
||||||
*/
|
*/
|
||||||
|
@Override
|
||||||
public LambdaQueryBuilder<T> notIn(boolean condition, SFunction<T, ?> column, Object... values) {
|
public LambdaQueryBuilder<T> notIn(boolean condition, SFunction<T, ?> column, Object... values) {
|
||||||
wrapper.notIn(condition, column, values);
|
wrapper.notIn(condition, column, values);
|
||||||
return this;
|
return this;
|
||||||
@@ -1219,6 +1235,7 @@ public final class LambdaQueryBuilder<T> implements LambdaQueryCondition<T, Lamb
|
|||||||
* @param values SQL 片段参数
|
* @param values SQL 片段参数
|
||||||
* @return 当前查询构造辅助对象
|
* @return 当前查询构造辅助对象
|
||||||
*/
|
*/
|
||||||
|
@Override
|
||||||
public LambdaQueryBuilder<T> apply(boolean condition, String applySql, Object... values) {
|
public LambdaQueryBuilder<T> apply(boolean condition, String applySql, Object... values) {
|
||||||
wrapper.apply(condition, applySql, values);
|
wrapper.apply(condition, applySql, values);
|
||||||
return this;
|
return this;
|
||||||
@@ -1368,7 +1385,6 @@ public final class LambdaQueryBuilder<T> implements LambdaQueryCondition<T, Lamb
|
|||||||
*
|
*
|
||||||
* @return 聚合查询包装器
|
* @return 聚合查询包装器
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
private AggregateLambdaQueryWrapper<T> aggregateWrapper() {
|
private AggregateLambdaQueryWrapper<T> aggregateWrapper() {
|
||||||
return (AggregateLambdaQueryWrapper<T>) wrapper;
|
return (AggregateLambdaQueryWrapper<T>) wrapper;
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-11
@@ -2,22 +2,13 @@ package org.dromara.common.mybatis.core.query;
|
|||||||
|
|
||||||
import com.baomidou.mybatisplus.core.metadata.TableInfo;
|
import com.baomidou.mybatisplus.core.metadata.TableInfo;
|
||||||
import com.baomidou.mybatisplus.core.metadata.TableInfoHelper;
|
import com.baomidou.mybatisplus.core.metadata.TableInfoHelper;
|
||||||
import com.baomidou.mybatisplus.core.toolkit.Assert;
|
import com.baomidou.mybatisplus.core.toolkit.*;
|
||||||
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
|
|
||||||
import com.baomidou.mybatisplus.core.toolkit.Constants;
|
|
||||||
import com.baomidou.mybatisplus.core.toolkit.LambdaUtils;
|
|
||||||
import com.baomidou.mybatisplus.core.toolkit.StringPool;
|
|
||||||
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
|
|
||||||
import com.baomidou.mybatisplus.core.toolkit.support.ColumnCache;
|
import com.baomidou.mybatisplus.core.toolkit.support.ColumnCache;
|
||||||
import com.baomidou.mybatisplus.core.toolkit.support.LambdaMeta;
|
import com.baomidou.mybatisplus.core.toolkit.support.LambdaMeta;
|
||||||
import com.baomidou.mybatisplus.core.toolkit.support.SFunction;
|
import com.baomidou.mybatisplus.core.toolkit.support.SFunction;
|
||||||
import org.apache.ibatis.reflection.property.PropertyNamer;
|
import org.apache.ibatis.reflection.property.PropertyNamer;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.*;
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -112,7 +112,7 @@ public class PlusDataPermissionHandler {
|
|||||||
}
|
}
|
||||||
Object defaultValue = "-1";
|
Object defaultValue = "-1";
|
||||||
NullSafeStandardEvaluationContext context = new NullSafeStandardEvaluationContext(defaultValue);
|
NullSafeStandardEvaluationContext context = new NullSafeStandardEvaluationContext(defaultValue);
|
||||||
context.addPropertyAccessor(new NullSafePropertyAccessor(context.getPropertyAccessors().get(0), defaultValue));
|
context.addPropertyAccessor(new NullSafePropertyAccessor(context.getPropertyAccessors().getFirst(), defaultValue));
|
||||||
context.setBeanResolver(beanResolver);
|
context.setBeanResolver(beanResolver);
|
||||||
DataPermissionHelper.getContext().forEach(context::setVariable);
|
DataPermissionHelper.getContext().forEach(context::setVariable);
|
||||||
Set<String> conditions = new HashSet<>();
|
Set<String> conditions = new HashSet<>();
|
||||||
|
|||||||
+2
-5
@@ -35,10 +35,7 @@ import java.nio.file.Files;
|
|||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import java.time.Duration;
|
import java.time.Duration;
|
||||||
import java.time.ZoneOffset;
|
import java.time.ZoneOffset;
|
||||||
import java.util.Collection;
|
import java.util.*;
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Objects;
|
|
||||||
import java.util.Optional;
|
|
||||||
import java.util.concurrent.CompletionException;
|
import java.util.concurrent.CompletionException;
|
||||||
import java.util.concurrent.ExecutionException;
|
import java.util.concurrent.ExecutionException;
|
||||||
import java.util.concurrent.ExecutorService;
|
import java.util.concurrent.ExecutorService;
|
||||||
@@ -203,7 +200,7 @@ public abstract class AbstractOssClientImpl implements OssClient {
|
|||||||
.orElse("");
|
.orElse("");
|
||||||
String mergedPrefix = mergePrefix(defaultPrefix, businessPrefix);
|
String mergedPrefix = mergePrefix(defaultPrefix, businessPrefix);
|
||||||
String suffix = suffix(fileName);
|
String suffix = suffix(fileName);
|
||||||
String datePath = DateUtils.datePath();
|
String datePath = DateUtils.format(new Date(), "yyyy/MM/dd");
|
||||||
String uuid = IdUtil.fastSimpleUUID();
|
String uuid = IdUtil.fastSimpleUUID();
|
||||||
String path = mergedPrefix.isEmpty() ? datePath + StringUtils.SLASH + uuid : mergedPrefix + StringUtils.SLASH + datePath + StringUtils.SLASH + uuid;
|
String path = mergedPrefix.isEmpty() ? datePath + StringUtils.SLASH + uuid : mergedPrefix + StringUtils.SLASH + datePath + StringUtils.SLASH + uuid;
|
||||||
return path + suffix;
|
return path + suffix;
|
||||||
|
|||||||
+2
-1
@@ -5,19 +5,20 @@ package org.dromara.common.oss.config;
|
|||||||
*
|
*
|
||||||
* @param <T> 配置类型
|
* @param <T> 配置类型
|
||||||
* @param <B> 配置构建器类型
|
* @param <B> 配置构建器类型
|
||||||
*
|
|
||||||
* @author 秋辞未寒
|
* @author 秋辞未寒
|
||||||
*/
|
*/
|
||||||
public interface Config<T, B> {
|
public interface Config<T, B> {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 配置对象拷贝
|
* 配置对象拷贝
|
||||||
|
*
|
||||||
* @return 拷贝后的新配置对象
|
* @return 拷贝后的新配置对象
|
||||||
*/
|
*/
|
||||||
T copy();
|
T copy();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 转为构建器对象
|
* 转为构建器对象
|
||||||
|
*
|
||||||
* @return 构建器对象
|
* @return 构建器对象
|
||||||
*/
|
*/
|
||||||
B toBuilder();
|
B toBuilder();
|
||||||
|
|||||||
+3
-3
@@ -60,7 +60,7 @@ public record HandleAsyncResult<T>(
|
|||||||
* @return 异步处理结果
|
* @return 异步处理结果
|
||||||
*/
|
*/
|
||||||
public static <T> HandleAsyncResult<T> of(T result, Throwable error) {
|
public static <T> HandleAsyncResult<T> of(T result, Throwable error) {
|
||||||
return new HandleAsyncResult<T>(result, error);
|
return new HandleAsyncResult<>(result, error);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -71,7 +71,7 @@ public record HandleAsyncResult<T>(
|
|||||||
* @return 异步处理结果
|
* @return 异步处理结果
|
||||||
*/
|
*/
|
||||||
public static <T> HandleAsyncResult<T> success(T result) {
|
public static <T> HandleAsyncResult<T> success(T result) {
|
||||||
return new HandleAsyncResult<T>(result, null);
|
return new HandleAsyncResult<>(result, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -82,6 +82,6 @@ public record HandleAsyncResult<T>(
|
|||||||
* @return 异步处理结果
|
* @return 异步处理结果
|
||||||
*/
|
*/
|
||||||
public static <T> HandleAsyncResult<T> failure(Throwable error) {
|
public static <T> HandleAsyncResult<T> failure(Throwable error) {
|
||||||
return new HandleAsyncResult<T>(null, error);
|
return new HandleAsyncResult<>(null, error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-5
@@ -3,11 +3,7 @@ package org.dromara.common.push.annotation;
|
|||||||
import org.dromara.common.push.condition.MessageTransportCondition;
|
import org.dromara.common.push.condition.MessageTransportCondition;
|
||||||
import org.springframework.context.annotation.Conditional;
|
import org.springframework.context.annotation.Conditional;
|
||||||
|
|
||||||
import java.lang.annotation.Documented;
|
import java.lang.annotation.*;
|
||||||
import java.lang.annotation.ElementType;
|
|
||||||
import java.lang.annotation.Retention;
|
|
||||||
import java.lang.annotation.RetentionPolicy;
|
|
||||||
import java.lang.annotation.Target;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 按消息推送传输方式启用组件。
|
* 按消息推送传输方式启用组件。
|
||||||
|
|||||||
+1
-1
@@ -1,10 +1,10 @@
|
|||||||
package org.dromara.common.push.config;
|
package org.dromara.common.push.config;
|
||||||
|
|
||||||
import org.dromara.common.push.annotation.ConditionalOnMessageTransport;
|
import org.dromara.common.push.annotation.ConditionalOnMessageTransport;
|
||||||
import org.dromara.common.push.listener.MessageTopicListener;
|
|
||||||
import org.dromara.common.push.core.WebSocketSessionManager;
|
import org.dromara.common.push.core.WebSocketSessionManager;
|
||||||
import org.dromara.common.push.handler.PlusWebSocketHandler;
|
import org.dromara.common.push.handler.PlusWebSocketHandler;
|
||||||
import org.dromara.common.push.interceptor.PlusWebSocketInterceptor;
|
import org.dromara.common.push.interceptor.PlusWebSocketInterceptor;
|
||||||
|
import org.dromara.common.push.listener.MessageTopicListener;
|
||||||
import org.dromara.common.push.properties.MessageProperties;
|
import org.dromara.common.push.properties.MessageProperties;
|
||||||
import org.springframework.boot.autoconfigure.AutoConfiguration;
|
import org.springframework.boot.autoconfigure.AutoConfiguration;
|
||||||
import org.springframework.context.annotation.Bean;
|
import org.springframework.context.annotation.Bean;
|
||||||
|
|||||||
+3
-3
@@ -112,13 +112,13 @@ public class RateLimiterAspect {
|
|||||||
key = expression.getValue(context, String.class);
|
key = expression.getValue(context, String.class);
|
||||||
}
|
}
|
||||||
StringBuilder stringBuffer = new StringBuilder(GlobalConstants.RATE_LIMIT_KEY);
|
StringBuilder stringBuffer = new StringBuilder(GlobalConstants.RATE_LIMIT_KEY);
|
||||||
stringBuffer.append(ServletUtils.getRequest().getRequestURI()).append(":");
|
stringBuffer.append(ServletUtils.getRequest().getRequestURI()).append(StringUtils.COLON);
|
||||||
if (rateLimiter.limitType() == LimitType.IP) {
|
if (rateLimiter.limitType() == LimitType.IP) {
|
||||||
// 获取请求ip
|
// 获取请求ip
|
||||||
stringBuffer.append(ServletUtils.getClientIP()).append(":");
|
stringBuffer.append(ServletUtils.getClientIP()).append(StringUtils.COLON);
|
||||||
} else if (rateLimiter.limitType() == LimitType.CLUSTER) {
|
} else if (rateLimiter.limitType() == LimitType.CLUSTER) {
|
||||||
// 获取客户端实例id
|
// 获取客户端实例id
|
||||||
stringBuffer.append(RedisUtils.getClient().getId()).append(":");
|
stringBuffer.append(RedisUtils.getClient().getId()).append(StringUtils.COLON);
|
||||||
}
|
}
|
||||||
return stringBuffer.append(key).toString();
|
return stringBuffer.append(key).toString();
|
||||||
}
|
}
|
||||||
|
|||||||
+19
-4
@@ -24,6 +24,7 @@ import org.dromara.common.redis.utils.RedisUtils;
|
|||||||
import org.springframework.validation.BindingResult;
|
import org.springframework.validation.BindingResult;
|
||||||
import org.springframework.web.multipart.MultipartFile;
|
import org.springframework.web.multipart.MultipartFile;
|
||||||
|
|
||||||
|
import java.lang.reflect.Array;
|
||||||
import java.time.Duration;
|
import java.time.Duration;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
@@ -62,7 +63,7 @@ public class RepeatSubmitAspect {
|
|||||||
// 唯一值(没有消息头则使用请求地址)
|
// 唯一值(没有消息头则使用请求地址)
|
||||||
String submitKey = StringUtils.trimToEmpty(request.getHeader(SaManager.getConfig().getTokenName()));
|
String submitKey = StringUtils.trimToEmpty(request.getHeader(SaManager.getConfig().getTokenName()));
|
||||||
|
|
||||||
submitKey = SecureUtil.md5(submitKey + ":" + nowParams);
|
submitKey = SecureUtil.md5(submitKey + StringUtils.COLON + nowParams);
|
||||||
// 唯一标识(指定key + url + 消息头)
|
// 唯一标识(指定key + url + 消息头)
|
||||||
String cacheRepeatKey = GlobalConstants.REPEAT_SUBMIT_KEY + url + submitKey;
|
String cacheRepeatKey = GlobalConstants.REPEAT_SUBMIT_KEY + url + submitKey;
|
||||||
if (RedisUtils.setObjectIfAbsent(cacheRepeatKey, "", Duration.ofMillis(interval))) {
|
if (RedisUtils.setObjectIfAbsent(cacheRepeatKey, "", Duration.ofMillis(interval))) {
|
||||||
@@ -150,16 +151,30 @@ public class RepeatSubmitAspect {
|
|||||||
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 MultipartFile.class.isAssignableFrom(clazz.getComponentType());
|
if (MultipartFile.class.isAssignableFrom(clazz.getComponentType())) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
int length = Array.getLength(o);
|
||||||
|
for (int i = 0; i < length; i++) {
|
||||||
|
Object value = Array.get(o, i);
|
||||||
|
if (ObjectUtil.isNotNull(value) && isFilterObject(value)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
} 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;
|
if (ObjectUtil.isNotNull(value) && isFilterObject(value)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else if (Map.class.isAssignableFrom(clazz)) {
|
} else if (Map.class.isAssignableFrom(clazz)) {
|
||||||
Map map = (Map) o;
|
Map map = (Map) o;
|
||||||
for (Object value : map.values()) {
|
for (Object value : map.values()) {
|
||||||
return value instanceof MultipartFile;
|
if (ObjectUtil.isNotNull(value) && isFilterObject(value)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return o instanceof MultipartFile || o instanceof HttpServletRequest || o instanceof HttpServletResponse
|
return o instanceof MultipartFile || o instanceof HttpServletRequest || o instanceof HttpServletResponse
|
||||||
|
|||||||
-1
@@ -24,7 +24,6 @@ import tools.jackson.databind.module.SimpleModule;
|
|||||||
|
|
||||||
import java.time.LocalDateTime;
|
import java.time.LocalDateTime;
|
||||||
import java.time.format.DateTimeFormatter;
|
import java.time.format.DateTimeFormatter;
|
||||||
import java.util.List;
|
|
||||||
import java.util.TimeZone;
|
import java.util.TimeZone;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
+1
-1
@@ -21,7 +21,7 @@ public class KeyPrefixHandler implements NameMapper {
|
|||||||
*/
|
*/
|
||||||
public KeyPrefixHandler(String keyPrefix) {
|
public KeyPrefixHandler(String keyPrefix) {
|
||||||
//前缀为空 则返回空前缀
|
//前缀为空 则返回空前缀
|
||||||
this.keyPrefix = StringUtils.isBlank(keyPrefix) ? "" : keyPrefix + ":";
|
this.keyPrefix = StringUtils.isBlank(keyPrefix) ? "" : keyPrefix + StringUtils.COLON;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
+3
-2
@@ -1,5 +1,6 @@
|
|||||||
package org.dromara.common.redis.manager;
|
package org.dromara.common.redis.manager;
|
||||||
|
|
||||||
|
import org.dromara.common.core.utils.StringUtils;
|
||||||
import org.springframework.cache.Cache;
|
import org.springframework.cache.Cache;
|
||||||
|
|
||||||
import java.util.concurrent.Callable;
|
import java.util.concurrent.Callable;
|
||||||
@@ -55,7 +56,7 @@ public class CaffeineCacheDecorator implements Cache {
|
|||||||
* @return 唯一键
|
* @return 唯一键
|
||||||
*/
|
*/
|
||||||
public String getUniqueKey(Object key) {
|
public String getUniqueKey(Object key) {
|
||||||
return name + ":" + key;
|
return name + StringUtils.COLON + key;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -175,7 +176,7 @@ public class CaffeineCacheDecorator implements Cache {
|
|||||||
* 清理当前缓存命名空间下的本地一级缓存。
|
* 清理当前缓存命名空间下的本地一级缓存。
|
||||||
*/
|
*/
|
||||||
private void clearLocalCache() {
|
private void clearLocalCache() {
|
||||||
String prefix = name + ":";
|
String prefix = name + StringUtils.COLON;
|
||||||
caffeine.asMap().keySet().removeIf(key -> key instanceof String cacheKey && cacheKey.startsWith(prefix));
|
caffeine.asMap().keySet().removeIf(key -> key instanceof String cacheKey && cacheKey.startsWith(prefix));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+7
-8
@@ -22,7 +22,7 @@ import java.util.stream.Stream;
|
|||||||
* @version 3.1.0 新增
|
* @version 3.1.0 新增
|
||||||
*/
|
*/
|
||||||
@NoArgsConstructor(access = AccessLevel.PRIVATE)
|
@NoArgsConstructor(access = AccessLevel.PRIVATE)
|
||||||
@SuppressWarnings(value = {"unchecked", "rawtypes"})
|
@SuppressWarnings(value = {"rawtypes"})
|
||||||
public class RedisUtils {
|
public class RedisUtils {
|
||||||
|
|
||||||
private static final RedissonClient CLIENT = SpringUtils.getBean(RedissonClient.class);
|
private static final RedissonClient CLIENT = SpringUtils.getBean(RedissonClient.class);
|
||||||
@@ -280,9 +280,7 @@ public class RedisUtils {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
RBatch batch = CLIENT.createBatch();
|
RBatch batch = CLIENT.createBatch();
|
||||||
collection.forEach(t -> {
|
collection.forEach(t -> batch.getBucket(t.toString()).deleteAsync());
|
||||||
batch.getBucket(t.toString()).deleteAsync();
|
|
||||||
});
|
|
||||||
batch.execute();
|
batch.execute();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -561,15 +559,16 @@ public class RedisUtils {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 获得缓存的基本对象列表(全局匹配忽略租户 自行拼接租户id)
|
* 获得缓存的基本对象列表(全局匹配忽略租户 自行拼接租户id)
|
||||||
* <P>
|
* <p>
|
||||||
* limit-设置扫描的限制数量(默认为0,查询全部)
|
* limit-设置扫描的限制数量(默认为0,查询全部)
|
||||||
* pattern-设置键的匹配模式(默认为null)
|
* pattern-设置键的匹配模式(默认为null)
|
||||||
* chunkSize-设置每次扫描的块大小(默认为0,本方法设置为1000)
|
* chunkSize-设置每次扫描的块大小(默认为0,本方法设置为1000)
|
||||||
* type-设置键的类型(默认为null,查询全部类型)
|
* type-设置键的类型(默认为null,查询全部类型)
|
||||||
* </P>
|
* </P>
|
||||||
* @see KeysScanOptions
|
*
|
||||||
* @param pattern 字符串前缀
|
* @param pattern 字符串前缀
|
||||||
* @return 对象列表
|
* @return 对象列表
|
||||||
|
* @see KeysScanOptions
|
||||||
*/
|
*/
|
||||||
public static Collection<String> keys(final String pattern) {
|
public static Collection<String> keys(final String pattern) {
|
||||||
return keys(KeysScanOptions.defaults().pattern(pattern).chunkSize(1000));
|
return keys(KeysScanOptions.defaults().pattern(pattern).chunkSize(1000));
|
||||||
@@ -579,14 +578,14 @@ public class RedisUtils {
|
|||||||
* 通过扫描参数获取缓存的基本对象列表
|
* 通过扫描参数获取缓存的基本对象列表
|
||||||
*
|
*
|
||||||
* @param keysScanOptions 扫描参数
|
* @param keysScanOptions 扫描参数
|
||||||
* <P>
|
* <p>
|
||||||
* limit-设置扫描的限制数量(默认为0,查询全部)
|
* limit-设置扫描的限制数量(默认为0,查询全部)
|
||||||
* pattern-设置键的匹配模式(默认为null)
|
* pattern-设置键的匹配模式(默认为null)
|
||||||
* chunkSize-设置每次扫描的块大小(默认为0)
|
* chunkSize-设置每次扫描的块大小(默认为0)
|
||||||
* type-设置键的类型(默认为null,查询全部类型)
|
* type-设置键的类型(默认为null,查询全部类型)
|
||||||
* </P>
|
* </P>
|
||||||
* @see KeysScanOptions
|
|
||||||
* @return 对象列表
|
* @return 对象列表
|
||||||
|
* @see KeysScanOptions
|
||||||
*/
|
*/
|
||||||
public static Collection<String> keys(final KeysScanOptions keysScanOptions) {
|
public static Collection<String> keys(final KeysScanOptions keysScanOptions) {
|
||||||
Stream<String> keysStream = CLIENT.getKeys().getKeysStream(keysScanOptions);
|
Stream<String> keysStream = CLIENT.getKeys().getKeysStream(keysScanOptions);
|
||||||
|
|||||||
+2
-1
@@ -4,6 +4,7 @@ import cn.dev33.satoken.dao.auto.SaTokenDaoBySessionFollowObject;
|
|||||||
import cn.dev33.satoken.util.SaFoxUtil;
|
import cn.dev33.satoken.util.SaFoxUtil;
|
||||||
import com.github.benmanes.caffeine.cache.Cache;
|
import com.github.benmanes.caffeine.cache.Cache;
|
||||||
import com.github.benmanes.caffeine.cache.Caffeine;
|
import com.github.benmanes.caffeine.cache.Caffeine;
|
||||||
|
import org.dromara.common.core.utils.StringUtils;
|
||||||
import org.dromara.common.redis.utils.RedisUtils;
|
import org.dromara.common.redis.utils.RedisUtils;
|
||||||
|
|
||||||
import java.time.Duration;
|
import java.time.Duration;
|
||||||
@@ -157,7 +158,7 @@ public class PlusSaTokenDao implements SaTokenDaoBySessionFollowObject {
|
|||||||
@Override
|
@Override
|
||||||
public List<String> searchData(String prefix, String keyword, int start, int size, boolean sortType) {
|
public List<String> searchData(String prefix, String keyword, int start, int size, boolean sortType) {
|
||||||
String pattern = prefix + "*" + keyword + "*";
|
String pattern = prefix + "*" + keyword + "*";
|
||||||
String cacheKey = pattern + start + ":" + size + ":" + sortType;
|
String cacheKey = pattern + start + StringUtils.COLON + size + StringUtils.COLON + sortType;
|
||||||
return (List<String>) CAFFEINE.get(cacheKey, k -> {
|
return (List<String>) CAFFEINE.get(cacheKey, k -> {
|
||||||
Collection<String> keys = RedisUtils.keys(pattern);
|
Collection<String> keys = RedisUtils.keys(pattern);
|
||||||
List<String> list = new ArrayList<>(keys);
|
List<String> list = new ArrayList<>(keys);
|
||||||
|
|||||||
+1
-1
@@ -9,8 +9,8 @@ import org.dromara.common.core.utils.SpringUtils;
|
|||||||
import org.dromara.common.satoken.utils.LoginHelper;
|
import org.dromara.common.satoken.utils.LoginHelper;
|
||||||
import org.dromara.system.api.model.LoginUser;
|
import org.dromara.system.api.model.LoginUser;
|
||||||
|
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collection;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.function.BiFunction;
|
import java.util.function.BiFunction;
|
||||||
|
|
||||||
|
|||||||
+8
-1
@@ -45,7 +45,14 @@ public class SaTokenExceptionHandler {
|
|||||||
public R<Void> handleNotLoginException(NotLoginException e, HttpServletRequest request) {
|
public R<Void> handleNotLoginException(NotLoginException e, HttpServletRequest request) {
|
||||||
String requestURI = request.getRequestURI();
|
String requestURI = request.getRequestURI();
|
||||||
log.error("请求地址'{}',认证失败'{}',无法访问系统资源", requestURI, e.getMessage());
|
log.error("请求地址'{}',认证失败'{}',无法访问系统资源", requestURI, e.getMessage());
|
||||||
return R.fail(HttpStatus.HTTP_UNAUTHORIZED, "认证失败,无法访问系统资源");
|
String msg = switch (e.getType()) {
|
||||||
|
case NotLoginException.TOKEN_TIMEOUT -> "登录已过期,请重新登录";
|
||||||
|
case NotLoginException.BE_REPLACED -> "当前账号已在其他设备登录,您已被强制下线";
|
||||||
|
case NotLoginException.KICK_OUT -> "账号已被管理员强制下线";
|
||||||
|
case NotLoginException.TOKEN_FREEZE -> "账号已被冻结,请联系管理员处理";
|
||||||
|
default -> "登录状态异常,请重新登录";
|
||||||
|
};
|
||||||
|
return R.fail(HttpStatus.HTTP_UNAUTHORIZED, msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -1,9 +1,9 @@
|
|||||||
package org.dromara.common.satoken.utils;
|
package org.dromara.common.satoken.utils;
|
||||||
|
|
||||||
|
import cn.dev33.satoken.exception.NotLoginException;
|
||||||
import cn.dev33.satoken.session.SaSession;
|
import cn.dev33.satoken.session.SaSession;
|
||||||
import cn.dev33.satoken.stp.StpUtil;
|
import cn.dev33.satoken.stp.StpUtil;
|
||||||
import cn.dev33.satoken.stp.parameter.SaLoginParameter;
|
import cn.dev33.satoken.stp.parameter.SaLoginParameter;
|
||||||
import cn.dev33.satoken.exception.NotLoginException;
|
|
||||||
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.useragent.UserAgent;
|
import cn.hutool.http.useragent.UserAgent;
|
||||||
|
|||||||
+1
-1
@@ -130,7 +130,7 @@ public class SecurityConfig implements WebMvcConfigurer {
|
|||||||
return new SaServletFilter()
|
return new SaServletFilter()
|
||||||
.addInclude("/actuator", "/actuator/**")
|
.addInclude("/actuator", "/actuator/**")
|
||||||
.setAuth(obj -> {
|
.setAuth(obj -> {
|
||||||
SaHttpBasicUtil.check(username + ":" + password);
|
SaHttpBasicUtil.check(username + StringUtils.COLON + password);
|
||||||
})
|
})
|
||||||
.setError(e -> {
|
.setError(e -> {
|
||||||
HttpServletResponse response = ServletUtils.getResponse();
|
HttpServletResponse response = ServletUtils.getResponse();
|
||||||
|
|||||||
+1
-1
@@ -1,8 +1,8 @@
|
|||||||
package org.dromara.common.security.handler;
|
package org.dromara.common.security.handler;
|
||||||
|
|
||||||
import cn.hutool.core.util.ReUtil;
|
import cn.hutool.core.util.ReUtil;
|
||||||
import org.dromara.common.core.utils.SpringUtils;
|
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
import org.dromara.common.core.utils.SpringUtils;
|
||||||
import org.springframework.beans.factory.InitializingBean;
|
import org.springframework.beans.factory.InitializingBean;
|
||||||
import org.springframework.web.method.HandlerMethod;
|
import org.springframework.web.method.HandlerMethod;
|
||||||
import org.springframework.web.servlet.mvc.method.RequestMappingInfo;
|
import org.springframework.web.servlet.mvc.method.RequestMappingInfo;
|
||||||
|
|||||||
+1
-5
@@ -2,11 +2,7 @@ package org.dromara.common.sensitive.annotation;
|
|||||||
|
|
||||||
import org.dromara.common.sensitive.core.SensitiveStrategy;
|
import org.dromara.common.sensitive.core.SensitiveStrategy;
|
||||||
|
|
||||||
import java.lang.annotation.Documented;
|
import java.lang.annotation.*;
|
||||||
import java.lang.annotation.ElementType;
|
|
||||||
import java.lang.annotation.Retention;
|
|
||||||
import java.lang.annotation.RetentionPolicy;
|
|
||||||
import java.lang.annotation.Target;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 数据脱敏注解
|
* 数据脱敏注解
|
||||||
|
|||||||
-1
@@ -124,7 +124,6 @@ public class AuthTopIamRequest extends AuthDefaultRequest {
|
|||||||
.add("Authorization", "Bearer " + authToken.getAccessToken()), false).getBody();
|
.add("Authorization", "Bearer " + authToken.getAccessToken()), false).getBody();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 生成 TopIAM 授权地址。
|
* 生成 TopIAM 授权地址。
|
||||||
*
|
*
|
||||||
|
|||||||
+6
-5
@@ -33,7 +33,6 @@ public class SocialUtils {
|
|||||||
* @return 授权响应
|
* @return 授权响应
|
||||||
* @throws AuthException 授权异常
|
* @throws AuthException 授权异常
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
public static AuthResponse<AuthUser> loginAuth(String source, String code, String state, SocialProperties socialProperties) throws AuthException {
|
public static AuthResponse<AuthUser> loginAuth(String source, String code, String state, SocialProperties socialProperties) throws AuthException {
|
||||||
AuthRequest authRequest = getAuthRequest(source, socialProperties);
|
AuthRequest authRequest = getAuthRequest(source, socialProperties);
|
||||||
AuthCallback callback = new AuthCallback();
|
AuthCallback callback = new AuthCallback();
|
||||||
@@ -69,7 +68,8 @@ public class SocialUtils {
|
|||||||
case "coding" -> new AuthCodingRequest(builder.build(), STATE_CACHE);
|
case "coding" -> new AuthCodingRequest(builder.build(), STATE_CACHE);
|
||||||
case "oschina" -> new AuthOschinaRequest(builder.build(), STATE_CACHE);
|
case "oschina" -> new AuthOschinaRequest(builder.build(), STATE_CACHE);
|
||||||
// 支付宝在创建回调地址时,不允许使用localhost或者127.0.0.1,所以这儿的回调地址使用的局域网内的ip
|
// 支付宝在创建回调地址时,不允许使用localhost或者127.0.0.1,所以这儿的回调地址使用的局域网内的ip
|
||||||
case "alipay_wallet" -> new AuthAlipayRequest(builder.build(), socialProperties.getType().get("alipay_wallet").getAlipayPublicKey(), STATE_CACHE);
|
case "alipay_wallet" ->
|
||||||
|
new AuthAlipayRequest(builder.build(), socialProperties.getType().get("alipay_wallet").getAlipayPublicKey(), STATE_CACHE);
|
||||||
case "qq" -> new AuthQqRequest(builder.build(), STATE_CACHE);
|
case "qq" -> new AuthQqRequest(builder.build(), STATE_CACHE);
|
||||||
case "wechat_open" -> new AuthWeChatOpenRequest(builder.build(), STATE_CACHE);
|
case "wechat_open" -> new AuthWeChatOpenRequest(builder.build(), STATE_CACHE);
|
||||||
case "taobao" -> new AuthTaobaoRequest(builder.build(), STATE_CACHE);
|
case "taobao" -> new AuthTaobaoRequest(builder.build(), STATE_CACHE);
|
||||||
@@ -77,9 +77,11 @@ public class SocialUtils {
|
|||||||
case "linkedin" -> new AuthLinkedinRequest(builder.build(), STATE_CACHE);
|
case "linkedin" -> new AuthLinkedinRequest(builder.build(), STATE_CACHE);
|
||||||
case "microsoft" -> new AuthMicrosoftRequest(builder.tenantId(obj.getTenantId()).build(), STATE_CACHE);
|
case "microsoft" -> new AuthMicrosoftRequest(builder.tenantId(obj.getTenantId()).build(), STATE_CACHE);
|
||||||
case "renren" -> new AuthRenrenRequest(builder.build(), STATE_CACHE);
|
case "renren" -> new AuthRenrenRequest(builder.build(), STATE_CACHE);
|
||||||
case "stack_overflow" -> new AuthStackOverflowRequest(builder.stackOverflowKey(obj.getStackOverflowKey()).build(), STATE_CACHE);
|
case "stack_overflow" ->
|
||||||
|
new AuthStackOverflowRequest(builder.stackOverflowKey(obj.getStackOverflowKey()).build(), STATE_CACHE);
|
||||||
case "huawei" -> new AuthHuaweiV3Request(builder.build(), STATE_CACHE);
|
case "huawei" -> new AuthHuaweiV3Request(builder.build(), STATE_CACHE);
|
||||||
case "wechat_enterprise" -> new AuthWeChatEnterpriseQrcodeV2Request(builder.agentId(obj.getAgentId()).build(), STATE_CACHE);
|
case "wechat_enterprise" ->
|
||||||
|
new AuthWeChatEnterpriseQrcodeV2Request(builder.agentId(obj.getAgentId()).build(), STATE_CACHE);
|
||||||
case "gitlab" -> new AuthGitlabRequest(builder.build(), STATE_CACHE);
|
case "gitlab" -> new AuthGitlabRequest(builder.build(), STATE_CACHE);
|
||||||
case "wechat_mp" -> new AuthWeChatMpRequest(builder.build(), STATE_CACHE);
|
case "wechat_mp" -> new AuthWeChatMpRequest(builder.build(), STATE_CACHE);
|
||||||
case "aliyun" -> new AuthAliyunRequest(builder.build(), STATE_CACHE);
|
case "aliyun" -> new AuthAliyunRequest(builder.build(), STATE_CACHE);
|
||||||
@@ -90,4 +92,3 @@ public class SocialUtils {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+1
-5
@@ -1,10 +1,6 @@
|
|||||||
package org.dromara.common.translation.annotation;
|
package org.dromara.common.translation.annotation;
|
||||||
|
|
||||||
import java.lang.annotation.Documented;
|
import java.lang.annotation.*;
|
||||||
import java.lang.annotation.ElementType;
|
|
||||||
import java.lang.annotation.Retention;
|
|
||||||
import java.lang.annotation.RetentionPolicy;
|
|
||||||
import java.lang.annotation.Target;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 通用翻译注解
|
* 通用翻译注解
|
||||||
|
|||||||
+2
-8
@@ -7,13 +7,7 @@ import org.dromara.common.translation.annotation.TranslationType;
|
|||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
import java.util.Arrays;
|
import java.util.*;
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.LinkedHashSet;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.LinkedHashMap;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Set;
|
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -88,8 +82,8 @@ public interface TranslationInterface<T> {
|
|||||||
*
|
*
|
||||||
* @param ids 原始 ID 字符串
|
* @param ids 原始 ID 字符串
|
||||||
* @param mapper ID 到值的映射函数
|
* @param mapper ID 到值的映射函数
|
||||||
* @return 拼接后的结果字符串
|
|
||||||
* @param <E> 值类型
|
* @param <E> 值类型
|
||||||
|
* @return 拼接后的结果字符串
|
||||||
*/
|
*/
|
||||||
default <E> String joinMappedValues(String ids, Function<Long, E> mapper) {
|
default <E> String joinMappedValues(String ids, Function<Long, E> mapper) {
|
||||||
return StreamUtils.join(parseLongIds(ids), id -> {
|
return StreamUtils.join(parseLongIds(ids), id -> {
|
||||||
|
|||||||
+1
-6
@@ -12,12 +12,7 @@ import org.dromara.common.translation.annotation.TranslationType;
|
|||||||
import org.dromara.common.translation.core.TranslationInterface;
|
import org.dromara.common.translation.core.TranslationInterface;
|
||||||
import org.springframework.core.annotation.Order;
|
import org.springframework.core.annotation.Order;
|
||||||
|
|
||||||
import java.util.Collections;
|
import java.util.*;
|
||||||
import java.util.LinkedHashMap;
|
|
||||||
import java.util.LinkedHashSet;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 翻译响应处理器。
|
* 翻译响应处理器。
|
||||||
|
|||||||
+3
-3
@@ -1,7 +1,7 @@
|
|||||||
package org.dromara.common.web.config;
|
package org.dromara.common.web.config;
|
||||||
|
|
||||||
import cn.hutool.core.date.DateTime;
|
import cn.hutool.core.date.DateTime;
|
||||||
import cn.hutool.core.date.DateUtil;
|
import org.dromara.common.core.utils.DateUtils;
|
||||||
import org.dromara.common.core.utils.ObjectUtils;
|
import org.dromara.common.core.utils.ObjectUtils;
|
||||||
import org.dromara.common.json.enhance.JsonValueEnhancer;
|
import org.dromara.common.json.enhance.JsonValueEnhancer;
|
||||||
import org.dromara.common.web.advice.ResponseEnhancementAdvice;
|
import org.dromara.common.web.advice.ResponseEnhancementAdvice;
|
||||||
@@ -50,14 +50,14 @@ public class ResourcesConfig implements WebMvcConfigurer {
|
|||||||
public void addFormatters(FormatterRegistry registry) {
|
public void addFormatters(FormatterRegistry registry) {
|
||||||
// 全局日期格式转换配置
|
// 全局日期格式转换配置
|
||||||
registry.addConverter(String.class, Date.class, source -> {
|
registry.addConverter(String.class, Date.class, source -> {
|
||||||
DateTime parse = DateUtil.parse(source);
|
DateTime parse = DateUtils.parse(source);
|
||||||
if (ObjectUtils.isNull(parse)) {
|
if (ObjectUtils.isNull(parse)) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
return parse.toJdkDate();
|
return parse.toJdkDate();
|
||||||
});
|
});
|
||||||
registry.addConverter(String.class, LocalDateTime.class, source -> {
|
registry.addConverter(String.class, LocalDateTime.class, source -> {
|
||||||
DateTime parse = DateUtil.parse(source);
|
DateTime parse = DateUtils.parse(source);
|
||||||
if (ObjectUtils.isNull(parse)) {
|
if (ObjectUtils.isNull(parse)) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-2
@@ -1,9 +1,9 @@
|
|||||||
package org.dromara.common.web.core;
|
package org.dromara.common.web.core;
|
||||||
|
|
||||||
import org.springframework.web.servlet.LocaleResolver;
|
|
||||||
|
|
||||||
import jakarta.servlet.http.HttpServletRequest;
|
import jakarta.servlet.http.HttpServletRequest;
|
||||||
import jakarta.servlet.http.HttpServletResponse;
|
import jakarta.servlet.http.HttpServletResponse;
|
||||||
|
import org.springframework.web.servlet.LocaleResolver;
|
||||||
|
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
+3
-3
@@ -1,10 +1,10 @@
|
|||||||
package org.dromara.common.web.filter;
|
package org.dromara.common.web.filter;
|
||||||
|
|
||||||
import org.dromara.common.core.utils.StringUtils;
|
|
||||||
import org.springframework.http.MediaType;
|
|
||||||
|
|
||||||
import jakarta.servlet.*;
|
import jakarta.servlet.*;
|
||||||
import jakarta.servlet.http.HttpServletRequest;
|
import jakarta.servlet.http.HttpServletRequest;
|
||||||
|
import org.dromara.common.core.utils.StringUtils;
|
||||||
|
import org.springframework.http.MediaType;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
+1
-2
@@ -1,13 +1,12 @@
|
|||||||
package org.dromara.common.web.filter;
|
package org.dromara.common.web.filter;
|
||||||
|
|
||||||
import cn.hutool.core.io.IoUtil;
|
import cn.hutool.core.io.IoUtil;
|
||||||
import org.dromara.common.core.constant.Constants;
|
|
||||||
|
|
||||||
import jakarta.servlet.ReadListener;
|
import jakarta.servlet.ReadListener;
|
||||||
import jakarta.servlet.ServletInputStream;
|
import jakarta.servlet.ServletInputStream;
|
||||||
import jakarta.servlet.ServletResponse;
|
import jakarta.servlet.ServletResponse;
|
||||||
import jakarta.servlet.http.HttpServletRequest;
|
import jakarta.servlet.http.HttpServletRequest;
|
||||||
import jakarta.servlet.http.HttpServletRequestWrapper;
|
import jakarta.servlet.http.HttpServletRequestWrapper;
|
||||||
|
import org.dromara.common.core.constant.Constants;
|
||||||
|
|
||||||
import java.io.BufferedReader;
|
import java.io.BufferedReader;
|
||||||
import java.io.ByteArrayInputStream;
|
import java.io.ByteArrayInputStream;
|
||||||
|
|||||||
+3
-3
@@ -1,13 +1,13 @@
|
|||||||
package org.dromara.common.web.filter;
|
package org.dromara.common.web.filter;
|
||||||
|
|
||||||
|
import jakarta.servlet.*;
|
||||||
|
import jakarta.servlet.http.HttpServletRequest;
|
||||||
|
import jakarta.servlet.http.HttpServletResponse;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import org.dromara.common.core.utils.StringUtils;
|
import org.dromara.common.core.utils.StringUtils;
|
||||||
import org.dromara.common.web.config.properties.XssProperties;
|
import org.dromara.common.web.config.properties.XssProperties;
|
||||||
import org.springframework.http.HttpMethod;
|
import org.springframework.http.HttpMethod;
|
||||||
|
|
||||||
import jakarta.servlet.*;
|
|
||||||
import jakarta.servlet.http.HttpServletRequest;
|
|
||||||
import jakarta.servlet.http.HttpServletResponse;
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|||||||
+7
-4
@@ -1,6 +1,7 @@
|
|||||||
package org.dromara.common.web.handler;
|
package org.dromara.common.web.handler;
|
||||||
|
|
||||||
import cn.hutool.core.util.ObjectUtil;
|
import cn.hutool.core.util.ObjectUtil;
|
||||||
|
import cn.hutool.core.util.RandomUtil;
|
||||||
import cn.hutool.http.HttpStatus;
|
import cn.hutool.http.HttpStatus;
|
||||||
import jakarta.servlet.ServletException;
|
import jakarta.servlet.ServletException;
|
||||||
import jakarta.servlet.http.HttpServletRequest;
|
import jakarta.servlet.http.HttpServletRequest;
|
||||||
@@ -151,8 +152,9 @@ public class GlobalExceptionHandler {
|
|||||||
@ExceptionHandler(RuntimeException.class)
|
@ExceptionHandler(RuntimeException.class)
|
||||||
public R<Void> handleRuntimeException(RuntimeException e, HttpServletRequest request) {
|
public R<Void> handleRuntimeException(RuntimeException e, HttpServletRequest request) {
|
||||||
String requestURI = request.getRequestURI();
|
String requestURI = request.getRequestURI();
|
||||||
log.error("请求地址'{}',发生未知异常.", requestURI, e);
|
String errorId = RandomUtil.randomNumbers(8);
|
||||||
return R.fail("发生未知异常,请联系管理员");
|
log.error("请求地址'{}',发生未知异常, 错误编号: {}", requestURI, errorId, e);
|
||||||
|
return R.fail("发生未知异常,请联系管理员 [错误编号: " + errorId + "]");
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -161,8 +163,9 @@ public class GlobalExceptionHandler {
|
|||||||
@ExceptionHandler(Exception.class)
|
@ExceptionHandler(Exception.class)
|
||||||
public R<Void> handleException(Exception e, HttpServletRequest request) {
|
public R<Void> handleException(Exception e, HttpServletRequest request) {
|
||||||
String requestURI = request.getRequestURI();
|
String requestURI = request.getRequestURI();
|
||||||
log.error("请求地址'{}',发生系统异常.", requestURI, e);
|
String errorId = RandomUtil.randomNumbers(8);
|
||||||
return R.fail("发生系统异常,请联系管理员");
|
log.error("请求地址'{}',发生系统异常, 错误编号: {}", requestURI, errorId, e);
|
||||||
|
return R.fail("发生系统异常,请联系管理员 [错误编号: " + errorId + "]");
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
+1
-6
@@ -1,11 +1,6 @@
|
|||||||
package com.aizuda.snail.ai.starter.filter;
|
package com.aizuda.snail.ai.starter.filter;
|
||||||
|
|
||||||
import jakarta.servlet.Filter;
|
import jakarta.servlet.*;
|
||||||
import jakarta.servlet.FilterChain;
|
|
||||||
import jakarta.servlet.FilterConfig;
|
|
||||||
import jakarta.servlet.ServletException;
|
|
||||||
import jakarta.servlet.ServletRequest;
|
|
||||||
import jakarta.servlet.ServletResponse;
|
|
||||||
import jakarta.servlet.http.HttpServletRequest;
|
import jakarta.servlet.http.HttpServletRequest;
|
||||||
import jakarta.servlet.http.HttpServletResponse;
|
import jakarta.servlet.http.HttpServletResponse;
|
||||||
|
|
||||||
|
|||||||
@@ -4,6 +4,10 @@ server:
|
|||||||
context-path: /snail-ai
|
context-path: /snail-ai
|
||||||
|
|
||||||
spring:
|
spring:
|
||||||
|
application:
|
||||||
|
name: ruoyi-snailai-server
|
||||||
|
profiles:
|
||||||
|
active: @profiles.active@
|
||||||
servlet:
|
servlet:
|
||||||
multipart:
|
multipart:
|
||||||
enabled: true
|
enabled: true
|
||||||
@@ -14,8 +18,7 @@ spring:
|
|||||||
web:
|
web:
|
||||||
resources:
|
resources:
|
||||||
static-locations: classpath:admin/
|
static-locations: classpath:admin/
|
||||||
profiles:
|
|
||||||
active: @profiles.active@
|
|
||||||
snail-ai:
|
snail-ai:
|
||||||
server:
|
server:
|
||||||
grpc-port: 18888
|
grpc-port: 18888
|
||||||
|
|||||||
+1
-1
@@ -1,8 +1,8 @@
|
|||||||
package org.dromara.demo.controller;
|
package org.dromara.demo.controller;
|
||||||
|
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
import org.dromara.common.core.domain.R;
|
import org.dromara.common.core.domain.R;
|
||||||
import org.dromara.common.redis.utils.RedisUtils;
|
import org.dromara.common.redis.utils.RedisUtils;
|
||||||
import lombok.RequiredArgsConstructor;
|
|
||||||
import org.springframework.web.bind.annotation.GetMapping;
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
import org.springframework.web.bind.annotation.RequestMapping;
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
import org.springframework.web.bind.annotation.RestController;
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|||||||
+10
-10
@@ -1,36 +1,36 @@
|
|||||||
package org.dromara.demo.controller;
|
package org.dromara.demo.controller;
|
||||||
|
|
||||||
import cn.dev33.satoken.annotation.SaCheckPermission;
|
import cn.dev33.satoken.annotation.SaCheckPermission;
|
||||||
|
import jakarta.servlet.http.HttpServletResponse;
|
||||||
|
import jakarta.validation.constraints.NotEmpty;
|
||||||
|
import jakarta.validation.constraints.NotNull;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import org.dromara.common.core.domain.PageResult;
|
||||||
import org.dromara.common.core.domain.R;
|
import org.dromara.common.core.domain.R;
|
||||||
import org.dromara.common.core.utils.MapstructUtils;
|
import org.dromara.common.core.utils.MapstructUtils;
|
||||||
import org.dromara.common.core.utils.ValidatorUtils;
|
import org.dromara.common.core.utils.ValidatorUtils;
|
||||||
import org.dromara.common.core.validate.AddGroup;
|
import org.dromara.common.core.validate.AddGroup;
|
||||||
import org.dromara.common.core.validate.EditGroup;
|
import org.dromara.common.core.validate.EditGroup;
|
||||||
import org.dromara.common.core.validate.QueryGroup;
|
import org.dromara.common.core.validate.QueryGroup;
|
||||||
import org.dromara.common.web.core.BaseController;
|
|
||||||
import org.dromara.common.redis.annotation.RepeatSubmit;
|
|
||||||
import org.dromara.common.mybatis.core.page.PageQuery;
|
|
||||||
import org.dromara.common.core.domain.PageResult;
|
|
||||||
import org.dromara.common.excel.core.ExcelResult;
|
import org.dromara.common.excel.core.ExcelResult;
|
||||||
import org.dromara.common.excel.utils.ExcelBuilder;
|
import org.dromara.common.excel.utils.ExcelBuilder;
|
||||||
import org.dromara.common.log.annotation.Log;
|
import org.dromara.common.log.annotation.Log;
|
||||||
import org.dromara.common.log.enums.BusinessType;
|
import org.dromara.common.log.enums.BusinessType;
|
||||||
|
import org.dromara.common.mybatis.core.page.PageQuery;
|
||||||
|
import org.dromara.common.redis.annotation.RepeatSubmit;
|
||||||
|
import org.dromara.common.web.core.BaseController;
|
||||||
import org.dromara.demo.domain.TestDemo;
|
import org.dromara.demo.domain.TestDemo;
|
||||||
import org.dromara.demo.domain.bo.TestDemoBo;
|
import org.dromara.demo.domain.bo.TestDemoBo;
|
||||||
import org.dromara.demo.domain.vo.TestDemoImportVo;
|
import org.dromara.demo.domain.vo.TestDemoImportVo;
|
||||||
import org.dromara.demo.domain.vo.TestDemoVo;
|
import org.dromara.demo.domain.vo.TestDemoVo;
|
||||||
import org.dromara.demo.service.ITestDemoService;
|
import org.dromara.demo.service.ITestDemoService;
|
||||||
import lombok.RequiredArgsConstructor;
|
|
||||||
import org.springframework.http.MediaType;
|
import org.springframework.http.MediaType;
|
||||||
import org.springframework.validation.annotation.Validated;
|
import org.springframework.validation.annotation.Validated;
|
||||||
import org.springframework.web.bind.annotation.*;
|
import org.springframework.web.bind.annotation.*;
|
||||||
import org.springframework.web.multipart.MultipartFile;
|
import org.springframework.web.multipart.MultipartFile;
|
||||||
|
|
||||||
import jakarta.servlet.http.HttpServletResponse;
|
import java.util.Arrays;
|
||||||
import jakarta.validation.constraints.NotEmpty;
|
import java.util.List;
|
||||||
import jakarta.validation.constraints.NotNull;
|
|
||||||
|
|
||||||
import java.util.*;
|
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
+3
-4
@@ -1,17 +1,16 @@
|
|||||||
package org.dromara.demo.controller;
|
package org.dromara.demo.controller;
|
||||||
|
|
||||||
|
import jakarta.validation.constraints.NotBlank;
|
||||||
|
import jakarta.validation.constraints.NotNull;
|
||||||
|
import lombok.Data;
|
||||||
import org.dromara.common.core.domain.R;
|
import org.dromara.common.core.domain.R;
|
||||||
import org.dromara.common.core.utils.MessageUtils;
|
import org.dromara.common.core.utils.MessageUtils;
|
||||||
import lombok.Data;
|
|
||||||
import org.hibernate.validator.constraints.Range;
|
import org.hibernate.validator.constraints.Range;
|
||||||
import org.springframework.validation.annotation.Validated;
|
import org.springframework.validation.annotation.Validated;
|
||||||
import org.springframework.web.bind.annotation.GetMapping;
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
import org.springframework.web.bind.annotation.RequestMapping;
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
import org.springframework.web.bind.annotation.RestController;
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
import jakarta.validation.constraints.NotBlank;
|
|
||||||
import jakarta.validation.constraints.NotNull;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 测试国际化
|
* 测试国际化
|
||||||
|
|||||||
+4
-4
@@ -1,11 +1,11 @@
|
|||||||
package org.dromara.demo.controller;
|
package org.dromara.demo.controller;
|
||||||
|
|
||||||
import org.dromara.common.core.domain.R;
|
|
||||||
import org.dromara.common.web.core.BaseController;
|
|
||||||
import org.dromara.common.sensitive.annotation.Sensitive;
|
|
||||||
import org.dromara.common.sensitive.core.SensitiveStrategy;
|
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
import org.dromara.common.core.domain.R;
|
||||||
|
import org.dromara.common.sensitive.annotation.Sensitive;
|
||||||
import org.dromara.common.sensitive.core.SensitiveService;
|
import org.dromara.common.sensitive.core.SensitiveService;
|
||||||
|
import org.dromara.common.sensitive.core.SensitiveStrategy;
|
||||||
|
import org.dromara.common.web.core.BaseController;
|
||||||
import org.springframework.web.bind.annotation.GetMapping;
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
import org.springframework.web.bind.annotation.RequestMapping;
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
import org.springframework.web.bind.annotation.RestController;
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|||||||
+6
-6
@@ -1,25 +1,25 @@
|
|||||||
package org.dromara.demo.controller;
|
package org.dromara.demo.controller;
|
||||||
|
|
||||||
import cn.dev33.satoken.annotation.SaCheckPermission;
|
import cn.dev33.satoken.annotation.SaCheckPermission;
|
||||||
|
import jakarta.servlet.http.HttpServletResponse;
|
||||||
|
import jakarta.validation.constraints.NotEmpty;
|
||||||
|
import jakarta.validation.constraints.NotNull;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
import org.dromara.common.core.domain.R;
|
import org.dromara.common.core.domain.R;
|
||||||
import org.dromara.common.core.validate.AddGroup;
|
import org.dromara.common.core.validate.AddGroup;
|
||||||
import org.dromara.common.core.validate.EditGroup;
|
import org.dromara.common.core.validate.EditGroup;
|
||||||
import org.dromara.common.core.validate.QueryGroup;
|
import org.dromara.common.core.validate.QueryGroup;
|
||||||
import org.dromara.common.web.core.BaseController;
|
|
||||||
import org.dromara.common.excel.utils.ExcelBuilder;
|
import org.dromara.common.excel.utils.ExcelBuilder;
|
||||||
import org.dromara.common.redis.annotation.RepeatSubmit;
|
|
||||||
import org.dromara.common.log.annotation.Log;
|
import org.dromara.common.log.annotation.Log;
|
||||||
import org.dromara.common.log.enums.BusinessType;
|
import org.dromara.common.log.enums.BusinessType;
|
||||||
|
import org.dromara.common.redis.annotation.RepeatSubmit;
|
||||||
|
import org.dromara.common.web.core.BaseController;
|
||||||
import org.dromara.demo.domain.bo.TestTreeBo;
|
import org.dromara.demo.domain.bo.TestTreeBo;
|
||||||
import org.dromara.demo.domain.vo.TestTreeVo;
|
import org.dromara.demo.domain.vo.TestTreeVo;
|
||||||
import org.dromara.demo.service.ITestTreeService;
|
import org.dromara.demo.service.ITestTreeService;
|
||||||
import lombok.RequiredArgsConstructor;
|
|
||||||
import org.springframework.validation.annotation.Validated;
|
import org.springframework.validation.annotation.Validated;
|
||||||
import org.springframework.web.bind.annotation.*;
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
|
||||||
import jakarta.servlet.http.HttpServletResponse;
|
|
||||||
import jakarta.validation.constraints.NotEmpty;
|
|
||||||
import jakarta.validation.constraints.NotNull;
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
|||||||
+2
-2
@@ -1,10 +1,10 @@
|
|||||||
package org.dromara.demo.controller.queue;
|
package org.dromara.demo.controller.queue;
|
||||||
|
|
||||||
import cn.hutool.core.util.RandomUtil;
|
import cn.hutool.core.util.RandomUtil;
|
||||||
import org.dromara.common.core.domain.R;
|
|
||||||
import org.dromara.common.redis.utils.QueueUtils;
|
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.dromara.common.core.domain.R;
|
||||||
|
import org.dromara.common.redis.utils.QueueUtils;
|
||||||
import org.springframework.web.bind.annotation.GetMapping;
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
import org.springframework.web.bind.annotation.RequestMapping;
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
import org.springframework.web.bind.annotation.RestController;
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
package org.dromara.demo.domain;
|
package org.dromara.demo.domain;
|
||||||
|
|
||||||
import com.baomidou.mybatisplus.annotation.TableName;
|
import com.baomidou.mybatisplus.annotation.TableName;
|
||||||
import org.dromara.common.encrypt.annotation.EncryptField;
|
|
||||||
import org.dromara.common.encrypt.enums.AlgorithmType;
|
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import lombok.EqualsAndHashCode;
|
import lombok.EqualsAndHashCode;
|
||||||
|
import org.dromara.common.encrypt.annotation.EncryptField;
|
||||||
|
import org.dromara.common.encrypt.enums.AlgorithmType;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 测试加密字段实体。
|
* 测试加密字段实体。
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
package org.dromara.demo.domain.vo;
|
package org.dromara.demo.domain.vo;
|
||||||
|
|
||||||
import org.apache.fesod.sheet.annotation.ExcelIgnoreUnannotated;
|
|
||||||
import org.apache.fesod.sheet.annotation.ExcelProperty;
|
|
||||||
import jakarta.validation.constraints.NotEmpty;
|
import jakarta.validation.constraints.NotEmpty;
|
||||||
import jakarta.validation.constraints.NotNull;
|
import jakarta.validation.constraints.NotNull;
|
||||||
import lombok.AllArgsConstructor;
|
import lombok.AllArgsConstructor;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import lombok.NoArgsConstructor;
|
import lombok.NoArgsConstructor;
|
||||||
|
import org.apache.fesod.sheet.annotation.ExcelIgnoreUnannotated;
|
||||||
|
import org.apache.fesod.sheet.annotation.ExcelProperty;
|
||||||
import org.dromara.common.core.enums.UserStatus;
|
import org.dromara.common.core.enums.UserStatus;
|
||||||
import org.dromara.common.core.validate.AddGroup;
|
import org.dromara.common.core.validate.AddGroup;
|
||||||
import org.dromara.common.core.validate.EditGroup;
|
import org.dromara.common.core.validate.EditGroup;
|
||||||
|
|||||||
+2
-3
@@ -1,11 +1,10 @@
|
|||||||
package org.dromara.demo.domain.vo;
|
package org.dromara.demo.domain.vo;
|
||||||
|
|
||||||
import org.apache.fesod.sheet.annotation.ExcelProperty;
|
|
||||||
import io.github.linpeilie.annotations.AutoMapper;
|
import io.github.linpeilie.annotations.AutoMapper;
|
||||||
import lombok.Data;
|
|
||||||
|
|
||||||
import jakarta.validation.constraints.NotBlank;
|
import jakarta.validation.constraints.NotBlank;
|
||||||
import jakarta.validation.constraints.NotNull;
|
import jakarta.validation.constraints.NotNull;
|
||||||
|
import lombok.Data;
|
||||||
|
import org.apache.fesod.sheet.annotation.ExcelProperty;
|
||||||
import org.dromara.demo.domain.TestDemo;
|
import org.dromara.demo.domain.TestDemo;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
package org.dromara.demo.domain.vo;
|
package org.dromara.demo.domain.vo;
|
||||||
|
|
||||||
|
import io.github.linpeilie.annotations.AutoMapper;
|
||||||
|
import lombok.Data;
|
||||||
import org.apache.fesod.sheet.annotation.ExcelIgnoreUnannotated;
|
import org.apache.fesod.sheet.annotation.ExcelIgnoreUnannotated;
|
||||||
import org.apache.fesod.sheet.annotation.ExcelProperty;
|
import org.apache.fesod.sheet.annotation.ExcelProperty;
|
||||||
import org.apache.fesod.sheet.annotation.format.DateTimeFormat;
|
import org.apache.fesod.sheet.annotation.format.DateTimeFormat;
|
||||||
@@ -8,8 +10,6 @@ import org.dromara.common.excel.annotation.ExcelRequired;
|
|||||||
import org.dromara.common.translation.annotation.Translation;
|
import org.dromara.common.translation.annotation.Translation;
|
||||||
import org.dromara.common.translation.constant.TransConstant;
|
import org.dromara.common.translation.constant.TransConstant;
|
||||||
import org.dromara.demo.domain.TestDemo;
|
import org.dromara.demo.domain.TestDemo;
|
||||||
import io.github.linpeilie.annotations.AutoMapper;
|
|
||||||
import lombok.Data;
|
|
||||||
|
|
||||||
import java.io.Serial;
|
import java.io.Serial;
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
package org.dromara.demo.domain.vo;
|
package org.dromara.demo.domain.vo;
|
||||||
|
|
||||||
|
import io.github.linpeilie.annotations.AutoMapper;
|
||||||
|
import lombok.Data;
|
||||||
import org.apache.fesod.sheet.annotation.ExcelIgnoreUnannotated;
|
import org.apache.fesod.sheet.annotation.ExcelIgnoreUnannotated;
|
||||||
import org.apache.fesod.sheet.annotation.ExcelProperty;
|
import org.apache.fesod.sheet.annotation.ExcelProperty;
|
||||||
import org.dromara.demo.domain.TestTree;
|
import org.dromara.demo.domain.TestTree;
|
||||||
import io.github.linpeilie.annotations.AutoMapper;
|
|
||||||
import lombok.Data;
|
|
||||||
|
|
||||||
import java.io.Serial;
|
import java.io.Serial;
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user