Spring 实战-第五章-构建Spring Web应用程序

SpringWeb应用程序,这里指的的是Spring MVC框架,包括了控制器,对象,视图解析,渲染等功能。

ref:http://blog.csdn.net/zuoluoboy/article/details/19766131 

MVC结构图如上,其中DispacherServlet是整个系统的核心,用于分配、调用各个模块。

流程上,请求到服务器,DispatcherServlet查询处理映射器(handler mapping),确定需要使用哪个Controller,当Controller接收到请求后,会将数据打包和需要使用的视图名称,

返回到DispatcherServlet,DispatcherServlet会根据视图名称,找到对应的机图解析器(view resolver),视图解析器会根据数据和视图进行渲染,然后返回。

按照传统方式,需要增加很多xml配置,java based配置方式相对更简单明了。

配置DispatcherServlet

package spittr.config;

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

/**
 * Created by jwlv on 2017/10/27.
 */
public class SpittrWebAppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {

    //for "root" application context (non-web infrastructure) configuration.
    //返回的带有@Configuration注解的类将会用来配置ContextLoaderListener创建的应用上下文中的Bean
    @Override
    protected Class<?>[] getRootConfigClasses() {
        return new Class<?>[]{RootConfig.class};
    }

    // for DispatcherServlet application context (Spring MVC infrastructure) configuration.
    //返回的带有@Configuration注解的类将会用来定义DispatcherServlet应用上下文中的Bean
    @Override
    protected Class<?>[] getServletConfigClasses() {
        return new Class<?>[]{WebConfig.class};
    }

    //将一个或多个路径映射到DispatcherServlet上
    @Override
    protected String[] getServletMappings() {
        return new String[]{"/"};
    }
}

当DispatcherServlet启动的时候,会创建Spring应用上下文,并加载配置文件或配置类中所声明的bean。

配置WebConfig

package spittr.web;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
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;

/**
 * Created by jwlv on 2017/10/27.
 */
@Configuration
@EnableWebMvc
@ComponentScan("spittr.web")
public class WebConfig extends WebMvcConfigurerAdapter{

    @Bean
    public ViewResolver viewResolver(){
        InternalResourceViewResolver resolver= new InternalResourceViewResolver();
        resolver.setPrefix("/WEB-INF/views/");
        resolver.setSuffix(".jsp");
        resolver.setExposeContextBeansAsAttributes(true);
        return resolver;
    }

    @Override
    public void configureDefaultServletHandling(
            DefaultServletHandlerConfigurer configurer){
        configurer.enable();
    }

//    @Autowired
//    private AnnotationConfigWebApplicationContext applicationContext;
}

@EnableWebMvc用来启用注解驱动的SpringMVC,如果是通过xml配置,需要xml中增加<mvc:annotation-driven>,这两个是等效的

于此同时,这还启用了其他特性,包括

  1. Spring 3 style type conversion through a ConversionService instance in addition to the JavaBeans PropertyEditors used for Data Binding.

  2. Support for formatting Number fields using the @NumberFormat annotation through the ConversionService.

  3. Support for formatting Date, Calendar, Long, and Joda Time fields using the @DateTimeFormat annotation.

  4. Support for validating @Controller inputs with @Valid, if a JSR-303 Provider is present on the classpath.

  5. HttpMessageConverter support for @RequestBody method parameters and @ResponseBody method return values from @RequestMapping or@ExceptionHandler methods.

ref:https://docs.spring.io/spring/docs/3.2.x/spring-framework-reference/html/mvc.html#mvc-config-enable

viewResolver()方法会用来解析视图地址,根据controller返回的视图名称,和这里配置的前缀后缀,会找到对应的视图。

比如controller返回了“homepage”,根据这里的配置,找到的地址是~/WEB-INF/views/homepage.jsp。

定义控制器

package spittr.web;

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

import static org.springframework.web.bind.annotation.RequestMethod.GET;

/**
 * Created by jwlv on 2017/10/27.
 */
@Controller
@RequestMapping({"/home","/testhome"})
public class HomeController {
    @RequestMapping(method=GET)
    public  String home(){
        return "home";
    }

    @RequestMapping(value="/homepage", method=GET)
    public  String home2(){
        return "home";
    }

}

Controller的Mapping

handler mapping会根据请求的地址,结合controller上的RequestMapping,找到合适的controller,RequestMapping注解可以用于类和方法,可以灵活组合,method参数表示了请求的类型

如上controller,可以对应如下地址

类级别:http://localhost:8080/home,http://localhost:8080/testhome

方法级别:http://localhost:8080/homepage

类和方法组合:http://localhost:8080/home/homepage,http://localhost:8080/testhome/homepage

Controller的传值

请求传入到Controller,可以查询参数、路径参数、对象等方式实现

//通过查询参数传入
@RequestMapping(method=RequestMethod.GET)
public List<Spittle> spittles(
        @RequestParam(value="max",defaultValue = "9999") long max,
        @RequestParam(value="count",defaultValue = "20") int count) {
    return spittleRepository.findSpittles(max,count);
}

//通过路径参数传入
@RequestMapping(value="/{spittleId}",method=RequestMethod.GET)
public String findOne(
        @PathVariable("spittleId") long spittleId,
        Model model){
    model.addAttribute("spittle",spittleRepository.findOne(spittleId));
    return "spittle";
}

//通过对象Post表单传入
@RequestMapping(value="/register",method = POST)
public String processRegistration(
        @Valid Spitter spitter,
        Errors errors){
    if(errors.hasErrors()){
        return "registerForm";
    }
    spitterRepository.save(spitter);
    return "redirect:/spitter/"+ spitterRepository.findByUsername("").getUsername();
}

Controller传入到View,可以通过Model、Map、对象或集合,本质是传KeyValue

//调用addAttribute()方法并且不指定key的时候,key会根据值的对象类型判断,
//此处因为是一个List<Spittle>,故键将会推断为spittleList
@RequestMapping(method = RequestMethod.GET)
public String spittles(Model model){
    model.addAttribute(
            spittleRepository.findSpittles(Long.MAX_VALUE,20));
    return "spittles";
}

//显示指定key
@RequestMapping(method = RequestMethod.GET)
public String spittles(Model model){
    model.addAttribute("spittleList",
            spittleRepository.findSpittles(Long.MAX_VALUE,20));
    return "spittles";
}

//使用Map作为入参
@RequestMapping(method = RequestMethod.GET)
public String spittles(Map model) {
    model.put("spittleList",
            spittleRepository.findSpittles(Long.MAX_VALUE,20));
    return "spittles";
}

//当处理器方法返回对象或集合时,这个值会放到模型中,模型的key会根据其类型推断得出。此处为spittleList
//逻辑视图的名称将会根据请求路径推断得出。因为这个方法处理针对“/spittles”的GET请求,
//因此视图的名称将会是spittles(去掉开头的斜线)
@RequestMapping(method = RequestMethod.GET)
public List<Spittle> spittles(Model model) {
    return spittleRepository.findSpittles(Long.MAX_VALUE,20);
}

校验表单

Spring3.0开始,Spring MVC中提供了对Java校验API的支持(Java Validation API,又称JSR-303),当启用注解驱动时,不需要额外的配置,只要保证在类路径下包含这个API的实现即可,比如Hibernate Validator。

package spittr;

import org.apache.commons.lang3.builder.EqualsBuilder;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;

/**
 * Created by jwlv on 2017/11/7.
 */
public class Spitter {
    private Long id;

    @NotNull
    @Size(min = 5,max = 16)
    private String username;

    @NotNull
    @Size(min = 5,max = 25)
    private String password;

    @NotNull
    @Size(min = 2,max = 30)
    private String firstName;

    @NotNull
    @Size(min = 2,max = 30)
    private String lastName;
    
    ...    
}

同时在Controller中使用@Valid注解,Errors对象要紧跟在有@Valid注解的参数后面,使用的时候,如果有不符合格式的传入,errors.hasErrors()会返回true。

@RequestMapping(value="/register",method = POST)
    public String processRegistration(
            @Valid Spitter spitter,
            Errors errors){
        if(errors.hasErrors()){
            return "registerForm";
        }
        spitterRepository.save(spitter);
        //return "redirect:/spitter/"+ spitter.getUsername();
        return "redirect:/spitter/"+ spitterRepository.findByUsername("").getUsername();
    }

code:https://github.com/ljw8947/SpringInAction/tree/master/Capter5/Spittr

参考:

https://docs.spring.io/spring/docs/3.2.x/spring-framework-reference/html/mvc.html

http://benweizhu.github.io/blog/2014/07/19/spring-validation-by-example/

原文地址:https://www.cnblogs.com/lvjianwei/p/7815219.html