Spring In Action--03(SpringMVC通过java配置的方法搭建)

 

目录

 

1.基于java配置的SpringMVC搭建

 2.SpringMVC是如何启动的?

3.SpringMVC启动的时候会创建两个两个应用上下文:

 4.自定义DispatcherServlet配置

5.如何注册其他的Servlet,Filter,Listener.?


1.基于java配置的SpringMVC搭建

传统的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_3_1.xsd"
         version="3.1">

  <display-name>springMvc</display-name>
  <description>springMvc0.0.1</description>

  <!-- 编码过滤器 -->
  <filter>
    <filter-name>encodingFilter</filter-name>
    <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
    <init-param>
      <param-name>encoding</param-name>
      <param-value>UTF-8</param-value>
    </init-param>
  </filter>
  <filter-mapping>
    <filter-name>encodingFilter</filter-name>
    <url-pattern>/*</url-pattern>
  </filter-mapping>

  <!-- 配置DispatcherServlet -->
  <servlet>
    <servlet-name>springMvc</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <!-- 配置springMVC需要加载的配置文件-->
    <init-param>
      <param-name>contextConfigLocation</param-name>
      <param-value>classpath:spring-*.xml</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
    <async-supported>true</async-supported>
  </servlet>
  <servlet-mapping>
    <servlet-name>springMvc</servlet-name>
    <!-- 匹配所有请求,此处也可以配置成 *.do 形式 -->
    <url-pattern>/</url-pattern>
  </servlet-mapping>

  <!--配置thymeleaf  -->

  <servlet-mapping>
    <servlet-name>springMvc</servlet-name>
    <url-pattern>*.html</url-pattern>
  </servlet-mapping>



  <welcome-file-list>
    <welcome-file>index.html</welcome-file>
  </welcome-file-list>

</web-app>

  

传统的SpringMVC的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"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:mvc="http://www.springframework.org/schema/mvc"
       xmlns:task="http://www.springframework.org/schema/task"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd
       http://www.springframework.org/schema/context
       http://www.springframework.org/schema/context/spring-context.xsd
       http://www.springframework.org/schema/mvc
       http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd
       http://www.springframework.org/schema/task
       http://www.springframework.org/schema/task/spring-task.xsd">


    <!-- 扫描web相关的bean -->
    <context:component-scan base-package="com.wx.controller"/>

    <!-- 开启SpringMVC注解模式 -->
    <mvc:annotation-driven/>

    <!-- 静态资源默认servlet配置 -->
    <mvc:default-servlet-handler/>
    <!--自动任务扫描配置-->
    <task:annotation-driven/>
    <context:component-scan base-package="com.wx.component"/>

    <mvc:resources mapping="/static/**" location="/WEB-INF/static/"/>

    <!-- 模板解析器  -->
    <bean id="templateResolver" class="org.thymeleaf.templateresolver.ServletContextTemplateResolver">
        <property name="prefix" value="/WEB-INF/templates/"/>
        <property name="suffix" value=".html"/>
        <property name="templateMode" value="HTML5"/>
        <property name="cacheable" value="false"/>
        <property name="characterEncoding" value="UTF-8"/>
    </bean>

    <bean id="templateEngine" class="org.thymeleaf.spring4.SpringTemplateEngine">
        <property name="templateResolver" ref="templateResolver"/>
    </bean>

    <bean class="org.thymeleaf.spring4.view.ThymeleafViewResolver">
        <property name="templateEngine" ref="templateEngine"/>
        <property name="characterEncoding" value="UTF-8"/>
    </bean>

    <!--扫描包下所有的被标注的类-->
    <context:component-scan base-package="com.wx.domain"/>

    <!--配置验证器-->
    <bean id="myvalidator" class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean">
        <property name="providerClass" value="org.hibernate.validator.HibernateValidator"/>
    </bean>

    <!--绑定验证器-->
    <mvc:annotation-driven validator="myvalidator"/>
    <!-- 配置拦截器链 -->
    <!--<mvc:interceptors>
        &lt;!&ndash; 配置第1个拦截器 &ndash;&gt;
        <mvc:interceptor>
            &lt;!&ndash; 指定拦截路径,不在拦截路径之内的将不予处理,即拦截器根本就不运行 &ndash;&gt;
            <mvc:mapping path="/index"/>
            <mvc:mapping path="/user/password.do"/>
            &lt;!&ndash; 指定拦截器类 &ndash;&gt;
            <bean class="com.wx.Interceptor.LoginInterceptor"/>
        </mvc:interceptor>
    </mvc:interceptors>-->

    <!-- 自定义的实现类 -->
    <bean id="exceptionHandler" class="com.wx.error.CustomExceptionHandler"/>
    <!-- 默认的实现类注入 -->

    <!-- 配置文件上传 -->
    <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
        <!-- 指定默认的编码格式 -->
        <property name="defaultEncoding" value="UTF-8"/>
        <!-- 指定允许上传的文件大小,单位Byte -->
        <property name="maxUploadSize" value="5120000000000"/>
    </bean>

    <!-- 国际化 -->
    <bean id="messageSource" class="org.springframework.context.support.ResourceBundleMessageSource">
        <property name="basenames" value="i18n.message"></property>
    </bean>

    <!-- 国际化操作拦截器如果采用基于(session/cookie)则必须配置 -->
    <mvc:interceptors>
        <bean class="org.springframework.web.servlet.i18n.LocaleChangeInterceptor"></bean>
    </mvc:interceptors>


    <!-- 配置LocalResolver用来获取本地化语言 -->
    <bean id="localeResolver" class="org.springframework.web.servlet.i18n.SessionLocaleResolver"></bean>
    <!-- 配置LocaleChanceInterceptor拦截器 -->
    <mvc:interceptors>
        <bean class="org.springframework.web.servlet.i18n.LocaleChangeInterceptor"/>
    </mvc:interceptors>


</beans>

 2.SpringMVC是如何启动的?

 请求第一站DispatcherServlet(前端控制器),配置DispatcherServlet可以使用web.xml,还可以使用通过继承AbstractAnnotationConfigDispatcherServletInitializer来配置DispatcherServlet,以替代使用web.xml配置DispatcherServlet。

为什么DispatcherServlet启动的时候就会找到AbstractAnnotationConfigDispatcherServletInitializer的扩展呢?在Servlet3.0的容器环境中,容器会在类路径中查找实现ServletContainerInitializer接口的类,如果能发现的话就用它来配置Servlet容器,换句话说我们可以在web容器启动时为提供给第三方组件机会做一些初始化的工作。

Spring的web框架中已经有了ServletContainerInitializer对应的实现类SpringServletContainerInitializer:

SpringServletContainerInitializer反过来又会去找WebApplicationInitializer接口的实现类,即AbstractAnnotationConfigDispatcherServletInitializer,然后就会将初始化的交给他。

AbstractAnnotationConfigDispatcherServletInitializer中做了什么?

3.SpringMVC启动的时候会创建两个两个应用上下文:

  • DispatcherServlet启动的时候会创建应用的上下文,它的配置就是在我们自定义的WebConfig中,DispatcherServlet加载的时候会包含Web组件的bean,如控制器,视图解析器,以及映射处理器,
  • 而另外一个应用上下文由ContextLoaderListener创建,它的作用是加载应用中的其他bean,这些通常是驱动应用后端的中间层或者数据层组件。

具体两个上下文创建的时候会去加载哪些bean,当然是让用户自己来决定:

  • getServletConfigClasses():定义 DispatcherServlet 应用上下文中的 beans
  • getRootConfigClasses():定义拦截器 ContextLoaderListener 应用上下文中的 beans

这种配置Servlet的方式只有Servlet3.0的服务器才能使用,如Tomcat7.0及以上。

下面配置SpringMVC,启动DispatcherServlet的方式有多种,那么启动SpringMVC的方式自然也有多种,我们还是使用java配置来实现,这个其实是延续上面DispatcherServlet配置的内容。

启动SpringMVC主要就是一个注解@EnableWebMvc ,启用注解驱动的Spring MVC,使@RequestParam、@RequestMapping等注解可以被识别并且这个类想要称为SpringMVC的启动类就必须要继承WebMvcConfigurationSupport,在SpringMVC的启动类里面需要配置视图解析器和对静态资源的处理:

package com.wx.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.context.ContextLoader;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.servlet.ViewResolver;
import org.springframework.web.servlet.config.annotation.DefaultServletHandlerConfigurer;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport;
import org.thymeleaf.TemplateEngine;
import org.thymeleaf.spring5.SpringTemplateEngine;
import org.thymeleaf.spring5.templateresolver.SpringResourceTemplateResolver;
import org.thymeleaf.spring5.view.ThymeleafViewResolver;
import org.thymeleaf.templatemode.TemplateMode;
import org.thymeleaf.templateresolver.ServletContextTemplateResolver;


/**
 * User: Mr.Wang
 * Date: 2020/2/9
 */
@Configuration
@EnableWebMvc// 相当于<mvc:annotation-driver/>,启用注解驱动的Spring MVC,使@RequestParam、@RequestMapping等注解可以被识别
@ComponentScan("com.wx")
public class WebConfig extends WebMvcConfigurationSupport {
    /**
     * 这里根据不同的前端配置不同的模板引擎
     *
     * @return
     */
    //1.配置模板解析器,ServletContextTemplateResolver被替换成SpringResourceTemplateResolver
    @Bean
    public SpringResourceTemplateResolver templateResolver(){
        SpringResourceTemplateResolver springResourceTemplateResolver = new SpringResourceTemplateResolver();
        springResourceTemplateResolver.setPrefix("/WEB-INF/templates/");
        springResourceTemplateResolver.setSuffix(".html");
        springResourceTemplateResolver.setTemplateMode("HTML5");
        springResourceTemplateResolver.setCacheable(false);
        springResourceTemplateResolver.setCharacterEncoding("UTF-8");
        return springResourceTemplateResolver;
//        WebApplicationContext webApplicationContext = ContextLoader.getCurrentWebApplicationContext();
//        // ServletContextTemplateResolver需要一个ServletContext作为构造参数,可通过WebApplicationContext 的方法获得
//        ServletContextTemplateResolver templateResolver = new ServletContextTemplateResolver(
//                webApplicationContext.getServletContext());
//        templateResolver.setPrefix("/WEB-INF/templates/");
//        templateResolver.setSuffix(".html");
//        // templateResolver.setCharacterEncoding("UTF-8");
//        // 设置模板模式,也可用字符串"HTML"代替,此处不建议使用HTML5,原因看下图源码
//        templateResolver.setTemplateMode(TemplateMode.HTML);
//        return templateResolver;

    }




    //2.配置Spring的模板引擎
    @Bean
    public SpringTemplateEngine templateEngine(SpringResourceTemplateResolver templateResolver){
        SpringTemplateEngine templateEngine = new SpringTemplateEngine();
        templateEngine.setTemplateResolver(templateResolver);
        return templateEngine;
    }
    //3.配置视图解析器
    @Bean
    public ViewResolver viewResolver(SpringTemplateEngine templateEngine) {
        ThymeleafViewResolver templateResolver = new ThymeleafViewResolver();
        templateResolver.setTemplateEngine(templateEngine);
        templateResolver.setCharacterEncoding("UTF-8");
        return templateResolver;
    }

    /**
     * 配置静态资源的处理
     *
     * @param configurer
     */
    @Override
    protected void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
        //对静态资源的请求转发到Servelt容器的默认Servlet中,而不是使用前端控制器来吃力这类请求
        configurer.enable();
    }
}

ServletConfig已经配置好了,下面我们配置RootConfig,基于web的开发,相关的配置都通过DispatcherServlet配置好了,RootConfig配置就很简单了。

package com.wx.config;

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.FilterType;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;

/**
 * User: Mr.Wang
 * Date: 2020/3/7
 * FilterType.ANNOTATION 按照注解的方式进行扫描.后面classes属性,为注解的类型
 */
@Configuration
@ComponentScan(basePackages = {"com.wx"}, excludeFilters = {
        @ComponentScan.Filter(type = FilterType.ANNOTATION, value = EnableWebMvc.class)
})
public class RootConfig {
}

测试:

package com.wx.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

/**
 * User: Mr.Wang
 * Date: 2020/3/7
 */
@Controller
public class IndexController {
    

    @RequestMapping("/v1/home")
    public String home() {
        return "index";
    }
}

 SpringMVC的java配置:https://blog.csdn.net/z28126308/article/details/54429853

 Spring自带的视图解析器:https://www.cnblogs.com/lyj-gyq/p/8963885.html

 4.自定义DispatcherServlet配置

   AbstractAnnotationConfigDispatcherServletInitializer将DispatcherServlet注册到Servlet容器中之后,就是掉用customizeRegistration()方法。

注册DispatcherServlet:

通过重载customizeRegistration()我们可以对DispatcherServlet进行额外的配置。

5.如何注册其他的Servlet,Filter,Listener.?

  第一种方法式是通过实现WebApplicationInitializer接口。如果是Filter的化还可以重载AbstractAnnotationConfigDispatcherServletInitializer的getServletFilter方法,这种方式就不需要指明Filter的路径,他会全部映射到DispatcherServlet上。

发布了217 篇原创文章 · 获赞 70 · 访问量 6万+

猜你喜欢

转载自blog.csdn.net/weixin_37650458/article/details/104229524