パラメータ付きSpring RestTemplate GET


267

RESTカスタムヘッダーとクエリパラメーターを含む呼び出しを行う必要があります。HttpEntityヘッダーのみ(本文なし)を設定し、RestTemplate.exchange()メソッドを次のように使用します。

HttpHeaders headers = new HttpHeaders();
headers.set("Accept", "application/json");

Map<String, String> params = new HashMap<String, String>();
params.put("msisdn", msisdn);
params.put("email", email);
params.put("clientVersion", clientVersion);
params.put("clientType", clientType);
params.put("issuerName", issuerName);
params.put("applicationName", applicationName);

HttpEntity entity = new HttpEntity(headers);

HttpEntity<String> response = restTemplate.exchange(url, HttpMethod.GET, entity, String.class, params);

これは、クライアント側で失敗し、dispatcher servletハンドラーへの要求を解決できません。デバッグしたところ、リクエストパラメータが送信されていないようです。

POSTリクエスト本文を使用し、クエリパラメータを使用せずに交換を行うと、問題なく機能します。

誰かが何かアイデアを持っていますか?

回答:


481

URL、パス、パラメータなどを簡単に操作するには、SpringのUriComponentsBuilderクラスを使用できます。文字列を手動で連結する方がきれいで、URLエンコーディングを処理します。

HttpHeaders headers = new HttpHeaders();
headers.set("Accept", MediaType.APPLICATION_JSON_VALUE);

UriComponentsBuilder builder = UriComponentsBuilder.fromHttpUrl(url)
        .queryParam("msisdn", msisdn)
        .queryParam("email", email)
        .queryParam("clientVersion", clientVersion)
        .queryParam("clientType", clientType)
        .queryParam("issuerName", issuerName)
        .queryParam("applicationName", applicationName);

HttpEntity<?> entity = new HttpEntity<>(headers);

HttpEntity<String> response = restTemplate.exchange(
        builder.toUriString(), 
        HttpMethod.GET, 
        entity, 
        String.class);

10
素晴らしいヒント。単純exchangegetForEntityrestTemplate.getForEntity(builder.build().encode().toUri(), String.class);に変更しました。
フェルナンドM.ピニェイロ2015年

12
@ FernandoM.Pinheiro:正しいですが、応答にジェネリック型が必要な場合は、を使用exchangeして提供する必要がありますParameterizedTypeReference。実施例はさらに置換、しかし簡略化することができるbuilder.build().encode().toUri()builder.toUriString()
mirzmaster

@Christophe Lサーバー側でこれらの文字列パラメーターをどのように受け取ることができるかを教えてください
KJEjava48 2017

3
URIを取得するショートカットがあります。電話するだけbuilder.toUriString()
Michael Piefel


180

uriVariablesもクエリ文字列で展開されます。たとえば、次の呼び出しは、アカウントと名前の両方の値を展開します。

restTemplate.exchange("http://my-rest-url.org/rest/account/{account}?name={name}",
    HttpMethod.GET,
    httpEntity,
    clazz,
    "my-account",
    "my-name"
);

したがって、実際のリクエストURLは

http://my-rest-url.org/rest/account/my-account?name=my-name

詳細については、HierarchicalUriComponents.expandInternal(UriTemplateVariables)を参照してください。Springのバージョンは3.1.3です。


ありがとう-非常にシンプルなソリューション
Angshuman Agarwal

2
また、RestTemplateインスタンスを作成するときに、DefaultUriTemplateHandler(Spring 5より前)またはDefaultUriBuilderFactory(Spring 5+)を指定することで、これらのクエリパラメーター値をどのように展開するかを指定できます。次のような追加の文字をエンコードしたいときに便利です、(、)、など!
スティーブン・ルドルフ

私のURLには10個以上のパラメーターがありますが、すべての変数をリストする代わりにオブジェクト/マップで同じことを実現する方法はありますか?私はUriComponentsBuilderどちらも使用できません。これは、リクエストごとに異なるメトリックを生成するためですMicrometer
Doug

@Doug — RestTemplate値の位置配列(Object... uriVariables)または名前付き値のマップ()を指定するための並列メソッドがありますMap<String, ?> uriVariables。地図バージョンのような音が何をしたいですrestTemplate.exchange(url, HttpMethod.GET, httpEntity, clazz, urlVariablesMap)
M.ジャスティン

42

少なくともSpring 3以降UriComponentsBuilder、URLの作成に使用する(少し冗長)代わりに、メソッドの多くRestTemplate(だけではなくexchange)パラメーターのパスにプレースホルダーを受け入れます。

ドキュメントから:

RestTemplateメソッドの多くは、URIテンプレートとURIテンプレート変数をStringvarargまたはとして受け入れ Map<String,String>ます。

たとえば、Stringvarargの場合:

restTemplate.getForObject(
   "http://example.com/hotels/{hotel}/rooms/{room}", String.class, "42", "21");

またはMap<String, String>

Map<String, String> vars = new HashMap<>();
vars.put("hotel", "42");
vars.put("room", "21");

restTemplate.getForObject("http://example.com/hotels/{hotel}/rooms/{room}", 
    String.class, vars);

リファレンス:https : //docs.spring.io/spring/docs/current/spring-framework-reference/integration.html#rest-resttemplate-uri

あなたが見ればJavaDocのためRestTemplateおよび「URIテンプレート」を検索し、あなたがして、プレースホルダを使用できる方法を見ることができます。


35

さて、私はばかであり、クエリパラメータとURLパラメータを混同しています。ひどく連結された文字列ではなく、クエリパラメータを入力するためのより良い方法があることを少し期待していましたが、それはあります。これは、正しいパラメータを使用してURLを作成する場合にすぎません。String Springとして渡すと、エンコーディングも処理されます。


それはあなたのために働きましたか?UriComponentsBuilderを使用する同じアプローチに従いましたが、ターゲットURLでrequest.getAttribute()を実行すると、nullが取得されます。
yathirigan 2015

47
この回答に緑色のチェックマークが付いている理由を真剣に理解していません。
Pradeep、2018年

7
彼がOPであるため
カルペシュソニー

それであなたの解決策は何ですか?ありがとう!
Raymond Chen

18

私は同様のことを試みていましたが、RoboSpiceの例はそれを解決するのに役立ちました

HttpHeaders headers = new HttpHeaders();
headers.set("Accept", "application/json");

HttpEntity<String> request = new HttpEntity<>(input, createHeader());

String url = "http://awesomesite.org";
Uri.Builder uriBuilder = Uri.parse(url).buildUpon();
uriBuilder.appendQueryParameter(key, value);
uriBuilder.appendQueryParameter(key, value);
...

String url = uriBuilder.build().toString();

HttpEntity<String> response = restTemplate.exchange(url, HttpMethod.GET, request , String.class);

15
    String uri = http://my-rest-url.org/rest/account/{account};

    Map<String, String> uriParam = new HashMap<>();
    uriParam.put("account", "my_account");

    UriComponents builder = UriComponentsBuilder.fromHttpUrl(uri)
                .queryParam("pageSize","2")
                        .queryParam("page","0")
                        .queryParam("name","my_name").build();

    HttpEntity<String> requestEntity = new HttpEntity<>(null, getHeaders());

    ResponseEntity<String> strResponse = restTemplate.exchange(builder.toUriString(),HttpMethod.GET, requestEntity,
                        String.class,uriParam);

    //final URL: http://my-rest-url.org/rest/account/my_account?pageSize=2&page=0&name=my_name

RestTemplate:UriComponents(URI変数とリクエストパラメータ)を使用して動的URIを構築する


6

ハッシュマップからクエリパラメータの文字列への変換:

Map<String, String> params = new HashMap<>();
params.put("msisdn", msisdn);
params.put("email", email);
params.put("clientVersion", clientVersion);
params.put("clientType", clientType);
params.put("issuerName", issuerName);
params.put("applicationName", applicationName);

UriComponentsBuilder builder = UriComponentsBuilder.fromHttpUrl(url);
for (Map.Entry<String, String> entry : params.entrySet()) {
    builder.queryParam(entry.getKey(), entry.getValue());
}

HttpHeaders headers = new HttpHeaders();
headers.set("Accept", "application/json");

HttpEntity<String> response = restTemplate.exchange(builder.toUriString(), HttpMethod.GET, new HttpEntity(headers), String.class);

3

私は別のアプローチをとっていますが、同意してもしなくてもかまいませんが、コンパイルされたJavaコードの代わりに.propertiesファイルから制御したい

application.propertiesファイル内

endpoint.url = https:// yourHost / resource?requestParam1 = {0}&requestParam2 = {1}

ここにJavaコードが入り、.propertiesファイルのエンドポイントURLに@PathVariable({}を含む)または@RequestParam(yourURL?key = value)などがあるかどうかを確認するためにifまたはswitch条件を記述し、それに応じてメソッドを呼び出します。 。そのようにそのダイナミックで、将来のワンストップショップでコードを変更する必要はありません...

私はここで実際のコードよりも多くのアイデアを提供しようとしています... @RequestParamや@PathVariableなどに対してそれぞれジェネリックメソッドを記述してみてください...必要に応じて適宜呼び出してください

  @Value("${endpoint.url}")
  private String endpointURL;
  // you can use variable args feature in Java
  public String requestParamMethodNameHere(String value1, String value2) {
    RestTemplate restTemplate = new RestTemplate();
    restTemplate
           .getMessageConverters()
           .add(new MappingJackson2HttpMessageConverter());

    HttpHeaders headers = new HttpHeaders();
    headers.set("Accept", MediaType.APPLICATION_JSON_VALUE);
    HttpEntity<String> entity = new HttpEntity<>(headers);

    try {
      String formatted_URL = MessageFormat.format(endpointURL, value1, value2);
      ResponseEntity<String> response = restTemplate.exchange(
                    formatted_URL ,
                    HttpMethod.GET,
                    entity,
                    String.class);
     return response.getBody();
    } catch (Exception e) { e.printStackTrace(); }

3

Spring Web 4.3.6では、

public <T> T getForObject(String url, Class<T> responseType, Object... uriVariables)

つまり、醜いマップを作成する必要はありません

だからあなたがこのURLを持っているなら

http://my-url/action?param1={param1}&param2={param2}

あなたはどちらかをすることができます

restTemplate.getForObject(url, Response.class, param1, param2)

または

restTemplate.getForObject(url, Response.class, param [])

2
public static void main(String[] args) {
         HttpHeaders httpHeaders = new HttpHeaders();
         httpHeaders.set("Accept", MediaType.APPLICATION_JSON_VALUE);
         final String url = "https://host:port/contract/{code}";
         Map<String, String> params = new HashMap<String, String>();
         params.put("code", "123456");
         HttpEntity<?> httpEntity  = new HttpEntity<>(httpHeaders); 
         RestTemplate restTemplate  = new RestTemplate();
         restTemplate.exchange(url, HttpMethod.GET, httpEntity,String.class, params);
    }

2

RestTemplateにパラメータ化されていないパラメータを渡すと、パラメータを考慮して、渡すすべての単一の異なるURLに対して1つのメトリックが得られます。パラメータ化されたURLを使用したい場合:

http://my-url/action?param1={param1}&param2={param2}

の代わりに

http://my-url/action?param1=XXXX&param2=YYYY

2番目のケースは、UriComponentsBuilderクラスを使用して取得したものです。

最初の動作を実装する1つの方法は次のとおりです。

Map<String, Object> params = new HashMap<>();
params.put("param1", "XXXX");
params.put("param2", "YYYY");

String url = "http://my-url/action?%s";

String parametrizedArgs = params.keySet().stream().map(k ->
    String.format("%s={%s}", k, k)
).collect(Collectors.joining("&"));

HttpHeaders headers = new HttpHeaders();
headers.set("Accept", MediaType.APPLICATION_JSON_VALUE);
HttpEntity<String> entity = new HttpEntity<>(headers);

restTemplate.exchange(String.format(url, parametrizedArgs), HttpMethod.GET, entity, String.class, params);

0

あなたのURLが http://localhost:8080/context path?msisdn={msisdn}&email={email}

その後

Map<String,Object> queryParams=new HashMap<>();
queryParams.put("msisdn",your value)
queryParams.put("email",your value)

あなたが説明したように、resttemplate交換方法で機能します

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.