Merge branch 'master-jdk17' of https://gitee.com/zhijiantianya/ruoyi-vue-pro into feature/iot

# Conflicts:
#	yudao-server/src/main/resources/application-local.yaml
This commit is contained in:
YunaiV
2024-09-07 20:37:57 +08:00
334 changed files with 6162 additions and 2642 deletions

View File

@ -32,6 +32,11 @@
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<scope>provided</scope> <!-- 解决工具类 SpringExpressionUtils 加载的时候访问不到 org.aspectj.lang.JoinPoint 问题 -->
</dependency>
<dependency>
<groupId>com.github.xiaoymin</groupId>

View File

@ -2,15 +2,10 @@ package cn.iocoder.yudao.framework.apilog.config;
import cn.iocoder.yudao.framework.apilog.core.filter.ApiAccessLogFilter;
import cn.iocoder.yudao.framework.apilog.core.interceptor.ApiAccessLogInterceptor;
import cn.iocoder.yudao.framework.apilog.core.service.ApiAccessLogFrameworkService;
import cn.iocoder.yudao.framework.apilog.core.service.ApiAccessLogFrameworkServiceImpl;
import cn.iocoder.yudao.framework.apilog.core.service.ApiErrorLogFrameworkService;
import cn.iocoder.yudao.framework.apilog.core.service.ApiErrorLogFrameworkServiceImpl;
import cn.iocoder.yudao.framework.common.enums.WebFilterOrderEnum;
import cn.iocoder.yudao.framework.web.config.WebProperties;
import cn.iocoder.yudao.framework.web.config.YudaoWebAutoConfiguration;
import cn.iocoder.yudao.module.infra.api.logger.ApiAccessLogApi;
import cn.iocoder.yudao.module.infra.api.logger.ApiErrorLogApi;
import jakarta.servlet.Filter;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.AutoConfiguration;
@ -23,18 +18,6 @@ import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@AutoConfiguration(after = YudaoWebAutoConfiguration.class)
public class YudaoApiLogAutoConfiguration implements WebMvcConfigurer {
@Bean
@SuppressWarnings("SpringJavaInjectionPointsAutowiringInspection")
public ApiAccessLogFrameworkService apiAccessLogFrameworkService(ApiAccessLogApi apiAccessLogApi) {
return new ApiAccessLogFrameworkServiceImpl(apiAccessLogApi);
}
@Bean
@SuppressWarnings("SpringJavaInjectionPointsAutowiringInspection")
public ApiErrorLogFrameworkService apiErrorLogFrameworkService(ApiErrorLogApi apiErrorLogApi) {
return new ApiErrorLogFrameworkServiceImpl(apiErrorLogApi);
}
/**
* 创建 ApiAccessLogFilter Bean记录 API 请求日志
*/
@ -42,8 +25,8 @@ public class YudaoApiLogAutoConfiguration implements WebMvcConfigurer {
@ConditionalOnProperty(prefix = "yudao.access-log", value = "enable", matchIfMissing = true) // 允许使用 yudao.access-log.enable=false 禁用访问日志
public FilterRegistrationBean<ApiAccessLogFilter> apiAccessLogFilter(WebProperties webProperties,
@Value("${spring.application.name}") String applicationName,
ApiAccessLogFrameworkService apiAccessLogFrameworkService) {
ApiAccessLogFilter filter = new ApiAccessLogFilter(webProperties, applicationName, apiAccessLogFrameworkService);
ApiAccessLogApi apiAccessLogApi) {
ApiAccessLogFilter filter = new ApiAccessLogFilter(webProperties, applicationName, apiAccessLogApi);
return createFilterBean(filter, WebFilterOrderEnum.API_ACCESS_LOG_FILTER);
}

View File

@ -9,7 +9,6 @@ import cn.hutool.core.util.BooleanUtil;
import cn.hutool.core.util.StrUtil;
import cn.iocoder.yudao.framework.apilog.core.annotation.ApiAccessLog;
import cn.iocoder.yudao.framework.apilog.core.enums.OperateTypeEnum;
import cn.iocoder.yudao.framework.apilog.core.service.ApiAccessLogFrameworkService;
import cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeConstants;
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
@ -18,6 +17,7 @@ import cn.iocoder.yudao.framework.common.util.servlet.ServletUtils;
import cn.iocoder.yudao.framework.web.config.WebProperties;
import cn.iocoder.yudao.framework.web.core.filter.ApiRequestFilter;
import cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils;
import cn.iocoder.yudao.module.infra.api.logger.ApiAccessLogApi;
import cn.iocoder.yudao.module.infra.api.logger.dto.ApiAccessLogCreateReqDTO;
import com.fasterxml.jackson.databind.JsonNode;
import io.swagger.v3.oas.annotations.Operation;
@ -36,7 +36,7 @@ import java.time.temporal.ChronoUnit;
import java.util.Iterator;
import java.util.Map;
import static cn.iocoder.yudao.framework.apilog.core.interceptor.ApiAccessLogInterceptor.*;
import static cn.iocoder.yudao.framework.apilog.core.interceptor.ApiAccessLogInterceptor.ATTRIBUTE_HANDLER_METHOD;
import static cn.iocoder.yudao.framework.common.util.json.JsonUtils.toJsonString;
/**
@ -53,12 +53,12 @@ public class ApiAccessLogFilter extends ApiRequestFilter {
private final String applicationName;
private final ApiAccessLogFrameworkService apiAccessLogFrameworkService;
private final ApiAccessLogApi apiAccessLogApi;
public ApiAccessLogFilter(WebProperties webProperties, String applicationName, ApiAccessLogFrameworkService apiAccessLogFrameworkService) {
public ApiAccessLogFilter(WebProperties webProperties, String applicationName, ApiAccessLogApi apiAccessLogApi) {
super(webProperties);
this.applicationName = applicationName;
this.apiAccessLogFrameworkService = apiAccessLogFrameworkService;
this.apiAccessLogApi = apiAccessLogApi;
}
@Override
@ -91,7 +91,7 @@ public class ApiAccessLogFilter extends ApiRequestFilter {
if (!enable) {
return;
}
apiAccessLogFrameworkService.createApiAccessLog(accessLog);
apiAccessLogApi.createApiAccessLogAsync(accessLog);
} catch (Throwable th) {
log.error("[createApiAccessLog][url({}) log({}) 发生异常]", request.getRequestURI(), toJsonString(accessLog), th);
}
@ -181,7 +181,7 @@ public class ApiAccessLogFilter extends ApiRequestFilter {
// ========== 请求和响应的脱敏逻辑,移除类似 password、token 等敏感字段 ==========
private static String sanitizeMap(Map<String, ?> map, String[] sanitizeKeys) {
if (CollUtil.isNotEmpty(map)) {
if (CollUtil.isEmpty(map)) {
return null;
}
if (sanitizeKeys != null) {

View File

@ -1,19 +0,0 @@
package cn.iocoder.yudao.framework.apilog.core.service;
import cn.iocoder.yudao.module.infra.api.logger.dto.ApiAccessLogCreateReqDTO;
/**
* API 访问日志 Framework Service 接口
*
* @author 芋道源码
*/
public interface ApiAccessLogFrameworkService {
/**
* 创建 API 访问日志
*
* @param reqDTO API 访问日志
*/
void createApiAccessLog(ApiAccessLogCreateReqDTO reqDTO);
}

View File

@ -1,33 +0,0 @@
package cn.iocoder.yudao.framework.apilog.core.service;
import cn.iocoder.yudao.module.infra.api.logger.ApiAccessLogApi;
import cn.iocoder.yudao.module.infra.api.logger.dto.ApiAccessLogCreateReqDTO;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.annotation.Async;
/**
* API 访问日志 Framework Service 实现类
*
* 基于 {@link ApiAccessLogApi} 服务,记录访问日志
*
* @author 芋道源码
*/
@RequiredArgsConstructor
@Slf4j
public class ApiAccessLogFrameworkServiceImpl implements ApiAccessLogFrameworkService {
private final ApiAccessLogApi apiAccessLogApi;
@Override
@Async
public void createApiAccessLog(ApiAccessLogCreateReqDTO reqDTO) {
try {
apiAccessLogApi.createApiAccessLog(reqDTO);
} catch (Throwable ex) {
// 由于 @Async 异步调用,这里打印下日志,更容易跟进
log.error("[createApiAccessLog][url({}) log({}) 发生异常]", reqDTO.getRequestUrl(), reqDTO, ex);
}
}
}

View File

@ -1,19 +0,0 @@
package cn.iocoder.yudao.framework.apilog.core.service;
import cn.iocoder.yudao.module.infra.api.logger.dto.ApiErrorLogCreateReqDTO;
/**
* API 错误日志 Framework Service 接口
*
* @author 芋道源码
*/
public interface ApiErrorLogFrameworkService {
/**
* 创建 API 错误日志
*
* @param reqDTO API 错误日志
*/
void createApiErrorLog(ApiErrorLogCreateReqDTO reqDTO);
}

View File

@ -1,33 +0,0 @@
package cn.iocoder.yudao.framework.apilog.core.service;
import cn.iocoder.yudao.module.infra.api.logger.ApiErrorLogApi;
import cn.iocoder.yudao.module.infra.api.logger.dto.ApiErrorLogCreateReqDTO;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.annotation.Async;
/**
* API 错误日志 Framework Service 实现类
*
* 基于 {@link ApiErrorLogApi} 服务,记录错误日志
*
* @author 芋道源码
*/
@RequiredArgsConstructor
@Slf4j
public class ApiErrorLogFrameworkServiceImpl implements ApiErrorLogFrameworkService {
private final ApiErrorLogApi apiErrorLogApi;
@Override
@Async
public void createApiErrorLog(ApiErrorLogCreateReqDTO reqDTO) {
try {
apiErrorLogApi.createApiErrorLog(reqDTO);
} catch (Throwable ex) {
// 由于 @Async 异步调用,这里打印下日志,更容易跟进
log.error("[createApiErrorLog][url({}) log({}) 发生异常]", reqDTO.getRequestUrl(), reqDTO, ex);
}
}
}

View File

@ -1,5 +1,7 @@
package cn.iocoder.yudao.framework.desensitize.core.base.handler;
import cn.hutool.core.util.ReflectUtil;
import java.lang.annotation.Annotation;
/**
@ -18,4 +20,21 @@ public interface DesensitizationHandler<T extends Annotation> {
*/
String desensitize(String origin, T annotation);
/**
* 是否禁用脱敏的 Spring EL 表达式
*
* 如果返回 true 则跳过脱敏
*
* @param annotation 注解信息
* @return 是否禁用脱敏的 Spring EL 表达式
*/
default String getDisable(T annotation) {
// 约定:默认就是 enable() 属性。如果不符合,子类重写
try {
return (String) ReflectUtil.invoke(annotation, "disable");
} catch (Exception ex) {
return "";
}
}
}

View File

@ -33,4 +33,12 @@ public @interface EmailDesensitize {
* 比如example@gmail.com 脱敏之后为 e****@gmail.com
*/
String replacer() default "$1****$2";
/**
* 是否禁用脱敏
*
* 支持 Spring EL 表达式,如果返回 true 则跳过脱敏
*/
String disable() default "";
}

View File

@ -35,4 +35,12 @@ public @interface RegexDesensitize {
* 脱敏后字符串 ******456789
*/
String replacer() default "******";
/**
* 是否禁用脱敏
*
* 支持 Spring EL 表达式,如果返回 true 则跳过脱敏
*/
String disable() default "";
}

View File

@ -1,5 +1,6 @@
package cn.iocoder.yudao.framework.desensitize.core.regex.handler;
import cn.iocoder.yudao.framework.common.util.spring.SpringExpressionUtils;
import cn.iocoder.yudao.framework.desensitize.core.base.handler.DesensitizationHandler;
import java.lang.annotation.Annotation;
@ -14,6 +15,13 @@ public abstract class AbstractRegexDesensitizationHandler<T extends Annotation>
@Override
public String desensitize(String origin, T annotation) {
// 1. 判断是否禁用脱敏
Object disable = SpringExpressionUtils.parseExpression(getDisable(annotation));
if (Boolean.TRUE.equals(disable)) {
return origin;
}
// 2. 执行脱敏
String regex = getRegex(annotation);
String replacer = getReplacer(annotation);
return origin.replaceAll(regex, replacer);

View File

@ -18,4 +18,10 @@ public class DefaultRegexDesensitizationHandler extends AbstractRegexDesensitiza
String getReplacer(RegexDesensitize annotation) {
return annotation.replacer();
}
@Override
public String getDisable(RegexDesensitize annotation) {
return annotation.disable();
}
}

View File

@ -37,4 +37,11 @@ public @interface BankCardDesensitize {
*/
String replacer() default "*";
/**
* 是否禁用脱敏
*
* 支持 Spring EL 表达式,如果返回 true 则跳过脱敏
*/
String disable() default "";
}

View File

@ -37,4 +37,11 @@ public @interface CarLicenseDesensitize {
*/
String replacer() default "*";
/**
* 是否禁用脱敏
*
* 支持 Spring EL 表达式,如果返回 true 则跳过脱敏
*/
String disable() default "";
}

View File

@ -37,4 +37,11 @@ public @interface ChineseNameDesensitize {
*/
String replacer() default "*";
/**
* 是否禁用脱敏
*
* 支持 Spring EL 表达式,如果返回 true 则跳过脱敏
*/
String disable() default "";
}

View File

@ -37,4 +37,11 @@ public @interface FixedPhoneDesensitize {
*/
String replacer() default "*";
/**
* 是否禁用脱敏
*
* 支持 Spring EL 表达式,如果返回 true 则跳过脱敏
*/
String disable() default "";
}

View File

@ -37,4 +37,11 @@ public @interface IdCardDesensitize {
*/
String replacer() default "*";
/**
* 是否禁用脱敏
*
* 支持 Spring EL 表达式,如果返回 true 则跳过脱敏
*/
String disable() default "";
}

View File

@ -37,4 +37,11 @@ public @interface MobileDesensitize {
*/
String replacer() default "*";
/**
* 是否禁用脱敏
*
* 支持 Spring EL 表达式,如果返回 true 则跳过脱敏
*/
String disable() default "";
}

View File

@ -39,4 +39,11 @@ public @interface PasswordDesensitize {
*/
String replacer() default "*";
/**
* 是否禁用脱敏
*
* 支持 Spring EL 表达式,如果返回 true 则跳过脱敏
*/
String disable() default "";
}

View File

@ -40,4 +40,12 @@ public @interface SliderDesensitize {
* 前缀保留长度
*/
int prefixKeep() default 0;
/**
* 是否禁用脱敏
*
* 支持 Spring EL 表达式,如果返回 true 则跳过脱敏
*/
String disable() default "";
}

View File

@ -1,5 +1,6 @@
package cn.iocoder.yudao.framework.desensitize.core.slider.handler;
import cn.iocoder.yudao.framework.common.util.spring.SpringExpressionUtils;
import cn.iocoder.yudao.framework.desensitize.core.base.handler.DesensitizationHandler;
import java.lang.annotation.Annotation;
@ -14,6 +15,13 @@ public abstract class AbstractSliderDesensitizationHandler<T extends Annotation>
@Override
public String desensitize(String origin, T annotation) {
// 1. 判断是否禁用脱敏
Object disable = SpringExpressionUtils.parseExpression(getDisable(annotation));
if (Boolean.FALSE.equals(disable)) {
return origin;
}
// 2. 执行脱敏
int prefixKeep = getPrefixKeep(annotation);
int suffixKeep = getSuffixKeep(annotation);
String replacer = getReplacer(annotation);

View File

@ -24,4 +24,9 @@ public class BankCardDesensitization extends AbstractSliderDesensitizationHandle
return annotation.replacer();
}
@Override
public String getDisable(BankCardDesensitize annotation) {
return "";
}
}

View File

@ -8,6 +8,7 @@ import cn.iocoder.yudao.framework.desensitize.core.slider.annotation.CarLicenseD
* @author gaibu
*/
public class CarLicenseDesensitization extends AbstractSliderDesensitizationHandler<CarLicenseDesensitize> {
@Override
Integer getPrefixKeep(CarLicenseDesensitize annotation) {
return annotation.prefixKeep();
@ -22,4 +23,10 @@ public class CarLicenseDesensitization extends AbstractSliderDesensitizationHand
String getReplacer(CarLicenseDesensitize annotation) {
return annotation.replacer();
}
@Override
public String getDisable(CarLicenseDesensitize annotation) {
return annotation.disable();
}
}

View File

@ -8,6 +8,7 @@ import cn.iocoder.yudao.framework.desensitize.core.slider.annotation.SliderDesen
* @author gaibu
*/
public class DefaultDesensitizationHandler extends AbstractSliderDesensitizationHandler<SliderDesensitize> {
@Override
Integer getPrefixKeep(SliderDesensitize annotation) {
return annotation.prefixKeep();
@ -22,4 +23,5 @@ public class DefaultDesensitizationHandler extends AbstractSliderDesensitization
String getReplacer(SliderDesensitize annotation) {
return annotation.replacer();
}
}

View File

@ -8,6 +8,7 @@ import cn.iocoder.yudao.framework.desensitize.core.slider.annotation.FixedPhoneD
* @author gaibu
*/
public class FixedPhoneDesensitization extends AbstractSliderDesensitizationHandler<FixedPhoneDesensitize> {
@Override
Integer getPrefixKeep(FixedPhoneDesensitize annotation) {
return annotation.prefixKeep();
@ -22,4 +23,5 @@ public class FixedPhoneDesensitization extends AbstractSliderDesensitizationHand
String getReplacer(FixedPhoneDesensitize annotation) {
return annotation.replacer();
}
}

View File

@ -22,4 +22,5 @@ public class IdCardDesensitization extends AbstractSliderDesensitizationHandler<
String getReplacer(IdCardDesensitize annotation) {
return annotation.replacer();
}
}

View File

@ -23,4 +23,5 @@ public class MobileDesensitization extends AbstractSliderDesensitizationHandler<
String getReplacer(MobileDesensitize annotation) {
return annotation.replacer();
}
}

View File

@ -22,4 +22,5 @@ public class PasswordDesensitization extends AbstractSliderDesensitizationHandle
String getReplacer(PasswordDesensitize annotation) {
return annotation.replacer();
}
}

View File

@ -1,12 +1,14 @@
package cn.iocoder.yudao.framework.web.config;
import cn.iocoder.yudao.framework.apilog.core.service.ApiErrorLogFrameworkService;
import cn.iocoder.yudao.framework.common.enums.WebFilterOrderEnum;
import cn.iocoder.yudao.framework.web.core.filter.CacheRequestBodyFilter;
import cn.iocoder.yudao.framework.web.core.filter.DemoFilter;
import cn.iocoder.yudao.framework.web.core.handler.GlobalExceptionHandler;
import cn.iocoder.yudao.framework.web.core.handler.GlobalResponseBodyHandler;
import cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils;
import cn.iocoder.yudao.module.infra.api.logger.ApiErrorLogApi;
import jakarta.annotation.Resource;
import jakarta.servlet.Filter;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.AutoConfiguration;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
@ -25,9 +27,6 @@ import org.springframework.web.filter.CorsFilter;
import org.springframework.web.servlet.config.annotation.PathMatchConfigurer;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import jakarta.annotation.Resource;
import jakarta.servlet.Filter;
@AutoConfiguration
@EnableConfigurationProperties(WebProperties.class)
public class YudaoWebAutoConfiguration implements WebMvcConfigurer {
@ -59,8 +58,9 @@ public class YudaoWebAutoConfiguration implements WebMvcConfigurer {
}
@Bean
public GlobalExceptionHandler globalExceptionHandler(ApiErrorLogFrameworkService ApiErrorLogFrameworkService) {
return new GlobalExceptionHandler(applicationName, ApiErrorLogFrameworkService);
@SuppressWarnings("SpringJavaInjectionPointsAutowiringInspection")
public GlobalExceptionHandler globalExceptionHandler(ApiErrorLogApi apiErrorLogApi) {
return new GlobalExceptionHandler(applicationName, apiErrorLogApi);
}
@Bean

View File

@ -4,7 +4,7 @@ import cn.hutool.core.exceptions.ExceptionUtil;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.ObjUtil;
import cn.hutool.core.util.StrUtil;
import cn.iocoder.yudao.framework.apilog.core.service.ApiErrorLogFrameworkService;
import cn.hutool.extra.servlet.JakartaServletUtil;
import cn.iocoder.yudao.framework.common.exception.ServiceException;
import cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil;
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
@ -13,14 +13,16 @@ import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
import cn.iocoder.yudao.framework.common.util.monitor.TracerUtils;
import cn.iocoder.yudao.framework.common.util.servlet.ServletUtils;
import cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils;
import cn.iocoder.yudao.module.infra.api.logger.ApiErrorLogApi;
import cn.iocoder.yudao.module.infra.api.logger.dto.ApiErrorLogCreateReqDTO;
import com.fasterxml.jackson.databind.exc.InvalidFormatException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.validation.ConstraintViolation;
import jakarta.validation.ConstraintViolationException;
import jakarta.validation.ValidationException;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.exception.ExceptionUtils;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.util.Assert;
import org.springframework.validation.BindException;
@ -58,7 +60,7 @@ public class GlobalExceptionHandler {
@SuppressWarnings("SpringJavaInjectionPointsAutowiringInspection")
private final String applicationName;
private final ApiErrorLogFrameworkService apiErrorLogFrameworkService;
private final ApiErrorLogApi apiErrorLogApi;
/**
* 处理所有异常,主要是提供给 Filter 使用
@ -88,7 +90,7 @@ public class GlobalExceptionHandler {
return validationException((ValidationException) ex);
}
if (ex instanceof NoHandlerFoundException) {
return noHandlerFoundExceptionHandler(request, (NoHandlerFoundException) ex);
return noHandlerFoundExceptionHandler((NoHandlerFoundException) ex);
}
if (ex instanceof NoResourceFoundException) {
return noResourceFoundExceptionHandler(request, (NoResourceFoundException) ex);
@ -123,7 +125,7 @@ public class GlobalExceptionHandler {
*/
@ExceptionHandler(MethodArgumentTypeMismatchException.class)
public CommonResult<?> methodArgumentTypeMismatchExceptionHandler(MethodArgumentTypeMismatchException ex) {
log.warn("[missingServletRequestParameterExceptionHandler]", ex);
log.warn("[methodArgumentTypeMismatchExceptionHandler]", ex);
return CommonResult.error(BAD_REQUEST.getCode(), String.format("请求参数类型错误:%s", ex.getMessage()));
}
@ -149,6 +151,22 @@ public class GlobalExceptionHandler {
return CommonResult.error(BAD_REQUEST.getCode(), String.format("请求参数不正确:%s", fieldError.getDefaultMessage()));
}
/**
* 处理 SpringMVC 请求参数类型错误
*
* 例如说,接口上设置了 @RequestBody实体中 xx 属性类型为 Integer结果传递 xx 参数类型为 String
*/
@ExceptionHandler(HttpMessageNotReadableException.class)
public CommonResult<?> methodArgumentTypeInvalidFormatExceptionHandler(HttpMessageNotReadableException ex) {
log.warn("[methodArgumentTypeInvalidFormatExceptionHandler]", ex);
if(ex.getCause() instanceof InvalidFormatException) {
InvalidFormatException invalidFormatException = (InvalidFormatException) ex.getCause();
return CommonResult.error(BAD_REQUEST.getCode(), String.format("请求参数类型错误:%s", invalidFormatException.getValue()));
}else {
return defaultExceptionHandler(ServletUtils.getRequest(), ex);
}
}
/**
* 处理 Validator 校验不通过产生的异常
*/
@ -177,7 +195,7 @@ public class GlobalExceptionHandler {
* 2. spring.mvc.static-path-pattern 为 /statics/**
*/
@ExceptionHandler(NoHandlerFoundException.class)
public CommonResult<?> noHandlerFoundExceptionHandler(HttpServletRequest req, NoHandlerFoundException ex) {
public CommonResult<?> noHandlerFoundExceptionHandler(NoHandlerFoundException ex) {
log.warn("[noHandlerFoundExceptionHandler]", ex);
return CommonResult.error(NOT_FOUND.getCode(), String.format("请求地址不存在:%s", ex.getRequestURL()));
}
@ -253,7 +271,7 @@ public class GlobalExceptionHandler {
// 情况二:处理异常
log.error("[defaultExceptionHandler]", ex);
// 插入异常日志
this.createExceptionLog(req, ex);
createExceptionLog(req, ex);
// 返回 ERROR CommonResult
return CommonResult.error(INTERNAL_SERVER_ERROR.getCode(), INTERNAL_SERVER_ERROR.getMsg());
}
@ -265,7 +283,7 @@ public class GlobalExceptionHandler {
// 初始化 errorLog
buildExceptionLog(errorLog, req, e);
// 执行插入 errorLog
apiErrorLogFrameworkService.createApiErrorLog(errorLog);
apiErrorLogApi.createApiErrorLogAsync(errorLog);
} catch (Throwable th) {
log.error("[createExceptionLog][url({}) log({}) 发生异常]", req.getRequestURI(), JsonUtils.toJsonString(errorLog), th);
}
@ -279,7 +297,7 @@ public class GlobalExceptionHandler {
errorLog.setExceptionName(e.getClass().getName());
errorLog.setExceptionMessage(ExceptionUtil.getMessage(e));
errorLog.setExceptionRootCauseMessage(ExceptionUtil.getRootCauseMessage(e));
errorLog.setExceptionStackTrace(ExceptionUtils.getStackTrace(e));
errorLog.setExceptionStackTrace(ExceptionUtil.stacktraceToString(e));
StackTraceElement[] stackTraceElements = e.getStackTrace();
Assert.notEmpty(stackTraceElements, "异常 stackTraceElements 不能为空");
StackTraceElement stackTraceElement = stackTraceElements[0];
@ -292,12 +310,12 @@ public class GlobalExceptionHandler {
errorLog.setApplicationName(applicationName);
errorLog.setRequestUrl(request.getRequestURI());
Map<String, Object> requestParams = MapUtil.<String, Object>builder()
.put("query", ServletUtils.getParamMap(request))
.put("body", ServletUtils.getBody(request)).build();
.put("query", JakartaServletUtil.getParamMap(request))
.put("body", JakartaServletUtil.getBody(request)).build();
errorLog.setRequestParams(JsonUtils.toJsonString(requestParams));
errorLog.setRequestMethod(request.getMethod());
errorLog.setUserAgent(ServletUtils.getUserAgent(request));
errorLog.setUserIp(ServletUtils.getClientIP(request));
errorLog.setUserIp(JakartaServletUtil.getClientIP(request));
errorLog.setExceptionTime(LocalDateTime.now());
}
@ -314,51 +332,51 @@ public class GlobalExceptionHandler {
}
// 1. 数据报表
if (message.contains("report_")) {
log.error("[报表模块 yudao-module-report - 表结构未导入][参考 https://doc.iocoder.cn/report/ 开启]");
log.error("[报表模块 yudao-module-report - 表结构未导入][参考 https://cloud.iocoder.cn/report/ 开启]");
return CommonResult.error(NOT_IMPLEMENTED.getCode(),
"[报表模块 yudao-module-report - 表结构未导入][参考 https://doc.iocoder.cn/report/ 开启]");
"[报表模块 yudao-module-report - 表结构未导入][参考 https://cloud.iocoder.cn/report/ 开启]");
}
// 2. 工作流
if (message.contains("bpm_")) {
log.error("[工作流模块 yudao-module-bpm - 表结构未导入][参考 https://doc.iocoder.cn/bpm/ 开启]");
log.error("[工作流模块 yudao-module-bpm - 表结构未导入][参考 https://cloud.iocoder.cn/bpm/ 开启]");
return CommonResult.error(NOT_IMPLEMENTED.getCode(),
"[工作流模块 yudao-module-bpm - 表结构未导入][参考 https://doc.iocoder.cn/bpm/ 开启]");
"[工作流模块 yudao-module-bpm - 表结构未导入][参考 https://cloud.iocoder.cn/bpm/ 开启]");
}
// 3. 微信公众号
if (message.contains("mp_")) {
log.error("[微信公众号 yudao-module-mp - 表结构未导入][参考 https://doc.iocoder.cn/mp/build/ 开启]");
log.error("[微信公众号 yudao-module-mp - 表结构未导入][参考 https://cloud.iocoder.cn/mp/build/ 开启]");
return CommonResult.error(NOT_IMPLEMENTED.getCode(),
"[微信公众号 yudao-module-mp - 表结构未导入][参考 https://doc.iocoder.cn/mp/build/ 开启]");
"[微信公众号 yudao-module-mp - 表结构未导入][参考 https://cloud.iocoder.cn/mp/build/ 开启]");
}
// 4. 商城系统
if (StrUtil.containsAny(message, "product_", "promotion_", "trade_")) {
log.error("[商城系统 yudao-module-mall - 已禁用][参考 https://doc.iocoder.cn/mall/build/ 开启]");
log.error("[商城系统 yudao-module-mall - 已禁用][参考 https://cloud.iocoder.cn/mall/build/ 开启]");
return CommonResult.error(NOT_IMPLEMENTED.getCode(),
"[商城系统 yudao-module-mall - 已禁用][参考 https://doc.iocoder.cn/mall/build/ 开启]");
"[商城系统 yudao-module-mall - 已禁用][参考 https://cloud.iocoder.cn/mall/build/ 开启]");
}
// 5. ERP 系统
if (message.contains("erp_")) {
log.error("[ERP 系统 yudao-module-erp - 表结构未导入][参考 https://doc.iocoder.cn/erp/build/ 开启]");
log.error("[ERP 系统 yudao-module-erp - 表结构未导入][参考 https://cloud.iocoder.cn/erp/build/ 开启]");
return CommonResult.error(NOT_IMPLEMENTED.getCode(),
"[ERP 系统 yudao-module-erp - 表结构未导入][参考 https://doc.iocoder.cn/erp/build/ 开启]");
"[ERP 系统 yudao-module-erp - 表结构未导入][参考 https://cloud.iocoder.cn/erp/build/ 开启]");
}
// 6. CRM 系统
if (message.contains("crm_")) {
log.error("[CRM 系统 yudao-module-crm - 表结构未导入][参考 https://doc.iocoder.cn/crm/build/ 开启]");
log.error("[CRM 系统 yudao-module-crm - 表结构未导入][参考 https://cloud.iocoder.cn/crm/build/ 开启]");
return CommonResult.error(NOT_IMPLEMENTED.getCode(),
"[CRM 系统 yudao-module-crm - 表结构未导入][参考 https://doc.iocoder.cn/crm/build/ 开启]");
"[CRM 系统 yudao-module-crm - 表结构未导入][参考 https://cloud.iocoder.cn/crm/build/ 开启]");
}
// 7. 支付平台
if (message.contains("pay_")) {
log.error("[支付模块 yudao-module-pay - 表结构未导入][参考 https://doc.iocoder.cn/pay/build/ 开启]");
log.error("[支付模块 yudao-module-pay - 表结构未导入][参考 https://cloud.iocoder.cn/pay/build/ 开启]");
return CommonResult.error(NOT_IMPLEMENTED.getCode(),
"[支付模块 yudao-module-pay - 表结构未导入][参考 https://doc.iocoder.cn/pay/build/ 开启]");
"[支付模块 yudao-module-pay - 表结构未导入][参考 https://cloud.iocoder.cn/pay/build/ 开启]");
}
// 8. AI 大模型
if (message.contains("ai_")) {
log.error("[AI 大模型 yudao-module-ai - 表结构未导入][参考 https://doc.iocoder.cn/ai/build/ 开启]");
log.error("[AI 大模型 yudao-module-ai - 表结构未导入][参考 https://cloud.iocoder.cn/ai/build/ 开启]");
return CommonResult.error(NOT_IMPLEMENTED.getCode(),
"[AI 大模型 yudao-module-ai - 表结构未导入][参考 https://doc.iocoder.cn/ai/build/ 开启]");
"[AI 大模型 yudao-module-ai - 表结构未导入][参考 https://cloud.iocoder.cn/ai/build/ 开启]");
}
// 9. IOT 物联网
if (message.contains("iot_")) {