Весна RestTemplate сделать с параметрами
Я должен сделать вызов 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);
это не удается на клиентском конце, когда сервлет диспетчера не может разрешить запрос обработчику. Havinf отладил его, похоже, параметры запроса не отправляются.
когда я делаю обмен с сообщением, используя тело запроса и без запроса параметры он работает просто отлично.
есть ли у кого-нибудь идеи?
8 ответов
легко манипулировать URLs / path / params / etc. вы можете использовать весной 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.
хорошо, поэтому я идиот, и я путаю параметры запроса с параметрами url. Я надеялся, что будет более хороший способ заполнить мои параметры запроса, а не уродливую объединенную строку, но мы есть. Это просто случай построения URL с правильными параметрами. Если вы передадите его как строку, Весна также позаботится о кодировке для вас.
Я пытался сделать что-то подобное, и пример 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);
по крайней мере, с весны 3, вместо использования UriComponentsBuilder
чтобы построить URL (который немного многословен),много на RestTemplate
методы принимают заполнители в пути для параметров (не только exchange
).
из документации:
многие
RestTemplate
методы принимают шаблон URI и URI переменные шаблона, либо какString
vararg, или какMap<String,String>
.например
String
с vararg:restTemplate.getForObject( "http://example.com/hotels/{hotel}/rooms/{hotel}", String.class, "42", "21");
или
Map<String, String>
:Map<String, String> vars = Collections.singletonMap("hotel", "42"); restTemplate.getForObject("http://example.com/hotels/{hotel}/rooms/{hotel}", String.class, vars);
если вы посмотрите на JavaDoc на RestTemplate
и поиск "шаблона URI", вы можете увидеть, какие методы вы можете использовать заполнители.
Я беру другой подход, вы можете согласиться или нет, но я хочу контролировать.файл свойств вместо скомпилированного кода Java
внутри приложения.свойства файла
конечной точки.URL-адрес = https://yourHost/resource?requestParam1={0}&requestParam2={1}
Java-код идет здесь, вы можете написать условие if или switch, чтобы узнать, есть ли URL конечной точки .файл свойств имеет @PathVariable (содержит {}) или @RequestParam (yourURL?ключ=значение) и т. д... затем вызовите метод соответственно... таким образом, его динамичность и не нужно менять код в будущем...
Я пытаюсь дать больше идея, чем реальный код ...попробуйте написать общий метод для @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(); }
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, у вас будет одна метрика для каждого отдельного 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);