全部学科
Python全栈
python
NodeJS全栈
nodejs
小程序首页
📅 2026-05-18 8 分钟 ✍️ juanwangdev

异常处理机制

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结果。

要点总结

  1. HandlerExceptionResolver接口定义异常处理契约
  2. @ExceptionHandler方法可定义在Controller或@ControllerAdvice中
  3. 异常匹配遵循最近原则,优先匹配精确异常类型
  4. @ControllerAdvice实现全局异常处理,统一管理异常响应
  5. DefaultHandlerExceptionResolver兜底处理Spring标准异常

jwdev/articles/SPRINGMVC/专家/MVC核心源码执行流程/MVC核心源码执行流程/异常处理机制.md

📝 发现内容有误?点击此处直接编辑

← 上一篇 响应数据转换与渲染
下一篇 → 拦截器执行顺序
想查看更多题目和详细解析?
小程序提供完整的题库、模拟考试和详细解析
马上就来

长按或扫描二维码,立即体验

扫码体验小程序
马上就来
使用微信扫描二维码
立即体验完整题库