一、跟踪Spring MVC的请求
客户端发起请求,请求将经历各个组件:
- DispatcherServlet。Spring MVC 所有的请求都会通过一个前端控制器Servlet。前端控制器是常用的web应用程序模式,在这里一个单实例的Servlet将请求委托给应用程序的其他组件来执行实际的处理。在Spring MVC 中,DispatcherServlet就是前端控制器。DispatcherServlet的任务是将请求发送给控制器(controller)。DispatcherServlet会查询一个或多个处理器映射(handler mapping)来确定将请求发送给哪个controler
- 处理器映射。处理器映射会根据请求携带的URL信息进行决策。
- 控制器。选择合适的控制器后,DispatcherServlet卸下其负载(用户提交的信息),等待控制器处理这些信息。
- 模型及逻辑视图名。控制器完成逻辑处理后产生的信息叫做模型(model),一般需要将原始信息格式化,所以需要将信息发送给一个视图。
控制器最后将模型数据打包,并标示出用户渲染输出的视图名。它接下来会将请求连同模型和视图名发送回DispatcherServlet - 视图解析器。DispatcherServlet使用视图解析器将逻辑视图名匹配为一个特定的视图实现。
- 视图。视图将模型数据渲染输出,这个输出会通过响应对象传递给客户端。
二、搭建Spring MVC
1、配置DispatcherServlet
在web.xml中配置
在Servlet容器中配置
public class WebAppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
@Override
protected Class<?>[] getRootConfigClasses() {
return new Class<?>[] { RootConfig.class };
}
/**
* 指定配置类
* @return
*/
@Override
protected Class<?>[] getServletConfigClasses() {
return new Class<?>[] { WebConfig.class };
}
/**
* 将 DispatcherServlet映射到"/"
* @return
*/
@Override
protected String[] getServletMappings() {
return new String[] { "/" };
}
}
扩展了AbstractAnnotationConfigDispatcherServletInitializer
的类都会自动配置 DispatcherServler 和Spring 应用上下文,Spring 应用上下文在Servlet 上下文之中。
AbstractAnnotationConfigDispatcherServletInitializer
剖析
在Servlet 3.0环境中,容器会在类路径中查找实现了javax.servlet.SewrvletContainerIntializer
接口的类,如果能发现就用它来配置Servlet容器。
Spring提供了这个接口的实现,名为SpringServletContainerIntializer
,这个类反过来又会查找实现WebApplicationIntializer
的类并将配置的任务交给它们来完成。Spring 3.2 引入了一个便利的WebApplicationIntializer
基础实现,即AbstractAnnotationConfigDispatcherServletInitializer
。
两个应用上下文的区别
当 DispatcherServlet 启动的时候,它会创建Spring应用上下文,并加载配置文件中或配置类中所声明的bean。
在Spring Web,通常还会有另一个应用上下文,是由ContextLoderListener
创建的。
我们希望 DispatcherServlet
加载Web组件的bean,如控制器、视图解析器以及处理器映射,而ContextLoderListener
要加载应用中的其他bean,这些bean通常是驱动应用后端的中间层和数据层组件。
实际上AbstractAnnotationConfigDispatcherServletInitializer
会同时创建DispatcherServlet
和ContextLoderListener
。getServletConfigClasses()
方法返回的带有@Configuration
注解的类将会用来定义DispatcherServlet
应用上下文中的bean。getRootConfigClasses()
方法返回的带有@Configuration
注解的类将会用来定义ContextLoderListener
应用上下文中的bean。
启用Spring MVC
xml配置:<mvc:annotation-driven>
Java配置:@EnableWebMvc
public class WebConfig extends WebMvcConfigurationSupport {
/**
* 配置JSP 视图解析器
* @return
*/
@Bean
public ViewResolver viewResolver(){
InternalResourceViewResolver resolver = new InternalResourceViewResolver();
resolver.setPrefix("/WEB-INF/views/)");
resolver.setSuffix(".jsp");
resolver.setExposeContextBeansAsAttributes(true);
return resolver;
}
/**
* 配置静态资源的处理
* @param configurer
*/
@Override
protected void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
configurer.enable();
}
}
@Configuration
@ComponentScan(basePackages = { "cc.learn" }, excludeFilters = {
@ComponentScan.Filter(type = FilterType.ANNOTATION, value = EnableWebMvc.class) })
//@Import({ DataSourceConfig.class, MybatisConfig.class, ThreadConfig.class })
//@ImportResource("classpath:spring/spring.xml")
public class RootConfig {
@Bean
public static PropertySourcesPlaceholderConfigurer placeholderConfigurer() {
PropertySourcesPlaceholderConfigurer placeholderConfigurer = new PropertySourcesPlaceholderConfigurer();
return placeholderConfigurer;
}
}
2、编写控制器
@Controller
@RequestMapping(value="/",method = RequestMethod.GET)
测试控制器
public class PublucControllerTest {
@Test
public void testIndexPage() throws Exception {
PublicController publicController = new PublicController();
MockMvc mockMvc = MockMvcBuilders.standaloneSetup(publicController).build();
mockMvc.perform(MockMvcRequestBuilders.get("/")).andExpect(MockMvcResultMatchers.view().name("index"));
}
}
传递模型数据到视图中
@RequestMapping("/getAllUser")
//Model 可用 Map 代替
public String getAllUser(Model model) {
List<User> userList = userService.listAllUser();
model.addAttribute("userList",userList);
return "userList";
}
3、接收参数
@RequestParam
@PathVariable
4、处理表单
校验表单
Java校验API(Java Validation API ,又称JSR-303)
Java检验API提供的检验注解(位于 javax.valication.constrants 包中)
注解 | 描述 |
---|---|
@AssertFalse | 所注解的内容必须是Boolean ,并且值为fasle |
@AssertTrue | |
@DecimalMax | 必须是数字,并且值要小于或等于给定的BigDecimalString的值 |
@DecimalMin | |
@Digits | 必须是数字,并且值必须有指定的位数 |
@Future | 必须是一个将来的日期 |
@Max | 必须是数字,且小于等于给定的值 |
@Min | |
@NotNull | |
@Null | |
@Past | 必须是一个过去的日期 |
@Pattern | 必须匹配给定的正则表达式 |
@Size | 必须是String、集合或者数组,且长度符合给定的范围 |
启用校验
@RequestMapping(value="/register", method=POST)
public String processRegistration( @Valid Spitter spitter, Errors errors) {
//检查是否有错误
if (errors.hasErrors()) {
return "registerForm";
}
@Valid
注解表示Spitter对象需要满足检验限制,Errors
对象要紧跟带有@Valid注解的参数后面。