@ -4,6 +4,7 @@ import cn.hutool.core.exceptions.ExceptionUtil;
import cn.hutool.core.map.MapUtil ;
import cn.hutool.core.map.MapUtil ;
import cn.hutool.core.util.ObjUtil ;
import cn.hutool.core.util.ObjUtil ;
import cn.hutool.core.util.StrUtil ;
import cn.hutool.core.util.StrUtil ;
import cn.hutool.extra.servlet.JakartaServletUtil ;
import cn.iocoder.yudao.framework.apilog.core.service.ApiErrorLogFrameworkService ;
import cn.iocoder.yudao.framework.apilog.core.service.ApiErrorLogFrameworkService ;
import cn.iocoder.yudao.framework.common.exception.ServiceException ;
import cn.iocoder.yudao.framework.common.exception.ServiceException ;
import cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil ;
import cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil ;
@ -14,13 +15,14 @@ import cn.iocoder.yudao.framework.common.util.monitor.TracerUtils;
import cn.iocoder.yudao.framework.common.util.servlet.ServletUtils ;
import cn.iocoder.yudao.framework.common.util.servlet.ServletUtils ;
import cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils ;
import cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils ;
import cn.iocoder.yudao.module.infra.api.logger.dto.ApiErrorLogCreateReqDTO ;
import cn.iocoder.yudao.module.infra.api.logger.dto.ApiErrorLogCreateReqDTO ;
import com.fasterxml.jackson.databind.exc.InvalidFormatException ;
import jakarta.servlet.http.HttpServletRequest ;
import jakarta.servlet.http.HttpServletRequest ;
import jakarta.validation.ConstraintViolation ;
import jakarta.validation.ConstraintViolation ;
import jakarta.validation.ConstraintViolationException ;
import jakarta.validation.ConstraintViolationException ;
import jakarta.validation.ValidationException ;
import jakarta.validation.ValidationException ;
import lombok.AllArgsConstructor ;
import lombok.AllArgsConstructor ;
import lombok.extern.slf4j.Slf4j ;
import lombok.extern.slf4j.Slf4j ;
import org.apache.commons.lang3.exception. ExceptionUtils ;
import org.springframework.http.converter.HttpMessageNotReadable Exception ;
import org.springframework.security.access.AccessDeniedException ;
import org.springframework.security.access.AccessDeniedException ;
import org.springframework.util.Assert ;
import org.springframework.util.Assert ;
import org.springframework.validation.BindException ;
import org.springframework.validation.BindException ;
@ -38,7 +40,12 @@ import java.time.LocalDateTime;
import java.util.Map ;
import java.util.Map ;
import java.util.Set ;
import java.util.Set ;
import static cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeConstants.* ;
import static cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeConstants.BAD_REQUEST ;
import static cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeConstants.FORBIDDEN ;
import static cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeConstants.INTERNAL_SERVER_ERROR ;
import static cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeConstants.METHOD_NOT_ALLOWED ;
import static cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeConstants.NOT_FOUND ;
import static cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeConstants.NOT_IMPLEMENTED ;
/**
/**
* 全局异常处理器,将 Exception 翻译成 CommonResult + 对应的异常编号
* 全局异常处理器,将 Exception 翻译成 CommonResult + 对应的异常编号
@ -88,7 +95,7 @@ public class GlobalExceptionHandler {
return validationException ( ( ValidationException ) ex ) ;
return validationException ( ( ValidationException ) ex ) ;
}
}
if ( ex instanceof NoHandlerFoundException ) {
if ( ex instanceof NoHandlerFoundException ) {
return noHandlerFoundExceptionHandler ( request , ( NoHandlerFoundException ) ex ) ;
return noHandlerFoundExceptionHandler ( ( NoHandlerFoundException ) ex ) ;
}
}
if ( ex instanceof NoResourceFoundException ) {
if ( ex instanceof NoResourceFoundException ) {
return noResourceFoundExceptionHandler ( request , ( NoResourceFoundException ) ex ) ;
return noResourceFoundExceptionHandler ( request , ( NoResourceFoundException ) ex ) ;
@ -123,7 +130,7 @@ public class GlobalExceptionHandler {
*/
*/
@ExceptionHandler ( MethodArgumentTypeMismatchException . class )
@ExceptionHandler ( MethodArgumentTypeMismatchException . class )
public CommonResult < ? > methodArgumentTypeMismatchExceptionHandler ( MethodArgumentTypeMismatchException ex ) {
public CommonResult < ? > methodArgumentTypeMismatchExceptionHandler ( MethodArgumentTypeMismatchException ex ) {
log . warn ( " [missingServletRequestParameter ExceptionHandler] " , ex ) ;
log . warn ( " [methodArgumentTypeMismatch ExceptionHandler] " , ex ) ;
return CommonResult . error ( BAD_REQUEST . getCode ( ) , String . format ( " 请求参数类型错误:%s " , ex . getMessage ( ) ) ) ;
return CommonResult . error ( BAD_REQUEST . getCode ( ) , String . format ( " 请求参数类型错误:%s " , ex . getMessage ( ) ) ) ;
}
}
@ -149,6 +156,22 @@ public class GlobalExceptionHandler {
return CommonResult . error ( BAD_REQUEST . getCode ( ) , String . format ( " 请求参数不正确:%s " , fieldError . getDefaultMessage ( ) ) ) ;
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 校验不通过产生的异常
* 处理 Validator 校验不通过产生的异常
*/
*/
@ -177,7 +200,7 @@ public class GlobalExceptionHandler {
* 2. spring.mvc.static-path-pattern 为 /statics/**
* 2. spring.mvc.static-path-pattern 为 /statics/**
*/
*/
@ExceptionHandler ( NoHandlerFoundException . class )
@ExceptionHandler ( NoHandlerFoundException . class )
public CommonResult < ? > noHandlerFoundExceptionHandler ( HttpServletRequest req , NoHandlerFoundException ex ) {
public CommonResult < ? > noHandlerFoundExceptionHandler ( NoHandlerFoundException ex ) {
log . warn ( " [noHandlerFoundExceptionHandler] " , ex ) ;
log . warn ( " [noHandlerFoundExceptionHandler] " , ex ) ;
return CommonResult . error ( NOT_FOUND . getCode ( ) , String . format ( " 请求地址不存在:%s " , ex . getRequestURL ( ) ) ) ;
return CommonResult . error ( NOT_FOUND . getCode ( ) , String . format ( " 请求地址不存在:%s " , ex . getRequestURL ( ) ) ) ;
}
}
@ -253,7 +276,7 @@ public class GlobalExceptionHandler {
// 情况二:处理异常
// 情况二:处理异常
log . error ( " [defaultExceptionHandler] " , ex ) ;
log . error ( " [defaultExceptionHandler] " , ex ) ;
// 插入异常日志
// 插入异常日志
this . createExceptionLog( req , ex ) ;
createExceptionLog( req , ex ) ;
// 返回 ERROR CommonResult
// 返回 ERROR CommonResult
return CommonResult . error ( INTERNAL_SERVER_ERROR . getCode ( ) , INTERNAL_SERVER_ERROR . getMsg ( ) ) ;
return CommonResult . error ( INTERNAL_SERVER_ERROR . getCode ( ) , INTERNAL_SERVER_ERROR . getMsg ( ) ) ;
}
}
@ -279,7 +302,7 @@ public class GlobalExceptionHandler {
errorLog . setExceptionName ( e . getClass ( ) . getName ( ) ) ;
errorLog . setExceptionName ( e . getClass ( ) . getName ( ) ) ;
errorLog . setExceptionMessage ( ExceptionUtil . getMessage ( e ) ) ;
errorLog . setExceptionMessage ( ExceptionUtil . getMessage ( e ) ) ;
errorLog . setExceptionRootCauseMessage ( ExceptionUtil . getRootCauseMessage ( e ) ) ;
errorLog . setExceptionRootCauseMessage ( ExceptionUtil . getRootCauseMessage ( e ) ) ;
errorLog . setExceptionStackTrace ( ExceptionUtils . getS tackT race( e ) ) ;
errorLog . setExceptionStackTrace ( ExceptionUtil . s tackt raceToString ( e ) ) ;
StackTraceElement [ ] stackTraceElements = e . getStackTrace ( ) ;
StackTraceElement [ ] stackTraceElements = e . getStackTrace ( ) ;
Assert . notEmpty ( stackTraceElements , " 异常 stackTraceElements 不能为空 " ) ;
Assert . notEmpty ( stackTraceElements , " 异常 stackTraceElements 不能为空 " ) ;
StackTraceElement stackTraceElement = stackTraceElements [ 0 ] ;
StackTraceElement stackTraceElement = stackTraceElements [ 0 ] ;
@ -292,12 +315,12 @@ public class GlobalExceptionHandler {
errorLog . setApplicationName ( applicationName ) ;
errorLog . setApplicationName ( applicationName ) ;
errorLog . setRequestUrl ( request . getRequestURI ( ) ) ;
errorLog . setRequestUrl ( request . getRequestURI ( ) ) ;
Map < String , Object > requestParams = MapUtil . < String , Object > builder ( )
Map < String , Object > requestParams = MapUtil . < String , Object > builder ( )
. put ( " query " , ServletUtils . getParamMap ( request ) )
. put ( " query " , Jakarta ServletUtil. getParamMap ( request ) )
. put ( " body " , ServletUtils . getBody ( request ) ) . build ( ) ;
. put ( " body " , Jakarta ServletUtil. getBody ( request ) ) . build ( ) ;
errorLog . setRequestParams ( JsonUtils . toJsonString ( requestParams ) ) ;
errorLog . setRequestParams ( JsonUtils . toJsonString ( requestParams ) ) ;
errorLog . setRequestMethod ( request . getMethod ( ) ) ;
errorLog . setRequestMethod ( request . getMethod ( ) ) ;
errorLog . setUserAgent ( ServletUtils . getUserAgent ( request ) ) ;
errorLog . setUserAgent ( ServletUtils . getUserAgent ( request ) ) ;
errorLog . setUserIp ( ServletUtils . getClientIP ( request ) ) ;
errorLog . setUserIp ( Jakarta ServletUtil. getClientIP ( request ) ) ;
errorLog . setExceptionTime ( LocalDateTime . now ( ) ) ;
errorLog . setExceptionTime ( LocalDateTime . now ( ) ) ;
}
}
@ -314,51 +337,51 @@ public class GlobalExceptionHandler {
}
}
// 1. 数据报表
// 1. 数据报表
if ( message . contains ( " report_ " ) ) {
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 ( ) ,
return CommonResult . error ( NOT_IMPLEMENTED . getCode ( ) ,
" [报表模块 yudao-module-report - 表结构未导入][参考 https://doc .iocoder.cn/report/ 开启] " ) ;
" [报表模块 yudao-module-report - 表结构未导入][参考 https://cloud .iocoder.cn/report/ 开启] " ) ;
}
}
// 2. 工作流
// 2. 工作流
if ( message . contains ( " bpm_ " ) ) {
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 ( ) ,
return CommonResult . error ( NOT_IMPLEMENTED . getCode ( ) ,
" [工作流模块 yudao-module-bpm - 表结构未导入][参考 https://doc .iocoder.cn/bpm/ 开启] " ) ;
" [工作流模块 yudao-module-bpm - 表结构未导入][参考 https://cloud .iocoder.cn/bpm/ 开启] " ) ;
}
}
// 3. 微信公众号
// 3. 微信公众号
if ( message . contains ( " mp_ " ) ) {
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 ( ) ,
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. 商城系统
// 4. 商城系统
if ( StrUtil . containsAny ( message , " product_ " , " promotion_ " , " trade_ " ) ) {
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 ( ) ,
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 系统
// 5. ERP 系统
if ( message . contains ( " 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 ( ) ,
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 系统
// 6. CRM 系统
if ( message . contains ( " 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 ( ) ,
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. 支付平台
// 7. 支付平台
if ( message . contains ( " pay_ " ) ) {
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 ( ) ,
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 大模型
// 8. AI 大模型
if ( message . contains ( " 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 ( ) ,
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/ 开启] " ) ;
}
}
return null ;
return null ;
}
}