一次获取多个参数的映射
Get mapping with multiple params as once
我有这样的映射:
@GetMapping(value = "/topics", params = "dateRange")
public Set<Integer> getTopicsInRange(@RequestParam DateRange dateRange) {
return topicService.getTopicsInRange(dateRange);
}
现在我想测试它:
private final static DateRange VALID_DATE_RANGE = new DateRange(LocalDate.of(2018, 1, 1), LocalDate.of(2018, 2, 2));
@Test
public void gettingTopicsInRangeShouldReturn200(){
given().
.when()
.get(String.format("/topics?dateRange=%s", VALID_DATE_RANGE)
.then()
.statusCode(200);
}
Expected status code <200> doesn't match actual status code <400>.
我知道如果我将我的 DateRange 参数更改为 2 个单独的参数,我的解决方案就会起作用:
@GetMapping(value = "/topics", params = {"begin", "end"})
public Set<Integer> getTopicsInRange(@RequestParam Date begin, @RequestParam Date end) {
return topicService.getTopicsInRange(begin, end);
}
然后将其测试为 /topics?begin=value&end=value2
但这不是我要找的(如果 DateRange 会喜欢 10 个字段使 10 个参数我认为真的太多了)
有什么想法可以解决我的问题吗?
编辑
这是我的日期范围 class:
@Data
@AllArgsConstructor
@NoArgsConstructor
public class DateRange {
LocalDate begin;
LocalDate end;
}
添加DateTimeFormat
注释:
public class DateRange {
@DateTimeFormat(pattern = "yyyy-MM-dd")
private LocalDate begin;
@DateTimeFormat(pattern = "yyyy-MM-dd")
private LocalDate end;
// getter and setters
}
在控制器中接收对象:
@GetMapping(value = "/topics")
public Set<Integer> getTopicsInRange(DateRange dateRange) {
return topicService.getTopicsInRange(dateRange);
}
并分别发送参数:
@Test
public void gettingTopicsInRangeShouldReturn200() {
given()
.queryParams("begin", LocalDate.of(2018, 1, 1).format(ISO_DATE),
"end", LocalDate.of(2018, 2, 2))
.when()
.get("/topics")
.then()
.statusCode(200);
}
您需要一种方法将 DateRange class 转换为 String,反之亦然。由于您使用的是 Spring,因此可以这样做:
1) 添加转换逻辑
@Data
@AllArgsConstructor
@NoArgsConstructor
public class DateRange {
LocalDate begin;
LocalDate end;
private static final String DELIMITER = "_";
public static DateRange fromFormattedString(String source) {
if (source != null) {
String[] tokens = source.split(DELIMITER);
if (tokens.length == 2) {
return new DateRange(
LocalDate.parse(tokens[0]), // begin
LocalDate.parse(tokens[1]) // end
);
}
}
return null;
}
public String toFormattedString() {
return begin + DELIMITER + end;
}
}
2) 创建 Spring 转换器
import org.springframework.core.convert.converter.Converter;
public class DateRangeConverter implements Converter<String, DateRange> {
@Override
public DateRange convert(String source) {
return DateRange.fromFormattedString(source);
}
}
3) 注册这个转换器
这将允许 Spring 处理作为 @RequestParam
-s
传递的 DateRange 对象
@Configuration
public class WebApiConfiguration extends WebMvcConfigurationSupport {
...
@Override
public FormattingConversionService mvcConversionService() {
FormattingConversionService f = super.mvcConversionService();
f.addConverter(new DateRangeConverter());
return f;
}
...
}
最后像这样使用:
.get(String.format("/topics?dateRange=%s", VALID_DATE_RANGE.toFormattedString())
或(使用原始字符串):
.get(String.format("/topics?dateRange=%s", "2018-1-1_2018-2-2")
但是:
尽管如此,我还是建议您使用单独的请求参数(开始、结束等),即使它们有 10 个,因为它是:
1) RESTful 方式
2)防错,因为传入的是订单请求参数,所以不严格。另一方面,将参数打包到单个对象中会迫使您注意参数顺序。此外,您必须将所有参数打包为字符串,因此不允许使用可选参数,否则解包逻辑可能会被破坏
我有这样的映射:
@GetMapping(value = "/topics", params = "dateRange")
public Set<Integer> getTopicsInRange(@RequestParam DateRange dateRange) {
return topicService.getTopicsInRange(dateRange);
}
现在我想测试它:
private final static DateRange VALID_DATE_RANGE = new DateRange(LocalDate.of(2018, 1, 1), LocalDate.of(2018, 2, 2));
@Test
public void gettingTopicsInRangeShouldReturn200(){
given().
.when()
.get(String.format("/topics?dateRange=%s", VALID_DATE_RANGE)
.then()
.statusCode(200);
}
Expected status code <200> doesn't match actual status code <400>.
我知道如果我将我的 DateRange 参数更改为 2 个单独的参数,我的解决方案就会起作用:
@GetMapping(value = "/topics", params = {"begin", "end"})
public Set<Integer> getTopicsInRange(@RequestParam Date begin, @RequestParam Date end) {
return topicService.getTopicsInRange(begin, end);
}
然后将其测试为 /topics?begin=value&end=value2
但这不是我要找的(如果 DateRange 会喜欢 10 个字段使 10 个参数我认为真的太多了)
有什么想法可以解决我的问题吗?
编辑 这是我的日期范围 class:
@Data
@AllArgsConstructor
@NoArgsConstructor
public class DateRange {
LocalDate begin;
LocalDate end;
}
添加DateTimeFormat
注释:
public class DateRange {
@DateTimeFormat(pattern = "yyyy-MM-dd")
private LocalDate begin;
@DateTimeFormat(pattern = "yyyy-MM-dd")
private LocalDate end;
// getter and setters
}
在控制器中接收对象:
@GetMapping(value = "/topics")
public Set<Integer> getTopicsInRange(DateRange dateRange) {
return topicService.getTopicsInRange(dateRange);
}
并分别发送参数:
@Test
public void gettingTopicsInRangeShouldReturn200() {
given()
.queryParams("begin", LocalDate.of(2018, 1, 1).format(ISO_DATE),
"end", LocalDate.of(2018, 2, 2))
.when()
.get("/topics")
.then()
.statusCode(200);
}
您需要一种方法将 DateRange class 转换为 String,反之亦然。由于您使用的是 Spring,因此可以这样做:
1) 添加转换逻辑
@Data
@AllArgsConstructor
@NoArgsConstructor
public class DateRange {
LocalDate begin;
LocalDate end;
private static final String DELIMITER = "_";
public static DateRange fromFormattedString(String source) {
if (source != null) {
String[] tokens = source.split(DELIMITER);
if (tokens.length == 2) {
return new DateRange(
LocalDate.parse(tokens[0]), // begin
LocalDate.parse(tokens[1]) // end
);
}
}
return null;
}
public String toFormattedString() {
return begin + DELIMITER + end;
}
}
2) 创建 Spring 转换器
import org.springframework.core.convert.converter.Converter;
public class DateRangeConverter implements Converter<String, DateRange> {
@Override
public DateRange convert(String source) {
return DateRange.fromFormattedString(source);
}
}
3) 注册这个转换器
这将允许 Spring 处理作为 @RequestParam
-s
@Configuration
public class WebApiConfiguration extends WebMvcConfigurationSupport {
...
@Override
public FormattingConversionService mvcConversionService() {
FormattingConversionService f = super.mvcConversionService();
f.addConverter(new DateRangeConverter());
return f;
}
...
}
最后像这样使用:
.get(String.format("/topics?dateRange=%s", VALID_DATE_RANGE.toFormattedString())
或(使用原始字符串):
.get(String.format("/topics?dateRange=%s", "2018-1-1_2018-2-2")
但是:
尽管如此,我还是建议您使用单独的请求参数(开始、结束等),即使它们有 10 个,因为它是:
1) RESTful 方式
2)防错,因为传入的是订单请求参数,所以不严格。另一方面,将参数打包到单个对象中会迫使您注意参数顺序。此外,您必须将所有参数打包为字符串,因此不允许使用可选参数,否则解包逻辑可能会被破坏