Эта статья была авторизована для эксклюзивной публикации «Выбор серверной технологии».
RestTemplate
даSpring
Клиент предоставил доступ к сервису Rest,RestTemplate
Предоставляет множество удобных методов доступа к удаленным службам Http, которые могут значительно повысить эффективность записи клиента.
Моя предыдущая разработка HTTP была разработана с помощью HttpClient от apache, код был сложным, и мне приходилось беспокоиться о повторном использовании ресурсов. Код очень сложный и много лишнего. Сделайте скриншот. Это инструмент пост-запроса, который я инкапсулировал:
Это руководство поможет вам реализовать RestTemplate в экосистеме Spring.Get请求
иPost请求
иexchange指定请求类型
практика иRestTemplate
Прочитав анализ исходного кода основного метода, вы будете элегантно отправлять HTTP-запросы.
1. Кратко опишите RestTemplate
да
Spring
Базовый класс, используемый для синхронизации на стороне клиента, что упрощает иhttp
обслуживать связь и встречатьсяRestFul
В принципе, программный код может дать ему URL и извлечь результат. по умолчанию,RestTemplate
По умолчанию он использует инструмент HTTP-соединения jdk. Конечно, вы также можетеsetRequestFactory
свойство для переключения на другой источник HTTP, напримерApache HttpComponents
,Netty
иOkHttp
.
RestTemplate может значительно упростить отправку данных формы и поставляется с функцией автоматического преобразования данных JSON, но только поняв состав HttpEntity (заголовок и тело) и поняв разницу с uriVariables, вы сможете по-настоящему понять его использование. Это более заметно в почтовых запросах, которые будут представлены ниже.
Запись этого класса в основном сформулирована в соответствии с шестью методами HTTP:
HTTP method | RestTemplate methods |
---|---|
DELETE | delete |
GET | getForObject |
getForEntity | |
HEAD | headForHeaders |
OPTIONS | optionsForAllow |
POST | postForLocation |
postForObject | |
PUT | put |
any | exchange |
execute |
Кроме того, обмен и выполнение могут использовать описанный выше метод в целом.
Внутренний,RestTemplate
Использовать по умолчаниюHttpMessageConverter
экземпляр будетHTTP
сообщение вPOJO
или изPOJO
преобразовать вHTTP
Информация. Преобразователи для основного MIME-типа зарегистрированы по умолчанию, но их также можноsetMessageConverters
Зарегистрируйте другие преобразователи. (На самом деле это не заметно при его использовании. Многие методы имеют параметр responseType, который позволяет вам передать объект, отображаемый телом ответа, а затем нижний слой использует HttpMessageConverter для его отображения)
HttpMessageConverterExtractor<T> responseExtractor =
new HttpMessageConverterExtractor<>(responseType, getMessageConverters(), logger);
HttpMessageConverter.java
Исходный код:
public interface HttpMessageConverter<T> {
//指示此转换器是否可以读取给定的类。
boolean canRead(Class<?> clazz, @Nullable MediaType mediaType);
//指示此转换器是否可以写给定的类。
boolean canWrite(Class<?> clazz, @Nullable MediaType mediaType);
//返回List<MediaType>
List<MediaType> getSupportedMediaTypes();
//读取一个inputMessage
T read(Class<? extends T> clazz, HttpInputMessage inputMessage)
throws IOException, HttpMessageNotReadableException;
//往output message写一个Object
void write(T t, @Nullable MediaType contentType, HttpOutputMessage outputMessage)
throws IOException, HttpMessageNotWritableException;
}
Внутренний,RestTemplate
Использовать по умолчаниюSimpleClientHttpRequestFactory
иDefaultResponseErrorHandler
обрабатываться отдельноHTTP
создания и ошибок, но также может бытьsetRequestFactory
иsetErrorHandler
покрывать.
2. получить практику запроса
2.1. Метод getForObject()
public <T> T getForObject(String url, Class<T> responseType, Object... uriVariables){}
public <T> T getForObject(String url, Class<T> responseType, Map<String, ?> uriVariables)
public <T> T getForObject(URI url, Class<T> responseType)
getForObject()
На самом деле, чемgetForEntity()
Он содержит больше функций для преобразования HTTP в POJO, ноgetForObject
без обработкиresponse
Способность. Потому что он принимает формуpojo
. многое пропустилresponse
Информация.
2.1.1 POJO:
public class Notice {
private int status;
private Object msg;
private List<DataBean> data;
}
public class DataBean {
private int noticeId;
private String noticeTitle;
private Object noticeImg;
private long noticeCreateTime;
private long noticeUpdateTime;
private String noticeContent;
}
Пример: 2.1.2 получить запрос без параметров
/**
* 不带参的get请求
*/
@Test
public void restTemplateGetTest(){
RestTemplate restTemplate = new RestTemplate();
Notice notice = restTemplate.getForObject("http://xxx.top/notice/list/1/5"
, Notice.class);
System.out.println(notice);
}
Отпечатки консоли:
INFO 19076 --- [ main] c.w.s.c.w.c.HelloControllerTest
: Started HelloControllerTest in 5.532 seconds (JVM running for 7.233)
Notice{status=200, msg=null, data=[DataBean{noticeId=21, noticeTitle='aaa', noticeImg=null,
noticeCreateTime=1525292723000, noticeUpdateTime=1525292723000, noticeContent='<p>aaa</p>'},
DataBean{noticeId=20, noticeTitle='ahaha', noticeImg=null, noticeCreateTime=1525291492000,
noticeUpdateTime=1525291492000, noticeContent='<p>ah.......'
Пример: 2.1.3 получить запрос с параметрами 1
Notice notice = restTemplate.getForObject("http://fantj.top/notice/list/{1}/{2}"
, Notice.class,1,5);
Проницательный человек может с первого взгляда увидеть, что используется заполнитель{1}
.
Пример: 2.1.4 получить запрос с параметрами 2
Map<String,String> map = new HashMap();
map.put("start","1");
map.put("page","5");
Notice notice = restTemplate.getForObject("http://fantj.top/notice/list/"
, Notice.class,map);
На первый взгляд, проницательный человек использует карту для загрузки параметров, но она парсит по умолчаниюPathVariable
форма URL.
2.2 Метод getForEntity()
public <T> ResponseEntity<T> getForEntity(String url, Class<T> responseType, Object... uriVariables){}
public <T> ResponseEntity<T> getForEntity(String url, Class<T> responseType, Map<String, ?> uriVariables){}
public <T> ResponseEntity<T> getForEntity(URI url, Class<T> responseType){}
В отличие от метода getForObject(), возвращается следующее:ResponseEntity
Object, если вам нужно преобразовать его в pojo, вам также необходимо ввести класс инструмента json, который используется в соответствии с личными предпочтениями. Может ли Baidu не анализировать jsonFastJson
илиJackson
и другие инструменты. Потом будем учитьсяResponseEntity
Какой метод ниже.
ResponseEntity, HttpStatus, структура BodyBuilder
ResponseEntity.java
public HttpStatus getStatusCode(){}
public int getStatusCodeValue(){}
public boolean equals(@Nullable Object other) {}
public String toString() {}
public static BodyBuilder status(HttpStatus status) {}
public static BodyBuilder ok() {}
public static <T> ResponseEntity<T> ok(T body) {}
public static BodyBuilder created(URI location) {}
...
HttpStatus.java
public enum HttpStatus {
public boolean is1xxInformational() {}
public boolean is2xxSuccessful() {}
public boolean is3xxRedirection() {}
public boolean is4xxClientError() {}
public boolean is5xxServerError() {}
public boolean isError() {}
}
BodyBuilder.java
public interface BodyBuilder extends HeadersBuilder<BodyBuilder> {
//设置正文的长度,以字节为单位,由Content-Length标头
BodyBuilder contentLength(long contentLength);
//设置body的MediaType 类型
BodyBuilder contentType(MediaType contentType);
//设置响应实体的主体并返回它。
<T> ResponseEntity<T> body(@Nullable T body);
}
Видно, что ResponseEntity содержит информацию HttpStatus и BodyBuilder, что нам удобнее для работы с нативными вещами response.
Пример:
@Test
public void rtGetEntity(){
RestTemplate restTemplate = new RestTemplate();
ResponseEntity<Notice> entity = restTemplate.getForEntity("http://fantj.top/notice/list/1/5"
, Notice.class);
HttpStatus statusCode = entity.getStatusCode();
System.out.println("statusCode.is2xxSuccessful()"+statusCode.is2xxSuccessful());
Notice body = entity.getBody();
System.out.println("entity.getBody()"+body);
ResponseEntity.BodyBuilder status = ResponseEntity.status(statusCode);
status.contentLength(100);
status.body("我在这里添加一句话");
ResponseEntity<Class<Notice>> body1 = status.body(Notice.class);
Class<Notice> body2 = body1.getBody();
System.out.println("body1.toString()"+body1.toString());
}
statusCode.is2xxSuccessful()true
entity.getBody()Notice{status=200, msg=null, data=[DataBean{noticeId=21, noticeTitle='aaa', ...
body1.toString()<200 OK,class com.waylau.spring.cloud.weather.pojo.Notice,{Content-Length=[100]}>
Конечно, естьgetHeaders()
Примеров других способов нет.
3. Практика отправки запросов
Точно так же почтовый запрос также имеет
postForObject
иpostForEntity
.
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 rtPostObject(){
RestTemplate restTemplate = new RestTemplate();
String url = "http://47.xxx.xxx.96/register/checkEmail";
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
MultiValueMap<String, String> map= new LinkedMultiValueMap<>();
map.add("email", "844072586@qq.com");
HttpEntity<MultiValueMap<String, String>> request = new HttpEntity<>(map, headers);
ResponseEntity<String> response = restTemplate.postForEntity( url, request , String.class );
System.out.println(response.getBody());
}
Результаты:
{"status":500,"msg":"该邮箱已被注册","data":null}
в коде,MultiValueMap
даMap
подкласс , один из егоkey
может хранить несколькоvalue
, просто посмотрите на этот интерфейс:
public interface MultiValueMap<K, V> extends Map<K, List<V>> {...}
зачем использоватьMultiValueMap
?так какHttpEntity
Принятый тип запроса это.
public HttpEntity(@Nullable T body, @Nullable MultiValueMap<String, String> headers){}
我这里只展示它的一个construct,从它可以看到我们传入的map是请求体,headers是请求头。
зачем использоватьHttpEntity
Потому чтоrestTemplate.postForEntity
метод, хотя запрос, полученный на поверхности,@Nullable Object request
тип, но если вы отследите, то обнаружите, что этоrequest
используетсяHttpEntity
анализировать. Основной код выглядит следующим образом:
if (requestBody instanceof HttpEntity) {
this.requestEntity = (HttpEntity<?>) requestBody;
}else if (requestBody != null) {
this.requestEntity = new HttpEntity<>(requestBody);
}else {
this.requestEntity = HttpEntity.EMPTY;
}
Я попытался использовать карту для передачи параметров, компиляция не сообщит об ошибке, но не может быть выполнена, это недопустимый запрос запроса URL (400 ERROR). На самом деле этот метод запроса удовлетворил почтовый запрос, и куки также являются частью заголовка. Заголовок запроса и тело запроса могут быть установлены по мере необходимости. Другие методы аналогичны.
4. Используйте exchange, чтобы указать метод вызова
Отличие метода exchange() от описанных выше методов getForObject(), getForEntity(), postForObject(), postForEntity() заключается в том, что он может указывать HTTP-тип запроса.
Но вы обнаружите, что методы обмена, кажется,@Nullable HttpEntity<?> requestEntity
Этот параметр означает, что мы по крайней мере используем HttpEntity для передачи тела запроса.Я упоминал исходный код ранее, поэтому рекомендуется использовать HttpEntity для повышения производительности.
Пример
@Test
public void rtExchangeTest() throws JSONException {
RestTemplate restTemplate = new RestTemplate();
String url = "http://xxx.top/notice/list";
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
JSONObject jsonObj = new JSONObject();
jsonObj.put("start",1);
jsonObj.put("page",5);
HttpEntity<String> entity = new HttpEntity<>(jsonObj.toString(), headers);
ResponseEntity<JSONObject> exchange = restTemplate.exchange(url,
HttpMethod.GET, entity, JSONObject.class);
System.out.println(exchange.getBody());
}
Как видите, на этот раз я использовалJSONObject
Объекты передаются и возвращаются.
Конечно, существует много методов HttpMethod, и их использование аналогично.
5. execute() указывает вызывающий метод
excute()
использование иexchange()
Почти так же, он также может указывать разныеHttpMethod
, разница в том, что объект, который он возвращает, является объектом, сопоставленным телом ответа.<T>
, вместоResponseEntity<T>
.
Следует подчеркнуть, что,execute()
Метод — это базовый вызов всех вышеперечисленных методов. Просто посмотрите на один:
@Override
@Nullable
public <T> T postForObject(String url, @Nullable Object request, Class<T> responseType, Map<String, ?> uriVariables)
throws RestClientException {
RequestCallback requestCallback = httpEntityCallback(request, responseType);
HttpMessageConverterExtractor<T> responseExtractor =
new HttpMessageConverterExtractor<>(responseType, getMessageConverters(), logger);
return execute(url, HttpMethod.POST, requestCallback, responseExtractor, uriVariables);
}
Обратите внимание на публичный номер, ответьте
java架构
Получите ресурс видео архитектуры.