经过前面3天的学习,我想大家应该对SOA的架构有了初步的了解,其实 SOA与三层架构并不冲突,而是三层架构的升级版。
来看下传统的三层架构! 一共可以分为4个层: 模型层(可有可无),客户端,服务端,公共层。
我们在原有的三层架构的基础上,我们增加一个服务中转层! 然后客户端 通过 调用 服务中转,然后在调用 服务层,因为客户端可以有多个,可以是安卓,可以是IOS,
可以是电脑,可以是linux, 因为这个不管是什么样的语言和系统,她们都支持JSON以及xml。
如下图:(common:公共层,DataServer服务层,wcf服务中转层,webClient web 客户端)
接下我们来看下关键代码处: (下面有对应的源代码下载)
来看下如何通过 通用查询 来查询数据的流程:
首先 前台通过 ajax 的访问我们的 svc 文件,来进行访问:
1.这里需要注意的是, ajax 使用 get 和post 时,传入json的格式是不一样的。
var s = '{ "aa":"' + $("#txt_data").val() + '"}';
$.postwcf = function (database, method, //操作的方法名字 sql, //sql语句或者传入的 数据 success, //执行成功所返回的方法 err) { //执行失败所返回的方法 var url = $.getrooturl() + "/WebService.svc/operate"; var data; if (sql.indexOf("{")>0 && sql.indexOf('"')>0 && sql.indexOf("}")>0) { data = { "database": database, "method": method, "sql": JSON.stringify(sql), }; } else { data = { "database": database, "method": method, "sql":sql, }; } $.ajax({ url: url, contentType: "application/json;charset=utf-8", data: JSON.stringify(data), type: "post", success: function (data) { success(data); }, error: function (error) { err(error); } }); }
上面这个 post的方法, json 格式需要 ' {"aa":"123"} '
西面这个是get的方法,json格式为 {"aa":"123"}
很显然,一个传入json格式是需要引号才能辨认,一个这不需要引号进行辨认。
$.getwcf = function (database, method, //操作的方法名字 sql, //sql语句或者传入的 数据 success, //执行成功所返回的方法 err) { //执行失败所返回的方法 var url = $.getrooturl() + "/WebService.svc/operateByGet"; var data; if (sql.indexOf("{") > 0 && sql.indexOf('"') > 0 && sql.indexOf("}") > 0) { data = { "database": database, "method": method, "sql": JSON.stringify(sql), }; } else { data = { "database": database, "method": method, "sql": sql, }; } $.ajax({ url: url, contentType: "application/json;charset=utf-8", data:data, type: "get", success: function (data) { success(data); }, error: function (error) { err(error); } }); }
2.另外我们的后台,对应的 契约,也就是接口需要注意的就是:
我们可以看到,我们可以看到我们写了2个接口,一个是需要用 POST
调用的,一个是需要用get 调用的,其实2个所执行的方法都是一样的。WebInvoke对应的是post,WebGet对应的是get的调用。
[ServiceContract] interface ISqlServer { /// <summary> /// 这里指所执行的操作(其中保证 sql 语句) /// </summary> /// <param name="database">数据库的名字</param> /// <param name="operate">所执行的操作,select ,insert,delete</param> /// <param name="method">方法名</param> /// <param name="sql">sql语句</param> /// <returns>返回数据类型为json格式</returns> [OperationContract] [WebInvoke(ResponseFormat = WebMessageFormat.Json, BodyStyle = WebMessageBodyStyle.WrappedRequest)] string operate(string database, string method, string sql); [WebGet(ResponseFormat = WebMessageFormat.Json, BodyStyle = WebMessageBodyStyle.WrappedRequest)] string operateByGet(string database, string method, string sql); }
3.实现原有类的方法扩展,例如 在datatable的基础上 增加一个 .toJson的方法:如何来写呢?
public static class Extend { /// <summary> /// 这是将 datatable转化为json的方法 /// </summary> /// <param name="pData"></param> /// <returns></returns> public static string ToJson(this DataTable pData) { //这里就可以来写你的代码了 }
注意 必须 是静态类中的静态方法,参数中 带有 this 关键字
4.实现一种反射能够 通过 指定 命名空间,类名,方法名, 参数,就能够执行对应的 方法(静态 与非静态都能执行)
/// <summary> /// 根据字符执行该方法 /// </summary> /// <param name="path">命名空间</param> /// <param name="className">类名</param> /// <param name="MethodName">方法名</param> /// <param name="dic">传入的参数</param> /// <returns>返回object类型</returns> public static object Execute(string path, string className, string MethodName, Dictionary<string,object> dic) { object[] parameters=new object[1]; parameters[0] = dic; //动态从程序集中查找所需要的类并使用系统激活器创建实例最后获取它的Type Type type = Assembly.Load(path).CreateInstance(path + "." + className).GetType(); //定义参数的个数,顺序以及类型的存储空间; Type[] parametersLength; if (parameters != null) //表示方法的参数不为空才执行 { parametersLength = new Type[parameters.Length]; int i = 0; foreach (object obj in parameters) { parametersLength.SetValue(obj.GetType(), i); i++; } } else { //没有参数就为空 parametersLength = new Type[0]; } //然后我们来查找制定的方法 MethodInfo methodinfo = type.GetMethod(MethodName, parametersLength); if (methodinfo.IsStatic) { return methodinfo.Invoke(null, parameters); } else { object obj = Activator.CreateInstance(type); //表示不属于静态方法的调用 return methodinfo.Invoke(obj, parameters); } }
注意 看到 执行方法 时 要 分 静态 与非静态,静态时 不用实例化对象,否则就得 实例化对象。
5.另外我还附上, json 与字典方法的相互转换:
/// <summary> /// 这是将 json 转成 dictionary 的方法 /// </summary> /// <param name="JsonData"></param> /// <returns></returns> public static Dictionary<string, object> ToDictionary(this string JsonData) { object Data = null; Dictionary<string, object> Dic = new Dictionary<string, object>(); if (JsonData.StartsWith("[")) { //如果目标直接就为数组类型,则将会直接输出一个Key为List的List<Dictionary<string, object>>集合 21. //使用示例 List<Dictionary<string, object>> ListDic = (List<Dictionary<string, object>>)Dic["List"]; List<Dictionary<string, object>> List = new List<Dictionary<string, object>>(); MatchCollection ListMatch = Regex.Matches(JsonData, @"{[sS]+?}");//使用正则表达式匹配出JSON数组 24. foreach (Match ListItem in ListMatch) { List.Add(ToDictionary(ListItem.ToString()));//递归调用 } Data = List; Dic.Add("List", Data); } else { MatchCollection Match = Regex.Matches(JsonData, @"""(.+?)"": {0,1}([[sS]+?]|null|"".+?""|-{0,1}d*)");//使用正则表达式匹配出JSON数据中的键与值 foreach (Match item in Match) { if (item.Groups[2].ToString().StartsWith("[")) { //如果目标是数组,将会输出一个Key为当前Json的List<Dictionary<string, object>>集合 List<Dictionary<string, object>> ListDic = (List<Dictionary<string, object>>)Dic["Json中的Key"]; List<Dictionary<string, object>> List = new List<Dictionary<string, object>>(); MatchCollection ListMatch = Regex.Matches(item.Groups[2].ToString(), @"{[sS]+?}");//使用正则表达式匹配出JSON数组 foreach (Match ListItem in ListMatch) { List.Add(ToDictionary(ListItem.ToString()));//递归调用 } Data = List; } else if (item.Groups[2].ToString().ToLower() == "null") Data = null;//如果数据为null(字符串类型),直接转换成null else Data = item.Groups[2].ToString(); //数据为数字、字符串中的一类,直接写入 Dic.Add(item.Groups[1].ToString(), Data); } } return Dic; }
6.另外其他的 东西,在前面的章节中有讲过,不过wcf的原理看以简单的介绍下:
首先,通过ajax 请求 wcf 服务,然后进入到wcf服务后台,验证该方法名是否存在,如果 存在 则直接执行该方法名,
否则通过 反射 寻找到该方法执行。返回string的json格式。直接传输到前台。这样就可以达到 前台与 后台直接进行交互,而去掉了繁杂的
C#调用后台的方法。
另外附上VS2012的源代码:
http://files.cnblogs.com/files/liujing379069296/MySOA.rar
(说明:只需要修改web.config 中的连接字符串,然后写入 你对应数据库的sql语句就可以使用了)