首页 > 解决方案 > Spring Controller:将查询参数绑定到自定义 POJO 字段

问题描述

我正在尝试将某些值从请求查询参数映射到 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映射。

有没有办法做到这一点?

标签: javaspringpojohttp-request-parameters

解决方案


您可以实现它的方法是@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> filtersis @RequestParam,所以它包括所有请求参数,即使是上面定义的。因此,如果您不想在地图 中,则需要删除pesonId, 。fromtofilters

仅包含请求映射的示例

@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 的良好或简单配置,所以我建议您使用这些示例中的一些内容。否则使用请求正文或尝试使用此示例


推荐阅读