在Spring中使用RestTemplate.例外 - 没有足够的变量可用于扩展

use*_*403 35 spring resttemplate

我正在尝试访问API的内容,我需要使用RestTemplate发送URL.

String url1 = "http://api.example.com/Search?key=52ddafbe3ee659bad97fcce7c53592916a6bfd73&term=&limit=100&sort={\"price\":\"desc\"}";

OutputPage page = restTemplate.getForObject(url1, OutputPage .class);
Run Code Online (Sandbox Code Playgroud)

但是,我收到以下错误.

Exception in thread "main" java.lang.IllegalArgumentException: Not enough variable values available to expand '"price"'
at org.springframework.web.util.UriComponents$VarArgsTemplateVariables.getValue(UriComponents.java:284)
at org.springframework.web.util.UriComponents.expandUriComponent(UriComponents.java:220)
at org.springframework.web.util.HierarchicalUriComponents.expandInternal(HierarchicalUriComponents.java:317)
at org.springframework.web.util.HierarchicalUriComponents.expandInternal(HierarchicalUriComponents.java:46)
at org.springframework.web.util.UriComponents.expand(UriComponents.java:162)
at org.springframework.web.util.UriTemplate.expand(UriTemplate.java:119)
at org.springframework.web.client.RestTemplate.execute(RestTemplate.java:501)
at org.springframework.web.client.RestTemplate.getForObject(RestTemplate.java:239)
at hello.Application.main(Application.java:26)
Run Code Online (Sandbox Code Playgroud)

如果我删除排序条件,它正常工作.我需要使用排序条件解析JSON.任何帮助都感激不尽.

谢谢

Sot*_*lis 53

根本原因是将给定URL中的RestTemplate花括号{...}视为URI变量的占位符,并尝试根据其名称替换它们.例如

{pageSize}
Run Code Online (Sandbox Code Playgroud)

会尝试获取一个名为的URI变量pageSize.这些URI变量是使用其他一些重载getForObject方法指定的.您没有提供任何内容,但您的URL需要一个,因此该方法会抛出异常.

一种解决方案是使String对象包含该值

String sort = "{\"price\":\"desc\"}";
Run Code Online (Sandbox Code Playgroud)

并在您的URL中提供真正的URI变量

String url1 = "http://api.example.com/Search?key=52ddafbe3ee659bad97fcce7c53592916a6bfd73&term=&limit=100&sort={sort}";
Run Code Online (Sandbox Code Playgroud)

你会打电话给你getForObject(),像这样

OutputPage page = restTemplate.getForObject(url1, OutputPage.class, sort);
Run Code Online (Sandbox Code Playgroud)

我强烈建议您不要在GET请求的请求参数中发送任何JSON,而是将其发送到POST请求的正文中.


Tho*_*hor 5

您可以对参数值进行URL编码:

String url1 = "http://api.example.com/Search?key=52ddafbe3ee659bad97fcce7c53592916a6bfd73&term=&limit=100&sort=";

org.apache.commons.codec.net.URLCodec codec = new org.apache.commons.codec.net.URLCodec();
url1 = url1 + codec.encode("{\"price\":\"desc\"}");
OutputPage page = restTemplate.getForObject(url1, OutputPage.class);
Run Code Online (Sandbox Code Playgroud)


noo*_*oob 5

如果所建议的解决方案索蒂里奥斯-delimanolis是有点困难的情况下实现的,如果含有大括号和其他字符的URI字符串保证是正确的,它可能是简单的编码的URI字符串传递给的方法RestTemplate是点击ReST服务器。

的URI字符串可以使用内置UriComponentsBuilder.build() ,使用编码UriComponents.encode() ,并且使用发送RestTemplate.exchange()是这样的:

public ResponseEntity<Object> requestRestServer()
{
    HttpEntity<?> entity = new HttpEntity<>(requestHeaders);
    UriComponentsBuilder builder = UriComponentsBuilder.fromUriString(rawValidUrl)
            .queryParams(
                    (LinkedMultiValueMap<String, String>) allRequestParams);
    UriComponents uriComponents = builder.build().encode();
    ResponseEntity<Object> responseEntity = restTemplate.exchange(uriComponents.toUri(), HttpMethod.GET,
            entity, String.class);
    return responseEntity;
}
Run Code Online (Sandbox Code Playgroud)

为了清楚起见,在上面的代码片段中已经分离了构建,编码和提取URI。