5.3.1 处理查询参数
在 Spittr 应用中,我们可能需要处理的一件事就是展现分页的 Spittle 列表。在现在的 SpittleController 中,它只能展现最新的 Spittle,并没有办法向前翻页查看以前编写的 Spittle 历史记录。如果你想让用户每次都能查看某一页的 Spittle 历史,那么就需要提供一种方式让用户传递参数进来,进而确定要展现哪些 Spittle 集合。
在确定该如何实现时,假设我们要查看某一页 Spittle 列表,这个列表会按照最新的 Spittle 在前的方式进行排序。因此,下一页中第一条的 ID 肯定会早于当前页最后一条的 ID。所以,为了显示下一页的 Spittle,我们需要将一个 Spittle 的 ID 传入进来,这个 ID 要恰好小于当 前页最后一条 Spittle 的 ID。另外,你还可以传入一个参数来确定要展现的 Spittle 数量。
为了实现这个分页的功能,我们所编写的处理器方法要接受如下的参 数:
  • before 参数(表明结果中所有 Spittle 的 ID 均应该在这个值之前)。
  • count 参数(表明在结果中要包含的 Spittle 数量)。
为了实现这个功能,我们将程序清单 5.10 中的 spittles() 方法替换为使用 before 和 count 参数的新 spittles() 方法。我们首先添加一个测试,这个测试反映了新 spittles() 方法的功能。
程序清单 5.11 用来测试分页 Spittle 列表的新方法
1
@Test
2
public void shouldShowRecentSpittles() throws Exception {
3
List<Spittle> expectedSpittles = createSpittleList(50);
4
SpittleRepository mockRepository = mock(SpittleRepository.class);
5
when(mockRepository.findSpittles(238900, 50))
6
.thenReturn(expectedSpittles);
7
8
SpittleController controller = new SpittleController(mockRepository);
9
MockMvc mockMvc = standaloneSetup(controller)
10
.setSingleView(new InternalResourceView("/WEB-INF/views/spittles.jsp"))
11
.build();
12
13
mockMvc.perform(get("/spittles?max=238900&count=50"))
14
.andExpect(view().name("spittles"))
15
.andExpect(model().attributeExists("spittleList"))
16
.andExpect(model().attribute("spittleList", hasItems(expectedSpittles.toArray())));
17
}
Copied!
这个测试方法与程序清单 5.9 中的测试方法关键区别在于它针对 /spittles 发送 GET 请求,同时还传入了 max 和 count 参数。它测试了这些参数存在时的处理器方法,而另一个测试方法则测试了没有这些参数时的情景。这两个测试就绪后,我们就能确保不管控制器发生什么样的变化,它都能够处理这两种类型的请求:
1
@RequestMapping(method=RequestMethod.GET)
2
public List<Spittle> spittles(
3
@RequestParam("max") long max,
4
@RequestParam("count") int count) {
5
return spittleRepository.findSpittles(max, count);
6
}
Copied!
SpittleController 中的处理器方法要同时处理有参数和没有参数的场景,那我们需要对其进行修改,让它能接受参数,同时,如果这些参数在请求中不存在的话,就使用默认值 Long.MAX_VALUE 和 20。@RequestParam 注解的default-Value 属性可以完成这项任务:
1
@RequestMapping(method=RequestMethod.GET)
2
public List<Spittle> spittles(
3
@RequestParam(value="max", defaultValue=MAX_LONG_AS_STRING) long max,
4
@RequestParam(value="count", defaultValue="20") int count) {
5
return spittleRepository.findSpittles(max, count);
6
}
Copied!
现在,如果 max 参数没有指定的话,它将会是 Long 类型的最大值。因为查询参数都是 String 类型的,因此 defaultValue 属性需要 String 类型的值。因此,使用 Long.MAX_VALUE 是不行的。我们可以将 Long.MAX_VALUE 转换为名为 MAX_LONG_AS_STRING 的 String 类型常量:
1
private static final String MAX_LONG_AS_STRING = Long.toString(Long.MAX_VALUE);
Copied!
尽管 defaultValue 属性给定的是 String 类型的值,但是当绑定到方法的 max 参数时,它会转换为 Long 类型。
如果请求中没有 count 参数的话,count 参数的默认值将会设置为 20。
请求中的查询参数是往控制器中传递信息的常用手段。另外一种方式也很流行,尤其是在构建面向资源的控制器时,这种方式就是将传递参数作为请求路径的一部分。让我们看一下如何将路径变量作为请求路径的一部分,从而实现信息的输入。
Last modified 2yr ago
Copy link