Резюме использования Spring RestTemplate
Как бэкэнд Java, запрос других сетевых ресурсов через HTTP является относительно распространенным случаем; как это сделать вообще?
Может быть, большинство мелких партнеров напрямую берут HttpClient Apache и начинают его делать, или используют какие-то другие известные библиотеки с открытым исходным кодом, такие как OkHttp, конечно, родной HttpURLConnection также не является проблемой.
Этот пост в блоге в основном посвящен экологии Sprig с использованиемRestTemplate
Используйте положение для инициирования HTTP-запроса
I. Основное использование RestTempalate
0. Голы
Прежде чем представить, как использовать RestTemplate, давайте закинем несколько небольших целей, по крайней мере, нам нужно знать, что можно сделать с помощью RestTemplate, и что мы можем с ним сделать.
Вот краткий обзор общих проблем
- Обычный Get запрос на получение возвращаемых данных, как играть?
- Почта отправляет экспресс-запрос, как с этим справиться
- Метод запроса RequestBody в почтовом запросе отличается от обычного метода запроса.
- Как обрабатывать https/http два вида доступа отдельно
- Как включить указанный заголовок в запрос
- Есть ли междоменные проблемы? если да то как решить
- Есть запрос на верификацию логина, что делать и как нести идентификационную информацию
- Поддерживается ли загрузка файлов?
- Для http-ресурсов, для доступа к которым требуется прокси-сервер, какова ситуация с добавлением прокси-сервера?
Выше много проблем, и визуальный осмотр не может быть завершен в одном посте в блоге, поэтому давайте разберем это.Эта статья в основном сосредоточена на использовании простых запросов Get/Post RestTemplate
1. Базовый интерфейс
Выньте исходный код и взгляните на некоторые общие интерфейсы, которые он предоставляет, которые можно в основном разделить на следующие типы.
// get 请求
public <T> T getForObject();
public <T> ResponseEntity<T> getForEntity();
// head 请求
public HttpHeaders headForHeaders();
// post 请求
public URI postForLocation();
public <T> T postForObject();
public <T> ResponseEntity<T> postForEntity();
// put 请求
public void put();
// pathch
public <T> T patchForObject
// delete
public void delete()
// options
public Set<HttpMethod> optionsForAllow
// exchange
public <T> ResponseEntity<T> exchange()
Интерфейсы, предоставленные выше, в основном являются соответствующими методами доступа, предоставляемыми Http, но обмен отличается, что будет подробно описано позже.
2. Получить запрос
Из приведенного выше именования интерфейса видно, что есть два способа использованияgetForObject
иgetForEntity
Так в чем же разница между этими двумя?
- Из сигнатуры интерфейса видно, что один должен напрямую возвращать ожидаемый объект, а другой — оборачивать объект в
ResponseEntity
в классе пакетов - Если вас интересует только возвращаемый результат, используйте
GetForObject
Просто - Если вам нужно получить возвращенный заголовок и другую информацию в дополнение к возвращаемому содержимому объекта, вы можете использовать
getForEntit
А. Создайте интерфейс Get
Чтобы проверить состояние использования RestTemplate, конечно, сначала должна быть предоставлена внутренняя служба REST, которая напрямую использует внутренний интерфейс одной из моих личных древних поэм в качестве простого теста Get.
Запрос соединения:https://story.hhui.top/detail?id=666106231640
Возвращаемый результат:
{
"status": {
"code": 200,
"msg": "SUCCESS"
},
"result": {
"id": 666106231640,
"title": "西塞山二首(今谓之道士矶,即兴国军大冶县",
"author": "王周",
"content": "西塞名山立翠屏,浓岚横入半江青。\n千寻铁锁无由问,石壁空存道者形。\n匹妇顽然莫问因,匹夫何去望千春。\n翻思岵屺传诗什,举世曾无化石人。",
"explain": "",
"theme": "无",
"dynasty": "唐诗"
}
}
б. Метод getForObject
Первый взгляд на полную сигнатуру интерфейса
@Nullable
public <T> T getForObject(String url, Class<T> responseType, Object... uriVariables) throws RestClientException ;
@Nullable
public <T> T getForObject(String url, Class<T> responseType, Map<String, ?> uriVariables) throws RestClientException ;
@Nullable
public <T> T getForObject(URI url, Class<T> responseType) throws RestClientException;
Есть три перегруженных метода, и относительно легко увидеть, как их использовать из интерфейса, один из них немного сбивает с толку, как должны передаваться параметры.
public class RestTestmplateTest {
private RestTemplate restTemplate;
@Before
public void init() {
restTemplate = new RestTemplate();
}
@lombok.Data
static class InnerRes {
private Status status;
private Data result;
}
@lombok.Data
static class Status {
int code;
String msg;
}
@lombok.Data
static class Data {
long id;
String theme;
String title;
String dynasty;
String explain;
String content;
String author;
}
@Test
public void testGet() {
// 使用方法一,不带参数
String url = "https://story.hhui.top/detail?id=666106231640";
InnerRes res = restTemplate.getForObject(url, InnerRes.class);
System.out.println(res);
// 使用方法一,传参替换
url = "https://story.hhui.top/detail?id={?}";
res = restTemplate.getForObject(url, InnerRes.class, "666106231640");
System.out.println(res);
// 使用方法二,map传参
url = "https://story.hhui.top/detail?id={id}";
Map<String, Object> params = new HashMap<>();
params.put("id", 666106231640L);
res = restTemplate.getForObject(url, InnerRes.class, params);
System.out.println(res);
// 使用方法三,URI访问
URI uri = URI.create("https://story.hhui.top/detail?id=666106231640");
res = restTemplate.getForObject(uri, InnerRes.class);
System.out.println(res);
}
}
Глядя на тестовый пример выше, нечего сказать об использовании последних двух методов, в основном смотрите наorg.springframework.web.client.RestTemplate#getForObject(java.lang.String, java.lang.Class<T>, java.lang.Object...)
Использование жестов
- Замените содержимое в шаблоне URL в соответствии с фактическими параметрами
- При использовании метода 1 используйте в шаблоне
{?}
для представления ямы, которая заполняется в соответствии с фактическим порядком параметров. - При использовании метода 2 используйте в шаблоне
{xx}
, и этот xx соответствует ключу в карте
Скриншот после вышеуказанного выполнения выглядит следующим образом
в. Метод getForEntity
Поскольку у getForObject есть три метода использования, то и у getForEntity теоретически должно быть три соответствующих метода.
public <T> ResponseEntity<T> getForEntity(String url, Class<T> responseType, Object... uriVariables) throws RestClientException ;
public <T> ResponseEntity<T> getForEntity(String url, Class<T> responseType, Map<String, ?> uriVariables) throws RestClientException;
public <T> ResponseEntity<T> getForEntity(URI url, Class<T> responseType) throws RestClientException;
Поскольку поза такая же, как и выше, для тестирования используется только одна.
@Test
public void testGetForEntity() {
String url = "https://story.hhui.top/detail?id=666106231640";
ResponseEntity<InnerRes> res = restTemplate.getForEntity(url, InnerRes.class);
System.out.println(res);
}
Для этого нас больше всего беспокоит то, что добавляется в пакет ResponseEntity.Скриншоты выглядят следующим образом.
Как видно из вышеизложенного, есть еще две вещи
- Возвращаемый код состояния http, например 200 для успешного запроса, 500 для ошибки сервера, 404 не найдено и т. д.
- заголовок ответа
3. Разместить запрос
Из описания интерфейса выше, в дополнение к foroubject и в преддверии, запрос на почту также имеет выравнивание. Во-вторых, очевидная разница между постом и получением является позором передачи параметров. Параметры получения, как правило, остаются на URL; более распространены через форму
Итак, следующее внимание уделяется тому, что такое forLocation и как передавать параметры.
А. Макет почтового интерфейса
Сначала создайте простую службу REST, которая предоставляет запросы POST, и просто создайте ее на основе Spring-boot, как показано ниже.
@ResponseBody
@RequestMapping(path = "post", method = {RequestMethod.GET, RequestMethod.OPTIONS, RequestMethod.POST})
public String post(HttpServletRequest request,
@RequestParam(value = "email", required = false) String email,
@RequestParam(value = "nick", required = false) String nick) {
Map<String, Object> map = new HashMap<>();
map.put("code", "200");
map.put("result", "add " + email + " # " + nick + " success!");
return JSON.toJSONString(map);
}
б) метод postForObject
Первый взгляд на сигнатуру интерфейса
public <T> T postForObject(String url, @Nullable Object request, Class<T> responseType, Object... uriVariables) throws RestClientException ;
public <T> T postForObject(String url, @Nullable Object request, Class<T> responseType, Map<String, ?> uriVariables) throws RestClientException;
public <T> T postForObject(URI url, @Nullable Object request, Class<T> responseType) throws RestClientException ;
Вышеупомянутые три метода вроде бы не сильно отличаются от предыдущих, но есть еще один параметр запроса, так что насчет конкретного использования?
Варианты использования приведены ниже
@Test
public void testPost() {
String url = "http://localhost:8080/post";
String email = "test@hhui.top";
String nick = "一灰灰Blog";
MultiValueMap<String, String> request = new LinkedMultiValueMap<>();
request.add("email", email);
request.add("nick", nick);
// 使用方法三
URI uri = URI.create(url);
String ans = restTemplate.postForObject(uri, request, String.class);
System.out.println(ans);
// 使用方法一
ans = restTemplate.postForObject(url, request, String.class);
System.out.println(ans);
// 使用方法一,但是结合表单参数和uri参数的方式,其中uri参数的填充和get请求一致
request.clear();
request.add("email", email);
ans = restTemplate.postForObject(url + "?nick={?}", request, String.class, nick);
System.out.println(ans);
// 使用方法二
Map<String, String> params = new HashMap<>();
params.put("nick", nick);
ans = restTemplate.postForObject(url + "?nick={nick}", request, String.class, params);
System.out.println(ans);
}
Три метода вызова приведены выше.Существует два типа параметров сообщения, один из которых является параметром uri, который вставляется в URL, а другой является параметром формы.
- Параметр uri, используя ту же позу, что и в запросе на получение, заполняет яму шаблона в uri.
- параметры формы, по
MultiValueMap
Инкапсуляция, такая же структура kv
c. postForEntity
Как и предыдущая поза использования, это не более чем дополнительный слой упаковки, пропустите его и не говорите об этом.
d. postForLocation
Это немного отличается от предыдущего.Из определения интерфейса, это в основном
POST-данные на URL-адрес, возвращая URL-адрес вновь созданного ресурса
Он также предоставляет три интерфейса, а именно: Следует отметить, что возвращаемый результат является объектом URI, то есть сетевым ресурсом.
public URI postForLocation(String url, @Nullable Object request, Object... uriVariables)
throws RestClientException ;
public URI postForLocation(String url, @Nullable Object request, Map<String, ?> uriVariables)
throws RestClientException ;
public URI postForLocation(URI url, @Nullable Object request) throws RestClientException ;
Итак, какой интерфейс подходит для такого жеста доступа?
Думаете у нас общий вход или регистрация это пост запроса, а после эти операции завершены? Большинство из них переходят на другие страницы. В этом случае вы можете использоватьpostForLocation
Теперь отправьте данные и получите возвращенный URI, тест выглядит следующим образом.
Первый макет внутреннего интерфейса
@ResponseBody
@RequestMapping(path = "success")
public String loginSuccess(String email, String nick) {
return "welcome " + nick;
}
@RequestMapping(path = "post", method = {RequestMethod.GET, RequestMethod.OPTIONS, RequestMethod.POST})
public String post(HttpServletRequest request, @RequestParam(value = "email", required = false) String email,
@RequestParam(value = "nick", required = false) String nick) {
return "redirect:/success?email=" + email + "&nick=" + nick + "&status=success";
}
Доступные тестовые случаи, в основном такие же, как и предыдущие, сказать особо нечего
@Test
public void testPostLocation() {
String url = "http://localhost:8080/post";
String email = "test@hhui.top";
String nick = "一灰灰Blog";
MultiValueMap<String, String> request = new LinkedMultiValueMap<>();
request.add("email", email);
request.add("nick", nick);
// 使用方法三
URI uri = restTemplate.postForLocation(url, request);
System.out.println(uri);
}
Результат выполнения следующий
То, что получается, является внутренним URL-адресом перенаправления 302. Внимательные друзья могут увидеть проблему с искаженными китайскими иероглифами выше. Как ее решить?
Простое решение - закодировать URL
@RequestMapping(path = "post", method = {RequestMethod.GET, RequestMethod.OPTIONS, RequestMethod.POST},
produces = "charset/utf8")
public String post(HttpServletRequest request, @RequestParam(value = "email", required = false) String email,
@RequestParam(value = "nick", required = false) String nick) throws UnsupportedEncodingException {
return "redirect:/success?email=" + email + "&nick=" + URLEncoder.encode(nick, "UTF-8") + "&status=success";
}
II. Резюме
Вышеприведенное дает только базовое использование двух методов запроса Get/Post и не включает более продвинутые, такие как добавление заголовков запросов, добавление сертификатов, установка прокси и т. д. Расширенное использование ожидает выпуска следующего метода. Вышеупомянутая поза
1. Получить запрос
В запросе на получение параметры обычно передаются в URL-адресе. Существует два способа заполнения параметров. Та же идея заключается в том, чтобы заполнить содержимое заполнителя в URL-адресе в соответствии с фактическими параметрами, в соответствии с возвращаемым результатом также два способа. , один заботится только о возвращаемом объекте, а другой содержит уверенность в возвращении заголовков
заполнение параметра
- В форме
http://story.hhui.top?id={0}
URL-адрес
- перечислить
getForObject(String url, Class<T> responseType, Object... uriVariables)
- 0 в шаблоне означает 0-е место в массиве uriVariables, i означает i-е
- Если нет параметра url, этот метод тоже рекомендуется, только не передавайте uriVariables
- В форме
http://story.hhui.top?id={id}
URL-адрес
- перечислить
getForObject(String url, Class<T> responseType, Map<String, ?> uriVariables)
- Ключом в параметре карты является содержимое {} в параметре URL.
На самом деле есть еще один способ передачи параметров, то есть параметр пути.Способ заполнения тот же, что и выше, и особого способа воспроизведения нет.Выше специально не указан.
вернуть результат
- Получить возвращенные данные напрямую
getForObject
- Получить данные, которые будут responseHeader
getForEntity
2. Разместить запрос
- Также существует два типа возврата почтового запроса, как указано выше.
- Для почтового запроса параметры можно разделить на отправку формы и параметры URL, где параметр URL соответствует предыдущей логике.
- параметры почтовой формы, пожалуйста, заверните
MultiValueMap
, как второй параметрRequest
представить - почтовый метод и другое
postForLocation
, который возвращает объект URI, то есть метод запроса, подходящий для возврата сетевых ресурсов
3. Другое
В начале я упомянул много общих случаев с сетевыми запросами, но приведенное выше введение, очевидно, только в основах, нам все еще нужно обратить внимание на
- Как установить заголовки запроса?
- Как передать идентификационную информацию при запросе аутентификации?
- настройки прокси
- Что я могу сделать с загрузкой файла?
- Как опубликовать строку отправки json (т.е. RequestBody)
Вышеупомянутое может все еще оставаться в главе приложения.Если вас интересуют исходный код и реализация, проблема придет.
- Каков принцип реализации RestTemplaet
- Является ли реализация логики заполнения предыдущих параметров URL элегантной?
- Как анализируется возвращаемый объект
- ....
Небольшой класс инструментов, на самом деле там довольно много всего.Следующая небольшая цель - изучить пункты, упомянутые выше, один за другим.
III. Другое
1. Серый блог:liuyueyi.github.io/hexblog
Серый личный блог, записывающий все посты блога по учебе и работе, приглашаю всех в гости
2. Заявление
Это не так хорошо, как письмо веры.Контент уже был размещен, и это чисто из семьи.Из-за ограниченных личных возможностей неизбежно будут упущения и ошибки.Если вы найдете ошибки или лучше предложения, вы можете критиковать и исправлять их.
- Адрес вейбо:Блог Маленького Серого
- QQ: серо-серый / 3302797840
3. Сканируйте внимание
Блог Little Grey и общедоступный номер
планета знаний