博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
队列工厂之(MSMQ)
阅读量:6879 次
发布时间:2019-06-26

本文共 13376 字,大约阅读时间需要 44 分钟。

最近vs2017神器正式版发布让人很是激动,vs2017支持了很多语言的开发,从前端-后端-底层的支持,堪称是工具中的神器;netcore我喜爱的架构之一也得到了大力的宣传,应群友的邀请将在队列工厂(msmq,redis,rabbitmq)一些列文章过后,继续增加.netcore方面的文章,只为.netcore发展更好贡献一份微弱的力量;本章内容分享的是队列(msmq,redis,rabbitmq)封装的队列工厂之MSMQ希望大家能够喜欢,也希望各位多多"扫码支持"和"推荐"谢谢!

 

» 创建队列工厂QueueReposity<T>

  . 队列公共操作接口IQueue

  . 配置文件操作类ConfClass<T>

  . 非安全单例创建队列实例

» Win7和Server2008安装MSMQ支持

» MSMQ测试用例(服务端+客户端)

 

下面一步一个脚印的来分享:

» 创建队列工厂QueueReposity<T>

首先,因为这里需要统一封装几个常用的队列方式的用法,因此采用了简单工厂模式,所以有了QueueReposity<T>

. 队列公共操作接口IQueue

工厂模式的特性创建实例,因为这里封装的都是队列,故而能提取出统一的规则来,因此定义了如下接口(这里没有考虑一些队列兼容的异步方法请忽略):

1 ///  2     /// 队列公共操作 3     ///  4     public interface IQueue : IDisposable 5     { 6         ///  7         /// 创建队列 8         ///  9         void Create();10 11         /// 12         /// 总数13         /// 14         /// 
15 int Total();16 17 /// 18 /// 读取一个队列19 /// 20 ///
21 Message Read();22 23 / 24 / 读取多个队列25 / 26 /
27 //List
ReadAll();28 29 ///
30 /// 写入队列31 /// 32 ///
33 bool Write(string content, string name = "");34 }

. 配置文件操作类ConfClass<T>

因为每个队列的都有自己的配置信息,因此封装了统一管理的配置文件读取类ConfClass<T>,来读取配置在同一个xml文件中的配置信息,如下封装了自定义配置文件的属性和读取方法:

1 #region 文件操作类  2         ///   3         /// 配置文件操作类  4         ///   5         /// 
6 public class ConfClass
where T : class,new() 7 { 8 9 public ConfClass() { 10 11 var apiNodeName = this.GetType().Name; 12 Reader(apiNodeName); 13 } 14 15 #region 单例模式 16 17 public static readonly object Singleton_Lock = new object(); 18 19 ///
20 /// 单例对象 21 /// 22 private static T t = default(T); 23 24 ///
25 /// 通过方法获取单例 26 /// 27 ///
28 ///
29 public static T GetInstance(T t) 30 { 31 t = t ?? new T(); 32 return t; 33 } 34 35 ///
36 /// 通过属性获取单例(在继承的时候使用) 37 /// 38 public static T Current 39 { 40 get 41 { 42 t = t ?? new T(); 43 return t; 44 } 45 } 46 47 #endregion 48 49 #region 配置文件操作 50 51 #region 配置文件属性 52 ///
53 /// 配置文件地址 54 /// 55 //public string ConfPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Conf", "ShenNiuApi.xml"); 56 public string ConfPath = @"C:\Conf\ShenNiuApi.xml"; 57 58 ///
59 /// 配置文件父节点名称 60 /// 61 public string ConfParentNodeName = "ShenNiuApi"; 62 63 ///
64 /// 配置文件内容 65 /// 66 public string ConfContent { get; set; } 67 68 ///
69 /// 配置文件文档doc对象 70 /// 71 public XmlDocument doc { get; set; } 72 73 74 ///
75 /// 账号 76 /// 77 public string UserName { get; set; } 78 79 ///
80 /// 密码 81 /// 82 public string UserPwd { get; set; } 83 84 ///
85 /// 接口地址 86 /// 87 public string ApiUrl { get; set; } 88 89 ///
90 /// 秘钥 91 /// 92 public string ApiKey { get; set; } 93 94 #endregion 95 96 public ConfClass(string ConfPath, string ConfParentNodeName="") 97 { 98 99 this.ConfPath = string.IsNullOrWhiteSpace(ConfPath) ? this.ConfPath : ConfPath;100 this.ConfParentNodeName = string.IsNullOrWhiteSpace(ConfParentNodeName) ? this.ConfParentNodeName : ConfParentNodeName;101 102 var apiNodeName = this.GetType().Name;103 Reader(apiNodeName);104 }105 106 ///
107 /// 读取配置信息108 /// 109 ///
110 public void Reader(string apiNodeName)111 {112 try113 {114 if (string.IsNullOrWhiteSpace(ConfPath) || string.IsNullOrWhiteSpace(ConfParentNodeName))115 {116 throw new Exception("配置文件地址或者配置文件父节点名称不能为空");117 }118 119 if (!File.Exists(ConfPath)) { return; }120 121 //获取配置文件信息122 using (StreamReader reader = new StreamReader(ConfPath))123 {124 this.ConfContent = reader.ReadToEndAsync().Result;125 }126 127 if (string.IsNullOrWhiteSpace(this.ConfContent)) { return; }128 129 //加入doc中130 this.doc = new XmlDocument();131 this.doc.LoadXml(this.ConfContent);132 133 //解析134 var parentNode = string.Format("{0}/{1}", this.ConfParentNodeName, apiNodeName);135 var apiNode = this.doc.SelectSingleNode(parentNode);136 if (apiNode == null) { throw new Exception("未能找到" + parentNode + "节点"); }137 138 this.UserName = apiNode.SelectSingleNode("UserName").InnerText;139 this.UserPwd = apiNode.SelectSingleNode("UserPwd").InnerText;140 this.ApiUrl = apiNode.SelectSingleNode("ApiUrl").InnerText;141 this.ApiKey = apiNode.SelectSingleNode("ApiKey").InnerText;142 }143 catch (Exception ex)144 {145 146 throw new Exception("加载配置文件" + this.ConfPath + "异常:" + ex.Message);147 }148 }149 #endregion150 }151 #endregion

这个配置文件的类主要运用在队列实例继承上,只要继承了默认就会读取响应的配置节点信息;配置xml文件默认存储的地址: C:\Conf\ShenNiuApi.xml ,最大父节点名称默认:ShenNiuApi,格式如下所示:

1 
2
3
4
5
.\Private$\MyMsmq
6
7
8

. 非安全单例创建队列实例

由于工厂都是专门用来提供实例的存在,创建实例的模式也有很多这种,这里我选择的是非安全单例创建队列实例,所有在ConfClass类中默认加入了单例模式:

1 #region 单例模式 2  3             public static readonly object Singleton_Lock = new object(); 4  5             ///  6             /// 单例对象 7             ///  8             private static T t = default(T); 9 10             /// 11             /// 通过方法获取单例12             /// 13             /// 14             /// 
15 public static T GetInstance(T t)16 {17 t = t ?? new T();18 return t;19 }20 21 /// 22 /// 通过属性获取单例(在继承的时候使用)23 /// 24 public static T Current25 {26 get27 {28 t = t ?? new T();29 return t;30 }31 }32 33 #endregion

因此这里所说的工厂模式通过泛型传递类型,再创建实例的具体代码只有这么点,简短精炼:

1 ///  2     /// 队列工厂 3     ///  4     public class QueueReposity
where T : class,IQueue, new() 5 { 6 public static IQueue Current 7 { 8 get 9 {10 return PublicClass.ConfClass
.Current;11 }12 }13 }

 

» Win7和Server2008安装MSMQ支持

上面分享的是队列工厂的结构,到这里就要开始我们的第一个MSMQ队列的安装和封装分享了;首先来看Win7测试环境上怎么安装MSMQ的支持:开始菜单-》控制面板-》程序和功能:

-》打开或关闭Windows功能-》勾选如图所示队列安装组件:

-》确定等待安装完成;到此win7安装msmq就完成了,因为msmq是系统默认的所以安装起来很方便,当然server2008也差不多,按照如下操作安装(这里我使用租的阿里云Server2008R2服务器为例):开始-》控制面板-》程序(下面的打开或关闭Window功能)->功能-》添加功能-》消息队列:

在server上安装的步骤基本没啥变化,是不是很简单;安装完成后这样你的电脑或服务器就支持msmq了,此刻的你是不是很兴奋,觉得又能学到新东西了呵呵;

 

» MSMQ测试用例(服务端+客户端)

首先,这里我用控制台程序做测试用例,我分为客户端和服务端,用服务端通过分装的插入队列方法插入数据,然后通过客户端读取队列信息,先来上个图撑撑场面吧:

这里我创建了MSMQ的分装类 public class QMsmq : PublicClass.ConfClass<QMsmq>, IQueue 实现了队列接口IQueue和继承配置文件类ConfClass<QMsmq>,此时具体的方法体如下:

1  public class QMsmq : PublicClass.ConfClass
, IQueue 2 { 3 4 5 private MessageQueue _msmq = null; 6 7 public void Create() 8 { 9 if (string.IsNullOrWhiteSpace(this.ApiUrl)) { throw new Exception("创建队列需要指定队列:地址"); }10 11 _msmq = MessageQueue.Exists(this.ApiUrl) ?12 new MessageQueue(this.ApiUrl) :13 _msmq ?? MessageQueue.Create(this.ApiUrl);14 //设置数据格式15 _msmq.Formatter = new XmlMessageFormatter(new Type[] { typeof(string) });16 }17 18 public int Total()19 {20 if (_msmq == null) { throw new Exception("请先创建队列"); }21 return _msmq.GetAllMessages().Length; 22 }23 24 public Message Read()25 {26 try27 {28 if (_msmq == null) { throw new Exception("请先创建队列"); }29 30 //60s超时31 return _msmq.Receive(TimeSpan.FromSeconds(60));32 }33 catch (Exception ex)34 {35 throw new Exception(ex.Message);36 }37 }38 39 //public List
ReadAll()40 //{41 // try42 // {43 // if (_msmq == null) { throw new Exception("请先创建队列"); }44 45 // var messages = _msmq.GetAllMessages();46 // return messages.ToList();47 // }48 // catch (Exception ex)49 // {50 // throw new Exception(ex.Message);51 // }52 //}53 54 public bool Write(string content, string name = "")55 {56 try57 {58 if (_msmq == null) { throw new Exception("请先创建队列"); }59 if (string.IsNullOrWhiteSpace(content)) { throw new Exception("填充内容不能为空"); }60 61 var message = new Message();62 message.Body = content;63 message.Label = name;64 _msmq.Send(message);65 return true;66 }67 catch (Exception ex)68 {69 throw new Exception(ex.Message);70 }71 }72 73 public void Dispose()74 {75 if (_msmq != null)76 {77 _msmq.Close();78 _msmq.Dispose();79 _msmq = null;80 }81 }82 }

到这里我们的MSMQ简单封装代码已经完成了,咋们再来通过控制台调用下这个队列客户端代码

1  class Program 2     { 3         static void Main(string[] args) 4         { 5             Client(); 6         } 7  8         ///  9         /// 客户端10         /// 11         private static void Client()12         {13             //实例化QMsmq对象14             var msmq = QueueReposity
.Current;15 try16 {17 Console.WriteLine("创建:msmq");18 msmq.Create();19 20 while (true)21 {22 try23 {24 var result = msmq.Read();25 Console.WriteLine(string.Format("接受第{0}个:{1}", result.Label, result.Body));26 }27 catch (Exception ex)28 { Console.WriteLine("异常信息:" + ex.Message); }29 }30 }31 catch (Exception ex)32 {33 throw ex;34 }35 finally36 {37 Console.WriteLine("释放。");38 msmq.Dispose();39 }40 }41 }

这里能够看出客户端代码中使用MSMQ步骤主要有:QueueReposity<QMsmq>.Current工厂创建自定义队列实例-》Create()创建-》Read()读取-》Dispose()释放mq,流程还算清晰吧;如下服务端代码:

1  class Program 2     { 3         static void Main(string[] args) 4         { 5             Server(); 6         } 7  8         ///  9         /// 服务端10         /// 11         private static void Server()12         {13             //实例化QMsmq对象14             var msmq = QueueReposity
.Current;15 16 try17 {18 Console.WriteLine("创建:msmq");19 msmq.Create();20 21 var num = 0;22 do23 {24 Console.WriteLine("输入循环数量(数字,0表示结束):");25 var readStr = Console.ReadLine();26 num = string.IsNullOrWhiteSpace(readStr) ? 0 : Convert.ToInt32(readStr);27 28 Console.WriteLine("插入数据:");29 for (int i = 0; i < num; i++)30 {31 var str = "我的编号是:" + i;32 msmq.Write(str, i.ToString());33 Console.WriteLine(str);34 }35 } while (num > 0);36 }37 catch (Exception ex)38 {39 }40 finally41 {42 Console.WriteLine("释放。");43 msmq.Dispose();44 }45 Console.ReadLine();46 }47 }

服务端的步骤几乎和客户端差不多,区别在于一个读取一个写入,服务端步骤:QueueReposity<QMsmq>.Current工厂创建自定义队列实例-》Create()创建-》Write()写入-》Dispose()释放mq;以上对MSMQ的代码分享和环境搭建讲解,希望能给您带来好的帮助,谢谢阅读;

转载地址:http://rvgfl.baihongyu.com/

你可能感兴趣的文章
java8 stream实现列表去重,java8的stream 和lambda的使用实例
查看>>
iOS中通知的添加和移除
查看>>
企业分布式微服务云SpringCloud SpringBoot mybatis (一)服务的注册与发现(Eureka)...
查看>>
批量下载图片
查看>>
Java内存模型(Memory Model)
查看>>
某大型网站迁移纪实(一)
查看>>
C#进行Socket 连接发送和接收数据
查看>>
即时编辑插件-jeditable|已迁移
查看>>
Linux下CA证书服务配置
查看>>
《JMeter从入门到精通》之一——开始你的第一个JMeter脚本
查看>>
从技术到管理,艰难的转型
查看>>
如何制作Windows 8系统U盘
查看>>
Linux之cgi实现系统主机监控
查看>>
我的友情链接
查看>>
[sig09]Rendering Technology at Black Rock Studio
查看>>
“8+1”,解决企业绩效管理老大难!
查看>>
指责和分享
查看>>
查询同一表内多字段同时重复记录的SQL语句
查看>>
(.公司)域名2015年度报告:仅一家注册量过万
查看>>
关于红黑树的学习笔记
查看>>