【问题标题】:Populate query parameters from DTO从 DTO 填充查询参数
【发布时间】:2020-12-17 06:44:25
【问题描述】:

有没有办法让 Spring 从 DTO 自动填充 RestTemplate 查询参数,类似于它自动实例化响应 DTO 的方式?

我想写这样的东西:

RequestDto request = new RequestDto();
request.setFoo("foo");
request.setBar("bar");

ResponseDto response = restTemplate.getForObject(
        "http://example.com/api",
        ResponseDto.class, 
        request
);

代替:

ResponseDto response = restTemplate.getForObject(
        "http://example.com/api?foo={foo}&bar={bar}",
        ResponseDto.class,
        "foo",
        "bar"
);

因为有许多大型 DTO,需要大量样板代码,必须与任何 DTO 更改保持同步。

春季 4.3.25

【问题讨论】:

  • 我很惊讶我仍然找不到这个问题的答案,而且还没有人回答。不可能吗?

标签: spring resttemplate dto query-parameters


【解决方案1】:

我不认为这是直接可能的。以下内容并不完全使用 DTO,但它确实让您无需手动形成 URL 字符串即可构建请求。你可以使用 Spring 的 UriComponentsBuilder 类。

UriComponentsBuilder builder = UriComponentsBuilder.fromHttpUrl("http://example.com/api")
    .queryParam("foo", "bar")
    // etc. ...
    .queryParam("bar", "foo");

String result = restTemplate.getForObject(builder.toString(), String.class);

您可以遍历 DTO 并按上述方式构建查询。或者没有 DTO,您可以使用 Map<String, String> 并循环它。

Map<String, String> params = new HashMap<>();
params.put("foo", "bar");

UriComponentsBuilder builder = UriComponentsBuilder.fromHttpUrl("http://example.com/api");
for (Map.Entry<String, String> entry : params.entrySet()) {
    builder.queryParam(entry.getKey(), entry.getValue());
}
String result = restTemplate.getForObject(builder.toString(), String.class);

编辑:

正如下面的 crizzis 建议的那样,您可以使用 Spring Cloud OpenFeign 的 REST 客户端(来自 Feign @QueryMap support):

OpenFeign @QueryMap 注解支持 POJO 用作 GET 参数映射。不幸的是,默认的 OpenFeign QueryMap 注解与 Spring 不兼容,因为它缺少 value 属性。

Spring Cloud OpenFeign提供了一个等价的@SpringQueryMap注解,用于将POJO或Map参数注解为查询参数映射。

从您的问题示例中:

public class RequestDto {
  private string foo;
  private string bar;
}
@FeignClient(name = "client", url = "http://example.com")
public interface FooTemplate {

    @GetMapping(path = "/api")
    String endpoint(@SpringQueryMap RequestDto requestDto);
}

【讨论】:

  • Feign 看起来很酷,但是你在哪里指定 URL http://example.com 以符合问题?
  • @Snackoverflow 您可以通过在注释中指定 url 来做到这一点,即@FeignClient(name = "client", url = "https://example.com")。我会相应地更新答案。
【解决方案2】:

你可以这样做-

UriComponentsBuilder builder = UriComponentsBuilder.fromUriString("http://example.com/api")
        .queryParam("foo", "foo")
        .queryParam("bar", "bar");

ResponseDto response = restTemplate.getForObject(
        builder.buildAndExpand(builder).toUriString(),
        ResponseDto.class);

可以在这里找到更详细的答案-RestTemplate: How to send URL and query parameters together

【讨论】:

    【解决方案3】:

    使用 Feign 怎么样?它允许您像 Spring Controller 一样描述远程端点。这包括对查询参数 DTO 的支持。

    查看示例here

    【讨论】:

    • 答案不清楚。请发布一些示例代码,说明我们将如何考虑问题中的代码来实现这一点。单独的链接是不可行的,因为它们很容易过期(即使是 SO 链接,因为帖子可以被删除或更改)。
    • @Snackoverflow 我在回答中添加了一个使用 Feign 的示例。
    猜你喜欢
    • 2018-03-03
    • 2013-04-18
    • 1970-01-01
    • 2017-11-28
    • 1970-01-01
    • 2018-02-01
    • 2013-05-01
    • 2013-06-09
    • 1970-01-01
    相关资源
    最近更新 更多