Spring学习笔记之构建Spring Web应用程序

Spring MVC起步

1. Spring MVC 的请求过程

Spring学习笔记之构建Spring Web应用程序_第1张图片

2. 搭建Spring MVC

2.1 用Java来搭建Spring MVC(需要Servlet 3.0环境)

配置DispatcherServlet和ContextLoaderListener

package spittr.config;

import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;

public class SpittrWebAppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer{

    //对应ContextLoaderListener
    @Override
    protected Class[] getRootConfigClasses() {
        return new Class[] { RootConfig.class };
    }

    //对于DispatcherServlet
    @Override
    protected Class[] getServletConfigClasses() {
        return new Class[] { WebConfig.class };//指定配置类
    }

    @Override
    protected String[] getServletMappings() {
        return new String[] { "/" };//将DispatcherServlet映射到"/"
    }

}

AbstractAnnotationConfigDispatcherServletInitializer剖析
在Servlet3.0环境中,容器会在类路径中查找实现javax.servlet.ServletContainerInitializer接口的类,如果发现的话,就会用它来配置Servlet容器。Spring提供了这个接口的实现,名为SpringServletContainerInitializer,这个两类反过来又会查找实现WebApplicationInitializer的类并将配置的任务交给它们来完成。Spring3.2引入了一个便利的WebApplicationInitializer基础实现,也就是AbstractAnnotationConfigDispatcherServletInitializer。因为我们的SpittrWebAppInitializer扩展了AbstractAnnotationConfigDispatcherServletInitializer(同时也实现了WebApplicationInitializer),因此当部署到Servlet3.0容器的时候,容器会自动发现它,并用它来配置Servlet上下文。

AbstractAnnotationConfigDispatcherServletInitializer会同时创建DispatcherServlet和ContextLoaderListener。getRootConfigClasses方法返回的带有@Configuration注解的类将用来定义ContextLoaderListener应用上下文的Bean。getServletConfigClasses方法返回的带有@Configuration注解的类将用来定义DispatcherServlet应用上下文的Bean。我们希望DispatcherServlet加载包含Web组件的Bean,如控制器、视图解析器以及处理器映射,而ContextLoaderListener要加载应用中的其他Bean。这些Bean通常是驱动应用后端的中间层和数据层组件。

配置Spring MVC

package spittr.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
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.WebMvcConfigurerAdapter;
import org.springframework.web.servlet.view.InternalResourceViewResolver;

@Configuration 
@EnableWebMvc //启用Spring MVC
@ComponentScan("spittr.web") //启用组件扫描
public class WebConfig 
        extends WebMvcConfigurerAdapter{

    /**
     * 配置JSP视图解析器
     * @return
     */
    @Bean
    public ViewResolver viewResolver(){
        InternalResourceViewResolver resolver = new InternalResourceViewResolver();
        resolver.setPrefix("/WEB-INF/view/");
        resolver.setSuffix(".jsp");
        resolver.setExposeContextBeansAsAttributes(true);
        return resolver;
    }

    /**
     * 配置静态资源的处理,要求DispatcherServlet将对静态资源的请求转发到Servlet
     * 容器默认的Servlet上,而不是使用DispatcherServlet本身来处理此类请求
     */
    @Override
    public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
        configurer.enable();
    }
}

自定义DispatcherServlet配置
在SpittrWebAppInitializer中我们重写了三个方法来配置DispatcherServlet,实际上有更多的方法可以进行重载从而实现对DispatcherServlet额外的配置。
方法之一就是customizeRegistration(),在AbstractAnnotationConfigDispatcherServletInitializer将DispatcherServlet注册到Servlet容器之后,就会调用customizeRegistration(),并将Servlet注册后得到的Registration.Dynamic传递进来。通过重载customizeRegistration()方法,我们可以对DispatcherServlet进行额外的配置。例如设置MultipartConfigElement:

@Override
    protected void customizeRegistration(Dynamic registration) {
        registration.setMultipartConfig(
                new MultipartConfigElement("/tmp/spittr/uploads"));
    }

至于这个设置到底是很忙我们将会在Spring上传中介绍。

添加其他的Servlet和Filter
如果我们想在web容器中注册其他的Servlet、Filter或者Listener,我们可以通过实现Spring的WebApplicationInitializer(我们前面说过Servlet3.0容器会自动寻找它的实现类并用来配置servlet容器)。例如注入一个servlet和一个Filter:

import javax.servlet.ServletContext;
import javax.servlet.ServletException;

import org.springframework.web.WebApplicationInitializer;

public class MyServletInitializer implements WebApplicationInitializer{

    public void onStartup(ServletContext servletContext) throws ServletException {
        //注册Servlet
        javax.servlet.ServletRegistration.Dynamic myServlet = 
                servletContext.addServlet("myServlet", MyServlet.class);
        myServlet.addMapping("/custom/**");//映射Servlet
        javax.servlet.FilterRegistration.Dynamic myFilter = 
                servletContext.addFilter("myFilter", MyFilter.class);
        myFilter.addMappingForUrlPatterns(null, false, "/custom/**");//添加Filter的映射路径
    }
}

如果你只是注册Filter并将其映射到DispatcherServlet上的话,在AbstractAnnotationConfigDispatcherServletInitializer中还有一种便捷的方法——重载getServletFilters()方法:

@Override
    protected Filter[] getServletFilters() {
        return new Filter[] { new MyFilter() };
    }

2.2 在web.xml中配置Spring MVC:
web.xml:


<web-app version="2.5" 
    xmlns="http://java.sun.com/xml/ns/javaee" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance 
    http://www.springmodules.org/schema/cache/springmodules-cache.xsd 
    http://www.springmodules.org/schema/cache/springmodules-ehcache.xsd" 
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee 
    http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">  
    
  <context-param>
    <param-name>contextConfigLocationparam-name>
    <param-value>classpath:applicationContext.xmlparam-value>
  context-param>

 <listener>
    <listener-class>org.springframework.web.context.ContextLoaderListenerlistener-class>
 listener>

 <servlet>
    <servlet-name>dispatcherServletservlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServletservlet-class>
    <init-param>
        
        <param-name>contextConfigLocationparam-name>
        <param-value>classpath:dispatcherServlet-context.xmlparam-value>
    init-param>
    <load-on-startup>1load-on-startup>
 servlet>

 <servlet-mapping>
    <servlet-name>dispatcherServletservlet-name>
    <url-pattern>/url-pattern>
 servlet-mapping>
web-app>

applicationContext.xml:


<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop"
    xmlns:tx="http://www.springframework.org/schema/tx" xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd">

    <bean id="test" class="spittr.web.Test" />

    <context:component-scan base-package="spittr" />

beans>

dispatcherServlet-context.xml:


<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop"
    xmlns:tx="http://www.springframework.org/schema/tx" xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd">

    <bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix">/WEB-INF/property>
        <property name="suffix">.jspproperty>
    bean>

beans>

2.3 让web.xml使用Java配置而不是XML配置
也即是说让Spring MVC在启动的时候,从带有@Configuration注解的类上加载配置,我们需要告诉DispatcherServlet和ContextLoaderListener使用AnnotationConfigWebApplicationContext,这是一个WebApplicationContext的实现类,它会加载Java配置类,而不是使用XML。要实现这种配置,我们只需要设置contextClass上下文参数以及DispatcherServlet的初始化参数。


<web-app version="2.5" 
    xmlns="http://java.sun.com/xml/ns/javaee" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance 
    http://www.springmodules.org/schema/cache/springmodules-cache.xsd 
    http://www.springmodules.org/schema/cache/springmodules-ehcache.xsd" 
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee 
    http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
 
    <context-param>
        <param-name>contextClassparam-name>
        <param-value>org.springframework.web.context.support.AnnotationConfigWebApplicationContextparam-value>
    context-param>

  <context-param>
    <param-name>contextConfigLocationparam-name>
    
    <param-value>spittr.config.RootConfigparam-value>
  context-param>

 <listener>
    <listener-class>org.springframework.web.context.ContextLoaderListenerlistener-class>
 listener>

 <servlet>
    <servlet-name>dispatcherServletservlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServletservlet-class>
    
    <init-param>
        <param-name>contextClassparam-name>
        <param-value>org.springframework.web.context.support.AnnotationConfigWebApplicationContextparam-value>
    init-param>
    <init-param>
        <param-name>contextConfigLocationparam-name>
        
        <param-value>spittr.config.WebConfigparam-value>
    init-param>
    <load-on-startup>1load-on-startup>
 servlet>

 <servlet-mapping>
    <servlet-name>dispatcherServletservlet-name>
    <url-pattern>/url-pattern>
 servlet-mapping>
web-app>

控制器

占位符
Spring MVC允许我们在@RequestMapping路径中添加占位符。占位符的名称要用大括号(“{”和”}”)括起来。路径中的其他部分要与所处理的请求完全匹配,但是占位符部分是任意的值。

package spittr.web;

import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;

public class Spittler {

    @RequestMapping("/{spittleId}")
    public String spittle(
            @PathVariable("spittleId") long spittleId){
        System.out.println(spittleId);
        return "page";
    }
}

这样,在请求路径中,不管占位符部分的值是什么都会传递到处理器方法的spittleId参数中。
如果@PathVariable中没有value属性的话,它会假设占位符的名称与方法的参数名相同。

重定向和前往指定的URL路径

return "redirect:/spitter/";//重定向
return "forward:/spitter";//前往指定的URL路径

表单检验
从Spring3.0开始,Spring MVC中提供了对Java 校验API的支持。

public class User {

    @NotNull
    @Size(min=5,max=16)
    private String userName; //非空,5-16个字符
    @NotNull
    @Size(min=6, max=10)
    private String password;//非空,6-10个字符

}
package spittr.web;

import org.springframework.validation.Errors;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.RequestMapping;

import spittr.entity.User;

public class Spittler {

    @RequestMapping("/login")
    public String spittle(
            @Validated User user,//校验输入
            Errors errors){
        if(errors.hasErrors()){
            return "registerForm";//如果校验出现错误,则重新返回表单。
        }
        return "redirect:/spitter/";
    }
}

Errors参数要紧跟在带有校验注解的参数后面。

你可能感兴趣的:(Spring学习笔记)