完成OSS.Http底层HttpClient重构封装 支持标准库
作者:KevinCC 发布时间:2021-09-28 11:25:40
OSS.Http项目对于.Net Standard标准库的支持已经迁移完毕,OSS开源系列两个最底层的类库已经具备跨运行时支持的能力。由于OSS.Http类库是几年前我参照RestSharp的思路,完成的一个轻量型Http请求框架。因为时间较久底层使用的还是HttpWebRequest,这次基本上是完全重构,这篇文章主要包含 1. HttpClient的介绍,2. 重构的思路, 3. 容易遇到的问题。
一. httpclient的基本介绍
HttpClient应该是在.net framework4.5版本左右引用的新功能,在此之前常用的是HttpWebRequest,相比较而言,前者更加的简单清晰,最重要的是完全支持.net standard API,这也是我选择它的重要原因。
HttpClient在结构上做了很大的调整,并且是完全异步的实现,可以说从底层上完成了异步的支持,这里先介绍对应的几个主要类:
1. HtttpRequestMessage
请求的基本信息,请求地址,请求动作等,此值是在HttpClient发起请求的方法中当参数传入,与他对应的是响应 HttpResponseMessage
2. HttpContent
请求的内容体,主要包含请求的具体内容,contenttype,contentlenght等,是HtttpRequestMessage的一个属性,这两个都包含Headers属性,但是范围分别不一样,这个是很容易混淆出错的地方,我给做了简单分类:
HttpRequestMessage的头部(HttpRequestHeaders )主要是请求的属性,如Accept,UserAgent,AcceptEncoding等http链接的基本属性。
HttpContent的头部(HttpContentHeaders)主要是当前请求内容的属性,主要有:Allow,Content-Encoding,Content-Length,Content-Type ,Expires ,Last-Modified 等,详见官方类库。
HttpContent 系统提供了几个默认实现,主要如下几个:
3. HttpMessageHandler
此类主要作用是请求内容处理动作等的定义,如是否支持重定向,是否可以使用cookie,代理Proxy等,偏向于系统的设置,可以此值通过HttpClient构造函数传入其中,系统默认的提供的子类为HttpClientHandler。
4. HttpClient
具体的请求实现调用实现,完整实现了POST,GET,Delete等Http请求方法,所有的方法最终调用的是SendAsync方法。
上边的四个主要类,构成了HttpClient请求的主要实现,如果你只是简单的使用,那么只需要关心HttpClient即可,如下:
其实在它内部已经默认实现了HttpRequestMessage和HttpClientHandler的赋值。
虽然简单介绍,但是基本上可以看出,HttpClient的实现做了非常明确的分工,不是再像以前所有的设置都集中在webrequest中。分工的明确最直接的优势是HttpClient实现了多请求共用,参见博文:
The default HttpClient is the simplest way in which you can start sending requests. A single HttpClient can be used to send as many HTTP requests as you want concurrently so in many scenarios you can just create one HttpClient and then use that for all your requests.
也就是当你系统中要发起不同的请求时,可以共用一个HttpClient,而不用像HttpWebReqest基本每次请求都需要重新定义一个对象,以减少资源的消耗。
二. 重构OSS.Http
回到正题,重构我们的当前代码模块,如我所说,由于.Net Standard下完全不提供httpWebRequest的支持,直接导致了我做出重新实现的决定,因为以前httpWebRequest的简陋,所以我基本上做了很大的封装框架,上层完全不需要接触具体的底层实现,基本上实现了RestSharp的核心,有兴趣的同学可以参考代码 OSS.Http 下Old分支。
重构之前由于对HttpClient不是十分了解,本想延续已有框架流程,转换实现。不过随着对Client文档的查看研究,发现很多封装已经完全不需要,流程也发生了变化,所以删除很多原来框架下的东西,重新整理出最终的实现。
当然现在的HttpClient本身实现已经足够简单清晰,不过在很多情况下直接调用POST,GET等方法,会减少部分代码的重用,像在OSS.Social项目中,底层我只需要实现一个RestCommon方法,即可达到全局请求控制,调用方只需要提供Url,HttpMothed,Parameter即可。
这里我画了一个简单的流程图作为呈现:
流程基本没有太大的出入,代码在Github,文件的结构如下:
Mos文件下: Enum.cs 枚举类,FileParameter.cs 文件参数类,FormParameter Form表单参数类 ,OsHttpRequest 请求参数类,
OsRest.cs 是当前封装类的主要实现,同时为了保证HttpClient本身功能通用,OsRest继承自HttpClient,同时提供了RestSend方法,在这个方法中完成流程的实现并最终调用SendAsync方法执行请求。
RestUtil.cs 辅助类,完成了全局OsRest(HttpClient)的共用,并定义了一个默认HttpClientHandler实现,正常直接调用这个类就可以了。
流程中的执行用户自定义设置,可以在OSHttpRequest中的RequestSet委托属性中设置,例如可以设置访问类型是json:
三. 容易遇到的问题
虽然整个重构后的代码已经不多了,但是应该还是有些问题可以给大家分享下
1. Header赋值问题,请参见我第一部分,一定要分清不同Headers,否则就可能给你报不正确的值错误
2. 可以发现上边的流程图中有个“是否是Get”的判断,因为如果是Get请求,Content是不能赋值的,就像在HttpWebReqest中,如果get请求调用了GetRequestStream方法,会有“无法发送具有此谓词类型的内容正文”的异常错误。当然如果你使用的是OSS.Http作为请求,那么就没有这个问题了。
3. 和上传文件同时上传的表单参数,与单独的表单参数提交,是不一样的,请注意处理,不懂得参见OsRest类即可,已经做了处理。
如果你还有其他问题,或者对后续的更新感兴趣,请关注公众号(OSSCoder):
来源:http://www.cnblogs.com/sunhoy/p/6392305.html
![](https://www.aspxhome.com/images/zang.png)
![](https://www.aspxhome.com/images/jiucuo.png)
猜你喜欢
- 本文所述为基于C#实现的三层架构。对于三层的概念查相信大家并不陌生,这里举一个关于三层的简单实例,真正看一下它是如何具体实现的.我们先来一起
- Java中如何输出像1-2-3-4-5 这样的字符抱歉对于这个问题我甚至不能想到一个合适的标题,但是不重要 以下操作基于 jdk 1.8St
- 在上一篇文章:Flutter进阶—实现动画效果(二)的最后,我们实现了一个控件,其中包含各种布局和状态处理控件。以及使用自定义的动画感知绘图
- 步骤,如图所示:1.添加异步任务业务类package top.ytheng.demo.task;import java.util.concu
- 在jdk文档中对RandomAccess接口的定义如下: public interface RandomAccess下面是jdk
- 问题是这样的在开发时,为了节约时间,我选择了mybatis框架来开发,然后又在网上找了一个许多人都推荐的mybatis-plus来作为持久层
- JVM自带的类加载器:其关系如下:其中,类加载器在加载类的时候是使用了所谓的“父委托”机制。其中,除了根类加载器以外,其他的类加载器都有且只
- Object是所有类的父类,也就是说java中所有的类都是直接或者间接继承自Object类。比如你随便创建一个classA,虽然没有明说,但
- 本文实例讲述了C#使用webbrowser的常见用法。分享给大家供大家参考。具体如下:判断是否网络正常private bool IsConn
- 前言继上次skywalking出故障《解析Arthas协助排查线上skywalking不可用问题》不到一个月,线上skywalking又出毛
- 本文实例讲述了C#将布尔类型转换成字节数组的方法。分享给大家供大家参考。具体如下:byte[] b = null;b = BitConver
- 前言在我们日常的开发过程中通过打印详细的日志信息能够帮助我们很好地去发现开发过程中可能出现的Bug,特别是在开发Controller层的接口
- java 反射机制:测试实体类以Human为例/** * Project: Day12_for_lxy * Created: Lulu *
- 在实际开发中经常需要了解具体对象的类型,所以经常会使用GetType()和typeof()、尽管可以得到相应的类型、但两者之间也存在一些差别
- package com.huateng.readcsv;import java.io.BufferedReader;import java.
- 封装(Encapsulation)是面向对象编程的一个核心概念,它意味着将数据(属性)和方法(操作数据的函数)捆绑在一起,形成一个类(Cla
- 目录1、Java Application 源程序的主类是指包含有( )方法的类。2、如果定义一种表达式结构:(+ 6 3)的值为9,(- 6
- SpringCloud Zuul 是SpringCloud系列的网关实现,具有均衡负载,将非业务性校验剥离出来,使微服务专注于业务的一个组件
- 本文实例分析了java中transient关键字用法。分享给大家供大家参考。具体分析如下:java有个特点就是序列化,简单地来说就是可以将这
- 前言:由于项目需求,短信验证码的接口需要换成阿里大于的,但是尴尬的发现阿里大于的jar包没有maven版本的,于是便开始了一上午的 * 引包之