最近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

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

 /// <summary>
/// 队列公共操作
/// </summary>
public interface IQueue : IDisposable
{
/// <summary>
/// 创建队列
/// </summary>
void Create(); /// <summary>
/// 总数
/// </summary>
/// <returns></returns>
int Total(); /// <summary>
/// 读取一个队列
/// </summary>
/// <returns></returns>
Message Read(); ///// <summary>
///// 读取多个队列
///// </summary>
///// <returns></returns>
//List<Message> ReadAll(); /// <summary>
/// 写入队列
/// </summary>
/// <returns></returns>
bool Write(string content, string name = "");
}

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

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

 #region 文件操作类
/// <summary>
/// 配置文件操作类
/// </summary>
/// <typeparam name="T"></typeparam>
public class ConfClass<T> where T : class,new()
{ public ConfClass() { var apiNodeName = this.GetType().Name;
Reader(apiNodeName);
} #region 单例模式 public static readonly object Singleton_Lock = new object(); /// <summary>
/// 单例对象
/// </summary>
private static T t = default(T); /// <summary>
/// 通过方法获取单例
/// </summary>
/// <param name="t"></param>
/// <returns></returns>
public static T GetInstance(T t)
{
t = t ?? new T();
return t;
} /// <summary>
/// 通过属性获取单例(在继承的时候使用)
/// </summary>
public static T Current
{
get
{
t = t ?? new T();
return t;
}
} #endregion #region 配置文件操作 #region 配置文件属性
/// <summary>
/// 配置文件地址
/// </summary>
//public string ConfPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Conf", "ShenNiuApi.xml");
public string ConfPath = @"C:\Conf\ShenNiuApi.xml"; /// <summary>
/// 配置文件父节点名称
/// </summary>
public string ConfParentNodeName = "ShenNiuApi"; /// <summary>
/// 配置文件内容
/// </summary>
public string ConfContent { get; set; } /// <summary>
/// 配置文件文档doc对象
/// </summary>
public XmlDocument doc { get; set; } /// <summary>
/// 账号
/// </summary>
public string UserName { get; set; } /// <summary>
/// 密码
/// </summary>
public string UserPwd { get; set; } /// <summary>
/// 接口地址
/// </summary>
public string ApiUrl { get; set; } /// <summary>
/// 秘钥
/// </summary>
public string ApiKey { get; set; } #endregion public ConfClass(string ConfPath, string ConfParentNodeName="")
{ this.ConfPath = string.IsNullOrWhiteSpace(ConfPath) ? this.ConfPath : ConfPath;
this.ConfParentNodeName = string.IsNullOrWhiteSpace(ConfParentNodeName) ? this.ConfParentNodeName : ConfParentNodeName; var apiNodeName = this.GetType().Name;
Reader(apiNodeName);
} /// <summary>
/// 读取配置信息
/// </summary>
/// <param name="apiNodeName"></param>
public void Reader(string apiNodeName)
{
try
{
if (string.IsNullOrWhiteSpace(ConfPath) || string.IsNullOrWhiteSpace(ConfParentNodeName))
{
throw new Exception("配置文件地址或者配置文件父节点名称不能为空");
} if (!File.Exists(ConfPath)) { return; } //获取配置文件信息
using (StreamReader reader = new StreamReader(ConfPath))
{
this.ConfContent = reader.ReadToEndAsync().Result;
} if (string.IsNullOrWhiteSpace(this.ConfContent)) { return; } //加入doc中
this.doc = new XmlDocument();
this.doc.LoadXml(this.ConfContent); //解析
var parentNode = string.Format("{0}/{1}", this.ConfParentNodeName, apiNodeName);
var apiNode = this.doc.SelectSingleNode(parentNode);
if (apiNode == null) { throw new Exception("未能找到" + parentNode + "节点"); } this.UserName = apiNode.SelectSingleNode("UserName").InnerText;
this.UserPwd = apiNode.SelectSingleNode("UserPwd").InnerText;
this.ApiUrl = apiNode.SelectSingleNode("ApiUrl").InnerText;
this.ApiKey = apiNode.SelectSingleNode("ApiKey").InnerText;
}
catch (Exception ex)
{ throw new Exception("加载配置文件" + this.ConfPath + "异常:" + ex.Message);
}
}
#endregion
}
#endregion

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

 <ShenNiuApi>
<QMsmq>
<UserName></UserName>
<UserPwd></UserPwd>
<ApiUrl>.\Private$\MyMsmq</ApiUrl>
<ApiKey></ApiKey>
</QMsmq>
</ShenNiuApi>

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

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

 #region 单例模式

             public static readonly object Singleton_Lock = new object();

             /// <summary>
/// 单例对象
/// </summary>
private static T t = default(T); /// <summary>
/// 通过方法获取单例
/// </summary>
/// <param name="t"></param>
/// <returns></returns>
public static T GetInstance(T t)
{
t = t ?? new T();
return t;
} /// <summary>
/// 通过属性获取单例(在继承的时候使用)
/// </summary>
public static T Current
{
get
{
t = t ?? new T();
return t;
}
} #endregion

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

 /// <summary>
/// 队列工厂
/// </summary>
public class QueueReposity<T> where T : class,IQueue, new()
{
public static IQueue Current
{
get
{
return PublicClass.ConfClass<T>.Current;
}
}
}

» 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>,此时具体的方法体如下:

  public class QMsmq : PublicClass.ConfClass<QMsmq>, IQueue
{ private MessageQueue _msmq = null; public void Create()
{
if (string.IsNullOrWhiteSpace(this.ApiUrl)) { throw new Exception("创建队列需要指定队列:地址"); } _msmq = MessageQueue.Exists(this.ApiUrl) ?
new MessageQueue(this.ApiUrl) :
_msmq ?? MessageQueue.Create(this.ApiUrl);
//设置数据格式
_msmq.Formatter = new XmlMessageFormatter(new Type[] { typeof(string) });
} public int Total()
{
if (_msmq == null) { throw new Exception("请先创建队列"); }
return _msmq.GetAllMessages().Length;
} public Message Read()
{
try
{
if (_msmq == null) { throw new Exception("请先创建队列"); } //60s超时
return _msmq.Receive(TimeSpan.FromSeconds());
}
catch (Exception ex)
{
throw new Exception(ex.Message);
}
} //public List<Message> ReadAll()
//{
// try
// {
// if (_msmq == null) { throw new Exception("请先创建队列"); } // var messages = _msmq.GetAllMessages();
// return messages.ToList();
// }
// catch (Exception ex)
// {
// throw new Exception(ex.Message);
// }
//} public bool Write(string content, string name = "")
{
try
{
if (_msmq == null) { throw new Exception("请先创建队列"); }
if (string.IsNullOrWhiteSpace(content)) { throw new Exception("填充内容不能为空"); } var message = new Message();
message.Body = content;
message.Label = name;
_msmq.Send(message);
return true;
}
catch (Exception ex)
{
throw new Exception(ex.Message);
}
} public void Dispose()
{
if (_msmq != null)
{
_msmq.Close();
_msmq.Dispose();
_msmq = null;
}
}
}

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

  class Program
{
static void Main(string[] args)
{
Client();
} /// <summary>
/// 客户端
/// </summary>
private static void Client()
{
//实例化QMsmq对象
var msmq = QueueReposity<QMsmq>.Current;
try
{
Console.WriteLine("创建:msmq");
msmq.Create(); while (true)
{
try
{
var result = msmq.Read();
Console.WriteLine(string.Format("接受第{0}个:{1}", result.Label, result.Body));
}
catch (Exception ex)
{ Console.WriteLine("异常信息:" + ex.Message); }
}
}
catch (Exception ex)
{
throw ex;
}
finally
{
Console.WriteLine("释放。");
msmq.Dispose();
}
}
}

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

  class Program
{
static void Main(string[] args)
{
Server();
} /// <summary>
/// 服务端
/// </summary>
private static void Server()
{
//实例化QMsmq对象
var msmq = QueueReposity<QMsmq>.Current; try
{
Console.WriteLine("创建:msmq");
msmq.Create(); var num = ;
do
{
Console.WriteLine("输入循环数量(数字,0表示结束):");
var readStr = Console.ReadLine();
num = string.IsNullOrWhiteSpace(readStr) ? : Convert.ToInt32(readStr); Console.WriteLine("插入数据:");
for (int i = ; i < num; i++)
{
var str = "我的编号是:" + i;
msmq.Write(str, i.ToString());
Console.WriteLine(str);
}
} while (num > );
}
catch (Exception ex)
{
}
finally
{
Console.WriteLine("释放。");
msmq.Dispose();
}
Console.ReadLine();
}
}

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

队列工厂之(MSMQ)的更多相关文章

  1. 队列工厂之RabbitMQ

    本次和大家分享的是RabbitMQ队列的用法,前一篇文章队列工厂之(MSMQ)中在描述的时候已经搭建了简单工厂,因此本章内容是在其之上扩充的子项不再过多讲解工厂的代码了:RabbitMQ应该是现在互联 ...

  2. 队列工厂之RedisMQ

    本次和大家分享的是RedisMQ队列的用法,前两篇文章队列工厂之(MSMQ)和队列工厂之RabbitMQ分别简单介绍对应队列环境的搭建和常用方法的使用,加上本篇分享的RedisMQ那么就完成了咋们队列 ...

  3. 消息队列数量统计(MSMQ,Performance Counter)

    微软消息队列服务MSMQ (Microsoft Message Queue),工作在在线或者离线场景,并提供异步编程功能.互联网和企业开发很多场景应用,例如电商的订单处理流程,这是因为客户端不需要等待 ...

  4. 消息队列工具类(MSMQ)

    所要做的是简化msmq的调用代码以及做到可替代性,实现后,调用消息队列代码变为如下所示: QueueService srv = QueueService.Instance(); //检查存储DTO1的 ...

  5. Open Source

    资源来源于http://www.cnblogs.com/Leo_wl/category/246424.html RabbitMQ 安装与使用 摘要: RabbitMQ 安装与使用 前言 吃多了拉就是队 ...

  6. RedisMQ

    RedisMQ 本次和大家分享的是RedisMQ队列的用法,前两篇文章队列工厂之(MSMQ)和队列工厂之RabbitMQ分别简单介绍对应队列环境的搭建和常用方法的使用,加上本篇分享的RedisMQ那么 ...

  7. MSMQ队列学习记录

    微软消息队列-MicroSoft Message Queue(MSMQ) 使用感受:简单. 一.windows安装MSMQ服务 控制面板->控制面板->所有控制面板项->程序和功能- ...

  8. MSMQ队列的简单使用

    微软消息队列-MicroSoft Message Queue(MSMQ) 使用感受:简单. 一.windows安装MSMQ服务 控制面板->控制面板->所有控制面板项->程序和功能- ...

  9. 微软消息队列-MicroSoft Message Queue(MSMQ)队列的C#使用

    目录 定义的接口 接口实现 建立队列工厂 写入队列 获取消息 什么是MSMQ Message Queuing(MSMQ) 是微软开发的消息中间件,可应用于程序内部或程序之间的异步通信.主要的机制是:消 ...

随机推荐

  1. thinkphp 配置项总结

    'URL_PATHINFO_DEPR'=>'-',//修改URL的分隔符 'TMPL_L_DELIM'=>'<{', //修改左定界符 'TMPL_R_DELIM'=>'}&g ...

  2. thinkphp 3.2 模型的使用示例

    原来以为thinkPHP的 model 就和PHPCMS一样  就起到一个连接数据库的作用,今天看了视频,才发现这个也是 mvc中的m 使用方法可以使用 D() 方法 下面是 UserControll ...

  3. OGG数据仓库以及单向复制(一)

    Item Source System Target System Platform OEL5.4 OEL5.4 Hostname gc1 oraclelinux54.cuug.net Database ...

  4. Bootstrap入门(四)表格

    Bootstrap入门(四)表格 <table>标签 首先,引入bootstrap的css文件,然后表格内容放在一个class为table的<table>标签中(class=& ...

  5. ABP入门系列(7)——分页实现

    ABP入门系列目录--学习Abp框架之实操演练 完成了任务清单的增删改查,咱们来讲一讲必不可少的的分页功能. 首先很庆幸ABP已经帮我们封装了分页实现,实在是贴心啊. 来来来,这一节咱们就来捋一捋如何 ...

  6. Hadoop权威指南: 专有数据类型

    Writable 和 WritableComparable接口 Writable接口 ** Writable接口的主要目的是,当数据在网络上传输或从硬盘读写时,提供数据的序列化和反序列化机智 ** * ...

  7. MySQL插入数据中文乱码问题的解决

    一.使用语句 show variables like 'character%'; 来查看当前数据库的相关编码集. 1.启动cmd,登录mysql ①cd C:\Program Files\MySQL\ ...

  8. asp.net权限认证:摘要认证(digest authentication)

    asp.net权限认证系列 asp.net权限认证:Forms认证 asp.net权限认证:HTTP基本认证(http basic) asp.net权限认证:Windows认证 asp.net权限认证 ...

  9. haproxy学习

    1.安装 # wget http://haproxy.1wt.eu/download/1.3/src/haproxy-1.3.20.tar.gz # tar zcvf haproxy-1.3.20.t ...

  10. 2.JAVA垃圾回收机制

    前言 线程独享的内存区域有程序计数器,虚拟机栈,本地方法栈,这些区域不用考虑内存回收的问题,随着线程的执行结束,自然就回收了,而堆内存和方法区的回收则不一样,他们的内存分配和回收是动态的. 1.对象存 ...