diff --git a/ruoyi-admin/src/main/java/org/dromara/DromaraApplication.java b/ruoyi-admin/src/main/java/org/dromara/DromaraApplication.java index 8ef33fe5f..0f4defbd7 100644 --- a/ruoyi-admin/src/main/java/org/dromara/DromaraApplication.java +++ b/ruoyi-admin/src/main/java/org/dromara/DromaraApplication.java @@ -13,6 +13,11 @@ import org.springframework.boot.context.metrics.buffering.BufferingApplicationSt @SpringBootApplication public class DromaraApplication { + /** + * 应用启动入口。 + * + * @param args 启动参数 + */ public static void main(String[] args) { SpringApplication application = new SpringApplication(DromaraApplication.class); application.setApplicationStartup(new BufferingApplicationStartup(2048)); diff --git a/ruoyi-admin/src/main/java/org/dromara/DromaraServletInitializer.java b/ruoyi-admin/src/main/java/org/dromara/DromaraServletInitializer.java index 066a68377..2363e3c5c 100644 --- a/ruoyi-admin/src/main/java/org/dromara/DromaraServletInitializer.java +++ b/ruoyi-admin/src/main/java/org/dromara/DromaraServletInitializer.java @@ -10,6 +10,12 @@ import org.springframework.boot.web.servlet.support.SpringBootServletInitializer */ public class DromaraServletInitializer extends SpringBootServletInitializer { + /** + * 配置外部 Web 容器启动源。 + * + * @param application Spring 应用构建器 + * @return 配置后的 Spring 应用构建器 + */ @Override protected SpringApplicationBuilder configure(SpringApplicationBuilder application) { return application.sources(DromaraApplication.class); diff --git a/ruoyi-admin/src/main/java/org/dromara/web/service/SysLoginService.java b/ruoyi-admin/src/main/java/org/dromara/web/service/SysLoginService.java index 77a03c270..b14120391 100644 --- a/ruoyi-admin/src/main/java/org/dromara/web/service/SysLoginService.java +++ b/ruoyi-admin/src/main/java/org/dromara/web/service/SysLoginService.java @@ -46,9 +46,15 @@ import java.util.function.Supplier; @Service public class SysLoginService { + /** + * 最大重试次数。 + */ @Value("${user.password.maxRetryCount}") private Integer maxRetryCount; + /** + * 锁定时间。 + */ @Value("${user.password.lockTime}") private Integer lockTime; diff --git a/ruoyi-api/src/main/java/org/dromara/system/api/domain/TaskAssigneeDTO.java b/ruoyi-api/src/main/java/org/dromara/system/api/domain/TaskAssigneeDTO.java index e6f8bcea4..867565c09 100644 --- a/ruoyi-api/src/main/java/org/dromara/system/api/domain/TaskAssigneeDTO.java +++ b/ruoyi-api/src/main/java/org/dromara/system/api/domain/TaskAssigneeDTO.java @@ -34,6 +34,12 @@ public class TaskAssigneeDTO implements Serializable { */ private List list; + /** + * 创建任务受让人分页结果。 + * + * @param total 总大小 + * @param list 受让人列表 + */ public TaskAssigneeDTO(Long total, List list) { this.total = total; this.list = list; diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/config/ThreadPoolConfig.java b/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/config/ThreadPoolConfig.java index 1322e1d73..a5f423aea 100644 --- a/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/config/ThreadPoolConfig.java +++ b/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/config/ThreadPoolConfig.java @@ -14,7 +14,7 @@ import java.util.concurrent.*; * 线程池配置 * * @author Lion Li - **/ + */ @Slf4j @AutoConfiguration public class ThreadPoolConfig { diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/utils/DateUtils.java b/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/utils/DateUtils.java index 498c273ba..03841f642 100644 --- a/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/utils/DateUtils.java +++ b/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/utils/DateUtils.java @@ -20,6 +20,9 @@ import java.util.concurrent.TimeUnit; * @author ruoyi */ public class DateUtils extends org.apache.commons.lang3.time.DateUtils { + /** + * 日期解析格式集合。 + */ 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", diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/utils/file/MimeTypeUtils.java b/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/utils/file/MimeTypeUtils.java index 23fa2cfe2..517082dc3 100644 --- a/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/utils/file/MimeTypeUtils.java +++ b/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/utils/file/MimeTypeUtils.java @@ -6,25 +6,56 @@ package org.dromara.common.core.utils.file; * @author ruoyi */ public class MimeTypeUtils { + + /** + * PNG 图片 MIME 类型。 + */ public static final String IMAGE_PNG = "image/png"; + /** + * JPG 图片 MIME 类型。 + */ public static final String IMAGE_JPG = "image/jpg"; + /** + * JPEG 图片 MIME 类型。 + */ public static final String IMAGE_JPEG = "image/jpeg"; + /** + * BMP 图片 MIME 类型。 + */ public static final String IMAGE_BMP = "image/bmp"; + /** + * GIF 图片 MIME 类型。 + */ public static final String IMAGE_GIF = "image/gif"; + /** + * 图片扩展名集合。 + */ public static final String[] IMAGE_EXTENSION = {"bmp", "gif", "jpg", "jpeg", "png"}; + /** + * Flash 扩展名集合。 + */ 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[] DEFAULT_ALLOWED_EXTENSION = { // 图片 "bmp", "gif", "jpg", "jpeg", "png", diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/validate/enums/EnumPatternValidator.java b/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/validate/enums/EnumPatternValidator.java index a6cd52865..14f15a245 100644 --- a/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/validate/enums/EnumPatternValidator.java +++ b/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/validate/enums/EnumPatternValidator.java @@ -16,8 +16,16 @@ import java.util.Set; */ public class EnumPatternValidator implements ConstraintValidator { + /** + * 枚举允许值集合。 + */ private final Set values = new HashSet<>(); + /** + * 初始化枚举允许值集合。 + * + * @param annotation 枚举校验注解 + */ @Override public void initialize(EnumPattern annotation) { ConstraintValidator.super.initialize(annotation); @@ -33,6 +41,13 @@ public class EnumPatternValidator implements ConstraintValidator { + /** + * 校验字符串是否包含 HTML 标签。 + * + * @param value 待校验值 + * @param constraintValidatorContext 校验上下文 + * @return true 校验通过 false 包含 HTML 标签 + */ @Override public boolean isValid(String value, ConstraintValidatorContext constraintValidatorContext) { if (StringUtils.isBlank(value)) { diff --git a/ruoyi-common/ruoyi-common-elasticsearch/src/main/java/org/dromara/common/elasticsearch/config/ActuatorEnvironmentPostProcessor.java b/ruoyi-common/ruoyi-common-elasticsearch/src/main/java/org/dromara/common/elasticsearch/config/ActuatorEnvironmentPostProcessor.java index e33a67edc..2fcacc804 100644 --- a/ruoyi-common/ruoyi-common-elasticsearch/src/main/java/org/dromara/common/elasticsearch/config/ActuatorEnvironmentPostProcessor.java +++ b/ruoyi-common/ruoyi-common-elasticsearch/src/main/java/org/dromara/common/elasticsearch/config/ActuatorEnvironmentPostProcessor.java @@ -12,12 +12,23 @@ import org.springframework.core.env.ConfigurableEnvironment; */ public class ActuatorEnvironmentPostProcessor implements EnvironmentPostProcessor, Ordered { + /** + * 根据 easy-es 开关同步设置 Elasticsearch 健康检查开关。 + * + * @param environment Spring 环境配置 + * @param application Spring 应用实例 + */ @Override public void postProcessEnvironment(ConfigurableEnvironment environment, SpringApplication application) { String enable = environment.getProperty("easy-es.enable", "false"); System.setProperty("management.health.elasticsearch.enabled", enable); } + /** + * 返回环境后处理器执行顺序。 + * + * @return 最高优先级 + */ @Override public int getOrder() { return Ordered.HIGHEST_PRECEDENCE; diff --git a/ruoyi-common/ruoyi-common-encrypt/src/main/java/org/dromara/common/encrypt/config/EncryptorAutoConfiguration.java b/ruoyi-common/ruoyi-common-encrypt/src/main/java/org/dromara/common/encrypt/config/EncryptorAutoConfiguration.java index 686e2fcc4..7c5de50bd 100644 --- a/ruoyi-common/ruoyi-common-encrypt/src/main/java/org/dromara/common/encrypt/config/EncryptorAutoConfiguration.java +++ b/ruoyi-common/ruoyi-common-encrypt/src/main/java/org/dromara/common/encrypt/config/EncryptorAutoConfiguration.java @@ -56,7 +56,7 @@ public class EncryptorAutoConfiguration { /** * 创建加密字段处理器。 * - * @param encryptorManager 加解密管理器 + * @param encryptorManager 加解密管理器 * @param encryptContextFactory 加密上下文工厂 * @return 加密字段处理器 */ @@ -87,6 +87,11 @@ public class EncryptorAutoConfiguration { return new MybatisDecryptInterceptor(encryptedFieldProcessor); } + /** + * 校验字段加解密配置完整性。 + * + * @param properties 字段加解密配置 + */ private void validateEncryptorProperties(EncryptorProperties properties) { AlgorithmType algorithm = properties.getAlgorithm(); if (algorithm == AlgorithmType.AES || algorithm == AlgorithmType.SM4) { @@ -102,5 +107,3 @@ public class EncryptorAutoConfiguration { } } - - diff --git a/ruoyi-common/ruoyi-common-encrypt/src/main/java/org/dromara/common/encrypt/core/EncryptedFieldProcessor.java b/ruoyi-common/ruoyi-common-encrypt/src/main/java/org/dromara/common/encrypt/core/EncryptedFieldProcessor.java index b6b712c22..07f646e94 100644 --- a/ruoyi-common/ruoyi-common-encrypt/src/main/java/org/dromara/common/encrypt/core/EncryptedFieldProcessor.java +++ b/ruoyi-common/ruoyi-common-encrypt/src/main/java/org/dromara/common/encrypt/core/EncryptedFieldProcessor.java @@ -23,7 +23,7 @@ public class EncryptedFieldProcessor { * 构造加密字段处理器。 * * @param encryptorManager 加解密管理器 - * @param contextFactory 加密上下文工厂 + * @param contextFactory 加密上下文工厂 */ public EncryptedFieldProcessor(EncryptorManager encryptorManager, EncryptContextFactory contextFactory) { this.encryptorManager = encryptorManager; @@ -58,6 +58,13 @@ public class EncryptedFieldProcessor { field.set(target, encryptorManager.decrypt(value, contextFactory.create(field)))); } + /** + * 递归处理对象、集合或 Map 中声明加密注解的字段。 + * + * @param sourceObject 待处理对象 + * @param visited 已访问对象集合 + * @param fieldHandler 字段处理回调 + */ private void handle(Object sourceObject, Set visited, FieldHandler fieldHandler) { if (ObjectUtil.isNull(sourceObject) || sourceObject instanceof String || visited.contains(sourceObject)) { return; @@ -100,8 +107,8 @@ public class EncryptedFieldProcessor { * 处理单个加密字段。 * * @param target 字段所属对象 - * @param field 加密字段 - * @param value 字段原始字符串值 + * @param field 加密字段 + * @param value 字段原始字符串值 * @throws IllegalAccessException 字段访问失败时抛出 */ void handle(Object target, Field field, String value) throws IllegalAccessException; diff --git a/ruoyi-common/ruoyi-common-encrypt/src/main/java/org/dromara/common/encrypt/core/encryptor/AbstractEncryptor.java b/ruoyi-common/ruoyi-common-encrypt/src/main/java/org/dromara/common/encrypt/core/encryptor/AbstractEncryptor.java index 858d229d8..be2d001f6 100644 --- a/ruoyi-common/ruoyi-common-encrypt/src/main/java/org/dromara/common/encrypt/core/encryptor/AbstractEncryptor.java +++ b/ruoyi-common/ruoyi-common-encrypt/src/main/java/org/dromara/common/encrypt/core/encryptor/AbstractEncryptor.java @@ -11,6 +11,11 @@ import org.dromara.common.encrypt.core.IEncryptor; */ public abstract class AbstractEncryptor implements IEncryptor { + /** + * 初始化加密执行者。 + * + * @param context 加密上下文 + */ public AbstractEncryptor(EncryptContext context) { // 用户配置校验与配置注入 } diff --git a/ruoyi-common/ruoyi-common-encrypt/src/main/java/org/dromara/common/encrypt/core/encryptor/Base64Encryptor.java b/ruoyi-common/ruoyi-common-encrypt/src/main/java/org/dromara/common/encrypt/core/encryptor/Base64Encryptor.java index a7b241608..a6709c95a 100644 --- a/ruoyi-common/ruoyi-common-encrypt/src/main/java/org/dromara/common/encrypt/core/encryptor/Base64Encryptor.java +++ b/ruoyi-common/ruoyi-common-encrypt/src/main/java/org/dromara/common/encrypt/core/encryptor/Base64Encryptor.java @@ -13,6 +13,11 @@ import org.dromara.common.encrypt.utils.EncryptUtils; */ public class Base64Encryptor extends AbstractEncryptor { + /** + * 初始化 Base64 加密执行者。 + * + * @param context 加密上下文 + */ public Base64Encryptor(EncryptContext context) { super(context); } diff --git a/ruoyi-common/ruoyi-common-encrypt/src/main/java/org/dromara/common/encrypt/core/encryptor/RsaEncryptor.java b/ruoyi-common/ruoyi-common-encrypt/src/main/java/org/dromara/common/encrypt/core/encryptor/RsaEncryptor.java index 46f3f2539..1c947fe11 100644 --- a/ruoyi-common/ruoyi-common-encrypt/src/main/java/org/dromara/common/encrypt/core/encryptor/RsaEncryptor.java +++ b/ruoyi-common/ruoyi-common-encrypt/src/main/java/org/dromara/common/encrypt/core/encryptor/RsaEncryptor.java @@ -17,6 +17,11 @@ public class RsaEncryptor extends AbstractEncryptor { private final EncryptContext context; + /** + * 构造 RSA 加密器。 + * + * @param context 加密上下文 + */ public RsaEncryptor(EncryptContext context) { super(context); String privateKey = context.getPrivateKey(); @@ -53,7 +58,7 @@ public class RsaEncryptor extends AbstractEncryptor { /** * 解密 * - * @param value 待加密字符串 + * @param value 待加密字符串 */ @Override public String decrypt(String value) { diff --git a/ruoyi-common/ruoyi-common-encrypt/src/main/java/org/dromara/common/encrypt/core/encryptor/Sm2Encryptor.java b/ruoyi-common/ruoyi-common-encrypt/src/main/java/org/dromara/common/encrypt/core/encryptor/Sm2Encryptor.java index a1113788a..3356099ca 100644 --- a/ruoyi-common/ruoyi-common-encrypt/src/main/java/org/dromara/common/encrypt/core/encryptor/Sm2Encryptor.java +++ b/ruoyi-common/ruoyi-common-encrypt/src/main/java/org/dromara/common/encrypt/core/encryptor/Sm2Encryptor.java @@ -16,6 +16,11 @@ public class Sm2Encryptor extends AbstractEncryptor { private final EncryptContext context; + /** + * 构造 SM2 加密器。 + * + * @param context 加密上下文 + */ public Sm2Encryptor(EncryptContext context) { super(context); String privateKey = context.getPrivateKey(); @@ -52,7 +57,7 @@ public class Sm2Encryptor extends AbstractEncryptor { /** * 解密 * - * @param value 待加密字符串 + * @param value 待加密字符串 */ @Override public String decrypt(String value) { diff --git a/ruoyi-common/ruoyi-common-encrypt/src/main/java/org/dromara/common/encrypt/core/encryptor/Sm4Encryptor.java b/ruoyi-common/ruoyi-common-encrypt/src/main/java/org/dromara/common/encrypt/core/encryptor/Sm4Encryptor.java index 8528fbbbf..11ce53c0b 100644 --- a/ruoyi-common/ruoyi-common-encrypt/src/main/java/org/dromara/common/encrypt/core/encryptor/Sm4Encryptor.java +++ b/ruoyi-common/ruoyi-common-encrypt/src/main/java/org/dromara/common/encrypt/core/encryptor/Sm4Encryptor.java @@ -15,6 +15,11 @@ public class Sm4Encryptor extends AbstractEncryptor { private final EncryptContext context; + /** + * 构造 SM4 加密器。 + * + * @param context 加密上下文 + */ public Sm4Encryptor(EncryptContext context) { super(context); this.context = context; @@ -46,7 +51,7 @@ public class Sm4Encryptor extends AbstractEncryptor { /** * 解密 * - * @param value 待加密字符串 + * @param value 待加密字符串 */ @Override public String decrypt(String value) { diff --git a/ruoyi-common/ruoyi-common-encrypt/src/main/java/org/dromara/common/encrypt/filter/CryptoFilter.java b/ruoyi-common/ruoyi-common-encrypt/src/main/java/org/dromara/common/encrypt/filter/CryptoFilter.java index 8a13a00af..044bf3466 100644 --- a/ruoyi-common/ruoyi-common-encrypt/src/main/java/org/dromara/common/encrypt/filter/CryptoFilter.java +++ b/ruoyi-common/ruoyi-common-encrypt/src/main/java/org/dromara/common/encrypt/filter/CryptoFilter.java @@ -32,9 +32,9 @@ public class CryptoFilter implements Filter { /** * 构造加解密过滤器。 * - * @param properties API 解密配置 + * @param properties API 解密配置 * @param requestMappingHandlerMapping 请求映射处理器 - * @param handlerExceptionResolver 异常处理器 + * @param handlerExceptionResolver 异常处理器 */ public CryptoFilter(ApiDecryptProperties properties, RequestMappingHandlerMapping requestMappingHandlerMapping, @@ -46,6 +46,15 @@ public class CryptoFilter implements Filter { EncryptUtils.validateRsaPrivateKey(properties.getPrivateKey()); } + /** + * 根据接口注解与请求头执行请求解密和响应加密。 + * + * @param request 原始请求 + * @param response 原始响应 + * @param chain 过滤器链 + * @throws IOException IO 异常 + * @throws ServletException Servlet 异常 + */ @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { HttpServletRequest servletRequest = (HttpServletRequest) request; @@ -96,6 +105,9 @@ public class CryptoFilter implements Filter { /** * 获取 ApiEncrypt 注解 + * + * @param servletRequest 当前请求 + * @return API 加密注解 */ private ApiEncrypt getApiEncryptAnnotation(HttpServletRequest servletRequest) { // 获取注解 @@ -116,6 +128,9 @@ public class CryptoFilter implements Filter { return null; } + /** + * 销毁过滤器。 + */ @Override public void destroy() { } diff --git a/ruoyi-common/ruoyi-common-encrypt/src/main/java/org/dromara/common/encrypt/filter/DecryptRequestBodyWrapper.java b/ruoyi-common/ruoyi-common-encrypt/src/main/java/org/dromara/common/encrypt/filter/DecryptRequestBodyWrapper.java index b5ca633f8..314028f36 100644 --- a/ruoyi-common/ruoyi-common-encrypt/src/main/java/org/dromara/common/encrypt/filter/DecryptRequestBodyWrapper.java +++ b/ruoyi-common/ruoyi-common-encrypt/src/main/java/org/dromara/common/encrypt/filter/DecryptRequestBodyWrapper.java @@ -23,6 +23,9 @@ import java.nio.charset.StandardCharsets; */ public class DecryptRequestBodyWrapper extends HttpServletRequestWrapper { + /** + * 请求体字节数据。 + */ private final byte[] body; /** @@ -48,6 +51,11 @@ public class DecryptRequestBodyWrapper extends HttpServletRequestWrapper { body = decryptBody.getBytes(StandardCharsets.UTF_8); } + /** + * 基于解密后的请求体创建字符读取器。 + * + * @return 字符读取器 + */ @Override public BufferedReader getReader() { Charset charset = Charset.forName(getCharacterEncoding()); @@ -55,46 +63,91 @@ public class DecryptRequestBodyWrapper extends HttpServletRequestWrapper { } + /** + * 返回解密后请求体长度。 + * + * @return 请求体长度 + */ @Override public int getContentLength() { return body.length; } + /** + * 返回解密后请求体长度。 + * + * @return 请求体长度 + */ @Override public long getContentLengthLong() { return body.length; } + /** + * 返回解密后的请求体类型。 + * + * @return JSON 内容类型 + */ @Override public String getContentType() { return MediaType.APPLICATION_JSON_VALUE; } + /** + * 返回基于解密请求体的输入流。 + * + * @return 解密请求体输入流 + */ @Override public ServletInputStream getInputStream() { final ByteArrayInputStream bais = new ByteArrayInputStream(body); return new ServletInputStream() { + /** + * 读取解密请求体下一个字节。 + * + * @return 下一个字节 + */ @Override public int read() { return bais.read(); } + /** + * 返回解密请求体剩余可读字节数。 + * + * @return 剩余字节数 + */ @Override public int available() { return bais.available(); } + /** + * 判断解密请求体是否读取完毕。 + * + * @return 是否读取完毕 + */ @Override public boolean isFinished() { return bais.available() == 0; } + /** + * 判断解密请求体输入流是否可读。 + * + * @return 固定为 true + */ @Override public boolean isReady() { return true; } + /** + * 设置异步读取监听器。 + * + * @param readListener 读取监听器 + */ @Override public void setReadListener(ReadListener readListener) { diff --git a/ruoyi-common/ruoyi-common-encrypt/src/main/java/org/dromara/common/encrypt/filter/EncryptResponseBodyWrapper.java b/ruoyi-common/ruoyi-common-encrypt/src/main/java/org/dromara/common/encrypt/filter/EncryptResponseBodyWrapper.java index 680111d49..35200db34 100644 --- a/ruoyi-common/ruoyi-common-encrypt/src/main/java/org/dromara/common/encrypt/filter/EncryptResponseBodyWrapper.java +++ b/ruoyi-common/ruoyi-common-encrypt/src/main/java/org/dromara/common/encrypt/filter/EncryptResponseBodyWrapper.java @@ -6,7 +6,10 @@ import jakarta.servlet.http.HttpServletResponse; import jakarta.servlet.http.HttpServletResponseWrapper; import org.dromara.common.encrypt.utils.EncryptUtils; -import java.io.*; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.OutputStreamWriter; +import java.io.PrintWriter; import java.nio.charset.Charset; import java.nio.charset.StandardCharsets; import java.security.SecureRandom; @@ -39,6 +42,11 @@ public class EncryptResponseBodyWrapper extends HttpServletResponseWrapper { this.charset = resolveCharset(response); } + /** + * 返回缓存响应内容的字符输出器。 + * + * @return 字符输出器 + */ @Override public PrintWriter getWriter() { if (printWriter == null) { @@ -48,6 +56,11 @@ public class EncryptResponseBodyWrapper extends HttpServletResponseWrapper { return printWriter; } + /** + * 刷新缓存的响应输出流和字符输出器。 + * + * @throws IOException IO 异常 + */ @Override public void flushBuffer() throws IOException { if (servletOutputStream != null) { @@ -58,11 +71,17 @@ public class EncryptResponseBodyWrapper extends HttpServletResponseWrapper { } } + /** + * 重置已缓存的响应内容。 + */ @Override public void reset() { byteArrayOutputStream.reset(); } + /** + * 重置已缓存的响应缓冲区。 + */ @Override public void resetBuffer() { byteArrayOutputStream.reset(); @@ -122,29 +141,64 @@ public class EncryptResponseBodyWrapper extends HttpServletResponseWrapper { return encryptContent; } + /** + * 返回缓存响应内容的二进制输出流。 + * + * @return 响应输出流 + */ @Override public ServletOutputStream getOutputStream() throws IOException { return new ServletOutputStream() { + /** + * 判断响应输出流是否可写。 + * + * @return 固定为 true + */ @Override public boolean isReady() { return true; } + /** + * 设置异步写入监听器。 + * + * @param writeListener 写入监听器 + */ @Override public void setWriteListener(WriteListener writeListener) { } + /** + * 写入单个字节到响应缓存。 + * + * @param b 待写入字节 + * @throws IOException IO 异常 + */ @Override public void write(int b) throws IOException { byteArrayOutputStream.write(b); } + /** + * 写入字节数组到响应缓存。 + * + * @param b 待写入字节数组 + * @throws IOException IO 异常 + */ @Override public void write(byte[] b) throws IOException { byteArrayOutputStream.write(b); } + /** + * 写入字节数组片段到响应缓存。 + * + * @param b 待写入字节数组 + * @param off 起始偏移量 + * @param len 写入长度 + * @throws IOException IO 异常 + */ @Override public void write(byte[] b, int off, int len) throws IOException { byteArrayOutputStream.write(b, off, len); @@ -152,6 +206,12 @@ public class EncryptResponseBodyWrapper extends HttpServletResponseWrapper { }; } + /** + * 解析响应字符集,未设置时默认使用 UTF-8。 + * + * @param response 原始响应 + * @return 响应字符集 + */ private Charset resolveCharset(HttpServletResponse response) { String characterEncoding = response.getCharacterEncoding(); if (characterEncoding == null) { @@ -160,6 +220,11 @@ public class EncryptResponseBodyWrapper extends HttpServletResponseWrapper { return Charset.forName(characterEncoding); } + /** + * 生成响应内容 AES 加密密钥。 + * + * @return AES 密钥 + */ private String generateAesPassword() { byte[] bytes = new byte[24]; SECURE_RANDOM.nextBytes(bytes); diff --git a/ruoyi-common/ruoyi-common-encrypt/src/main/java/org/dromara/common/encrypt/interceptor/MybatisDecryptInterceptor.java b/ruoyi-common/ruoyi-common-encrypt/src/main/java/org/dromara/common/encrypt/interceptor/MybatisDecryptInterceptor.java index e278fcecd..d9932b0d1 100644 --- a/ruoyi-common/ruoyi-common-encrypt/src/main/java/org/dromara/common/encrypt/interceptor/MybatisDecryptInterceptor.java +++ b/ruoyi-common/ruoyi-common-encrypt/src/main/java/org/dromara/common/encrypt/interceptor/MybatisDecryptInterceptor.java @@ -23,6 +23,13 @@ public class MybatisDecryptInterceptor implements Interceptor { private final EncryptedFieldProcessor encryptedFieldProcessor; + /** + * 解密 MyBatis 查询结果中的加密字段。 + * + * @param invocation 拦截调用信息 + * @return 查询结果 + * @throws Throwable 拦截处理异常 + */ @Override public Object intercept(Invocation invocation) throws Throwable { // 获取执行mysql执行结果 @@ -34,11 +41,22 @@ public class MybatisDecryptInterceptor implements Interceptor { return result; } + /** + * 包装 MyBatis 目标对象。 + * + * @param target 目标对象 + * @return 包装后的对象 + */ @Override public Object plugin(Object target) { return Plugin.wrap(target, this); } + /** + * 设置插件属性。 + * + * @param properties 插件属性 + */ @Override public void setProperties(Properties properties) { diff --git a/ruoyi-common/ruoyi-common-encrypt/src/main/java/org/dromara/common/encrypt/interceptor/MybatisEncryptInterceptor.java b/ruoyi-common/ruoyi-common-encrypt/src/main/java/org/dromara/common/encrypt/interceptor/MybatisEncryptInterceptor.java index 7659bd9b7..2516649b8 100644 --- a/ruoyi-common/ruoyi-common-encrypt/src/main/java/org/dromara/common/encrypt/interceptor/MybatisEncryptInterceptor.java +++ b/ruoyi-common/ruoyi-common-encrypt/src/main/java/org/dromara/common/encrypt/interceptor/MybatisEncryptInterceptor.java @@ -25,6 +25,13 @@ public class MybatisEncryptInterceptor implements Interceptor { private final EncryptedFieldProcessor encryptedFieldProcessor; + /** + * 加密 MyBatis 入参中的加密字段,并在执行后恢复原始值。 + * + * @param invocation 拦截调用信息 + * @return MyBatis 执行结果 + * @throws Throwable 拦截处理异常 + */ @Override public Object intercept(Invocation invocation) throws Throwable { List snapshots = List.of(); @@ -44,11 +51,22 @@ public class MybatisEncryptInterceptor implements Interceptor { } } + /** + * 包装 MyBatis 目标对象。 + * + * @param target 目标对象 + * @return 包装后的对象 + */ @Override public Object plugin(Object target) { return Plugin.wrap(target, this); } + /** + * 设置插件属性。 + * + * @param properties 插件属性 + */ @Override public void setProperties(Properties properties) { } diff --git a/ruoyi-common/ruoyi-common-encrypt/src/main/java/org/dromara/common/encrypt/utils/EncryptUtils.java b/ruoyi-common/ruoyi-common-encrypt/src/main/java/org/dromara/common/encrypt/utils/EncryptUtils.java index 1d5396708..459b164b1 100644 --- a/ruoyi-common/ruoyi-common-encrypt/src/main/java/org/dromara/common/encrypt/utils/EncryptUtils.java +++ b/ruoyi-common/ruoyi-common-encrypt/src/main/java/org/dromara/common/encrypt/utils/EncryptUtils.java @@ -381,6 +381,11 @@ public class EncryptUtils { } } + /** + * 校验 RSA 密钥长度是否满足最低安全要求。 + * + * @param rsaKey RSA 密钥 + */ private static void validateRsaKeySize(RSAKey rsaKey) { int keySize = rsaKey.getModulus().bitLength(); if (keySize < MIN_RSA_KEY_SIZE) { diff --git a/ruoyi-common/ruoyi-common-excel/src/main/java/org/dromara/common/excel/convert/ExcelBigNumberConvert.java b/ruoyi-common/ruoyi-common-excel/src/main/java/org/dromara/common/excel/convert/ExcelBigNumberConvert.java index ef69cec70..fc6745ae2 100644 --- a/ruoyi-common/ruoyi-common-excel/src/main/java/org/dromara/common/excel/convert/ExcelBigNumberConvert.java +++ b/ruoyi-common/ruoyi-common-excel/src/main/java/org/dromara/common/excel/convert/ExcelBigNumberConvert.java @@ -21,21 +21,47 @@ import java.math.BigDecimal; @Slf4j public class ExcelBigNumberConvert implements Converter { + /** + * 支持的 Java 类型。 + * + * @return Long 类型 + */ @Override public Class supportJavaTypeKey() { return Long.class; } + /** + * 支持的 Excel 单元格类型。 + * + * @return 默认支持全部类型 + */ @Override public CellDataTypeEnum supportExcelTypeKey() { return null; } + /** + * 将 Excel 单元格数据转换为 Long。 + * + * @param cellData 单元格数据 + * @param contentProperty 内容属性 + * @param globalConfiguration 全局配置 + * @return Long 值 + */ @Override public Long convertToJavaData(ReadCellData cellData, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) { return Convert.toLong(cellData.getStringValue()); } + /** + * 将 Long 转换为 Excel 单元格数据,超长数字按字符串写出。 + * + * @param object Java 值 + * @param contentProperty 内容属性 + * @param globalConfiguration 全局配置 + * @return Excel 写入数据 + */ @Override public WriteCellData convertToExcelData(Long object, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) { if (ObjectUtil.isNull(object)) { diff --git a/ruoyi-common/ruoyi-common-excel/src/main/java/org/dromara/common/excel/convert/ExcelDictConvert.java b/ruoyi-common/ruoyi-common-excel/src/main/java/org/dromara/common/excel/convert/ExcelDictConvert.java index 19d883429..68675a024 100644 --- a/ruoyi-common/ruoyi-common-excel/src/main/java/org/dromara/common/excel/convert/ExcelDictConvert.java +++ b/ruoyi-common/ruoyi-common-excel/src/main/java/org/dromara/common/excel/convert/ExcelDictConvert.java @@ -3,17 +3,17 @@ package org.dromara.common.excel.convert; import cn.hutool.core.annotation.AnnotationUtil; import cn.hutool.core.convert.Convert; import cn.hutool.core.util.ObjectUtil; +import lombok.extern.slf4j.Slf4j; import org.apache.fesod.sheet.converters.Converter; import org.apache.fesod.sheet.enums.CellDataTypeEnum; import org.apache.fesod.sheet.metadata.GlobalConfiguration; import org.apache.fesod.sheet.metadata.data.ReadCellData; import org.apache.fesod.sheet.metadata.data.WriteCellData; import org.apache.fesod.sheet.metadata.property.ExcelContentProperty; -import org.dromara.common.excel.annotation.ExcelDictFormat; import org.dromara.common.core.service.DictService; import org.dromara.common.core.utils.SpringUtils; import org.dromara.common.core.utils.StringUtils; -import lombok.extern.slf4j.Slf4j; +import org.dromara.common.excel.annotation.ExcelDictFormat; import java.lang.reflect.Field; import java.util.LinkedHashMap; @@ -30,16 +30,34 @@ public class ExcelDictConvert implements Converter { private DictService dictService; + /** + * 支持的 Java 类型。 + * + * @return Object 类型 + */ @Override public Class supportJavaTypeKey() { return Object.class; } + /** + * 支持的 Excel 单元格类型。 + * + * @return 默认支持全部类型 + */ @Override public CellDataTypeEnum supportExcelTypeKey() { return null; } + /** + * 将 Excel 字典显示值转换为 Java 字段值。 + * + * @param cellData 单元格数据 + * @param contentProperty 内容属性 + * @param globalConfiguration 全局配置 + * @return Java 字段值 + */ @Override public Object convertToJavaData(ReadCellData cellData, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) { ExcelDictFormat anno = getAnnotation(contentProperty.getField()); @@ -54,6 +72,14 @@ public class ExcelDictConvert implements Converter { return Convert.convert(contentProperty.getField().getType(), value); } + /** + * 将 Java 字段值转换为 Excel 字典显示值。 + * + * @param object Java 字段值 + * @param contentProperty 内容属性 + * @param globalConfiguration 全局配置 + * @return Excel 写入数据 + */ @Override public WriteCellData convertToExcelData(Object object, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) { if (ObjectUtil.isNull(object)) { @@ -71,10 +97,21 @@ public class ExcelDictConvert implements Converter { return new WriteCellData<>(label); } + /** + * 获取字段上的字典格式注解。 + * + * @param field 字段 + * @return 字典格式注解 + */ private ExcelDictFormat getAnnotation(Field field) { return AnnotationUtil.getAnnotation(field, ExcelDictFormat.class); } + /** + * 延迟获取字典服务。 + * + * @return 字典服务 + */ private DictService getDictService() { if (dictService == null) { dictService = SpringUtils.getBean(DictService.class); @@ -84,6 +121,11 @@ public class ExcelDictConvert implements Converter { /** * 解析导出值 0=男,1=女,2=未知。 + * + * @param propertyValue 字段值 + * @param converterExp 转换表达式 + * @param separator 分隔符 + * @return 导出显示值 */ private static String convertByExp(String propertyValue, String converterExp, String separator) { StringBuilder propertyString = new StringBuilder(); @@ -107,6 +149,11 @@ public class ExcelDictConvert implements Converter { /** * 反向解析值 男=0,女=1,未知=2。 + * + * @param propertyValue 显示值 + * @param converterExp 转换表达式 + * @param separator 分隔符 + * @return 字段值 */ private static String reverseByExp(String propertyValue, String converterExp, String separator) { StringBuilder propertyString = new StringBuilder(); @@ -128,6 +175,12 @@ public class ExcelDictConvert implements Converter { return StringUtils.stripEnd(propertyString.toString(), separator); } + /** + * 解析转换表达式。 + * + * @param converterExp 转换表达式 + * @return 字段值与显示值映射 + */ private static Map parseConverterExp(String converterExp) { Map result = new LinkedHashMap<>(); if (StringUtils.isBlank(converterExp)) { @@ -143,6 +196,13 @@ public class ExcelDictConvert implements Converter { return result; } + /** + * 按分隔符拆分多值字段。 + * + * @param propertyValue 字段值 + * @param separator 分隔符 + * @return 拆分后的字段值数组 + */ private static String[] splitPropertyValue(String propertyValue, String separator) { return propertyValue.split(Pattern.quote(separator)); } diff --git a/ruoyi-common/ruoyi-common-excel/src/main/java/org/dromara/common/excel/convert/ExcelEnumConvert.java b/ruoyi-common/ruoyi-common-excel/src/main/java/org/dromara/common/excel/convert/ExcelEnumConvert.java index 7c6c787cf..30cee03bd 100644 --- a/ruoyi-common/ruoyi-common-excel/src/main/java/org/dromara/common/excel/convert/ExcelEnumConvert.java +++ b/ruoyi-common/ruoyi-common-excel/src/main/java/org/dromara/common/excel/convert/ExcelEnumConvert.java @@ -26,19 +26,43 @@ import java.util.concurrent.ConcurrentHashMap; @Slf4j public class ExcelEnumConvert implements Converter { + /** + * 枚举字典缓存。 + */ private static final Map> ENUM_MAP_CACHE = new ConcurrentHashMap<>(); + /** + * 枚举反向字典缓存。 + */ private static final Map> ENUM_REVERSE_MAP_CACHE = new ConcurrentHashMap<>(); + /** + * 支持的 Java 类型。 + * + * @return Object 类型 + */ @Override public Class supportJavaTypeKey() { return Object.class; } + /** + * 支持的 Excel 单元格类型。 + * + * @return 默认支持全部类型 + */ @Override public CellDataTypeEnum supportExcelTypeKey() { return null; } + /** + * 将 Excel 枚举文本转换为 Java 字段值。 + * + * @param cellData 单元格数据 + * @param contentProperty 内容属性 + * @param globalConfiguration 全局配置 + * @return Java 字段值 + */ @Override public Object convertToJavaData(ReadCellData cellData, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) { cellData.checkEmpty(); @@ -76,6 +100,14 @@ public class ExcelEnumConvert implements Converter { return Convert.convert(contentProperty.getField().getType(), codeValue); } + /** + * 将 Java 枚举编码转换为 Excel 显示文本。 + * + * @param object Java 字段值 + * @param contentProperty 内容属性 + * @param globalConfiguration 全局配置 + * @return Excel 写入数据 + */ @Override public WriteCellData convertToExcelData(Object object, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) { if (ObjectUtil.isNull(object)) { @@ -86,6 +118,12 @@ public class ExcelEnumConvert implements Converter { return new WriteCellData<>(value); } + /** + * 准备枚举编码与显示文本映射。 + * + * @param contentProperty 内容属性 + * @return 枚举编码与显示文本映射 + */ private Map beforeConvert(ExcelContentProperty contentProperty) { return ENUM_MAP_CACHE.computeIfAbsent(contentProperty.getField(), field -> { ExcelEnumFormat anno = getAnnotation(field); @@ -103,6 +141,12 @@ public class ExcelEnumConvert implements Converter { }); } + /** + * 获取字段上的枚举格式注解。 + * + * @param field 字段 + * @return 枚举格式注解 + */ private ExcelEnumFormat getAnnotation(Field field) { return AnnotationUtil.getAnnotation(field, ExcelEnumFormat.class); } diff --git a/ruoyi-common/ruoyi-common-excel/src/main/java/org/dromara/common/excel/core/CellMergeHandler.java b/ruoyi-common/ruoyi-common-excel/src/main/java/org/dromara/common/excel/core/CellMergeHandler.java index a8dca7b2f..2d6490741 100644 --- a/ruoyi-common/ruoyi-common-excel/src/main/java/org/dromara/common/excel/core/CellMergeHandler.java +++ b/ruoyi-common/ruoyi-common-excel/src/main/java/org/dromara/common/excel/core/CellMergeHandler.java @@ -21,14 +21,32 @@ import java.util.*; */ public class CellMergeHandler { + /** + * 是否包含标题行。 + */ private final boolean hasTitle; + /** + * 当前行索引。 + */ private int rowIndex; + /** + * 创建单元格合并处理器。 + * + * @param hasTitle 是否存在标题行 + */ private CellMergeHandler(final boolean hasTitle) { this.hasTitle = hasTitle; // 行合并开始下标 this.rowIndex = hasTitle ? 1 : 0; } + + /** + * 创建单元格合并处理器。 + * + * @param hasTitle 是否存在标题行 + * @param rowIndex 起始行索引 + */ private CellMergeHandler(final boolean hasTitle, final int rowIndex) { this.hasTitle = hasTitle; this.rowIndex = hasTitle ? rowIndex : 0; @@ -143,6 +161,14 @@ public class CellMergeHandler { return mergeFields; } + /** + * 判断当前行是否满足依赖字段合并条件。 + * + * @param currentRow 当前行数据 + * @param preRow 上一行数据 + * @param cellMerge 合并配置 + * @return 是否允许合并 + */ private boolean isMerge(Object currentRow, Object preRow, CellMerge cellMerge) { final String[] mergeBy = cellMerge.mergeBy(); if (StrUtil.isAllNotBlank(mergeBy)) { @@ -159,10 +185,24 @@ public class CellMergeHandler { return true; } + /** + * 判断单元格值是否为空。 + * + * @param value 单元格值 + * @return 是否为空 + */ private boolean isBlankCell(Object value) { return value == null || StrUtil.isBlankIfStr(value); } + /** + * 追加有效的合并区域。 + * + * @param result 合并区域结果集 + * @param repeatCell 连续重复单元格信息 + * @param endIndex 结束行索引 + * @param colNum 列索引 + */ private void appendMergeResult(List result, RepeatCell repeatCell, int endIndex, int colNum) { if (repeatCell == null || endIndex <= repeatCell.current()) { return; @@ -174,6 +214,13 @@ public class CellMergeHandler { * 单元格合并 */ record RepeatCell(Object value, int current) { + /** + * 创建连续重复单元格信息。 + * + * @param value 单元格值 + * @param current 当前行索引 + * @return 连续重复单元格信息 + */ static RepeatCell of(Object value, int current) { return new RepeatCell(value, current); } @@ -183,10 +230,18 @@ public class CellMergeHandler { * 字段列索引和合并注解信息 */ record FieldColumnIndex(int colIndex, CellMerge cellMerge) { + /** + * 创建字段列索引和合并注解信息。 + * + * @param colIndex 列索引 + * @param cellMerge 合并注解 + * @return 字段列索引和合并注解信息 + */ static FieldColumnIndex of(int colIndex, CellMerge cellMerge) { return new FieldColumnIndex(colIndex, cellMerge); } } + /** * 创建一个单元格合并处理器实例 * diff --git a/ruoyi-common/ruoyi-common-excel/src/main/java/org/dromara/common/excel/core/CellMergeStrategy.java b/ruoyi-common/ruoyi-common-excel/src/main/java/org/dromara/common/excel/core/CellMergeStrategy.java index 4346bd08f..79f0e6576 100644 --- a/ruoyi-common/ruoyi-common-excel/src/main/java/org/dromara/common/excel/core/CellMergeStrategy.java +++ b/ruoyi-common/ruoyi-common-excel/src/main/java/org/dromara/common/excel/core/CellMergeStrategy.java @@ -21,20 +21,49 @@ import java.util.List; @Slf4j public class CellMergeStrategy extends AbstractMergeStrategy implements SheetWriteHandler { + /** + * 合并单元格区域集合。 + */ private final List cellList; + /** + * 创建单元格合并策略。 + * + * @param cellList 合并区域列表 + */ public CellMergeStrategy(List cellList) { this.cellList = cellList; } + /** + * 根据数据列表创建单元格合并策略。 + * + * @param list 数据列表 + * @param hasTitle 是否存在标题行 + */ public CellMergeStrategy(List list, boolean hasTitle) { this.cellList = CellMergeHandler.of(hasTitle).handle(list); } + /** + * 根据数据列表和起始行创建单元格合并策略。 + * + * @param list 数据列表 + * @param hasTitle 是否存在标题行 + * @param rowIndex 起始行索引 + */ public CellMergeStrategy(List list, boolean hasTitle, int rowIndex) { this.cellList = CellMergeHandler.of(hasTitle, rowIndex).handle(list); } + /** + * 写入单元格时清理合并区域非首行内容。 + * + * @param sheet 工作表 + * @param cell 当前单元格 + * @param head 表头 + * @param relativeRowIndex 相对行索引 + */ @Override protected void merge(Sheet sheet, Cell cell, Head head, Integer relativeRowIndex) { if (CollUtil.isEmpty(cellList)) { @@ -50,6 +79,12 @@ public class CellMergeStrategy extends AbstractMergeStrategy implements SheetWri } } + /** + * 工作表创建后写入合并区域。 + * + * @param writeWorkbookHolder 工作簿上下文 + * @param writeSheetHolder 工作表上下文 + */ @Override public void afterSheetCreate(final WriteWorkbookHolder writeWorkbookHolder, final WriteSheetHolder writeSheetHolder) { if (CollUtil.isEmpty(cellList)) { diff --git a/ruoyi-common/ruoyi-common-excel/src/main/java/org/dromara/common/excel/core/DefaultExcelListener.java b/ruoyi-common/ruoyi-common-excel/src/main/java/org/dromara/common/excel/core/DefaultExcelListener.java index dadf6b147..cace7a3ae 100644 --- a/ruoyi-common/ruoyi-common-excel/src/main/java/org/dromara/common/excel/core/DefaultExcelListener.java +++ b/ruoyi-common/ruoyi-common-excel/src/main/java/org/dromara/common/excel/core/DefaultExcelListener.java @@ -103,12 +103,24 @@ public class DefaultExcelListener extends AnalysisEventListener implements } } + /** + * 记录 Excel 表头信息。 + * + * @param headMap 表头映射 + * @param context 解析上下文 + */ @Override public void invokeHeadMap(Map headMap, AnalysisContext context) { this.headMap = headMap; log.debug("解析到一条表头数据: {}", JsonUtils.toJsonString(headMap)); } + /** + * 处理一行导入数据。 + * + * @param data 行数据 + * @param context 解析上下文 + */ @Override public void invoke(T data, AnalysisContext context) { if (isValidate) { @@ -117,11 +129,21 @@ public class DefaultExcelListener extends AnalysisEventListener implements excelResult.getList().add(data); } + /** + * 全部数据解析完成回调。 + * + * @param context 解析上下文 + */ @Override public void doAfterAllAnalysed(AnalysisContext context) { log.debug("所有数据解析完成!"); } + /** + * 获取 Excel 导入解析结果。 + * + * @return 导入解析结果 + */ @Override public ExcelResult getExcelResult() { return excelResult; diff --git a/ruoyi-common/ruoyi-common-excel/src/main/java/org/dromara/common/excel/core/DefaultExcelResult.java b/ruoyi-common/ruoyi-common-excel/src/main/java/org/dromara/common/excel/core/DefaultExcelResult.java index 3f887ebed..e69292b51 100644 --- a/ruoyi-common/ruoyi-common-excel/src/main/java/org/dromara/common/excel/core/DefaultExcelResult.java +++ b/ruoyi-common/ruoyi-common-excel/src/main/java/org/dromara/common/excel/core/DefaultExcelResult.java @@ -26,26 +26,50 @@ public class DefaultExcelResult implements ExcelResult { @Setter private List errorList; + /** + * 创建默认导入结果。 + */ public DefaultExcelResult() { this.list = new ArrayList<>(); this.errorList = new ArrayList<>(); } + /** + * 创建导入结果。 + * + * @param list 成功数据列表 + * @param errorList 错误信息列表 + */ public DefaultExcelResult(List list, List errorList) { this.list = list; this.errorList = errorList; } + /** + * 复制导入结果。 + * + * @param excelResult 原导入结果 + */ public DefaultExcelResult(ExcelResult excelResult) { this.list = excelResult.getList(); this.errorList = excelResult.getErrorList(); } + /** + * 获取成功数据列表。 + * + * @return 成功数据列表 + */ @Override public List getList() { return list; } + /** + * 获取错误信息列表。 + * + * @return 错误信息列表 + */ @Override public List getErrorList() { return errorList; diff --git a/ruoyi-common/ruoyi-common-excel/src/main/java/org/dromara/common/excel/core/ExcelDownHandler.java b/ruoyi-common/ruoyi-common-excel/src/main/java/org/dromara/common/excel/core/ExcelDownHandler.java index 801764c03..f8dd5f864 100644 --- a/ruoyi-common/ruoyi-common-excel/src/main/java/org/dromara/common/excel/core/ExcelDownHandler.java +++ b/ruoyi-common/ruoyi-common-excel/src/main/java/org/dromara/common/excel/core/ExcelDownHandler.java @@ -6,13 +6,13 @@ import cn.hutool.core.util.ArrayUtil; import cn.hutool.core.util.EnumUtil; import cn.hutool.core.util.ObjectUtil; import cn.hutool.core.util.StrUtil; +import lombok.extern.slf4j.Slf4j; import org.apache.fesod.sheet.metadata.FieldCache; import org.apache.fesod.sheet.metadata.FieldWrapper; import org.apache.fesod.sheet.util.ClassUtils; import org.apache.fesod.sheet.write.handler.SheetWriteHandler; import org.apache.fesod.sheet.write.metadata.holder.WriteSheetHolder; import org.apache.fesod.sheet.write.metadata.holder.WriteWorkbookHolder; -import lombok.extern.slf4j.Slf4j; import org.apache.poi.ss.usermodel.*; import org.apache.poi.ss.util.CellRangeAddressList; import org.apache.poi.ss.util.CellReference; @@ -41,7 +41,13 @@ import java.util.*; @Slf4j public class ExcelDownHandler implements SheetWriteHandler { + /** + * 首个数据行索引。 + */ private static final int FIRST_DATA_ROW_INDEX = 1; + /** + * 最后数据行索引。 + */ private static final int LAST_DATA_ROW_INDEX = 1000; /** * 单选数据Sheet名 @@ -411,6 +417,11 @@ public class ExcelDownHandler implements SheetWriteHandler { return CellReference.convertNumToColString(columnIndex); } + /** + * 延迟获取字典服务。 + * + * @return 字典服务 + */ private DictService getDictService() { if (dictService == null) { dictService = SpringUtils.getBean(DictService.class); diff --git a/ruoyi-common/ruoyi-common-excel/src/main/java/org/dromara/common/excel/core/ExcelListener.java b/ruoyi-common/ruoyi-common-excel/src/main/java/org/dromara/common/excel/core/ExcelListener.java index d7388f81b..fd839ed21 100644 --- a/ruoyi-common/ruoyi-common-excel/src/main/java/org/dromara/common/excel/core/ExcelListener.java +++ b/ruoyi-common/ruoyi-common-excel/src/main/java/org/dromara/common/excel/core/ExcelListener.java @@ -9,6 +9,11 @@ import org.apache.fesod.sheet.read.listener.ReadListener; */ public interface ExcelListener extends ReadListener { + /** + * 获取 Excel 导入结果。 + * + * @return Excel 导入结果 + */ ExcelResult getExcelResult(); } diff --git a/ruoyi-common/ruoyi-common-excel/src/main/java/org/dromara/common/excel/handler/DataWriteHandler.java b/ruoyi-common/ruoyi-common-excel/src/main/java/org/dromara/common/excel/handler/DataWriteHandler.java index baca75fb0..8ae32ac07 100644 --- a/ruoyi-common/ruoyi-common-excel/src/main/java/org/dromara/common/excel/handler/DataWriteHandler.java +++ b/ruoyi-common/ruoyi-common-excel/src/main/java/org/dromara/common/excel/handler/DataWriteHandler.java @@ -50,6 +50,11 @@ public class DataWriteHandler implements SheetWriteHandler, CellWriteHandler { headColumnMap = getRequiredMap(clazz); } + /** + * 在单元格写入后设置表头文本格式、必填样式与批注。 + * + * @param context 单元格写入上下文 + */ @Override public void afterCellDispose(CellWriteHandlerContext context) { if (CollUtil.isEmpty(notationMap) && CollUtil.isEmpty(headColumnMap)) { diff --git a/ruoyi-common/ruoyi-common-excel/src/main/java/org/dromara/common/excel/utils/ExcelBuilder.java b/ruoyi-common/ruoyi-common-excel/src/main/java/org/dromara/common/excel/utils/ExcelBuilder.java index 4ab5699ee..42743e47e 100644 --- a/ruoyi-common/ruoyi-common-excel/src/main/java/org/dromara/common/excel/utils/ExcelBuilder.java +++ b/ruoyi-common/ruoyi-common-excel/src/main/java/org/dromara/common/excel/utils/ExcelBuilder.java @@ -55,52 +55,127 @@ import java.util.zip.ZipOutputStream; */ public final class ExcelBuilder { + /** + * 默认工作表名称。 + */ private static final String DEFAULT_SHEET_NAME = "sheet1"; + /** + * 默认 ZIP 分页大小。 + */ private static final int DEFAULT_ZIP_PAGE_SIZE = 999; + /** + * 数据内容。 + */ private final List data; + /** + * 表头类型。 + */ private final Class headType; + /** + * 工作表名称。 + */ private String sheetName = DEFAULT_SHEET_NAME; + /** + * 工作表编号。 + */ private Integer sheetNo; + /** + * 是否合并单元格。 + */ private boolean merge; + /** + * 下拉选项集合。 + */ private List options; + /** + * 是否 ZIP 打包。 + */ private boolean zip; + /** + * 分页大小。 + */ private int pageSize = DEFAULT_ZIP_PAGE_SIZE; + /** + * 认证密码。 + */ private String password; + /** + * 是否写入表头。 + */ private Boolean needHead; + /** + * 是否自动合并表头。 + */ private Boolean automaticMergeHead; + /** + * 包含字段集合。 + */ private Collection includeFields; + /** + * 排除字段集合。 + */ private Collection excludeFields; + /** + * 包含列索引集合。 + */ private Collection includeIndexes; + /** + * 排除列索引集合。 + */ private Collection excludeIndexes; + /** + * 是否按包含列排序。 + */ private Boolean orderByIncludeColumn; + /** + * 列宽。 + */ private Integer columnWidth; + /** + * 表头行高。 + */ private Short headRowHeight; + /** + * 内容行高。 + */ private Short contentRowHeight; + /** + * 写入处理器集合。 + */ private List writeHandlers; + /** + * 转换器集合。 + */ private List> converters; + /** + * 创建 Excel 导出构造器。 + * + * @param data 导出数据 + * @param headType 表头类型 + */ private ExcelBuilder(List data, Class headType) { this.data = data; this.headType = headType; @@ -373,6 +448,11 @@ public final class ExcelBuilder { } } + /** + * 写入单个工作表。 + * + * @param outputStream 输出流 + */ private void writeSheet(OutputStream outputStream) { ExcelWriterSheetBuilder builder = createSheetBuilder(createWriterBuilder(outputStream)); if (merge) { @@ -382,10 +462,22 @@ public final class ExcelBuilder { builder.doWrite(data); } + /** + * 创建 Excel 写入器。 + * + * @param outputStream 输出流 + * @return Excel 写入器 + */ private ExcelWriter createWriter(OutputStream outputStream) { return createWriterBuilder(outputStream).build(); } + /** + * 创建并配置 Excel 写入构造器。 + * + * @param outputStream 输出流 + * @return Excel 写入构造器 + */ private ExcelWriterBuilder createWriterBuilder(OutputStream outputStream) { ExcelWriterBuilder builder = FesodSheet.write(outputStream, headType) .autoCloseStream(false) @@ -437,6 +529,12 @@ public final class ExcelBuilder { return builder; } + /** + * 创建工作表写入构造器。 + * + * @param builder Excel 写入构造器 + * @return 工作表写入构造器 + */ private ExcelWriterSheetBuilder createSheetBuilder(ExcelWriterBuilder builder) { if (sheetNo != null) { return builder.sheet(sheetNo, sheetName); @@ -444,6 +542,11 @@ public final class ExcelBuilder { return builder.sheet(sheetName); } + /** + * 将大数据导出拆分为多个 Excel 文件并压缩写入响应。 + * + * @param response HTTP 响应 + */ private void exportZipToResponse(HttpServletResponse response) { if (pageSize <= 0) { throw new IllegalArgumentException("pageSize 必须大于 0"); @@ -474,6 +577,13 @@ public final class ExcelBuilder { } } + /** + * 构建 ZIP 内单个 Excel 文件内容。 + * + * @param pageData 当前分页数据 + * @param exportSheetName 导出工作表名称 + * @return Excel 文件字节 + */ private byte[] buildZipEntry(List pageData, String exportSheetName) { try (ByteArrayOutputStream bos = new ByteArrayOutputStream()) { ExcelBuilder builder = ExcelBuilder.of(pageData, headType) @@ -486,6 +596,11 @@ public final class ExcelBuilder { } } + /** + * 复制导出配置到分页导出构造器。 + * + * @param builder 目标构造器 + */ private void copyOptionsTo(ExcelBuilder builder) { builder.merge = merge; builder.options = options; @@ -506,12 +621,22 @@ public final class ExcelBuilder { /** * 重置响应体。 + * + * @param filename 文件名 + * @param response HTTP 响应 + * @throws UnsupportedEncodingException 文件名编码异常 */ private static void resetResponse(String filename, HttpServletResponse response) throws UnsupportedEncodingException { FileUtils.setAttachmentResponseHeader(response, encodingFilename(filename)); response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=UTF-8"); } + /** + * 生成带随机前缀的导出文件名。 + * + * @param filename 原始文件名 + * @return 编码前的导出文件名 + */ private static String encodingFilename(String filename) { return IdUtil.fastSimpleUUID() + "_" + filename + ".xlsx"; } @@ -521,34 +646,82 @@ public final class ExcelBuilder { */ public static final class ReadBuilder { + /** + * 导入输入流。 + */ private final InputStream inputStream; + /** + * 表头类型。 + */ private final Class headType; + /** + * 是否执行数据校验。 + */ private boolean validate = true; + /** + * 是否快速失败。 + */ private boolean failFast = true; + /** + * Excel 监听器。 + */ private ExcelListener listener; + /** + * 工作表编号。 + */ private Integer sheetNo; + /** + * 工作表名称。 + */ private String sheetName; + /** + * 表头行数。 + */ private Integer headRowNumber; + /** + * 是否忽略空行。 + */ private Boolean ignoreEmptyRow; + /** + * 认证密码。 + */ private String password; + /** + * 是否自动裁剪空白。 + */ private Boolean autoTrim; + /** + * 是否自动清理不可见字符。 + */ private Boolean autoStrip; + /** + * 读取行数。 + */ private Integer numRows; + /** + * 转换器集合。 + */ private List> converters; + /** + * 创建 Excel 导入读取构造器。 + * + * @param inputStream 输入流 + * @param headType 表头类型 + */ private ReadBuilder(InputStream inputStream, Class headType) { this.inputStream = inputStream; this.headType = headType; @@ -700,6 +873,12 @@ public final class ExcelBuilder { return createReaderBuilder(null).doReadAllSync(); } + /** + * 创建并配置 Excel 读取构造器。 + * + * @param readListener 读取监听器 + * @return Excel 读取构造器 + */ private ExcelReaderBuilder createReaderBuilder(ExcelListener readListener) { ExcelReaderBuilder builder = FesodSheet.read(inputStream) .head(headType) @@ -731,6 +910,12 @@ public final class ExcelBuilder { return builder; } + /** + * 创建工作表读取构造器。 + * + * @param builder Excel 读取构造器 + * @return 工作表读取构造器 + */ private ExcelReaderSheetBuilder createSheetBuilder(ExcelReaderBuilder builder) { ExcelReaderSheetBuilder sheetBuilder; if (sheetNo != null && StringUtils.isNotBlank(sheetName)) { @@ -754,14 +939,31 @@ public final class ExcelBuilder { */ public static final class TemplateBuilder { + /** + * 模板路径。 + */ private final String templatePath; + /** + * 文件名称。 + */ private String filename = DEFAULT_SHEET_NAME; + /** + * 模板模式。 + */ private TemplateMode mode; + /** + * 数据内容。 + */ private Object data; + /** + * 创建 Excel 模板导出构造器。 + * + * @param templatePath 模板路径 + */ private TemplateBuilder(String templatePath) { this.templatePath = templatePath; } @@ -838,6 +1040,11 @@ public final class ExcelBuilder { } } + /** + * 按模板模式填充数据。 + * + * @param excelWriter Excel 写入器 + */ @SuppressWarnings("unchecked") private void fill(ExcelWriter excelWriter) { if (mode == TemplateMode.LIST) { @@ -874,6 +1081,9 @@ public final class ExcelBuilder { } } + /** + * 校验模板导出数据。 + */ private void validateData() { if (mode == null || data == null) { throw new IllegalArgumentException("数据为空"); diff --git a/ruoyi-common/ruoyi-common-json/src/main/java/org/dromara/common/json/handler/BigNumberSerializer.java b/ruoyi-common/ruoyi-common-json/src/main/java/org/dromara/common/json/handler/BigNumberSerializer.java index 1e7ef2629..7bf928033 100644 --- a/ruoyi-common/ruoyi-common-json/src/main/java/org/dromara/common/json/handler/BigNumberSerializer.java +++ b/ruoyi-common/ruoyi-common-json/src/main/java/org/dromara/common/json/handler/BigNumberSerializer.java @@ -17,6 +17,9 @@ public class BigNumberSerializer extends NumberSerializer { * 根据 JS Number.MAX_SAFE_INTEGER 与 Number.MIN_SAFE_INTEGER 得来 */ private static final long MAX_SAFE_INTEGER = 9007199254740991L; + /** + * JavaScript 最小安全整数。 + */ private static final long MIN_SAFE_INTEGER = -9007199254740991L; /** diff --git a/ruoyi-common/ruoyi-common-mail/src/main/java/org/dromara/common/mail/core/MailBuilder.java b/ruoyi-common/ruoyi-common-mail/src/main/java/org/dromara/common/mail/core/MailBuilder.java index 2cd98de7b..5352d44c0 100644 --- a/ruoyi-common/ruoyi-common-mail/src/main/java/org/dromara/common/mail/core/MailBuilder.java +++ b/ruoyi-common/ruoyi-common-mail/src/main/java/org/dromara/common/mail/core/MailBuilder.java @@ -19,32 +19,74 @@ import java.util.*; */ public final class MailBuilder { + /** + * 邮件账户配置。 + */ private MailAccount mailAccount; + /** + * 是否使用全局邮件会话。 + */ private boolean useGlobalSession = true; + /** + * 收件人列表。 + */ private final List tos = new ArrayList<>(); + /** + * 抄送人列表。 + */ private final List ccs = new ArrayList<>(); + /** + * 密送人列表。 + */ private final List bccs = new ArrayList<>(); + /** + * 内嵌图片集合。 + */ private final Map images = new LinkedHashMap<>(); + /** + * 附件文件集合。 + */ private File[] files = new File[0]; + /** + * 发件人。 + */ private String from; + /** + * 登录用户。 + */ private String user; + /** + * 登录密码。 + */ private String pass; + /** + * 邮件主题。 + */ private String subject; + /** + * 邮件内容。 + */ private String content; + /** + * 是否 HTML 内容。 + */ private boolean html; + /** + * 私有构造器,统一通过静态工厂创建。 + */ private MailBuilder() { } @@ -220,7 +262,7 @@ public final class MailBuilder { * 设置正文。 * * @param content 正文 - * @param html 是否 HTML + * @param html 是否 HTML * @return 当前构建器 */ public MailBuilder content(String content, boolean html) { @@ -232,7 +274,7 @@ public final class MailBuilder { /** * 添加内联图片。 * - * @param cid 图片 cid + * @param cid 图片 cid * @param inputStream 图片输入流 * @return 当前构建器 */ @@ -297,6 +339,9 @@ public final class MailBuilder { } } + /** + * 校验邮件发送必填项。 + */ private void validate() { if (CollUtil.isEmpty(tos)) { throw new IllegalArgumentException("邮件收件人不能为空"); @@ -309,6 +354,11 @@ public final class MailBuilder { } } + /** + * 解析实际使用的邮件账户。 + * + * @return 邮件账户 + */ private MailAccount resolveMailAccount() { MailAccount account = mailAccount; if (account == null) { @@ -324,6 +374,12 @@ public final class MailBuilder { return copy; } + /** + * 拆分逗号或分号分隔的邮箱地址。 + * + * @param addresses 邮箱地址字符串 + * @return 邮箱地址列表 + */ private List splitAddress(String addresses) { if (StrUtil.isBlank(addresses)) { return Collections.emptyList(); @@ -331,6 +387,12 @@ public final class MailBuilder { return normalizeAddresses(StrUtil.splitTrim(addresses.replace(';', ','), ',')); } + /** + * 过滤并标准化邮箱地址集合。 + * + * @param addresses 邮箱地址集合 + * @return 标准化后的邮箱地址列表 + */ private List normalizeAddresses(Collection addresses) { if (CollUtil.isEmpty(addresses)) { return Collections.emptyList(); diff --git a/ruoyi-common/ruoyi-common-mcp/src/main/java/org/dromara/common/mcp/core/McpClientTemplate.java b/ruoyi-common/ruoyi-common-mcp/src/main/java/org/dromara/common/mcp/core/McpClientTemplate.java index 962665cdd..483411a88 100644 --- a/ruoyi-common/ruoyi-common-mcp/src/main/java/org/dromara/common/mcp/core/McpClientTemplate.java +++ b/ruoyi-common/ruoyi-common-mcp/src/main/java/org/dromara/common/mcp/core/McpClientTemplate.java @@ -41,7 +41,7 @@ public class McpClientTemplate { /** * 调用所有 MCP Server 上的同名工具。 * - * @param toolName 工具名称 + * @param toolName 工具名称 * @param arguments 工具参数 * @return 各 Server 的工具调用结果 */ @@ -58,8 +58,8 @@ public class McpClientTemplate { * 调用指定 MCP Server 上的工具。 * * @param serverName Server 名称 - * @param toolName 工具名称 - * @param arguments 工具参数 + * @param toolName 工具名称 + * @param arguments 工具参数 * @return 工具调用结果 */ public Optional callTool(String serverName, String toolName, Map arguments) { @@ -86,7 +86,7 @@ public class McpClientTemplate { * 读取指定 MCP Server 上的资源。 * * @param serverName Server 名称 - * @param uri 资源地址 + * @param uri 资源地址 * @return 资源内容 */ public Optional readResource(String serverName, String uri) { @@ -115,6 +115,12 @@ public class McpClientTemplate { return mcpSyncClients; } + /** + * 解析 MCP Server 名称。 + * + * @param client MCP 同步客户端 + * @return Server 名称 + */ private String getServerName(McpSyncClient client) { McpSchema.Implementation serverInfo = client.getServerInfo(); if (serverInfo == null || serverInfo.name() == null) { diff --git a/ruoyi-common/ruoyi-common-mqtt/src/main/java/org/dromara/common/mqtt/listener/MqttClientConnectListener.java b/ruoyi-common/ruoyi-common-mqtt/src/main/java/org/dromara/common/mqtt/listener/MqttClientConnectListener.java index fd53eeabd..35afe485e 100644 --- a/ruoyi-common/ruoyi-common-mqtt/src/main/java/org/dromara/common/mqtt/listener/MqttClientConnectListener.java +++ b/ruoyi-common/ruoyi-common-mqtt/src/main/java/org/dromara/common/mqtt/listener/MqttClientConnectListener.java @@ -12,19 +12,38 @@ import org.tio.core.ChannelContext; */ @Slf4j public class MqttClientConnectListener implements IMqttClientConnectListener { - // + private final MqttClientCreator mqttClientCreator; + /** + * 创建 MQTT 客户端连接监听器。 + * + * @param mqttClientCreator MQTT 客户端创建器 + */ public MqttClientConnectListener(MqttClientCreator mqttClientCreator) { this.mqttClientCreator = mqttClientCreator; } + /** + * 客户端连接成功回调。 + * + * @param context 通道上下文 + * @param isReconnect 是否重连 + */ @Override public void onConnected(ChannelContext context, boolean isReconnect) { // 创建连接 log.info("MqttConnectedEvent:{}", context); } + /** + * 客户端断开连接回调。 + * + * @param context 通道上下文 + * @param throwable 断开异常 + * @param remark 断开说明 + * @param isRemove 是否移除连接 + */ @Override public void onDisconnect(ChannelContext context, Throwable throwable, String remark, boolean isRemove) { // 离线时更新重连 diff --git a/ruoyi-common/ruoyi-common-mqtt/src/main/java/org/dromara/common/mqtt/listener/MqttClientGlobalMessageListener.java b/ruoyi-common/ruoyi-common-mqtt/src/main/java/org/dromara/common/mqtt/listener/MqttClientGlobalMessageListener.java index a3117eb74..f360725a3 100644 --- a/ruoyi-common/ruoyi-common-mqtt/src/main/java/org/dromara/common/mqtt/listener/MqttClientGlobalMessageListener.java +++ b/ruoyi-common/ruoyi-common-mqtt/src/main/java/org/dromara/common/mqtt/listener/MqttClientGlobalMessageListener.java @@ -15,6 +15,14 @@ import java.nio.charset.StandardCharsets; @Slf4j public class MqttClientGlobalMessageListener implements IMqttClientGlobalMessageListener { + /** + * 接收并记录全局 MQTT 消息。 + * + * @param context 通道上下文 + * @param topic 主题 + * @param message MQTT 消息对象 + * @param payload 消息载荷 + */ @Override public void onMessage(ChannelContext context, String topic, MqttPublishMessage message, byte[] payload) { log.info("MqttGlobalMessageEvent => topic: {}, msg: {}", topic, new String(payload, StandardCharsets.UTF_8)); diff --git a/ruoyi-common/ruoyi-common-oss/src/main/java/org/dromara/common/oss/client/AbstractOssClientImpl.java b/ruoyi-common/ruoyi-common-oss/src/main/java/org/dromara/common/oss/client/AbstractOssClientImpl.java index 76c8858b7..da94ca63e 100644 --- a/ruoyi-common/ruoyi-common-oss/src/main/java/org/dromara/common/oss/client/AbstractOssClientImpl.java +++ b/ruoyi-common/ruoyi-common-oss/src/main/java/org/dromara/common/oss/client/AbstractOssClientImpl.java @@ -17,7 +17,10 @@ import software.amazon.awssdk.core.async.AsyncRequestBody; import software.amazon.awssdk.core.async.AsyncResponseTransformer; import software.amazon.awssdk.core.async.ResponsePublisher; import software.amazon.awssdk.services.s3.S3AsyncClient; -import software.amazon.awssdk.services.s3.model.*; +import software.amazon.awssdk.services.s3.model.GetObjectRequest; +import software.amazon.awssdk.services.s3.model.GetObjectResponse; +import software.amazon.awssdk.services.s3.model.PutObjectRequest; +import software.amazon.awssdk.services.s3.model.PutObjectResponse; import software.amazon.awssdk.services.s3.presigner.S3Presigner; import software.amazon.awssdk.transfer.s3.S3TransferManager; import software.amazon.awssdk.transfer.s3.model.CompletedUpload; @@ -38,8 +41,8 @@ import java.util.Map; import java.util.Objects; import java.util.Optional; import java.util.concurrent.CompletionException; -import java.util.concurrent.ExecutorService; import java.util.concurrent.ExecutionException; +import java.util.concurrent.ExecutorService; import java.util.concurrent.atomic.AtomicBoolean; import java.util.function.BiFunction; import java.util.function.Consumer; @@ -90,7 +93,7 @@ public abstract class AbstractOssClientImpl implements OssClient { * 构造 S3 存储客户端基础实现。 * * @param clientId 客户端 ID - * @param config S3 存储客户端配置 + * @param config S3 存储客户端配置 */ public AbstractOssClientImpl(String clientId, OssClientConfig config) { Assert.notNull(config, () -> S3StorageException.form("S3StorageClientConfig must not be null")); @@ -100,22 +103,40 @@ public abstract class AbstractOssClientImpl implements OssClient { this.initialize(); } + /** + * 获取客户端 ID。 + * + * @return 客户端 ID + */ @Override public String clientId() { return this.clientId; } + /** + * 获取客户端配置副本。 + * + * @return 客户端配置副本 + */ @Override public OssClientConfig config() { // 仅返回copy副本,防篡改 return this.config.copy(); } + /** + * 判断客户端是否已经初始化。 + * + * @return 是否已初始化 + */ @Override public boolean isInitialized() { return initialized.get(); } + /** + * 初始化底层 S3 客户端资源。 + */ @Override public void initialize() { // 如果已经是初始化状态,则直接返回 @@ -131,24 +152,52 @@ public abstract class AbstractOssClientImpl implements OssClient { } } + /** + * 执行客户端具体初始化逻辑。 + */ abstract void doInitialize(); + /** + * 使用回调校验当前客户端配置。 + * + * @param verifyConfigAction 配置校验回调 + * @return 是否校验通过 + */ @Override public boolean verifyConfig(Function verifyConfigAction) { OssClientConfig config = config(); return Boolean.TRUE.equals(verifyConfigAction.apply(config)); } + /** + * 校验当前客户端配置是否与指定配置一致。 + * + * @param verifyConfig 待校验配置 + * @return 是否一致 + */ @Override public boolean verifyConfig(OssClientConfig verifyConfig) { return verifyConfig((config) -> Objects.equals(config, verifyConfig)); } + /** + * 根据文件名构建对象键。 + * + * @param fileName 原始文件名 + * @return 对象键 + */ @Override public String buildPathKey(String fileName) { return buildPathKey(null, fileName); } + /** + * 根据业务前缀和文件名构建对象键。 + * + * @param businessPrefix 业务前缀 + * @param fileName 原始文件名 + * @return 对象键 + */ @Override public String buildPathKey(String businessPrefix, String fileName) { String defaultPrefix = config.prefix() @@ -161,6 +210,16 @@ public abstract class AbstractOssClientImpl implements OssClient { return path + suffix; } + /** + * 执行自定义上传请求。 + * + * @param body 上传请求体 + * @param putObjectRequestBuilderConsumer PutObject 请求构建回调 + * @param transferListeners 传输监听器集合 + * @param handleAsyncAction 上传完成处理函数 + * @param 返回值类型 + * @return 上传处理结果 + */ @Override public T doCustomUpload(AsyncRequestBody body, Consumer putObjectRequestBuilderConsumer, Collection transferListeners, BiFunction handleAsyncAction) { try { @@ -177,11 +236,28 @@ public abstract class AbstractOssClientImpl implements OssClient { } } + /** + * 执行自定义上传请求。 + * + * @param body 上传请求体 + * @param putObjectRequestBuilderConsumer PutObject 请求构建回调 + * @param handleAsyncAction 上传完成处理函数 + * @param 返回值类型 + * @return 上传处理结果 + */ @Override public T doCustomUpload(AsyncRequestBody body, Consumer putObjectRequestBuilderConsumer, BiFunction handleAsyncAction) { return doCustomUpload(body, putObjectRequestBuilderConsumer, null, handleAsyncAction); } + /** + * 执行自定义上传请求并返回统一异步结果。 + * + * @param body 上传请求体 + * @param putObjectRequestBuilderConsumer PutObject 请求构建回调 + * @param transferListeners 传输监听器集合 + * @return 上传结果 + */ @Override public HandleAsyncResult doCustomUpload(AsyncRequestBody body, Consumer putObjectRequestBuilderConsumer, Collection transferListeners) { return doCustomUpload(body, putObjectRequestBuilderConsumer, transferListeners, (completedUpload, throwable) -> { @@ -192,6 +268,13 @@ public abstract class AbstractOssClientImpl implements OssClient { }); } + /** + * 执行自定义上传请求并返回统一异步结果。 + * + * @param body 上传请求体 + * @param putObjectRequestBuilderConsumer PutObject 请求构建回调 + * @return 上传结果 + */ @Override public HandleAsyncResult doCustomUpload(AsyncRequestBody body, Consumer putObjectRequestBuilderConsumer) { return doCustomUpload(body, putObjectRequestBuilderConsumer, null, (completedUpload, throwable) -> { @@ -202,28 +285,71 @@ public abstract class AbstractOssClientImpl implements OssClient { }); } + /** + * 上传本地路径文件到指定存储桶。 + * + * @param bucket 存储桶名称 + * @param key 对象键 + * @param path 文件路径 + * @param options 上传选项 + * @return 上传结果 + */ @Override public PutObjectResult bucketUpload(String bucket, String key, Path path, Options options) { AsyncRequestBody body = AsyncRequestBody.fromFile(path); return bucketUpload(bucket, key, body, options); } + /** + * 上传本地路径文件到指定存储桶。 + * + * @param bucket 存储桶名称 + * @param key 对象键 + * @param path 文件路径 + * @return 上传结果 + */ @Override public PutObjectResult bucketUpload(String bucket, String key, Path path) { return bucketUpload(bucket, key, path, Options.builder()); } + /** + * 上传文件到指定存储桶。 + * + * @param bucket 存储桶名称 + * @param key 对象键 + * @param file 文件对象 + * @param options 上传选项 + * @return 上传结果 + */ @Override public PutObjectResult bucketUpload(String bucket, String key, File file, Options options) { AsyncRequestBody body = AsyncRequestBody.fromFile(file); return bucketUpload(bucket, key, body, options); } + /** + * 上传文件到指定存储桶。 + * + * @param bucket 存储桶名称 + * @param key 对象键 + * @param file 文件对象 + * @return 上传结果 + */ @Override public PutObjectResult bucketUpload(String bucket, String key, File file) { return bucketUpload(bucket, key, file, Options.builder()); } + /** + * 上传随机访问文件到指定存储桶。 + * + * @param bucket 存储桶名称 + * @param key 对象键 + * @param file 随机访问文件 + * @param options 上传选项 + * @return 上传结果 + */ @Override public PutObjectResult bucketUpload(String bucket, String key, RandomAccessFile file, Options options) { try { @@ -235,11 +361,29 @@ public abstract class AbstractOssClientImpl implements OssClient { } } + /** + * 上传随机访问文件到指定存储桶。 + * + * @param bucket 存储桶名称 + * @param key 对象键 + * @param file 随机访问文件 + * @return 上传结果 + */ @Override public PutObjectResult bucketUpload(String bucket, String key, RandomAccessFile file) { return bucketUpload(bucket, key, file, Options.builder()); } + /** + * 上传可读通道数据到指定存储桶。 + * + * @param bucket 存储桶名称 + * @param key 对象键 + * @param channel 可读通道 + * @param contentLength 内容长度 + * @param options 上传选项 + * @return 上传结果 + */ @Override public PutObjectResult bucketUpload(String bucket, String key, ReadableByteChannel channel, long contentLength, Options options) { // 让调用者自行处理通道的关闭 @@ -256,11 +400,30 @@ public abstract class AbstractOssClientImpl implements OssClient { } } + /** + * 上传可读通道数据到指定存储桶。 + * + * @param bucket 存储桶名称 + * @param key 对象键 + * @param channel 可读通道 + * @param contentLength 内容长度 + * @return 上传结果 + */ @Override public PutObjectResult bucketUpload(String bucket, String key, ReadableByteChannel channel, long contentLength) { return bucketUpload(bucket, key, channel, contentLength, Options.builder()); } + /** + * 上传输入流数据到指定存储桶。 + * + * @param bucket 存储桶名称 + * @param key 对象键 + * @param in 输入流 + * @param contentLength 内容长度 + * @param options 上传选项 + * @return 上传结果 + */ @Override public PutObjectResult bucketUpload(String bucket, String key, InputStream in, long contentLength, Options options) { options.setLength(contentLength); @@ -268,11 +431,29 @@ public abstract class AbstractOssClientImpl implements OssClient { return bucketUpload(bucket, key, body, options); } + /** + * 上传输入流数据到指定存储桶。 + * + * @param bucket 存储桶名称 + * @param key 对象键 + * @param in 输入流 + * @param contentLength 内容长度 + * @return 上传结果 + */ @Override public PutObjectResult bucketUpload(String bucket, String key, InputStream in, long contentLength) { return bucketUpload(bucket, key, in, contentLength, Options.builder()); } + /** + * 上传字节数组到指定存储桶。 + * + * @param bucket 存储桶名称 + * @param key 对象键 + * @param data 字节数组 + * @param options 上传选项 + * @return 上传结果 + */ @Override public PutObjectResult bucketUpload(String bucket, String key, byte[] data, Options options) { try (ByteArrayInputStream in = new ByteArrayInputStream(data)) { @@ -282,11 +463,28 @@ public abstract class AbstractOssClientImpl implements OssClient { } } + /** + * 上传字节数组到指定存储桶。 + * + * @param bucket 存储桶名称 + * @param key 对象键 + * @param data 字节数组 + * @return 上传结果 + */ @Override public PutObjectResult bucketUpload(String bucket, String key, byte[] data) { return bucketUpload(bucket, key, data, Options.builder()); } + /** + * 执行指定存储桶的底层上传。 + * + * @param bucket 存储桶名称 + * @param key 对象键 + * @param body 上传请求体 + * @param options 上传选项 + * @return 上传结果 + */ @NullMarked private PutObjectResult bucketUpload(String bucket, String key, AsyncRequestBody body, Options options) { // 优先使用body中的内容大小,如果不存在,再获取可选项中的 @@ -321,6 +519,15 @@ public abstract class AbstractOssClientImpl implements OssClient { return PutObjectResult.form("%s/%s".formatted(bucketUrl, key), key, response.eTag(), size); } + /** + * 执行自定义下载请求。 + * + * @param getObjectRequestBuilderConsumer GetObject 请求构建回调 + * @param responseTransformer 下载响应转换器 + * @param transferListeners 传输监听器集合 + * @param 下载结果类型 + * @return 下载结果 + */ @Override public T doCustomDownload(Consumer getObjectRequestBuilderConsumer, AsyncResponseTransformer responseTransformer, Collection transferListeners) { try { @@ -338,6 +545,14 @@ public abstract class AbstractOssClientImpl implements OssClient { } } + /** + * 将指定存储桶对象下载到订阅器。 + * + * @param bucket 存储桶名称 + * @param key 对象键 + * @param downloadSubscriber 下载订阅器 + * @return 下载结果 + */ @Override public GetObjectResult bucketDownload(String bucket, String key, OutputStreamDownloadSubscriber downloadSubscriber) { try { @@ -350,6 +565,15 @@ public abstract class AbstractOssClientImpl implements OssClient { } } + /** + * 将指定存储桶对象下载到转换器。 + * + * @param bucket 存储桶名称 + * @param key 对象键 + * @param downloadTransformer 下载转换器 + * @param 下载结果类型 + * @return 下载结果 + */ @Override public T bucketDownload(String bucket, String key, BiFunction downloadTransformer) { try (ResponseInputStream responseInputStream = doCustomDownload(builder -> builder.bucket(bucket).key(key), AsyncResponseTransformer.toBlockingInputStream(), null)) { @@ -361,6 +585,14 @@ public abstract class AbstractOssClientImpl implements OssClient { } } + /** + * 将指定存储桶对象下载到本地路径。 + * + * @param bucket 存储桶名称 + * @param key 对象键 + * @param path 本地路径 + * @return 下载结果 + */ @Override public GetObjectResult bucketDownload(String bucket, String key, Path path) { try (OutputStream out = Files.newOutputStream(path)) { @@ -370,6 +602,14 @@ public abstract class AbstractOssClientImpl implements OssClient { } } + /** + * 将指定存储桶对象下载到文件。 + * + * @param bucket 存储桶名称 + * @param key 对象键 + * @param file 本地文件 + * @return 下载结果 + */ @Override public GetObjectResult bucketDownload(String bucket, String key, File file) { try (FileOutputStream out = new FileOutputStream(file)) { @@ -379,21 +619,52 @@ public abstract class AbstractOssClientImpl implements OssClient { } } + /** + * 将指定存储桶对象下载到随机访问文件。 + * + * @param bucket 存储桶名称 + * @param key 对象键 + * @param file 随机访问文件 + * @return 下载结果 + */ @Override public GetObjectResult bucketDownload(String bucket, String key, RandomAccessFile file) { return bucketDownload(bucket, key, file.getChannel()); } + /** + * 将指定存储桶对象下载到可写通道。 + * + * @param bucket 存储桶名称 + * @param key 对象键 + * @param channel 可写通道 + * @return 下载结果 + */ @Override public GetObjectResult bucketDownload(String bucket, String key, WritableByteChannel channel) { return bucketDownload(bucket, key, OutputStreamDownloadSubscriber.create(channel)); } + /** + * 将指定存储桶对象下载到输出流。 + * + * @param bucket 存储桶名称 + * @param key 对象键 + * @param out 输出流 + * @return 下载结果 + */ @Override public GetObjectResult bucketDownload(String bucket, String key, OutputStream out) { return bucketDownload(bucket, key, OutputStreamDownloadSubscriber.create(out)); } + /** + * 根据 S3 响应构建下载结果。 + * + * @param key 对象键 + * @param response S3 下载响应 + * @return 下载结果 + */ private GetObjectResult buildGetObjectResult(String key, GetObjectResponse response) { return GetObjectResult.form( key, @@ -409,6 +680,13 @@ public abstract class AbstractOssClientImpl implements OssClient { ); } + /** + * 删除指定存储桶中的对象。 + * + * @param bucket 存储桶名称 + * @param key 对象键 + * @return 是否删除成功 + */ @Override public boolean bucketDelete(String bucket, String key) { try { @@ -419,6 +697,14 @@ public abstract class AbstractOssClientImpl implements OssClient { } } + /** + * 生成指定存储桶对象的下载预签名 URL。 + * + * @param bucket 存储桶名称 + * @param key 对象键 + * @param expiredTime 过期时间 + * @return 预签名下载 URL + */ @Override public String bucketPresignGetUrl(String bucket, String key, Duration expiredTime) { try { @@ -433,6 +719,15 @@ public abstract class AbstractOssClientImpl implements OssClient { } } + /** + * 生成指定存储桶对象的上传预签名 URL。 + * + * @param bucket 存储桶名称 + * @param key 对象键 + * @param expiredTime 过期时间 + * @param metadata 对象元数据 + * @return 预签名上传 URL + */ @Override public String bucketPresignPutUrl(String bucket, String key, Duration expiredTime, Map metadata) { try { @@ -447,122 +742,299 @@ public abstract class AbstractOssClientImpl implements OssClient { } } + /** + * 上传本地路径文件到默认存储桶。 + * + * @param key 对象键 + * @param path 文件路径 + * @param options 上传选项 + * @return 上传结果 + */ @Override public PutObjectResult upload(String key, Path path, Options options) { return bucketUpload(defaultBucket(), key, path, options); } + /** + * 上传本地路径文件到默认存储桶。 + * + * @param key 对象键 + * @param path 文件路径 + * @return 上传结果 + */ @Override public PutObjectResult upload(String key, Path path) { return bucketUpload(defaultBucket(), key, path); } + /** + * 上传文件到默认存储桶。 + * + * @param key 对象键 + * @param file 文件对象 + * @param options 上传选项 + * @return 上传结果 + */ @Override public PutObjectResult upload(String key, File file, Options options) { return bucketUpload(defaultBucket(), key, file, options); } + /** + * 上传文件到默认存储桶。 + * + * @param key 对象键 + * @param file 文件对象 + * @return 上传结果 + */ @Override public PutObjectResult upload(String key, File file) { return bucketUpload(defaultBucket(), key, file); } + /** + * 上传随机访问文件到默认存储桶。 + * + * @param key 对象键 + * @param file 随机访问文件 + * @param options 上传选项 + * @return 上传结果 + */ @Override public PutObjectResult upload(String key, RandomAccessFile file, Options options) { return bucketUpload(defaultBucket(), key, file, options); } + /** + * 上传随机访问文件到默认存储桶。 + * + * @param key 对象键 + * @param file 随机访问文件 + * @return 上传结果 + */ @Override public PutObjectResult upload(String key, RandomAccessFile file) { return bucketUpload(defaultBucket(), key, file); } + /** + * 上传可读通道数据到默认存储桶。 + * + * @param key 对象键 + * @param channel 可读通道 + * @param contentLength 内容长度 + * @param options 上传选项 + * @return 上传结果 + */ @Override public PutObjectResult upload(String key, ReadableByteChannel channel, long contentLength, Options options) { return bucketUpload(defaultBucket(), key, channel, contentLength, options); } + /** + * 上传可读通道数据到默认存储桶。 + * + * @param key 对象键 + * @param channel 可读通道 + * @param contentLength 内容长度 + * @return 上传结果 + */ @Override public PutObjectResult upload(String key, ReadableByteChannel channel, long contentLength) { return bucketUpload(defaultBucket(), key, channel, contentLength); } + /** + * 上传输入流数据到默认存储桶。 + * + * @param key 对象键 + * @param in 输入流 + * @param contentLength 内容长度 + * @param options 上传选项 + * @return 上传结果 + */ @Override public PutObjectResult upload(String key, InputStream in, long contentLength, Options options) { return bucketUpload(defaultBucket(), key, in, contentLength, options); } + /** + * 上传输入流数据到默认存储桶。 + * + * @param key 对象键 + * @param in 输入流 + * @param contentLength 内容长度 + * @return 上传结果 + */ @Override public PutObjectResult upload(String key, InputStream in, long contentLength) { return bucketUpload(defaultBucket(), key, in, contentLength); } + /** + * 上传字节数组到默认存储桶。 + * + * @param key 对象键 + * @param data 字节数组 + * @param options 上传选项 + * @return 上传结果 + */ @Override public PutObjectResult upload(String key, byte[] data, Options options) { return bucketUpload(defaultBucket(), key, data, options); } + /** + * 上传字节数组到默认存储桶。 + * + * @param key 对象键 + * @param data 字节数组 + * @return 上传结果 + */ @Override public PutObjectResult upload(String key, byte[] data) { return bucketUpload(defaultBucket(), key, data); } + /** + * 将默认存储桶对象下载到订阅器。 + * + * @param key 对象键 + * @param downloadSubscriber 下载订阅器 + * @return 下载结果 + */ @Override public GetObjectResult download(String key, OutputStreamDownloadSubscriber downloadSubscriber) { return bucketDownload(defaultBucket(), key, downloadSubscriber); } + /** + * 将默认存储桶对象下载到转换器。 + * + * @param key 对象键 + * @param downloadTransformer 下载转换器 + * @param 下载结果类型 + * @return 下载结果 + */ @Override public T download(String key, BiFunction downloadTransformer) { return bucketDownload(defaultBucket(), key, downloadTransformer); } + /** + * 将默认存储桶对象下载到本地路径。 + * + * @param key 对象键 + * @param path 本地路径 + * @return 下载结果 + */ @Override public GetObjectResult download(String key, Path path) { return bucketDownload(defaultBucket(), key, path); } + /** + * 将默认存储桶对象下载到文件。 + * + * @param key 对象键 + * @param file 本地文件 + * @return 下载结果 + */ @Override public GetObjectResult download(String key, File file) { return bucketDownload(defaultBucket(), key, file); } + /** + * 将默认存储桶对象下载到随机访问文件。 + * + * @param key 对象键 + * @param file 随机访问文件 + * @return 下载结果 + */ @Override public GetObjectResult download(String key, RandomAccessFile file) { return bucketDownload(defaultBucket(), key, file); } + /** + * 将默认存储桶对象下载到可写通道。 + * + * @param key 对象键 + * @param channel 可写通道 + * @return 下载结果 + */ @Override public GetObjectResult download(String key, WritableByteChannel channel) { return bucketDownload(defaultBucket(), key, channel); } + /** + * 将默认存储桶对象下载到输出流。 + * + * @param key 对象键 + * @param out 输出流 + * @return 下载结果 + */ @Override public GetObjectResult download(String key, OutputStream out) { return bucketDownload(defaultBucket(), key, out); } + /** + * 删除默认存储桶中的对象。 + * + * @param key 对象键 + * @return 是否删除成功 + */ @Override public boolean delete(String key) { return bucketDelete(defaultBucket(), key); } + /** + * 生成默认存储桶对象的下载预签名 URL。 + * + * @param key 对象键 + * @param expiredTime 过期时间 + * @return 预签名下载 URL + */ @Override public String presignGetUrl(String key, Duration expiredTime) { return bucketPresignGetUrl(defaultBucket(), key, expiredTime); } + /** + * 生成默认存储桶对象的上传预签名 URL。 + * + * @param key 对象键 + * @param expiredTime 过期时间 + * @param metadata 对象元数据 + * @return 预签名上传 URL + */ @Override public String presignPutUrl(String key, Duration expiredTime, Map metadata) { return bucketPresignPutUrl(defaultBucket(), key, expiredTime, metadata); } + /** + * 获取默认存储桶名称。 + * + * @return 默认存储桶名称 + */ private String defaultBucket() { return config.bucket() .filter(bucket -> !bucket.isBlank()) .orElseThrow(() -> S3StorageException.form("bucket is not configured.")); } + /** + * 合并默认前缀与业务前缀。 + * + * @param defaultPrefix 默认前缀 + * @param businessPrefix 业务前缀 + * @return 合并后的前缀 + */ private String mergePrefix(String defaultPrefix, String businessPrefix) { String left = normalizePrefix(defaultPrefix); String right = normalizePrefix(businessPrefix); @@ -575,6 +1047,12 @@ public abstract class AbstractOssClientImpl implements OssClient { return left + StringUtils.SLASH + right; } + /** + * 规范化对象键前缀。 + * + * @param prefix 原始前缀 + * @return 规范化后的前缀 + */ private String normalizePrefix(String prefix) { if (prefix == null) { return ""; @@ -589,6 +1067,12 @@ public abstract class AbstractOssClientImpl implements OssClient { return normalized; } + /** + * 提取文件扩展名。 + * + * @param fileName 文件名 + * @return 文件扩展名 + */ private String suffix(String fileName) { if (fileName == null) { return ""; @@ -600,6 +1084,12 @@ public abstract class AbstractOssClientImpl implements OssClient { return fileName.substring(index); } + /** + * 转换为统一的 S3 存储异常。 + * + * @param e 原始异常 + * @return S3 存储异常 + */ private S3StorageException toStorageException(Throwable e) { Throwable cause = unwrapAsyncException(e); if (cause instanceof S3StorageException ex) { @@ -608,6 +1098,12 @@ public abstract class AbstractOssClientImpl implements OssClient { return S3StorageException.form(cause); } + /** + * 解包异步执行异常。 + * + * @param e 原始异常 + * @return 根因异常 + */ private Throwable unwrapAsyncException(Throwable e) { Throwable cause = e; while ((cause instanceof CompletionException || cause instanceof ExecutionException) && cause.getCause() != null) { @@ -616,6 +1112,11 @@ public abstract class AbstractOssClientImpl implements OssClient { return cause; } + /** + * 关闭底层 S3 客户端资源。 + * + * @throws Exception 关闭资源异常 + */ @Override public void close() throws Exception { if (s3TransferManager != null) { diff --git a/ruoyi-common/ruoyi-common-oss/src/main/java/org/dromara/common/oss/client/DefaultOssClientImpl.java b/ruoyi-common/ruoyi-common-oss/src/main/java/org/dromara/common/oss/client/DefaultOssClientImpl.java index ccbbae447..52438028f 100644 --- a/ruoyi-common/ruoyi-common-oss/src/main/java/org/dromara/common/oss/client/DefaultOssClientImpl.java +++ b/ruoyi-common/ruoyi-common-oss/src/main/java/org/dromara/common/oss/client/DefaultOssClientImpl.java @@ -35,6 +35,9 @@ public class DefaultOssClientImpl extends AbstractOssClientImpl { super(clientId, config); } + /** + * 初始化默认 S3 客户端、传输管理器和预签名生成器。 + */ @Override void doInitialize() { // 校验配置 diff --git a/ruoyi-common/ruoyi-common-oss/src/main/java/org/dromara/common/oss/config/AccessControlPolicyConfig.java b/ruoyi-common/ruoyi-common-oss/src/main/java/org/dromara/common/oss/config/AccessControlPolicyConfig.java index ab75fc734..ad95fde3f 100644 --- a/ruoyi-common/ruoyi-common-oss/src/main/java/org/dromara/common/oss/config/AccessControlPolicyConfig.java +++ b/ruoyi-common/ruoyi-common-oss/src/main/java/org/dromara/common/oss/config/AccessControlPolicyConfig.java @@ -32,17 +32,32 @@ public record AccessControlPolicyConfig( .accessPolicy(AccessPolicy.PUBLIC_READ_WRITE) .build(); + /** + * 获取访问策略,未配置时返回默认策略。 + * + * @return 访问策略 + */ @Override public @NonNull AccessPolicy accessPolicy() { return Optional.ofNullable(accessPolicy) .orElse(AccessPolicy.PUBLIC_READ_WRITE); } + /** + * 复制访问策略配置。 + * + * @return 配置副本 + */ @Override public AccessControlPolicyConfig copy() { return toBuilder().build(); } + /** + * 转换为构建器。 + * + * @return 配置构建器 + */ @Override public AccessControlPolicyConfigBuilder toBuilder() { return builder() diff --git a/ruoyi-common/ruoyi-common-oss/src/main/java/org/dromara/common/oss/config/OssAsyncExecutorConfig.java b/ruoyi-common/ruoyi-common-oss/src/main/java/org/dromara/common/oss/config/OssAsyncExecutorConfig.java index df3e83c56..cb9e1a63a 100644 --- a/ruoyi-common/ruoyi-common-oss/src/main/java/org/dromara/common/oss/config/OssAsyncExecutorConfig.java +++ b/ruoyi-common/ruoyi-common-oss/src/main/java/org/dromara/common/oss/config/OssAsyncExecutorConfig.java @@ -52,11 +52,21 @@ public record OssAsyncExecutorConfig( return corePoolSize; } + /** + * 复制异步执行器配置。 + * + * @return 配置副本 + */ @Override public OssAsyncExecutorConfig copy() { return toBuilder().build(); } + /** + * 转换为构建器。 + * + * @return 配置构建器 + */ @Override public OssAsyncExecutorConfigBuilder toBuilder() { return builder() diff --git a/ruoyi-common/ruoyi-common-oss/src/main/java/org/dromara/common/oss/config/OssClientConfig.java b/ruoyi-common/ruoyi-common-oss/src/main/java/org/dromara/common/oss/config/OssClientConfig.java index f6986e99c..f25bb7b84 100644 --- a/ruoyi-common/ruoyi-common-oss/src/main/java/org/dromara/common/oss/config/OssClientConfig.java +++ b/ruoyi-common/ruoyi-common-oss/src/main/java/org/dromara/common/oss/config/OssClientConfig.java @@ -226,6 +226,12 @@ public class OssClientConfig implements Config !s.isBlank()) .orElseThrow(() -> S3StorageException.form("endpoint is not configured.")); } + /** + * 判断 URL 是否包含 HTTP 协议头。 + * + * @param url URL + * @return 是否包含 HTTP 协议头 + */ private static boolean hasHttpHeader(String url) { return HttpUtil.isHttp(url) || HttpUtil.isHttps(url); } diff --git a/ruoyi-common/ruoyi-common-oss/src/main/java/org/dromara/common/oss/factory/OssFactory.java b/ruoyi-common/ruoyi-common-oss/src/main/java/org/dromara/common/oss/factory/OssFactory.java index 4169303e4..618b7758c 100644 --- a/ruoyi-common/ruoyi-common-oss/src/main/java/org/dromara/common/oss/factory/OssFactory.java +++ b/ruoyi-common/ruoyi-common-oss/src/main/java/org/dromara/common/oss/factory/OssFactory.java @@ -92,10 +92,22 @@ public class OssFactory { } } + /** + * 获取指定配置键对应的客户端锁。 + * + * @param configKey 配置键 + * @return 客户端锁 + */ private static ReentrantLock getClientLock(String configKey) { return CLIENT_LOCKS.computeIfAbsent(configKey, key -> new ReentrantLock()); } + /** + * 关闭 OSS 客户端。 + * + * @param configKey 配置键 + * @param client OSS 客户端 + */ private static void closeClient(String configKey, OssClient client) { try { client.close(); diff --git a/ruoyi-common/ruoyi-common-oss/src/main/java/org/dromara/common/oss/io/OutputStreamDownloadSubscriber.java b/ruoyi-common/ruoyi-common-oss/src/main/java/org/dromara/common/oss/io/OutputStreamDownloadSubscriber.java index 14f96a517..ce11d5f21 100644 --- a/ruoyi-common/ruoyi-common-oss/src/main/java/org/dromara/common/oss/io/OutputStreamDownloadSubscriber.java +++ b/ruoyi-common/ruoyi-common-oss/src/main/java/org/dromara/common/oss/io/OutputStreamDownloadSubscriber.java @@ -20,11 +20,23 @@ public class OutputStreamDownloadSubscriber implements Consumer, Aut private final boolean allowAutoClose; + /** + * 创建输出流下载订阅器。 + * + * @param channel 可写通道 + * @param allowAutoClose 是否允许自动关闭通道 + */ private OutputStreamDownloadSubscriber(WritableByteChannel channel, boolean allowAutoClose) { this.channel = channel; this.allowAutoClose = allowAutoClose; } + /** + * 创建输出流下载订阅器。 + * + * @param out 输出流 + * @param allowAutoClose 是否允许自动关闭流 + */ private OutputStreamDownloadSubscriber(OutputStream out, boolean allowAutoClose) { this.allowAutoClose = allowAutoClose; // 创建可写入的字节通道 @@ -36,6 +48,11 @@ public class OutputStreamDownloadSubscriber implements Consumer, Aut } } + /** + * 写入下载到的字节缓冲区。 + * + * @param byteBuffer 字节缓冲区 + */ @Override public void accept(ByteBuffer byteBuffer) { try { @@ -47,6 +64,11 @@ public class OutputStreamDownloadSubscriber implements Consumer, Aut } } + /** + * 按配置关闭底层通道。 + * + * @throws Exception 关闭通道异常 + */ @Override public void close() throws Exception { if (channel.isOpen() && allowAutoClose) { diff --git a/ruoyi-common/ruoyi-common-redis/src/main/java/org/dromara/common/redis/aspectj/RateLimiterAspect.java b/ruoyi-common/ruoyi-common-redis/src/main/java/org/dromara/common/redis/aspectj/RateLimiterAspect.java index 5b2a5fb9b..88455807a 100644 --- a/ruoyi-common/ruoyi-common-redis/src/main/java/org/dromara/common/redis/aspectj/RateLimiterAspect.java +++ b/ruoyi-common/ruoyi-common-redis/src/main/java/org/dromara/common/redis/aspectj/RateLimiterAspect.java @@ -85,6 +85,13 @@ public class RateLimiterAspect { } } + /** + * 组装限流缓存键。 + * + * @param rateLimiter 限流注解配置 + * @param point 切点信息 + * @return 限流缓存键 + */ private String getCombineKey(RateLimiter rateLimiter, JoinPoint point) { String key = rateLimiter.key(); // 判断 key 不为空 和 不是表达式 diff --git a/ruoyi-common/ruoyi-common-redis/src/main/java/org/dromara/common/redis/aspectj/RepeatSubmitAspect.java b/ruoyi-common/ruoyi-common-redis/src/main/java/org/dromara/common/redis/aspectj/RepeatSubmitAspect.java index df025d160..cd8b3b12a 100644 --- a/ruoyi-common/ruoyi-common-redis/src/main/java/org/dromara/common/redis/aspectj/RepeatSubmitAspect.java +++ b/ruoyi-common/ruoyi-common-redis/src/main/java/org/dromara/common/redis/aspectj/RepeatSubmitAspect.java @@ -42,7 +42,7 @@ public class RepeatSubmitAspect { /** * 请求进入前校验是否重复提交。 * - * @param point 切点 + * @param point 切点 * @param repeatSubmit 防重复提交注解 */ @Before("@annotation(repeatSubmit)") @@ -111,6 +111,9 @@ public class RepeatSubmitAspect { } } + /** + * 删除当前请求写入的防重键。 + */ private void deleteRepeatKey() { String key = KEY_CACHE.get(); if (StringUtils.isNotBlank(key)) { @@ -120,6 +123,9 @@ public class RepeatSubmitAspect { /** * 参数拼装 + * + * @param paramsArray 方法参数数组 + * @return 拼装后的参数字符串 */ private String argsArrayToString(Object[] paramsArray) { StringJoiner params = new StringJoiner(" "); @@ -157,7 +163,7 @@ public class RepeatSubmitAspect { } } return o instanceof MultipartFile || o instanceof HttpServletRequest || o instanceof HttpServletResponse - || o instanceof BindingResult; + || o instanceof BindingResult; } } diff --git a/ruoyi-common/ruoyi-common-redis/src/main/java/org/dromara/common/redis/manager/CaffeineCacheDecorator.java b/ruoyi-common/ruoyi-common-redis/src/main/java/org/dromara/common/redis/manager/CaffeineCacheDecorator.java index 8368aa3c7..81fb4228e 100644 --- a/ruoyi-common/ruoyi-common-redis/src/main/java/org/dromara/common/redis/manager/CaffeineCacheDecorator.java +++ b/ruoyi-common/ruoyi-common-redis/src/main/java/org/dromara/common/redis/manager/CaffeineCacheDecorator.java @@ -18,7 +18,7 @@ public class CaffeineCacheDecorator implements Cache { /** * 创建带 Caffeine 一级缓存的缓存装饰器。 * - * @param name 缓存名称 + * @param name 缓存名称 * @param cache 被装饰的缓存实例 * @param caffeine 本地一级缓存实例 */ @@ -73,7 +73,7 @@ public class CaffeineCacheDecorator implements Cache { /** * 按指定类型获取缓存值。 * - * @param key 缓存键 + * @param key 缓存键 * @param type 值类型 * @return 缓存值 */ @@ -87,7 +87,7 @@ public class CaffeineCacheDecorator implements Cache { /** * 写入缓存值,并清理本地一级缓存。 * - * @param key 缓存键 + * @param key 缓存键 * @param value 缓存值 */ @Override @@ -99,7 +99,7 @@ public class CaffeineCacheDecorator implements Cache { /** * 当键不存在时写入缓存值。 * - * @param key 缓存键 + * @param key 缓存键 * @param value 缓存值 * @return 原缓存值包装对象 */ @@ -160,7 +160,7 @@ public class CaffeineCacheDecorator implements Cache { /** * 获取缓存值,不存在时通过回调加载。 * - * @param key 缓存键 + * @param key 缓存键 * @param valueLoader 回调加载器 * @return 缓存值 */ @@ -171,6 +171,9 @@ public class CaffeineCacheDecorator implements Cache { return (T) o; } + /** + * 清理当前缓存命名空间下的本地一级缓存。 + */ private void clearLocalCache() { String prefix = name + ":"; caffeine.asMap().keySet().removeIf(key -> key instanceof String cacheKey && cacheKey.startsWith(prefix)); diff --git a/ruoyi-common/ruoyi-common-redis/src/main/java/org/dromara/common/redis/manager/PlusSpringCacheManager.java b/ruoyi-common/ruoyi-common-redis/src/main/java/org/dromara/common/redis/manager/PlusSpringCacheManager.java index 7e02a7dd2..a64f5ae65 100644 --- a/ruoyi-common/ruoyi-common-redis/src/main/java/org/dromara/common/redis/manager/PlusSpringCacheManager.java +++ b/ruoyi-common/ruoyi-common-redis/src/main/java/org/dromara/common/redis/manager/PlusSpringCacheManager.java @@ -1,12 +1,12 @@ /** * Copyright (c) 2013-2021 Nikita Koksharov - * + *

* Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * + *

+ * http://www.apache.org/licenses/LICENSE-2.0 + *

* Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -169,6 +169,14 @@ public class PlusSpringCacheManager implements CacheManager { return createMapCache(cacheName, name, config, local); } + /** + * 解析缓存配置,支持从模板配置复制并叠加缓存名称中的扩展参数。 + * + * @param cacheName 完整缓存名称 + * @param name 基础缓存名称 + * @param array 缓存名称拆分参数 + * @return 缓存配置 + */ private CacheConfig resolveCacheConfig(String cacheName, String name, String[] array) { CacheConfig config = configMap.get(cacheName); if (config != null) { @@ -196,6 +204,12 @@ public class PlusSpringCacheManager implements CacheManager { return config; } + /** + * 解析是否启用本地一级缓存。 + * + * @param array 缓存名称拆分参数 + * @return 本地缓存开关 + */ private int resolveLocal(String[] array) { int local = 1; if (array.length > 4) { @@ -204,6 +218,12 @@ public class PlusSpringCacheManager implements CacheManager { return local; } + /** + * 复制 Redisson 缓存配置,避免修改模板配置。 + * + * @param source 模板缓存配置 + * @return 新缓存配置 + */ private CacheConfig copyConfig(CacheConfig source) { CacheConfig target = new CacheConfig(); target.setTTL(source.getTTL()); diff --git a/ruoyi-common/ruoyi-common-redis/src/main/java/org/dromara/common/redis/utils/CacheUtils.java b/ruoyi-common/ruoyi-common-redis/src/main/java/org/dromara/common/redis/utils/CacheUtils.java index 89c098f36..22fff7b1d 100644 --- a/ruoyi-common/ruoyi-common-redis/src/main/java/org/dromara/common/redis/utils/CacheUtils.java +++ b/ruoyi-common/ruoyi-common-redis/src/main/java/org/dromara/common/redis/utils/CacheUtils.java @@ -57,6 +57,12 @@ public class CacheUtils { getRequiredCache(cacheNames).clear(); } + /** + * 获取必需存在的缓存实例。 + * + * @param cacheNames 缓存组名称 + * @return 缓存实例 + */ private static Cache getRequiredCache(String cacheNames) { Cache cache = CacheManagerHolder.CACHE_MANAGER.getCache(cacheNames); if (cache == null) { diff --git a/ruoyi-common/ruoyi-common-satoken/src/main/java/org/dromara/common/satoken/config/SaTokenConfig.java b/ruoyi-common/ruoyi-common-satoken/src/main/java/org/dromara/common/satoken/config/SaTokenConfig.java index 61c6b9acc..6856edf3a 100644 --- a/ruoyi-common/ruoyi-common-satoken/src/main/java/org/dromara/common/satoken/config/SaTokenConfig.java +++ b/ruoyi-common/ruoyi-common-satoken/src/main/java/org/dromara/common/satoken/config/SaTokenConfig.java @@ -21,6 +21,11 @@ import org.springframework.context.annotation.PropertySource; @PropertySource(value = "classpath:common-satoken.yml", factory = YmlPropertySourceFactory.class) public class SaTokenConfig { + /** + * 创建 Sa-Token JWT 登录逻辑。 + * + * @return JWT 登录逻辑 + */ @Bean public StpLogic getStpLogicJwt() { // Sa-Token 整合 jwt (简单模式) diff --git a/ruoyi-common/ruoyi-common-sensitive/src/main/java/org/dromara/common/sensitive/annotation/Sensitive.java b/ruoyi-common/ruoyi-common-sensitive/src/main/java/org/dromara/common/sensitive/annotation/Sensitive.java index 79f7b338d..d722c72dd 100644 --- a/ruoyi-common/ruoyi-common-sensitive/src/main/java/org/dromara/common/sensitive/annotation/Sensitive.java +++ b/ruoyi-common/ruoyi-common-sensitive/src/main/java/org/dromara/common/sensitive/annotation/Sensitive.java @@ -18,6 +18,11 @@ import java.lang.annotation.Target; @Documented public @interface Sensitive { + /** + * 脱敏策略。 + * + * @return 脱敏策略 + */ SensitiveStrategy strategy(); /** diff --git a/ruoyi-common/ruoyi-common-sensitive/src/main/java/org/dromara/common/sensitive/handler/SensitiveJsonFieldProcessor.java b/ruoyi-common/ruoyi-common-sensitive/src/main/java/org/dromara/common/sensitive/handler/SensitiveJsonFieldProcessor.java index fbaf1f42a..cfbf3698a 100644 --- a/ruoyi-common/ruoyi-common-sensitive/src/main/java/org/dromara/common/sensitive/handler/SensitiveJsonFieldProcessor.java +++ b/ruoyi-common/ruoyi-common-sensitive/src/main/java/org/dromara/common/sensitive/handler/SensitiveJsonFieldProcessor.java @@ -20,11 +20,25 @@ public class SensitiveJsonFieldProcessor implements JsonFieldProcessor { @Autowired(required = false) private SensitiveService sensitiveService; + /** + * 判断字段是否声明了脱敏注解。 + * + * @param fieldContext 字段上下文 + * @return 是否支持脱敏处理 + */ @Override public boolean supports(JsonFieldContext fieldContext) { return fieldContext.getAnnotation(Sensitive.class) != null; } + /** + * 按字段脱敏策略处理字符串值。 + * + * @param fieldContext 字段上下文 + * @param value 字段原始值 + * @param context JSON 增强上下文 + * @return 脱敏后的字段值 + */ @Override public Object process(JsonFieldContext fieldContext, Object value, JsonEnhancementContext context) { Sensitive sensitive = fieldContext.getAnnotation(Sensitive.class); diff --git a/ruoyi-common/ruoyi-common-social/src/main/java/me/zhyd/oauth/request/AbstractAuthWeChatEnterpriseRequest.java b/ruoyi-common/ruoyi-common-social/src/main/java/me/zhyd/oauth/request/AbstractAuthWeChatEnterpriseRequest.java index f2a1f7b9f..b1890623a 100644 --- a/ruoyi-common/ruoyi-common-social/src/main/java/me/zhyd/oauth/request/AbstractAuthWeChatEnterpriseRequest.java +++ b/ruoyi-common/ruoyi-common-social/src/main/java/me/zhyd/oauth/request/AbstractAuthWeChatEnterpriseRequest.java @@ -24,15 +24,34 @@ import me.zhyd.oauth.utils.UrlBuilder; */ public abstract class AbstractAuthWeChatEnterpriseRequest extends AuthDefaultRequest { + /** + * 创建企业微信认证请求。 + * + * @param config 授权配置 + * @param source 授权来源 + */ public AbstractAuthWeChatEnterpriseRequest(AuthConfig config, AuthSource source) { super(config,source); } + /** + * 创建企业微信认证请求。 + * + * @param config 授权配置 + * @param source 授权来源 + * @param authStateCache 授权状态缓存 + */ public AbstractAuthWeChatEnterpriseRequest(AuthConfig config, AuthSource source, AuthStateCache authStateCache) { super(config, source, authStateCache); } + /** + * 获取企业微信访问令牌。 + * + * @param authCallback 授权回调参数 + * @return 访问令牌 + */ @Override public AuthToken getAccessToken(AuthCallback authCallback) { String response = doGetAuthorizationCode(accessTokenUrl(null)); @@ -46,6 +65,12 @@ public abstract class AbstractAuthWeChatEnterpriseRequest extends AuthDefaultReq .build(); } + /** + * 获取企业微信用户信息。 + * + * @param authToken 访问令牌 + * @return 授权用户信息 + */ @Override public AuthUser getUserInfo(AuthToken authToken) { String response = doGetUserInfo(authToken); diff --git a/ruoyi-common/ruoyi-common-social/src/main/java/me/zhyd/oauth/request/AuthDingTalkV2Request.java b/ruoyi-common/ruoyi-common-social/src/main/java/me/zhyd/oauth/request/AuthDingTalkV2Request.java index 86532d48a..38309c607 100644 --- a/ruoyi-common/ruoyi-common-social/src/main/java/me/zhyd/oauth/request/AuthDingTalkV2Request.java +++ b/ruoyi-common/ruoyi-common-social/src/main/java/me/zhyd/oauth/request/AuthDingTalkV2Request.java @@ -26,14 +26,31 @@ import java.util.Map; */ public class AuthDingTalkV2Request extends AuthDefaultRequest { + /** + * 创建钉钉 V2 认证请求。 + * + * @param config 授权配置 + */ public AuthDingTalkV2Request(AuthConfig config) { super(config, AuthDefaultSource.DINGTALK_V2); } + /** + * 创建钉钉 V2 认证请求。 + * + * @param config 授权配置 + * @param authStateCache 授权状态缓存 + */ public AuthDingTalkV2Request(AuthConfig config, AuthStateCache authStateCache) { super(config, AuthDefaultSource.DINGTALK_V2, authStateCache); } + /** + * 生成钉钉 V2 授权地址。 + * + * @param state 授权状态 + * @return 授权地址 + */ @Override public String authorize(String state) { return UrlBuilder.fromBaseUrl(source.authorize()) @@ -50,6 +67,12 @@ public class AuthDingTalkV2Request extends AuthDefaultRequest { .build(); } + /** + * 获取钉钉 V2 访问令牌。 + * + * @param authCallback 授权回调参数 + * @return 访问令牌 + */ @Override public AuthToken getAccessToken(AuthCallback authCallback) { Map params = new HashMap<>(); @@ -70,6 +93,12 @@ public class AuthDingTalkV2Request extends AuthDefaultRequest { .build(); } + /** + * 获取钉钉 V2 用户信息。 + * + * @param authToken 访问令牌 + * @return 授权用户信息 + */ @Override public AuthUser getUserInfo(AuthToken authToken) { HttpHeader header = new HttpHeader(); diff --git a/ruoyi-common/ruoyi-common-social/src/main/java/org/dromara/common/social/gitea/AuthGiteaRequest.java b/ruoyi-common/ruoyi-common-social/src/main/java/org/dromara/common/social/gitea/AuthGiteaRequest.java index d3fc7516f..977b0eaa6 100644 --- a/ruoyi-common/ruoyi-common-social/src/main/java/org/dromara/common/social/gitea/AuthGiteaRequest.java +++ b/ruoyi-common/ruoyi-common-social/src/main/java/org/dromara/common/social/gitea/AuthGiteaRequest.java @@ -20,6 +20,9 @@ import org.dromara.common.json.utils.JsonUtils; @Slf4j public class AuthGiteaRequest extends AuthDefaultRequest { + /** + * 服务器地址。 + */ public static final String SERVER_URL = SpringUtils.getProperty("justauth.type.gitea.server-url"); /** @@ -29,10 +32,22 @@ public class AuthGiteaRequest extends AuthDefaultRequest { super(config, AuthGiteaSource.GITEA); } + /** + * 创建 Gitea 认证请求。 + * + * @param config 授权配置 + * @param authStateCache 授权状态缓存 + */ public AuthGiteaRequest(AuthConfig config, AuthStateCache authStateCache) { super(config, AuthGiteaSource.GITEA, authStateCache); } + /** + * 获取 Gitea 访问令牌。 + * + * @param authCallback 授权回调参数 + * @return 访问令牌 + */ @Override public AuthToken getAccessToken(AuthCallback authCallback) { String body = doPostAuthorizationCode(authCallback.getCode()); @@ -54,6 +69,12 @@ public class AuthGiteaRequest extends AuthDefaultRequest { .build(); } + /** + * 使用授权码换取 Gitea 访问令牌响应。 + * + * @param code 授权码 + * @return 令牌接口响应体 + */ @Override protected String doPostAuthorizationCode(String code) { HttpRequest request = HttpRequest.post(source.accessToken()) @@ -66,6 +87,12 @@ public class AuthGiteaRequest extends AuthDefaultRequest { return response.body(); } + /** + * 获取 Gitea 用户信息。 + * + * @param authToken 访问令牌 + * @return 授权用户信息 + */ @Override public AuthUser getUserInfo(AuthToken authToken) { String body = doGetUserInfo(authToken); diff --git a/ruoyi-common/ruoyi-common-social/src/main/java/org/dromara/common/social/maxkey/AuthMaxKeyRequest.java b/ruoyi-common/ruoyi-common-social/src/main/java/org/dromara/common/social/maxkey/AuthMaxKeyRequest.java index 97774ac5d..b19b75314 100644 --- a/ruoyi-common/ruoyi-common-social/src/main/java/org/dromara/common/social/maxkey/AuthMaxKeyRequest.java +++ b/ruoyi-common/ruoyi-common-social/src/main/java/org/dromara/common/social/maxkey/AuthMaxKeyRequest.java @@ -16,6 +16,9 @@ import org.dromara.common.json.utils.JsonUtils; */ public class AuthMaxKeyRequest extends AuthDefaultRequest { + /** + * 服务器地址。 + */ public static final String SERVER_URL = SpringUtils.getProperty("justauth.type.maxkey.server-url"); /** @@ -25,10 +28,22 @@ public class AuthMaxKeyRequest extends AuthDefaultRequest { super(config, AuthMaxKeySource.MAXKEY); } + /** + * 创建 MaxKey 认证请求。 + * + * @param config 授权配置 + * @param authStateCache 授权状态缓存 + */ public AuthMaxKeyRequest(AuthConfig config, AuthStateCache authStateCache) { super(config, AuthMaxKeySource.MAXKEY, authStateCache); } + /** + * 获取 MaxKey 访问令牌。 + * + * @param authCallback 授权回调参数 + * @return 访问令牌 + */ @Override public AuthToken getAccessToken(AuthCallback authCallback) { String body = doPostAuthorizationCode(authCallback.getCode()); @@ -50,6 +65,12 @@ public class AuthMaxKeyRequest extends AuthDefaultRequest { .build(); } + /** + * 获取 MaxKey 用户信息。 + * + * @param authToken 访问令牌 + * @return 授权用户信息 + */ @Override public AuthUser getUserInfo(AuthToken authToken) { String body = doGetUserInfo(authToken); diff --git a/ruoyi-common/ruoyi-common-social/src/main/java/org/dromara/common/social/topiam/AuthTopIamRequest.java b/ruoyi-common/ruoyi-common-social/src/main/java/org/dromara/common/social/topiam/AuthTopIamRequest.java index 080c97a93..4cb932984 100644 --- a/ruoyi-common/ruoyi-common-social/src/main/java/org/dromara/common/social/topiam/AuthTopIamRequest.java +++ b/ruoyi-common/ruoyi-common-social/src/main/java/org/dromara/common/social/topiam/AuthTopIamRequest.java @@ -30,6 +30,9 @@ import static org.dromara.common.social.topiam.AuthTopIamSource.TOPIAM; @Slf4j public class AuthTopIamRequest extends AuthDefaultRequest { + /** + * 服务器地址。 + */ public static final String SERVER_URL = SpringUtils.getProperty("justauth.type.topiam.server-url"); /** @@ -39,10 +42,22 @@ public class AuthTopIamRequest extends AuthDefaultRequest { super(config, TOPIAM); } + /** + * 创建 TopIAM 认证请求。 + * + * @param config 授权配置 + * @param authStateCache 授权状态缓存 + */ public AuthTopIamRequest(AuthConfig config, AuthStateCache authStateCache) { super(config, TOPIAM, authStateCache); } + /** + * 获取 TopIAM 访问令牌。 + * + * @param authCallback 授权回调参数 + * @return 访问令牌 + */ @Override public AuthToken getAccessToken(AuthCallback authCallback) { String body = doPostAuthorizationCode(authCallback.getCode()); @@ -57,6 +72,12 @@ public class AuthTopIamRequest extends AuthDefaultRequest { .build(); } + /** + * 获取 TopIAM 用户信息。 + * + * @param authToken 访问令牌 + * @return 授权用户信息 + */ @Override public AuthUser getUserInfo(AuthToken authToken) { String body = doGetUserInfo(authToken); @@ -73,6 +94,12 @@ public class AuthTopIamRequest extends AuthDefaultRequest { .build(); } + /** + * 使用授权码换取 TopIAM 访问令牌响应。 + * + * @param code 授权码 + * @return 令牌接口响应体 + */ @Override protected String doPostAuthorizationCode(String code) { HttpRequest request = HttpRequest.post(source.accessToken()) @@ -84,6 +111,12 @@ public class AuthTopIamRequest extends AuthDefaultRequest { return response.body(); } + /** + * 获取 TopIAM 用户信息接口响应。 + * + * @param authToken 访问令牌 + * @return 用户信息响应体 + */ @Override protected String doGetUserInfo(AuthToken authToken) { return new HttpUtils(config.getHttpConfig()).get(source.userInfo(), null, new HttpHeader() @@ -92,6 +125,12 @@ public class AuthTopIamRequest extends AuthDefaultRequest { } + /** + * 生成 TopIAM 授权地址。 + * + * @param state 授权状态 + * @return 授权地址 + */ @Override public String authorize(String state) { return UrlBuilder.fromBaseUrl(super.authorize(state)) @@ -99,6 +138,11 @@ public class AuthTopIamRequest extends AuthDefaultRequest { .build(); } + /** + * 校验 TopIAM 接口响应。 + * + * @param object 响应内容 + */ private static void checkResponse(Dict object) { // oauth/token 验证异常 if (object.containsKey("error")) { diff --git a/ruoyi-common/ruoyi-common-web/src/main/java/org/dromara/common/web/config/FilterConfig.java b/ruoyi-common/ruoyi-common-web/src/main/java/org/dromara/common/web/config/FilterConfig.java index b7de20e86..57f9066fd 100644 --- a/ruoyi-common/ruoyi-common-web/src/main/java/org/dromara/common/web/config/FilterConfig.java +++ b/ruoyi-common/ruoyi-common-web/src/main/java/org/dromara/common/web/config/FilterConfig.java @@ -23,6 +23,7 @@ public class FilterConfig { /** * 注册 XSS 过滤器。 * + * @param xssProperties XSS 配置 * @return XSS 请求过滤器实例 */ @Bean diff --git a/ruoyi-common/ruoyi-common-web/src/main/java/org/dromara/common/web/filter/RepeatedlyRequestWrapper.java b/ruoyi-common/ruoyi-common-web/src/main/java/org/dromara/common/web/filter/RepeatedlyRequestWrapper.java index a5e14451c..669abe79a 100644 --- a/ruoyi-common/ruoyi-common-web/src/main/java/org/dromara/common/web/filter/RepeatedlyRequestWrapper.java +++ b/ruoyi-common/ruoyi-common-web/src/main/java/org/dromara/common/web/filter/RepeatedlyRequestWrapper.java @@ -21,6 +21,9 @@ import java.nio.charset.StandardCharsets; * @author ruoyi */ public class RepeatedlyRequestWrapper extends HttpServletRequestWrapper { + /** + * 请求体字节数据。 + */ private final byte[] body; /** @@ -59,26 +62,53 @@ public class RepeatedlyRequestWrapper extends HttpServletRequestWrapper { public ServletInputStream getInputStream() throws IOException { final ByteArrayInputStream bais = new ByteArrayInputStream(body); return new ServletInputStream() { + /** + * 读取缓存请求体的下一个字节。 + * + * @return 下一个字节 + * @throws IOException IO 异常 + */ @Override public int read() throws IOException { return bais.read(); } + /** + * 返回缓存请求体剩余可读字节数。 + * + * @return 剩余字节数 + * @throws IOException IO 异常 + */ @Override public int available() throws IOException { return bais.available(); } + /** + * 判断缓存请求体是否已读取完毕。 + * + * @return 是否读取完毕 + */ @Override public boolean isFinished() { return bais.available() == 0; } + /** + * 判断输入流是否可读。 + * + * @return 固定为 true + */ @Override public boolean isReady() { return true; } + /** + * 设置异步读取监听器。 + * + * @param readListener 读取监听器 + */ @Override public void setReadListener(ReadListener readListener) { diff --git a/ruoyi-common/ruoyi-common-web/src/main/java/org/dromara/common/web/filter/XssHttpServletRequestWrapper.java b/ruoyi-common/ruoyi-common-web/src/main/java/org/dromara/common/web/filter/XssHttpServletRequestWrapper.java index 247c7564e..d2d897eed 100644 --- a/ruoyi-common/ruoyi-common-web/src/main/java/org/dromara/common/web/filter/XssHttpServletRequestWrapper.java +++ b/ruoyi-common/ruoyi-common-web/src/main/java/org/dromara/common/web/filter/XssHttpServletRequestWrapper.java @@ -124,25 +124,52 @@ public class XssHttpServletRequestWrapper extends HttpServletRequestWrapper { byte[] jsonBytes = json.getBytes(StandardCharsets.UTF_8); final ByteArrayInputStream bis = IoUtil.toStream(jsonBytes); return new ServletInputStream() { + /** + * 判断清洗后的 JSON 流是否已读取完毕。 + * + * @return 是否读取完毕 + */ @Override public boolean isFinished() { return true; } + /** + * 判断清洗后的 JSON 流是否可读。 + * + * @return 固定为 true + */ @Override public boolean isReady() { return true; } + /** + * 返回清洗后的 JSON 字节数。 + * + * @return JSON 字节数 + * @throws IOException IO 异常 + */ @Override public int available() throws IOException { return jsonBytes.length; } + /** + * 设置异步读取监听器。 + * + * @param readListener 读取监听器 + */ @Override public void setReadListener(ReadListener readListener) { } + /** + * 读取清洗后的 JSON 流下一个字节。 + * + * @return 下一个字节 + * @throws IOException IO 异常 + */ @Override public int read() throws IOException { return bis.read(); diff --git a/ruoyi-extend/ruoyi-monitor-admin/src/main/java/org/dromara/monitor/admin/MonitorAdminApplication.java b/ruoyi-extend/ruoyi-monitor-admin/src/main/java/org/dromara/monitor/admin/MonitorAdminApplication.java index a7335616c..16667ce8d 100644 --- a/ruoyi-extend/ruoyi-monitor-admin/src/main/java/org/dromara/monitor/admin/MonitorAdminApplication.java +++ b/ruoyi-extend/ruoyi-monitor-admin/src/main/java/org/dromara/monitor/admin/MonitorAdminApplication.java @@ -13,6 +13,11 @@ import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication public class MonitorAdminApplication { + /** + * Admin 监控服务启动入口。 + * + * @param args 启动参数 + */ public static void main(String[] args) { SpringApplication.run(MonitorAdminApplication.class, args); System.out.println("Admin 监控启动成功"); diff --git a/ruoyi-extend/ruoyi-monitor-admin/src/main/java/org/dromara/monitor/admin/config/SecurityConfig.java b/ruoyi-extend/ruoyi-monitor-admin/src/main/java/org/dromara/monitor/admin/config/SecurityConfig.java index 102424549..1b5b0aade 100644 --- a/ruoyi-extend/ruoyi-monitor-admin/src/main/java/org/dromara/monitor/admin/config/SecurityConfig.java +++ b/ruoyi-extend/ruoyi-monitor-admin/src/main/java/org/dromara/monitor/admin/config/SecurityConfig.java @@ -21,8 +21,16 @@ import org.springframework.security.web.servlet.util.matcher.PathPatternRequestM @Configuration public class SecurityConfig { + /** + * 监控后台上下文路径。 + */ private final String adminContextPath; + /** + * 创建监控后台安全配置。 + * + * @param adminServerProperties 监控后台配置 + */ public SecurityConfig(AdminServerProperties adminServerProperties) { this.adminContextPath = adminServerProperties.getContextPath(); } diff --git a/ruoyi-extend/ruoyi-monitor-admin/src/main/java/org/dromara/monitor/admin/notifier/CustomNotifier.java b/ruoyi-extend/ruoyi-monitor-admin/src/main/java/org/dromara/monitor/admin/notifier/CustomNotifier.java index 45d279cef..e9ba450ef 100644 --- a/ruoyi-extend/ruoyi-monitor-admin/src/main/java/org/dromara/monitor/admin/notifier/CustomNotifier.java +++ b/ruoyi-extend/ruoyi-monitor-admin/src/main/java/org/dromara/monitor/admin/notifier/CustomNotifier.java @@ -20,6 +20,11 @@ import static de.codecentric.boot.admin.server.domain.values.StatusInfo.*; @Component public class CustomNotifier extends AbstractEventNotifier { + /** + * 初始化自定义事件通知处理器。 + * + * @param repository 实例仓库 + */ protected CustomNotifier(InstanceRepository repository) { super(repository); } diff --git a/ruoyi-extend/ruoyi-snailai-server/src/main/java/com/aizuda/snail/ai/starter/filter/ActuatorAuthFilter.java b/ruoyi-extend/ruoyi-snailai-server/src/main/java/com/aizuda/snail/ai/starter/filter/ActuatorAuthFilter.java index c84013e7b..2dd564c2d 100644 --- a/ruoyi-extend/ruoyi-snailai-server/src/main/java/com/aizuda/snail/ai/starter/filter/ActuatorAuthFilter.java +++ b/ruoyi-extend/ruoyi-snailai-server/src/main/java/com/aizuda/snail/ai/starter/filter/ActuatorAuthFilter.java @@ -20,7 +20,13 @@ import java.util.Base64; */ public class ActuatorAuthFilter implements Filter { + /** + * 认证用户名。 + */ private final String username; + /** + * 认证密码。 + */ private final String password; /** @@ -34,6 +40,15 @@ public class ActuatorAuthFilter implements Filter { this.password = password; } + /** + * 校验 Actuator Basic Auth 请求。 + * + * @param servletRequest 原始请求 + * @param servletResponse 原始响应 + * @param filterChain 过滤器链 + * @throws IOException IO 异常 + * @throws ServletException Servlet 异常 + */ @Override public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { HttpServletRequest request = (HttpServletRequest) servletRequest; @@ -63,10 +78,18 @@ public class ActuatorAuthFilter implements Filter { filterChain.doFilter(request, response); } + /** + * 初始化过滤器。 + * + * @param filterConfig 过滤器配置 + */ @Override public void init(FilterConfig filterConfig) { } + /** + * 销毁过滤器。 + */ @Override public void destroy() { } diff --git a/ruoyi-extend/ruoyi-snailai-server/src/main/java/com/aizuda/snail/ai/starter/filter/SecurityConfig.java b/ruoyi-extend/ruoyi-snailai-server/src/main/java/com/aizuda/snail/ai/starter/filter/SecurityConfig.java index 3674e668f..f12908bc9 100644 --- a/ruoyi-extend/ruoyi-snailai-server/src/main/java/com/aizuda/snail/ai/starter/filter/SecurityConfig.java +++ b/ruoyi-extend/ruoyi-snailai-server/src/main/java/com/aizuda/snail/ai/starter/filter/SecurityConfig.java @@ -13,8 +13,14 @@ import org.springframework.context.annotation.Configuration; @Configuration public class SecurityConfig { + /** + * 认证用户名。 + */ @Value("${spring.boot.admin.client.username}") private String username; + /** + * 认证密码。 + */ @Value("${spring.boot.admin.client.password}") private String password; diff --git a/ruoyi-extend/ruoyi-snailai-server/src/main/java/org/dromara/snailai/SnailAiServerApplication.java b/ruoyi-extend/ruoyi-snailai-server/src/main/java/org/dromara/snailai/SnailAiServerApplication.java index b2aa4d94a..905efd0d7 100644 --- a/ruoyi-extend/ruoyi-snailai-server/src/main/java/org/dromara/snailai/SnailAiServerApplication.java +++ b/ruoyi-extend/ruoyi-snailai-server/src/main/java/org/dromara/snailai/SnailAiServerApplication.java @@ -11,6 +11,11 @@ import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication public class SnailAiServerApplication { + /** + * Snail AI 服务启动入口。 + * + * @param args 启动参数 + */ public static void main(String[] args) { com.aizuda.snail.ai.starter.SnailAiSpringbootApplication.main(args); } diff --git a/ruoyi-extend/ruoyi-snailjob-server/src/main/java/com/aizuda/snailjob/server/starter/filter/ActuatorAuthFilter.java b/ruoyi-extend/ruoyi-snailjob-server/src/main/java/com/aizuda/snailjob/server/starter/filter/ActuatorAuthFilter.java index 3e08f3346..7847b42f3 100644 --- a/ruoyi-extend/ruoyi-snailjob-server/src/main/java/com/aizuda/snailjob/server/starter/filter/ActuatorAuthFilter.java +++ b/ruoyi-extend/ruoyi-snailjob-server/src/main/java/com/aizuda/snailjob/server/starter/filter/ActuatorAuthFilter.java @@ -15,7 +15,13 @@ import java.util.Base64; */ public class ActuatorAuthFilter implements Filter { + /** + * 认证用户名。 + */ private final String username; + /** + * 认证密码。 + */ private final String password; /** @@ -29,6 +35,15 @@ public class ActuatorAuthFilter implements Filter { this.password = password; } + /** + * 校验 Actuator Basic Auth 请求。 + * + * @param servletRequest 原始请求 + * @param servletResponse 原始响应 + * @param filterChain 过滤器链 + * @throws IOException IO 异常 + * @throws ServletException Servlet 异常 + */ @Override public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { HttpServletRequest request = (HttpServletRequest) servletRequest; @@ -64,10 +79,18 @@ public class ActuatorAuthFilter implements Filter { filterChain.doFilter(request, response); } + /** + * 初始化过滤器。 + * + * @param filterConfig 过滤器配置 + */ @Override public void init(FilterConfig filterConfig) { } + /** + * 销毁过滤器。 + */ @Override public void destroy() { } diff --git a/ruoyi-extend/ruoyi-snailjob-server/src/main/java/com/aizuda/snailjob/server/starter/filter/SecurityConfig.java b/ruoyi-extend/ruoyi-snailjob-server/src/main/java/com/aizuda/snailjob/server/starter/filter/SecurityConfig.java index 57cb77dda..26784326a 100644 --- a/ruoyi-extend/ruoyi-snailjob-server/src/main/java/com/aizuda/snailjob/server/starter/filter/SecurityConfig.java +++ b/ruoyi-extend/ruoyi-snailjob-server/src/main/java/com/aizuda/snailjob/server/starter/filter/SecurityConfig.java @@ -13,8 +13,14 @@ import org.springframework.context.annotation.Configuration; @Configuration public class SecurityConfig { + /** + * 认证用户名。 + */ @Value("${spring.boot.admin.client.username}") private String username; + /** + * 认证密码。 + */ @Value("${spring.boot.admin.client.password}") private String password; diff --git a/ruoyi-extend/ruoyi-snailjob-server/src/main/java/org/dromara/snailjob/SnailJobServerApplication.java b/ruoyi-extend/ruoyi-snailjob-server/src/main/java/org/dromara/snailjob/SnailJobServerApplication.java index dfab0684f..03e8bac12 100644 --- a/ruoyi-extend/ruoyi-snailjob-server/src/main/java/org/dromara/snailjob/SnailJobServerApplication.java +++ b/ruoyi-extend/ruoyi-snailjob-server/src/main/java/org/dromara/snailjob/SnailJobServerApplication.java @@ -12,6 +12,11 @@ import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication public class SnailJobServerApplication { + /** + * SnailJob 服务启动入口。 + * + * @param args 启动参数 + */ public static void main(String[] args) { SpringApplication.run(com.aizuda.snailjob.server.SnailJobServerApplication.class, args); } diff --git a/ruoyi-modules/ruoyi-ai/src/main/java/org/dromara/ai/controller/SnailAiController.java b/ruoyi-modules/ruoyi-ai/src/main/java/org/dromara/ai/controller/SnailAiController.java index 82449dc7f..5bfe004a1 100644 --- a/ruoyi-modules/ruoyi-ai/src/main/java/org/dromara/ai/controller/SnailAiController.java +++ b/ruoyi-modules/ruoyi-ai/src/main/java/org/dromara/ai/controller/SnailAiController.java @@ -46,13 +46,22 @@ import java.util.concurrent.atomic.AtomicBoolean; OpenApiConversationClient.class, OpenApiUserClient.class}) public class SnailAiController extends BaseController { + /** + * Snail AI 成功状态码。 + */ private static final int SNAIL_AI_SUCCESS = 1; + /** + * SSE 超时时间。 + */ private static final long SSE_TIMEOUT = 300000L; private final OpenApiAgentClient agentClient; private final OpenApiChatClient chatClient; private final OpenApiConversationClient conversationClient; private final OpenApiUserClient userClient; + /** + * 聊天模式。 + */ @Value("${snail-ai.chat-mode:stream}") private String chatMode; @@ -97,8 +106,8 @@ public class SnailAiController extends BaseController { */ @PostMapping("/agent/{agentId}/conversation") public R createConversation( - @NotNull(message = "智能体ID不能为空") @PathVariable Long agentId, - @RequestBody OpenApiCreateConversationRequest request) { + @NotNull(message = "智能体ID不能为空") @PathVariable Long agentId, + @RequestBody OpenApiCreateConversationRequest request) { request.setAgentId(agentId); request.setOpenId(ensureOpenId()); return toR(conversationClient.createConversation(request)); @@ -109,9 +118,9 @@ public class SnailAiController extends BaseController { */ @GetMapping("/agent/{agentId}/conversations") public R> listConversations( - @NotNull(message = "智能体ID不能为空") @PathVariable Long agentId, - @Min(value = 1, message = "页码不能小于1") @RequestParam(defaultValue = "1") int page, - @Min(value = 1, message = "每页条数不能小于1") @RequestParam(defaultValue = "10") int size) { + @NotNull(message = "智能体ID不能为空") @PathVariable Long agentId, + @Min(value = 1, message = "页码不能小于1") @RequestParam(defaultValue = "1") int page, + @Min(value = 1, message = "每页条数不能小于1") @RequestParam(defaultValue = "10") int size) { OpenApiConversationQueryRequest request = new OpenApiConversationQueryRequest(); request.setAgentId(agentId); request.setOpenId(ensureOpenId()); @@ -125,8 +134,8 @@ public class SnailAiController extends BaseController { */ @GetMapping("/agent/{agentId}/conversation/{conversationId}/messages") public R> getMessages( - @NotNull(message = "智能体ID不能为空") @PathVariable Long agentId, - @NotBlank(message = "会话ID不能为空") @PathVariable String conversationId) { + @NotNull(message = "智能体ID不能为空") @PathVariable Long agentId, + @NotBlank(message = "会话ID不能为空") @PathVariable String conversationId) { OpenApiConversationIdentityRequest request = new OpenApiConversationIdentityRequest(); request.setAgentId(agentId); request.setConversationId(conversationId); @@ -139,8 +148,8 @@ public class SnailAiController extends BaseController { */ @DeleteMapping("/agent/{agentId}/conversation/{conversationId}") public R deleteConversation( - @NotNull(message = "智能体ID不能为空") @PathVariable Long agentId, - @NotBlank(message = "会话ID不能为空") @PathVariable String conversationId) { + @NotNull(message = "智能体ID不能为空") @PathVariable Long agentId, + @NotBlank(message = "会话ID不能为空") @PathVariable String conversationId) { OpenApiConversationIdentityRequest request = new OpenApiConversationIdentityRequest(); request.setAgentId(agentId); request.setConversationId(conversationId); @@ -162,8 +171,8 @@ public class SnailAiController extends BaseController { */ @PostMapping("/agent/{agentId}/chat/sync") public R chatSync( - @NotNull(message = "智能体ID不能为空") @PathVariable Long agentId, - @RequestBody OpenApiChatRequest request) { + @NotNull(message = "智能体ID不能为空") @PathVariable Long agentId, + @RequestBody OpenApiChatRequest request) { request.setAgentId(agentId); request.setOpenId(ensureOpenId()); log.info("Sync chat request: agentId={}", agentId); @@ -175,9 +184,9 @@ public class SnailAiController extends BaseController { */ @PostMapping(value = "/agent/{agentId}/chat/stream", produces = MediaType.TEXT_EVENT_STREAM_VALUE) public SseEmitter chatStream( - @NotNull(message = "智能体ID不能为空") @PathVariable Long agentId, - @RequestBody OpenApiChatRequest request, - HttpServletResponse response) { + @NotNull(message = "智能体ID不能为空") @PathVariable Long agentId, + @RequestBody OpenApiChatRequest request, + HttpServletResponse response) { prepareSseResponse(response); SseEmitter emitter = new SseEmitter(SSE_TIMEOUT); AtomicBoolean closed = new AtomicBoolean(false); @@ -202,16 +211,31 @@ public class SnailAiController extends BaseController { log.info("Stream chat request: agentId={}", agentId); try { chatClient.chatStream(request, new SseEventListener() { + /** + * 推送普通文本片段。 + * + * @param text 文本片段 + */ @Override public void onText(String text) { safeSend(emitter, closed, "text", text); } + /** + * 推送思考内容片段。 + * + * @param thinking 思考内容 + */ @Override public void onThinking(String thinking) { safeSend(emitter, closed, "thinking", thinking); } + /** + * 处理流式对话完成事件。 + * + * @param data 完成数据 + */ @Override public void onComplete(String data) { if (!closed.get()) { @@ -223,6 +247,11 @@ public class SnailAiController extends BaseController { } } + /** + * 处理流式对话异常事件。 + * + * @param errorMessage 错误信息 + */ @Override public void onError(String errorMessage) { log.error("Stream chat error: {}", errorMessage); diff --git a/ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/controller/queue/PriorityDemo.java b/ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/controller/queue/PriorityDemo.java index e2449b518..ed457ff9b 100644 --- a/ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/controller/queue/PriorityDemo.java +++ b/ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/controller/queue/PriorityDemo.java @@ -12,9 +12,22 @@ import lombok.NoArgsConstructor; @Data @NoArgsConstructor public class PriorityDemo implements Comparable { + /** + * 队列元素名称。 + */ private String name; + + /** + * 优先级排序值。 + */ private Integer orderNum; + /** + * 按排序值比较优先级。 + * + * @param other 另一个队列元素 + * @return 比较结果 + */ @Override public int compareTo(PriorityDemo other) { return Integer.compare(getOrderNum(), other.getOrderNum()); diff --git a/ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/listener/ExportDemoListener.java b/ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/listener/ExportDemoListener.java index 781329eed..7e9772cad 100644 --- a/ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/listener/ExportDemoListener.java +++ b/ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/listener/ExportDemoListener.java @@ -18,11 +18,20 @@ import java.util.List; */ public class ExportDemoListener extends DefaultExcelListener { + /** + * 创建下拉框导入解析监听器。 + */ public ExportDemoListener() { // 显示使用构造函数,否则将导致空指针 super(true); } + /** + * 解析并校验一行下拉框演示数据。 + * + * @param data 行数据 + * @param context 解析上下文 + */ @Override public void invoke(ExportDemoVo data, AnalysisContext context) { // 先校验必填 diff --git a/ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/mapper/TestDemoMapper.java b/ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/mapper/TestDemoMapper.java index 19b2d52df..4342f5f87 100644 --- a/ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/mapper/TestDemoMapper.java +++ b/ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/mapper/TestDemoMapper.java @@ -23,12 +23,26 @@ import java.util.List; */ public interface TestDemoMapper extends BaseMapperPlus { + /** + * 自定义分页查询演示数据。 + * + * @param page 分页对象 + * @param wrapper 查询条件 + * @return 分页结果 + */ @DataPermission({ @DataColumn(key = "deptName", value = "dept_id"), @DataColumn(key = "userName", value = "user_id") }) Page customPageList(@Param("page") Page page, @Param("ew") Wrapper wrapper); + /** + * 分页查询演示 VO 列表并应用数据权限。 + * + * @param page 分页对象 + * @param wrapper 查询条件 + * @return 分页结果 + */ @Override @DataPermission({ @DataColumn(key = "deptName", value = "dept_id"), @@ -38,6 +52,12 @@ public interface TestDemoMapper extends BaseMapperPlus { return selectVoPage(page, wrapper, this.currentVoClass()); } + /** + * 查询演示 VO 列表并应用数据权限。 + * + * @param wrapper 查询条件 + * @return 演示 VO 列表 + */ @Override @DataPermission({ @DataColumn(key = "deptName", value = "dept_id"), @@ -47,6 +67,12 @@ public interface TestDemoMapper extends BaseMapperPlus { return selectVoList(wrapper, this.currentVoClass()); } + /** + * 按主键集合查询演示数据并应用数据权限。 + * + * @param idList 主键集合 + * @return 演示数据列表 + */ @Override @DataPermission(value = { @DataColumn(key = "deptName", value = "dept_id"), @@ -54,6 +80,12 @@ public interface TestDemoMapper extends BaseMapperPlus { }, joinStr = "AND") List selectByIds(@Param(Constants.COLL) Collection idList); + /** + * 按主键更新演示数据并应用数据权限。 + * + * @param entity 演示数据实体 + * @return 更新行数 + */ @Override @DataPermission({ @DataColumn(key = "deptName", value = "dept_id"), diff --git a/ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/mcp/McpDemoClientService.java b/ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/mcp/McpDemoClientService.java index f8983ab7c..eb152c854 100644 --- a/ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/mcp/McpDemoClientService.java +++ b/ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/mcp/McpDemoClientService.java @@ -1,9 +1,9 @@ package org.dromara.demo.mcp; +import lombok.RequiredArgsConstructor; import org.dromara.common.mcp.core.McpClientTemplate; import org.dromara.common.mcp.core.McpResourceReadResult; import org.dromara.common.mcp.core.McpToolCallResult; -import lombok.RequiredArgsConstructor; import org.springframework.beans.factory.ObjectProvider; import org.springframework.stereotype.Service; @@ -42,7 +42,7 @@ public class McpDemoClientService { /** * 调用外部 MCP 工具接收数据。 * - * @param toolName 工具名称 + * @param toolName 工具名称 * @param arguments 工具参数 * @return 工具返回内容 */ @@ -65,7 +65,7 @@ public class McpDemoClientService { *

* MCP 返回数据不建议直接入库,应先转换成业务 BO/DTO,再进入业务 Service。 * - * @param toolName 工具名称 + * @param toolName 工具名称 * @param arguments 工具参数 * @return 处理结果 */ @@ -73,6 +73,13 @@ public class McpDemoClientService { return new McpDemoHandleResult("MCP", true, callRemoteTool(toolName, arguments)); } + /** + * 执行 MCP Client 操作。 + * + * @param action MCP Client 操作 + * @param 返回值类型 + * @return 操作结果 + */ private T execute(Function action) { McpClientTemplate template = mcpClientTemplateProvider.getIfAvailable(); if (template == null) { @@ -85,8 +92,8 @@ public class McpDemoClientService { * MCP 数据处理结果。 * * @param sourceType 数据来源类型 - * @param handled 是否已处理 - * @param data MCP 原始返回数据 + * @param handled 是否已处理 + * @param data MCP 原始返回数据 */ public record McpDemoHandleResult( String sourceType, diff --git a/ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/service/impl/ExportExcelServiceImpl.java b/ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/service/impl/ExportExcelServiceImpl.java index 97a0710ab..6a28f4bc2 100644 --- a/ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/service/impl/ExportExcelServiceImpl.java +++ b/ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/service/impl/ExportExcelServiceImpl.java @@ -28,6 +28,11 @@ import java.util.Map; @RequiredArgsConstructor public class ExportExcelServiceImpl implements IExportExcelService { + /** + * 导出带下拉框选项的 Excel 示例文件。 + * + * @param response HTTP 响应 + */ @Override public void exportWithOptions(HttpServletResponse response) { // 创建表格数据,业务中一般通过数据库查询 @@ -106,6 +111,13 @@ public class ExportExcelServiceImpl implements IExportExcelService { .toResponse(response); } + /** + * 构建下拉框显示值。 + * + * @param cityDataList 城市演示数据列表 + * @param id 选项 id + * @return 下拉框显示值 + */ private String buildOptions(List cityDataList, Integer id) { Map> groupByIdMap = StreamUtils.groupByKey(cityDataList, DemoCityData::getId); @@ -246,6 +258,11 @@ public class ExportExcelServiceImpl implements IExportExcelService { } + /** + * 自定义写入多个工作表。 + * + * @param response HTTP 响应 + */ @Override public void customExport(HttpServletResponse response) { ExcelBuilder.writer(ExportDemoVo.class).sheetName("自定义导出").toResponse(response, wrapper -> { diff --git a/ruoyi-modules/ruoyi-gen/src/main/java/org/dromara/gen/service/GenTableServiceImpl.java b/ruoyi-modules/ruoyi-gen/src/main/java/org/dromara/gen/service/GenTableServiceImpl.java index f470c8ca1..5c3442fc7 100644 --- a/ruoyi-modules/ruoyi-gen/src/main/java/org/dromara/gen/service/GenTableServiceImpl.java +++ b/ruoyi-modules/ruoyi-gen/src/main/java/org/dromara/gen/service/GenTableServiceImpl.java @@ -460,8 +460,8 @@ public class GenTableServiceImpl implements IGenTableService { /** * 模板渲染上下文。 * - * @param table 生成表信息 - * @param context 模板上下文 + * @param table 生成表信息 + * @param context 模板上下文 * @param templates 待渲染模板 */ private record RenderContext(GenTable table, Dict context, List templates) { @@ -488,6 +488,11 @@ public class GenTableServiceImpl implements IGenTableService { } } + /** + * 校验生成选项中配置的字段是否存在。 + * + * @param genTable 业务表信息 + */ private void validateOptionColumns(GenTable genTable) { Map params = genTable.getParams(); if (CollUtil.isEmpty(params) || CollUtil.isEmpty(genTable.getColumns())) { @@ -510,6 +515,13 @@ public class GenTableServiceImpl implements IGenTableService { } } + /** + * 校验单个选项字段。 + * + * @param validFields 有效字段集合 + * @param field 待校验字段 + * @param label 字段显示名称 + */ private void validateOptionField(Set validFields, Object field, String label) { if (ObjectUtil.isNull(field)) { return; @@ -523,6 +535,11 @@ public class GenTableServiceImpl implements IGenTableService { } } + /** + * 规范化字段扩展配置。 + * + * @param columns 表字段列表 + */ private void normalizeColumnOptions(List columns) { if (CollUtil.isEmpty(columns)) { return; diff --git a/ruoyi-modules/ruoyi-gen/src/main/java/org/dromara/gen/util/GenUtils.java b/ruoyi-modules/ruoyi-gen/src/main/java/org/dromara/gen/util/GenUtils.java index b82ba1e55..0bb21d6a5 100644 --- a/ruoyi-modules/ruoyi-gen/src/main/java/org/dromara/gen/util/GenUtils.java +++ b/ruoyi-modules/ruoyi-gen/src/main/java/org/dromara/gen/util/GenUtils.java @@ -134,6 +134,15 @@ public class GenUtils { } } + /** + * 解析数值类型对应的 Java 类型。 + * + * @param dataType 数据库字段类型 + * @param columnLength 字段长度 + * @param columnScale 小数位数 + * @param columnName 字段名称 + * @return Java 类型 + */ private static String resolveNumberJavaType(String dataType, Integer columnLength, Integer columnScale, String columnName) { if (isBooleanColumn(dataType, columnLength, columnScale, columnName)) { return GenConstants.TYPE_BOOLEAN; @@ -159,6 +168,12 @@ public class GenUtils { return GenConstants.TYPE_LONG; } + /** + * 根据整数字段长度解析 Java 类型。 + * + * @param columnLength 字段长度 + * @return Java 类型 + */ private static String resolveIntegerJavaType(Integer columnLength) { if (columnLength > 0 && columnLength <= 9) { return GenConstants.TYPE_INTEGER; @@ -166,6 +181,15 @@ public class GenUtils { return GenConstants.TYPE_LONG; } + /** + * 判断字段是否适合按布尔类型生成。 + * + * @param dataType 数据库字段类型 + * @param columnLength 字段长度 + * @param columnScale 小数位数 + * @param columnName 字段名称 + * @return 是否布尔字段 + */ private static boolean isBooleanColumn(String dataType, Integer columnLength, Integer columnScale, String columnName) { if (columnScale > 0) { return false; @@ -180,6 +204,12 @@ public class GenUtils { return false; } + /** + * 判断字段名称是否为开关类字段。 + * + * @param columnName 字段名称 + * @return 是否开关类字段 + */ private static boolean isSwitchColumn(String columnName) { return StringUtils.endsWithAny(columnName, "status", "flag", "enabled", "disabled", "available", "visible") || columnName.startsWith("is_") @@ -188,6 +218,12 @@ public class GenUtils { || columnName.startsWith("disable_"); } + /** + * 判断字段名称是否为排序字段。 + * + * @param columnName 字段名称 + * @return 是否排序字段 + */ private static boolean isSortColumn(String columnName) { return StringUtils.endsWithAny(columnName, "sort", "order_num", "order", "rank", "seq", "sequence"); } diff --git a/ruoyi-modules/ruoyi-gen/src/main/java/org/dromara/gen/util/TemplateEngineUtils.java b/ruoyi-modules/ruoyi-gen/src/main/java/org/dromara/gen/util/TemplateEngineUtils.java index e917502fa..2e60e2531 100644 --- a/ruoyi-modules/ruoyi-gen/src/main/java/org/dromara/gen/util/TemplateEngineUtils.java +++ b/ruoyi-modules/ruoyi-gen/src/main/java/org/dromara/gen/util/TemplateEngineUtils.java @@ -140,9 +140,9 @@ public class TemplateEngineUtils { /** * 向树形模板上下文写入树字段相关变量。 * - * @param context 模板上下文 - * @param genTable 代码生成业务表对象 - * @param paramsObj 已解析的 options 参数(避免重复解析) + * @param context 模板上下文 + * @param genTable 代码生成业务表对象 + * @param paramsObj 已解析的 options 参数(避免重复解析) */ public static void setTreeContext(Dict context, GenTable genTable, Dict paramsObj) { String treeCode = getTreeCode(paramsObj); @@ -328,7 +328,7 @@ public class TemplateEngineUtils { /** * 添加字典列表 * - * @param dicts 字典列表 + * @param dicts 字典列表 * @param columns 列集合 */ public static void addDicts(Set dicts, List columns) { @@ -408,7 +408,7 @@ public class TemplateEngineUtils { /** * 获取树根节点值。 * - * @param paramsObj 其他选项 + * @param paramsObj 其他选项 * @param treeParentColumn 父节点字段 * @return 树根节点值 */ @@ -423,6 +423,14 @@ public class TemplateEngineUtils { return defaultValue; } + /** + * 读取布尔类型生成选项。 + * + * @param paramsObj 生成选项 + * @param key 选项键 + * @param defaultValue 默认值 + * @return 选项值 + */ private static boolean getBooleanOption(Dict paramsObj, String key, boolean defaultValue) { if (CollUtil.isEmpty(paramsObj) || !paramsObj.containsKey(key)) { return defaultValue; @@ -430,6 +438,13 @@ public class TemplateEngineUtils { return Convert.toBool(paramsObj.get(key), defaultValue); } + /** + * 根据字段名查找业务表字段。 + * + * @param genTable 业务表 + * @param field 字段名称或 Java 属性名 + * @return 业务表字段 + */ private static GenTableColumn getColumn(GenTable genTable, String field) { if (StringUtils.isBlank(field) || CollUtil.isEmpty(genTable.getColumns())) { return null; @@ -442,6 +457,13 @@ public class TemplateEngineUtils { return null; } + /** + * 根据字段配置查找业务表字段列表。 + * + * @param genTable 业务表 + * @param fieldValues 字段配置值 + * @return 业务表字段列表 + */ private static List getColumns(GenTable genTable, Object fieldValues) { List fields = new ArrayList<>(); if (fieldValues instanceof Collection collection) { @@ -459,6 +481,13 @@ public class TemplateEngineUtils { return columns; } + /** + * 转换为 Java 字面量。 + * + * @param column 业务表字段 + * @param value 字段值 + * @return Java 字面量 + */ private static String getJavaLiteral(GenTableColumn column, String value) { if (ObjectUtil.isNull(column) || StringUtils.isBlank(value)) { return "null"; @@ -472,6 +501,13 @@ public class TemplateEngineUtils { return "\"" + value + "\""; } + /** + * 转换为 TypeScript 字面量。 + * + * @param column 业务表字段 + * @param value 字段值 + * @return TypeScript 字面量 + */ private static String getTsLiteral(GenTableColumn column, String value) { if (ObjectUtil.isNull(column) || StringUtils.isBlank(value)) { return "undefined"; diff --git a/ruoyi-modules/ruoyi-gen/src/main/java/org/dromara/gen/util/template/PathNamedTemplate.java b/ruoyi-modules/ruoyi-gen/src/main/java/org/dromara/gen/util/template/PathNamedTemplate.java index ded95dce8..43d041530 100644 --- a/ruoyi-modules/ruoyi-gen/src/main/java/org/dromara/gen/util/template/PathNamedTemplate.java +++ b/ruoyi-modules/ruoyi-gen/src/main/java/org/dromara/gen/util/template/PathNamedTemplate.java @@ -23,26 +23,56 @@ public class PathNamedTemplate implements Template { private final Template delegate; + /** + * 创建基于路径命名的模板。 + * + * @param pathName 路径名称 + * @param delegate 委托模板 + */ private PathNamedTemplate(String pathName, Template delegate) { this.pathName = pathName; this.delegate = delegate; } + /** + * 渲染模板到字符输出器。 + * + * @param bindingMap 模板绑定数据 + * @param writer 字符输出器 + */ @Override public void render(Map bindingMap, Writer writer) { delegate.render(bindingMap, writer); } + /** + * 渲染模板到输出流。 + * + * @param bindingMap 模板绑定数据 + * @param out 输出流 + */ @Override public void render(Map bindingMap, OutputStream out) { delegate.render(bindingMap, out); } + /** + * 渲染模板到文件。 + * + * @param bindingMap 模板绑定数据 + * @param file 输出文件 + */ @Override public void render(Map bindingMap, File file) { delegate.render(bindingMap, file); } + /** + * 渲染模板为字符串。 + * + * @param bindingMap 模板绑定数据 + * @return 渲染结果 + */ @Override public String render(Map bindingMap) { return delegate.render(bindingMap); @@ -66,8 +96,8 @@ public class PathNamedTemplate implements Template { * @param pathName 路径名称 * @return 带路径名称的模板 */ - public static PathNamedTemplate form(TemplateEngine templateEngine,String pathName) { - return new PathNamedTemplate(pathName,templateEngine.getTemplate(pathName)); + public static PathNamedTemplate form(TemplateEngine templateEngine, String pathName) { + return new PathNamedTemplate(pathName, templateEngine.getTemplate(pathName)); } /** diff --git a/ruoyi-modules/ruoyi-job/src/main/java/org/dromara/job/snailjob/TestBroadcastJob.java b/ruoyi-modules/ruoyi-job/src/main/java/org/dromara/job/snailjob/TestBroadcastJob.java index 690d835e5..a33d071d3 100644 --- a/ruoyi-modules/ruoyi-job/src/main/java/org/dromara/job/snailjob/TestBroadcastJob.java +++ b/ruoyi-modules/ruoyi-job/src/main/java/org/dromara/job/snailjob/TestBroadcastJob.java @@ -20,6 +20,9 @@ import org.springframework.stereotype.Component; @JobExecutor(name = "testBroadcastJob") public class TestBroadcastJob { + /** + * 客户端端口。 + */ @Value("${snail-job.port}") private int clientPort; diff --git a/ruoyi-modules/ruoyi-job/src/main/java/org/dromara/job/snailjob/TestClassJobExecutor.java b/ruoyi-modules/ruoyi-job/src/main/java/org/dromara/job/snailjob/TestClassJobExecutor.java index 93da0a903..6465dd234 100644 --- a/ruoyi-modules/ruoyi-job/src/main/java/org/dromara/job/snailjob/TestClassJobExecutor.java +++ b/ruoyi-modules/ruoyi-job/src/main/java/org/dromara/job/snailjob/TestClassJobExecutor.java @@ -12,6 +12,12 @@ import org.springframework.stereotype.Component; @Component public class TestClassJobExecutor extends AbstractJobExecutor { + /** + * 执行测试类任务。 + * + * @param jobArgs 任务参数 + * @return 任务执行结果 + */ @Override protected ExecuteResult doJobExecute(JobArgs jobArgs) { return ExecuteResult.success("TestJobExecutor测试成功"); diff --git a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/vo/MetaVo.java b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/vo/MetaVo.java index 5c5c98c0d..8d5e72b9a 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/vo/MetaVo.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/vo/MetaVo.java @@ -37,23 +37,51 @@ public class MetaVo { */ private String activeMenu; + /** + * 构造路由显示信息。 + * + * @param title 路由标题 + * @param icon 路由图标 + */ public MetaVo(String title, String icon) { this.title = title; this.icon = icon; } + /** + * 构造路由显示信息。 + * + * @param title 路由标题 + * @param icon 路由图标 + * @param noCache 是否不缓存 + */ public MetaVo(String title, String icon, Boolean noCache) { this.title = title; this.icon = icon; this.noCache = noCache; } + /** + * 构造带内链地址的路由显示信息。 + * + * @param title 路由标题 + * @param icon 路由图标 + * @param link 内链地址 + */ public MetaVo(String title, String icon, String link) { this.title = title; this.icon = icon; this.link = link; } + /** + * 构造带缓存配置和内链地址的路由显示信息。 + * + * @param title 路由标题 + * @param icon 路由图标 + * @param noCache 是否不缓存 + * @param link 内链地址 + */ public MetaVo(String title, String icon, Boolean noCache, String link) { this.title = title; this.icon = icon; @@ -63,6 +91,15 @@ public class MetaVo { } } + /** + * 构造带激活菜单的路由显示信息。 + * + * @param title 路由标题 + * @param icon 路由图标 + * @param noCache 是否不缓存 + * @param link 内链地址 + * @param activeMenu 激活菜单路径 + */ public MetaVo(String title, String icon, Boolean noCache, String link, String activeMenu) { this.title = title; this.icon = icon; diff --git a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/listener/DeptExcelConverter.java b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/listener/DeptExcelConverter.java index 5be4c6d26..d370c3dab 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/listener/DeptExcelConverter.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/listener/DeptExcelConverter.java @@ -37,6 +37,11 @@ public class DeptExcelConverter implements Converter { .expireAfterWrite(30, TimeUnit.SECONDS) .build(); + /** + * 获取部门导入导出映射缓存。 + * + * @return 部门 ID 与部门路径名称互转映射 + */ private DeptMaps getDeptMaps() { ISysDeptService deptService = SpringUtils.getBean(ISysDeptService.class); return DEPT_CACHE.get(CACHE_KEY, k -> { diff --git a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/listener/SysUserImportListener.java b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/listener/SysUserImportListener.java index 8f8f6ce39..db0361d67 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/listener/SysUserImportListener.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/listener/SysUserImportListener.java @@ -47,6 +47,11 @@ public class SysUserImportListener extends AnalysisEventListener getExcelResult() { return new ExcelResult<>() { + /** + * 获取导入结果分析消息。 + * + * @return 导入结果消息 + */ @Override public String getAnalysis() { if (failureNum > 0) { @@ -115,11 +141,21 @@ public class SysUserImportListener extends AnalysisEventListener getList() { return null; } + /** + * 获取导入错误信息列表。 + * + * @return 导入错误信息列表 + */ @Override public List getErrorList() { return null; diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/vo/FlowDefinitionVo.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/vo/FlowDefinitionVo.java index 841ca3bf2..ae28d722a 100644 --- a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/vo/FlowDefinitionVo.java +++ b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/vo/FlowDefinitionVo.java @@ -19,6 +19,9 @@ public class FlowDefinitionVo implements Serializable { @Serial private static final long serialVersionUID = 1L; + /** + * 流程定义主键 + */ private Long id; /** diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/vo/FlowHisTaskVo.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/vo/FlowHisTaskVo.java index e13080922..06a69d4c6 100644 --- a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/vo/FlowHisTaskVo.java +++ b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/vo/FlowHisTaskVo.java @@ -23,6 +23,9 @@ public class FlowHisTaskVo implements Serializable { @Serial private static final long serialVersionUID = 1L; + /** + * 历史任务主键 + */ private Long id; /** diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/listener/WorkflowGlobalListener.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/listener/WorkflowGlobalListener.java index 826990f1c..c2e597500 100644 --- a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/listener/WorkflowGlobalListener.java +++ b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/listener/WorkflowGlobalListener.java @@ -34,7 +34,11 @@ import org.dromara.workflow.service.IFlwNodeExtService; import org.dromara.workflow.service.IFlwTaskService; import org.springframework.stereotype.Component; -import java.util.*; +import java.io.Serial; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; /** * 工作流全局监听器,处理任务流转中的扩展变量、消息和事件发布。 @@ -48,6 +52,8 @@ import java.util.*; public class WorkflowGlobalListener implements GlobalListener { private static final String NODE_KEY_SEPARATOR = ":"; + @Serial + private static final long serialVersionUID = -5133036757491932497L; private final IFlwTaskService flwTaskService; private final IFlwInstanceService flwInstanceService; @@ -256,6 +262,14 @@ public class WorkflowGlobalListener implements GlobalListener { ); } + /** + * 判断是否需要发送后续待办消息。 + * + * @param flowParams 流程参数 + * @param definition 流程定义 + * @param nextTasks 后续任务列表 + * @return 是否发送待办消息 + */ private boolean shouldSendTaskMessage(FlowParams flowParams, Definition definition, List nextTasks) { if (flowParams == null || !TaskStatusEnum.BACK.getStatus().equals(flowParams.getHisStatus())) { return true; @@ -268,6 +282,14 @@ public class WorkflowGlobalListener implements GlobalListener { return !StringUtils.equals(applyNodeCode, nextTasks.get(0).getNodeCode()); } + /** + * 在流程完成或退回时通知发起人。 + * + * @param definition 流程定义 + * @param instance 流程实例 + * @param status 业务状态 + * @param variable 流程变量 + */ private void notifyInitiatorIfNeeded(Definition definition, Instance instance, String status, Map variable) { if (!StringUtils.equalsAny(status, BusinessStatusEnum.FINISH.getStatus(), BusinessStatusEnum.BACK.getStatus())) { return; diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/mapper/FlwHisTaskMapper.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/mapper/FlwHisTaskMapper.java index ca7d5fdd2..372c81ca0 100644 --- a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/mapper/FlwHisTaskMapper.java +++ b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/mapper/FlwHisTaskMapper.java @@ -24,6 +24,15 @@ import java.util.Map; */ public interface FlwHisTaskMapper extends BaseMapperPlus, MPJBaseMapper { + /** + * 分页查询已办任务列表。 + * + * @param page 分页对象 + * @param bo 查询条件 + * @param categoryIds 流程分类 ID 集合 + * @param userId 当前用户 ID + * @return 已办任务分页结果 + */ default Page getListFinishTask(Page page, FlowTaskBo bo, List categoryIds, String userId) { Map params = bo.getParams(); return QueryBuilder.lambdaJoin("a", FlowHisTask.class) diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/mapper/FlwTaskMapper.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/mapper/FlwTaskMapper.java index ceb96457e..4d58ad468 100644 --- a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/mapper/FlwTaskMapper.java +++ b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/mapper/FlwTaskMapper.java @@ -22,6 +22,15 @@ import java.util.Map; */ public interface FlwTaskMapper extends BaseMapperPlus, MPJBaseMapper { + /** + * 分页查询运行中的待办任务。 + * + * @param page 分页对象 + * @param bo 查询条件 + * @param categoryIds 流程分类 id 列表 + * @param userId 当前用户 id + * @return 待办任务分页结果 + */ default Page getListRunTask(Page page, FlowTaskBo bo, List categoryIds, String userId) { Map params = bo.getParams(); return QueryBuilder.lambdaJoin("t", FlowTask.class) @@ -54,6 +63,15 @@ public interface FlwTaskMapper extends BaseMapperPlus, MPJ .page(page, FlowTaskVo.class); } + /** + * 分页查询抄送任务。 + * + * @param page 分页对象 + * @param bo 查询条件 + * @param categoryIds 流程分类 id 列表 + * @param userId 当前用户 id + * @return 抄送任务分页结果 + */ default Page getTaskCopyByPage(Page page, FlowTaskBo bo, List categoryIds, String userId) { Map params = bo.getParams(); return QueryBuilder.lambdaJoin("a", FlowUser.class) diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/FlwCommonServiceImpl.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/FlwCommonServiceImpl.java index 7b0c50786..f610b217b 100644 --- a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/FlwCommonServiceImpl.java +++ b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/FlwCommonServiceImpl.java @@ -89,6 +89,14 @@ public class FlwCommonServiceImpl implements IFlwCommonService { sendMessage(messageType, message, subject, userList, null); } + /** + * 发送流程结果通知。 + * + * @param flowName 流程名称 + * @param status 业务状态 + * @param messageType 消息类型列表 + * @param userList 接收用户列表 + */ @Override public void sendResultMessage(String flowName, BusinessStatusEnum status, List messageType, List userList) { if (status == null || CollUtil.isEmpty(messageType) || CollUtil.isEmpty(userList)) { @@ -99,6 +107,15 @@ public class FlwCommonServiceImpl implements IFlwCommonService { sendMessage(messageType, message, DEFAULT_SUBJECT, userList, PATH_MY_DOCUMENT); } + /** + * 发送消息给指定用户列表。 + * + * @param messageType 消息类型列表 + * @param message 消息内容 + * @param subject 邮件标题 + * @param userList 接收用户列表 + * @param path 前端跳转路径 + */ @Override public void sendMessage(List messageType, String message, String subject, List userList, String path) { if (CollUtil.isEmpty(messageType) || CollUtil.isEmpty(userList)) { @@ -114,6 +131,17 @@ public class FlwCommonServiceImpl implements IFlwCommonService { ThreadUtils.virtualInvokeAll(sendTasks); } + /** + * 按消息类型执行具体发送逻辑。 + * + * @param code 消息类型编码 + * @param message 消息内容 + * @param subject 邮件标题 + * @param path 前端跳转路径 + * @param userIds 接收用户 id 列表 + * @param emails 接收邮箱集合 + * @param userCount 接收用户数量 + */ private void sendMessageByType(String code, String message, String subject, String path, List userIds, Set emails, int userCount) { MessageTypeEnum messageTypeEnum = MessageTypeEnum.getByCode(code); if (ObjectUtil.isEmpty(messageTypeEnum)) { diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/FlwInstanceServiceImpl.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/FlwInstanceServiceImpl.java index e1dccaae8..5065a325d 100644 --- a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/FlwInstanceServiceImpl.java +++ b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/FlwInstanceServiceImpl.java @@ -273,6 +273,11 @@ public class FlwInstanceServiceImpl implements IFlwInstanceService { } + /** + * 校验当前用户是否有权限删除流程实例,并发布删除事件。 + * + * @param flowInstances 待删除流程实例列表 + */ private void processDeleteHandler(List flowInstances) { String userId = LoginHelper.getUserIdStr(); diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/FlwTaskAssigneeServiceImpl.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/FlwTaskAssigneeServiceImpl.java index 76efa6366..de652c485 100644 --- a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/FlwTaskAssigneeServiceImpl.java +++ b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/FlwTaskAssigneeServiceImpl.java @@ -120,7 +120,7 @@ public class FlwTaskAssigneeServiceImpl implements IFlwTaskAssigneeService, Hand /** * 根据办理人类型查询右侧候选数据。 * - * @param type 办理人类型 + * @param type 办理人类型 * @param taskQuery 查询条件 * @return 办理人数据 */ @@ -180,7 +180,7 @@ public class FlwTaskAssigneeServiceImpl implements IFlwTaskAssigneeService, Hand /** * 构建设计器右侧办理人列表数据。 * - * @param dto 办理人数据 + * @param dto 办理人数据 * @param type 办理人类型 * @return 办理人列表构建器 */ @@ -218,6 +218,12 @@ public class FlwTaskAssigneeServiceImpl implements IFlwTaskAssigneeService, Hand .toList(); } + /** + * 按任务分配类型批量查询用户。 + * + * @param typeIdMap 任务分配类型与 id 列表映射 + * @return 用户列表 + */ private List getUsersByTypes(Map> typeIdMap) { return typeIdMap.entrySet().stream() .map(entry -> this.getUsersByType(entry.getKey(), entry.getValue())) @@ -226,6 +232,12 @@ public class FlwTaskAssigneeServiceImpl implements IFlwTaskAssigneeService, Hand .toList(); } + /** + * 按任务分配类型批量查询名称映射。 + * + * @param typeIdMap 任务分配类型与 id 列表映射 + * @return 任务分配类型与名称映射 + */ private Map> getNamesByTypes(Map> typeIdMap) { Map> nameMap = new EnumMap<>(TaskAssigneeEnum.class); typeIdMap.forEach((type, ids) -> nameMap.put(type, this.getNamesByType(type, ids)));