hello, 大家好
我是一只不是在戏精,就是在戏精路上的极品二哈
新年上班第一天,给大家贡献一篇 MQTT 协议使用示例文章
也是本汪自己的一篇实用笔记

本汪先总的说下: MQTT协议进行数据交互,一共有两种方式:第一种,请求时不带任何参数的,走上报订阅,设备直接往服务器上传,我们只需要在程序里订阅固定的主题,就可以接收到实时数据,然后进行解析入库就行(比如后面的接收道闸小门的人员上报打卡实时记录);第二种, 有查询条件的,走下发订阅,请求时把查询条件下发给主题 report1,接收对应数据时,监听对应的主题request1,拿到符合查询条件的数据后进行处理(比如人脸数据下发和根据时间段查询人员打卡记录) report/aaa -> request/aaa,都是一一对应的哈。

一、MQTT 服务安装
windows安装包:
链接:https://pan.baidu.com/s/1wb7yNCeCRbjKxauigoaHHQ
提取码:pswp
解压后直接运行即可:

在服务中,可以看到对应的 MQTT 服务

二、MQTT 调用程序

1、 基本原理RRPC 请求消息: 服务器通过 MQTT 下发给设备端的消息;RRPC 响应消息: 设备端通过 MQTT 回复给服务器的消息;RRPC 消息 ID: 服务器为每次 RRPC 调用生成的唯一消息 ID;RRPC 订阅 Topic: 设备端以及服务器订阅 RRPC 消息时传递的 Topic,含有通配符。2、推荐使用的MQTT 测试工具 MQTT.fx ,MQTT.fx 是一个老牌的 MQTT 客户端工具,Azure IoT Hub、AWS IoT、阿里云 IoT 等云服务提供商相关产品文档教程均以 MQTT.fx 为例。个人感觉简洁好用。
官网下载地址:https://mqttfx.jensd.de/index.php/download
本汪使用的是1.7.1,云盘地址:
链接:https://pan.baidu.com/s/1anp7PCgfq3EiCPvuaBD77Q
提取码:66w7

3、添加MQTT订阅
在Web管理后台的 设备管理 → HTTP/MQTT订阅 菜单,点击创建按钮,如下图所示。

然后填写上报MQTT服务器的地址和主题。如下图所示:

项目 填写参考示例
上报方式 MQTT
上报地址 tcp://:@:
MQTT topic <topic_name>/<设备ID>/report
是否启用 勾选
是否上报历史记录 不勾选
是否上传图片 勾选

该教程中设备的ID为5182618e-caaf-45ca-81d5-ae5dce6f8e9f,则MQTT topic为<topic_name>/5182618e-caaf-45ca-81d5-ae5dce6f8e9f/report。
其他字段如、、、和<topic_name>,需要根据MQTT服务器实际情况填写。

4、示例代码:
(1)MQTT 网关, common中的常量

package com.cccc.common.constant;public class DeviceConstants {public static final String GET_DEVICE_INFORMATION = "getDeviceInformation/ba3ec3e4-2e1f-4e8d-9ff8-e0235f6e1f41/request/abc";public static final String OPEN_THE_DOOR = "openTheDoor/ba3ec3e4-2e1f-4e8d-9ff8-e0235f6e1f41/report";public static final String LIST_PEOPLE_INFORMATION_BY_ID =  "listPeopleInformationById/ba3ec3e4-2e1f-4e8d-9ff8-e0235f6e1f41/report";public static final String SELECT_PEOPLE_INFORMATION_BY_FIELD = "selectPeopleInformationByField/ba3ec3e4-2e1f-4e8d-9ff8-e0235f6e1f41/report";public static final String INSERT_PEOPLE = "insertPeople/ba3ec3e4-2e1f-4e8d-9ff8-e0235f6e1f41/request/abc";public static final String ADD_BATCH = "addbatch/ba3ec3e4-2e1f-4e8d-9ff8-e0235f6e1f41/report";public static final String DELETE = "delete/ba3ec3e4-2e1f-4e8d-9ff8-e0235f6e1f41/report";public static final String DELETE_BATCH =  "deleteBatch/ba3ec3e4-2e1f-4e8d-9ff8-e0235f6e1f41/report";public static final String GET_CARD_RECORD =  "getCardRecord/ba3ec3e4-2e1f-4e8d-9ff8-e0235f6e1f41/request/abc";}
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import org.springframework.integration.annotation.MessagingGateway;
import org.springframework.integration.mqtt.support.MqttHeaders;
import org.springframework.messaging.handler.annotation.Header;/*** @ Author: yuezejian* @ Description:* @ Date: 2021/12/14 11:25*/
@MessagingGateway(defaultRequestChannel = "mqttOutboundChannel")
public interface MqttGateway {// 定义重载方法,用于消息发送void sendToMqtt(String payload);// 指定topic进行消息发送void sendToMqtt(@Header(MqttHeaders.TOPIC) String topic, String payload);void sendToMqtt(@Header(MqttHeaders.TOPIC) String topic, @Header(MqttHeaders.QOS) int qos, String payload);void sendToMqtt(@Header(MqttHeaders.TOPIC) String topic, @Header(MqttHeaders.QOS) int qos, byte[] payload);
}

(2)MQTT config

package com.cccc.framework.config;import com.cccc.common.constant.DeviceConstants;
import org.eclipse.paho.client.mqttv3.MqttConnectOptions;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.integration.annotation.ServiceActivator;
import org.springframework.integration.channel.DirectChannel;
import org.springframework.integration.core.MessageProducer;
import org.springframework.integration.mqtt.core.DefaultMqttPahoClientFactory;
import org.springframework.integration.mqtt.core.MqttPahoClientFactory;
import org.springframework.integration.mqtt.inbound.MqttPahoMessageDrivenChannelAdapter;
import org.springframework.integration.mqtt.outbound.MqttPahoMessageHandler;
import org.springframework.integration.mqtt.support.DefaultPahoMessageConverter;
import org.springframework.messaging.MessageChannel;
import org.springframework.messaging.MessageHandler;/*** @Description: 订阅并监听MQTT消息,进行相应的处理* @Author: yuezejian* @Date: 2021/12/14 11:22* @Version: 1.0**/
@Configuration
public class MQTTConfig {private static final Logger LOG = LoggerFactory.getLogger(MQTTConfig.class);/*** 创建MqttPahoClientFactory,设置MQTT Broker连接属性,如果使用SSL验证,也在这里设置。* @return factory*/@Beanpublic MqttPahoClientFactory mqttClientFactory() {DefaultMqttPahoClientFactory factory = new DefaultMqttPahoClientFactory();MqttConnectOptions options = new MqttConnectOptions();// 设置代理端的URL地址,可以是多个options.setServerURIs(new String[]{"tcp://192.168.20.48:1883"});factory.setConnectionOptions(options);return factory;}/*** 入站通道*/@Beanpublic MessageChannel mqttInputChannel() {return new DirectChannel();}/*** 入站*/@Beanpublic MessageProducer inbound() {// Paho客户端消息驱动通道适配器,主要用来订阅主题MqttPahoMessageDrivenChannelAdapter adapter = new MqttPahoMessageDrivenChannelAdapter("consumerClient-paho",mqttClientFactory(), DeviceConstants.GET_DEVICE_INFORMATION,DeviceConstants.OPEN_THE_DOOR,DeviceConstants.LIST_PEOPLE_INFORMATION_BY_ID,DeviceConstants.SELECT_PEOPLE_INFORMATION_BY_FIELD,DeviceConstants.INSERT_PEOPLE,DeviceConstants.ADD_BATCH,DeviceConstants.DELETE,DeviceConstants.DELETE_BATCH,DeviceConstants.GET_DEVICE_INFORMATION);adapter.setCompletionTimeout(5000);// Paho消息转换器DefaultPahoMessageConverter defaultPahoMessageConverter = new DefaultPahoMessageConverter();// 按字节接收消息
//        defaultPahoMessageConverter.setPayloadAsBytes(true);adapter.setConverter(defaultPahoMessageConverter);adapter.setQos(1); // 设置QoSadapter.setOutputChannel(mqttInputChannel());return adapter;}@Bean// ServiceActivator注解表明:当前方法用于处理MQTT消息,inputChannel参数指定了用于消费消息的channel。@ServiceActivator(inputChannel = "mqttInputChannel")public MessageHandler handler() {return message -> {String payload = message.getPayload().toString();// byte[] bytes = (byte[]) message.getPayload(); // 收到的消息是字节格式String topic = message.getHeaders().get("mqtt_receivedTopic").toString();// 根据主题分别进行消息处理。if (topic.equals(DeviceConstants.GET_DEVICE_INFORMATION)) { // 匹配:1/sensorString sensorSn = "getDeviceInformation";LOG.debug("获取设备信息: " + payload);} else if (topic.equals(DeviceConstants.OPEN_THE_DOOR)) {LOG.debug("远程开门:" + payload);} else if (topic.equals(DeviceConstants.LIST_PEOPLE_INFORMATION_BY_ID)) {LOG.debug("根据ID查询录入人员" + payload);}  else if (topic.equals(DeviceConstants.SELECT_PEOPLE_INFORMATION_BY_FIELD)) {LOG.debug("根据录入信息字段,查询录入人员" + payload);}  else if (topic.equals(DeviceConstants.INSERT_PEOPLE)) {LOG.debug("新增人员录入" + payload);}  else if (topic.equals(DeviceConstants.ADD_BATCH)) {LOG.debug("批量添加人员" + payload);} else if (topic.equals(DeviceConstants.DELETE)) {LOG.debug("删除单个人员" + payload);} else if (topic.equals(DeviceConstants.DELETE_BATCH)) {LOG.debug("批量删除多个人员录入" + payload);} else if (topic.equals(DeviceConstants.GET_CARD_RECORD)) {LOG.debug("获取打卡记录" + payload);}};}// 发送消息/*** 出站通道*/@Beanpublic MessageChannel mqttOutboundChannel() {return new DirectChannel();}/*** 出站*/@Bean@ServiceActivator(inputChannel = "mqttOutboundChannel")public MessageHandler outbound() {// 发送消息和消费消息Channel可以使用相同MqttPahoClientFactoryMqttPahoMessageHandler messageHandler = new MqttPahoMessageHandler("publishClient", mqttClientFactory());messageHandler.setAsync(true); // 如果设置成true,即异步,发送消息时将不会阻塞。messageHandler.setDefaultTopic("command");messageHandler.setDefaultQos(1); // 设置默认QoS// Paho消息转换器DefaultPahoMessageConverter defaultPahoMessageConverter = new DefaultPahoMessageConverter();// defaultPahoMessageConverter.setPayloadAsBytes(true); // 发送默认按字节类型发送消息messageHandler.setConverter(defaultPahoMessageConverter);return messageHandler;}
}

(3)控制层,包括道闸小门门禁一体机人脸下发和获取打卡记录 2 个调用示例。


/*** @Description: 道闸小门门禁一体机数据交互控制层* @Author: yuezejian* @Date: 2021/12/14 11:28* @Version: 1.0**/
@RestController
@RequestMapping("/mqtt")
public class MqttController extends BaseController {@Autowiredprivate MqttGateway mqttGateway;@Autowiredprivate ICcccHealthyEquipmentinfoService ccccHealthyEquipmentinfoService;@Autowiredprivate Environment env;/*** 下发人脸* @return* @throws IOException*/@PostMapping("/send")public String send() throws IOException {// 发送消息到指定主题ccccHealthyEquipmentinfoService.insertPersionInformation(new DeviceDto(1,"face.set"));return "人脸批量新增" ;}/*** 获取道小门的打卡记录* @return* @throws IOException*/@PostMapping("/record")public String record() throws IOException {// 发送消息到指定主题ccccHealthyEquipmentinfoService.recordGet(new DeviceDto(2,"faceRecord.bulkGet"));return "获取打卡记录" ;}}

(4)服务层

/*** 设备信息Service接口* * @author jiezhaokai* @date 2021-12-20*/
public interface ICcccHealthyEquipmentinfoService
{/*** 闸道小门数据全员下发* @param deviceDto* @throws IOException*/public void insertPersionInformation(DeviceDto deviceDto) throws IOException;/*** get record from outdoor* @param deviceDto* @throws IOException*/public void recordGet(DeviceDto deviceDto) throws IOException;/*** 闸道小门数据下发通过用户id* @param deviceDto* @throws IOException*/public void insertPersionInformationByUserId(DeviceDto deviceDto, Long userId) throws IOException;}

(5)服务层具体实现

/*** 设备信息Service业务层处理* * @author jiezhaokai* @date 2021-12-20*/
@Service
public class CcccHealthyEquipmentinfoServiceImpl implements ICcccHealthyEquipmentinfoService
{/*** 闸道小门数据全员下发* @param deviceDto* @throws IOException*/@Overridepublic void insertPersionInformation(DeviceDto deviceDto) throws IOException {//查询员工//List<EmployeeUserNameAndJobNumberAndFaceImage>  faceImageList = ccccCheckonworkDeviceMapper.getEmployeeUserNameAndJobNumberAndFaceImage();faceImageList.forEach( i -> {if (StringUtils.isNotEmpty(i.getImageUrl()) && StringUtils.isNotEmpty(i.getJobNumber())&& StringUtils.isNotEmpty(i.getUserName()) && i.getCardNo() != null) {Image image = new Image();image.setType("URL");// 图片地址拼接image.setUrl("http://192.168.20.48:8088/prod-api/faceimage/faceRegisterImage/"+i.getImageUrl());PersonInformationDto personInformationDto = new PersonInformationDto();personInformationDto.setId(0);personInformationDto.setImage(image);personInformationDto.setTrdID(Integer.valueOf(i.getJobNumber().replaceAll("[a-zA-Z]","" )));personInformationDto.setName(i.getUserName());//赋值卡号if ( i.getCardNo()< 1000000000) {String cardNo = "0" +  i.getCardNo();personInformationDto.setAccessCardNo(cardNo);} else {String cardNo = i.getCardNo()+"";personInformationDto.setAccessCardNo(cardNo);}deviceDto.setParams(JSONObject.parseObject(JSONObject.toJSON(personInformationDto).toString()));MyMqttMessage myMqttMessage = new MyMqttMessage();myMqttMessage.setTopic(DeviceConstants.INSERT_PEOPLE);myMqttMessage.setContent(JSON.toJSONString(deviceDto));mqttGateway.sendToMqtt(myMqttMessage.getTopic(), 1, myMqttMessage.getContent());LOG.info("闸道小门人脸下发成功,ip为192.168.20.34, 员工名字为:"+ i.getUserName()+ ",员工工号为:"+ i.getJobNumber());try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}}});}/*** 获取道闸小门门禁一体机打卡记录* @param deviceDto* @throws IOException*/@Overridepublic void recordGet(DeviceDto deviceDto) throws IOException {RecordHistoryDto recordHistoryDto = new RecordHistoryDto();//每次获取当前时间前的两个小时内的数据,因此定时任务的执行时间也应当是没两小时执行一次String startDate = DateUtils.getDate() +"T"+ DateUtils.dateRoll(6) + ".32+08:00";String endDate = DateUtils.getDate() +"T"+ DateUtils.dateRoll(0)+ ".32+08:00";recordHistoryDto.setStartDate(startDate);recordHistoryDto.setEndDate(endDate);recordHistoryDto.setLimit(30);recordHistoryDto.setPage(1);recordHistoryDto.setSortBy("id");recordHistoryDto.setSortOrder("asc");recordHistoryDto.setWithImage(false);deviceDto.setParams((JSONObject)JSONObject.toJSON(recordHistoryDto));MyMqttMessage myMqttMessage = new MyMqttMessage();myMqttMessage.setTopic(DeviceConstants.GET_CARD_RECORD);myMqttMessage.setContent(JSON.toJSONString(deviceDto));System.out.println(myMqttMessage.toString());mqttGateway.sendToMqtt(myMqttMessage.getTopic(), 1, myMqttMessage.getContent());try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}}/*** 每次新增人脸记录时,对道闸小门的门禁一体机进行人脸下发。* @param deviceDto* @param userId* @throws IOException*/@Override@Async("threadPoolTaskExecutor1")public void insertPersionInformationByUserId(DeviceDto deviceDto, Long userId) throws IOException {//查询员工//List<EmployeeUserNameAndJobNumberAndFaceImage>  faceImageList = ccccCheckonworkDeviceMapper.getEmployeeUserNameAndJobNumberAndFaceImageByUserId(userId);//如果当前员工还没有卡号,则工号去掉字母,开头拼接0为其卡号,for example: SC9879 -> 09879if (faceImageList.get(0).getCardNo() == null) {faceImageList.get(0).setCardNo(Long.valueOf(faceImageList.get(0).getJobNumber().replaceAll("[a-zA-Z]","" )));}faceImageList.forEach( i -> {if (StringUtils.isNotEmpty(i.getImageUrl()) && StringUtils.isNotEmpty(i.getJobNumber())&& StringUtils.isNotEmpty(i.getUserName()) && i.getCardNo() != null) {Image image = new Image();image.setType("URL");// 图片地址拼接image.setUrl("http://192.168.20.48:8088/prod-api/faceimage/faceRegisterImage/"+i.getImageUrl());PersonInformationDto personInformationDto = new PersonInformationDto();personInformationDto.setId(0);personInformationDto.setImage(image);personInformationDto.setTrdID(Integer.valueOf(i.getJobNumber().replaceAll("[a-zA-Z]","" )));personInformationDto.setName(i.getUserName());//赋值卡号if ( i.getCardNo()< 1000000000) {String cardNo = "0" +  i.getCardNo();personInformationDto.setAccessCardNo(cardNo);} else {String cardNo = i.getCardNo()+"";personInformationDto.setAccessCardNo(cardNo);}deviceDto.setParams(JSONObject.parseObject(JSONObject.toJSON(personInformationDto).toString()));MyMqttMessage myMqttMessage = new MyMqttMessage();myMqttMessage.setTopic(DeviceConstants.INSERT_PEOPLE);myMqttMessage.setContent(JSON.toJSONString(deviceDto));mqttGateway.sendToMqtt(myMqttMessage.getTopic(), 1, myMqttMessage.getContent());try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}}});}
}

5、配置MQTT协议监听对应的主题


import com.alibaba.fastjson.JSONObject;
import com.cccc.business.duty.ondutyhistoryrecord.service.ICcccCheckonworkHistoryRecordService;
import com.cccc.common.core.domain.entity.SysUser;
import com.cccc.common.utils.StringUtils;
import com.cccc.framework.config.BeanWiredAdvice;
import com.cccc.system.mapper.SysUserMapper;
import com.google.gson.JsonObject;
import org.eclipse.paho.client.mqttv3.*;
import org.eclipse.paho.client.mqttv3.persist.MemoryPersistence;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.core.Ordered;
import org.springframework.core.env.Environment;
import org.springframework.stereotype.Component;import java.util.Date;/*** 道闸小门打卡记录监听,MQTT协议* @auth yuezejian*/
//@Component
public class MqttListener implements ApplicationRunner, Ordered {@Autowiredprivate Environment env;public static final Logger LOG = LoggerFactory.getLogger(MqttListener.class);/* 打卡历史记录的服务层 */ICcccCheckonworkHistoryRecordService ccccCheckonworkHistoryRecordService = BeanWiredAdvice.getBean(ICcccCheckonworkHistoryRecordService.class);private SysUserMapper sysUserMapper = BeanWiredAdvice.getBean(SysUserMapper.class);@Overridepublic void run(ApplicationArguments args) throws Exception {//MQTT协议前缀 urlFrontSuffix = tcp://:@192.168.20.48:1883String urlFrontSuffix = env.getProperty("barriergate.urlFrontSuffix", String.class);String clienId = String.valueOf(System.currentTimeMillis());System.out.println(clienId);//Topic前缀  allTopic = record/ba3ec3e4-2e1f-4e8d-9ff8-e0235f6e1f41/reportString allTopic = env.getProperty("barriergate.allTopic", String.class);try {MemoryPersistence memoryPersistence = new MemoryPersistence();MqttClient client = new MqttClient(urlFrontSuffix, clienId, memoryPersistence);MqttConnectOptions options = new MqttConnectOptions();// 设置客户端和服务器是否应在重新启动和重新连接期间记住状态 默认falseoptions.setCleanSession(true);// 设置会话心跳时间options.setKeepAliveInterval(20);// 设置超时时间options.setConnectionTimeout(10);// 设置回调函数,当订阅到信息时调用此方法client.setCallback(new MqttCallback() {@Overridepublic void connectionLost(Throwable throwable) {// 连接失败时调用  重新连接订阅try {System.out.println("开始重连");Thread.sleep(3000);client.connect(options);} catch (InterruptedException e) {e.printStackTrace();} catch (MqttSecurityException e) {e.printStackTrace();} catch (MqttException e) {e.printStackTrace();}}@Overridepublic void messageArrived(String s, MqttMessage mqttMessage) throws Exception {// 订阅成功,并接受信息时调用String payload = new String(mqttMessage.getPayload()); // 获取消息内容JSONObject pa=JSONObject.parseObject(payload);String person = pa.getString("person");if (StringUtils.isNotEmpty(person)) {JSONObject personObject = JSONObject.parseObject(person);String jobNum = personObject.getString("trdID");if (StringUtils.isNotEmpty(jobNum)) {SysUser sysUser = sysUserMapper.selectUserByJobNum(jobNum);ccccCheckonworkHistoryRecordService.insertCcccCheckonworkHistoryRecordEntranceGuard(sysUser.getUserId(),env.getProperty("barriergate.ip", String.class),new Date(),0);}}LOG.debug("MqttAccept_________"+ payload);}@Overridepublic void deliveryComplete(IMqttDeliveryToken iMqttDeliveryToken) {LOG.debug("deliveryComplete");}});client.connect(options);client.subscribe(allTopic,0);System.out.println("连接成功");} catch (Exception e) {e.printStackTrace();}}@Overridepublic int getOrder() {return 3;}
}

最后附件1,这是协议的部分内容:
一个设备只需要一个上报主题和一个下发主题即可。调用不同的内容,对应的RPC 方法是不同的。

mqtt协议调用示例(包括MQTT一键启动服务+测试工具 MQTTFX云盘下载),对捷顺门禁温感一体机进行人员信息下发相关推荐

  1. mysql修改元宝,端游[君·天下]高仿魔兽世界一键启动服务端+配套客户端+元宝金币修改教程等...

    资源说明: 1.本资源为君·天下OL单机版一键启动服务端,此游戏高仿魔兽世界. 2.四大职业:武修.羽箭.仙道.真巫. 3.慈善系统.变身系统.召唤系统.动态副本-单人进入.配对系统.狩猎时装.商城. ...

  2. 网页游戏服务器安装包,网页游戏[窝窝世界]一键启动服务端+全套组件+启动教程+GM工具...

    网页游戏[窝窝世界]一键启动服务端+全套组件+启动教程+GM工具 资源说明: 1.本资源默认单机架设,无需修改IP直接按照教程架设即可. 2.窝窝世界是一个以魔兽世界背景为题材的在线回合制网页游戏. ...

  3. 制作MySql5绿色免安装版(一键启动服务)

    制作MySql5绿色免安装版(一键启动服务) 前言 MySQL安装有镜像和免安装的,相比较而言免安装简单一下,但免安装使用命令初始化mysql服务会安装到C盘,本篇文章介绍一键启动服务绿色免安装,制作 ...

  4. 侠义道服务器修改,[侠义道1]1.85虚拟机镜像一键启动服务端+客户端+启动教程+元宝修改...

    [侠义道1]1.85虚拟机镜像一键启动服务端+客户端+启动教程+元宝修改 资源说明: 1.本资源为侠义道Online1.85版本,默认IP为192.168.200.175,虚拟机架设,默认使用NAT模 ...

  5. 搭建SpringBoot脚手架工程系列(3): 一键启动服务

    前言 接上篇文章SpringBoot脚手架工程系列(2):代码格式化/质量审核/提交检查,赋予了脚手架工程完善的代码格式化/质量审核/提交检查能力.让我们继续来完善脚手架,提高脚手架的工程本地运行&a ...

  6. 【MQTT协议详解】MQTT协议

    文章前注:本文的大量素材来自于百度百科和MQTT协议3.1.1中文板 MQTT协议3.1.1中文版网址:http://blog.mcxiaoke.com/mqtt/protocol/MQTT-3.1. ...

  7. 阿昌教你IDEA一键启动服务设置

    前言 当我们在使用IDEA去开发我们的微服务项目的时候,总是需要一个一个的打开每一个服务. 这里菜鸡阿昌教你如何设置IDEA,让他一键打开我们需要的打开的服务们(s). 正文 在IDEA的上面,服务栏 ...

  8. 修改手游登录服务器,手游[有侠气]一键启动服务端+客户端+GM管理运营后台+VIP修改+启动教程等...

    内容介绍 资源说明: 1.本资源默认IP为192.168.1.110,本机网络为1网段用户可将本机IP设置为192.168.1.110后直接按照教程步骤启动游戏,同时支持手机WIFI局域网使用. 2. ...

  9. 手游服务器ip 修改密码,手游无双小师妹一键启动服务端+配套客户端+启动教程+IP修改说明等...

    内容介绍 资源说明: 1.本资源默认IP为192.168.1.116 2.如本机为此IP则可按照启动教程直接启动服务端. 3.如本机IP为非此IP,请自行修改本机IP为192.168.1.116或参考 ...

最新文章

  1. mysql 本周函数_【转】MySQL时间函数的使用:查询本周、下周、本月、下个月份的数据...
  2. Redis学习手册(Sorted-Sets数据类型)
  3. 【数据挖掘】基于方格的聚类方法 ( 概念 | STING 方法 | CLIQUE 方法 )
  4. knn人脸识别判断_WEEK1_LRamp;KNN
  5. 初等数论--同余--Fermat素性检测算法(为什么每次概率改变1/2)
  6. EBS默认的登录账户和密码
  7. 基于ASP.NET的comet简单实现
  8. XFire下根据WSDL生成Client Stub,并测试Client
  9. 组策略 之 恢复默认组策略对象命令
  10. 2014-10-30NOIP复习题1
  11. android layout_margin的值,Android自定义ViewGroup( 支持layout_margin属性)
  12. Mybatis ResultMap Collection 复合主键
  13. Python知识点之Python进阶
  14. mescroll.js -- 精致的下拉刷新和上拉加载js框架
  15. 搜索引擎优化的九大方法
  16. 锐龙r7 4750u和i7 10510u 哪个好
  17. nginx 访问a 域名跳转到b域名_微信qq域名防红防封,怎么才能避免自己的域名被屏蔽...
  18. 细则从哈利·波特与来自您好麻雀船长
  19. 关于Nginx服务器的一些粗略认识
  20. 关于java开发阿里云视频直播的使用及掉坑、爬坑,欢迎入坑交流

热门文章

  1. vue-06 监听事件-自学视频
  2. 网页如何打开exe文件
  3. matlab函数内定义常量,matlab 里定义全局变量,常量
  4. SMPTE ST 2110 概论(一)
  5. python 用PIL库缩放图片并保存
  6. 第18章 系统功能设计
  7. ElementUI富文本框组件wangEditor实现
  8. java dao层编写及注释_JAVA代码注释规范
  9. vue项目中 页面生成pdf并下载,vue 中页面转PDF
  10. 一张图进阶 RocketMQ - 通信机制