Merge remote-tracking branch 'origin/dev' into warm-flow-future
This commit is contained in:
commit
c1e26a3229
33
pom.xml
33
pom.xml
@ -14,21 +14,21 @@
|
||||
|
||||
<properties>
|
||||
<revision>5.2.2</revision>
|
||||
<spring-boot.version>3.2.9</spring-boot.version>
|
||||
<spring-boot.version>3.2.10</spring-boot.version>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
|
||||
<java.version>17</java.version>
|
||||
<mybatis.version>3.5.16</mybatis.version>
|
||||
<springdoc.version>2.6.0</springdoc.version>
|
||||
<therapi-javadoc.version>0.15.0</therapi-javadoc.version>
|
||||
<easyexcel.version>4.0.2</easyexcel.version>
|
||||
<easyexcel.version>4.0.3</easyexcel.version>
|
||||
<velocity.version>2.3</velocity.version>
|
||||
<satoken.version>1.39.0</satoken.version>
|
||||
<mybatis-plus.version>3.5.7</mybatis-plus.version>
|
||||
<mybatis-plus.version>3.5.8</mybatis-plus.version>
|
||||
<p6spy.version>3.9.1</p6spy.version>
|
||||
<hutool.version>5.8.31</hutool.version>
|
||||
<spring-boot-admin.version>3.2.3</spring-boot-admin.version>
|
||||
<redisson.version>3.34.1</redisson.version>
|
||||
<redisson.version>3.36.0</redisson.version>
|
||||
<lock4j.version>2.2.7</lock4j.version>
|
||||
<dynamic-ds.version>4.3.1</dynamic-ds.version>
|
||||
<snailjob.version>1.1.2</snailjob.version>
|
||||
@ -39,17 +39,16 @@
|
||||
<justauth.version>1.16.6</justauth.version>
|
||||
<!-- 离线IP地址定位库 -->
|
||||
<ip2region.version>2.7.0</ip2region.version>
|
||||
<undertow.version>2.3.15.Final</undertow.version>
|
||||
|
||||
<!-- OSS 配置 -->
|
||||
<aws.sdk.version>2.25.15</aws.sdk.version>
|
||||
<aws.crt.version>0.29.13</aws.crt.version>
|
||||
<aws.sdk.version>2.28.22</aws.sdk.version>
|
||||
<aws.crt.version>0.31.3</aws.crt.version>
|
||||
<!-- SMS 配置 -->
|
||||
<sms4j.version>3.3.2</sms4j.version>
|
||||
<sms4j.version>3.3.3</sms4j.version>
|
||||
<!-- 限制框架中的fastjson版本 -->
|
||||
<fastjson.version>1.2.83</fastjson.version>
|
||||
<!-- 面向运行时的D-ORM依赖 -->
|
||||
<anyline.version>8.7.2-20240808</anyline.version>
|
||||
<anyline.version>8.7.2-20240930</anyline.version>
|
||||
<!--工作流配置-->
|
||||
<warm-flow.version>1.2.10</warm-flow.version>
|
||||
|
||||
@ -315,22 +314,6 @@
|
||||
<version>${ip2region.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.undertow</groupId>
|
||||
<artifactId>undertow-core</artifactId>
|
||||
<version>${undertow.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.undertow</groupId>
|
||||
<artifactId>undertow-servlet</artifactId>
|
||||
<version>${undertow.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.undertow</groupId>
|
||||
<artifactId>undertow-websockets-jsr</artifactId>
|
||||
<version>${undertow.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>commons-io</groupId>
|
||||
<artifactId>commons-io</artifactId>
|
||||
|
@ -25,6 +25,8 @@ snail-job:
|
||||
namespace: ${spring.profiles.active}
|
||||
# 随主应用端口飘逸
|
||||
port: 2${server.port}
|
||||
# 客户端ip指定
|
||||
host:
|
||||
|
||||
--- # 数据源配置
|
||||
spring:
|
||||
|
@ -28,6 +28,8 @@ snail-job:
|
||||
namespace: ${spring.profiles.active}
|
||||
# 随主应用端口飘逸
|
||||
port: 2${server.port}
|
||||
# 客户端ip指定
|
||||
host:
|
||||
|
||||
--- # 数据源配置
|
||||
spring:
|
||||
|
@ -0,0 +1,62 @@
|
||||
package org.dromara.common.core.exception;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.io.Serial;
|
||||
|
||||
/**
|
||||
* sse 特制异常
|
||||
*
|
||||
* @author LionLi
|
||||
*/
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public final class SseException extends RuntimeException {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 错误码
|
||||
*/
|
||||
private Integer code;
|
||||
|
||||
/**
|
||||
* 错误提示
|
||||
*/
|
||||
private String message;
|
||||
|
||||
/**
|
||||
* 错误明细,内部调试错误
|
||||
*/
|
||||
private String detailMessage;
|
||||
|
||||
public SseException(String message) {
|
||||
this.message = message;
|
||||
}
|
||||
|
||||
public SseException(String message, Integer code) {
|
||||
this.message = message;
|
||||
this.code = code;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMessage() {
|
||||
return message;
|
||||
}
|
||||
|
||||
public SseException setMessage(String message) {
|
||||
this.message = message;
|
||||
return this;
|
||||
}
|
||||
|
||||
public SseException setDetailMessage(String detailMessage) {
|
||||
this.detailMessage = detailMessage;
|
||||
return this;
|
||||
}
|
||||
}
|
@ -17,7 +17,10 @@ import org.springframework.core.type.classreading.CachingMetadataReaderFactory;
|
||||
import org.springframework.util.ClassUtils;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.*;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@ -34,7 +37,7 @@ public class EncryptorManager {
|
||||
/**
|
||||
* 缓存加密器
|
||||
*/
|
||||
Map<EncryptContext, IEncryptor> encryptorMap = new ConcurrentHashMap<>();
|
||||
Map<Integer, IEncryptor> encryptorMap = new ConcurrentHashMap<>();
|
||||
|
||||
/**
|
||||
* 类加密字段缓存
|
||||
@ -67,11 +70,12 @@ public class EncryptorManager {
|
||||
* @param encryptContext 加密执行者需要的相关配置参数
|
||||
*/
|
||||
public IEncryptor registAndGetEncryptor(EncryptContext encryptContext) {
|
||||
if (encryptorMap.containsKey(encryptContext)) {
|
||||
return encryptorMap.get(encryptContext);
|
||||
int key = encryptContext.hashCode();
|
||||
if (encryptorMap.containsKey(key)) {
|
||||
return encryptorMap.get(key);
|
||||
}
|
||||
IEncryptor encryptor = ReflectUtil.newInstance(encryptContext.getAlgorithm().getClazz(), encryptContext);
|
||||
encryptorMap.put(encryptContext, encryptor);
|
||||
encryptorMap.put(key, encryptor);
|
||||
return encryptor;
|
||||
}
|
||||
|
||||
@ -81,7 +85,7 @@ public class EncryptorManager {
|
||||
* @param encryptContext 加密执行者需要的相关配置参数
|
||||
*/
|
||||
public void removeEncryptor(EncryptContext encryptContext) {
|
||||
this.encryptorMap.remove(encryptContext);
|
||||
this.encryptorMap.remove(encryptContext.hashCode());
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -99,7 +99,7 @@ public class CryptoFilter implements Filter {
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
return null;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
@ -159,8 +159,7 @@ public class LogAspect {
|
||||
private void setRequestValue(JoinPoint joinPoint, OperLogEvent operLog, String[] excludeParamNames) throws Exception {
|
||||
Map<String, String> paramsMap = ServletUtils.getParamMap(ServletUtils.getRequest());
|
||||
String requestMethod = operLog.getRequestMethod();
|
||||
if (MapUtil.isEmpty(paramsMap)
|
||||
&& HttpMethod.PUT.name().equals(requestMethod) || HttpMethod.POST.name().equals(requestMethod)) {
|
||||
if (MapUtil.isEmpty(paramsMap) && StringUtils.equalsAny(requestMethod, HttpMethod.PUT.name(), HttpMethod.POST.name(), HttpMethod.DELETE.name())) {
|
||||
String params = argsArrayToString(joinPoint.getArgs(), excludeParamNames);
|
||||
operLog.setOperParam(StringUtils.substring(params, 0, 2000));
|
||||
} else {
|
||||
|
@ -18,9 +18,7 @@ import java.io.Serializable;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* 自定义 Mapper 接口, 实现 自定义扩展
|
||||
@ -69,9 +67,7 @@ public interface BaseMapperPlus<T, V> extends BaseMapper<T> {
|
||||
* @return 插入操作是否成功的布尔值
|
||||
*/
|
||||
default boolean insertBatch(Collection<T> entityList) {
|
||||
Db.saveBatch(entityList);
|
||||
// 临时解决 新版本 mp 插入状态判断错误问题
|
||||
return true;
|
||||
return Db.saveBatch(entityList);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -81,9 +77,7 @@ public interface BaseMapperPlus<T, V> extends BaseMapper<T> {
|
||||
* @return 更新操作是否成功的布尔值
|
||||
*/
|
||||
default boolean updateBatchById(Collection<T> entityList) {
|
||||
Db.updateBatchById(entityList);
|
||||
// 临时解决 新版本 mp 插入状态判断错误问题
|
||||
return true;
|
||||
return Db.updateBatchById(entityList);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -93,9 +87,7 @@ public interface BaseMapperPlus<T, V> extends BaseMapper<T> {
|
||||
* @return 插入或更新操作是否成功的布尔值
|
||||
*/
|
||||
default boolean insertOrUpdateBatch(Collection<T> entityList) {
|
||||
Db.saveOrUpdateBatch(entityList);
|
||||
// 临时解决 新版本 mp 插入状态判断错误问题
|
||||
return true;
|
||||
return Db.saveOrUpdateBatch(entityList);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -106,9 +98,7 @@ public interface BaseMapperPlus<T, V> extends BaseMapper<T> {
|
||||
* @return 插入操作是否成功的布尔值
|
||||
*/
|
||||
default boolean insertBatch(Collection<T> entityList, int batchSize) {
|
||||
Db.saveBatch(entityList, batchSize);
|
||||
// 临时解决 新版本 mp 插入状态判断错误问题
|
||||
return true;
|
||||
return Db.saveBatch(entityList, batchSize);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -119,9 +109,7 @@ public interface BaseMapperPlus<T, V> extends BaseMapper<T> {
|
||||
* @return 更新操作是否成功的布尔值
|
||||
*/
|
||||
default boolean updateBatchById(Collection<T> entityList, int batchSize) {
|
||||
Db.updateBatchById(entityList, batchSize);
|
||||
// 临时解决 新版本 mp 插入状态判断错误问题
|
||||
return true;
|
||||
return Db.updateBatchById(entityList, batchSize);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -132,9 +120,7 @@ public interface BaseMapperPlus<T, V> extends BaseMapper<T> {
|
||||
* @return 插入或更新操作是否成功的布尔值
|
||||
*/
|
||||
default boolean insertOrUpdateBatch(Collection<T> entityList, int batchSize) {
|
||||
Db.saveOrUpdateBatch(entityList, batchSize);
|
||||
// 临时解决 新版本 mp 插入状态判断错误问题
|
||||
return true;
|
||||
return Db.saveOrUpdateBatch(entityList, batchSize);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -169,8 +155,8 @@ public interface BaseMapperPlus<T, V> extends BaseMapper<T> {
|
||||
* @param idList 主键ID集合
|
||||
* @return 查询到的VO对象列表
|
||||
*/
|
||||
default List<V> selectVoBatchIds(Collection<? extends Serializable> idList) {
|
||||
return selectVoBatchIds(idList, this.currentVoClass());
|
||||
default List<V> selectVoByIds(Collection<? extends Serializable> idList) {
|
||||
return selectVoByIds(idList, this.currentVoClass());
|
||||
}
|
||||
|
||||
/**
|
||||
@ -181,8 +167,8 @@ public interface BaseMapperPlus<T, V> extends BaseMapper<T> {
|
||||
* @param <C> VO类的类型
|
||||
* @return 查询到的VO对象列表,经过转换为指定的VO类后返回
|
||||
*/
|
||||
default <C> List<C> selectVoBatchIds(Collection<? extends Serializable> idList, Class<C> voClass) {
|
||||
List<T> list = this.selectBatchIds(idList);
|
||||
default <C> List<C> selectVoByIds(Collection<? extends Serializable> idList, Class<C> voClass) {
|
||||
List<T> list = this.selectByIds(idList);
|
||||
if (CollUtil.isEmpty(list)) {
|
||||
return CollUtil.newArrayList();
|
||||
}
|
||||
|
@ -6,8 +6,8 @@ import cn.hutool.core.util.ObjectUtil;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import net.sf.jsqlparser.JSQLParserException;
|
||||
import net.sf.jsqlparser.expression.Expression;
|
||||
import net.sf.jsqlparser.expression.Parenthesis;
|
||||
import net.sf.jsqlparser.expression.operators.conditional.AndExpression;
|
||||
import net.sf.jsqlparser.expression.operators.relational.ParenthesedExpressionList;
|
||||
import net.sf.jsqlparser.parser.CCJSqlParserUtil;
|
||||
import org.apache.ibatis.io.Resources;
|
||||
import org.dromara.common.core.domain.dto.RoleDTO;
|
||||
@ -106,7 +106,7 @@ public class PlusDataPermissionHandler {
|
||||
try {
|
||||
Expression expression = CCJSqlParserUtil.parseExpression(dataFilterSql);
|
||||
// 数据权限使用单独的括号 防止与其他条件冲突
|
||||
Parenthesis parenthesis = new Parenthesis(expression);
|
||||
ParenthesedExpressionList<Expression> parenthesis = new ParenthesedExpressionList<>(expression);
|
||||
if (ObjectUtil.isNotNull(where)) {
|
||||
return new AndExpression(where, parenthesis);
|
||||
} else {
|
||||
|
@ -15,12 +15,12 @@ import org.dromara.common.oss.properties.OssProperties;
|
||||
import software.amazon.awssdk.auth.credentials.AwsBasicCredentials;
|
||||
import software.amazon.awssdk.auth.credentials.StaticCredentialsProvider;
|
||||
import software.amazon.awssdk.core.ResponseInputStream;
|
||||
import software.amazon.awssdk.core.async.AsyncRequestBody;
|
||||
import software.amazon.awssdk.core.async.AsyncResponseTransformer;
|
||||
import software.amazon.awssdk.core.async.BlockingInputStreamAsyncRequestBody;
|
||||
import software.amazon.awssdk.regions.Region;
|
||||
import software.amazon.awssdk.services.s3.S3AsyncClient;
|
||||
import software.amazon.awssdk.services.s3.S3Configuration;
|
||||
import software.amazon.awssdk.services.s3.crt.S3CrtHttpConfiguration;
|
||||
import software.amazon.awssdk.services.s3.model.GetObjectResponse;
|
||||
import software.amazon.awssdk.services.s3.model.NoSuchBucketException;
|
||||
import software.amazon.awssdk.services.s3.model.S3Exception;
|
||||
@ -83,8 +83,8 @@ public class OssClient {
|
||||
StaticCredentialsProvider credentialsProvider = StaticCredentialsProvider.create(
|
||||
AwsBasicCredentials.create(properties.getAccessKey(), properties.getSecretKey()));
|
||||
|
||||
//MinIO 使用 HTTPS 限制使用域名访问,站点填域名。需要启用路径样式访问
|
||||
boolean isStyle = !StringUtils.containsAny(properties.getEndpoint(), OssConstant.CLOUD_SERVICE);
|
||||
//使用对象存储服务时要求明确配置访问样式(路径样式或虚拟托管样式)。需要启用路径样式访问
|
||||
boolean isStyle = true;
|
||||
|
||||
//创建AWS基于 CRT 的 S3 客户端
|
||||
this.client = S3AsyncClient.crtBuilder()
|
||||
@ -95,6 +95,9 @@ public class OssClient {
|
||||
.minimumPartSizeInBytes(10 * 1025 * 1024L)
|
||||
.checksumValidationEnabled(false)
|
||||
.forcePathStyle(isStyle)
|
||||
.httpConfiguration(S3CrtHttpConfiguration.builder()
|
||||
.connectionTimeout(Duration.ofSeconds(60)) // 设置连接超时
|
||||
.build())
|
||||
.build();
|
||||
|
||||
//AWS基于 CRT 的 S3 AsyncClient 实例用作 S3 传输管理器的底层客户端
|
||||
@ -178,7 +181,9 @@ public class OssClient {
|
||||
.key(key)
|
||||
.contentMD5(StringUtils.isNotEmpty(md5Digest) ? md5Digest : null)
|
||||
.contentType(contentType)
|
||||
.acl(getAccessPolicy().getObjectCannedACL())
|
||||
// 用于设置对象的访问控制列表(ACL)。不同云厂商对ACL的支持和实现方式有所不同,
|
||||
// 因此根据具体的云服务提供商,你可能需要进行不同的配置(自行开启,阿里云有acl权限配置,腾讯云没有acl权限配置)
|
||||
//.acl(getAccessPolicy().getObjectCannedACL())
|
||||
.build())
|
||||
.addTransferListener(LoggingTransferListener.create())
|
||||
.source(filePath).build());
|
||||
@ -215,7 +220,10 @@ public class OssClient {
|
||||
}
|
||||
try {
|
||||
// 创建异步请求体(length如果为空会报错)
|
||||
BlockingInputStreamAsyncRequestBody body = AsyncRequestBody.forBlockingInputStream(length);
|
||||
BlockingInputStreamAsyncRequestBody body = BlockingInputStreamAsyncRequestBody.builder()
|
||||
.contentLength(length)
|
||||
.subscribeTimeout(Duration.ofSeconds(30))
|
||||
.build();
|
||||
|
||||
// 使用 transferManager 进行上传
|
||||
Upload upload = transferManager.upload(
|
||||
@ -224,7 +232,9 @@ public class OssClient {
|
||||
y -> y.bucket(properties.getBucketName())
|
||||
.key(key)
|
||||
.contentType(contentType)
|
||||
.acl(getAccessPolicy().getObjectCannedACL())
|
||||
// 用于设置对象的访问控制列表(ACL)。不同云厂商对ACL的支持和实现方式有所不同,
|
||||
// 因此根据具体的云服务提供商,你可能需要进行不同的配置(自行开启,阿里云有acl权限配置,腾讯云没有acl权限配置)
|
||||
//.acl(getAccessPolicy().getObjectCannedACL())
|
||||
.build())
|
||||
.build());
|
||||
|
||||
|
@ -44,6 +44,7 @@ public class CaffeineCacheDecorator implements Cache {
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public <T> T get(Object key, Class<T> type) {
|
||||
Object o = CAFFEINE.get(getUniqueKey(key), k -> cache.get(key, type));
|
||||
return (T) o;
|
||||
@ -55,6 +56,7 @@ public class CaffeineCacheDecorator implements Cache {
|
||||
cache.put(key, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ValueWrapper putIfAbsent(Object key, Object value) {
|
||||
CAFFEINE.invalidate(getUniqueKey(key));
|
||||
return cache.putIfAbsent(key, value);
|
||||
@ -65,6 +67,7 @@ public class CaffeineCacheDecorator implements Cache {
|
||||
evictIfPresent(key);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean evictIfPresent(Object key) {
|
||||
boolean b = cache.evictIfPresent(key);
|
||||
if (b) {
|
||||
@ -78,6 +81,7 @@ public class CaffeineCacheDecorator implements Cache {
|
||||
cache.clear();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean invalidate() {
|
||||
return cache.invalidate();
|
||||
}
|
||||
|
@ -1,19 +1,15 @@
|
||||
package org.dromara.common.redis.utils;
|
||||
|
||||
import org.dromara.common.core.utils.SpringUtils;
|
||||
import lombok.AccessLevel;
|
||||
import lombok.NoArgsConstructor;
|
||||
import org.redisson.api.RMap;
|
||||
import org.dromara.common.core.utils.SpringUtils;
|
||||
import org.springframework.cache.Cache;
|
||||
import org.springframework.cache.CacheManager;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* 缓存操作工具类 {@link }
|
||||
* 缓存操作工具类
|
||||
*
|
||||
* @author Michelle.Chung
|
||||
* @date 2022/8/13
|
||||
*/
|
||||
@NoArgsConstructor(access = AccessLevel.PRIVATE)
|
||||
@SuppressWarnings(value = {"unchecked"})
|
||||
@ -21,16 +17,6 @@ public class CacheUtils {
|
||||
|
||||
private static final CacheManager CACHE_MANAGER = SpringUtils.getBean(CacheManager.class);
|
||||
|
||||
/**
|
||||
* 获取缓存组内所有的KEY
|
||||
*
|
||||
* @param cacheNames 缓存组名称
|
||||
*/
|
||||
public static Set<Object> keys(String cacheNames) {
|
||||
RMap<Object, Object> rmap = (RMap<Object, Object>) CACHE_MANAGER.getCache(cacheNames).getNativeCache();
|
||||
return rmap.keySet();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取缓存值
|
||||
*
|
||||
|
@ -517,7 +517,7 @@ public class RedisUtils {
|
||||
}
|
||||
|
||||
/**
|
||||
* 获得缓存的基本对象列表
|
||||
* 获得缓存的基本对象列表(全局匹配忽略租户 自行拼接租户id)
|
||||
*
|
||||
* @param pattern 字符串前缀
|
||||
* @return 对象列表
|
||||
@ -528,7 +528,7 @@ public class RedisUtils {
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除缓存的基本对象列表
|
||||
* 删除缓存的基本对象列表(全局匹配忽略租户 自行拼接租户id)
|
||||
*
|
||||
* @param pattern 字符串前缀
|
||||
*/
|
||||
|
@ -7,9 +7,11 @@ import cn.dev33.satoken.interceptor.SaInterceptor;
|
||||
import cn.dev33.satoken.router.SaRouter;
|
||||
import cn.dev33.satoken.stp.StpUtil;
|
||||
import cn.dev33.satoken.util.SaResult;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.dromara.common.core.constant.HttpStatus;
|
||||
import org.dromara.common.core.exception.SseException;
|
||||
import org.dromara.common.core.utils.ServletUtils;
|
||||
import org.dromara.common.core.utils.SpringUtils;
|
||||
import org.dromara.common.core.utils.StringUtils;
|
||||
@ -50,11 +52,20 @@ public class SecurityConfig implements WebMvcConfigurer {
|
||||
.match(allUrlHandler.getUrls())
|
||||
// 对未排除的路径进行检查
|
||||
.check(() -> {
|
||||
HttpServletRequest request = ServletUtils.getRequest();
|
||||
// 检查是否登录 是否有token
|
||||
StpUtil.checkLogin();
|
||||
try {
|
||||
StpUtil.checkLogin();
|
||||
} catch (NotLoginException e) {
|
||||
if (request.getRequestURI().contains("sse")) {
|
||||
throw new SseException(e.getMessage(), e.getCode());
|
||||
} else {
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
// 检查 header 与 param 里的 clientid 与 token 里的是否一致
|
||||
String headerCid = ServletUtils.getRequest().getHeader(LoginHelper.CLIENT_KEY);
|
||||
String headerCid = request.getHeader(LoginHelper.CLIENT_KEY);
|
||||
String paramCid = ServletUtils.getParameter(LoginHelper.CLIENT_KEY);
|
||||
String clientId = StpUtil.getExtra(LoginHelper.CLIENT_KEY).toString();
|
||||
if (!StringUtils.equalsAny(clientId, headerCid, paramCid)) {
|
||||
|
@ -1,14 +1,11 @@
|
||||
package org.dromara.common.sse.core;
|
||||
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.dromara.common.redis.utils.RedisUtils;
|
||||
import org.dromara.common.sse.dto.SseMessageDto;
|
||||
import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.function.Consumer;
|
||||
@ -124,25 +121,13 @@ public class SseEmitterManager {
|
||||
* @param sseMessageDto 要发布的SSE消息对象
|
||||
*/
|
||||
public void publishMessage(SseMessageDto sseMessageDto) {
|
||||
List<Long> unsentUserIds = new ArrayList<>();
|
||||
// 当前服务内用户,直接发送消息
|
||||
for (Long userId : sseMessageDto.getUserIds()) {
|
||||
if (USER_TOKEN_EMITTERS.containsKey(userId)) {
|
||||
sendMessage(userId, sseMessageDto.getMessage());
|
||||
continue;
|
||||
}
|
||||
unsentUserIds.add(userId);
|
||||
}
|
||||
// 不在当前服务内用户,发布订阅消息
|
||||
if (CollUtil.isNotEmpty(unsentUserIds)) {
|
||||
SseMessageDto broadcastMessage = new SseMessageDto();
|
||||
broadcastMessage.setMessage(sseMessageDto.getMessage());
|
||||
broadcastMessage.setUserIds(unsentUserIds);
|
||||
RedisUtils.publish(SSE_TOPIC, broadcastMessage, consumer -> {
|
||||
log.info("SSE发送主题订阅消息topic:{} session keys:{} message:{}",
|
||||
SSE_TOPIC, unsentUserIds, sseMessageDto.getMessage());
|
||||
});
|
||||
}
|
||||
SseMessageDto broadcastMessage = new SseMessageDto();
|
||||
broadcastMessage.setMessage(sseMessageDto.getMessage());
|
||||
broadcastMessage.setUserIds(sseMessageDto.getUserIds());
|
||||
RedisUtils.publish(SSE_TOPIC, broadcastMessage, consumer -> {
|
||||
log.info("SSE发送主题订阅消息topic:{} session keys:{} message:{}",
|
||||
SSE_TOPIC, sseMessageDto.getUserIds(), sseMessageDto.getMessage());
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -35,7 +35,8 @@ public class TenantKeyPrefixHandler extends KeyPrefixHandler {
|
||||
}
|
||||
String tenantId = TenantHelper.getTenantId();
|
||||
if (StringUtils.isBlank(tenantId)) {
|
||||
log.error("无法获取有效的租户id -> Null");
|
||||
log.debug("无法获取有效的租户id -> Null");
|
||||
return super.map(name);
|
||||
}
|
||||
if (StringUtils.startsWith(name, tenantId + "")) {
|
||||
// 如果存在则直接返回
|
||||
@ -61,7 +62,8 @@ public class TenantKeyPrefixHandler extends KeyPrefixHandler {
|
||||
}
|
||||
String tenantId = TenantHelper.getTenantId();
|
||||
if (StringUtils.isBlank(tenantId)) {
|
||||
log.error("无法获取有效的租户id -> Null");
|
||||
log.debug("无法获取有效的租户id -> Null");
|
||||
return super.unmap(name);
|
||||
}
|
||||
if (StringUtils.startsWith(unmap, tenantId + "")) {
|
||||
// 如果存在则删除
|
||||
|
@ -43,19 +43,6 @@
|
||||
<artifactId>spring-boot-starter-undertow</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.undertow</groupId>
|
||||
<artifactId>undertow-core</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.undertow</groupId>
|
||||
<artifactId>undertow-servlet</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.undertow</groupId>
|
||||
<artifactId>undertow-websockets-jsr</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-actuator</artifactId>
|
||||
|
@ -9,9 +9,10 @@ import jakarta.validation.ConstraintViolationException;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.dromara.common.core.domain.R;
|
||||
import org.dromara.common.core.exception.ServiceException;
|
||||
import org.dromara.common.core.exception.SseException;
|
||||
import org.dromara.common.core.exception.base.BaseException;
|
||||
import org.dromara.common.core.utils.StreamUtils;
|
||||
import org.dromara.common.core.utils.StringUtils;
|
||||
import org.dromara.common.json.utils.JsonUtils;
|
||||
import org.springframework.context.support.DefaultMessageSourceResolvable;
|
||||
import org.springframework.validation.BindException;
|
||||
import org.springframework.web.HttpRequestMethodNotSupportedException;
|
||||
@ -55,20 +56,25 @@ public class GlobalExceptionHandler {
|
||||
return ObjectUtil.isNotNull(code) ? R.fail(code, e.getMessage()) : R.fail(e.getMessage());
|
||||
}
|
||||
|
||||
/**
|
||||
* 认证失败
|
||||
*/
|
||||
@ResponseStatus(org.springframework.http.HttpStatus.UNAUTHORIZED)
|
||||
@ExceptionHandler(SseException.class)
|
||||
public String handleNotLoginException(SseException e, HttpServletRequest request) {
|
||||
String requestURI = request.getRequestURI();
|
||||
log.error("请求地址'{}',认证失败'{}',无法访问系统资源", requestURI, e.getMessage());
|
||||
return JsonUtils.toJsonString(R.fail(HttpStatus.HTTP_UNAUTHORIZED, "认证失败,无法访问系统资源"));
|
||||
}
|
||||
|
||||
/**
|
||||
* servlet异常
|
||||
*/
|
||||
@ExceptionHandler(ServletException.class)
|
||||
public R<Void> handleServletException(ServletException e, HttpServletRequest request) {
|
||||
if (StringUtils.contains(e.getMessage(), "NotLoginException")) {
|
||||
String requestURI = request.getRequestURI();
|
||||
log.error("请求地址'{}',认证失败'{}',无法访问系统资源", requestURI, e.getMessage());
|
||||
return R.fail(HttpStatus.HTTP_UNAUTHORIZED, "认证失败,无法访问系统资源");
|
||||
} else {
|
||||
String requestURI = request.getRequestURI();
|
||||
log.error("请求地址'{}',发生未知异常.", requestURI, e);
|
||||
return R.fail(e.getMessage());
|
||||
}
|
||||
String requestURI = request.getRequestURI();
|
||||
log.error("请求地址'{}',发生未知异常.", requestURI, e);
|
||||
return R.fail(e.getMessage());
|
||||
}
|
||||
|
||||
/**
|
||||
@ -170,7 +176,7 @@ public class GlobalExceptionHandler {
|
||||
@ExceptionHandler(MethodArgumentNotValidException.class)
|
||||
public R<Void> handleMethodArgumentNotValidException(MethodArgumentNotValidException e) {
|
||||
log.error(e.getMessage());
|
||||
String message = e.getBindingResult().getFieldError().getDefaultMessage();
|
||||
String message = StreamUtils.join(e.getBindingResult().getAllErrors(), DefaultMessageSourceResolvable::getDefaultMessage, ", ");
|
||||
return R.fail(message);
|
||||
}
|
||||
|
||||
|
@ -48,7 +48,7 @@ public interface TestDemoMapper extends BaseMapperPlus<TestDemo, TestDemoVo> {
|
||||
@DataColumn(key = "deptName", value = "dept_id"),
|
||||
@DataColumn(key = "userName", value = "user_id")
|
||||
}, joinStr = "AND")
|
||||
List<TestDemo> selectBatchIds(@Param(Constants.COLL) Collection<? extends Serializable> idList);
|
||||
List<TestDemo> selectByIds(@Param(Constants.COLL) Collection<? extends Serializable> idList);
|
||||
|
||||
@Override
|
||||
@DataPermission({
|
||||
|
@ -101,7 +101,7 @@ public class TestDemoServiceImpl implements ITestDemoService {
|
||||
public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
|
||||
if (isValid) {
|
||||
// 做一些业务上的校验,判断是否需要校验
|
||||
List<TestDemo> list = baseMapper.selectBatchIds(ids);
|
||||
List<TestDemo> list = baseMapper.selectByIds(ids);
|
||||
if (list.size() != ids.size()) {
|
||||
throw new ServiceException("您没有删除权限!");
|
||||
}
|
||||
|
@ -56,13 +56,13 @@ public interface GenConstants {
|
||||
* 数据库时间类型
|
||||
*/
|
||||
String[] COLUMNTYPE_TIME = {"datetime", "time", "date", "timestamp", "year", "interval",
|
||||
"smalldatetime", "datetime2", "datetimeoffset"};
|
||||
"smalldatetime", "datetime2", "datetimeoffset", "timestamptz"};
|
||||
|
||||
/**
|
||||
* 数据库数字类型
|
||||
*/
|
||||
String[] COLUMNTYPE_NUMBER = {"tinyint", "smallint", "mediumint", "int", "number", "integer",
|
||||
"bit", "bigint", "float", "double", "decimal", "numeric", "real", "double precision",
|
||||
String[] COLUMNTYPE_NUMBER = {"tinyint", "smallint", "mediumint", "int", "int2", "int4", "int8", "number", "integer",
|
||||
"bit", "bigint", "float", "float4", "float8", "double", "decimal", "numeric", "real", "double precision",
|
||||
"smallserial", "serial", "bigserial", "money", "smallmoney"};
|
||||
|
||||
/**
|
||||
|
@ -244,7 +244,7 @@ public class SysOssServiceImpl implements ISysOssService, OssService {
|
||||
if (isValid) {
|
||||
// 做一些业务上的校验,判断是否需要校验
|
||||
}
|
||||
List<SysOss> list = baseMapper.selectBatchIds(ids);
|
||||
List<SysOss> list = baseMapper.selectByIds(ids);
|
||||
for (SysOss sysOss : list) {
|
||||
OssClient storage = OssFactory.instance(sysOss.getService());
|
||||
storage.delete(sysOss.getUrl());
|
||||
|
@ -444,12 +444,14 @@ public class SysTenantServiceImpl implements ISysTenantService {
|
||||
}
|
||||
}
|
||||
}
|
||||
if (CollUtil.isNotEmpty(saveTypeList)) {
|
||||
dictTypeMapper.insertBatch(saveTypeList);
|
||||
}
|
||||
if (CollUtil.isNotEmpty(saveDataList)) {
|
||||
dictDataMapper.insertBatch(saveDataList);
|
||||
}
|
||||
TenantHelper.ignore(() -> {
|
||||
if (CollUtil.isNotEmpty(saveTypeList)) {
|
||||
dictTypeMapper.insertBatch(saveTypeList);
|
||||
}
|
||||
if (CollUtil.isNotEmpty(saveDataList)) {
|
||||
dictDataMapper.insertBatch(saveDataList);
|
||||
}
|
||||
});
|
||||
for (String tenantId : set) {
|
||||
TenantHelper.dynamic(tenantId, () -> CacheUtils.clear(CacheNames.SYS_DICT));
|
||||
}
|
||||
|
@ -142,11 +142,16 @@ public class TestLeaveServiceImpl implements ITestLeaveService {
|
||||
*
|
||||
* @param processTaskEvent 参数
|
||||
*/
|
||||
@EventListener(condition = "#processTaskEvent.key=='leave1' && #processTaskEvent.taskDefinitionKey=='Activity_14633hx'")
|
||||
@EventListener(condition = "#processTaskEvent.key.startsWith('leave')")
|
||||
public void processTaskHandler(ProcessTaskEvent processTaskEvent) {
|
||||
log.info("当前任务执行了{}", processTaskEvent.toString());
|
||||
TestLeave testLeave = baseMapper.selectById(Long.valueOf(processTaskEvent.getBusinessKey()));
|
||||
testLeave.setStatus(BusinessStatusEnum.WAITING.getStatus());
|
||||
baseMapper.updateById(testLeave);
|
||||
// 所有demo案例的申请人节点id
|
||||
String[] ids = {"Activity_14633hx", "Activity_19b1i4j", "Activity_0uscrk3",
|
||||
"Activity_0uscrk3", "Activity_0x6b71j", "Activity_0zy3g6j", "Activity_06a55t0"};
|
||||
if (StringUtils.equalsAny(processTaskEvent.getTaskDefinitionKey(), ids)) {
|
||||
log.info("当前任务执行了{}", processTaskEvent.toString());
|
||||
TestLeave testLeave = baseMapper.selectById(Long.valueOf(processTaskEvent.getBusinessKey()));
|
||||
testLeave.setStatus(BusinessStatusEnum.WAITING.getStatus());
|
||||
baseMapper.updateById(testLeave);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -41,7 +41,7 @@ public class WfFormManageServiceImpl implements IWfFormManageService {
|
||||
|
||||
@Override
|
||||
public List<WfFormManageVo> queryByIds(List<Long> ids) {
|
||||
return baseMapper.selectVoBatchIds(ids);
|
||||
return baseMapper.selectVoByIds(ids);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -427,7 +427,7 @@ comment on column sys_menu.remark is '备注';
|
||||
-- ----------------------------
|
||||
-- 一级菜单
|
||||
insert into sys_menu values('1', '系统管理', '0', '1', 'system', null, '', '1', '0', 'M', '0', '0', '', 'system', 103, 1, now(), null, null, '系统管理目录');
|
||||
insert into sys_menu values('6', '系统管理', '0', '2', 'tenant', null, '', '1', '0', 'M', '0', '0', '', 'chart', 103, 1, now(), null, null, '租户管理目录');
|
||||
insert into sys_menu values('6', '租户管理', '0', '2', 'tenant', null, '', '1', '0', 'M', '0', '0', '', 'chart', 103, 1, now(), null, null, '租户管理目录');
|
||||
insert into sys_menu values('2', '系统监控', '0', '3', 'monitor', null, '', '1', '0', 'M', '0', '0', '', 'monitor', 103, 1, now(), null, null, '系统监控目录');
|
||||
insert into sys_menu values('3', '系统工具', '0', '4', 'tool', null, '', '1', '0', 'M', '0', '0', '', 'tool', 103, 1, now(), null, null, '系统工具目录');
|
||||
insert into sys_menu values('4', 'PLUS官网', '0', '5', 'https://gitee.com/dromara/RuoYi-Vue-Plus', null, '', '0', '0', 'M', '0', '0', '', 'guide', 103, 1, now(), null, null, 'RuoYi-Vue-Plus官网地址');
|
||||
|
Loading…
x
Reference in New Issue
Block a user