喵星之旅-狂奔的兔子-rabbitmq的java客户端使用入门
一、简介
RabbitMQ是实现了高级消息队列协议(AMQP)的开源消息代理软件(亦称面向消息的中间件)。
消息队列都涉及的生产者消费者模型,不做详解,本文只作为快速使用的参考文档。
消息队列主要有点对点和发布订阅模式。
其主要用途是异步、削峰,充当一个缓存的作用。只有可以异步处理时才可以使用消息队列。
官方参考文档地址:
https://www.rabbitmq.com/getstarted.html
需要添加jar包:
amqp-client-3.5.6.jar hamcrest-core-1.3.jar
本文jdk版本1.8。
二、直接使用队列
1、简单队列
特点是生产者消费者一一对应。
生产者一般效率很高,生产者很低,所以一一对应是不对的。所以这个一般不使用。
其结构如图所示:

先创建一个工具类:
package com.bunny.rabbit;
/**
*
* @author bunny~~我是兔子我会喵,我叫喵星兔。
* 连接工具类
*/ import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory; public class LianjieGongjulei {
public static final String SIMPLE_QUEUE_NAME = "simplequeue";
public static final String WORK_QUEUE_NAME = "workqueue";
public static final String PUBSUB_EXCHANGE_NAME = "pubsubexchange";
public static final String ROUTING_EXCHANGE_NAME = "routingexchange";
public static final String TOPIC_EXCHANGE_NAME = "topicexchange";
public static final String PUBSUB_QUEUE_NAME1 = "pubsubqueue1";
public static final String PUBSUB_QUEUE_NAME2 = "pubsubqueue2";
public static final String ROUTING_QUEUE_NAME1 = "routingqueue1";
public static final String ROUTING_QUEUE_NAME2 = "routingqueue2";
public static final String TOPIC_QUEUE_NAME1 = "topicqueue1";
public static final String TOPIC_QUEUE_NAME2 = "topicqueue2"; public static Connection getConnection() {
try {
ConnectionFactory cf = new ConnectionFactory();
cf.setHost("127.0.0.1");
cf.setPort();
cf.setVirtualHost("/mybunny");
cf.setUsername("bunny");
cf.setPassword("bunny");
return cf.newConnection();
} catch (Exception e) {
e.printStackTrace();
}
return null;
} }
生产者:
package com.bunny.rabbit.simple; import java.io.IOException; import com.bunny.rabbit.LianjieGongjulei;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection; /**
*
* @author bunny~~我是兔子我会喵,我叫喵星兔。
* 简单队列生产者
*/
public class Shengchanzhe {
public static void main(String[] args) throws Exception {
Connection c = LianjieGongjulei.getConnection();
Channel ch = c.createChannel();
//如果已经存在,可以不声明,声明的话也没错。所以不管是否存在都可以声明。
ch.queueDeclare(LianjieGongjulei.SIMPLE_QUEUE_NAME, false, false, false, null); String mes = "Hello Kitty!";
ch.basicPublish("", LianjieGongjulei.SIMPLE_QUEUE_NAME, null, mes.getBytes());
System.out.println(" bunny Sent '" + mes + "'"); ch.close();
c.close(); }
}
消费者:
package com.bunny.rabbit.simple; import java.io.IOException; import com.bunny.rabbit.LianjieGongjulei;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.QueueingConsumer; /**
*
* @author bunny~~我是兔子我会喵,我叫喵星兔。
* 简单队列消费者
*/
public class Xiaofeizhe {
public static void main(String[] args) throws Exception {
Connection c = LianjieGongjulei.getConnection();
Channel ch = c.createChannel();
//如果已经存在,可以不声明,声明的话也没错。所以不管是否存在都可以声明。
ch.queueDeclare(LianjieGongjulei.SIMPLE_QUEUE_NAME, false, false, false, null); // 定义消费者
QueueingConsumer consumer = new QueueingConsumer(ch);
ch.basicConsume(LianjieGongjulei.SIMPLE_QUEUE_NAME, true, consumer); // 获取消息
while (true) {
QueueingConsumer.Delivery delivery = consumer.nextDelivery();
String message = new String(delivery.getBody());
System.out.println(" bunny Received '" + message + "'");
} }
}
2、work队列
手工确认则会按照消费端的能力进行分发(公平分发),否则是按照生产者的规则分发(轮询)。
一个消费者队列可以有多个消费者实例,只有其中一个消费者实例会消费。
如图所示:

生产者:
package com.bunny.rabbit.work; import com.bunny.rabbit.LianjieGongjulei;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection; /**
*
* @author bunny~~我是兔子我会喵,我叫喵星兔。
*
*/
public class Shengchanzhe {
public static void main(String[] args) throws Exception {
Connection c = LianjieGongjulei.getConnection();
Channel ch = c.createChannel();
ch.queueDeclare(LianjieGongjulei.WORK_QUEUE_NAME, false, false, false, null);
for (int i = ; i < ; i++, Thread.sleep()) {
String mes = "kitty" + i;
ch.basicPublish("", LianjieGongjulei.WORK_QUEUE_NAME, null, mes.getBytes());
System.out.println(" bunny Sent '" + mes + "'");
}
ch.close();
c.close();
}
}
消费者1:
package com.bunny.rabbit.work; import com.bunny.rabbit.LianjieGongjulei;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.DefaultConsumer;
import com.rabbitmq.client.QueueingConsumer; /**
*
* @author bunny~~我是兔子我会喵,我叫喵星兔。
*
*/
public class Xiaofeizhe1 {
public static void main(String[] args) throws Exception {
Connection c = LianjieGongjulei.getConnection();
Channel ch = c.createChannel();
ch.queueDeclare(LianjieGongjulei.WORK_QUEUE_NAME, false, false, false, null); QueueingConsumer consumer = new QueueingConsumer(ch);
// 监听队列,false表示手动返回完成状态,true表示自动
ch.basicConsume(LianjieGongjulei.WORK_QUEUE_NAME, true, consumer); while (true) {
QueueingConsumer.Delivery delivery = consumer.nextDelivery();
String message = new String(delivery.getBody());
System.out.println(" kitty Received '" + message + "'");
Thread.sleep(); } }
}
消费者2:
package com.bunny.rabbit.work; import java.io.IOException; import com.bunny.rabbit.LianjieGongjulei;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.QueueingConsumer; /**
*
* @author bunny~~我是兔子我会喵,我叫喵星兔。
*
*/
public class Xiaofeizhe2 {
public static void main(String[] args) throws Exception {
Connection c = LianjieGongjulei.getConnection();
Channel ch = c.createChannel();
ch.queueDeclare(LianjieGongjulei.WORK_QUEUE_NAME, false, false, false, null); //手工确认用
ch.basicQos(); // 定义队列的消费者
QueueingConsumer consumer = new QueueingConsumer(ch);
// 监听队列,false表示手动返回完成状态,true表示自动
ch.basicConsume(LianjieGongjulei.WORK_QUEUE_NAME, false, consumer); while (true) {
QueueingConsumer.Delivery delivery = consumer.nextDelivery();
String message = new String(delivery.getBody());
System.out.println(" bunny Received '" + message + "'"); Thread.sleep();
// 表示手动返回完成状态,如果没有下面的一行,将只能获取到上面ch.basicQos(1)里面写的数量
ch.basicAck(delivery.getEnvelope().getDeliveryTag(), false);
} }
}
三、通过交换机
1、发布订阅
1个生产者,多个消费者。
每一个消费者都有自己的一个队列。
生产者没有将消息直接发送到队列,而是发送到了交换机。
每个队列都要绑定到交换机。
生产者发送的消息,经过交换机,到达队列,实现一个消息被多个消费者获取的目的。
消息发送到没有队列绑定的交换机时,消息将丢失,因为,交换机没有存储消息的能力,消息只能存在在队列中。
如图:


生产者:
package com.bunny.rabbit.pubsub; import com.bunny.rabbit.LianjieGongjulei;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
/**
*
* @author bunny~~我是兔子我会喵,我叫喵星兔。
*
*/
public class Fabuzhe { public static void main(String[] args) throws Exception {
Connection c = LianjieGongjulei.getConnection();
Channel ch = c.createChannel();
//交换器的类型,常见的有direct,fanout,topic等,其中“fanout”是发布订阅
ch.exchangeDeclare(LianjieGongjulei.PUBSUB_EXCHANGE_NAME, "fanout");
String mes = "发布订阅信息";
ch.basicPublish(LianjieGongjulei.PUBSUB_EXCHANGE_NAME, "", null, mes.getBytes());
System.out.println(" pubsub Sent '" + mes + "'");
ch.close();
c.close(); } }
消费者1:
package com.bunny.rabbit.pubsub; import com.bunny.rabbit.LianjieGongjulei;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.QueueingConsumer;
/**
*
* @author bunny~~我是兔子我会喵,我叫喵星兔。
*
*/
public class Dingyuezhe1 {
public static void main(String[] args) throws Exception {
Connection c = LianjieGongjulei.getConnection();
Channel ch = c.createChannel();
ch.queueDeclare(LianjieGongjulei.PUBSUB_QUEUE_NAME1, false, false, false, null); // 绑定队列到交换机
ch.queueBind(LianjieGongjulei.PUBSUB_QUEUE_NAME1, LianjieGongjulei.PUBSUB_EXCHANGE_NAME, ""); // 监听队列,手动返回完成
ch.basicQos();
QueueingConsumer consumer = new QueueingConsumer(ch);
// 监听队列,手动返回完成
ch.basicConsume(LianjieGongjulei.PUBSUB_QUEUE_NAME1, false, consumer); while (true) {
QueueingConsumer.Delivery delivery = consumer.nextDelivery();
String mes = new String(delivery.getBody());
System.out.println(" 订阅者1 Received '" + mes + "'");
Thread.sleep();
// 监听队列,手动返回完成
ch.basicAck(delivery.getEnvelope().getDeliveryTag(), false);
} }
}
消费者2:
package com.bunny.rabbit.pubsub; import java.io.IOException; import com.bunny.rabbit.LianjieGongjulei;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.QueueingConsumer;
/**
*
* @author bunny~~我是兔子我会喵,我叫喵星兔。
*
*/
public class Dingyuezhe2 {
public static void main(String[] args) throws Exception {
Connection c = LianjieGongjulei.getConnection();
Channel ch = c.createChannel();
ch.queueDeclare(LianjieGongjulei.PUBSUB_QUEUE_NAME2, false, false, false, null); // 绑定队列到交换机
ch.queueBind(LianjieGongjulei.PUBSUB_QUEUE_NAME2, LianjieGongjulei.PUBSUB_EXCHANGE_NAME, ""); // 监听队列,手动返回完成
ch.basicQos();
QueueingConsumer consumer = new QueueingConsumer(ch);
// 监听队列,手动返回完成
ch.basicConsume(LianjieGongjulei.PUBSUB_QUEUE_NAME2, false, consumer); while (true) {
QueueingConsumer.Delivery delivery = consumer.nextDelivery();
String mes = new String(delivery.getBody());
System.out.println(" 订阅者2 Received '" + mes + "'");
Thread.sleep();
// 监听队列,手动返回完成
ch.basicAck(delivery.getEnvelope().getDeliveryTag(), false);
} }
}
2、路由模式
在前面基础上,改变交换机类型,添加key信息。
如图:


生产者:
package com.bunny.rabbit.routing; import com.bunny.rabbit.LianjieGongjulei;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
/**
*
* @author bunny~~我是兔子我会喵,我叫喵星兔。
*
*/
public class Fabuzhe { public static void main(String[] args) throws Exception {
Connection c = LianjieGongjulei.getConnection();
Channel ch = c.createChannel();
//交换器的类型,常见的有direct,fanout,topic等,其中“direct”是路由
ch.exchangeDeclare(LianjieGongjulei.ROUTING_EXCHANGE_NAME, "direct");
String mes1 = "路由直连信息1";
String mes2 = "路由直连信息2";
//第二个参数是消息key用于路由用
ch.basicPublish(LianjieGongjulei.ROUTING_EXCHANGE_NAME, "meskey1", null, mes1.getBytes());
ch.basicPublish(LianjieGongjulei.ROUTING_EXCHANGE_NAME, "meskey2", null, mes2.getBytes());
System.out.println(" pubsub Sent '" + mes1 + "'");
System.out.println(" pubsub Sent '" + mes2 + "'");
ch.close();
c.close(); } }
消费者1:
package com.bunny.rabbit.routing; import com.bunny.rabbit.LianjieGongjulei;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.QueueingConsumer;
/**
*
* @author bunny~~我是兔子我会喵,我叫喵星兔。
*
*/
public class Dingyuezhe1 {
public static void main(String[] args) throws Exception {
Connection c = LianjieGongjulei.getConnection();
Channel ch = c.createChannel();
ch.queueDeclare(LianjieGongjulei.ROUTING_QUEUE_NAME1, false, false, false, null); // 绑定队列到交换机,第三个参数是key
ch.queueBind(LianjieGongjulei.ROUTING_QUEUE_NAME1, LianjieGongjulei.ROUTING_EXCHANGE_NAME, "meskey1");
ch.queueBind(LianjieGongjulei.ROUTING_QUEUE_NAME1, LianjieGongjulei.ROUTING_EXCHANGE_NAME, "meskey2"); // 监听队列,手动返回完成
ch.basicQos();
QueueingConsumer consumer = new QueueingConsumer(ch);
// 监听队列,手动返回完成
ch.basicConsume(LianjieGongjulei.ROUTING_QUEUE_NAME1, false, consumer); while (true) {
QueueingConsumer.Delivery delivery = consumer.nextDelivery();
String mes = new String(delivery.getBody());
System.out.println(" 订阅者1 Received '" + mes + "'");
Thread.sleep();
// 监听队列,手动返回完成
ch.basicAck(delivery.getEnvelope().getDeliveryTag(), false);
} }
}
消费者2:
package com.bunny.rabbit.routing; import java.io.IOException; import com.bunny.rabbit.LianjieGongjulei;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.QueueingConsumer;
/**
*
* @author bunny~~我是兔子我会喵,我叫喵星兔。
*
*/
public class Dingyuezhe2 {
public static void main(String[] args) throws Exception {
Connection c = LianjieGongjulei.getConnection();
Channel ch = c.createChannel();
ch.queueDeclare(LianjieGongjulei.ROUTING_QUEUE_NAME2, false, false, false, null); // 绑定队列到交换机
ch.queueBind(LianjieGongjulei.ROUTING_QUEUE_NAME2, LianjieGongjulei.ROUTING_EXCHANGE_NAME, "meskey1"); // 监听队列,手动返回完成
ch.basicQos();
QueueingConsumer consumer = new QueueingConsumer(ch);
// 监听队列,手动返回完成
ch.basicConsume(LianjieGongjulei.ROUTING_QUEUE_NAME2, false, consumer); while (true) {
QueueingConsumer.Delivery delivery = consumer.nextDelivery();
String mes = new String(delivery.getBody());
System.out.println(" 订阅者2 Received '" + mes + "'");
Thread.sleep();
// 监听队列,手动返回完成
ch.basicAck(delivery.getEnvelope().getDeliveryTag(), false);
} }
}
3、主题模式
在路由基础上,模糊匹配。至于匹配规则,简单来说就是*代表一个单词,#代表多个单词。单词指的是字符串被“.”分割的部分。可以实际操作之后观察结果。
如图:


生产者:
package com.bunny.rabbit.topic; import com.bunny.rabbit.LianjieGongjulei;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
/**
*
* @author bunny~~我是兔子我会喵,我叫喵星兔。
*
*/
public class Fabuzhe { public static void main(String[] args) throws Exception {
Connection c = LianjieGongjulei.getConnection();
Channel ch = c.createChannel();
//交换器的类型,常见的有direct,fanout,topic等,其中“direct”是路由
ch.exchangeDeclare(LianjieGongjulei.TOPIC_EXCHANGE_NAME, "topic");
String mes1 = "主题信息1";
String mes2 = "主题信息2";
String mes3 = "主题信息3";
String mes4 = "主题信息4";
//第二个参数是消息key用于路由用
ch.basicPublish(LianjieGongjulei.TOPIC_EXCHANGE_NAME, "mes.key.bunny", null, mes1.getBytes());
ch.basicPublish(LianjieGongjulei.TOPIC_EXCHANGE_NAME, "bunny", null, mes2.getBytes());
ch.basicPublish(LianjieGongjulei.TOPIC_EXCHANGE_NAME, "mes", null, mes3.getBytes());
ch.basicPublish(LianjieGongjulei.TOPIC_EXCHANGE_NAME, "key.ee", null, mes4.getBytes());
System.out.println(" topic Sent '" + mes1 + "'");
System.out.println(" topic Sent '" + mes2 + "'");
System.out.println(" topic Sent '" + mes3 + "'");
System.out.println(" topic Sent '" + mes4 + "'");
ch.close();
c.close(); } }
消费者1:
package com.bunny.rabbit.topic; import com.bunny.rabbit.LianjieGongjulei;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.QueueingConsumer;
/**
*
* @author bunny~~我是兔子我会喵,我叫喵星兔。
*
*/
public class Dingyuezhe1 {
public static void main(String[] args) throws Exception {
Connection c = LianjieGongjulei.getConnection();
Channel ch = c.createChannel();
ch.queueDeclare(LianjieGongjulei.TOPIC_QUEUE_NAME1, false, false, false, null); // 绑定队列到交换机,第三个参数是key
ch.queueBind(LianjieGongjulei.TOPIC_QUEUE_NAME1, LianjieGongjulei.TOPIC_EXCHANGE_NAME, "*");
ch.queueBind(LianjieGongjulei.TOPIC_QUEUE_NAME1, LianjieGongjulei.TOPIC_EXCHANGE_NAME, "mes.#"); // 监听队列,手动返回完成
ch.basicQos();
QueueingConsumer consumer = new QueueingConsumer(ch);
// 监听队列,手动返回完成
ch.basicConsume(LianjieGongjulei.TOPIC_QUEUE_NAME1, false, consumer); while (true) {
QueueingConsumer.Delivery delivery = consumer.nextDelivery();
String mes = new String(delivery.getBody());
System.out.println(" 订阅者1 Received '" + mes + "'");
Thread.sleep();
// 监听队列,手动返回完成
ch.basicAck(delivery.getEnvelope().getDeliveryTag(), false);
} }
}
消费者2:
package com.bunny.rabbit.topic; import java.io.IOException; import com.bunny.rabbit.LianjieGongjulei;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.QueueingConsumer;
/**
*
* @author bunny~~我是兔子我会喵,我叫喵星兔。
*
*/
public class Dingyuezhe2 {
public static void main(String[] args) throws Exception {
Connection c = LianjieGongjulei.getConnection();
Channel ch = c.createChannel();
ch.queueDeclare(LianjieGongjulei.TOPIC_QUEUE_NAME2, false, false, false, null); // 绑定队列到交换机
ch.queueBind(LianjieGongjulei.TOPIC_QUEUE_NAME2, LianjieGongjulei.TOPIC_EXCHANGE_NAME, "#"); // 监听队列,手动返回完成
ch.basicQos();
QueueingConsumer consumer = new QueueingConsumer(ch);
// 监听队列,手动返回完成
ch.basicConsume(LianjieGongjulei.TOPIC_QUEUE_NAME2, false, consumer); while (true) {
QueueingConsumer.Delivery delivery = consumer.nextDelivery();
String mes = new String(delivery.getBody());
System.out.println(" 订阅者2 Received '" + mes + "'");
Thread.sleep();
// 监听队列,手动返回完成
ch.basicAck(delivery.getEnvelope().getDeliveryTag(), false);
} }
}
四、总结
队列中数据只会被处理一次,交换机的数据处理次数和发送的队列有关。所以针对消息队列而言,交换机不是必须的。
每一个消息队列中的数据只会被消费一次。交换机把数据发到几个队列,那么数据就应该被消费几次,完全取决于队列数量。
上面的所有涉及路由的都只有一个消费者对应一个队列,其实都可以是多个消费者对应一个队列。
无论是生产者还是消费者,创建队列和交换机、队列和交换机的绑定,这些操作都是一次性的,如果第二次运行会发现已经处理了就不需要作。同样的,改变代码后并没有解除之前的设置、绑定等。不会因为有创建命令就重新创建。所以如果一个交换机开始设置成路由,那么代码修改为topic将会失败。
上面任何一步使用队列或者交换机,如果之前没创建,将会报错,这就意味着上面的代码有执行顺序。但是按照不报错的执行也不行,因为有些没效果,可以考虑先从头到尾执行一遍,无视错误。然后把运行中的终端关掉,这样环境就准备好了。然后在运行查看结果。
ps:项目地址 svn://47.105.188.20/kitty/2%E3%80%81code/rabbitclient 用户名密码:reader/reader
喵星之旅-狂奔的兔子-rabbitmq的java客户端使用入门的更多相关文章
- 喵星之旅-狂奔的兔子-基于docker的rabbitmq安装
docker安装参考:喵星之旅-狂奔的兔子-docker安装和基本使用 一.查询镜像名称 由于我们要安装的是有web管理页面的,不能直接拉取,需要指定版本. 登录docker仓库查询:https:// ...
- 喵星之旅-狂奔的兔子-docker安装和基本使用
一.前提条件 目前,CentOS 仅发行版本中的内核支持 Docker. 位.系统内核版本为 3.10 以上. 位系统.参考喵星之旅-狂奔的兔子-linux安装 二.CentOS 7下安装 Doc ...
- 喵星之旅-狂奔的兔子-myeclipse搭建ssm
. 可以使用试用期限内的myeclipse,也可以找到有授权的机器进行操作.搭建好的项目框架可以直接移植到免费软件eclipse使用.或者直接购买myeclipse授权. 一.创建一个java web ...
- 喵星之旅-狂奔的兔子-centos7一键安装redmine
一.安装环境 CentOS-7-x86_64-DVD-1908.iso 二.获取安装文件 从官网获取,在下载页面提供了多种安装,最下方是一键安装版本,里面有两种选择,一个是安装包,一个是虚拟机硬盘文件 ...
- 喵星之旅-狂奔的兔子-centos7安装MySQL 5.5
安装环境:https://www.cnblogs.com/kittybunny/p/12296078.html 一.下载安装文件 下载地址 https://downloads.mysql.com/ar ...
- 喵星之旅-狂奔的兔子-linux安装
一.前言 本文演示虚拟机安装,和真机区别可能在网卡驱动上有差异. 真机环境:CentOS Linux release 7.6.1810 (Core) 虚拟机(虽然centos系统自带虚拟机软件,但是习 ...
- 喵星之旅-狂奔的兔子-redis使用
一.命令行使用 redis大概有200多命令,这里只是入门级别,列举了一些非常常见的内容,如果这些会了就可以开启redis进一步学习了. 1.登录数据库 我们需要知道ip地址.端口号.密码(如果有). ...
- 喵星之旅-狂奔的兔子-svn安装及使用
一.服务端安装配置 1.安装svn 创建版本库并配置 以root用户登录,或者具有sudo权限的用户,这里选择root. yum install subversion 都选择y 2.创建版本库并配置 ...
- 喵星之旅-狂奔的兔子-redis安装
一.前置条件 服务器版本CentOS-8-x86_64-1905-dvd1,在此版本上安装最新版redis.centos7以上版本都可以,不建议6以前的版本. 二.下载redis,并上传到服务器 登录 ...
随机推荐
- DES加密算法 转
1.什么是对称密码算法 网络安全通信中要用到两类密码算法,一类是对称密码算法,另一类是非对称密码算法.对称密码算法有时又叫传统密码算法.秘密密钥算法或单密钥算法,非对称密码算法也叫公开密钥密码算法或双 ...
- 更新centos本地仓库(换源)
/etc/yum.repos.d/CentOS-Base.repo 1,首先进行备份 mv /etc/yum.repos.d/CentOS-Base.repo /etc/yum.repos.d/Cen ...
- WebViewJavascriptBridge(H5与原生交互)
https://github.com/wangjiaojiao77/WebViewJavascriptBridge(IOS)和 https://github.com/wangjiaojiao77/Js ...
- Codeforces Round #611 (Div. 3) A-F简要题解
contest链接:https://codeforces.com/contest/1283 A. Minutes Before the New Year 题意:给一个当前时间,输出离第二天差多少分钟 ...
- jsonp实现js跨域请求
sonp是跨域通信的一个协议 具体来说jsonp实现跨域请求其实是使用js文件引用(js文件不一定是.js结尾)可跨域的性质,将请求的结果包裹在客户端需要调用的js方法内部.需要前后端配合使用. 前段 ...
- 给html元素添加自定义属性,并且用jquery进行筛选
例如有多个div,想要实现类似radio的效果. <div name="teacher" selected="selected">tch1</ ...
- quartus 9.0 对话框显示不完整
今天在quartus9.0新建SOPC build时,发现在添加PLL时对话框太大,笔记本分辨率差,导致结束和next不能选择: 解决: 如果电脑分辨率可以调整为合适的,就去调整: 现在介绍分辨率不合 ...
- 数位DP 不要62
数位DP的问法是从某个数到某个数的区间里,求出满足题目要求的个数: 如本题所说的不要62和4,就是求出这个区间内,满足这一条件的数: 比如问 6 199的这个区间内满足条件的数,那么就求出1到199满 ...
- 题解【洛谷P1938】 [USACO09NOV]找工就业Job Hunt
题面 题解 将路径连边\((x, y, d)\) ,将航线连边\((x, y, d - w)\).其中线路是从\(x\)到\(y\),航线的费用为\(w\),\(d\)的含义如题面. 跑一遍\(SPF ...
- PHP中spl_autoload_register()函数用法实例详解
本文实例分析了PHP中spl_autoload_register()函数用法.分享给大家供大家参考,具体如下: 在了解这个函数之前先来看另一个函数:__autoload. 一.__autoload 这 ...