异常处理机制
SpringMVC提供统一的异常处理机制,将异常转换为友好的响应结果。
异常处理入口
Java
// DispatcherServlet统一异常捕获
protected void doDispatch(HttpServletRequest request,
HttpServletResponse response) {
try {
// Handler执行
mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
} catch (Exception ex) {
// 统一异常处理
dispatchException = ex;
}
// 处理异常结果
processDispatchResult(request, response, mappedHandler, mv, dispatchException);
}
HandlerExceptionResolver接口
Java
public interface HandlerExceptionResolver {
@Nullable
ModelAndView resolveException(HttpServletRequest request,
HttpServletResponse response,
@Nullable Object handler,
Exception ex);
}
核心实现类
| 实现类 | 作用 | 优先级 |
|---|---|---|
| ExceptionHandlerExceptionResolver | 处理@ExceptionHandler | 最高 |
| ResponseStatusExceptionResolver | 处理@ResponseStatus | 中 |
| DefaultHandlerExceptionResolver | 处理Spring标准异常 | 低 |
@ExceptionHandler处理流程
ExceptionHandlerExceptionResolver源码
Java
public class ExceptionHandlerExceptionResolver
extends AbstractHandlerMethodExceptionResolver {
protected ModelAndView doResolveHandlerMethodException(
HttpServletRequest request, HttpServletResponse response,
HandlerMethod handlerMethod, Exception exception) {
// 查找匹配的@ExceptionHandler方法
ServletInvocableHandlerMethod exceptionHandlerMethod =
getExceptionHandlerMethod(handlerMethod, exception);
if (exceptionHandlerMethod == null) {
return null;
}
// 调用异常处理方法
exceptionHandlerMethod.invokeAndHandle(webRequest, mavContainer, exception);
return getModelAndView(mavContainer, model, webRequest);
}
}
查找异常处理方法
Java
protected ServletInvocableHandlerMethod getExceptionHandlerMethod(
HandlerMethod handlerMethod, Exception exception) {
Class<?> handlerType = handlerMethod.getBeanType();
// 1. 先在当前Controller查找
Map<ControllerAdviceBean, ExceptionHandlerMethodResolver> adviceMap =
this.exceptionHandlerAdviceCache;
for (Map.Entry<ControllerAdviceBean, ExceptionHandlerMethodResolver> entry :
adviceMap.entrySet()) {
ControllerAdviceBean advice = entry.getKey();
if (advice.isApplicableToBeanType(handlerType)) {
ExceptionHandlerMethodResolver resolver = entry.getValue();
Method method = resolver.resolveMethod(exception);
if (method != null) {
return new ServletInvocableHandlerMethod(advice.resolveBean(), method);
}
}
}
return null;
}
@ControllerAdvice全局异常处理
Java
@ControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(BusinessException.class)
public ResponseEntity<Result> handleBusinessException(BusinessException ex) {
return ResponseEntity.status(ex.getCode())
.body(Result.fail(ex.getMessage()));
}
@ExceptionHandler(MethodArgumentNotValidException.class)
public ResponseEntity<Result> handleValidationException(
MethodArgumentNotValidException ex) {
String message = ex.getBindingResult().getFieldErrors().stream()
.map(FieldError::getDefaultMessage)
.collect(Collectors.joining(", "));
return ResponseEntity.badRequest().body(Result.fail(message));
}
@ExceptionHandler(Exception.class)
public ResponseEntity<Result> handleException(Exception ex) {
log.error("系统异常", ex);
return ResponseEntity.internalServerError()
.body(Result.fail("系统异常"));
}
}
异常匹配规则
Java
// ExceptionHandlerMethodResolver - 异常匹配逻辑
public Method resolveMethod(Exception exception) {
Method method = this.exceptionLookupCache.get(exception.getClass());
if (method == null) {
method = getMappedMethod(exception.getClass());
}
return method;
}
private Method getMappedMethod(Class<? extends Exception> exceptionType) {
// 遍历异常继承链查找最匹配的方法
for (Class<?> exceptionClass : this.mappedExceptions) {
if (exceptionClass.isAssignableFrom(exceptionType)) {
return this.mappedMethods.get(exceptionClass);
}
}
return null;
}
ResponseStatusExceptionResolver
Java
// 处理@ResponseStatus注解
protected ModelAndView doResolveException(HttpServletRequest request,
HttpServletResponse response, Object handler, Exception ex) {
ResponseStatus status = AnnotatedElementUtils.findMergedAnnotation(
ex.getClass(), ResponseStatus.class);
if (status != null) {
int statusCode = status.code().value();
String reason = status.reason();
response.setStatus(statusCode);
return new ModelAndView();
}
return null;
}
DefaultHandlerExceptionResolver
Java
// 处理Spring标准异常
protected ModelAndView doResolveException(HttpServletRequest request,
HttpServletResponse response, Object handler, Exception ex) {
if (ex instanceof HttpRequestMethodNotSupportedException) {
return handleHttpRequestMethodNotSupported(
(HttpRequestMethodNotSupportedException) ex, response);
}
if (ex instanceof HttpMediaTypeNotSupportedException) {
return handleHttpMediaTypeNotSupported(
(HttpMediaTypeNotSupportedException) ex, response);
}
if (ex instanceof MissingServletRequestParameterException) {
return handleMissingServletRequestParameter(
(MissingServletRequestParameterException) ex, response);
}
// ... 更多标准异常
return null;
}
异常处理流程图
text
Controller抛出异常
↓
DispatcherServlet捕获
↓
遍历HandlerExceptionResolver列表
↓
ExceptionHandlerExceptionResolver
→ 查找@ExceptionHandler方法
→ 执行并返回ModelAndView
↓ (未处理)
ResponseStatusExceptionResolver
→ 检查@ResponseStatus注解
→ 设置响应状态码
↓ (未处理)
DefaultHandlerExceptionResolver
→ 处理Spring标准异常
↓
渲染错误视图或返回错误响应
异常处理通过责任链模式,按优先级依次尝试处理,直到某个Resolver返回非null结果。
要点总结
- HandlerExceptionResolver接口定义异常处理契约
- @ExceptionHandler方法可定义在Controller或@ControllerAdvice中
- 异常匹配遵循最近原则,优先匹配精确异常类型
- @ControllerAdvice实现全局异常处理,统一管理异常响应
- DefaultHandlerExceptionResolver兜底处理Spring标准异常
jwdev/articles/SPRINGMVC/专家/MVC核心源码执行流程/MVC核心源码执行流程/异常处理机制.md
📝 发现内容有误?点击此处直接编辑