第一小节介绍spring mvc,从以下五个方面
- spring mvc的概念,mvc是什么
- spring mvc的环境搭建,mvc如何使用?
- 配置spring mvc, 进一步深入使用spring mvc
- 配置dispatcherServlet的初始化参数,理解DispatcherServlet配置项的含义以及它的功能。
- 配置context层次结构(树形结构),webApplicationContext与applicationContext之间的关系,如何建造多层次的context。
1、概念(what)
引用原著中对Spring MVC的定义:
Spring Web MVC is the original web framework built on the Servlet API and has been included in the spring framework from the very beginning
这段话的含义有三个部分,Spring Web MVC是一个Web 框架。它是spring框架的一部分。它是基于Servlet API。学习好Spring-core,Servlet对学习Spring MVC有很大的帮助。
Parallel to Spring Web MVC,Spring Framework 5.0 introduced a reactive-stack web framework whose name “spring WebFlux”
从Spring 5.0开始,新添加了基于reactive的响应式框架spring WebFlux,本文略。
2、环境搭建(how)
环境搭建核心的关键点有三个, 创建XXWebApplicationContext对象, 注册dispatcherServlet, 绑定XXWebApplicationContext与ServletContext。
环境搭建的步骤如下:
1、第一步,首先需要引入spring-webmvc的jar。maven的配置如下:
<!--https://mvnrepository.com/artifact/org.springframework/spring-webmvc --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>版本号</version> </dependency>
2、第二步,创建XXWebApplicationContext对象,这个对象类似于Spring框架的ApplicationContext,代表Web IOC容器的上下文。它属于ApplicationContext类结构之中,常见的webApplicationContext有Xml和注解。
-
- XML方式,编写一份app-context.xml(名字随意),根据配置文件创建WebApplicationContext,这个过程绑定在ServletContext对象的生命周期,具体的方式为配置ContextLoaderListener,它实现了ServletContextListener(参考ServletContext对象),并将配置文件的路径作为ServletContext的初始化参数,示例如下:
<listener> <listenerclass>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> <context-param> <param-name>contextConfigLocation</param-name> <param-value>/WEB-INF/app-context.xml</param-value> </context-param>
-
- 注解方式,注解方式必须是Servlet3.0,编写一个AppConfig(名字随意),与xml方式的含义是相同的,即绑定ServletContext对象的生命周期,具体的实现方式不同,我采用实现WebApplicationInitializer接口的方式
3、第三步,配置DispatcherServlet,
当是XML时,在web.xml中配置DispatcherServlet
<servlet> <servlet-name>app</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servletclass> <init-param> <param-name>contextConfigLocation</param-name> <param-value></param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>app</servlet-name> <url-pattern>/app/*</url-pattern> </servlet-mapping>
当是注解时,调用ServletContext添加Servlet的方法。
DispatcherServlet servlet = new DispatcherServlet(ac); ServletRegistration.Dynamic registration = servletCxt.addServlet("app",servlet); registration.setLoadOnStartup(1); registration.addMapping("/app/*");
其中ServletRegistration代表Servlet的配置信息。调用它的方法等价于web.xml中Servlet的相关配置,例如上述中的setLoadOnStartUp方法等价于Servlet的load-on-startup子标签。addMapping等价于servlet-mapping的url-pattern子标签
3、环境搭建的方式
在环境搭建中,它不拘于具体的形式,只要完成三个关键点即可。环境搭建的方式是指它具体的实现方式
具体实现方式有两种,自定义方式,依赖于Servlet的API; mvc的自动方式,依赖于Servlet的API
- 依赖Servlet:在这些方法中可以自定义创建,绑定,注册。
-
- 第一种方式,实现ServletContainerInitializer接口,在onStartUp方法中创建WebApplicationContext。
- 第二种方式,实现ServletContextListener接口,在contextInitialized方法中创建WebApplicationContext。
2.依赖Spring mvc:提供相关的配置项,由mvc自动实现
-
- 第一种方式,实现WebApplicationInitializer接口,它本质上是实现了ServletContainerInitializer接口,查看SpringServletContainerInitializer的源码
@HandlesTypes(WebApplicationInitializer.class) public class SpringServletContainerInitializer implements ServletContainerInitializer {}
-
- 第二种方式,继承AbstractAnnotationConfigDispatcherServletInitializer或者是AbstractDispatcherServletInitializer。前者为注解类型的ApplicationContext,后者为XML方式的ApplicationContext
- 第三种方式,在web.xml中配置ContextLoaderListener,并配置ServletContext的contextConfigLocation参数,指定配置文件的路径。
注:当为依赖spring mvc方式时,需要确保spring mvc的jar包被Tomcat的类加载器加载。可以通过项目的properties--->Web Deployment Assembly,查看是否包含Maven依赖的jar包
4、dispatcherServlet的初始化参数
它的初始化参数有四个
- contextClass:指定WebApplicationContext的类型,默认值为XMLWebApplicationContext
- contextConfigLocation:配置文件的路径,多个时使用逗号分隔,当配置此项时,它会有默认值XMLWebApplicationContext。根据配置文件无法生成注解形式的WebApplicationContext
- namespace:为WebApplicationContext命名,无意义。默认值为【servlet-name】-servlet
- throwExceptionIfNoHandlerFound:当异常类型为请求Handler找不到时,是否抛出异常,若抛出异常会被HandlerExceptionResolver捕获,此时处理逻辑由Resolver决定。若不抛出异常,DispatcherServlet设置response对象的状态码为404。如果存在默认的Servlet,会将请求以forward形式分发给该Servlet,处理逻辑由该Servlet决定
5、context层次结构
一个普通的Spring项目,使用Spring框架,SpringMVC,它的层次结构是spring创建的ApplicationContext是WebApplicationContext的父上下文。当在WebApplicationContext找不到Bean时,会去父Context中查找Bean。在上下文中查找bean类似于JS语言中,在原型链查找变量。
其中spring的ApplicationContext是根据application-context.xml创建的,通常会注入数据源,Service的实现类,事物切面等等。WebApplicationContext是根据app-webmvc.xml(名称随意)创建的,它会注入Controller,SpringMVC的一些核心对象,例如HandlerMapping,MultiPartResolver。
它们都处于ApplicationContext接口的类层次结构中。
若要构建WebApplicationContext的类层次结构,需要理解DispatcherServlet与WebApplicationContext,项目之间的关系,
通常情况下,一个项目只存在一个WebApplicationContext,一个DispatcherServlet。
在多层次的类结构下,一个项目存在多个WebApplicationContext,多个DispatcherServlet对象,DispacterServlet对象与WebApplicationContext的关系为一对一,改变的是ServletContext对象与WebApplicationContext对象变为1对多。
步骤如下:
- 将父WebApplicationContext注入到ServletContext,即设置ServletContext的contextConfigLocation初始化参数。
- 将子WebApplicationContext注入到DispatcherServlet,即配置DispatcherServlet的contextConfigLocation初始化参数。DispatcherServlet与子WebApplicationContext一一对应。