Spring 控制器:将查询参数绑定到自定义 POJO 字段

Spring Controller: bind query parameters to custom POJO fields

我正在尝试将某些值从请求查询参数映射到 POJO 参数,如下所示。 这是 POJO:

import lombok.*;
import org.springframework.format.annotation.DateTimeFormat;

import javax.validation.constraints.Min;
import javax.validation.constraints.NotNull;
import java.time.LocalDateTime;
import java.util.Map;

@Data
@Builder
@ToString
@AllArgsConstructor
@NoArgsConstructor
public class Person {
    @NotNull(message = "personId cannot be null")
    @Min(value = 0)
    private Long personId;

    @NotNull(message = "from date cannot be null")
    @DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME)
    private LocalDateTime from;

    @NotNull(message = "to date cannot be null")
    @DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME)
    private LocalDateTime to;

    private Map<String, String> filters;
}

这是控制器:

    @GetMapping(path = "/persons")
    public ResponseEntity<Integer> getPersons(@Valid final Person personRequest) throws Exception {
        return ResponseEntity.ok(personService.getPersonsCount(personRequest));
    }

我想将请求查询参数映射到这个 pojo 的属性。这是预期的请求:

{application_url}/persons?personId=12&from=2017-03-22T00:00:00&to=2019-03-22T00:00:00&country=UK&company=xyz

我想将 personId, from, to 映射到 POJO 中的相应属性,并将其余查询参数 nationality, company 映射到过滤器映射。换句话说 personId, to, from 在请求中只是静态的,其余参数可能会有所不同,我们可以使用 salary=1000&minAage=31 而不是 country=UK&company=xyz 所以我想将其余参数映射到filters地图。

有办法实现吗?

实现它的方法是将 @RequestParam Map<String, String> filters 与其他请求参数一起使用,或者只使用 map 作为请求参数。因为所有参数都将包含在地图中。


请求中包含所有参数的示例:

@GetMapping(path = "persons")
public ResponseEntity<Integer> getPersons(@RequestParam Long personId,
                                          @RequestParam String from,
                                          @RequestParam String to,
                                          @RequestParam Map<String, String> filters) {
    Person person = Person.builder()
            .personId(personId)
            .from(getDate(from))
            .to(getDate(to))
            .filters(filterMap(filters))
            .build();
    return ResponseEntity.ok(personService.getPersonsCount(person));
}

private LocalDateTime getDate(String date) {
    DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm");
    return LocalDateTime.parse(date, formatter);
}

private Map<String, String> filterMap(Map<String, String> request) {
    request.remove("personId");
    request.remove("from");
    request.remove("to");
    return request;
}

代码完全乱七八糟。由于 Map<String, String> filters@RequestParam,因此它包括所有请求参数,甚至包括上面定义的参数。因此,如果您不想在 filters 地图中,则需要删除 pesonIdfromto

仅包含请求映射的示例

@GetMapping(path = "persons")
public ResponseEntity<Integer> getPerson(@RequestParam Map<String, String> requestParams) {
    Person person = Person.builder()
             .personId(Long.valueOf(requestParams.get("personId")))
             .from(getDate(requestParams.get("from")))
             .to(getDate(requestParams.get("to")))
             .filters(filterRequest(requestParams))
             .build();
    return ResponseEntity.ok(personService.getPersonsCount(person));
}

private LocalDateTime getDate(String date) {
    DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm");
    return LocalDateTime.parse(date, formatter);
}

private Map<String, String> filterRequest(Map<String, String> request) {
    request.remove("personId");
    request.remove("from");
    request.remove("to");
    return request;
}  

但是至少我不知道在调用控制器端点之前将路径参数转换为 POJO 的好的或简单的配置,因此我建议您使用这些示例中的内容。否则使用请求正文或尝试使用此 example