理解Spring WEB MVC架构的演变

  • 基础Servlet架构

  • 核心架构:前端控制器

  • Spring WEB MVC架构

认识Spring WEB MVC

传统时代的Spring WEB MVC

怎么讲呢?就是很传统的使用Spring Framework WEB MVC的方式,例如Bean配置在xml中,前端控制器配置在web.xml中等。

Maven 依赖

    <dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>5.1.3.RELEASE</version>
</dependency> <dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.1.3.RELEASE</version>
</dependency>
</dependencies>

web.xml

    <servlet>
<servlet-name>dispatcherServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet> <servlet-mapping>
<servlet-name>dispatcherServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>

Spring.xml

	<context:component-scan base-package="com.jimisun.web"/>
<mvc:annotation-driven/>
<bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="viewClass" value="org.springframework.web.servlet.view.JstlView"/>
<property name="prefix" value="/WEB-INF/jsp/"/>
<property name="suffix" value=".jsp"/>
</bean>

Controller

@Controller
public class HelloSpringController { @RequestMapping("")
public String index(){
return "index";
}
}

新时代Spring WEB MVC

所谓的新时代相比肯定是在传统时代上的升级。提到升级我们首先会想到会提升使用的便捷程度以及性能。

  1. 基于注解驱动配置WEB MVC
  2. 自动装配前端控制器

基于注解驱动配置WEB MVC

@Configuration
@EnableWebMvc
public class WebDispatcherServletConfigure implements WebMvcConfigurer { @Bean
public ViewResolver viewResolver() {
InternalResourceViewResolver resourceViewResolver = new InternalResourceViewResolver();
resourceViewResolver.setViewClass(JstlView.class);
resourceViewResolver.setPrefix("/WEB-INF/jsp/");
resourceViewResolver.setSuffix(".jsp");
return resourceViewResolver;
}
}

在Spring.xml文件中则不用再配置处理器映射器,处理器适配器和内部资源视图解析器(JSP)。只需要保留<context:component-scan base-package="com.jimisun.web"/> 以便发现我们自定义的前端控制器配置类WebDispatcherServletConfigure。因为@EnableWebMvc注解为我们自动配置内部资源视图解析器不符合我们自定义的要求,所以上述代码中我们使用@Bean注解重新装配了InternalResourceViewResolver类。

基于注解驱动配置的重点是@EnableWebMvc注解,此模块注解将导入DelegatingWebMvcConfiguration配置类,该类又集成了WebMvcConfigurationSupport类。WebMvcConfigurationSupport中则配置了一些关于 WEB MVC的相关Bean;例如:RequestMappingHandlerMappingContentNegotiationManagerHandlerMappingBeanNameUrlHandlerMappingRequestMappingHandlerAdapterViewResolver等等......

自动装配前端控制器

原理 : 在web容器启动时为提供给第三方组件机会做一些初始化的工作,例如注册servlet或者filtes等,servlet规范中通过ServletContainerInitializer实现此功能。每个框架要使用ServletContainerInitializer就必须在对应的jar包的META-INF/services 目录创建一个名为javax.servlet.ServletContainerInitializer的文件,文件内容指定具体的ServletContainerInitializer实现类,那么,当web容器启动时就会运行这个初始化器做一些组件内的初始化工作。一般伴随着ServletContainerInitializer一起使用的还有HandlesTypes注解,通过HandlesTypes可以将感兴趣的一些类注入到ServletContainerInitializerde的onStartup方法作为参数传入。

我们从spring-web的依赖包中找到这个文件,所以我们可以将前端控制器在Servlet容器启动的时候将Spring WEB MVC的前端控制器添加入Servlet容器中,而不用再配置在web.xml文件中。

我们可以看一下Spring的这个SpringServletContainerInitializer

@HandlesTypes(WebApplicationInitializer.class)
public class SpringServletContainerInitializer implements ServletContainerInitializer {
......
}

我们可以看到Spring定义的这个类实现了Servlet3.0的ServletContainerInitializer接口,并且标注了@HandlesTypes;表示将实现WebApplicationInitializer.class接口的类注入到ServletContainerInitializer的回调方法onStartup()进行初始化。

我们从上面图可以看到WebApplicationInitializer接口的实现类共有四个,所以就意味着我们自定义一个类实现这三个抽象方法其中的一个就行。下面是我们自定义的Servlet容器初始化器类。

public class DefaultAnnotationConfigDispatcherServletInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
protected Class<?>[] getRootConfigClasses() {
return new Class[0];
}
protected Class<?>[] getServletConfigClasses() {
return new Class[]{DispathcherConfig.class};
}
protected String[] getServletMappings() {
return new String[]{"/"};
}
}

getServletMappings()方法用来返回前端控制器要拦截的路径形式。其中getRootConfigClasses()方法用于配置Spring Framework与Service,response有关的Bean;而getServletConfigClasses()方法则用来配置Spring Framework中的WEB层相关的Bean。资料参考 :https://stackoverflow.com/questions/35258758/getservletconfigclasses-vs-getrootconfigclasses-when-extending-abstractannot

总的来说只要自定义一个类,实现WebApplicationInitializer接口即可;我们就可以不用在web.xml中配置前端控制器了。

SpringBoot简化WEB MVC开发

Spring Boot从一下三个方面来简化WEB开发;分别是“自动装配”,“条件装配”,“外部化配置” 三个方面来简化WEB MVC开发。

自动装配

SpringBooot对于WEB MVC的完全自动装配主要体现在一下三个方面。

  1. 前端控制器自动装配org.springframework.boot.autoconfigure.web.servlet.DispatcherServletAutoConfiguration,\
  2. WEB MVC相关组件自动装配 org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration,\
  3. WEB容器自动装配org.springframework.boot.autoconfigure.web.servlet.ServletWebServerFactoryAutoConfiguration,\

条件装配

从完全自动装配可以看到,SpringBoot替我们装配了很多东西;但是在大部分情况下就是基于条件进行装配的,既满足某某条件才会进行装配。还是来看一下前端控制器自定装配类org.springframework.boot.autoconfigure.web.servlet.DispatcherServletAutoConfiguration,\

@AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE)
@Configuration
@ConditionalOnWebApplication(type = Type.SERVLET)
@ConditionalOnClass(DispatcherServlet.class)
@AutoConfigureAfter(ServletWebServerFactoryAutoConfiguration.class)
public class DispatcherServletAutoConfiguration {
}

从该类的注解上我们可以知道@AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE)该类的装配顺序,@AutoConfigureAfter(ServletWebServerFactoryAutoConfiguration.class)在WEB容器装配之后再进行装配,@Configuration可被管理的Bean,@ConditionalOnWebApplication(type = Type.SERVLET)满足条件为WEB类型应用,@ConditionalOnClass(DispatcherServlet.class)满足条件存在DispatcherServlet类。

可以看到我们需要满足两个条件SpringBoot才会为我们装配这个前端控制器DispatcherServlet类。

外部化配置

关于WEB MVC的外部化配置我们需要了解一下WebMvcProperties类和ResourceProperties类;分别对WebMvc和资源文件进行配置。

@ConfigurationProperties(prefix = "spring.mvc")
public class WebMvcProperties {
.......
}
@ConfigurationProperties(prefix = "spring.resources", ignoreUnknownFields = false)
public class ResourceProperties {
......
}

从注解上我们可以了解到,我们可以在application.properties文件或者application.yml文件中进行相关配置。

例如:SpringBoot在自动装配WEB MVC组件的时候装配了一个内部资源视图解析器(JSP)

	@Bean
@ConditionalOnMissingBean
public InternalResourceViewResolver defaultViewResolver() {
InternalResourceViewResolver resolver = new InternalResourceViewResolver();
resolver.setPrefix(this.mvcProperties.getView().getPrefix());
resolver.setSuffix(this.mvcProperties.getView().getSuffix());
return resolver;
}

其中this.mvcProperties.getView().getPrefix()就是从application.properties文件或者application.yml文件中获取的值进行的操作而非硬编码。

本章源码下载

该教程所属Java工程师之SpringBoot系列教程,本系列相关博文目录 Java工程师之SpringBoot系列教程前言&目录

从Spring到SpringBoot构建WEB MVC核心配置详解的更多相关文章

  1. web.xml常用配置详解

    web.xml常用配置详解 context-param 指定 ServletContext(上下文) 配置文件路径,基本配置一般是Spring配置文件,或者是spring-security的配置文件. ...

  2. PHP的核心配置详解

    1.PHP核心配置详解 代码在不同的环境下执行的结果也会大有不同,可能就因为一个配置问题,导致一个非常高危的漏洞能够利用:也可能你已经找到的一个漏洞就因为你的配置问题,导致你鼓捣很久都无法构造成功的漏 ...

  3. spring基于通用Dao的多数据源配置详解【ds1】

    spring基于通用Dao的多数据源配置详解 有时候在一个项目中会连接多个数据库,需要在spring中配置多个数据源,最近就遇到了这个问题,由于我的项目之前是基于通用Dao的,配置的时候问题不断,这种 ...

  4. Nginx 核心配置详解

    目录 Nginx 核心配置详解 Nginx 四层访问控制: Nginx账户认证功能: 自定义错误页面: 自定义访问日志: 检测文件是否存在: 长连接配置: 作为下载服务器配置: 作为上传服务器: 其他 ...

  5. SpringBoot系列(十二)过滤器配置详解

    SpringBoot(十二)过滤器详解 往期精彩推荐 SpringBoot系列(一)idea新建Springboot项目 SpringBoot系列(二)入门知识 springBoot系列(三)配置文件 ...

  6. spring mvc+myBatis配置详解

    一.spring mvc Spring框架(框架即:编程注解+xml配置的方式)MVC是Spring框架的一大特征,Spring框架有三大特征(IOC(依赖注入),AOP(面向切面),MVC(建模M- ...

  7. 写给大忙人的nginx核心配置详解

    由于当前很多应该都是前后端分离了,同时大量的基于http的分布式和微服务架构,使得很多时候应用和不同项目组之间的系统相互来回调用,关系复杂.如果使用传统的做法,都在应用中进行各种处理和判断,不仅维护复 ...

  8. web.xml文件配置详解以及实例说明

    1.web.xml学名叫部署描述符文件,是在Servlet规范中定义的,是web应用的配置文件. 2.部署描述符文件就像所有XML文件一样,必须以一个XML头开始.这个头声明可以使用的XML版本并给出 ...

  9. SpringBoot + Spring Security 基本使用及个性化登录配置详解

    Spring Security 基本介绍 这里就不对Spring Security进行过多的介绍了,具体的可以参考官方文档 我就只说下SpringSecurity核心功能: 认证(你是谁) 授权(你能 ...

随机推荐

  1. QT OpenGL绘制三维图形(立方体、圆柱体、圆锥、球体、圆环等等)

    本文使用QGLWidget来绘制各种三维基本图形,包括立方体.圆柱体.圆锥.球体.圆环等等,涉及包括基本绘制以及上色.纹理.旋转等操作. 使用的软件版本:QT5.12 + QT Creater4.8. ...

  2. C#获取当前时区转换方法

    今天给Mongodb插入数据的时候发现,日期时间对不上,原来Mongodb(麻狗)默认是0时区,所以日期当然出错. 所以用下面进行转换就可以: log.AddTime = DateTime.Speci ...

  3. [Scikit-learn] 1.4 Support Vector Machines - Linear Classification

    Outline: 作为一种典型的应用升维的方法,内容比较多,自带体系,以李航的书为主,分篇学习. 函数间隔和几何间隔 最大间隔 凸最优化问题 凸二次规划问题 线性支持向量机和软间隔最大化 添加的约束很 ...

  4. 【GIS】地球经纬度和米换算(转)

    经度的定义是过某点的经线面和本初子午面之间的夹角.纬度的定义是过某点的球面切面垂线与赤道平面之间的线面角.可见,如果不加限定,1"之间的距离没有意义. 假设地球为一半径为R的表面光滑圆球体, ...

  5. ajax做省市联动

    原理: 当select.jsp页面打开时,向服务器发送异步请求,得到所有省份的名称(文本数据).然后使用每个省份名称创建<option>,添加到<select name=”provi ...

  6. JS 实现拖动效果

    <html> <body style="margin:0px;"> <script src="http://ajax.googleapis. ...

  7. Linux调试分析诊断利器——strace

    strace是个功能强大的Linux调试分析诊断工具,可用于跟踪程序执行时进程系统调用(system call)和所接收的信号,尤其是针对源码不可读或源码无法再编译的程序. 在Linux系统中,用户程 ...

  8. margin-left:10px; 不同浏览器距离为什么不一样?

    这是一个ie的bug.. 如果你设置margin对象是浮动的.ie就会把你设置的值双倍处理..可以设置浮动对象的 display:inline 解决

  9. ab压测工具

    在学习ab工具之前,我们需了解几个关于压力测试的概念 吞吐率(Requests per second)概念:服务器并发处理能力的量化描述,单位是reqs/s,指的是某个并发用户数下单位时间内处理的请求 ...

  10. ftp主动与被动模式详解

    FTP是仅基于TCP的服务,不支持UDP.与众不同的是FTP使用2个端口,一个数据端口和一个命令端口(也可叫做控制端口).通常来说这两个端口是21(命令端口)和20(数据端口).但FTP工作方式的不同 ...