zoukankan      html  css  js  c++  java
  • MVC WebAPI 三层分布式框架开发

    前言:SOA(面向服务的架构)是目前企业应用开发过程中普遍采用的技术,基于MVC WebAPI三层分布式框架开发,以此适用于企业信息系统的业务处理,是本文论述的重点。此外,插件技术的应用,富客户端jQuery实现技术,本文也对其具体实现做以说明。相关示例解决方案可以参考GitHub资源,在文章结尾给出。

    1. 系统分层体系架构设计

    分布式三层系统简单分为数据访问层,业务逻辑层和前端展现层。分层架构设计是构建大型分布式系统的必要手段,因为可以使得系统健壮,可扩展。

    SOA即面向服务的架构,可以帮助企业构建灵活,扩展性强的复杂业务系统,按照服务的理念进行功能交付,调用方也不用去知道实现一方的具体细节;双方是按照统一消息格式,接口方式进行交互的。


    SOA的实现是基于以Web服务的方式发布Api接口,目前WebAPI是一种Restfule形式的Web服务,相比WCF的复杂性,WebAPI的开发效率更高,而且在配置时也不需要客户端和服务端的xml配置。


    企业核心业务数据可以让桌面、Web、平板、手机或物联设备访问,所以需要统一API接口,WebApi作为业务逻辑处理服务能够满足接口访问和接口之间交互的需求。

    2.基础类库模块
    2.1 数据访问:Dapper-微型ORMapping框架
    Dapper的优势:
    1,Dapper是一个轻型的ORM类。代码就一个SqlMapper.cs文件,编译后就40K的一个很小的Dll.
    2,Dapper很快。Dapper的速度接近与IDataReader,取列表的数据超过了DataTable。
    3,Dapper支持Mysql,SqlLite,Mssql,Oracle等一系列的数据库,当然如果你知道原理也可以让它支持Mongo db
    4,Dapper的r支持多表并联的对象。支持一对多 多对多的关系。并且没侵入性,想用就用,不想用就不用。无XML无属性。代码以前怎么写现在还怎么写。
    5,Dapper原理通过Emit反射IDataReader的序列队列,来快速的得到和产生对象。性能实在高。
    6,Dapper 是C#实现,支持.net framework 各种版本;

    7,Dapper语法十分简单。并且无须迁就数据库的设计。

    国外大型网站采用的有:
    –StackOverflow, StackExcahnge等。。。

    读取500条记录,并做简单对象的序列化操作时间对比如下图:

    2.2 DataRepository类

    •实现数据实体操作封装
    -Insert—插入
    -Update—更新
    -Delete—删除
    -Select—选取
    -Paged—分页
    2.3  ServiceBase类
    •实现业务实体对象的操作封装
    –Insert—插入
    –Update—更新
    –Delete—删除
    –Select—选取
    –Paged—分页
    2.4 服务实现类
    -实现Iservice接口
    -继承ServiceBase基类
     
    2.5 WebAPI服务发布

    API Controller

        --[HttpGet]

        --[HttpPost]

        --[HttpPut]

        --[HttpDelete]

    2.6 动态加载插件
    -系统的扩展性
    -系统的变化性
    -客户二次开发
    -MEF
    –运行时加载
     
    2.7 AutoMapper—实体对象之间转换
    •两个实体类
    –EPProduct – 数据实体
    –Product– 业务实体
    •转化示例代码
    –EPProduct p =ProductRepository.Get(long.Parse(id));
    –AutoMapper.Mapper.CreateMap<EPProduct, Product>();
    –Productentity =AutoMapper.Mapper.Map<EPProduct, Product>(p)
     
    2.8 面向接口编程--Ioc框架
    •SimpleInjector
    –静态类型
    –编译阶段
    •MEF
    –动态类型
    –运行时阶段
     
    3.富客户端开发
    3.1 Asp.NETMVC 富客户端开发
    •Model
    –WebAPI (服务接口)
    •Controller
    –路由
    •View
    –页面
    •富客户端
    –Ajax 局部刷新
    – 鼠标、键盘响应事件等
    –如Gmail邮箱等应用示例
    3.2 Jquery插件
    •Layout—Jquery Layout
    •DataGrid – SlickGrid –性能非常高
    •Tree– Jstree/Ztree –评价都不错
    •Tab– Jquery Tools
    •Toolbar– Jquery Tools
    •Dialog– Jquery Tools
    •Form–Jquery Tools
    3.3 前端页面Ajax调用:
    GET/POST/PUT/DELETE
    [javascript] view plain copy
    1. /*** 
    2.     * HttpGet获取服务端数据 
    3.     * @url 业务数据 
    4.     * @data 
    5.     */  
    6.    $.doHttpClientGet = function(url, fn) {  
    7.        $.getJSON(url, fn);  
    8.    }  
    9.   
    10.   
    11.    /*** 
    12.     * HttpPut更新数据到服务端 
    13.     * @url 业务数据 
    14.     * @data 
    15.     */  
    16.    $.doHttpClientUpdate = function(url, data, fn) {  
    17.        $.ajax({  
    18.            url: url,  
    19.            type: 'PUT',  
    20.            data: data,  
    21.            dataType: 'json',  
    22.            contentType: 'application/json',  
    23.            success: fn  
    24.        });  
    25.    }  
    26.   
    27.   
    28.    /*** 
    29.     * HttpDelete删除数据 
    30.     * @url 业务数据 
    31.     * @data 
    32.     */  
    33.    $.doHttpClientDelete = function(url, data, fn) {  
    34.        $.ajax({  
    35.            url: url,  
    36.            type: 'DELETE',  
    37.            data: data,  
    38.            dataType: 'json',  
    39.            contentType: 'application/json',  
    40.            success: fn  
    41.        });  
    42.    }  
    43.   
    44.   
    45.    /*** 
    46.     * HttpPost保存数据 
    47.     * @url 业务数据 
    48.     * @data 
    49.     */  
    50.    $.doHttpClientSave = function(url, data, fn) {  
    51.        $.ajax({  
    52.            url: url,  
    53.            type: 'POST',  
    54.            data: data,  
    55.            dataType: 'json',  
    56.            contentType: 'application/json',  
    57.            success: fn  
    58.        });  
    59.    }  
    60.   
    61.   
    62.    /*** 
    63.     * ajax获取服务端数据 
    64.     * @url 业务数据 
    65.     * @data 
    66.     */  
    67.    $.doAjaxGet = function(url, fn) {  
    68.        //$.getJSON(url, fn);  
    69.        $.ajax({  
    70.            url: url,  
    71.            type: "GET",  
    72.            dataType: 'json',  
    73.            //data: data,  
    74.            contentType: 'application/json',  
    75.            success: fn  
    76.        });  
    77.    }  
    78.   
    79.   
    80.    $.doAjaxPost = function(url, data, fn) {  
    81.        $.ajax({  
    82.            url: url,  
    83.            type: 'POST',  
    84.            data: data,  
    85.            dataType: 'json',  
    86.            contentType: 'application/json',  
    87.            success: fn  
    88.        });  
    89.    }  
    90.   
    91.   
    92.    //构造html的通用方法  
    93.    $.buildHTML = function(tag, html, attrs) {  
    94.        // you can skip html param  
    95.        if (typeof (html) != 'string') {  
    96.            attrs = html;  
    97.            html = null;  
    98.        }  
    99.        var h = '<' + tag;  
    100.        for (attr in attrs) {  
    101.            if (attrs[attr] === false) continue;  
    102.            h += ' ' + attr + '="' + attrs[attr] + '"';  
    103.        }  
    104.        return h += html ? ">" + html + "</" + tag + ">" : "/>";  
    105.    }  
    106.   
    107.   
    108.    //构造JsTree的通用方法  
    109.    $.fn.buildJsTree = function (url, fn) {  
    110.        var object = require(['jstree'], function(){  
    111.            $.jstree._themes = "/PlatJS/Scripts/jstree/themes/";  
    112.            var myTree = $(this).jstree({  
    113.                "json_data": {  
    114.                    "ajax": {  
    115.                        "url": url,  
    116.                        "type": "GET",  
    117.                        "dataType": "json",  
    118.                        "contentType": "application/json charset=utf-8",  
    119.                        "success": fn  
    120.                    }  
    121.                },  
    122.                "plugins": ["themes", "json_data", "ui"]  
    123.            });  
    124.        })  
    125.    }  

    3.4 如何调试?
    •Fiddler--*****5star

    FireBug for Firefox

    •查看HTML,CSS,Javascript等
    •监控下载图片资源时间线
    •完善友好的调试
     

    Firefox的RestClient插件—Rest Client测试插件

    http://localhost:8081/ProductSys.WebAPI/api/order/insertwith?type="insertwith

     [HttpPost]

    public HttpResponseMessageInsertWith(Order entity, string type)

     

    http://localhost:8081/ProductSys.WebAPI/api/order/4

     [HttpDelete]

     public HttpResponseMessage Delete(string id)

    3.5 Web异常错误代码

    •100-199– Informational
    •200-299– Client request successful
    •300-399– Client request redirected, further action necessary
    •400-499– Client request incomplete
    •500-599– Server error
     
    4. Javascript 类语法
    4.1 常见问题
    •Namespace(命名空间)
    –默认为全局范围,有潜在类型冲突隐患
    •SelfExecuting Fuction (自执行匿名函数)
    •Objectand Array (对象和数组初始化)
    –不要使用new 关键字
    •NullOr Empty (检查NULL)

    4.2 Javascript-自执行匿名函数
    [javascript] view plain copy
    1. //Self-Executing Anonymous Func: Part 2 (Public & Private)  
    2. (function( skillet, $, undefined ) {  
    3.     //Private Property  
    4.     var isHot = true;  
    5.    
    6.     //Public Property  
    7.     skillet.ingredient = "Bacon Strips";  
    8.        
    9.     //Public Method  
    10.     skillet.fry = function() {  
    11.         var oliveOil;  
    12.            
    13.         addItem( "  Butter  " );  
    14.         addItem( oliveOil );  
    15.         console.log( "Frying " + skillet.ingredient );  
    16.     };  
    17.        
    18.     //Private Method  
    19.     function addItem( item ) {  
    20.         if ( item !== undefined ) {  
    21.             console.log( "Adding " + $.trim(item) );  
    22.         }  
    23.     }      
    24. }( window.skillet = window.skillet || {}, jQuery ));  
    25.  <pre name="code" class="javascript">//Public Properties  
    26. console.log( skillet.ingredient ); //Bacon Strips  
    27.    
    28. //Public Methods  
    29. skillet.fry(); //Adding Butter & Fraying Bacon Strips  
    30.    
    31. //Adding a Public Property  
    32. skillet.quantity = "12";  
    33. console.log( skillet.quantity ); //12  
    34.    
    35. //Adding New Functionality to the Skillet  
    36. (function( skillet, $, undefined ) {  
    37.     //Private Property  
    38.     var amountOfGrease = "1 Cup";  
    39.        
    40.     //Public Method  
    41.     skillet.toString = function() {  
    42.         console.log( skillet.quantity + " " +   
    43.                      skillet.ingredient + " & " +   
    44.                      amountOfGrease + " of Grease" );  
    45.         console.log( isHot ? "Hot" : "Cold" );  
    46.     };      
    47. }( window.skillet = window.skillet || {}, jQuery ));  
    48.    
    49. try {  
    50.     //12 Bacon Strips & 1 Cup of Grease  
    51.     skillet.toString(); //Throws Exception  
    52. catch( e ) {  
    53.     console.log( e.message ); //isHot is not defined  
    54. }  
    [javascript] view plain copy
    1. </pre>  
     
    4.3 对象和数组初始化
    [javascript] view plain copy
    1. //建议申明对象或数组的写法  
    2. var person = {},   
    3.     keys = [];  
    4.   
    5. //申明复杂对象或数组的写法  
    6. var person = {  
    7.         firstName: "Elijah",  
    8.         lastName: "Manor",  
    9.         sayFullName: function() {  
    10.             console.log( this.firstName + " " +   
    11.                 this.lastName );  
    12.         }  
    13.     },   
    14.     keys = ["123", "676", "242", "4e3"];  

    4.4 判断对象是否为NULL(c#)
    [csharp] view plain copy
    1. // <span >C# 例子. 不要在Javascript中这样写</span>  
    2. if ( someString != null &&  
    3.     someString.length > 0 ) {  
    4.     //Do something here...  
    5. }  
    6.   
    7. // C# 例子 检查字符串是否为空  
    8. if ( !string.IsNullOrEmpty(someString) ) {  
    9.     //Do something here...  
    10. }  

    4.5 判断对象是否为NULL(javascript)
    [javascript] view plain copy
    1. Javascript中的正确写法  
    2. // Simplified JavaScript syntax to check for  
    3. // undefined, null, & empty string values  
    4. if ( someString ) {  
    5.     //Do something here...  
    6. }  

    4.6 设置缺省值(c#)
     
    [csharp] view plain copy
    1. <span style="color: rgb(255, 0, 0);">// C# 例子,不要在Javascript这样写</span>  
    2. if ( someString == null ) {  
    3.    someString = "default Value";  
    4. }  
    5. // Slightly better, but don't do this either  
    6. someString = someString ? someString : "default value"; <pre name="code" class="javascript">请在Javascript按如下格式写  
    7. // JavaScript syntax to set a default value  
    8. someString = someString || "default value";  
     
     
    4.7 不同类型的比较操作符(==, !=)
    •// Unexpected Comparisons using the== Operator
    •0         ==  ''        //true
    •0         ==  '0'       //true
    •false     ==  '0'       //true
    •null      ==  undefined //true
    •' ' ==  0         //true
     
    4.8 不同类型的比较操作符(===, !==)
    •// Expected Comparisons using the ===Operator
    •0         === ''        //false
    •0         === '0'       //false
    •false     === '0'       //false
    •null      === undefined //false
    •' ' === 0         //false
     
    4.9 不可取的数组遍历操作符for…in
    [csharp] view plain copy
    1. var myArray = [], name;  
    2. myArray[5] = "test";  
    3. console.log( myArray.length ); //6  
    4.    
    5. for ( name in myArray ) {  
    6.     console.log( name, myArray[name] );  
    7.     //Outputs...  
    8.     //   5, test  
    9. }  

    4.10 正确的数组遍历操作符for…;…;
    [javascript] view plain copy
    1. var myArray = [], name;  
    2. myArray[5] = "test";  
    3. console.log( myArray.length ); //6  
    4.    
    5. for ( var i = 0, length = myArray.length; i < length; i++ ) {  
    6.     console.log( i, myArray[i] );  
    7.     //Outputs...  
    8.     //   0, undefined  
    9.     //   1, undefined  
    10.     //   2, undefined  
    11.     //   3, undefined  
    12.     //   4, undefined  
    13.     //   5, test  
    14. }  
    [javascript] view plain copy
    1. for ( var name in object ) {  
    2.     //Your code here  
    3. }  
    4.   
    5. /* Check if object has property before 
    6. iterating, because functions inherited 
    7. from prototype are also included */  
    8. for ( var name in object ) {  
    9.    if ( object.hasOwnProperty(name) ) {  
    10.       //Your code here  
    11.    }  
    12. }  
     
    5. RequireJS 模块化脚本
    RequireJS 是一个非常小巧的 JavaScript 模块载入框架,是 AMD 规范最好的实现者之一。最新版本的 RequireJS 压缩后只有 14K,堪称非常轻量。它还同时可以和其他的框架协同工作,使用 RequireJS 必将使的前端代码质量得以提升。
     
    RequireJS 作为 JavaScript 文件的加载器,还是可以完成异步非阻塞的文件加载。
    [javascript] view plain copy
    1. define(['Controllers/Main/ListView'], function (ListView) {  
    2.     function start() {  
    3.         var users = JSON.parse(localStorage.users);  
    4.         ListView.render({ users: users });  
    5.     }  
    6.   
    7.     return {  
    8.         start: start  
    9.     };  
    10. });  
     
    6. 网络资源
    6.1 NuGet—快捷获取软件包
    •充分利用开源软件包,避免重复制造轮子;
    •也可以自己发布软件包,回馈社区,先进技术的积累可以节约项目成本。
    6.2 技术资源
     
    •Asp.net MVC WebAPI
    –RestfulWeb Service的发展
    •Jquery
    –官网
    –插件开发
    •RequrieJS
    –Javascript模块化开发框架
    •Dapper
    –微型ORMapping 框架
    •EntityFramework
    –Microsoft实体框架
     
    7. 总结:
    本文基于MVC WebAPI实现分布式三层架构,实现了通用数据访问操作,业务实体和数据实体的交互操作,业务模块之间的接口交互;实现了插件化的加载技术。此外限于篇幅,对于流程化的设计,会在下文论述,主要会谈及到工作流Api和WebApi的交互。
     
     
    代码示例说明:

    提供的示例RequireMVC199中,可以看一下ProductSys.WebApi的服务层代码,前端代码看RequireMvc199的WebApplication项目即可。

     

    完整示例,可以看一下ProductList页面的代码,这个示例是完整的,包括文件:

    WebApplication 包括:

    Controllers

        --ProductController.cs

    ViewJS

      Controllers

        Product

           --product-list.js

          --product-detail.js

     

    Views

      Product

        --productlist.cshtml

     

    WebApi 包括:

    ProductSys.WebApi

      Controllers

        --ProductController.cs

     

    ProductSys.ServiceImp

      Service

        --ProductService.cs

     
    解决方案下载地址:
    https://github.com/besley/Plat2012
     
    新版本下载:
    http://github.com/besley/slickone
     
    后记:
    不断有朋友问到,是否有新版本?是否支持ORACLE?目前在最新的版本里已经解决这些问题。你可以在Slickflow的项目里面看到,即仍然是Mvc, WebApi和Dapper的架构,但是简化甚多,真是物至简方可尽其用,希望大家一起学习讨论。谢谢大家关注。
  • 相关阅读:
    chrome浏览器中安装以及使用Elasticsearch head 插件
    windows10 升级并安装配置 jmeter5.3
    linux下部署Elasticsearch6.8.1版本的集群
    【Rollo的Python之路】Python 爬虫系统学习 (八) logging模块的使用
    【Rollo的Python之路】Python 爬虫系统学习 (七) Scrapy初识
    【Rollo的Python之路】Python 爬虫系统学习 (六) Selenium 模拟登录
    【Rollo的Python之路】Python 爬虫系统学习 (五) Selenium
    【Rollo的Python之路】Python 爬虫系统学习 (四) XPath学习
    【Rollo的Python之路】Python 爬虫系统学习 (三)
    【Rollo的Python之路】Python sys argv[] 函数用法笔记
  • 原文地址:https://www.cnblogs.com/webenh/p/6094455.html
Copyright © 2011-2022 走看看