Apache Apollo是一个代理服务器,其是在ActiveMQ基础上发展而来的,可以支持STOMP, AMQP, MQTT, Openwire, SSL, and WebSockets 等多种协议。有关Apollo的搭建问题,参阅上一篇部落格。
废话不多言,直接撸代码,先去maven的官网引入mqtt的第三方支持包。
org.eclipse.paho
org.eclipse.paho.client.mqttv3
1.2.0
com.alibaba
fastjson
1.2.51
Demo结构:
服务端的代码:
package com.example.demo.mqtt.server;
import com.example.demo.mqtt.PushCallback;
import org.eclipse.paho.client.mqttv3.*;
import org.eclipse.paho.client.mqttv3.persist.MemoryPersistence;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
/**
* Created by pengcheng.du on 2018/10/12.com.example.demo.mqtt.server.Server
*/
/*服务器端向客户端推送不同的主题*/
public class Server {
public static final String SERVER_URL = "tcp://0.0.0.0:61613";
public static List TOPICList = new ArrayList<>(Arrays.asList("wether","car","topic"));
public static String clientid;
private MqttClient mqttClient;
public MqttTopic mqttTopic1;
private MqttTopic getMqttTopic2;
private String username = "admin";
private String password = "password";
private MqttMessage mqttMessage;
/*//创建新的topic链接的时候使用此构造方法
public Server() throws Exception{
mqttClient = new MqttClient(SERVER_URL, clientid, new MemoryPersistence());
Server server = new Server();
server.mqttMessage = new MqttMessage();
server.mqttMessage.setQos(2);
server.mqttMessage.setRetained(true);
server.mqttMessage.setPayload("装配成功".getBytes());
server.publish(server.mqttTopic1,server.mqttMessage);
System.out.println(server.mqttMessage.isRetained()+":retained状态");
connect();
}*/
public Server() throws Exception{
clientid = "wether";
mqttClient = new MqttClient(SERVER_URL, clientid, new MemoryPersistence());
String topic = "wether";
connect(topic);
}
public Server(String topic,String clientid) throws Exception{
TOPICList.add(topic);
mqttClient = new MqttClient(SERVER_URL, clientid, new MemoryPersistence());
this.createCon(topic);
//connect(topic);
}
public void connect(String topic){
MqttConnectOptions mqttConnectOptions = new MqttConnectOptions();
mqttConnectOptions.setCleanSession(false);
mqttConnectOptions.setUserName(username);
mqttConnectOptions.setPassword(password.toCharArray());
mqttConnectOptions.setConnectionTimeout(20);
mqttConnectOptions.setKeepAliveInterval(20);
try {
mqttClient.setCallback(new PushCallback());
mqttClient.connect(mqttConnectOptions);
mqttTopic1 = mqttClient.getTopic(topic);
} catch (MqttException e) {
e.printStackTrace();
}
}
public static void publish(MqttTopic topic,MqttMessage message) throws MqttException {
System.out.println("话题是"+topic.toString()+"要发送的消息是"+message.toString());
MqttDeliveryToken publish_token = topic.publish(message);
publish_token.waitForCompletion();
System.out.print("消息已经推送到客户端了");
}
public static void main(String[] args) throws Exception {
Server server = new Server();
server.mqttMessage = new MqttMessage();
server.mqttMessage.setQos(2);
server.mqttMessage.setRetained(true);
server.mqttMessage.setPayload("装配成功".getBytes());
server.publish(server.mqttTopic1,server.mqttMessage);
System.out.println(server.mqttMessage.isRetained()+":retained状态");
}
public String createCon(String topic) throws Exception{
Server server = new Server();
server.mqttMessage = new MqttMessage();
server.mqttMessage.setQos(2);
server.mqttMessage.setRetained(true);
server.mqttMessage.setPayload("装配成功".getBytes());
server.publish(server.getMqttClient().getTopic(topic),server.mqttMessage);
System.out.println(server.mqttMessage.isRetained()+":retained状态");
return "build success";
}
public static String getServerUrl() {
return SERVER_URL;
}
public List getTOPIC() {
return TOPICList;
}
public static String getClientid() {
return clientid;
}
public MqttClient getMqttClient() {
return mqttClient;
}
public MqttTopic getMqttTopic1() {
return mqttTopic1;
}
public MqttTopic getGetMqttTopic2() {
return getMqttTopic2;
}
public String getUsername() {
return username;
}
public String getPassword() {
return password;
}
public MqttMessage getMqttMessage() {
return mqttMessage;
}
}
Client端:
package com.example.demo.mqtt.client;
import com.example.demo.mqtt.PushCallback;
import org.eclipse.paho.client.mqttv3.MqttClient;
import org.eclipse.paho.client.mqttv3.MqttConnectOptions;
import org.eclipse.paho.client.mqttv3.MqttTopic;
import org.eclipse.paho.client.mqttv3.persist.MemoryPersistence;
import java.util.concurrent.ScheduledExecutorService;
/**
* Created by pengcheng.du on 2018/10/12.
*/
public class Client {
public static final String SERVER_URL = "tcp://0.0.0.0:61613";
public static final String TOPIC = "wether";
public static final String clientid = "client4";
private MqttClient client;
private MqttConnectOptions options;
private String userName = "admin";
private String passWord = "password";
private ScheduledExecutorService scheduler;
private void start() throws Exception{
client = new MqttClient(SERVER_URL, clientid, new MemoryPersistence());
options = new MqttConnectOptions();
options.setCleanSession(true);
options.setUserName(userName);
options.setPassword(passWord.toCharArray());
options.setConnectionTimeout(20);
options.setKeepAliveInterval(20);
client.setCallback(new PushCallback());
MqttTopic topic = client.getTopic(TOPIC);
client.connect(options);
int[] Qos = {1};
String[] topic1 = {TOPIC};
client.subscribe(topic1,Qos);
}
public static void main (String[] args) throws Exception{
Client client = new Client();
client.start();
}
}
发送断开回调 PushCallback.java
package com.example.demo.mqtt;
import org.eclipse.paho.client.mqttv3.IMqttDeliveryToken;
import org.eclipse.paho.client.mqttv3.MqttCallback;
import org.eclipse.paho.client.mqttv3.MqttMessage;
/**
* Created by pengcheng.du on 2018/10/12.
*/
public class PushCallback implements MqttCallback {
@Override
//处理链接断开
public void connectionLost(Throwable throwable) {
// 连接丢失后,一般在这里面进行重连
System.out.println("连接断开,可以做重连");
}
@Override
//处理消息送达
public void messageArrived(String s, MqttMessage mqttMessage) throws Exception {
System.out.println("接收消息主题 : " + s);
System.out.println("接收消息Qos : " + mqttMessage.getQos());
System.out.println("接收消息内容 : " + new String(mqttMessage.getPayload()));
}
@Override
public void deliveryComplete(IMqttDeliveryToken iMqttDeliveryToken) {
}
}
开放开放两个接口,作为触发点,亦可以使用其他方式:
package com.example.demo.controller;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.example.demo.mqtt.client.Client;
import com.example.demo.mqtt.server.Server;
import org.eclipse.paho.client.mqttv3.MqttClient;
import org.eclipse.paho.client.mqttv3.MqttException;
import org.eclipse.paho.client.mqttv3.MqttMessage;
import org.eclipse.paho.client.mqttv3.MqttTopic;
import org.eclipse.paho.client.mqttv3.persist.MemoryPersistence;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* Created by pengcheng.du on 2018/10/12.
*/
@RestController
public class PublishMessage {
private static String HOST = "tcp://0.0.0.0:61613";
public static MqttClient client;
public static final String SERVER_URL = "tcp://0.0.0.0:61613";
//推送消息
@RequestMapping(value = "mqtt/publishMessageOnTopic/{topic}",method = RequestMethod.POST)
public Map publishMessageOnTopic(
@PathVariable(value = "topic") String topic, @RequestBody String message) throws Exception {
Map map = new HashMap<>();
JSONObject jsonObject = (JSONObject) JSONObject.parse(message);
String mess = (String) jsonObject.get("message");
MqttMessage mqttMessage = new MqttMessage();
mqttMessage.setPayload(mess.getBytes());
mqttMessage.setQos(2);
mqttMessage.setRetained(true);
if (this.findIndex(topic) == -1) {
map.put("data","no topic");
return map;
}
int index = this.findIndex(topic);
Server server = new Server();
server.connect(topic);
MqttTopic mqttTopic1 = server.mqttTopic1;
Server.publish(mqttTopic1,mqttMessage);
map.put("data","已发送");
return map;
}
public int findIndex(String topic) throws Exception{
Server server = new Server();
final List topicList = server.getTOPIC();
int Idnex = 0;
for (String topic1: topicList) {
if (topic.equals(topic1)) {
break;
}
Idnex++;
}
if (Idnex==topicList.size()) {
return -1;
} else {
return Idnex;
}
}
private MqttClient getMqttClient(String clientId) throws MqttException {
if (client != null && clientId.equals(client.getClientId())) {
return client;
}
return new MqttClient(HOST, clientId);
}
//创建主题
@RequestMapping(value = "mqtt/createNewTopic/{topic}/{clientId}",method = RequestMethod.POST)
public Map createNewTopic(@PathVariable(value = "topic") String topic ,
@PathVariable(value = "clientId") String clientId){
System.out.println("topic:"+topic+",clientId"+clientId);
try{
Server server = new Server(topic,clientId);
//server.connect(topic);
MqttTopic topic1 = server.getMqttClient().getTopic("");
System.out.println("topic1:"+topic1);
} catch (Exception e){
System.out.println(e.toString());
}
return null;
}
}
运行结果:自上而下是请求触发,服务端的控制,两个客户端的控制台,均通过tcp协议获取到了订阅的话题message。
MQTT只是一种消息推送的协议目前(2016/1/13)为V3.1版本,而Apache Apollo是更具这种协议而开发的一款服务性的服务程序,被用来进行消息推送。Apache Apollo说白了其实很简单,就是在服务器端创建一个唯一订阅号,发送者可以向这个订阅号中发东西,然后接受者(即订阅了这个订阅号的人)都会收到这个订阅号发出来的消息。以此来完成消息的推送。服务器其实是一个消息中转站。