從Spring到SpringBoot構建WEB MVC核心配置詳解

[TOC]html

理解Spring WEB MVC架構的演變

  • 基礎Servlet架構 前端

  • 核心架構:前端控制器java

  • Spring WEB MVC架構

認識Spring WEB MVC

傳統時代的Spring WEB MVC

怎麼講呢?就是很傳統的使用Spring Framework WEB MVC的方式,例如Bean配置在xml中,前端控制器配置在web.xml中等。git

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

所謂的新時代相比確定是在傳統時代上的升級。提到升級咱們首先會想到會提高使用的便捷程度以及性能。github

  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類。web

基於註解驅動配置的重點是@EnableWebMvc註解,此模塊註解將導入DelegatingWebMvcConfiguration配置類,該類又集成了WebMvcConfigurationSupport類。WebMvcConfigurationSupport中則配置了一些關於 WEB MVC的相關Bean;例如:RequestMappingHandlerMappingContentNegotiationManagerHandlerMappingBeanNameUrlHandlerMappingRequestMappingHandlerAdapterViewResolver等等......spring

自動裝配前端控制器

原理 : 在web容器啓動時爲提供給第三方組件機會作一些初始化的工做,例如註冊servlet或者filtes等,servlet規範中經過ServletContainerInitializer實現此功能。每一個框架要使用ServletContainerInitializer就必須在對應的jar包的META-INF/services 目錄建立一個名爲javax.servlet.ServletContainerInitializer的文件,文件內容指定具體的ServletContainerInitializer實現類,那麼,當web容器啓動時就會運行這個初始化器作一些組件內的初始化工做。通常伴隨着ServletContainerInitializer一塊兒使用的還有HandlesTypes註解,經過HandlesTypes能夠將感興趣的一些類注入到ServletContainerInitializerde的onStartup方法做爲參數傳入。springboot

咱們從spring-web的依賴包中找到這個文件,因此咱們能夠將前端控制器在Servlet容器啓動的時候將Spring WEB MVC的前端控制器添加入Servlet容器中,而不用再配置在web.xml文件中。架構

咱們能夠看一下Spring的這個SpringServletContainerInitializermvc

@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

Spring Web MVC中的典型上下文层次ç"“æž„

img

總的來講只要自定義一個類,實現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系列教程前言&目錄

相關文章
相關標籤/搜索