简介
springmvc 是spring框架的一个模块,springmvc和spring 无需通过中间整合层进行整合。
springmvc是一个基于mvc的web框架。
MVC模式最早由Trygve Reenskaug在1978年提出[1],是施乐帕罗奥多研究中心(Xerox PARC)在20世纪80年代为程序语言Smalltalk发明的一种软件架构。MVC模式的目的是实现一种动态的程式设计,使后续对程序的修改和扩展简化,并且使程序某一部分的重复利用成为可能。除此之外,此模式通过对复杂度的简化,使程序结构更加直观。软件系统通过对自身基本部分分离的同时也赋予了各个基本部分应有的功能。专业人员可以通过自身的专长分组:
- 控制器(Controller)- 负责转发请求,对请求进行处理。
- 视图(View) - 界面设计人员进行图形界面设计。
- 模型(Model) - 程序员编写程序应有的功能(实现算法等等)、数据库专家进行数据管理和数据库设计(可以实现具体的功能)。
MVC 在B/S 系统下的应用
SpringMVC框架
Spring Web MVC 是基于 Servlet API 设计的,它被部署到 Servlet 容器 中
DispatcherServlet (前端控制器)
WebApplicationContext 是根据自己的配置对普通的 ApplicationContext 进行扩展。
它有一个指向 ServletContext 容器和其相关联的 Servlet 的连接。
1> Web 系统读取 web.xml 文件
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
...
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/applicationContext*.xml</param-value>
</context-param>
2> ContextLoaderListener 寻找相应的 /WEB-INF/applicationContext*.xml 文件并加载
此时 Spring 创建一个 WebApplicationContext 对象,将其存储在 ServletContext 中。
注:可以通过下面的方法从 ServletContext 中获取当时的 WebApplicationContext。
WebApplicationContext ctx = WebApplicationContextUtils.getWebApplicationContext(servletContext);
Spring 容器分级
由下图可以看出 , DispatcherServlet 需要 WebApplicationContext。Web ApplicationContext 一般 需要分级成 两级容器:一级是 Root WebApplicationContext,另一级是 Servlet WebApplicationContext 。前者被多个 servlet 共享,后者则是根据自己应用的 servlet 配置而来。
由图还可以看出,Root WebApplicationContext 与 Servlet WebApplicationContext 不是包含关系,只是存在引用。Servlet WebApplicationContext 引用 Root WebApplicationContext。
注:不分级的话,只有一个 单独的 WebApplicationContext 也是足够的,则所有 beans 都要从 Root WebApplicationContext 中获取。
再结合具体代码去理解:
1)通过 web.xml 配置 ServletContext(Servlet 容器),包含 RootApplicationContext 根容器,前端控制器( Servlet WebApplicationContext 子容器)
<web-app>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/root-context.xml</param-value> // Root WebApplicationContext 根容器配置
</context-param>
<servlet>
<servlet-name>app1</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/app1-context.xml</param-value> // Servlet WebApplicationContext 子容器配置
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>app1</servlet-name>
<url-pattern>/app1/*</url-pattern>
</servlet-mapping>
</web-app>
2)引入了一个 前端控制器(包含一个 Servlet WebApplicationContext 子容器 )
import org.springframework.web.WebApplicationInitializer;
public class MyWebApplicationInitializer implements WebApplicationInitializer {
@Override
public void onStartup(ServletContext container) {
XmlWebApplicationContext appContext = new XmlWebApplicationContext();
appContext.setConfigLocation("/WEB-INF/spring/dispatcher-config.xml");
ServletRegistration.Dynamic registration = container.addServlet("dispatcher", new DispatcherServlet(appContext));
registration.setLoadOnStartup(1);
registration.addMapping("/");
}
}
3)引入了一个 前端控制器(包含一个 Servlet WebApplicationContext 子容器)
public class MyWebApplicationInitializer implements WebApplicationInitializer {
@Override
public void onStartup(ServletContext servletCxt) {
// Load Spring web application configuration
AnnotationConfigWebApplicationContext ac = new AnnotationConfigWebApplicationContext();
ac.register(AppConfig.class);
ac.refresh();
// Create and register the DispatcherServlet
DispatcherServlet servlet = new DispatcherServlet(ac);
ServletRegistration.Dynamic registration = servletCxt.addServlet("app", servlet);
registration.setLoadOnStartup(1);
registration.addMapping("/app/*");
}
}
基本处理流程
上面的容器部署好了,下面开始 DispatcherServlet 处理请求:
用户发出请求 -> WebApplicationContext 绑定request 作为自己的一个属性,以便 Controller可以访问到。实际上也是绑定 request 到 Thread -> locale resolver,theme resolver,multipart file resolver 依次绑定到 request ,让其决定使用哪个resolver -> 搜索合适的 handler 处理,执行链 preprocessors, postprocessors, and controllers,直接返回或填充 model -> 回收 model,渲染视图。
WebApplicationContext 上声明的 HandlerExceptionResolver 负责处理请求过程中的异常。
实际应用
HandlerMapping 可以实现 Interception 拦截器
-
preHandle(..)
— before the actual handler is executed -
postHandle(..)
— after the handler is executed -
afterCompletion(..)
— after the complete request has finished
还支持 Filter(如 cors filter),这类 Filter 不包括在 servlet 中。注解 请看,RestTemplate 请看
参考资料
https://zh.wikipedia.org/wiki/MVC
https://spring.io/docs/reference
http://www.ruanyifeng.com/blog/2015/02/mvcmvp_mvvm.html