Spring MVC实战系列课程(4)-0配置实现spring mvc应用

Spring MVC实战系列教程(4)--0配置实现spring mvc应用

         之前我们的spring mvc应用搭建尽管有一部分可以使用spring注解,但环境的创建仍然要依赖xml配置文件,本节介绍利用servlet3新特性和spring的@configuration等注解来实现一个完全没有xml配置的spring mvc应用

 

   (一)概述

    之前的应用对xml配置文件的依赖主要有两块:

    1. web.xml,用于创建web应用的容器也就是servlet上下文,并且在当前web应用中声明spring mvc的核心servlet--DispatcherServlet,这个文件可以利用servlet3.x的编程式创建web容器的特性来替代,具体实现是可以通过spring3.1提供的WebApplicationInitializer接口来完成。

   2. spring mvc的核心配置文件,该文件主要配置要自动扫描的package,视图解析器等,该文件可以通过spring3以后提供的@Configuration,@ComponentScan,@Bean等注解用编程的方式替代。

 

  (二)实现WebApplicationInitializer接口替代web.xml

     自定义一个web应用初始化类,比如叫MyWebInitializer,实现spring的org.springframework.web.WebApplicationInitializer接口。该接口是spring用来封装servlet3.x配置的接口,其实现类在运行时将会被SpringServletContainerInitializer获取并自动调用WebApplicationInitializer实现类的onStartup方法,所以我们的初始化web容器的操作都定义在MyWebInitializer重写的onStartup方法中。代码如下:

public class MyWebInitializer implements WebApplicationInitializer {
    @Override
    public void onStartup(ServletContext servletContext) throws ServletException {
        // 创建spring容器
        AnnotationConfigWebApplicationContext ctx = new AnnotationConfigWebApplicationContext();
        ctx.register(SpringMVCConfig.class);// 在spring容器中加载spring mvc配置类
        ctx.setServletContext(servletContext);// 将spring容器放置在web容器中加载
        
        // 设置spring mvc核心控制器(DispatcherServlet)
        Dynamic springmvc = servletContext.addServlet("springmvc", new DispatcherServlet(ctx));
        springmvc.addMapping("/");
        springmvc.setLoadOnStartup(1);
    }
}

可以看到,web.xml中的所有配置都以编码方式一一替代,具体来说:

1. spring mvc核心控制器的声明和URL映射

<servlet-name>springmvc</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>

 

<servlet-mapping>
        <servlet-name>springmvc</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>

由这段代码替代:

Dynamic springmvc = servletContext.addServlet("springmvc", new DispatcherServlet(ctx));springmvc.addMapping("/");

这里使用了servlet3.0的ServletRegistration(具体是用其内部类Dynamic),用于向web容器即Servlet上下文动态注册一个servlet。

 

2. spring mvc核心配置文件的加载

     <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath:springmvc-config.xml</param-value>
        </init-param>

由这段代码替代:

AnnotationConfigWebApplicationContext ctx = new AnnotationConfigWebApplicationContext();
        ctx.register(SpringMVCConfig.class);// 在spring容器中加载spring mvc配置类

其中SpringMVCConfig我们自定义的用于替代spring mvc配置文件的类,也就是说该xml文件也将以编码方式替换,该类的实现稍后讲解。

 

3. DispatcherServlet启动加载优先级(用于在web容器启动时自动加载DispatcherServlet

<load-on-startup>1</load-on-startup>

由这段代码替代:

springmvc.setLoadOnStartup(1);

 

(三)借助spring注解以编码方式替代spring mvc配置文件

  刚才在配置Web容器时,我们为AnnotationConfigWebApplicationContext注册了一个叫SpringMVCConfig的自定义类,该类就是用来替代spring mvc核心配置文件的配置类,代码如下:

@Configuration
@EnableWebMvc
@ComponentScan("controller")
public class SpringMVCConfig {
    @Bean
    public InternalResourceViewResolver internalResourceViewResolver() {
        InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();
        viewResolver.setPrefix("/WEB-INF/jsp/");
        viewResolver.setSuffix(".jsp");
        return viewResolver;
    }
}

可以看到,该类是一个POJO,没有实现任何接口或继承任何基类,完全是依靠spring的几个注解完成功能。对比下之前的配置文件,可以分成这几个部分:

1. spring配置文件的根节点<beans>,该节点用类上的@Configuration来替代

2. 用于配置自动扫描的<context:component-scan base-package=“x.x”/>元素,在配置类中使用类上的@ComponentScan注解来替代

3.声明了一个InternalResourceViewResolver的spring bean,用于视图解析,在配置类中,每个<bean>元素的声明由一个方法+@Bean注解来替代。比如这个类,返回类型就是我们的视图解析器,并且以方法名作为bean的id。(所以这里的方法名看起来有点奇怪)
4. 最后还要在类上加上一个@EnableWebMvc注解,表示这是一个spring 的web容器的配置

   有了这两个配置类,我们就可以告别web.xml和spring mvc的配置文件了。

 

(四)修改POM文件

    由于maven打WAR包时默认要去找web.xml,现在我们已经没有这个文件了,build时就会报错,需要增加一个maven-war-plugin插件,并将failOnMissingWebXml节点设为false,让其打包时不去寻找web.xml即可

   <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-war-plugin</artifactId>
                <version>2.3</version>
                <configuration>
                    <failOnMissingWebXml>false</failOnMissingWebXml>
                </configuration>
            </plugin>