设为首页 加入收藏

TOP

java 拦截、过滤器2(一)
2023-07-26 08:17:45 】 浏览:157
Tags:java 拦截

一、概述

在SpringMVC中,除了Filter和Interceptor拦截器外,还有对请求Controller的处理,即对请求和响应内容的处理和对请求参数的处理。
image.png

二、ControllerAdvice

@ControllerAdvice本质上同Component一样,因此也会被当成组件扫描。
其中@ExceptionHandler常用到。即抛出的异常会被统一拦截处理。在项目中对MethodArgumentNotValidException异常拦截处理

@ControllerAdvice
public class GlobalHandler {
    @ExceptionHandler(MethodArgumentNotValidException.class)
    public Result exceptionHandler(MethodArgumentNotValidException e) {
        Result result = new Result(BizExceptionEnum.INVALID_REQ_PARAM.getErrorCode(),
                BizExceptionEnum.INVALID_REQ_PARAM.getErrorMsg());
        logger.error("req params error", e);
        return result;
    }
}
// 上述对MethodArgumentNotValidException异常统一拦截后并统一返回异常

实现原理:

public class DispatcherServlet extends FrameworkServlet {
    // ......
    protected void initStrategies(ApplicationContext context) {
        initMultipartResolver(context);
        initLocaleResolver(context);
        initThemeResolver(context);
        initHandlerMappings(context);
        initHandlerAdapters(context);
        // 处理所有异常
        initHandlerExceptionResolvers(context);
        initRequestToViewNameTranslator(context);
        initViewResolvers(context);
        initFlashMapManager(context);
    }
    // ......
}

DispatcherServlet的initHandlerExceptionResolvers(context)方法,方法会取得所有实现了HandlerExceptionResolver接口的bean并保存起来,其中就有一个类型为ExceptionHandlerExceptionResolver的bean,这个bean在应用启动过程中会获取所有被@ControllerAdvice注解标注的bean对象做进一步处理,关键代码在这里

public class ExceptionHandlerExceptionResolver extends AbstractHandlerMethodExceptionResolver
        implements ApplicationContextAware, InitializingBean {
    // ......
    private void initExceptionHandlerAdviceCache() {
        // ......
        List<ControllerAdviceBean> adviceBeans = ControllerAdviceBean.findAnnotatedBeans(getApplicationContext());
        AnnotationAwareOrderComparator.sort(adviceBeans);

        for (ControllerAdviceBean adviceBean : adviceBeans) {
            ExceptionHandlerMethodResolver resolver = new ExceptionHandlerMethodResolver(adviceBean.getBeanType());
            if (resolver.hasExceptionMappings()) {
                // 找到所有ExceptionHandler标注的方法并保存成一个ExceptionHandlerMethodResolver类型的对象缓存起来
                this.exceptionHandlerAdviceCache.put(adviceBean, resolver);
                if (logger.isInfoEnabled()) {
                    logger.info("Detected @ExceptionHandler methods in " + adviceBean);
                }
            }
            // ......
        }
    }
}

public ExceptionHandlerMethodResolver(Class<?> handlerType) {
    // 查询当前类中@ExceptionHandler的方法
    for (Method method : MethodIntrospector.selectMethods(handlerType, EXCEPTION_HANDLER_METHODS)) {
        // 获取方法的异常类型
        for (Class<? extends Throwable> exceptionType : detectExceptionMappings(method)) {
            // 添加到缓存中
            addExceptionMapping(exceptionType, method);
        }
    }
}

最后ExceptionHandler被执行过程

// 处理返回结果时,如果异常不为空,则进行异常处理
private void processDispatchResult(HttpServletRequest request, HttpServletResponse response,
                                   @Nullable HandlerExecutionChain mappedHandler, @Nullable ModelAndView mv,
                                   @Nullable Exception exception) throws Exception {
    boolean errorView = false;
    if (exception != null) {
        if (exception instanceof ModelAndViewDefiningException) {
            // ...
        }
        else {
            Object handler = (mappedHandler != null ? mappedHandler.getHandler() : null);
            // 调用异常Handler处理
            mv = processHandlerException(request, response, handler, exception);
            errorView = (mv != null);
        }
    }
    // ...
}

三、RequestBodyAdvice和R

首页 上一页 1 2 3 4 5 6 7 下一页 尾页 1/7/7
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇MyBatis 常用工具类 下一篇Java并发工具CountDownLatch的使..

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目