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

异常处理HandlerExceptionResolver

HandlerExceptionResolver定义了SpringMVC异常处理的标准接口,可扩展实现自定义异常处理逻辑。

接口定义

Java
public interface HandlerExceptionResolver {
    @Nullable
    ModelAndView resolveException(HttpServletRequest request,
            HttpServletResponse response,
            @Nullable Object handler,
            Exception ex);
}

内置实现类

实现类功能优先级
ExceptionHandlerExceptionResolver处理@ExceptionHandler方法1
ResponseStatusExceptionResolver处理@ResponseStatus注解2
DefaultHandlerExceptionResolver处理Spring标准异常3
SimpleMappingExceptionResolver异常映射到视图4

自定义HandlerExceptionResolver

实现方式

Java
@Component
public class CustomExceptionResolver implements HandlerExceptionResolver, Ordered {

    @Override
    public ModelAndView resolveException(HttpServletRequest request,
            HttpServletResponse response, Object handler, Exception ex) {

        // 处理自定义异常
        if (ex instanceof BusinessException) {
            BusinessException be = (BusinessException) ex;
            response.setStatus(be.getCode());
            response.setContentType("application/json;charset=UTF-8");

            try {
                response.getWriter().write(
                    "{\"code\":\"" + be.getCode() + "\",\"message\":\"" + be.getMessage() + "\"}");
            } catch (IOException e) {
                log.error("写入响应失败", e);
            }
            return new ModelAndView(); // 空ModelAndView表示已处理
        }

        return null; // null表示不处理,交给下一个Resolver
    }

    @Override
    public int getOrder() {
        return 0; // 最高优先级
    }
}

注册自定义Resolver

Java
@Configuration
public class WebConfig implements WebMvcConfigurer {
    @Override
    public void extendHandlerExceptionResolvers(List<HandlerExceptionResolver> resolvers) {
        // 添加到解析器链前端
        resolvers.add(0, new CustomExceptionResolver());
    }
}

ExceptionHandlerExceptionResolver详解

核心逻辑

Java
public class ExceptionHandlerExceptionResolver
        extends AbstractHandlerMethodExceptionResolver {

    // 异常处理方法缓存
    private final Map<Class<?>, ExceptionHandlerMethodResolver> exceptionHandlerCache =
        new ConcurrentHashMap<>(64);

    // @ControllerAdvice缓存
    private final Map<ControllerAdviceBean, ExceptionHandlerMethodResolver>
        exceptionHandlerAdviceCache = new LinkedHashMap<>();

    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查找@ExceptionHandler
    ExceptionHandlerMethodResolver resolver =
        this.exceptionHandlerCache.get(handlerType);
    if (resolver == null) {
        resolver = new ExceptionHandlerMethodResolver(handlerType);
        this.exceptionHandlerCache.put(handlerType, resolver);
    }
    Method method = resolver.resolveMethod(exception);
    if (method != null) {
        return new ServletInvocableHandlerMethod(handlerMethod.getBean(), method);
    }

    // 2. 在@ControllerAdvice中查找
    for (Map.Entry<ControllerAdviceBean, ExceptionHandlerMethodResolver> entry :
             this.exceptionHandlerAdviceCache.entrySet()) {
        ControllerAdviceBean advice = entry.getKey();
        if (advice.isApplicableToBeanType(handlerType)) {
            ExceptionHandlerMethodResolver adviceResolver = entry.getValue();
            Method adviceMethod = adviceResolver.resolveMethod(exception);
            if (adviceMethod != null) {
                return new ServletInvocableHandlerMethod(advice.resolveBean(), adviceMethod);
            }
        }
    }
    return null;
}

ResponseStatusExceptionResolver

Java
public class ResponseStatusExceptionResolver
        extends AbstractHandlerExceptionResolver {

    protected ModelAndView resolveResponseStatus(ResponseStatus responseStatus,
            HttpServletRequest request, HttpServletResponse response,
            Object handler, Exception ex) throws IOException {

        int statusCode = responseStatus.code().value();
        String reason = responseStatus.reason();

        if (StringUtils.hasLength(reason)) {
            response.sendError(statusCode, reason);
        } else {
            response.setStatus(statusCode);
        }

        return new ModelAndView();
    }
}

// 使用示例
@ResponseStatus(code = HttpStatus.NOT_FOUND, reason = "资源不存在")
public class ResourceNotFoundException extends RuntimeException {
}

DefaultHandlerExceptionResolver

Java
public class DefaultHandlerExceptionResolver
        extends AbstractHandlerExceptionResolver {

    protected ModelAndView doResolveException(HttpServletRequest request,
            HttpServletResponse response, Object handler, Exception ex) {

        try {
            // HTTP方法不支持
            if (ex instanceof HttpRequestMethodNotSupportedException) {
                return handleHttpRequestMethodNotSupported(
                    (HttpRequestMethodNotSupportedException) ex, request, response);
            }

            // Media类型不支持
            if (ex instanceof HttpMediaTypeNotSupportedException) {
                return handleHttpMediaTypeNotSupported(
                    (HttpMediaTypeNotSupportedException) ex, response);
            }

            // 缺少必填参数
            if (ex instanceof MissingServletRequestParameterException) {
                return handleMissingServletRequestParameter(
                    (MissingServletRequestParameterException) ex, response);
            }

            // 类型转换异常
            if (ex instanceof TypeMismatchException) {
                return handleTypeMismatch((TypeMismatchException) ex, response);
            }

            // 参数绑定异常
            if (ex instanceof BindException) {
                return handleBindException((BindException) ex, response);
            }

            // 更多标准异常处理...
            return null;
        } catch (IOException handlerException) {
            return null;
        }
    }
}

SimpleMappingExceptionResolver

Java
@Configuration
public class WebConfig implements WebMvcConfigurer {
    @Bean
    public SimpleMappingExceptionResolver simpleMappingExceptionResolver() {
        SimpleMappingExceptionResolver resolver = new SimpleMappingExceptionResolver();

        Properties mappings = new Properties();
        mappings.setProperty("BusinessException", "error/business");
        mappings.setProperty("DataAccessException", "error/data");
        mappings.setProperty("Exception", "error/general");

        resolver.setExceptionMappings(mappings);
        resolver.setDefaultErrorView("error/default");
        resolver.setExceptionAttribute("exception");

        return resolver;
    }
}

异常处理链执行顺序

Java
// DispatcherServlet
protected ModelAndView processHandlerException(HttpServletRequest request,
        HttpServletResponse response, Object handler, Exception ex) {

    ModelAndView mav = null;

    // 遍历所有HandlerExceptionResolver
    for (HandlerExceptionResolver resolver : this.handlerExceptionResolvers) {
        mav = resolver.resolveException(request, response, handler, ex);
        if (mav != null) {
            break; // 找到处理结果后停止
        }
    }

    // 所有Resolver都未处理
    if (mav == null) {
        throw new ServletException("Could not resolve exception", ex);
    }

    return mav;
}

扩展点总结

扩展方式适用场景说明
@ExceptionHandlerController内异常处理粒度细,只处理当前Controller异常
@ControllerAdvice全局异常处理统一管理,支持限定Controller范围
自定义Resolver特殊异常处理逻辑完全控制异常响应格式

异常处理优先级图

text
异常抛出
    ↓
遍历HandlerExceptionResolver链
    ↓
CustomExceptionResolver (order=0)
    ↓ (返回null)
ExceptionHandlerExceptionResolver
    ↓ 查找@ExceptionHandler
    ↓ 执行处理方法
    ↓ (返回null)
ResponseStatusExceptionResolver
    ↓ 处理@ResponseStatus
    ↓ (返回null)
DefaultHandlerExceptionResolver
    ↓ 处理Spring标准异常
    ↓ (返回null)
抛出ServletException

HandlerExceptionResolver按优先级顺序执行,返回非null表示已处理。

要点总结

  1. HandlerExceptionResolver接口定义异常处理契约
  2. 返回null表示不处理,交给下一个Resolver
  3. ExceptionHandlerExceptionResolver处理@ExceptionHandler方法
  4. 自定义Resolver可实现完全的异常响应控制
  5. 多个Resolver形成责任链,按Order顺序执行

jwdev/articles/SPRINGMVC/专家/容器级WEB组件扩展/容器级WEB组件扩展/异常处理HandlerExceptionResolver.md

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

← 上一篇 SpringMVC容器初始化与DispatcherServlet
下一篇 → 拦截器Interceptor
想查看更多题目和详细解析?
小程序提供完整的题库、模拟考试和详细解析
马上就来

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

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