.NET Core开源组件FastHttpApi:Web应用开发

2018 年 9 月 26 日 DotNet

(点击上方蓝字,可快速关注我们)


来源:smark

cnblogs.com/smark/p/9698566.html


《.NET Core高吞吐Http API服务组件FastHttpApi》


FastHttpApi相对于ASP.NET MVC来说有着更轻量和性能上的优势,性能上面就不在这里介绍了(具体可查看 https://github.com/IKende/FastHttpApi)。


在这里主要讲解一下如何使用FastHttpApi进行网站或WebApi开发,在使用FastHttpApi之前必须了解它具备那些功能,它除了提供webapi服务的编写外还提供了静态资源的支持,简单来说FastHttpApi除了能实现基于HTTP的服务交互外还能实现应用网站;


虽然不提供视MVC那样的视图处理功能,但可以通过现有比较成熟的前后端分离技术来实现应用网站的编写。


以下是简单地描述一下FastHttpApi的功能:


  1. 支持以函数的方式来制定HTTP请求逻辑


  2. 支持使用者处理异步响应


  3. 支持Filter功能,以便更好地控制请求方法的处理


  4. 支持自定义Http Body解释器,方便制定基于json,xml,protobuf,msgpack等数据格式的传输


  5. 支持QueryString参数和Cookies


  6. 支持外置或内嵌到DLL的静态资源输出(默认对html,js,css资源进行GZIP处理)


  7. 支持SSL


(在后续版升级主要功能:同一服务端口的控制器逻辑会同时兼容http和websocket两种协议请求)


通过以上功能完全可以用来构建高效全安的应用网站。


以下通过一些例子详细讲述如何使用FastHttpApi。


定义HTTP请求的方法


在FastHttpApi定义HTTP请求的方法和asp.net webapi差不多,都是通过定义一个控制器然后定义相关请求方法即可,当然使用起来会简单一些。


以下以Northwind的数据作为基础制定了一个简单的数据访问控制器


[FastHttpApi.Controller]

public class Controller

{

    public Controller()

    {

        mEmployees = Newtonsoft.Json.JsonConvert.DeserializeObject<List<Employee>>(Datas.Employees);

        mCustomers = Newtonsoft.Json.JsonConvert.DeserializeObject<List<Customer>>(Datas.Customers);

        mOrders = Newtonsoft.Json.JsonConvert.DeserializeObject<List<Order>>(Datas.Orders);

    }

    private List<Employee> mEmployees;

    private List<Customer> mCustomers;

    private List<Order> mOrders;

    public Employee GetEmployee(int id)

    {

        Employee result = mEmployees.Find(e => e.EmployeeID == id);

        if (result == null)

            result = new Employee();

        return result;

    }

    public bool EditEmployee(int id, [BodyParameter]Employee emp, FastHttpApi.HttpResponse response)

    {

        Employee record = mEmployees.Find(e => e.EmployeeID == id);

        if (record != null)

        {

            record.City = emp.City;

            record.Address = emp.Address;

            record.Title = emp.Title;

            record.HomePhone = emp.HomePhone;

            return true;

        }

        return false;

    }

    public object ListEmployees()

    {

        return mEmployees;

    }

    public object GetEmployeesName()

    {

        return from e in mEmployees select new { ID = e.EmployeeID, Name = e.FirstName + " " + e.LastName };

    }

    public object GetCustomersName()

    {

        return from c in mCustomers select new { ID = c.CustomerID, Name = c.CompanyName };

    }

    public object ListOrders(int employeeid, string customerid)

    {

        return mOrders.Where(o =>

        (employeeid == 0 || o.EmployeeID == employeeid)

        &&

        (string.IsNullOrEmpty(customerid) || o.CustomerID == customerid));

    }

}


相对于asp.net webapi来说,组件中会把所有控制器Public方法注册为URL,方法是不区分GET或POST,如果有需要可以通过HttpRequest中获取;参数根据自己需要来定义,参数有两种来源一种是通过QueryString获取而另一种则通过HttpBody获取;对于HttpResponse和HttpRequest则看情况需要,如果有需要直接在方法中定义相关类型参数即可获取。


当控制器编写完成后,需要给类写上[Controller]标签告诉组件这是一个api控制器接收HTTP请求。


异步应答处理


对于HTTP来说,一个请求就必须要应答,因为这是HTTP协议规范;在实际业务中往往方法处理完成就进行应答,但有些情况下需要异步应答;当一个业务需要处理大量IO的业务时那就会把线程处于等待状态,为了更好地处理这种情况组件提供了异步应答处理;通过异步应答可以在大量IO处理异步回调后再进行应答处理。


public void asyncHello(string name, HttpResponse response)

{

    response.Async();

    Task.Run(() =>

    {

        Console.WriteLine("sleep ...");

        System.Threading.Thread.Sleep(5000);

        response.Result(string.Format("[{0}] hello {1}", DateTime.Now, name));

    });

}


通过HttpResponse.Async方法告诉组件是异步应答,组件在这个方法执行完成后不会进行HTTP响应。


实际响应是使用者需要显式地调用HttpResponse.Result方法来进行应答。


filter的应用


相信写过asp.net mvc的朋友对filter并不陌生,它的主要工作就是对请求方法进行拦截控制。FastHttpApi支持使用都定义任意功能的Filter,用来记录日志、控制权限等等。


编写好的控制器可以标记在Controller上,生效于所有相关主求方法;也可以针对个别方法标记上。组件除了提供Filter外还提供了SkipFilter,它的主要作用是移走某些不需要的Filter拦截器。


public class GlobalFilter : FilterAttribute

{

    public override void Execute(ActionContext context)

    {

        Console.WriteLine(DateTime.Now + " globalFilter execting...");

        context.Execute();

        Console.WriteLine(DateTime.Now + " globalFilter executed");

    }

}


以上是标记一个全局的Filter,用于记录方法执行前和执行后的时候,context.Execute()是告诉组件往下执行;如果判断权限,则在这里可以依据HttpRequest的信息情况来决定是否执行context.Execute(),这样就起到了权限控制的作用。当希望某个方法不经过这个Filter的情况下可以这样做:


[SkipFilter(typeof(GlobalFilter))]

[CustomFilter]

public string Hello(string name)

{

    return DateTime.Now + " hello " + name;

}


HTTP消息体解释器


组件通过IBodySerializer接口来规范HTTP消息体的解释和一些错误状态返回的数据


public interface IBodySerializer

{

    int Serialize(PipeStream stream, object data);

    bool TryDeserialize(PipeStream stream, int length, Type type, out object data);

    object GetNotFoundData(HttpResponse response);

    object GetInnerError(Exception e, HttpResponse response, bool outputStackTrace);

    object GetNotSupport(HttpResponse response);

    string ContentType { get; set; }

}


接口提供的功能比较少,主要包括消息的序列化、反序列化和一些HTTP状态的处理,随便着功能的完善后期这接口可能会添加更多的方法。


以下是针对Json实现的一个解释器,毕竟在WEB通讯中json是最常用的(如果是网内服务交互为了提高效率可以实现protobuf,msgpack等二进制序列化)。


public virtual int Serialize(PipeStream stream, object data)

{

    int length = stream.CacheLength;

    string value = Newtonsoft.Json.JsonConvert.SerializeObject(data);

    stream.Write(value);

    return stream.CacheLength - length;

}


public virtual bool TryDeserialize(PipeStream stream, int length, Type type, out object data)

{

    data = null;

    if (stream.Length >= length)

    {

        string value = stream.ReadString(length);

        if (type != null)

        {

            data = Newtonsoft.Json.JsonConvert.DeserializeObject(value,type);

        }

        else

        {

            data = Newtonsoft.Json.JsonConvert.DeserializeObject(value);

        }

        return true;

    }

    return false;

}


可能通过以下方式'mApiServer.ServerConfig.BodySerializer = new JsonBodySerializer();'来设置相应HTTP服务的消息转换器。


Cookies处理


FastHttpApi和asp.net mvc处理的方式差不多,通过HttpResponse进行Cookie的写入,由HttpRequest来获取Cookie值。


public bool setCookie(string name, string value, HttpResponse response)

{

    response.SetCookie(name, value);

    return true;

}

public void getCookie(string name, HttpRequest request, HttpResponse response)

{

    string value = request.Cookies[name];

    response.Result(value);

}


网页资源处理


组件处理的网页资源需要存放在当前项目的views目录下,views目录可以说是网页资源的根目录。


网页资源有两种打包方式,一种是编译复制到发布目录下,而另一种则是嵌入到编译资源中;建议选择嵌入资源的发布方式,这样最终发布的时候就只需要复制一个DLL即可,不过这种方式发布需要修改网页资源都需要重新发布。


对于编译复制发布的好处是可以直接修改,组件会检则修改情况重新刷新资源缓存。



组件处理网页资源有两种方式,对于image的资源组件是在头上标识为客户端缓存,在没过期的情况客户端不会二次请求图片资源。那对于HTML,CSS,JS这些文件组件会加个缓存标签,当文件发生变化会重新响应给客户端,否则响应304给客户端。


开发阶段调试简化


由于网页资源需要编译才会被重新复制或嵌入的到程序中,这样每修改一次都要编译查看结果那是很麻烦的事情,也浪费大量工作时间。


所以在启动服务的时候执行一下HttpApiServer.Debug方法,通过这个方法可以把网页资源目录指向项目中网页资源的目录,这样修改网页也不需要重新编译即可查看。 


HttpApiServer.Debug只有在Debug模式下才能生效。 (提示FastHttpApi的url不区分大小写)


以下是NorthWind数据订单查询的页面代码


<script>

    $(document).ready(function () {

        $.get("/GetEmployeesName", function (items) {

            items.forEach(function (v, i) {

                $('#lstEmployees').append(' <option value="' + v.ID + '">' + v.Name + '</option>')

            });

        });

        $.get("/GetCustomersName", function (items) {

            items.forEach(function (v, i) {

                $('#lstCustomers').append(' <option value="' + v.ID + '">' + v.Name + '</option>')

            });

        });

        search();

    });

    function search() {

        $.get('/listorders?employeeid=' + $('#lstEmployees').val() + "&customerid=" + $('#lstCustomers').val(), function (items) {

            $("#lstbody").empty();

            items.forEach(function (v, i) {

                $("#lstbody").append('<tr><td>' + i + '</td><td>' + v.OrderID + '</td><td>' + v.ShipName + '</td><td>' + v.ShipAddress + '</td><td>' + v.ShipCity + '</td><td>' + v.OrderDate + '</td></tr>')

            });

        });

    }

</script>



运行服务


FastHttpApi启动Http服务非常简单,并不需要做太多的配置即可运行


private static HttpApiServer mApiServer;

static void Main(string[] args)

{

    mApiServer = new HttpApiServer();

    mApiServer.ServerConfig.BodySerializer = new JsonBodySerializer();

    mApiServer.Register(typeof(Program).Assembly);

    //config.SSL = true;

    //mApiServer.ServerConfig.CertificateFile = @"c:\ssltest.pfx";

    //mApiServer.ServerConfig.CertificatePassword = "123456";

    mApiServer.Debug();

    mApiServer.Open();

    Console.Write(mApiServer.BaseServer);

    Console.Read();

}


如果希望修改一些基础配置信息,如服务IP和端等可以通过HttpApiServer.ServerConfig来修改;


也可以通过HttpConfig.json来配置相应信息.


具体代码查看:https://github.com/IKende/FastHttpApi/tree/master/samples


看完本文有收获?请转发分享给更多人

关注「DotNet」,提升.Net技能 

登录查看更多
0

相关内容

模型优化基础,Sayak Paul,67页ppt
专知会员服务
75+阅读 · 2020年6月8日
【实用书】Python爬虫Web抓取数据,第二版,306页pdf
专知会员服务
117+阅读 · 2020年5月10日
【干货书】流畅Python,766页pdf,中英文版
专知会员服务
224+阅读 · 2020年3月22日
【新书】Java企业微服务,Enterprise Java Microservices,272页pdf
TensorFlow Lite指南实战《TensorFlow Lite A primer》,附48页PPT
专知会员服务
69+阅读 · 2020年1月17日
【大规模数据系统,552页ppt】Large-scale Data Systems
专知会员服务
60+阅读 · 2019年12月21日
【干货】大数据入门指南:Hadoop、Hive、Spark、 Storm等
专知会员服务
95+阅读 · 2019年12月4日
【电子书】C++ Primer Plus 第6版,附PDF
专知会员服务
87+阅读 · 2019年11月25日
用Now轻松部署无服务器Node应用程序
前端之巅
16+阅读 · 2019年6月19日
专访阿里亚顿:Serverless与BFF与前端
前端之巅
45+阅读 · 2019年5月8日
从webview到flutter:详解iOS中的Web开发
前端之巅
5+阅读 · 2019年3月24日
React Native 分包哪家强?看这文就够了!
程序人生
13+阅读 · 2019年1月16日
干货 | Python 爬虫的工具列表大全
机器学习算法与Python学习
10+阅读 · 2018年4月13日
开源巨献:阿里巴巴最热门29款开源项目
算法与数据结构
5+阅读 · 2017年7月14日
Reasoning on Knowledge Graphs with Debate Dynamics
Arxiv
14+阅读 · 2020年1月2日
Arxiv
35+阅读 · 2019年11月7日
Arxiv
4+阅读 · 2019年2月8日
Hierarchical Deep Multiagent Reinforcement Learning
Arxiv
8+阅读 · 2018年9月25日
Arxiv
3+阅读 · 2012年11月20日
VIP会员
相关VIP内容
模型优化基础,Sayak Paul,67页ppt
专知会员服务
75+阅读 · 2020年6月8日
【实用书】Python爬虫Web抓取数据,第二版,306页pdf
专知会员服务
117+阅读 · 2020年5月10日
【干货书】流畅Python,766页pdf,中英文版
专知会员服务
224+阅读 · 2020年3月22日
【新书】Java企业微服务,Enterprise Java Microservices,272页pdf
TensorFlow Lite指南实战《TensorFlow Lite A primer》,附48页PPT
专知会员服务
69+阅读 · 2020年1月17日
【大规模数据系统,552页ppt】Large-scale Data Systems
专知会员服务
60+阅读 · 2019年12月21日
【干货】大数据入门指南:Hadoop、Hive、Spark、 Storm等
专知会员服务
95+阅读 · 2019年12月4日
【电子书】C++ Primer Plus 第6版,附PDF
专知会员服务
87+阅读 · 2019年11月25日
相关资讯
用Now轻松部署无服务器Node应用程序
前端之巅
16+阅读 · 2019年6月19日
专访阿里亚顿:Serverless与BFF与前端
前端之巅
45+阅读 · 2019年5月8日
从webview到flutter:详解iOS中的Web开发
前端之巅
5+阅读 · 2019年3月24日
React Native 分包哪家强?看这文就够了!
程序人生
13+阅读 · 2019年1月16日
干货 | Python 爬虫的工具列表大全
机器学习算法与Python学习
10+阅读 · 2018年4月13日
开源巨献:阿里巴巴最热门29款开源项目
算法与数据结构
5+阅读 · 2017年7月14日
Top
微信扫码咨询专知VIP会员