|
|
@@ -0,0 +1,112 @@
|
|
|
+package com.platform.exception;
|
|
|
+
|
|
|
+
|
|
|
+import com.platform.enums.ErrorCodeEnum;
|
|
|
+import jakarta.servlet.http.HttpServletRequest;
|
|
|
+import jakarta.validation.ConstraintViolation;
|
|
|
+import jakarta.validation.ConstraintViolationException;
|
|
|
+import lombok.extern.slf4j.Slf4j;
|
|
|
+import org.springframework.dao.DataAccessException;
|
|
|
+import org.springframework.util.CollectionUtils;
|
|
|
+import org.springframework.validation.BindingResult;
|
|
|
+import org.springframework.validation.FieldError;
|
|
|
+import org.springframework.web.bind.MethodArgumentNotValidException;
|
|
|
+import org.springframework.web.bind.annotation.ExceptionHandler;
|
|
|
+import org.springframework.web.bind.annotation.ResponseBody;
|
|
|
+import org.springframework.web.bind.annotation.RestControllerAdvice;
|
|
|
+
|
|
|
+import java.util.Set;
|
|
|
+
|
|
|
+/**
|
|
|
+ * Author: donglang
|
|
|
+ * Time: 2025-10-16
|
|
|
+ * Des: 全局异常处理器
|
|
|
+ * Version: 1.0
|
|
|
+ */
|
|
|
+
|
|
|
+@RestControllerAdvice
|
|
|
+@Slf4j
|
|
|
+public class GlobalExceptionHandler {
|
|
|
+
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 理自定义业务异常(IotException)
|
|
|
+ * 场景:查询不到数据、数据过期、子表不存在等
|
|
|
+ */
|
|
|
+ @ExceptionHandler(IotException.class)
|
|
|
+ public BaseResult<Void> handlerIotException(IotException e, HttpServletRequest request) {
|
|
|
+ // 打印异常日志
|
|
|
+ log.warn("业务异常,请求路径:{},错误码:{}, 消息:{}", request.getRequestURI(), e.getErrorCode(), e.getMessage());
|
|
|
+ return BaseResult.error(e.getErrorCode(), e.getMessage());
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 处理参数校验异常(@Validated 触发)
|
|
|
+ * 场景:车牌为空、运单号为空等参数错误
|
|
|
+ */
|
|
|
+ @ExceptionHandler(MethodArgumentNotValidException.class)
|
|
|
+ public BaseResult<Void> handleValidationException(MethodArgumentNotValidException e, HttpServletRequest request) {
|
|
|
+ BindingResult bindingResult = e.getBindingResult();
|
|
|
+ // 拼接所有参数错误信息(如“车牌不能为空;运单号不能为空”)
|
|
|
+ StringBuilder errorMsg = new StringBuilder();
|
|
|
+
|
|
|
+ for (FieldError fieldError : bindingResult.getFieldErrors()) {
|
|
|
+ errorMsg.append(fieldError.getDefaultMessage()).append(";");
|
|
|
+
|
|
|
+ }
|
|
|
+ String finalMsg = !errorMsg.isEmpty() ? errorMsg.substring(0, errorMsg.length() - 1) : "参数校验失败";
|
|
|
+ // 打印异常日志
|
|
|
+ log.warn("参数校验异常,请求路径:{}, 消息:{}", request.getRequestURI(), finalMsg);
|
|
|
+ // 返回参数错误响应
|
|
|
+ return BaseResult.error(ErrorCodeEnum.PARAM_ERROR.getCode(), finalMsg);
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 处理数据库相关异常(时序库/关系库操作失败)
|
|
|
+ * 场景:查询时序库时SQL错误、连接超时等
|
|
|
+ */
|
|
|
+ @ExceptionHandler({DataAccessException.class, java.sql.SQLException.class})
|
|
|
+ public BaseResult<Void> handleDbException(Exception e, HttpServletRequest request) {
|
|
|
+ // 打印异常日志
|
|
|
+ log.warn("数据库异常,请求路径:{}, 原因:{}", request.getRequestURI(), e.getMessage(), e);
|
|
|
+ return BaseResult.error(ErrorCodeEnum.DB_OPERATE_FAIL.getCode(), "数据库操作失败,请稍后重试");
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 处理系统通用异常(未被上述方法捕获的异常)
|
|
|
+ * 场景:空指针、数组越界等未知错误
|
|
|
+ */
|
|
|
+ @ExceptionHandler(Exception.class)
|
|
|
+ public BaseResult<Void> handleSystemException(Exception e, HttpServletRequest request) {
|
|
|
+ // 打印异常日志
|
|
|
+ log.warn("数据库异常,请求路径:{}, 原因:{}", request.getRequestURI(), e.getMessage(), e);
|
|
|
+ return BaseResult.error(ErrorCodeEnum.SYSTEM_ERROR.getCode(), "系统内部错误,请联系管理员");
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 处理非请求体参数校验异常
|
|
|
+ * 场景:queryRealTimeLocation方法的carNo为空(加了@NotBlank)
|
|
|
+ */
|
|
|
+ @ResponseBody
|
|
|
+ @ExceptionHandler(ConstraintViolationException.class)
|
|
|
+ public BaseResult<Object> constraintViolationExceptionHandler(ConstraintViolationException e, HttpServletRequest request) {
|
|
|
+ Set<ConstraintViolation<?>> constraintViolations = e.getConstraintViolations();
|
|
|
+ StringBuilder errorMsg = new StringBuilder();
|
|
|
+ if (!CollectionUtils.isEmpty(constraintViolations)) {
|
|
|
+ boolean first = true;
|
|
|
+ for (ConstraintViolation<?> constraintViolation : constraintViolations) {
|
|
|
+ if (!first) {
|
|
|
+ errorMsg.append(",");
|
|
|
+ }
|
|
|
+ errorMsg.append(constraintViolation.getMessage());
|
|
|
+ first = false;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ // 打印异常日志
|
|
|
+ log.warn("数据库异常,请求路径:{}, 原因:{}", request.getRequestURI(), e.getMessage());
|
|
|
+ return BaseResult.error(ErrorCodeEnum.PARAM_ERROR.getCode(), errorMsg.toString());
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+}
|