Spring MVC允许多种方式将客户端中的数据传输到控制器的处理方法中,包括:
- 查询参数
- 表单参数
- 路径变量
1、处理查询参数
控制器方法例子:
@RequestMapping(method=RequestMethod.GET)
public List<Spittle> spittles(
@RequestParam(value="max", defaultValue=MAX_LONG_AS_STRING) long max,
@RequestParam(value="count", defaultValue="20") int count){
return spittleRepository.findSpittles(max, count);
}
注意,查询参数都是String类型的,因此defaultValue不能使用Long.MAX_VALUE。
测试方法例子:
@Test
public void shouldShowPagedSpittles() throws Exception{
List<Spittle> expectedSpittles = createSpittleList(50);
SpittleRepository mockRepository = mock(SpittleRepository.class);
when(mockRepository.findSpittles(238900, 50)).thenReturn(expectedSpittles);
SpittleController controller = new SpittleController(mockRepository);
MockMvc mockMvc = standaloneSetup(controller)
.setSingleView(new InternalResourceView("/WEB-INF/views/spittles.jsp"))
.build();
mockMvc.perform(get("/spittle?max=238900&count=50"))
.andExpect(view().name("spittles"))
.andExpect(model().attributeExists("spittleList"))
.andExpect(model().attribute("spittleList",
hasItems(expectedSpittles.toArray())));
}
2、通过路径参数接受输入
控制器方法例子:
@RequestMapping(value="/{spittleId}", method=RequestMethod.GET)
public String spittle(@PathVariable long spittleId, Model model) {
model.addAttribute(spittleRepository.findOne(spittleId));
return "spittle";
}
测试方法例子:
@Test
public void testSpittle() throws Exception{
Spittle expectedSpittle = new Spittle("Hello", new Date());
SpittleRepository mockRepository = mock(SpittleRepository.class);
when(mockRepository.findOne(12345)).thenReturn(expectedSpittle);
SpittleController controller = new SpittleController(mockRepository);
MockMvc mockMvc = standaloneSetup(controller).build();
mockMvc.perform(get("/spittles/12345"))
.andExpect(view().name("spittle"))
.andExpect(model().attributeExists("spittle"))
.andExpect(model().attribute("spittle", expectedSpittle));
}
3、处理表单
处理表单的控制器方法例子:
@RequestMapping(value="/{username}", method=RequestMethod.GET)
public String showSpitterProfile(
@PathVariable String username, Model model) {
Spitter spitter = spitterRepository.findByUsername(username);
model.addAttribute(spitter);
return "profile";
测试处理表单的控制器方法例子:
@Test
public void shouldProcessRegistration() throws Exception{
SpitterRepository mockRepository = mock(SpitterRepository.class);
Spitter unsaved = new Spitter("jbauer", "24hours", "Jack", "Bauer");
Spitter saved = new Spitter(24L, "jbauer", "24hours", "Jack", "Bauer");
when(mockRepository.save(unsaved)).thenReturn(saved);
SpitterController controller = new SpitterController(mockRepository);
MockMvc mockMvc = standaloneSetup(controller).build();
mockMvc.perform(post("/spitter/register")
.param("firstName", "Jack")
.param("lastName", "Bauer")
.param("username", "jbauer")
.param("password", "24hours"))
.andExpect(redirectedUrl("/spitter/jbauer"));
verify(mockRepository, atLeastOnce()).save(unsaved);
}
4、校验表单
java校验API所提供的校验注解(javax.validation.constraints):
在属性上添加校验注解例子:
@NotNull
@Size(min=5, max=16)
private String username;
在属性上添加校验注解并不能组织表单提交,因此必须在数据保存之前处理校验错误,例子如下:
@RequestMapping(value="/register", method=RequestMethod.POST)
public String processRegistration(@Valid Spitter spitter, Errors errors) {
if(errors.hasErrors()) {
return "registerForm";
}
spitterRepository.save(spitter);
return "redirect:/spitter/" + spitter.getUsername();
}
注:Errors参数要紧跟在带有@Valid注解的参数后面。