rabbitmq系列(二)几种常见模式的应用场景及实现
一、简单模式
原理:生产者将消息交给默认的交换机,交换机获取消息后交给绑定这个生产者的队列(投递规则为队列名称和routing key 相同的队列),监听当前队列的消费者获取信息并执行消费逻辑。
场景:有一个oa系统,用户通过接收手机验证码进行注册,页面上点击获取验证码后,将验证码放到消息队列,然后短信服务从队列中获取到验证码,并发送给用户。
实现:
生产者:
public class Producter {
public static void main(String[] args) throws Exception {
// 1. 创建出链接工厂
ConnectionFactory factory = new ConnectionFactory();
factory.setHost("127.0.0.1");
factory.setPort(5672);
factory.setVirtualHost("/");
// 2. 通过链接工厂创建链接对象
Connection connection = factory.newConnection();
// 3. 通过链接对象创建出channel
Channel channel = connection.createChannel();
// 4. 通过channel发布消息
/**
* 四个参数:
* 第一个参数是交换机的名称
* 第二个参数是路由键
* 第三个参数标识消息的一些额外的属性
* 第四个是消息的具体的内容
*/
String message = "字节";
for(int i = 0;i < 5;i ++){
channel.basicPublish("","byte001",null,message.getBytes());
}
// 5. 释放资源,释放channel 和 链接对象
channel.close();
connection.close();
}
}
消费者:
public class Consumer {
public static void main(String[] args) throws Exception {
// 1. 创建出链接工厂
ConnectionFactory factory = new ConnectionFactory();
factory.setHost("127.0.0.1");
factory.setPort(5672);
factory.setVirtualHost("/");
// 2. 通过链接工厂创建链接对象
Connection connection = factory.newConnection();
// 3. 通过链接对象创建出channel
Channel channel = connection.createChannel();
// 4. 创建出消息队列
/**
* 第一个参数是消息队列的名称
* 第二个参数表示消息是否持久化
* 第三个参数标识消息队列是否被channel独占
* 第四个参数标识是否自动删除消息队列,当消息队列没有绑定交换机后是否自动删除
* 第五个是消息队列扩展参数
*/
String queueName = "byte001";
channel.queueDeclare(queueName, true, false, false, null);
// 5. 创建消费者,对消息进行处理
DefaultConsumer consumer = new DefaultConsumer(channel) {
/**
* consumerTag 用来标识.可以再监听队列时候设置
* envelope 信封,通过envelope可以通过这个获取到很多东西
* properties 额外的消息属性
* body:消息体
*/
@Override
public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
String s = new String(body, "UTF-8");
System.out.println("获取到的消息:"+s);
}
};
// 6. 通过channel消费者和消息队列关联
/**
* 第一个参数是消息队列的名字
* 第二个参数是否自动签收(即消费消息后告知服务器已被消费)
* 第三个参数是消费者
*/
channel.basicConsume(queueName, true, consumer);
}
}
二、工作模式
原理:生产者将消息交给交换机,交换机交给绑定的队列,队列有多个消费者监听,一条消息只能由一个消费者消费,这样就形成了资源竞争,谁的资源空闲大,争抢到的可能性就大。
场景:有一个电商平台,有两个订单服务,用户下单的时候,任意一个订单服务消费用户的下单请求生成订单即可。不用两个订单服务同时消费用户的下单请求。
实现:
生产者:
public class Producter {
public static final String QUEUE_NAME = "byte002";
public static void main(String[] args) throws Exception {
// 1. 创建出链接工厂
ConnectionFactory factory = new ConnectionFactory();
factory.setHost("127.0.0.1");
factory.setPort(5672);
factory.setVirtualHost("/");
// 2. 通过链接工厂创建链接对象
Connection connection = factory.newConnection();
// 3. 通过链接对象创建出channel
Channel channel = connection.createChannel();
// 申明队列
channel.queueDeclare(QUEUE_NAME,false,false,false,null);
// 4. 通过channel发布消息
/**
* 四个参数:
* 第一个参数是交换机的名称
* 第二个参数是路由键
* 第三个参数标识消息的一些额外的属性
* 第四个是消息的具体的内容
*/
String message = "字节";
for(int i = 0;i < 100;i ++){
channel.basicPublish("",QUEUE_NAME,null,(message+i).getBytes());
}
// 5. 释放资源,释放channel 和 链接对象
channel.close();
connection.close();
}
}
消费者1:
public class Consumer {
public static final String QUEUE_NAME = "byte002";
public static void main(String[] args) throws Exception {
// 1. 创建出链接工厂
ConnectionFactory factory = new ConnectionFactory();
factory.setHost("127.0.0.1");
factory.setPort(5672);
factory.setVirtualHost("/");
// 2. 通过链接工厂创建链接对象
Connection connection = factory.newConnection();
// 3. 通过链接对象创建出channel
Channel channel = connection.createChannel();
// 4. 创建出消息队列
/**
* 第一个参数是消息队列的名称
* 第二个参数表示消息是否持久化
* 第三个参数标识消息队列是否被channel独占
* 第四个参数标识是否自动删除消息队列,当消息队列没有绑定交换机后是否自动删除
* 第五个是消息队列扩展参数
*/
channel.queueDeclare(QUEUE_NAME, false, false, false, null);
channel.basicQos(1); // 告诉服务器,在我们没有确认当前消息时不要给我们发送新的消息
// 5. 创建消费者,对消息进行处理
DefaultConsumer consumer = new DefaultConsumer(channel) {
/**
* consumerTag 用来标识.可以再监听队列时候设置
* envelope 信封,通过envelope可以通过这个获取到很多东西
* properties 额外的消息属性
* body:消息体
*/
@Override
public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
String s = new String(body, "UTF-8");
System.out.println("消费者1收到的内容:"+s);
try {
Thread.sleep(10); // 模拟消费耗时
} catch (InterruptedException e) {
e.printStackTrace();
}
channel.basicAck(envelope.getDeliveryTag(),false); // 参数2false为确认收到消息,true为拒绝收到消息
}
};
// 6. 通过channel消费者和消息队列关联
/**
* 第一个参数是消息队列的名字
* 第二个参数是否自动签收(即消费消息后告知服务器已被消费)
* 第三个参数是消费者
*/
channel.basicConsume(QUEUE_NAME, false, consumer);
}
}
消费者2:
public class Consumer2 {
public static final String QUEUE_NAME = "byte002";
public static void main(String[] args) throws Exception {
// 1. 创建出链接工厂
ConnectionFactory factory = new ConnectionFactory();
factory.setHost("127.0.0.1");
factory.setPort(5672);
factory.setVirtualHost("/");
// 2. 通过链接工厂创建链接对象
Connection connection = factory.newConnection();
// 3. 通过链接对象创建出channel
Channel channel = connection.createChannel();
// 4. 创建出消息队列
/**
* 第一个参数是消息队列的名称
* 第二个参数表示消息是否持久化
* 第三个参数标识消息队列是否被channel独占
* 第四个参数标识是否自动删除消息队列,当消息队列没有绑定交换机后是否自动删除
* 第五个是消息队列扩展参数
*/
channel.queueDeclare(QUEUE_NAME, false, false, false, null);
channel.basicQos(1); // 告诉服务器,在我们没有确认当前消息时不要给我们发送新的消息
// 5. 创建消费者,对消息进行处理
DefaultConsumer consumer = new DefaultConsumer(channel) {
/**
* consumerTag 用来标识.可以再监听队列时候设置
* envelope 信封,通过envelope可以通过这个获取到很多东西
* properties 额外的消息属性
* body:消息体
*/
@Override
public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
String s = new String(body, "UTF-8");
System.out.println("消费者2收到的内容:"+s);
try {
Thread.sleep(500); // 模拟消费耗时
} catch (InterruptedException e) {
e.printStackTrace();
}
channel.basicAck(envelope.getDeliveryTag(),false); // 参数2false为确认收到消息,true为拒绝收到消息
}
};
// 6. 通过channel消费者和消息队列关联
/**
* 第一个参数是消息队列的名字
* 第二个参数是否自动签收(即消费消息后告知服务器已被消费)
* 第三个参数是消费者
*/
channel.basicConsume(QUEUE_NAME, false, consumer);
}
}
保证资源竞争的代码就是这一行channel.basicQos(1);如果不加这一行,我们会发现两个消费者是轮询消费消息的。
三、发布订阅模式
原理:生产者将消息扔给交换机,交换机类型是fanout,不同的队列注册到交换机上,不同的消费注册在不同的队列上。所有消费者都会收到消息。
场景:有一个商城,我们新添加一个商品后,可能同时需要去更新缓存和数据库。
实现:
生产者:
public class Producter {
// 定义交换机的名字
public static final String EXCHANGE_NAME="byte003";
public static void main(String[] args) throws Exception {
// 1. 创建出链接工厂
ConnectionFactory factory = new ConnectionFactory();
factory.setHost("127.0.0.1");
factory.setPort(5672);
factory.setVirtualHost("/");
// 2. 通过链接工厂创建链接对象
Connection connection = factory.newConnection();
// 3. 通过链接对象创建出channel
Channel channel = connection.createChannel();
// 定义一个交换机,类型是fanout
channel.exchangeDeclare(EXCHANGE_NAME,"fanout");
// 因为消息先发到交换机,交换机没有保存功能,所以如果没有消费者,消息会丢失
channel.basicPublish(EXCHANGE_NAME,"",null,"发布订阅模式的消息".getBytes());
channel.close();
connection.close();
}
}
消费者1:
public class Consumer1 {
public static final String EXCHANGE_NAME="byte003";
public static void main(String[] args) throws Exception {
// 1. 创建出链接工厂
ConnectionFactory factory = new ConnectionFactory();
factory.setHost("127.0.0.1");
factory.setPort(5672);
factory.setVirtualHost("/");
// 2. 通过链接工厂创建链接对象
Connection connection = factory.newConnection();
// 3. 通过链接对象创建出channel
Channel channel = connection.createChannel();
String queueName = "queue003";
channel.queueDeclare(queueName,false,false,false,null);
// 绑定队列到交换机
channel.queueBind(queueName,EXCHANGE_NAME,"");
channel.basicQos(1);
DefaultConsumer consumer = new DefaultConsumer(channel) {
/**
* consumerTag 用来标识.可以再监听队列时候设置
* envelope 信封,通过envelope可以通过这个获取到很多东西
* properties 额外的消息属性
* body:消息体
*/
@Override
public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
String s = new String(body, "UTF-8");
System.out.println("消费者1:"+s);
channel.basicAck(envelope.getDeliveryTag(),false);
}
};
channel.basicConsume(queueName,false,consumer);
}
}
消费者2:
public class Consumer2 {
public static final String EXCHANGE_NAME="byte003";
public static void main(String[] args) throws Exception {
// 1. 创建出链接工厂
ConnectionFactory factory = new ConnectionFactory();
factory.setHost("127.0.0.1");
factory.setPort(5672);
factory.setVirtualHost("/");
// 2. 通过链接工厂创建链接对象
Connection connection = factory.newConnection();
// 3. 通过链接对象创建出channel
Channel channel = connection.createChannel();
String queueName = "queue004";
channel.queueDeclare(queueName,false,false,false,null);
// 绑定队列到交换机
channel.queueBind(queueName,EXCHANGE_NAME,"");
channel.basicQos(1);
DefaultConsumer consumer = new DefaultConsumer(channel) {
/**
* consumerTag 用来标识.可以再监听队列时候设置
* envelope 信封,通过envelope可以通过这个获取到很多东西
* properties 额外的消息属性
* body:消息体
*/
@Override
public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
String s = new String(body, "UTF-8");
System.out.println("消费者2:"+s);
channel.basicAck(envelope.getDeliveryTag(),false);
}
};
channel.basicConsume(queueName,false,consumer);
}
}
需要注意的一点就是交换机没有保存功能,如果没有消费者,则消息会丢失。
四、路由模式
原理:生产者将消息发送给交换机,消息携带具体的routingkey。交换机类型是direct,接收到消息中的routingkey,比对与之绑定的队列的routingkey,分发到不同的队列上。
场景:还是一样,有一个商城,新添加了一个商品,实时性不是很高,只需要添加到数据库即可,不用刷新缓存。
实现:
生产者:
public class Producter {
// 定义交换机的名字
public static final String EXCHANGE_NAME="byte004";
public static void main(String[] args) throws Exception {
// 1. 创建出链接工厂
ConnectionFactory factory = new ConnectionFactory();
factory.setHost("127.0.0.1");
factory.setPort(5672);
factory.setVirtualHost("/");
// 2. 通过链接工厂创建链接对象
Connection connection = factory.newConnection();
// 3. 通过链接对象创建出channel
Channel channel = connection.createChannel();
// 定义一个交换机,类型是direct
channel.exchangeDeclare(EXCHANGE_NAME,"direct");
// 因为消息先发到交换机,交换机没有保存功能,所以如果没有消费者,消息会丢失
channel.basicPublish(EXCHANGE_NAME,"key1",null,"发布路由模式的消息".getBytes());
channel.close();
connection.close();
}
}
消费者1:
public class Consumer1 {
public static final String EXCHANGE_NAME="byte004";
public static void main(String[] args) throws Exception {
// 1. 创建出链接工厂
ConnectionFactory factory = new ConnectionFactory();
factory.setHost("127.0.0.1");
factory.setPort(5672);
factory.setVirtualHost("/");
// 2. 通过链接工厂创建链接对象
Connection connection = factory.newConnection();
// 3. 通过链接对象创建出channel
Channel channel = connection.createChannel();
String queueName = "queue005";
channel.queueDeclare(queueName,false,false,false,null);
// 绑定队列到交换机
/**
* 参数3是routingkey,只有和它一样的routingkey的消息才会被当前消费者收到
*/
channel.queueBind(queueName,EXCHANGE_NAME,"key1");
// 如果要接收多个routingkey的消息,在执行一次上面的代码即可,如下
channel.queueBind(queueName,EXCHANGE_NAME,"key2");
channel.basicQos(1);
DefaultConsumer consumer = new DefaultConsumer(channel) {
/**
* consumerTag 用来标识.可以再监听队列时候设置
* envelope 信封,通过envelope可以通过这个获取到很多东西
* properties 额外的消息属性
* body:消息体
*/
@Override
public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
String s = new String(body, "UTF-8");
System.out.println("消费者1:"+s);
channel.basicAck(envelope.getDeliveryTag(),false);
}
};
channel.basicConsume(queueName,false,consumer);
}
}
消费者2:
public class Consumer2 {
public static final String EXCHANGE_NAME="byte004";
public static void main(String[] args) throws Exception {
// 1. 创建出链接工厂
ConnectionFactory factory = new ConnectionFactory();
factory.setHost("127.0.0.1");
factory.setPort(5672);
factory.setVirtualHost("/");
// 2. 通过链接工厂创建链接对象
Connection connection = factory.newConnection();
// 3. 通过链接对象创建出channel
Channel channel = connection.createChannel();
String queueName = "queue006";
channel.queueDeclare(queueName,false,false,false,null);
// 绑定队列到交换机
channel.queueBind(queueName,EXCHANGE_NAME,"key2");
channel.basicQos(1);
DefaultConsumer consumer = new DefaultConsumer(channel) {
/**
* consumerTag 用来标识.可以再监听队列时候设置
* envelope 信封,通过envelope可以通过这个获取到很多东西
* properties 额外的消息属性
* body:消息体
*/
@Override
public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
String s = new String(body, "UTF-8");
System.out.println("消费者2:"+s);
channel.basicAck(envelope.getDeliveryTag(),false);
}
};
channel.basicConsume(queueName,false,consumer);
}
}
五、主题模式
原理:路由模式的一种,路由功能添加了模糊匹配。星号(*)代表1个单词,#号(#)代表一个或多个单词。具体可参考路由模式。
场景:还是一样,有一个商城,新添加了一个商品,实时性不是很高,只需要添加到数据库即可,数据库包含了主数据库mysql1和从数据库mysql2的内容,不用刷新缓存。
实现:
生产者:
public class Producter {
// 定义交换机的名字
public static final String EXCHANGE_NAME="byte004";
public static void main(String[] args) throws Exception {
// 1. 创建出链接工厂
ConnectionFactory factory = new ConnectionFactory();
factory.setHost("127.0.0.1");
factory.setPort(5672);
factory.setVirtualHost("/");
// 2. 通过链接工厂创建链接对象
Connection connection = factory.newConnection();
// 3. 通过链接对象创建出channel
Channel channel = connection.createChannel();
// 定义一个交换机,类型是topic
channel.exchangeDeclare(EXCHANGE_NAME,"topic");
// 因为消息先发到交换机,交换机没有保存功能,所以如果没有消费者,消息会丢失
channel.basicPublish(EXCHANGE_NAME,"key.1.2",null,"发布路由模式的消息".getBytes());
channel.close();
connection.close();
}
}
消费者1:
public class Consumer1 {
public static final String EXCHANGE_NAME="byte004";
public static void main(String[] args) throws Exception {
// 1. 创建出链接工厂
ConnectionFactory factory = new ConnectionFactory();
factory.setHost("127.0.0.1");
factory.setPort(5672);
factory.setVirtualHost("/");
// 2. 通过链接工厂创建链接对象
Connection connection = factory.newConnection();
// 3. 通过链接对象创建出channel
Channel channel = connection.createChannel();
String queueName = "queue005";
channel.queueDeclare(queueName,false,false,false,null);
// 绑定队列到交换机
/**
* 参数3是routingkey,只有和它一样的routingkey的消息才会被当前消费者收到
*/
channel.queueBind(queueName,EXCHANGE_NAME,"key.*");
// 如果要接收多个routingkey的消息,在执行一次上面的代码即可,如下
channel.queueBind(queueName,EXCHANGE_NAME,"abc.#");
channel.basicQos(1);
DefaultConsumer consumer = new DefaultConsumer(channel) {
/**
* consumerTag 用来标识.可以再监听队列时候设置
* envelope 信封,通过envelope可以通过这个获取到很多东西
* properties 额外的消息属性
* body:消息体
*/
@Override
public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
String s = new String(body, "UTF-8");
System.out.println("消费者1:"+s);
channel.basicAck(envelope.getDeliveryTag(),false);
}
};
channel.basicConsume(queueName,false,consumer);
}
}
消费者2:
public class Consumer2 {
public static final String EXCHANGE_NAME="byte004";
public static void main(String[] args) throws Exception {
// 1. 创建出链接工厂
ConnectionFactory factory = new ConnectionFactory();
factory.setHost("127.0.0.1");
factory.setPort(5672);
factory.setVirtualHost("/");
// 2. 通过链接工厂创建链接对象
Connection connection = factory.newConnection();
// 3. 通过链接对象创建出channel
Channel channel = connection.createChannel();
String queueName = "queue006";
channel.queueDeclare(queueName,false,false,false,null);
// 绑定队列到交换机
channel.queueBind(queueName,EXCHANGE_NAME,"key.#");
channel.basicQos(1);
DefaultConsumer consumer = new DefaultConsumer(channel) {
/**
* consumerTag 用来标识.可以再监听队列时候设置
* envelope 信封,通过envelope可以通过这个获取到很多东西
* properties 额外的消息属性
* body:消息体
*/
@Override
public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
String s = new String(body, "UTF-8");
System.out.println("消费者2:"+s);
channel.basicAck(envelope.getDeliveryTag(),false);
}
};
channel.basicConsume(queueName,false,consumer);
}
}
代码已上传:
github地址: https://github.com/binzh303/zhixie-code-example
gitee地址: https://gitee.com/javaXiaoCaiJi/zhixie-code-example
> 如果文章对您有帮助,请记得点赞关注哟~
> 欢迎大家关注我的公众号:字节传说,每日推送技术文章供大家学习参考。
rabbitmq系列(二)几种常见模式的应用场景及实现的更多相关文章
- 在Node.js中使用RabbitMQ系列二 任务队列
在上一篇文章在Node.js中使用RabbitMQ系列一 Hello world我有使用一个任务队列,不过当时的场景是将消息发送给一个消费者,本篇文章我将讨论有多个消费者的场景. 其实,任务队列最核心 ...
- RabbitMQ入门及其几种工作模式
1.简介 MQ全程Message Queue,用于应用程序和应用程序间进行通信.RabbitMQ采用Erlang编写,实现了AMQP(高级消息队列)协议,跨平台,支持各种主流的操作系统和多种客户端. ...
- restql 学习二 几种查询模式
restql 提供了比较强大的查询处理. 支持的几种查询模式 基本查询,主要是单一映射资源的查询,(from,with,only,header,cache...) 并行查询,多个资源的同时查询,(对于 ...
- RabbitMQ系列(二)--基础组件
声明:对于RabbitMQ的学习基于某课网相关视频和<RabbitMQ实战指南>一书,后续关于RabbitMQ的博客都是基于二者 一.什么是RabbitMQ RabbitMQ是开源代理和队 ...
- RabbitMQ系列二(构建消息队列)
从AMQP协议可以看出,MessageQueue.Exchange和Binding构成了AMQP协议的核心.下面我们就围绕这三个主要组件,从应用使用的角度全面的介绍如何利用RabbitMQ构建消息队列 ...
- 【js基础】创建对象的几种常见模式(工厂模式,构造函数模式,原型模式,构造原型组合模式)
一.工厂模式 缺点:没有解决对象识别的问题 优点:解决了创建多个相似对象的问题 function createPerson(name,age,job){ var o = new Object(); o ...
- rabbitmq系列二 之工作队列
---恢复内容开始--- 1.工作队列的简介 在上一篇中,我们已经写了一个从已知队列中发送和获取消息的程序,在这里,我们创建一个工作队列(work queue), 会发送一些耗时的任务给多个工作者.模 ...
- robot framework接口测试之二-四种常见的POST提交数据方式
写接口测试用例时,遇到以json格式提交数据时,报错,Request如下图: Response如下图: 改成form格式提交,可以正常运行,如下图: 代码如下: ------------------- ...
- RabbitMQ学习系列(四): 几种Exchange 模式
上一篇,讲了RabbitMQ的具体用法,可以看看这篇文章:RabbitMQ学习系列(三): C# 如何使用 RabbitMQ.今天说些理论的东西,Exchange 的几种模式. AMQP协议中的核心思 ...
随机推荐
- HDU 1698 Just a Hook 线段树区间更新、
来谈谈自己对延迟标记(lazy标记)的理解吧. lazy标记的主要作用是尽可能的降低时间复杂度. 这样说吧. 如果你不用lazy标记,那么你对于一个区间更新的话是要对其所有的子区间都更新一次,但如果用 ...
- 安装 NodeJ Koa2、3 + 独立插件 cli脚手架 npm cnpm Vue
安装 NodeJ npm cnpm Koa2.3 + 独立插件 cli脚手架 Vue 安装 在 这里写过了 这两个分开了写 Nodej:下载 node.js 安装 10.0版 ...
- 11-28-----vertor和list使用场景
1.vector拥有一段连续的内存空间,因此支持随机访问,如果需要高效的随机访问,而不子啊胡插入和删除的效率,使用vector, 2.list拥有一段不连续的内存空间,如果需要高效的插入和删除,而不关 ...
- 2018.12.7 浪在ACM 集训队第八次测试赛
2018.12.7 浪在ACM 集训队第八次测试赛 https://blog.csdn.net/QLU_minoz/article/details/84886717 感谢苗学林同学C题和D题题解 ...
- dotnet Framework 源代码 类库的意思
本文告诉大家 dotnet framework 的源代码类库的意思 下面列出来 dotnet framework 源代码的各个类库的作用. System System 命名空间包含基本类和基类,这些类 ...
- 【37.48%】【hdu 2587】How far away ?(3篇文章,3种做法,LCA之Tarjan算法)
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Total Submission(s) ...
- 2018-2-13-win10-uwp-listView-绑定前一项
title author date CreateTime categories win10 uwp listView 绑定前一项 lindexi 2018-2-13 17:23:3 +0800 201 ...
- dotnet 通过 WMI 获取系统补丁
本文告诉大家如何通过 WMI 获取补丁 通过 Win32_QuickFixEngineering 可以获取系统启动的服务 下面代码只是获取补丁的 kb 字符 const string query = ...
- PostgreSQL 遇到 column "value" does not exist
初次使用PostgreSQL,在执行插入语句的时候死活插入不进去数据 INSERT INTO pre_trait ( archive_id, apply_from, owner_area_code ) ...
- Mybatis的mapper.xml文件详解
1.#{}和${}的区别: #{}表示一个占位符号,#{}接收输入参数,类型可以是简单类型,pojo.hashmap. 如果接收简单类型,#{}中可以写成value或其它名称. ...