Spring Boot 404等容器级异常处理
404等容器级异常不经过Controller层,无法被@ControllerAdvice捕获,需通过ErrorController机制处理。
问题分析
Java
@RestControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(NoHandlerFoundException.class)
public Result handle404(NoHandlerFoundException e) {
return Result.fail(404, "资源不存在");
}
}
// 默认情况下,404异常不会触发此处理器
// 因为DispatcherServlet没有找到Handler就返回了
解决方案
方案一:启用NoHandlerFoundException
YAML
# application.yml
spring:
mvc:
throw-exception-if-no-handler-found: true
web:
resources:
add-mappings: false # 禁用静态资源默认处理
Java
@RestControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(NoHandlerFoundException.class)
public ResponseEntity<Result> handle404(NoHandlerFoundException e) {
return ResponseEntity.status(404)
.body(Result.fail(404, "接口不存在: " + e.getRequestURL()));
}
}
方案二:自定义ErrorController
Java
@RestController
@RequestMapping("${server.error.path:${error.path:/error}}")
public class CustomErrorController implements ErrorController {
@Autowired
private ErrorAttributes errorAttributes;
@GetMapping
public ResponseEntity<Result> error(HttpServletRequest request) {
Map<String, Object> error = errorAttributes.getErrorAttributes(
new ServletWebRequest(request), ErrorAttributeOptions.defaults());
int status = (int) error.get("status");
String message = (String) error.get("message");
return ResponseEntity.status(status)
.body(Result.fail(status, message));
}
}
方案三:自定义ErrorAttributes
Java
@Component
public class CustomErrorAttributes extends DefaultErrorAttributes {
@Override
public Map<String, Object> getErrorAttributes(WebRequest webRequest,
ErrorAttributeOptions options) {
Map<String, Object> attrs = super.getErrorAttributes(webRequest, options);
// 自定义错误信息
attrs.put("code", attrs.get("status"));
attrs.put("message", attrs.get("error"));
attrs.put("path", attrs.get("path"));
// 移除默认字段
attrs.remove("status");
attrs.remove("error");
return attrs;
}
}
server.error配置
YAML
server:
error:
path: /error # 错误处理路径
include-message: always # 返回message
include-binding-errors: always # 返回绑定错误
include-stacktrace: on-param # 堆栈信息:never/always/on-param
include-exception: false # 不返回exception类名
whitelabel:
enabled: false # 禁用默认白标签错误页
常见容器级异常
| 状态码 | 异常类型 | 说明 |
|---|---|---|
| 404 | NoHandlerFoundException | 未找到处理器 |
| 405 | HttpRequestMethodNotSupportedException | 请求方法不支持 |
| 406 | HttpMediaTypeNotAcceptableException | 媒体类型不可接受 |
| 415 | HttpMediaTypeNotSupportedException | 媒体类型不支持 |
| 500 | InternalServerErrorException | 服务器内部错误 |
Java
@RestControllerAdvice
public class ContainerExceptionHandler {
@ExceptionHandler(HttpRequestMethodNotSupportedException.class)
public Result handle405(HttpRequestMethodNotSupportedException e) {
return Result.fail(405, "不支持" + e.getMethod() + "请求方法");
}
@ExceptionHandler(HttpMediaTypeNotSupportedException.class)
public Result handle415(HttpMediaTypeNotSupportedException e) {
return Result.fail(415, "不支持的媒体类型: " + e.getContentType());
}
}
要点总结
- 404等容器级异常需启用throw-exception-if-no-handler-found
- 自定义ErrorController统一处理容器级错误
- ErrorAttributes定制错误响应内容
- server.error配置控制错误信息展示
- HTTP方法、媒体类型异常可被@ControllerAdvice捕获
📝 发现内容有误?点击此处直接编辑