refactor(error): 优化自定义错误控制器实现

- 添加 SLF4J 日志记录功能
- 实现详细的错误信息提取和处理逻辑
- 增加对不同 HTTP 状态码的友好错误消息映射
- 添加错误日志记录,区分服务器错误和客户端错误
- 实现 getErrorPath 方法以符合 ErrorController 接口要求
- 添加详细的 JavaDoc 注释文档
This commit is contained in:
zkh
2026-02-14 12:39:40 +08:00
parent c0448ff6ab
commit 411565f812

View File

@ -2,6 +2,8 @@ package vip.jcfd.web.controller;
import jakarta.servlet.RequestDispatcher;
import jakarta.servlet.http.HttpServletRequest;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.web.servlet.error.ErrorController;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@ -9,15 +11,90 @@ import vip.jcfd.common.core.R;
import java.util.Optional;
/**
* 自定义错误控制器
* 重写 Spring MVC 默认的错误视图,返回 JSON 格式的错误响应
*/
@RestController
public class CustomErrorController implements ErrorController {
private static final Logger log = LoggerFactory.getLogger(CustomErrorController.class);
/**
* 处理错误请求
* 根据 HTTP 状态码返回相应的错误信息
*/
@RequestMapping("/error")
public R<?> handleError(HttpServletRequest request) {
// 获取状态码
int status = Optional.ofNullable(request.getAttribute(RequestDispatcher.ERROR_STATUS_CODE))
.map(Object::toString)
.map(Integer::parseInt)
.orElse(500);
return new R<>(status, "发生错误", false, null);
// 获取请求 URI
String requestUri = Optional.ofNullable(request.getAttribute(RequestDispatcher.ERROR_REQUEST_URI))
.map(Object::toString)
.orElse("unknown");
// 获取异常信息
String exceptionMessage = Optional.ofNullable(request.getAttribute(RequestDispatcher.ERROR_MESSAGE))
.map(Object::toString)
.orElse(null);
// 获取异常类型
String exceptionType = Optional.ofNullable(request.getAttribute(RequestDispatcher.ERROR_EXCEPTION_TYPE))
.map(Object::toString)
.orElse(null);
// 获取异常对象
Throwable throwable = Optional.ofNullable(request.getAttribute(RequestDispatcher.ERROR_EXCEPTION))
.filter(Throwable.class::isInstance)
.map(Throwable.class::cast)
.orElse(null);
// 记录错误日志
if (status >= 500) {
log.error("服务器错误 - 状态码: {}, 请求路径: {}, 异常类型: {}, 异常信息: {}",
status, requestUri, exceptionType, exceptionMessage, throwable);
} else if (status >= 400) {
log.warn("客户端错误 - 状态码: {}, 请求路径: {}, 异常信息: {}",
status, requestUri, exceptionMessage);
}
// 根据状态码获取友好的错误消息
String errorMessage = getErrorMessage(status, exceptionMessage);
return new R<>(status, errorMessage, false, null);
}
/**
* 根据状态码获取友好的错误消息
*/
private String getErrorMessage(int status, String originalMessage) {
if (originalMessage != null && !originalMessage.isEmpty()) {
return originalMessage;
}
return switch (status) {
case 400 -> "请求参数错误";
case 401 -> "未授权,请先登录";
case 403 -> "无权访问";
case 404 -> "您访问的地址不存在";
case 405 -> "请求方法不支持";
case 500 -> "服务器内部错误";
case 502 -> "网关错误";
case 503 -> "服务暂时不可用";
case 504 -> "网关超时";
default -> "请求失败";
};
}
/**
* 返回错误路径
* 实现 ErrorController 接口要求
*/
public String getErrorPath() {
return "/error";
}
}