私はsprings resttemplateで簡単な休憩呼び出しをしようとします:
private void doLogout(String endpointUrl, String sessionId) {
template.getForObject("http://{enpointUrl}?method=logout&session={sessionId}", Object.class,
endpointUrl, sessionId);
}
EndpointUrl変数にservice.Host.com/api/service.phpのようなものが含まれている場合
残念ながら、私の呼び出しはorg.springframework.web.client.ResourceAccessException:I/O error:service.Host.com%2Fapi%2Fservice.phpを引き起こします
したがって、Springは、URLの作成中に前に私のendpointUrl文字列をエンコードするようです。春がこれをしないようにする簡単な方法はありますか?
よろしく
これを行う簡単な方法はありません。 URIテンプレート変数は通常、パス要素またはクエリ文字列パラメーター用です。ホストを渡そうとしています。理想的には、URIを構築するためのより良い解決策を見つけるでしょう。 Yuci's solution をお勧めします。
Springユーティリティとテンプレート拡張を引き続き使用する場合、1つの回避策は、UriTemplate
を使用して、URI変数を含むURLを生成し、URLデコードしてRestTemplate
。
String url = "http://{enpointUrl}?method=logout&session={sessionId}";
URI expanded = new UriTemplate(url).expand(endpointUrl, sessionId); // this is what RestTemplate uses
url = URLDecoder.decode(expanded.toString(), "UTF-8"); // Java.net class
template.getForObject(url, Object.class);
使用しているSpringのバージョンによって異なります。バージョンが古すぎる場合、たとえば、バージョン3.0.6.RELEASEの場合、UriComponentsBuilder
などの機能はありません。あなたの春のウェブ瓶。
Spring RestTemplateがURLをエンコードしないようにする必要があります。あなたができることは:
_import Java.net.URI;
StringBuilder builder = new StringBuilder("http://");
builder.append(endpointUrl);
builder.append("?method=logout&session=");
builder.append(sessionId);
URI uri = URI.create(builder.toString());
restTemplate.getForObject(uri, Object.class);
_
Springバージョン3.0.6.RELEASEでテストしましたが、動作しました。
Wordでは、restTemplate.getForObject(String url, Object.class)
を使用する代わりにrestTemplate.getForObject(Java.net.URI uri, Object.class)
を使用します
代わりに、Java.net.URIを受け取るオーバーロードされたバリアントを使用できます。public T getForObject(URI url、Class responseType)throws RestClientException
UriComponents uriComponents =
UriComponentsBuilder.fromUriString("http://example.com/hotels/{hotel}/bookings/{booking}").build()
.expand("42", "21")
.encode();
URI uri = uriComponents.toUri();
私は最高のネイティブな方法(最新)の解決策を見つけたようです:
RestTemplate.exchange()
に渡さないでくださいUriComponentsBuilder
を使用してURIを構築します。以下の(簡略化された)例を参照してください。
String instanceUrl = "https://abc.my.salesforce.com"
HttpEntity<String> entity = new HttpEntity<>(headers);
UriComponents uriComponents =
UriComponentsBuilder.fromHttpUrl(instanceUrl)
.path("/services/data/v45.0/query/")
.queryParam("q", String.format(sqlSelect, id))
.build();
ResponseEntity<OpportunityLineItem> responseEntity =
restTemplate.exchange(
uriComponents.toUri(), HttpMethod.GET,
entity, OpportunityLineItem.class);
// Wrong! URI string will be double encoded
/*
ResponseEntity<OpportunityLineItem> responseEntity =
restTemplate.exchange(
uriComponents.toUriString(), HttpMethod.GET,
entity, OpportunityLineItem.class);
*/
この方法では、二重エンコーディングで問題が発生しません。
Spring RestTemplate
クライアント(SOQLクエリを含む)に基づいて、SalesForce RESTクライアントをデバッグしているときにソリューションが見つかりました。
どうやらこれを行うには、クラスUriComponentsBuilderのbuild(true)を呼び出すより良い方法があります。
private void doLogout(String endpointUrl, String sessionId) {
String url = "http://" + endpointUrl +"?method=logout&session=" + + URLEncoder.encode(sessionId, "UTF-8");
URI uri = UriComponentsBuilder.fromUriString(url.toString()).build(true).toUri();
template.getForObject(uri, Object.class,
endpointUrl, sessionId);
}
このメソッドは、URIの作成中にエンコードしないようにURIComponentsBuilderに指示します。
HttpMethodおよびResponseTypeのヘッダー、本文を含む完全な例は次のようになります。
String url = "http://google.com/{path}?param1={param1Value}¶m2={param2Value}";
Object body = null;
HttpEntity request = new HttpEntity(body, new HttpHeaders());
Map<String, String> uriVariables = new HashMap<>();
uriVariables.put("path", "search");
uriVariables.put("param1Value", "value1");
uriVariables.put("param2Value", "value2");
ResponseEntity<Void> responseEntity = restTemplate.exchange(url, HttpMethod.POST, request, Void.class, uriVariables)
//responseEntity.getBody()
実際には、同じUriTemplateとexpandメソッドを使用します