我必须进行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
进行交换而没有查询参数时,它可以正常工作。
有没有人有任何想法?
答案 0 :(得分:372)
要轻松操作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);
答案 1 :(得分:123)
uriVariables也在查询字符串中展开。例如,以下调用将扩展帐户和名称的值:
restTemplate.exchange("http://my-rest-url.org/rest/account/{account}?name={name}",
HttpMethod.GET,
httpEntity,
clazz,
"my-account",
"my-name"
);
所以实际的请求网址将是
http://my-rest-url.org/rest/account/my-account?name=my-name
查看HierarchicalUriComponents.expandInternal(UriTemplateVariables)以获取更多详细信息。 Spring的版本是3.1.3。
答案 2 :(得分:36)
好的,所以我是个白痴,我把查询参数与url参数混淆了。我有点希望有一个更好的方法来填充我的查询参数,而不是一个丑陋的连接字符串,但我们有。这只是用正确的参数构建URL的情况。如果你把它传递给一个String Spring也会为你处理编码。
答案 3 :(得分:18)
至少从Spring 3开始,不是使用UriComponentsBuilder
来构建URL(有点冗长),很多的RestTemplate
方法接受路径中的占位符参数(不只是exchange
)。
来自文档:
许多
RestTemplate
方法接受URI模板和URI 模板变量,可以是String
vararg,也可以是。{Map<String,String>
。例如使用
String
vararg: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
的{{3}}并搜索&#34; URI模板&#34;,您可以看到哪些方法可以使用占位符。
答案 4 :(得分:17)
我正在尝试类似的事情,the RoboSpice example helped me work it out:
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);
答案 5 :(得分:3)
我采取不同的方法,您可能同意或不同意,但我想从.properties文件而不是编译的Java代码控制
endpoint.url = https://yourHost/resource?requestParam1= {0}&amp; requestParam2 = {1}
Java代码在这里,您可以编写if或switch条件以查明.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(); }
答案 6 :(得分:3)
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变量和Request参数)构建动态URI
答案 7 :(得分:2)
如果您为RestTemplate传递非参数化的参数,那么考虑到参数,您将为每个传递的单个URL有一个度量标准。您想使用参数化的网址:
http://my-url/action?param1={param1}¶m2={param2}
代替
http://my-url/action?param1=XXXX¶m2=YYYY
第二种情况是使用UriComponentsBuilder类得到的结果。
实现第一个行为的一种方法如下:
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);
答案 8 :(得分:2)
在Spring Web 4.3.6中,我也看到了
public <T> T getForObject(String url, Class<T> responseType, Object... uriVariables)
这意味着您不必创建丑陋的地图
因此,如果您有此网址
http://my-url/action?param1={param1}¶m2={param2}
你可以做
restTemplate.getForObject(url, Response.class, param1, param2)
或
restTemplate.getForObject(url, Response.class, param [])
答案 9 :(得分:1)
另一种使用UriComponentsBuilder的解决方案(转换现有的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);
答案 10 :(得分:1)
我提供了带有路径参数示例的 RestTemplate GET 方法的代码片段
public ResponseEntity<String> getName(int id) {
final String url = "http://localhost:8080/springrestexample/employee/name?id={id}";
Map<String, String> params = new HashMap<String, String>();
params.put("id", id);
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
HttpEntity request = new HttpEntity(headers);
ResponseEntity<String> response = restTemplate.exchange(url, HttpMethod.GET, String.class, params);
return response;
}
答案 11 :(得分:0)
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);
}
答案 12 :(得分:0)
如果您的网址是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交换方法