技术之路,不进即退 。吾等菜鸡应埋头于技术之路,破甲斩棘。勿做土鸡瓦狗,贪图安逸。
今天我就来讲一讲我对于RestTemplate的一些理解,我相信大家肯定很多都会用。我今天把它拿出来讲的原因,就是让不清楚的人通过阅读这篇文章能够直接会用并且能懂得其中大概的原理。其实去年大学毕业到现在我可以说用过这个东西很多次了,由于网上的资料繁杂,所以当时只是单纯想着会用就行,具体的一些琐碎知识并未深究。
一 :概述
RestTemplate看名字就知道是“全家桶”的一员,其实我当时选择它的原因也是因为这一点。顺带说一句,它的底层是对httpclient进行了封装,在这里就不喧宾夺主了,以后有机会我再写一下相关的文章。
现在除了httpclient之外RPC 以及队列的使用看可以说也是越来越广泛了。在netty等NIO框架因为需要高效的传输所以往往选择RPC,队列则用于回调以及设备消息之间的传递(我是用来储存mqtt的消息)。Http这个经久不衰的大佬自然不用多说,简单,支持广泛,高度兼容性。
Http client 是否优秀可以从如下几个方面进行判断。
1. 连接池属性
我们现在大多数使用的仍是HTTP1.1,它并不支持多路复用,因此我们为了避免频繁的建立断开连接损耗性能,连接池的是衡量是优秀的一个重要标准。
2. 超时时间属性
设置时间超时属性,可以说对于Httpclient是必须要设置的属性。毕竟不可能我请求一个地址不可能无期限的等下去。你想象一下,你发送了一个请求,对方一直无响应。这时候你发挥了你“不见不散”的良好品质,当临终前的时候对方告诉你:“不好意思啊,接口我还没写呢。一路走好,兄弟。” 是不是极度尴尬。
3. 支持异步
客户端与服务端模式通常被人性能差的一个主要原因是因为它在过去很长的一段时间里无法对异步进行支持,这里不仅仅指非阻塞IO,还包括异步的编程模型。这句话也就是说,即便Http的协议栈是继续非阻塞IO实现的,调用客户端或服务端处理线的线程也会花费大量时间在等待IO上。
4.可以对请求和响应进行编解码
简洁来说我们不用直接面对原始消息,因此编解码大大的减少了开发的工作量。
5.扩展性
这个特性其实适用于任何地方,我曾听一位大佬说过,以增量的方式去编写代码,是一个架构师的必备的技能。而这个以增量的方式不仅仅是说无限的添加代码,而是当我们改动一部分代码而不影响其他代码。
RestTemplate的使用方法
ps:建议使用exchange ,其他方法都是对execute进行了封装,都拥有各自的局限性。
String url = "http://x.x.x.x:8080/v0/mcweb/mscenter/webservice/serverload"; try { User a = restTemplate.getForObject(url, User.class); System.out.println(a); } catch (HttpStatusCodeException e) { System.out.println(e.getResponseBodyAsString()); }
通过第一个图中我们可以看到,如果调用getForObject我们是没办法对编码格式或者请求做一些操作,比如添加消息头信息。
下面我们从头讲解一下,我以springboot项目为例。
首先我们需要配置一个关于RestTemplate的一个bean
@Configurationpublic class RestConfig { @Bean @ConditionalOnMissingBean({RestOperations.class, RestTemplate.class}) public RestTemplate restTemplate(ClientHttpRequestFactory factory) { return new RestTemplate(factory); } @Bean @ConditionalOnMissingBean({ClientHttpRequestFactory.class}) public ClientHttpRequestFactory simpleClientHttpRequestFactory() { SimpleClientHttpRequestFactory factory = new SimpleClientHttpRequestFactory(); factory.setReadTimeout(15000); factory.setConnectTimeout(15000); return factory; }//下面被注的是对编码进行了处理,但是一般是不需要的,如果你是第一次用的话,可以直接采用上面的配置,如果采用下面的是无法使用String进行接受的,这一点是需要注意的。/* @Bean @ConditionalOnMissingBean({RestOperations.class, RestTemplate.class}) public RestTemplate restTemplate(ClientHttpRequestFactory factory) { // return new RestTemplate(factory); RestTemplate restTemplate = new RestTemplate(factory); // 使用 utf-8 编码集的 conver 替换默认的 conver(默认的 string conver 的编码集为"ISO-8859-1") List> messageConverters = restTemplate.getMessageConverters(); messageConverters.removeIf(converter -> converter instanceof StringHttpMessageConverter); messageConverters.add(new StringHttpMessageConverter(Charset.forName("UTF-8"))); return restTemplate; } @Bean @ConditionalOnMissingBean({ClientHttpRequestFactory.class}) public ClientHttpRequestFactory simpleClientHttpRequestFactory() { SimpleClientHttpRequestFactory factory = new SimpleClientHttpRequestFactory(); factory.setReadTimeout(15000); factory.setConnectTimeout(15000); return factory; }*/}
通过上图我们可以看到,采用的 APPLICATION_FORM_URLENCODED格式进行消息发送的。也可以选择 APPLICATION_JSON_UTF8这种json格式。
如果返回值如下。
{"Result":"2