カスタムヘッダとクエリパラメータを含む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
と交換するとき、それはうまく機能します。
誰かアイデアがありますか?
OK、だから私はばかなんだし、クエリパラメータとURLパラメータを混同しています。私はちょっと醜い連結された文字列よりも私のクエリパラメータを埋めるためのより良い方法があるだろうと願っていました、しかし私たちはあります。それは単に正しいパラメータでURLを構築するケースです。あなたがそれを文字列として渡すなら、Springもあなたのためにエンコーディングの面倒を見るでしょう。
URL/path/params /などを簡単に操作するには、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);
UriVariablesもクエリ文字列で展開されます。たとえば、次の呼び出しはaccountとnameの両方の値を展開します。
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です。
少なくともSpring 3以降、(少し冗長な)URLの作成にUriComponentsBuilder
を使用する代わりに、多くのRestTemplate
メソッドが(exchange
だけでなく)パラメーターのパスにプレースホルダーを受け入れます).
ドキュメントから:
RestTemplate
メソッドの多くは、URIテンプレートとURIテンプレート変数を、String
変数またはMap<String,String>
として受け入れます。例えば
String
変数では: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/{hotel}", String.class, vars);
RestTemplate
の JavaDoc を見て「URI Template」を検索すると、どのメソッドでプレースホルダーを使用できるかがわかります。
私は似たようなことを試みていました、そして 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);
私は別のアプローチを取っています、あなたは同意するかもしれませんが、コンパイルされたJavaコードの代わりに.propertiesファイルから制御したいのですが
endpoint.url = https:// yourHost/resource?requestParam1 = {0}&requestParam2 = {1}
Javaコードはここに行きます、あなたは.propertiesファイルのエンドポイントURLが@PathVariable({{を含む)}または@RequestParam(yourURL?key = value)などを持っているかどうかを調べるために書くかまたは条件を切り替えることができます。そのようにして動的になり、将来ワンストップショップでコードを変更する必要がなくなります。
私はここで実際のコードよりも多くのアイデアを与えようとしています...それぞれ@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(); }
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変数とRequestパラメータ)
RestTemplateにパラメータ化されていないパラメータを渡すと、パラメータを考慮して、渡すすべてのURLに対して、1つのメトリクスがあることになります。あなたはパラメータ化されたURLを使いたいです:
http://my-url/action?param1={param1}¶m2={param2}
の代わりに
http://my-url/action?param1=XXXX¶m2=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);
Spring Web 4.3.6でも見ています
public <T> T getForObject(String url, Class<T> responseType, Object... uriVariables)
それはあなたが醜い地図を作成する必要がないことを意味します
あなたがこのURLを持っているのであれば
http://my-url/action?param1={param1}¶m2={param2}
どちらでもできます
restTemplate.getForObject(url, Response.class, param1, param2)
または
restTemplate.getForObject(url, Response.class, param [])
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);
}
riComponentsBuilder (既存のHashMapの変換)を使用した別のソリューション:
HttpHeaders headers = new HttpHeaders();
headers.set("Accept", "application/json");
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);
HttpEntity entity = new HttpEntity(headers);
UriComponentsBuilder builder = UriComponentsBuilder.fromHttpUrl(url);
for (Map.Entry<String, String> entry : params.entrySet()) {
builder.queryParam(entry.getKey(), entry.getValue());
}
HttpEntity<String> response = restTemplate.exchange(builder.toUriString(), HttpMethod.GET, entity, String.class);