spring DispatcherServlet、Resolver 和 Controllers 如何交互?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/14015642/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How does the DispatcherServlet, Resolver and Controllers interact?
提问by Philip Whitehouse
Ok so I have encountered the fairly common errror:
好的,所以我遇到了相当常见的错误:
WARNING: No mapping found for HTTP request with URI [/WEB-INF/jsp/index.jsp] in DispatcherServlet with name 'app'
WARNING: No mapping found for HTTP request with URI [/WEB-INF/jsp/index.jsp] in DispatcherServlet with name 'app'
I'm looking at the existing answers and I've not seen a really good explanation of how the components interact. Seeing as I can't solve my issue based on the existing answers, I'm hoping someone can provide a detailed explanation of the function of DispatcherServletand Resolvers.
我正在查看现有的答案,但我还没有看到对组件如何交互的真正好的解释。鉴于我无法根据现有答案解决我的问题,我希望有人可以详细解释DispatcherServlet和Resolvers的功能。
Developing in Eclipse, I have the following structure:
在 Eclipse 中开发,我有以下结构:
/src/com/whiuk/philip/web/controller/IndexController.java
/WebContent
/WebContent/WEB-INF
/WebContent/WEB-INF/web.xml
/WebContent/WEB-INF/app-servlet.xml
/WebContent/WEB-INF/jsp/index.jsp
Eclipse Deployment Assembly means it deploys as follows:
Eclipse 部署程序集意味着它按如下方式部署:
/src -> WEB-INF/classes
/WebContent -> /
/ivy.xml[*] -> WEB-INF/lib
I have a web.xmlfile that defines a DispatcherServletand a mapping to all files (/*)
我有一个web.xml文件,它定义了一个DispatcherServlet和所有文件的映射 ( /*)
<servlet>
<servlet-name>app</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>app</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
I have a app-servlet.xmlfile that scans the packages and defines a InternalResourceViewResolver:
我有一个app-servlet.xml文件,它扫描包并定义一个InternalResourceViewResolver:
<context:component-scan base-package="com.whiuk.philip.web" />
<mvc:annotation-driven />
<bean id="viewResolver"
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/jsp/" />
<property name="suffix" value=".jsp" />
</bean>
I have a IndexControllerthat has a RequestMapping for index:
我有一个IndexController具有 RequestMapping 索引的:
@Controller
public class IndexController {
@RequestMapping(value = "/index", method = RequestMethod.GET)
public ModelAndView index() {
return new ModelAndView();
}
}
Logs show this is registered:
日志显示已注册:
org.springframework.web.servlet.handler.AbstractHandlerMethodMapping registerHandlerMethod
INFO: Mapped "{[/index],methods=[GET],params=[],headers=[],consumes=[],produces=[],custom=[]}"
onto public org.springframework.web.servlet.ModelAndView
com.whiuk.philip.web.controller.IndexController.index()
Finally I have a index.jspfile.
最后我有一个index.jsp文件。
Can someone please explain what the misconfiguration is that results in the error shown at the top and, if possible, provide a sentence or so on the purpose of DispatcherServlet, Resolvers and how they feed into Controllers.
有人可以解释一下导致顶部显示错误的错误配置是什么,如果可能,请提供有关 DispatcherServlet、Resolvers 的目的以及它们如何馈入 Controllers 的句子左右。
采纳答案by Biju Kunjummen
Essentially what is happening is, since you have Spring's DispatcherServlet mapped to /*, it tends to be called for every request(which is okay), but unfortunately gets invoked even when the request gets dispatched to the JSP page (/WEB-INF/jsp/index.jsp), instead of the containers default servlet getting invoked.
本质上发生的事情是,由于您已将 Spring 的 DispatcherServlet 映射到/*,因此往往会为每个请求调用它(这没关系),但不幸的是,即使将请求分派到 JSP 页面(/WEB-INF/jsp/index.jsp),也会被调用,而不是容器默认值servlet 被调用。
The fix that I am aware of is the following:
我所知道的修复如下:
Map it to the default servlet path /instead:
将其映射到默认的 servlet 路径/:
<servlet-mapping>
<servlet-name>app</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
One issue that you would see with above is that the resources under the root of your webapp will unfortunately get handled by DispatcherServlet which will not know what do with it, the fix is to register a default-servlet-handler this way:
您会在上面看到的一个问题是,不幸的是,您的 web 应用程序根目录下的资源将被 DispatcherServlet 处理,而 DispatcherServlet 不知道如何处理它,解决方法是通过这种方式注册一个 default-servlet-handler:
<mvc:default-servlet-handler />
回答by micha
I will try to explain the "flow" of a request in a Spring Web MVC application.
我将尝试解释 Spring Web MVC 应用程序中请求的“流程”。
When sending a request to your application the following happens:
向您的应用程序发送请求时,会发生以下情况:
- The request arrives at your server (e.g. Tomcat). Depending on the context path in the url the server decides to which application the request belongs.
- Depending on the url and the servlet mapping in the web.xml file of your application the server knows which servlet should handle the request.
- The request is passed to the servlet filterchain which can modify or reject requests
- The servlet takes control over the request. In case of your Spring application the spring Dispatcherservlet receives the request. Now Spring kicks in
- The request is processed by mvc intercepters
preHandlemethods - The request is mapped to a controller based on the url. The corresponding controller method will be called.
- Your controller is processing the request. Many different responses can be returned in controllers (jsp, pdf, json, redirects, etc.). For now i assume you want to render a simple jsp view. Result of the controller are two things: a model and a view. The model is a map that contains the data you want to access later in your view. The view at this stage is most of the time a simple string containing a view name.
- Registered springs mvc interceptors can kick in again using the
postHandlemethod (e.g. for modifying the model) - The 'view' result of your controller is resolved to a real View using a
ViewResolver. Depending on the ViewResolver the result can be jsp page, a tiles view, a thymeleaf templateor many other 'Views'. In your case theViewResolverresolves a view name (e.g. 'myPage') to a jsp file (e.g./WEB-INF/jsp/myPage.jsp) - The view is rendered using the model data returned by your controller
- The response with the rendered view will be passed to mvc interceptors again (
afterCompletionmethod) - The response leaves the dispatcher servlet. Here ends spring land.
- The response passes servlet filters again
- The response is send back to client
- 请求到达您的服务器(例如 Tomcat)。根据 url 中的上下文路径,服务器决定请求属于哪个应用程序。
- 根据应用程序的 web.xml 文件中的 url 和 servlet 映射,服务器知道哪个 servlet 应该处理请求。
- 请求被传递到可以修改或拒绝请求的servlet 过滤器链
- servlet 控制请求。对于 Spring 应用程序,spring Dispatcherservlet 接收请求。现在春天来了
- 请求由mvc 拦截器
preHandle方法处理 - 请求根据 url 映射到控制器。相应的控制器方法将被调用。
- 您的控制器正在处理请求。许多不同的响应可以在控制器(jsp、pdf、json、重定向等)中返回。现在我假设您想要呈现一个简单的 jsp 视图。控制器的结果是两件事:模型和视图。该模型是一个地图,其中包含您稍后要在视图中访问的数据。这个阶段的视图大部分时间是一个包含视图名称的简单字符串。
- 注册的 springs mvc 拦截器可以使用该
postHandle方法再次启动(例如,用于修改模型) - 控制器的“视图”结果使用
ViewResolver. 根据 ViewResolver,结果可以是 jsp 页面、tile 视图、thymeleaf 模板或许多其他“视图”。在您的情况下,ViewResolver将视图名称(例如“myPage”)解析为 jsp 文件(例如/WEB-INF/jsp/myPage.jsp) - 视图是使用控制器返回的模型数据呈现的
- 带有渲染视图的响应将再次传递给 mvc 拦截器(
afterCompletion方法) - 响应离开调度程序 servlet。春天的土地到此结束。
- 响应再次通过 servlet 过滤器
- 响应被发送回客户端
Feel free to correct me if I'am not 100% correct or if I missed something :-)
如果我不是 100% 正确或者我错过了什么,请随时纠正我:-)

