Spring RestTemplate GET с параметрами
Я должен сделать 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
используя тело запроса и без параметров запроса, он работает просто отлично.
У кого-нибудь есть какие-либо идеи?
17 ответов
Итак, я идиот и путаю параметры запроса с параметрами URL. Я надеялся, что был бы более хороший способ заполнить параметры моего запроса, а не безобразно сцепленную строку, но мы здесь. Это просто случай построения URL с правильными параметрами. Если вы передадите его как String 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 также раскрываются в строке запроса. Например, следующий вызов расширит значения для учетной записи и имени:
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, вместо использования UriComponentsBuilder
чтобы построить URL (который является немного многословным), многие из RestTemplate
методы принимают заполнители в пути для параметров (не только exchange
).
Из документации:
Многие из
RestTemplate
методы принимают переменные шаблона URI и шаблона URI, либо какString
вараг, или как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);
Ссылка: https://docs.spring.io/spring/docs/current/spring-framework-reference/integration.html
Если вы посмотрите на JavaDoc для RestTemplate
и поиск "URI Template", вы можете увидеть, с какими методами вы можете использовать заполнители.
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: создание динамического URI с использованием UriComponents (переменная URI и параметры запроса)
Я пытался что-то подобное, и пример 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);
Преобразование хеш-карты в строку параметров запроса:
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);
В 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 [])
Я использую другой подход, вы можете согласиться или нет, но я хочу управлять из файла.properties вместо скомпилированного кода Java
Внутри файла application.properties
endpoint.url = https://yourhost/resource?requestParam1={0} & requestParam2 = {1}
Здесь идет Java-код, вы можете написать условие if или switch, чтобы узнать, имеет ли URL-адрес конечной точки в файле.properties значение @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(); }
Если вы передадите непараметризированные параметры для RestTemplate, у вас будет один показатель для каждого отдельного URL, который вы передаете, с учетом параметров. Вы хотели бы использовать параметризованные 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);
Еще одно решение как метод:
private String execute(String url, Map<String, String> params) {
UriComponentsBuilder uriBuilder = UriComponentsBuilder.fromUriString(url)
// predefined params
.queryParam("user", "userValue")
.queryParam("password", "passwordValue");
params.forEach(uriBuilder::queryParam);
HttpHeaders headers = new HttpHeaders() {{
setContentType(MediaType.APPLICATION_FORM_URLENCODED);
setAccept(List.of(MediaType.APPLICATION_JSON));
}};
ResponseEntity<String> request = restTemplate.exchange(uriBuilder.toUriString(),
HttpMethod.GET, new HttpEntity<>(headers), String.class);
return request.getBody();
}
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);
}
Я предоставляю фрагмент кода метода 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;
}
Вы можете использовать следующий код для String.
URL_EXAMPLE="http://{domain}/Index.php?Username={user}&password={password}";
String domain = "example.com";
String user = "user";
String password = "password";
String data=this.restTemplate.getForObject(URL_EXAMPLE,String.class,domain,user,password);
Если ваш 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, как описано вами
Смотрите, я наблюдаю две вещи: параметр запроса (@RequestParam) или динамические URL-адреса (@PathVariable) можно передать двумя способами, т.е.
- Передача данных в виде массива.
- Использование карты.
В обоих узорах есть одна общая черта. данные должны передаваться динамически, и мы можем пометить эти места с помощью фигурных скобок. {}ex.
https://api.themoviedb.org/3/movie/now_playing?api_key={api_key}
Документация Spring Теперь нам нужно передать данные,
Стиль 1
Map<String,String> data=new LinkedHashMap<String,String>();
data.put("api_key", api_key);
template.getForObject(url, TMDB.class,data);
Стиль 2
Object[] arr= {api_key};
template.getForObject(url, TMDB.class,arr);
привет, я создаю URL-адрес с параметрами запроса, используя этот код:
UriComponentsBuilder.fromHttpUrl(url)
.queryParam("bikerPhoneNumber", "phoneNumberString")
.toUriString();