环境 Spring 4.2.3
一下内容学习总结于《精通Spring 4.x——企业应用开发实战》,跟开涛学习Spring MVC
Spring MVC 体系结构
整个框架中DispatcherServlet处于核心的位置,他负责协调和组织不同 的组件以完成请求处理并返回相应的工作。 Spring MVC通过一个前端Servlet接受所有的请求,并将具体的工作委托 给其他组件进行处理,DispatcherServlet就是SpringMVC的前端的Servlet。
下面对Spring MVC处理请求的整体过程讲解
- 客户端发出一个HTTP请求,Web应用服务器接受到这个请求,如果匹配 DispatcherServlet的请求映射路径(在web.xml指定),则Web容器将请求转 交给 DispatcherServlet 处理。例如:
<servlet-mapping>
<servlet-name>springmvc</servlet-name>
<url-pattern>*.html</url-pattern>
<!--通过servlet-mapping指定DispatcherServlet处理所有的.html为后缀的http请求-->
</servlet-mapping>
- DispatcherServlet接受处理这个请求后,根据这个请求的信息(URL,请 求参数,报文头,Cookie等)以HandlerMapping的配置找到处理请求的处理器(Handler)。可将HanderMapping看作路由控制器,将Handlei•看作目标 主机。实际上任伯I 一个Object都可以看作请求处理器。
- 当DispatcherServlet根据HandlerMapping得到对应当前请求的Hanlder 后,通过HandlerAdapter对Handler进行封装,再以统一的是适配器接口调用 Handler。HandlerAdapter是一个适配器,它用统一的接口对各种Handler方法 进行调用。
- 处理器完成业务逻辑的处理后将放回的ModelAndView给 DispatcherServlet, ModelAnd View包含了视图逻辑名,和模式数据信息。
- ModelAndView包含逻辑视图名而非是真正的视图对象。DispatcherServlet 倍由ViewResolver完成逻辑视图名到真实视图对象的解析工作。
- 得到真正的视图对象View后,DispatchersServlet就使用这个View对象对 ModelAndView中的模型数据进行视图渲染。
- 最终返回到客户到的可能是HTML, XML、JSON、PDF等
以上每一步骤都包含丰富的知识点。
要了解Spring MVC 框架机制工作机理,也要知道几个问题
问题
- DispatcherServlet框架如何拦截特定的HTTP请求,并交由Spring MVC处理?
- 位于Web层的Spring容器(WebApplicationContext)如何与位于业务层的Spring容器(ApplicationContext)建立关联,以使Web层的Bean可以调用业务层的Bean?
- 如何初始化SpringMVC的各个组件,并将他们装配到DispatcherServlet中?
1、配置DispatcherServlet,截取特定的URL请求。
web.xml配置
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0">
<!-- ① -->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/appcationContext.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<servlet><!-- ② -->
<servlet-name>springmvc</servlet-name>
<servlet-class>
org.springframework.web.servlet.DispatcherServlet
</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping><!-- ③ -->
<servlet-name>springmvc</servlet-name>
<url-pattern>*.html</url-pattern>
<!--通过servlet-mapping指定DispatcherServlet处理所有的.html为后缀的http请求-->
</servlet-mapping>
</web-app>
①:contextConfigLocation:,表示用于加载Bean的配置文件。通过contextConfigLocation参数指定业务层Spring容器的配置文件;
②:配置名为springmvc的DispatcherServlet,他默认会自动加载/WEB/INF/springmvc-servlet.xml(servlet-Name-servlet.xml)的Webc层的Spring配置文件,启动Web层的Spring容器。
③:所有带.html为后缀的HTTP请求会被DispatcherServlet截获处理。
我们也可通过Java 编程方式来配置Servlet容器。不需要web.xml,思路一样
参考官方描述
将web,xml文件的配置全部注解掉,添加SpringmvcApplicationInitializer类,实现WebApplicationInitializer接口。 启动,效果是一样的。
package com.config;
import org.springframework.web.WebApplicationInitializer;
import org.springframework.web.context.support.XmlWebApplicationContext;
import org.springframework.web.servlet.DispatcherServlet;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletRegistration;
public class SpringmvcApplicationInitializer implements WebApplicationInitializer {
@Override
public void onStartup(ServletContext servletContext) throws ServletException {
XmlWebApplicationContext appContext = new XmlWebApplicationContext();
appContext.setConfigLocation("/WEB-INF/springmvc-servlet.xml");
ServletRegistration.Dynamic dynamic = servletContext.addServlet("dispatcher", new DispatcherServlet(appContext));
dynamic.setLoadOnStartup(1);
dynamic.addMapping("*.html*");
}
}
可能有人会疑问为什么实现WebApplicationInitializer接口就能配置Servlet了呢?
在Spring 3.0环境中,容器会在类路径中查找实现javax.servlet.ServletContainerInitializer的类,如果返现有实现的类,就会调用它,配置Servlet容器。在Spring中,org.springframework.web.SpringServletContainerInitializer类实现了ServletContainerInitializer接口,同时这个类会查找实现org.springframework.web.WebApplicationInitializer接口的类,并将配置任务交给这些实现类去完成。
扩充知识:
applicationContext.xml与servlet-Name-servlet.xml 区别,关系与加载顺序
引言:
-
多个Spring容器之间可设置子父的关系的,以实现良好的解耦。
-
这里“Web层”Spring容器将作为“业务层”Spring容器的子容器,即 “Web层”容器可以引用“业务层”容器的Bean,而“业务层”容器访问不到“Web层”容器的Bean。
关系与区别:
- applicationContext.xml文件通常用于加载业务层spring系统级别的组件,比如bean的初始化
- servlet-Name-servlet.xml文件通常用于加载controller层需要的类,比如拦截器,mvc标签加载的类
- 如果直接使用SpringMVC是可以不添加applicationContext.xml文件的,其实我的applicatiContext.xml是空,如下。因为applicationContext.xml是随着ContextLoaderListener的加载儿执行的。由于没有配置applicationContext.xml所以我们就可以去掉web.xml文件中的 context-param标签、listener标签。
直接采用SpringMVC,只需要把所有相关配置放到servlet-Name-servlet.xml中就OK了
applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<!--没有内容-->
</beans>
加载先后:
以下内容摘自
首先applicationContext.xml是随ContextLoaderListener的加载而执行的,而servlet-Name-servlet.xml是随DispatcherServlet的加载而执行的,在web.xml中;
加载顺序是listener>filter>servlet;