# Conflicts:
#	pom.xml
#	yudao-dependencies/pom.xml
This commit is contained in:
YunaiV
2025-11-24 17:03:53 +08:00
50 changed files with 349 additions and 159 deletions

View File

@@ -1,10 +1,10 @@
package cn.iocoder.yudao.framework.common.util.json.databind;
import cn.hutool.core.util.ReflectUtil;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializerProvider;
import org.apache.commons.lang3.reflect.FieldUtils;
import java.io.IOException;
import java.lang.reflect.Field;
@@ -25,7 +25,7 @@ public class TimestampLocalDateTimeSerializer extends JsonSerializer<LocalDateTi
public void serialize(LocalDateTime value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
String fieldName = gen.getOutputContext().getCurrentName();
Class<?> clazz = gen.getOutputContext().getCurrentValue().getClass();
Field field = FieldUtils.getField(clazz, fieldName, true);
Field field = ReflectUtil.getField(clazz, fieldName);
// 情况一:有 JsonFormat 自定义注解则使用它。https://github.com/YunaiV/ruoyi-vue-pro/pull/1019
JsonFormat[] jsonFormats = field.getAnnotationsByType(JsonFormat.class);
if (jsonFormats.length > 0) {

View File

@@ -9,6 +9,7 @@ import org.springframework.web.multipart.MultipartFile;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
/**
@@ -44,9 +45,12 @@ public class ExcelUtils {
}
public static <T> List<T> read(MultipartFile file, Class<T> head) throws IOException {
return FastExcelFactory.read(file.getInputStream(), head, null)
.autoCloseStream(false) // 不要自动关闭,交给 Servlet 自己处理
.doReadAllSync();
// 参考 https://t.zsxq.com/zM77F 帖子,增加 try 处理,兼容 windows 场景
try (InputStream inputStream = file.getInputStream()) {
return FastExcelFactory.read(inputStream, head, null)
.autoCloseStream(false) // 不要自动关闭,交给 Servlet 自己处理
.doReadAllSync();
}
}
}

View File

@@ -9,7 +9,10 @@ import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.env.EnvironmentPostProcessor;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.core.env.MapPropertySource;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
/**
@@ -56,11 +59,19 @@ public class IdTypeEnvironmentPostProcessor implements EnvironmentPostProcessor
}
public IdType getIdType(ConfigurableEnvironment environment) {
return environment.getProperty(ID_TYPE_KEY, IdType.class);
String value = environment.getProperty(ID_TYPE_KEY);
try {
return StrUtil.isNotBlank(value) ? IdType.valueOf(value) : IdType.NONE;
} catch (IllegalArgumentException ex) {
log.error("[getIdType][无法解析 id-type 配置值({})]", value, ex);
return IdType.NONE;
}
}
public void setIdType(ConfigurableEnvironment environment, IdType idType) {
environment.getSystemProperties().put(ID_TYPE_KEY, idType);
Map<String, Object> map = new HashMap<>();
map.put(ID_TYPE_KEY, idType);
environment.getPropertySources().addFirst(new MapPropertySource("mybatisPlusIdType", map));
log.info("[setIdType][修改 MyBatis Plus 的 idType 为({})]", idType);
}

View File

@@ -68,6 +68,29 @@ public interface BaseMapperX<T> extends MPJBaseMapper<T> {
return new PageResult<>(mpPage.getRecords(), mpPage.getTotal());
}
/**
* 执行分页查询并返回结果。
*
* @param pageParam 分页参数,包含页码、每页条数和排序字段信息。如果 pageSize 为 {@link PageParam#PAGE_SIZE_NONE},则不分页,直接查询所有数据。
* @param clazz 结果集的类类型
* @param lambdaWrapper MyBatis Plus Join 查询条件包装器
* @param <D> 结果集的泛型类型
* @return 返回分页查询的结果,包括总记录数和当前页的数据列表
*/
default <D> PageResult<D> selectJoinPage(SortablePageParam pageParam, Class<D> clazz, MPJLambdaWrapper<T> lambdaWrapper) {
// 特殊:不分页,直接查询全部
if (PageParam.PAGE_SIZE_NONE.equals(pageParam.getPageSize())) {
List<D> list = selectJoinList(clazz, lambdaWrapper);
return new PageResult<>(list, (long) list.size());
}
// MyBatis Plus Join 查询
IPage<D> mpPage = MyBatisUtils.buildPage(pageParam, pageParam.getSortingFields());
mpPage = selectJoinPage(mpPage, clazz, lambdaWrapper);
// 转换返回
return new PageResult<>(mpPage.getRecords(), mpPage.getTotal());
}
default <DTO> PageResult<DTO> selectJoinPage(PageParam pageParam, Class<DTO> resultTypeClass, MPJBaseJoin<T> joinQueryWrapper) {
IPage<DTO> mpPage = MyBatisUtils.buildPage(pageParam);
selectJoinPage(mpPage, resultTypeClass, joinQueryWrapper);

View File

@@ -42,15 +42,16 @@ public class ApiEncryptResponseWrapper extends HttpServletResponseWrapper {
this.flushBuffer();
byte[] body = byteArrayOutputStream.toByteArray();
// 2. 加密 body
String encryptedBody = symmetricEncryptor != null ? symmetricEncryptor.encryptBase64(body)
: asymmetricEncryptor.encryptBase64(body, KeyType.PublicKey);
response.getWriter().write(encryptedBody);
// 3. 添加加密 header 标识
// 2. 添加加密 header 标识
this.addHeader(properties.getHeader(), "true");
// 特殊特殊https://juejin.cn/post/6867327674675625992
this.addHeader("Access-Control-Expose-Headers", properties.getHeader());
// 3.1 加密 body
String encryptedBody = symmetricEncryptor != null ? symmetricEncryptor.encryptBase64(body)
: asymmetricEncryptor.encryptBase64(body, KeyType.PublicKey);
// 3.2 输出加密后的 body设置 header 要放在 response 的 write 之前)
response.getWriter().write(encryptedBody);
}
@Override