#先了解⼀下HTTP 协议
史前时期
HTTP 协议在我们的⽣活中随处可见,打开⼿机或者电脑,只要你上⽹,不论是⽤ iPhone、Android、Windows 还是 Mac,不论是⽤浏览器还是 App,不论是看新闻、短视频还是听⾳乐、玩游戏,后⾯总会有 HTTP 在默默为你服务。
据 NetCraft 公司统计,⽬前全球⾄少有 16 亿个⽹站、2 亿多个独⽴域名,⽽这个庞⼤⽹络世界的底层运转机制就是 HTTP。
那么,在享受如此便捷舒适的⽹络⽣活时,你有没有想过,HTTP 协议是怎么来的?它最开始是什么样⼦的?⼜是如何⼀步⼀步发展到今天,⼏乎“统治”了整个互联⽹世界的呢?
20 世纪 60 年代,美国国防部⾼等研究计划署(ARPA)建⽴了 ARPA ⽹,它有四个分布在各地的节点,被认为是如今互联⽹的“始祖”。
然后在 70 年代,基于对 ARPA ⽹的实践和思考,研究⼈员发明出了著名的 TCP/IP 协议。由于具有良好的分层结构和稳定的性能,TCP/IP 协议迅速战胜其他竞争对⼿流⾏起来,并在 80 年代中期进⼊了 UNIX 系统内核,促使更多的计算机接⼊了互联⽹。创世纪
19 年,任职于欧洲核⼦研究中⼼(CERN)的蒂姆·伯纳斯 - 李(Tim Berners-Lee)发表了⼀篇论⽂,提出了在互联⽹上构建超链接⽂档系统的构想。这篇论⽂中他确⽴了三项关键技术。
URI:即统⼀资源标识符,作为互联⽹上资源的唯⼀⾝份;HTML:即超⽂本标记语⾔,描述超⽂本⽂档;HTTP:即超⽂本传输协议,⽤来传输超⽂本。 所以在这⼀年,我们的HTTP诞⽣了。HTTP/0.9
20 世纪 90 年代初期的互联⽹世界⾮常简陋,计算机处理能⼒低,存储容量⼩,⽹速很慢,还是⼀⽚“信息荒漠”。⽹络上绝⼤多数的资源都是纯⽂本,很多通信协议也都使⽤纯⽂本,所以 HTTP 的设计也不可避免地受到了时代的。
这⼀时期的 HTTP 被定义为 0.9 版,结构⽐较简单,为了便于服务器和客户端处理,它也采⽤了纯⽂本格式。蒂姆·伯纳斯 - 李最初设想的系统⾥的⽂档都是只读的,所以只允许⽤“GET”动作从服务器上获取 HTML ⽂档,并且在响应请求之后⽴即关闭连接,功能⾮常有限。
HTTP/0.9 虽然很简单,但它作为⼀个“原型”,充分验证了 Web 服务的可⾏性,⽽“简单”也正是它的优点,蕴含了进化和扩展的可能性,因为: “把简单的系统变复杂”,要⽐“把复杂的系统变简单”容易得多。HTTP/1.0
1993 年,NCSA(美国国家超级计算应⽤中⼼)开发出了 Mosaic,是第⼀个可以图⽂混排的浏览器,随后⼜在 1995 年开发出了服务器软件 Apache,简化了 HTTP 服务器的搭建⼯作。
同⼀时期,计算机多媒体技术也有了新的发展:1992 年发明了 JPEG 图像格式,1995 年发明了 MP3 ⾳乐格式。
这些新软件新技术⼀经推出⽴刻就吸引了⼴⼤⽹民的热情,更的多的⼈开始使⽤互联⽹,研究 HTTP 并提出改进意见,甚⾄实验性地往协议⾥添加各种特性,从⽤户需求的⾓度促进了 HTTP 的发展。
于是在这些已有实践的基础上,经过⼀系列的草案,HTTP/1.0 版本在 1996 年正式发布。它在多⽅⾯增强了 0.9 版,形式上已经和我们现在的 HTTP 差别不⼤了,例如:
增加了 HEAD、POST 等新⽅法
增加了响应状态码,标记可能的错误原因引⼊了协议版本号概念
引⼊了 HTTP Header(头部)的概念,让 HTTP 处理请求和响应更加灵活传输的数据不再仅限于⽂本HTTP/1.1
1995 年,⽹景的 Netscape Navigator 和微软的 Internet Explorer 开始了著名的“浏览器⼤战”,都希望在互联⽹上占据主导地位。于是在“浏览器⼤战”结束之后的 1999年,HTTP/1.1 发布了 RFC ⽂档,编号为 2616,正式确⽴了延续⼗余年的传奇。 HTTP/1.1 主要的变更点有:
增加了 PUT、DELETE 等新的⽅法;增加了缓存管理和控制;
明确了连接管理,允许持久连接;
允许响应数据分块(chunked),利于传输⼤⽂件;强制要求 Host 头,让互联⽹主机托管成为可能。HTTP/2
HTTP/1.1 发布之后,整个互联⽹世界呈现出了爆发式的增长,度过了⼗多年的“快乐时光”,更涌现出了 Facebook、Twitter、淘宝、京东等互联⽹新贵。
这期间也出现了⼀些对 HTTP 不满的意见,主要就是连接慢,⽆法跟上迅猛发展的互联⽹,但 HTTP/1.1 标准⼀直“岿然不动”,⽆奈之下⼈们只好发明各式各样的“⼩花招”来缓解这些问题,⽐如以前常见的切图、JS 合并等⽹页优化⼿段。
终于有⼀天,搜索巨头 Google 忍不住了,⾸先开发了⾃⼰的浏览器 Chrome,然后推出了新的 SPDY 协议,并在 Chrome ⾥应⽤于⾃家的服务器,如同⼗多年前的⽹景与微软⼀样,从实际的⽤户⽅来“倒逼”HTTP 协议的变⾰,这也开启了第⼆次的“浏览器⼤战”。
历史再次重演,不过这次的胜利者是 Google,Chrome ⽬前的全球的占有率超过了 60%。Google 借此顺势把 SPDY 推上了标准的宝座,互联⽹标准化组织以 SPDY 为基础开始制定新版本的 HTTP 协议,最终在 2015 年发布了 HTTP/2,RFC 编号 70。
SPDY(读作“SPeeDY”)是Google开发的基于TCP的会话层协议,⽤以最⼩化⽹络延迟,提升⽹络速度,优化⽤户的⽹络使⽤体验。
SPDY并不是⼀种⽤于替代HTTP的协议,⽽是对HTTP协议的增强。新协议的功能包括数据流的多路复⽤、请求优先级以及HTTP报头压缩。⾕歌表⽰,引⼊SPDY协议后,在实验室测试中页⾯加载速度⽐原先快%。
HTTP/2 的制定充分考虑了现今互联⽹的现状:宽带、移动、不安全,在⾼度兼容 HTTP/1.1 的同时在性能改善⽅⾯做了很⼤努⼒,主要的特点有:
⼆进制协议,不再是纯⽂本
可发起多个请求,废弃了 1.1 ⾥的管道使⽤专⽤算法压缩头部,减少数据传输量允许服务器主动向客户端推送数据增强了安全性,“事实上”要求加密通信
虽然 HTTP/2 到今天已经五岁,也衍⽣出了 gRPC 等新协议,但由于 HTTP/1.1 实在是太过经典和强势,⽬前它的普及率还⽐较低,⼤多数⽹站使⽤的仍然还是 20 年前的HTTP/1.1。HTTP/3
在 HTTP/2 还处于草案之时,Google ⼜发明了⼀个新的协议,叫做 QUIC,⽽且还是相同的“套路”,继续在 Chrome 和⾃家服务器⾥试验着“玩”,依托它的庞⼤⽤户量和数据量,持续地推动 QUIC 协议成为互联⽹上的“既成事实”。
2018 年,互联⽹标准化组织 IETF 提议将“HTTP over QUIC”更名为“HTTP/3”并获得批准,HTTP/3 正式进⼊了标准化制订阶段,也许两三年后就会正式发布,到时候我们很
可能会跳过 HTTP/2 直接进⼊ HTTP/3。
QUIC(Quick UDP Internet Connection)是⾕歌制定的⼀种基于UDP的低时延的互联⽹传输层协议。在2016年11⽉国际互联⽹⼯程任务组(IETF)召开了第⼀次QUIC⼯作组会议,受到了业界的⼴泛关注。这也意味着QUIC开始了它的标准化过程,成为新⼀代传输层协议
了解这么多,那到底HTTP是什么呢?
你可能会不假思索、脱⼝⽽出:“HTTP 就是超⽂本传输协议,也就是 HyperText Transfer Protocol。”
回答的也没错,但是太过简单。更准确的回答应该是“HTTP 是⼀个在计算机世界⾥专门在两点之间传输⽂字、图⽚、⾳频、视频等超⽂本数据的约定和规范”
#关于HttpClient
简介 官⽹这样说
超⽂本传输协议(HTTP)可能是当今Internet上使⽤的最重要的协议。
Web服务,⽀持⽹络的设备和⽹络计算的增长继续将HTTP协议的作⽤扩展到⽤户驱动的Web浏览器之外,同时增加了需要HTTP⽀持的应⽤程序的数量。尽管java.net软件包提供了⽤于通过HTTP访问资源的基本功能,但它并未提供许多应⽤程序所需的全部灵活性或功能。HttpClient试图通过提供⾼效,最新且功能丰富的程序包来实现此空⽩,以实现最新HTTP标准和建议的客户端。
HttpClient是为扩展⽽设计的,同时提供了对基本HTTP协议的强⼤⽀持,
对于构建HTTP感知的客户端应⽤程序(例如Web浏览器,Web服务客户端或利⽤或扩展HTTP协议进⾏分布式通信的系统)的任何⼈来说,HttpClient都可能会感兴趣。
HttpClient 是 Apache Jakarta Common 下的⼦项⽬,⽤来提供⾼效的、最新的、功能丰富的⽀持 HTTP 协议的客户端编程⼯具包,并且它⽀持 HTTP 协议最新的版本和建议。HttpClient 已经应⽤在很多的项⽬中,⽐如 Apache Jakarta 上很著名的另外两个开源项⽬ Cactus 和 HTMLUnit 都使⽤了 HttpClient。
HttpClient 相⽐传统 JDK ⾃带的URLConnection,增加了易⽤性和灵活性,它不仅是客户端发送 HTTP 请求变得容易,⽽且也⽅便了开发⼈员测试接⼝(基于 HTTP 协议的),即提⾼了开发的效率,也⽅便提⾼代码的健壮性。因此熟练掌握 HttpClient 是很重要的必修内容,掌握 HttpClient 后,相信对于 HTTP 协议的了解会更加深⼊。
了解更新详情,参考官⽹ 特性
基于标准、纯净的 Java 语⾔。实现了 HTTP 1.0 和 HTTP 1.1
以可扩展的⾯向对象的结构实现了 HTTP 全部的⽅法(GET, POST, PUT, DELETE, HEAD, OPTIONS, and TRACE)。⽀持 HTTPS 协议。
通过 HTTP 代理建⽴透明的连接。
利⽤ CONNECT ⽅法通过 HTTP 代理建⽴隧道的 HTTPS 连接。
Basic, Digest, NTLMv1, NTLMv2, NTLM2 Session, SNPNEGO/Kerberos 认证⽅案。插件式的⾃定义认证⽅案。
便携可靠的套接字⼯⼚使它更容易的使⽤第三⽅解决⽅案。
连接管理器⽀持多线程应⽤。⽀持设置最⼤连接数,同时⽀持设置每个主机的最⼤连接数,发现并关闭过期的连接。⾃动处理 Set-Cookie 中的 Cookie。插件式的⾃定义 Cookie 策略。
Request 的输出流可以避免流中内容直接缓冲到 Socket 服务器。Response 的输⼊流可以有效的从 Socket 服务器直接读取相应内容。在 HTTP 1.0 和 HTTP 1.1 中利⽤ KeepAlive 保持持久连接。直接获取服务器发送的 response code 和 headers。设置连接超时的能⼒。
实验性的⽀持 HTTP 1.1 response caching。源代码基于 Apache License 可免费获取。使⽤流程
1. 创建 HttpClient 对象
2. 创建请求⽅法的实例,并指定请求 URL。如果需要发送 GET 请求,创建 HttpGet 对象;如果需要发送 POST 请求,创建 HttpPost 对象
3. 如果需要发送请求参数,可调⽤ HttpGet、HttpPost 共同的 setParams(HttpParams params) ⽅法来添加请求参数;对于 HttpPost 对象⽽⾔,也可调⽤ setEntity(HttpEntity entity) ⽅法来设置请求参数
4. 调⽤ HttpClient 对象的 execute(HttpUriRequest request) 发送请求,该⽅法返回⼀个 HttpResponse5. 调⽤ HttpResponse 的 getAllHeaders()、getHeaders(String name) 等⽅法可获取服务器的响应头
6. 调⽤ HttpResponse 的 getEntity() ⽅法可获取 HttpEntity 对象,该对象包装了服务器的响应内容。程序可通过该对象获取服务器的响应内容7. 释放连接。⽆论执⾏⽅法是否成功,都必须释放连接使⽤⽤例 pom配置
创建Get请求
@Test
void testGet() {
// 创建 HttpClient 客户端
CloseableHttpClient httpClient = HttpClients.createDefault(); // 创建 HttpGet 请求
HttpGet httpGet = new HttpGet(\"http://192.168.1.250:15005/dsm-ubm/base-role-info/list\"); // 设置长连接
httpGet.setHeader(\"Connection\ // 设置认证信息
httpGet.setHeader(\"Authorization\ // 设置代理(模拟浏览器版本)
httpGet.setHeader(\"User-Agent\ CloseableHttpResponse httpResponse = null; try {
// 请求并获得响应结果
httpResponse = httpClient.execute(httpGet);
HttpEntity httpEntity = httpResponse.getEntity(); //打印结果
System.out.println(EntityUtils.toString(httpEntity)); } catch (IOException e) { e.printStackTrace(); } finally {
if (httpResponse != null) { try {
httpResponse.close(); } catch (IOException e) { e.printStackTrace(); }
}
if (httpClient != null) { try {
httpClient.close(); } catch (IOException e) { e.printStackTrace(); } } }}
keep-alive说明
keep-alive:从HTTP/1.1起,浏览器默认都开启了Keep-Alive,保持连接特性,客户端和服务器都能选择随时关闭连接,则请求头中为connection:close。
简单地说,当⼀个⽹页打开完成后,客户端和服务器之间⽤于传输HTTP数据的TCP连接不会关闭,如果客户端再次访问这个服务器上的⽹页,会继续使⽤这⼀条已经建⽴的TCP连接。但是Keep-Alive不会永久保持连接,它有⼀个保持时间,可以在不同的服务器软件(如Apache)中设定这个时间。
创建Post请求,content-type=application/json
@Test
void testPost() {
// 创建 HttpClient 客户端
CloseableHttpClient httpClient = HttpClients.createDefault(); // 创建 HttpPost 请求
HttpPost httpPost = new HttpPost(\"http://192.168.1.250:15005/dsm-ubm/api/getInAreaPatientList\"); // 设置长连接
httpPost.setHeader(\"Connection\ // 设置认证信息
httpPost.setHeader(\"Authorization\ // 设置代理(模拟浏览器版本)
httpPost.setHeader(\"User-Agent\ // 创建 HttpPost 参数
JSONObject jsonObject = new JSONObject(); jsonObject.put(\"FromTime\ jsonObject.put(\"Ward\
CloseableHttpResponse httpResponse = null; try {
StringEntity entity = new StringEntity(jsonObject.toJSONString(), \"utf-8\"); entity.setContentType(\"application/json\"); httpPost.setEntity(entity);
httpResponse = httpClient.execute(httpPost); HttpEntity httpEntity = httpResponse.getEntity(); //打印结果
System.out.println(EntityUtils.toString(httpEntity)); } catch (IOException e) { e.printStackTrace(); } finally { try {
if (httpResponse != null) { httpResponse.close(); }
} catch (IOException e) { e.printStackTrace(); }
try {
if (httpClient != null) { httpClient.close(); }
} catch (IOException e) { e.printStackTrace(); } } }
创建Post请求,content-type=application/x-www-form-urlencoded
@Test
void testPost() {
// 创建 HttpClient 客户端
CloseableHttpClient httpClient = HttpClients.createDefault(); // 创建 HttpPost 请求
HttpPost httpPost = new HttpPost(\"http://localhost:8080/hello\"); // 设置长连接
httpPost.setHeader(\"Connection\ // 设置认证信息
httpPost.setHeader(\"Authorization\ // 设置代理(模拟浏览器版本)
httpPost.setHeader(\"User-Agent\ // 创建 HttpPost 参数
List params.add(new BasicNameValuePair(\"message\鹧鸪哨\")); CloseableHttpResponse httpResponse = null; try { httpPost.setEntity(new UrlEncodedFormEntity(params, \"utf-8\")); httpResponse = httpClient.execute(httpPost); HttpEntity httpEntity = httpResponse.getEntity(); //打印结果 System.out.println(EntityUtils.toString(httpEntity)); } catch (IOException e) { e.printStackTrace(); } finally { try { if (httpResponse != null) { httpResponse.close(); } } catch (IOException e) { e.printStackTrace(); } try { if (httpClient != null) { httpClient.close(); } } catch (IOException e) { e.printStackTrace(); } } } application/json与application/x-www-form-urlencoded区别 application/json和application/x-www-form-urlencoded都是表单数据发送时的编码类型。默认地,表单数据会编码为application/x-www-form-urlencoded。就是说,在发送到服务器之前,所有字符都会进⾏编码。 application/json,随着json规范的越来越流⾏,并且浏览器⽀持程度原来越好,许多开发⼈员将application/json作为请求content-type,告诉服务器请求的主体内容是json格式的字符串,服务器端会对json字符串进⾏解析,这种⽅式的好处就是前端⼈员不需要关⼼数据结构的复杂度,只要是标准的json格式就能提交成功,需要封装成对象的话,可以加上@RequestBody注解 application/x-www-form-urlencoded是Jquery的Ajax请求默认⽅式,这种⽅式的好处就是浏览器都⽀持,在请求发送过程中会对数据进⾏序列化处理,以键值对形式,数据拼接⽅式为key=value的⽅式,后台如果使⽤对象接收的话,可以⾃动封装成对象 @RequestBody和@RequestParam区别@RequestParam 1. ⽤来处理Content-Type: 为 application/x-www-form-urlencoded编码的内容。(Http协议中,如果不指定Content-Type,则默认传递的参数就是application/x-www-form-urlencoded类型)。 2. 在Content-Type: application/x-www-form-urlencoded的请求中, get ⽅式中queryString的值,和post⽅式中 body data的值都会被Servlet接受到并转化到Request.getParameter()参数集中,所以@RequestParam可以获取的到。@RequestBody 1. 处理HttpEntity传递过来的数据,⼀般⽤来处理⾮Content-Type: application/x-www-form-urlencoded编码格式的数据。2. GET请求中,因为没有HttpEntity,所以@RequestBody并不适⽤。 3. POST请求中,通过HttpEntity传递的参数,必须要在请求头中声明数据的类型Content-Type,SpringMVC通过使⽤HandlerAdapter 配置的HttpMessageConverters来解析HttpEntity中的数据,然后绑定到相应的bean上。 @ResponseBody 和 @RequestBody 区别 @ResponseBody是作⽤在⽅法上的,@ResponseBody 表⽰该⽅法的返回结果直接写⼊ HTTP response body 中,⼀般在异步获取数据时使⽤【也就是AJAX】,在使⽤@RequestMapping后,返回值通常解析为跳转路径,但是加上 @ResponseBody 后返回结果不会被解析为跳转路径,⽽是直接写⼊ HTTP response body 中。 ⽐如异步获取json 数据,加上 @ResponseBody 后,会直接返回 json 数据。 @RequestBody ⽤于读取Request请求的body部分数据,使系统默认的HttpMessageConverter进⾏解析,然后把相应的数据绑定要返回的对象上,再把HttpMessageConverter返回的对象数据绑定到Controller⽅法的参数上。 #关于RestTemplate 介绍 RestTemplate 是从 Spring3.0 开始⽀持的⼀个 HTTP 请求⼯具,它提供了常见的REST请求⽅案的模版,例如 GET 请求、POST 请求、PUT 请求、DELETE 请求以及⼀些通⽤的请求执⾏⽅法 exchange 以及 execute。RestTemplate 继承⾃ InterceptingHttpAccessor 并且实现了 RestOperations 接⼝,其中 RestOperations 接⼝定义了基本的RESTful 操作,这些操作在 RestTemplate 中都得到了实现。是⽐httpClient更优雅的Restful URL访问。 RestTemplate是Spring提供的⽤于访问Rest服务的客户端, RestTemplate提供了多种便捷访问远程Http服务的⽅法,能够⼤⼤提⾼客户端的编写效率。 调⽤RestTemplate的默认构造函数,RestTemplate对象在底层通过使⽤java.net包下的实现创建HTTP 请求,可以通过使⽤ClientHttpRequestFactory指定不同的HTTP请求⽅式。ClientHttpRequestFactory接⼝主要提供了三种实现⽅式 1、SimpleClientHttpRequestFactory⽅式,此处⽣成SimpleBufferingClientHttpRequest,使⽤HttpURLConnection创建底层的Http请求连接2、HttpComponentsClientHttpRequestFactory⽅式,此处⽣成HttpComponentsClientHttpRequest,使⽤http client来实现⽹络请求3、OkHttp3ClientHttpRequestFactory⽅式,此处⽣成OkHttp3ClientHttpRequest,使⽤okhttp来实现⽹络请求优点 并没有重写底层的HTTP请求技术,⽽是提供配置,可选⽤OkHttp/HttpClient等 在OkHttp/HttpClient之上,封装了请求操作,可以定义Convertor来实现对象到请求body的转换⽅法,以及返回body到对象的转换⽅法。配置 @Configuration public class RestTemplateConfig { @Bean public RestTemplate restTemplate(ClientHttpRequestFactory factory) { return new RestTemplate(factory); } @Bean public ClientHttpRequestFactory simpleClientHttpRequestFactory() { SimpleClientHttpRequestFactory factory = new SimpleClientHttpRequestFactory(); //单位为ms factory.setReadTimeout(5000); //单位为ms factory.setConnectTimeout(5000); return factory; } @Primary @Bean public ClientHttpRequestFactory httpComponentsClientHttpRequestFactory() { HttpComponentsClientHttpRequestFactory factory = new HttpComponentsClientHttpRequestFactory(); //单位为ms factory.setReadTimeout(6000); //单位为ms factory.setConnectTimeout(6000); return factory; } /*@Bean public ClientHttpRequestFactory okHttp3ClientHttpRequestFactory() { OkHttp3ClientHttpRequestFactory factory = new OkHttp3ClientHttpRequestFactory(); //单位为ms factory.setReadTimeout(7000); //单位为ms factory.setConnectTimeout(7000); return factory; }*/} 使⽤ @RunWith(SpringRunner.class)@SpringBootTestpublic class TestGet { @Autowired private RestTemplate restTemplate; @Test public void testGet() { String url = \"http://localhost:8080/welcome?message={1}\"; //可以使⽤map来封装请求参数 Map String jsonResult = restTemplate.getForObject(url, String.class, map); System.out.println(\"result:\" + jsonResult); }} @RunWith(SpringRunner.class)@SpringBootTest public class TestPost { @Autowired private RestTemplate restTemplate; @Test public void testPost() { RequestObj requestObj = RequestObj.builder().id(1) .age(20) .name(\"鹧鸪哨\").build(); String url = \"http://localhost:8080/test\"; //发起请求 String jsonResult = restTemplate.postForObject(url, requestObj, String.class); System.out.println(\"result:\" + jsonResult); }} #关于Feign 介绍 Feign 的英⽂表意为“假装,伪装,变形”, 是⼀个http请求调⽤的轻量级框架,可以以Java接⼝注解的⽅式调⽤Http请求,⽽不⽤像Java中通过封装HTTP请求报⽂的⽅式直接调⽤。Feign通过处理注解,将请求模板化,当实际调⽤的时候,传⼊参数,根据参数再应⽤到请求上,进⽽转化成真正的请求,这种请求相对⽽⾔⽐较直观。 Feign被⼴泛应⽤在Spring Cloud 的解决⽅案中,是学习基于Spring Cloud 微服务架构不可或缺的重要组件。 具体详情参考 pom配置 Feign配置 @Configuration public class FeignConfig { @Bean Logger.Level feignLoggerLevel() { //记录请求和响应的标头,正⽂和元数据 return Logger.Level.FULL; } /** * 如果远程接⼝由于各种问题没有在响应中设置content-type, * 导致FeignClient接收的时候contentType为null,HttpMessageConverterExtractor将其设置为MediaType.APPLICATION_OCTET_STREAM * 此时MessageConverter需要增加MediaType.APPLICATION_OCTET_STREAM⽀持 */ @Bean public Decoder feignDecoder() { MappingJackson2HttpMessageConverter hmc = new MappingJackson2HttpMessageConverter(customObjectMapper()); List List mediaTypeList.add(MediaType.APPLICATION_OCTET_STREAM); hmc.setSupportedMediaTypes(mediaTypeList); ObjectFactory @Bean public ObjectMapper customObjectMapper() { //解决LocalDate、LocalDateTime反序列化问题 ObjectMapper objectMapper = new ObjectMapper(); objectMapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS); objectMapper.registerModule(new JavaTimeModule()); return new ObjectMapper(); }} 启⽤feign客户端 @SpringBootApplication@EnableFeignClients public class DemoHttpApplication { public static void main(String[] args) { SpringApplication.run(DemoHttpApplication.class, args); } } 定义feign客户端 @FeignClient(name = \"test-service\public interface TestClient { @GetMapping(\"/welcome\") String welcome(@RequestParam String message); @PostMapping(\"/test\") String test(@RequestBody RequestObj param);} 测试调⽤ @RunWith(SpringRunner.class)@SpringBootTest public class FeignTest { @Autowired private TestClient testClient; @Test public void testGet() { System.out.println(\"result:\" + testClient.welcome(\"world\")); } @Test public void testPost() { RequestObj requestObj = RequestObj.builder().id(1) .age(20) .name(\"鹧鸪哨\").build(); System.out.println(\"result:\" + testClient.test(requestObj)); }} 因篇幅问题不能全部显示,请点此查看更多更全内容
Copyright © 2019- 69lv.com 版权所有 湘ICP备2023021910号-1
违法及侵权请联系:TEL:199 1889 7713 E-MAIL:2724546146@qq.com
本站由北京市万商天勤律师事务所王兴未律师提供法律服务