我正在尝试更详细地了解Spring MVC我目前所知道的内容。我指的是在线教程和书籍。据我了解,Spring MVC框架具有“前端控制器”和“MVC”设计模式。
前端控制器(DispatcherServlet)使用HandlerMapping
将URL映射到控制器类。 我没有使用注释,因为我想了解框架在幕后的作用。
在这个任务中,我创建了一个基于Spring MVC的简单Web应用程序,代码如下:
public class SimpleSpringController extends AbstractController {
@Override
protected ModelAndView handleRequestInternal(HttpServletRequest req, HttpServletResponse res) throws Exception {
ModelAndView mw = new ModelAndView("welcome","welcomeMessage", "welcome user!");
return mw;
}
}
<?xml version="1.0" encoding="UTF-8"?>
<web-app>
<display-name>FirstSpringMVCProject</display-name>
<servlet>
<servlet-name>spring-dispatcher</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>spring-dispatcher</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
<beans>
<bean id="HandlerMapping1" class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"/>
<bean name="/welcome" class="com.example.controller.SimpleSpringController"/>
<bean id="viewResolver1" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix"> <value>/WEB-INF/</value> </property>
<property name="suffix"> <value>.jsp</value> </property>
</bean>
</beans>
该应用程序按预期工作。
我无法理解的概念是在我们指定HandlerMapping
和ViewResolver
实现的spring配置xml中。
例如,我们在上面的spring xml配置中有以下bean定义:
<bean id="HandlerMapping1" class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"/>
在上面的xml配置中,org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping
是HandlerMapping
接口的实现之一。
这个bean的id是HandlerMapping1
,它只是一个随机标识符(我可以很好地选择MyHandlerMapping
)。以下是疑惑:
谁读取此配置文件?前端控制器是否读取此配置文件?
框架如何知道上述案例中HandlerMapping
实现的ID为HandlerMapping1
。通常我们会使用getBean(“beanId”),我们特别知道特定的bean id是什么。为什么spring框架会自动推断这是HandlerMapping
的实现类。
理解这一点的任何输入都会有很大的帮助。
答案 0 :(得分:2)
您的spring xml配置由Spring加载,将所有内容连接在一起。正在进行自动装配,即按类型进行布线,HandlerMapping1可以为HandlerMapping接口提供布线。
有趣的是,BeanNameUrlHandlerMapping是默认的处理程序映射类,因此当Spring无法找到声明的任何处理程序映射类时,它是由DispatcherServlet创建的。
如果您想尝试查看某些内容,请创建一个名为HandlerMapping2的重复bean并读取错误记录。
答案 1 :(得分:1)
好吧,要使spring MVC正常工作,应该实例化处理程序。 Spring MVC框架需要解析映射,所以我们 有像BeanNameUrl ...,ControllerBeanNameHandlerMapping这样的处理程序, 等
但是,您的应用程序通常不使用HandlerMapping 码。因此,您无需指定此bean是否按类型自动装配 或不。它由框架使用。所以它是自动装配的 按类型框架类。
您可以尝试在xml中定义bean而不使用任何id,name
之类的东西<bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"/>
它应该仍然有用。
只有当您想通过id引用bean时才需要Id或name 或名称供您使用。需要此处理程序的框架类 映射不要通过id或来引用HandlerMapping类型的bean 名称。框架将扫描&#39; xml(或加载的类)和if 它在类型中找到了一个具体的类 (org.springframework.web.servlet.HandlerMapping)然后它赢了#t 抱怨。
例如,在运行junit时,可以考虑类似的情况 测试时,引擎将扫描所有使用@Test注释的方法 它会知道&#39;这些是它需要执行的方法 试验。测试方法的名称无关紧要。
希望这可以回答查询。
答案 2 :(得分:1)
在Spring中,前端控制器是DispatcherServlet
,这扩展了FrameworkServlet
。默认情况下,FrameworkServlet
会创建XmlWebApplicationContext
并尝试读取名为<servlet-name>-servlet.xml
的XML文件(这是在使用web.xml
时!)。 (所有这些都可以通过为配置的init-param
设置适当的DispatcherServlet
来覆盖。
加载后DispatcherServlet
将最终调用initStrategies
方法。此方法将为DispatcherServlet
配置委派策略。它会首先尝试按类型检测大多数策略(例如HandlerMaping
,HandlerAdapter
,ViewResolver
等),有些则按名称(localeResolver
,themeResolver
检测, messageSource
等)。如果找不到,则将安装给定接口的默认策略。这些默认值在Spring中的DispatcherServlet.properties
中定义。
重要提示:只要您自己定义策略,该策略的默认设置就不再适用了!例如,如果您的配置中有BeanNameUrlHandlerMapping
,则HandlerMapping
的默认配置将不再加载,因为您提供了显式配置。
启动后,DispatcherServlet
已准备好处理请求。
图片来自Spring Framework reference guide
当DispatcherServlet
处理请求时,会检查所有已配置的HandlerMapping
以查看是否能够提供处理程序(Controller
或{{1}对于给定的请求,它只是可以处理的一种处理程序类型。一旦找到处理程序,它就会为检测处理程序查找HandlerAdapter
。如果找到了,则将找到的处理程序与当前@Controller
和HttpServletRequest
一起传递给HttpServletResponse
HandlerAdapter
方法。
现在,如果handle
方法返回ModelAndView
,如果HandlerAdapter.handle
方法返回名称,则View
将被解析,这将是将a传递给ViewResolver
以解析为View
。
当ModelAndView.getViewName()
是解析程序或从View
方法返回时,将调用ModeAndView.getView()
方法让所选的render
呈现自己。使用View
类中的(可选)模型。
在处理请求期间发生异常时,首先将此异常传递给配置的HandlerExceptionResolver
。如果其中一个人可以处理它,则会调用所选的ModelAndView
s HandlerExceptionResolver
方法。与resolveException
方法一样,此方法可以返回HandlerAdapter.handle
,当发生这种情况时,其处理方式与正常请求相同(请参阅查看解析)。
注意: ModelAndView
的{{3}}中也记录了这一点。您可以在其中找到所有默认策略和众所周知的名称,以及请求处理流程的说明。