为什么 DispatcherServlet 不调用我的 HandlerInterceptor?
Why doesn't DispatcherServlet invoke my HandlerInterceptor?
我知道在 JavaEE 中,过滤器可以拦截对 servlet 的任何请求。但是 Spring MVC 中的拦截器并不完全相同。如果您查看下图,您会发现拦截器位于 Dispatcher Servlet 之后。
在我提问之前,让我举个例子。
我有一个控制器,其中有 2 个方法映射到两个不同的请求。一个接受 GET 请求,另一个接受 POST 请求。现在,如果我在我的 Web 应用程序中添加一个拦截器,该拦截器将位于 Controller 之前。这意味着在命中控制器方法之前,首先 request
将命中我的拦截器的 preHandle
方法。
现在说在我的应用程序中,两个控制器方法如下所示:
@Controller
public class myController{
@RequestMapping(value = "/test", method = RequestMethod.GET)
public String test1(){
return "abc";
}
@RequestMapping(value = "/login", method = RequestMethod.POST)
public String test1(){
return "xyz";
}
假设我有一个像这样的简单拦截器:
public class URLInterceptors extends HandlerInterceptorAdapter {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("REQUESTED SERVLET PATH IS: " + request.getServletPath());
return true;
}
}
现在,如果我向 /test
发出 GET 请求,我的拦截器将被命中并打印 servlet 路径,但是当我向 /login
发出 GET
请求时,我知道它会失败,因为我处理 /login
映射的方法只接受 POST
请求,但是在它抛出“405 请求方法 'GET' 不支持”错误之前,它至少应该首先命中我的拦截器?它没有。我不想把 POST
改成 GET
。所以问题是为什么?
部分内容在
中有解释
总而言之,DispatcherServlet
尝试使用 HandlerMapping
为您的请求找到合适的处理程序(参见您的图形)。这些处理程序实际上是将实际处理程序方法(在本例中为 @RequestMapping
注释方法)与您注册的拦截器包装起来的适配器。如果找到此处理程序,则 DispatcherServlet
可以继续,调用拦截器,并在需要时调用您的处理程序方法。
在您的情况下,因为您的 @RequestMapping
仅限于 POST 请求并且您的请求是 GET,DispatcherServlet
无法找到合适的处理程序,因此 returns 在它有机会调用任何拦截器之前发生错误。
请注意 javadoc 状态
A HandlerInterceptor
gets called before the appropriate HandlerAdapter
triggers the execution of the handler itself.
但您的 DispatcherServlet
从未找到处理程序。
您可能要考虑改用 Servlet Filter
。
我知道在 JavaEE 中,过滤器可以拦截对 servlet 的任何请求。但是 Spring MVC 中的拦截器并不完全相同。如果您查看下图,您会发现拦截器位于 Dispatcher Servlet 之后。
在我提问之前,让我举个例子。
我有一个控制器,其中有 2 个方法映射到两个不同的请求。一个接受 GET 请求,另一个接受 POST 请求。现在,如果我在我的 Web 应用程序中添加一个拦截器,该拦截器将位于 Controller 之前。这意味着在命中控制器方法之前,首先 request
将命中我的拦截器的 preHandle
方法。
现在说在我的应用程序中,两个控制器方法如下所示:
@Controller
public class myController{
@RequestMapping(value = "/test", method = RequestMethod.GET)
public String test1(){
return "abc";
}
@RequestMapping(value = "/login", method = RequestMethod.POST)
public String test1(){
return "xyz";
}
假设我有一个像这样的简单拦截器:
public class URLInterceptors extends HandlerInterceptorAdapter {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("REQUESTED SERVLET PATH IS: " + request.getServletPath());
return true;
}
}
现在,如果我向 /test
发出 GET 请求,我的拦截器将被命中并打印 servlet 路径,但是当我向 /login
发出 GET
请求时,我知道它会失败,因为我处理 /login
映射的方法只接受 POST
请求,但是在它抛出“405 请求方法 'GET' 不支持”错误之前,它至少应该首先命中我的拦截器?它没有。我不想把 POST
改成 GET
。所以问题是为什么?
部分内容在
中有解释总而言之,DispatcherServlet
尝试使用 HandlerMapping
为您的请求找到合适的处理程序(参见您的图形)。这些处理程序实际上是将实际处理程序方法(在本例中为 @RequestMapping
注释方法)与您注册的拦截器包装起来的适配器。如果找到此处理程序,则 DispatcherServlet
可以继续,调用拦截器,并在需要时调用您的处理程序方法。
在您的情况下,因为您的 @RequestMapping
仅限于 POST 请求并且您的请求是 GET,DispatcherServlet
无法找到合适的处理程序,因此 returns 在它有机会调用任何拦截器之前发生错误。
请注意 javadoc 状态
A
HandlerInterceptor
gets called before the appropriateHandlerAdapter
triggers the execution of the handler itself.
但您的 DispatcherServlet
从未找到处理程序。
您可能要考虑改用 Servlet Filter
。