RestTemplate详解 Springboot — 用更优雅的方式发HTTP请求

RestTemplate是Spring提供的用于访问Rest服务的客户端,RestTemplate提供了多种便捷访问远程Http服务的方法,能够大大提高客户端的编写效率 。
我之前的HTTP开发是用Apache的HttpClient开发,代码复杂,还得操心资源回收等 。代码很复杂,冗余代码多,稍微截个图,这是我封装好的一个post请求工具:
RestTemplate详解 Springboot — 用更优雅的方式发HTTP请求

文章插图
本教程将带领大家实现Spring生态内RestTemplate的Get请求和Post请求还有exchange指定请求类型的实践和RestTemplate核心方法源码的分析,看完你就会用优雅的方式来发HTTP请求 。
1. 简述RestTemplate
是Spring用于同步client端的核心类,简化了与http服务的通信,并满足RestFul原则,程序代码可以给它提供URL,并提取结果 。默认情况下,RestTemplate默认依赖jdk的HTTP连接工具 。当然你也可以 通过setRequestFactory属性切换到不同的HTTP源,比如Apache HttpComponents?.NETty和OkHttp 。
RestTemplate能大幅简化了提交表单数据的难度,并且附带了自动转换JSON数据的功能,但只有理解了HttpEntity的组成结构(header与body),且理解了与uriVariables之间的差异,才能真正掌握其用法 。这一点在Post请求更加突出,下面会介绍到 。
该类的入口主要是根据HTTP的六个方法制定: HTTP method
RestTemplate methods
DELETE
delete
GET
getForObject
 
getForEntity
HEAD
headForHeaders
OPTIONS
optionsForAllow
POST
postForLocation
 
postForObject
PUT
put
any
exchange
 
execute
此外,exchange和excute可以通用上述方法 。
在内部,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. get请求实践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;}publicclass DataBean {private int noticeId;private String noticeTitle;private Object noticeImg;private long noticeCreateTime;private long noticeUpdateTime;private String noticeContent;}示例:2.1.2 不带参的get请求 /*** 不带参的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=https://www.isolves.com/it/cxkf/jiagou/2023-09-14/[DataBean{noticeId=21, noticeTitle='aaa', noticeImg=null, noticeCreateTime=1525292723000, noticeUpdateTime=1525292723000, noticeContent='

aaa

'}, DataBean{noticeId=20, noticeTitle='ahaha', noticeImg=null, noticeCreateTime=1525291492000, noticeUpdateTime=1525291492000, noticeContent='


推荐阅读