关于springMvc错误重定向/error

2020-05-26  本文已影响0人  矮子阿冰
代码

1.添加一个请求

@RequestMapping(value = "/A", method = RequestMethod.POST)

2.在WebMvcConfigurerAdapter添加excludePathPatterns("/A")
3.添加HandlerInterceptor的实现类,并在perHandle中校验参数

问题现象

发起url="/A"的GET请求,返回参数校验失败的结果。

Debug流程

1.Http11NioProcessor类对请求进行包装处理。通过CoyoteAdapter通过管道请求转发到第一个阀门中,然后又找到其下属StandardHost,StandardHostValve阀门又将请求转发到StandardContextValve上下文对象的阀门中进行对应的处理后继续转发到StandardWrapperValve阀门。StandardWrapperValve类对应的是一个Servlet类,这里就会对请求进行具体处理了。

connector.getService().getContainer().getPipeline().getFirst().invoke(request, response);

2.最终tomcat找到了DispatcherServlet,在servlet中根据HttpServletRequest获取HandlerExecutionChain对象,
在mappings中匹配请求对应handle,在RequestMappingInfoHandlerMapping进行匹配时,先匹配的url命中,但是在判断method到时候没有匹配成功,这是会在RequestMappingInfoHandlerMapping的handleNoMatch方法中抛出异常,在DispatcherServlet中进行捕获,并通过DefaultHandlerExceptionResolver将response的status设置为405

if (helper.hasMethodsMismatch()) {
            Set<String> methods = helper.getAllowedMethods();
            if (HttpMethod.OPTIONS.matches(request.getMethod())) {
                HttpOptionsHandler handler = new HttpOptionsHandler(methods);
                return new HandlerMethod(handler, HTTP_OPTIONS_HANDLE_METHOD);
            }
            throw new HttpRequestMethodNotSupportedException(request.getMethod(), methods);
        }

3.层层返回每个阀门,当回到StandardHostValve时,会去获取response的status如果response是错误转状态则继续去获取错误码对应的ErrorPage,如果没有定义则获取默认的ErrorPage(/error),并重定向/error请求。

ErrorPage errorPage = context.findErrorPage(statusCode);
        if (errorPage == null) {
            // Look for a default error page
            errorPage = context.findErrorPage(0);
        }
----------------------------------------------------------------------------------------------------------------
  rd.forward(request.getRequest(), response.getResponse());

4.通过阀门再次进入DispatcherServlet,这次在RequestMappingInfoHandlerMapping中成功匹配/error请求的handler,因为excludePathPatterns没有添加/error的过滤,所有/error就回进入HandlerInterceptor的perHandle方法进行校验。

tomcat启动(Ⅷ)--请求最终目的地 getContainer().getPipeline().getFirst().invoke(request, response)

上一篇下一篇

猜你喜欢

热点阅读