spring MVC的整体架构
和大多数Web MVC框架一样,Spring MVC通过一个前端Servlet接受所有的请求,并将具体工作委托给其他组件进行处理,DispatcherServlet就是Spring MVC的前端Servlet。
在整个框架中,DispatcherServlet处于核心的位置,它负责协调和组织不同的组件以完成请求处理并返回响应的工作。
DispatcherServlet的任务是将请求发送给Spring MVC控制器。控制器是一个用于处理请求的Spring组件。在典型的应用程序中可能会有多个控制器,DispatcherServlet需要知道应该将请求发送到哪一个控制器。所以DispatcherServlet会查找一个或多个处理器映射来确定请求的下一站在哪里。
一旦选择了合适的控制器,DispatcherServlet会将请求发送给选中的控制器。到达了控制器,请求会卸下其负载(用户提交的信息)并耐心等待控制器处理这些信息。
控制器在完成逻辑处理后,通常会产生一些信息,这些信息需要返回给用户并在浏览器上显示。这些信息被称作模型。将模型数据打包,并且标识出用于渲染输出的视图名称。接下来会将请求连同模型和视图名称发送回DispatcherServlet。
传递给DispatcherServlet的逻辑视图名称并不是直接表示某个特定的JSP。DispatcherServlet借由这个视图解析器来将逻辑视图名匹配为一个特定的视图实现,它可能是也可能不是JSP。
视图将使用模型数据渲染输出,并通过这个输出将响应对象传递给客户端。可能是普通的HTML页面,也可能是一个XML、JSON、JSP等不同的形式。
一、配置DispatcherServlet
Spring MVC的核心是DispatcherServlet,这个Servlet充当Spring MVC的前端控制器。与其他Servlet一样,DispatcherServlet必须在Web应用程序的web.xml文件中进行配置。
pom.xml中需要引入的jar包:
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>4.3.10.RELEASE</version>
</dependency>
web.xml中配置
<servlet>
<servlet-name>spiter</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>spiter</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
为这个Servlet所设置的<\servlet-name>是很重要的。默认情况下,DispatcherServlet在加载时会从一个基于这个Servlet名字的XML文件中加载Spring上下文,本实例中,因为servlet-name的名字是spiter,那么DispatcherServlet将尝试从一个名为spiter-servlet.xml的文件(位于应用的WEB-INF目录下)来加载应用上下文,启动Web层的Spring容器。
DispatcherServlet也提供了一些配置参数,方便对默认配置进行修改:
1、namespace参数:DispatcherServlet对应的命名空间,默认是WEB-INF/<\servlet-name>-servlet.xml。在显式配置该参数后,新的配置文件对应的路径是WEB-INF/<\namespace>.xml。(相当于取了别名,但是路径不变)
<servlet>
<servlet-name>spiter</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>namespace</param-name>
<param-value>mySpiter</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
2、contextConfigLocation参数:会按照设置的文件初始化web上下文,而不是根据默认的配置文件WEB-INF/<\servlet-name>-servlet.xml初始化:
<servlet>
<servlet-name>spiter</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>
<!--根据这两个XML文件初始化WEB上下文,分隔符(逗号,分号和空格)-->
classpath:myspiter.xml
/WEB-INF/sample.xml
</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
但是对于Spring中其他业务层的XML文件,也需要被加载到Spring应用上下文中。ContextLoaderListener是一个Servlet监听器,除了DispatcherServlet创建的应用上下文以外,它能够加载其他的配置文件到一个Spring应用上下文中。在web.xml中进行配置:
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
默认情况下,上下文加载器会查找/WEB-INF/applicationContext.xml这个Spring配置文件。但是这个配置文件并没有将应用上下文拆分多个XML文件,所以要修改默认配置,指定一个或多个Spring配置文件,也在web.xml中配置:
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
<!--多个文件可以使用分隔符(逗号,分号和空格)-->
/WEB-INF/sample.xml
classpath:myspiter.xml
</param-value>
</context-param>
spring框架在加载web配置文件的时候。首先加载的是context-param配置的内容,而并不会去初始化servlet。只有进行了网站的跳转,经过了DispatcherServlet的导航的时候,才会初始化servlet,从而加载init-param中的内容。所以最好将spring的所有配置文件都放在context-param(上下文参数)中进行加载,而<\servlet-name>-servlet.xml中只是配置一些简单的。
在首先加载context-param中的配置后,此时Spring上下文中的Bean已经初始化完毕。当初始化init-param中配置的Web上下文后,DispatcherServlet中的initStrategies()方法会自动执行,将上下文中的Spring MVC组件装配到DispatcherServlet中。
protected void initStrategies(ApplicationContext context) {
//初始化上传文件解析器
this.initMultipartResolver(context);
//初始化本地化解析器
this.initLocaleResolver(context);
//初始化主题解析器
this.initThemeResolver(context);
//初始化处理器映射器
this.initHandlerMappings(context);
//初始化处理器适配器
this.initHandlerAdapters(context);
//初始化处理器异常解析器
this.initHandlerExceptionResolvers(context);
//初始化请求到视图名翻译器
this.initRequestToViewNameTranslator(context);
//初始化视图解析器
this.initViewResolvers(context);
this.initFlashMapManager(context);
}
通过反射机制查找并装配Spring容器中用户显式自定义的组件Bean,如果找不到,则装配默认的组件实例。
在spring-webmvc的jar包中有一个DispatcherServlet.properties文件可以查看默认组件:
#处理器映射(2个)
org.springframework.web.servlet.HandlerMapping=org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping,\
org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping
#视图解析器
org.springframework.web.servlet.ViewResolver=org.springframework.web.servlet.view.InternalResourceViewResolver
如果用户采用非默认类型的组件,则只需在Spring配置文件中配置自定义的组件Bean即可。SpringMVC一旦发现上下文中有用户自定义的组件,就不会使用默认的组件。
同一类型的组件如果存在多个,可以通过order属性确定优先级,值越小优先级越高。
<!--因为DefaultAnnotationHandlerMapping被标注为@Deprecated(不建议使用,未来可能被删除)-->
<bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping">
<property name="order" value="2"/>
</bean>