Использование RestTemplate в Spring. Исключение. Недостаточно переменных для расширения
Я пытаюсь получить доступ к содержимому API, и мне нужно отправить URL-адрес с помощью RestTemplate.
String url1 = "http://api.example.com/Search?key=52ddafbe3ee659bad97fcce7c53592916a6bfd73&term=&limit=100&sort={\"price\":\"desc\"}";
OutputPage page = restTemplate.getForObject(url1, OutputPage .class);
Но я получаю следующую ошибку.
Exception in thread "main" java.lang.IllegalArgumentException: Not enough variable values available to expand '"price"'
at org.springframework.web.util.UriComponents$VarArgsTemplateVariables.getValue(UriComponents.java:284)
at org.springframework.web.util.UriComponents.expandUriComponent(UriComponents.java:220)
at org.springframework.web.util.HierarchicalUriComponents.expandInternal(HierarchicalUriComponents.java:317)
at org.springframework.web.util.HierarchicalUriComponents.expandInternal(HierarchicalUriComponents.java:46)
at org.springframework.web.util.UriComponents.expand(UriComponents.java:162)
at org.springframework.web.util.UriTemplate.expand(UriTemplate.java:119)
at org.springframework.web.client.RestTemplate.execute(RestTemplate.java:501)
at org.springframework.web.client.RestTemplate.getForObject(RestTemplate.java:239)
at hello.Application.main(Application.java:26)
Если я удалю критерии сортировки, он работает правильно.
Мне нужно проанализировать JSON, используя критерии сортировки.
Любая помощь будет высоко оценена.
Спасибо
Ответы
Ответ 1
Основная причина заключается в том, что RestTemplate
рассматривает фигурные скобки {...}
в данном URL как замещающий переменные URI и пытается заменить их на основе их имени. Например
{pageSize}
попытается получить переменную URI с именем pageSize
. Эти переменные URI указываются с некоторыми другими перегруженными методами getForObject
. Вы их не указали, но ваш URL-адрес ожидает его, поэтому метод генерирует исключение.
Одним из решений является создание объекта String
, содержащего значение
String sort = "{\"price\":\"desc\"}";
и предоставить реальную переменную URI в URL-адресе
String url1 = "http://api.example.com/Search?key=52ddafbe3ee659bad97fcce7c53592916a6bfd73&term=&limit=100&sort={sort}";
Вы бы назвали ваш getForObject()
таким образом
OutputPage page = restTemplate.getForObject(url1, OutputPage.class, sort);
Я настоятельно рекомендую вам не отправлять JSON в параметр запроса GET-запроса, а скорее отправлять его в тело запроса POST.
Ответ 2
Вы можете URL кодировать значения параметров:
String url1 = "http://api.example.com/Search?key=52ddafbe3ee659bad97fcce7c53592916a6bfd73&term=&limit=100&sort=";
org.apache.commons.codec.net.URLCodec codec = new org.apache.commons.codec.net.URLCodec();
url1 = url1 + codec.encode("{\"price\":\"desc\"}");
OutputPage page = restTemplate.getForObject(url1, OutputPage.class);
Ответ 3
Если решение, предложенное sotirios-delimanolis, немного сложно реализовать в сценарии, и если строка URI, содержащая фигурные скобки и другие символы, гарантированно верна, может быть проще передать закодированную строку URI в метод RestTemplate
который попадает на сервер ReST
.
Строка URI может быть построена с использованием UriComponentsBuilder.build(), закодирована с использованием UriComponents.encode() и отправлена с использованием RestTemplate.exchange() следующим образом:
public ResponseEntity<Object> requestRestServer()
{
HttpEntity<?> entity = new HttpEntity<>(requestHeaders);
UriComponentsBuilder builder = UriComponentsBuilder.fromUriString(rawValidUrl)
.queryParams(
(LinkedMultiValueMap<String, String>) allRequestParams);
UriComponents uriComponents = builder.build().encode();
ResponseEntity<Object> responseEntity = restTemplate.exchange(uriComponents.toUri(), HttpMethod.GET,
entity, String.class);
return responseEntity;
}
Построение, кодирование и извлечение URI были отделены для ясности в приведенном выше фрагменте кода.
Ответ 4
Вы можете просто добавить переменную в Url и передать значение для переменной в методе restTemplate.postForObject.
String url1 = "http://api.example.com/Search?
key=52ddafbe3ee659bad97fcce7c53592916a6bfd73&term=&limit=100&sort={data}";
String data="{\"price\":\"desc\"}";
OutputPage page = restTemplate.getForObject(url1, OutputPage.class, data);
Ответ 5
Вы можете закодировать URL перед использованием RestTemplate
URLEncoder.encode(data, StandardCharsets.UTF_8.toString());