web-dev-qa-db-ja.com

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);

しかし、次のエラーが表示されます。

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)

ソート基準を削除すると、正常に機能します。ソート基準を使用してJSONを解析する必要があります。どんな助けも大歓迎です。

ありがとう

31
user3311403

根本的な原因は、RestTemplateが、指定されたURL内の中括弧_{...}_をURI変数のプレースホルダーと見なし、名前に基づいてそれらを置換しようとすることです。例えば

_{pageSize}
_

pageSizeというURI変数を取得しようとします。これらのURI変数は、他のオーバーロードされたいくつかの getForObject メソッドで指定されます。あなたは何も提供していませんが、URLはそれを期待しているので、メソッドは例外をスローします。

1つの解決策は、値を含むStringオブジェクトを作成することです

_String sort = "{\"price\":\"desc\"}";
_

uRLに実際のURI変数を指定します

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

getForObject()は次のように呼び出します

_OutputPage page = restTemplate.getForObject(url1, OutputPage.class, sort);
_

GETリクエストのリクエストパラメータでJSONを送信するのではなく、POSTリクエストの本文で送信することを強くお勧めします。

51

パラメーター値を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);
5
Thor

sotirios-delimanolis によって提案されたソリューションがシナリオで実装するのが少し難しく、中括弧やその他の文字を含むURI文字列が正しいことが保証されている場合、エンコードされたRestTemplateサーバーにヒットするReSTのメソッドへのURI文字列。

URI文字列は、 riComponentsBuilder.build() を使用して構築し、 riComponents.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;
}

URIの構築、エンコード、および抽出は、上記のコードスニペットでわかりやすくするために分離されています。

5
noob

RestTemplateを使用する前にURLをエンコードできます

URLEncoder.encode(data, StandardCharsets.UTF_8.toString());
1
Zongguang

urlに変数を追加して、変数の値を restTemplate.postForObject 方法。

String url1 = "http://api.example.com/Search? 
key=52ddafbe3ee659bad97fcce7c53592916a6bfd73&term=&limit=100&sort={data}";
String data="{\"price\":\"desc\"}";
OutputPage page = restTemplate.getForObject(url1, OutputPage.class, data);
0
Somnath Singh