一次获取具有多个参数的映射

时间:2018-09-27 15:38:45

标签: spring rest endpoint gateway

我有这样的映射:

@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个参数的设置,我认为确实太过分了) 有什么想法可以解决我的问题吗?

编辑 这是我的DateRange类:

@Data
@AllArgsConstructor
@NoArgsConstructor
public class DateRange {
    LocalDate begin;
    LocalDate end;
}

2 个答案:

答案 0 :(得分:2)

添加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);
}

答案 1 :(得分:0)

您需要一种将DateRange类转换为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)防错,因为传递了订单请求参数,所以并不严格。另一方面,将参数打包到单个对象中将迫使您注意参数顺序。此外,您必须将所有参数打包为字符串,因此不允许使用任何可选参数,否则拆包逻辑可能会被破坏