自定义对象作为@RequestParam

时间:2019-03-26 16:21:24

标签: spring rest spring-mvc

我有一个分页的端点,看起来像/ api / clients?range = 0-25。

我希望我的ClientController中的getClients()方法直接接收自定义Range对象的实例,而不必验证“ 0-25”字符串,但是我很难弄清楚这一点。

@Getter
final class Range {

    @Min(0)
    private Integer offset = 0;

    @Min(1)
    private Integer limit = 25;
}
@ResponseBody
@GetMapping(params = { "range" })
public ResponseEntity<?> getAllClients(@RequestParam(value = "range", required = false) QueryRange queryRange, final HttpServletResponse response) {
    ...
}

我不确定如何指示控制器正确地将“ 0-25”字符串反序列化为Range ...

2 个答案:

答案 0 :(得分:0)

您可以使用Converter<S, T>,如下所示:

@Component
public class RangeConverter implements Converter<String, Range> {

    @Override
    public Range convert(String source) {
        String[] values = source.split("-");
        return new Range(Integer.valueOf(values[0]), Integer.valueOf(values[1]));
    }
}

您还可以根据需要处理无效值。如果按原样使用上述转换器,则尝试转换无效值(例如1-x)将导致ConversionFailedException

答案 1 :(得分:0)

您似乎还可以执行以下操作:

public class QueryRangeEditor extends PropertyEditorSupport {

    private static final Pattern PATTERN = Pattern.compile("^([1-9]\\d*|0)-([1-9]\\d*|0)$");

    @Override
    public void setAsText(String text) throws IllegalArgumentException {

        final QueryRange range = new QueryRange();

        Matcher matcher = PATTERN.matcher(text);

        if (matcher.find()) {

            range.setOffset(Integer.valueOf(matcher.group(1)));
            range.setLimit(Integer.valueOf(matcher.group(2)));
        } else {
            throw new IllegalArgumentException("OI"); // todo - replace
        }
        setValue(range);
    }
}
@InitBinder
public void initBinder(WebDataBinder binder) {
    binder.registerCustomEditor(QueryRange.class, new QueryRangeEditor());
}

但是@cassiomolin看起来更干净...