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 theConversionService
. -
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/