您的位置:首页 > 编程语言 > Java开发

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

2017-11-10 16:17 489 查看
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>,这两个是等效的

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

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

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

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

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

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/
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: