提交 4b5188f8 编写于 作者: 玉米子禾's avatar 玉米子禾 提交者: 玉米子禾

完成大部分功能。Perform most functions.

上级
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/J2SE-1.4"/>
<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
<classpathentry kind="src" path="src/main/resources"/>
<classpathentry kind="src" path="src/main/java-templates"/>
<classpathentry kind="src" path="src/main/java"/>
<classpathentry kind="src" path="src/main/Client"/>
<classpathentry kind="lib" path="lib/beautyeye_lnf.jar"/>
<classpathentry kind="lib" path="lib/sqlite-jdbc-3.27.2.1.jar"/>
<classpathentry kind="output" path="target/classes"/>
</classpath>
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>MQTT3JavaSwingClient</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.buildship.core.gradleprojectbuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.jdt.core.javabuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.pde.ManifestBuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.pde.SchemaBuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.m2e.core.maven2Builder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.m2e.core.maven2Nature</nature>
<nature>org.eclipse.jdt.core.javanature</nature>
<nature>org.eclipse.pde.PluginNature</nature>
<nature>org.eclipse.buildship.core.gradleprojectnature</nature>
</natures>
</projectDescription>
connection.project.dir=
eclipse.preferences.version=1
eclipse.preferences.version=1
encoding//src/main/java/org/eclipse/paho/client/mqttv3/MqttClient.java=UTF-8
eclipse.preferences.version=1
org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
org.eclipse.jdt.core.compiler.codegen.methodParameters=do not generate
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.7
org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
org.eclipse.jdt.core.compiler.compliance=1.7
org.eclipse.jdt.core.compiler.debug.lineNumber=generate
org.eclipse.jdt.core.compiler.debug.localVariable=generate
org.eclipse.jdt.core.compiler.debug.sourceFile=generate
org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
org.eclipse.jdt.core.compiler.source=1.7
#Wed Feb 04 17:08:18 GMT 2009
eclipse.preferences.version=1
resolve.requirebundle=false
Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: %bundle.name
Bundle-SymbolicName: MQTT3JavaSwingClient
Bundle-Version: 1.2.1
Bundle-Localization: bundle
Export-Package: org.eclipse.paho.client.mqttv3;version="1.2.1",
org.eclipse.paho.client.mqttv3.logging;version="1.2.1",
org.eclipse.paho.client.mqttv3.persist;version="1.2.1",
org.eclipse.paho.client.mqttv3.util;version="1.2.1"
Bundle-Vendor: %bundle.provider
Bundle-ActivationPolicy: lazy
Bundle-RequiredExecutionEnvironment: JavaSE-1.7
Import-Package: javax.net;resolution:=optional,
javax.net.ssl;resolution:=optional,
javax.swing.plaf.nimbus
文件已添加
# MQTT3JavaSwingClient
这是一个用Java写的有会话模式的MQTT客户端,用到了JavaSwing、SQLite、Paho、Beautyeye等技术。界面简洁清新,有MQTT的基本功能,有会话模式,可以在同一主题下会话,可以设置账号、密码、ID、遗嘱等登录初始信息。This is a conversational MQTT client written in Java that USES JavaSwing, SQLite, Paho, Beautyeye, and other technologies.The interface is simple and fresh, with the basic functions of MQTT and the session mode, which allows you to have a conversation under the same theme, and you can set the initial login information such as account number, password, ID and will.
package top.luckysmile.mqtt.client;
import javax.swing.UIManager;
import org.jb2011.lnf.beautyeye.BeautyEyeLNFHelper;
import org.jb2011.lnf.beautyeye.BeautyEyeLNFHelper.FrameBorderStyle;
import top.luckysmile.mqtt.client.view.MainView;
/**
* 启动主窗口的开始函数
* @author minuy
*
*/
public class MQTTClientStart {
/**
* 开始
* @param args
*/
public static void main(String[] args) {
try{
BeautyEyeLNFHelper.frameBorderStyle = FrameBorderStyle.translucencyAppleLike;
org.jb2011.lnf.beautyeye.BeautyEyeLNFHelper.launchBeautyEyeLNF();
UIManager.put("RootPane.setupButtonVisible", false);
}
catch(Exception e) {
System.out.println(e.toString());
}
new MainView();
}
}
\ No newline at end of file
package top.luckysmile.mqtt.client.data;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;
import top.luckysmile.mqtt.client.server.GeneratePassword;
/**
* 数据库交互
* @author minuy
*
*/
public class MqttDAO {
public boolean SaveSession(MqttMassageBeans massage) {
boolean yes = false;
SQLiteTest("mqtt_session");
//数据库语句
String sql = "INSERT INTO \"main\".\"mqtt_session\" (\"time\", \"topic\", \"context\", \"qos\", \"other\") VALUES (?, ?, ?, ?, ?)";
//获得数据库连接
Connection conn = MqttDbUtil.getConn();
//声明句柄对象
PreparedStatement pstm = null;
try {
//获得操作句柄
pstm = conn.prepareStatement(sql);
//拼接语句
if(massage.getTime() == null) {
massage.setTime("");
}
pstm.setString(1, massage.getTime());
if(massage.getTopic() == null) {
massage.setTopic("");
}
pstm.setString(2, massage.getTopic());
if(massage.getContext() == null) {
massage.setContext("");
}
pstm.setString(3, massage.getContext());
if(massage.getQos() == null) {
massage.setQos("");
}
pstm.setString(4, massage.getQos());
if(massage.getOther() == null) {
massage.setOther("");
}
pstm.setString(5, massage.getOther());
//执行语句
yes = pstm.execute();
} catch (SQLException e) {
System.out.println(e.toString());
}finally {
//一定要做的事,释放连接
MqttDbUtil.free(pstm,conn);
}
return yes;
}
/**
* 保存设置到数据库中
* @param set 设置
* @return 成败
*/
public boolean SaveSet(MqttSetBeans set) {
boolean yes = false;
SQLiteTest("mqtt_set");
String name = new GeneratePassword().get(8);
//数据库语句
String sql = "INSERT INTO \"main\".\"mqtt_set\" (\"set_name\", \"clientid\", \"ip\", \"port\", \"name\", \"passwd\", \"lwt_topic\", \"lwt_qos\", \"lwt_context\", \"sub_topic\", \"sub_qos\", \"pub_topic\", \"pub_context\", \"pub_qos\") VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?)";
//获得数据库连接
Connection conn = MqttDbUtil.getConn();
//声明句柄对象
PreparedStatement pstm = null;
try {
//获得操作句柄
pstm = conn.prepareStatement(sql);
//拼接语句
pstm.setString(1, name);
if(set.getId() == null) {
set.setId("");
}
pstm.setString(2, set.getId());
if(set.getIp() == null) {
set.setIp("");
}
pstm.setString(3, set.getIp());
if(set.getPort() == null) {
set.setPort("");
}
pstm.setString(4, set.getPort());
if(set.getName() == null) {
set.setName("");
}
pstm.setString(5, set.getName());
if(set.getPasswd() == null) {
set.setPasswd("");
}
pstm.setString(6, set.getPasswd());
if(set.getLWTTopic() == null) {
set.setLWTTopic("");
}
pstm.setString(7, set.getLWTTopic());
if(set.getLWTQos() == null) {
set.setLWTQos("");
}
pstm.setString(8, set.getLWTQos());
if(set.getLWTContext() == null) {
set.setLWTContext("");
}
pstm.setString(9, set.getLWTContext());
if(set.getSubTopic() == null) {
set.setSubTopic("");
}
pstm.setString(10, set.getSubTopic());
if(set.getSubQos() == null) {
set.setSubQos("");
}
pstm.setString(11, set.getSubQos());
if(set.getPubTopic() == null) {
set.setPubTopic("");
}
pstm.setString(12, set.getPubTopic());
if(set.getPubContext() == null) {
set.setPubContext("");
}
pstm.setString(13, set.getPubContext());
if(set.getPubQos() == null) {
set.setPubQos("");
}
pstm.setString(14, set.getPubQos());
//执行语句
yes = pstm.execute();
} catch (SQLException e) {
System.out.println(e.toString());
}finally {
//一定要做的事,释放连接
MqttDbUtil.free(pstm,conn);
}
return yes;
}
/**
* 20150416 判断sqlite中是否存在表
* author:zhouyun ,date:20150416
* @param dbFile db文件全路径
* @param tableName 需要查询的表名
* @return
*/
private boolean sqliteTabbleIsExist(String tableName){
boolean flag = false;
Connection conn = null;
ResultSet set = null;
Statement state = null;
try {
conn = MqttDbUtil.getConn();
String sql = "select count(*) from sqlite_master where type ='table' and name ='"+tableName.trim()+"' ";
state = conn.createStatement();
set = state.executeQuery(sql);
int count = set.getInt(1);
if(count>0){
flag = true;
}
} catch (Exception e) {
System.err.println(e);
}finally{
//一定要做的事,释放连接
MqttDbUtil.free(set,conn);
try {
if(state != null){
state.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
}
return flag;
}
private void SQLiteTest(String Table) {
if(!sqliteTabbleIsExist(Table)) {
SqliteCreateTable(Table);
}
}
private void SqliteCreateTable(String table) {
String sql = null;
if(table.equals("mqtt_set")) {
sql = new SqlCreatTable().getSetTable();
}
if(table.equals("mqtt_session")) {
sql = new SqlCreatTable().getSessionTable();
}
Connection conn = null;
ResultSet set = null;
Statement state = null;
try {
conn = MqttDbUtil.getConn();
state = conn.createStatement();
set = state.executeQuery(sql);
} catch (Exception e) {
System.err.println(e);
}finally{
//一定要做的事,释放连接
MqttDbUtil.free(set,conn);
try {
if(state != null){
state.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
}
}
public MqttSetBeans getSeting(){
SQLiteTest("mqtt_set");
List<MqttSetBeans> list = new ArrayList<MqttSetBeans>();
MqttSetBeans set = null;
//数据库语句
String sql = "select * from mqtt_set";
//获得数据库连接
Connection conn = MqttDbUtil.getConn();
//声明句柄对象
PreparedStatement pstm = null;
try {
//获得操作句柄
pstm = conn.prepareStatement(sql);
//根据SQL语句获取数据
list = getDataBySQL(pstm);
//提取
if(list.size() > 0) {
set = list.get(list.size()-1);
}
} catch (SQLException e) {
System.out.println(e.toString());
}finally {
//一定要做的事,释放连接
MqttDbUtil.free(pstm,conn);
}
return set;
}
public List<MqttSetBeans> getDataBySQL(PreparedStatement pstm){
List<MqttSetBeans> list = new ArrayList<MqttSetBeans>();
//声明操作对象
ResultSet rs = null;
//声明一个BookInfoBeans对象
MqttSetBeans mqttSet = null;
try {
//获得操作对象
rs = pstm.executeQuery();
//循环整个列表,rs.next()返回false时表示数据处理完
while(rs.next()) {
//新建一个AdministratorBeans对象以存数据
mqttSet = new MqttSetBeans();
//根据字段名获取相关数据
mqttSet.setId(rs.getString("clientid"));
mqttSet.setIp(rs.getString("ip"));
mqttSet.setLWTContext(rs.getString("lwt_context"));//遗言内容
mqttSet.setLWTQos(rs.getString("lwt_qos"));//遗言质量
mqttSet.setLWTTopic(rs.getString("lwt_topic"));//遗言主题
mqttSet.setName(rs.getString("name"));//账号
mqttSet.setPasswd(rs.getString("passwd"));//密码
mqttSet.setPort(rs.getString("port"));//端口号
mqttSet.setPubContext(rs.getString("pub_context"));//发布内容
mqttSet.setPubQos(rs.getString("pub_qos"));//发布质量
mqttSet.setPubTopic(rs.getString("pub_topic"));//发布主题
mqttSet.setSubQos(rs.getString("sub_qos"));//订阅质量
mqttSet.setSubTopic(rs.getString("sub_topic"));//订阅主题
//把数据压入列表
list.add(mqttSet);
}
} catch (SQLException e) {
System.out.println(e.toString());
} finally {
//一定要做的事,释放连接
MqttDbUtil.free(rs, pstm);
}
return list;
}
}
package top.luckysmile.mqtt.client.data;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import javax.swing.JOptionPane;
/**
* SQLite驱动相关,加载驱动,获取连接
* @author minuy
*
*/
public class MqttDbUtil {
//声明连接数据库所需要的相关信息
private static String driver = "org.sqlite.JDBC";//驱动名
private static String url = "Mqtt.db";//文件路径
private MqttDbUtil() {
}
//静态的方式加载JDBC驱动
static {
try {
Class.forName(driver);
} catch (ClassNotFoundException e) {
System.out.println(e.toString());
}
}
/**
* 返回一个数据库链接
* @return
*/
public static Connection getConn() {
Connection conn = null;
try {
//如果不存在就在当前目录下创建
conn = DriverManager.getConnection("jdbc:sqlite:" + url);
} catch (SQLException e) {
System.out.println("数据库连接失败!");
JOptionPane.showMessageDialog(null, "服务器连接失败");
e.printStackTrace();
}
return conn;
}
/**
* 释放数据库连接信息
* @param rs
* @param pstm
* @param conn
*/
public static void free(ResultSet rs,Statement pstm,Connection conn) {
FreeConnection(conn);
FreeStatement(pstm);
FreeResultSet(rs);
}
public static void free(Connection conn){
FreeConnection(conn);
}
public static void free(ResultSet rs,Statement pstm) {
FreeResultSet(rs);
FreeStatement(pstm);
}
public static void free(ResultSet rs,Connection conn) {
FreeResultSet(rs);
FreeConnection(conn);
}
public static void free(Statement pstm,Connection conn) {
FreeStatement(pstm);
FreeConnection(conn);
}
//释放连接
private static void FreeConnection(Connection conn){
if(conn != null) {
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
//释放资源
private static void FreeResultSet(ResultSet rs){
if(rs != null) {
try {
rs.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
//释放操作对象
private static void FreeStatement(Statement pstm){
if(pstm != null) {
try {
pstm.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
package top.luckysmile.mqtt.client.data;
/**
* 消息结构类,用于存消息信息
* @author minuy
*
*/
public class MqttMassageBeans {
private String time;
private String topic;
private String context;
private String qos;
private String other;
public String getTime() {
return time;
}
public void setTime(String time) {
this.time = time;
}
public String getTopic() {
return topic;
}
public void setTopic(String topic) {
this.topic = topic;
}
public String getContext() {
return context;
}
public void setContext(String context) {
this.context = context;
}
public String getQos() {
return qos;
}
public void setQos(String qos) {
this.qos = qos;
}
public String getOther() {
return other;
}
public void setOther(String other) {
this.other = other;
}
}
package top.luckysmile.mqtt.client.data;
/**
* 设置数据结构类,存设置数据
* @author minuy
*
*/
public class MqttSetBeans {
private int setId;
private String setName;
private String Ip;
private String Port;
private String Id;
private String Name;
private String Passwd;
private String LWTTopic;
private String LWTContext;
private String LWTQos;
private String SubTopic;
private String SubQos;
private String PubTopic;
private String PubContext;
private String PubQos;
public String getIp() {
return Ip;
}
public void setIp(String ip) {
Ip = ip;
}
public String getPort() {
return Port;
}
public void setPort(String port) {
Port = port;
}
public String getId() {
return Id;
}
public void setId(String id) {
Id = id;
}
public String getName() {
return Name;
}
public void setName(String name) {
Name = name;
}
public String getPasswd() {
return Passwd;
}
public void setPasswd(String passwd) {
Passwd = passwd;
}
public String getLWTTopic() {
return LWTTopic;
}
public void setLWTTopic(String lWTTopic) {
LWTTopic = lWTTopic;
}
public String getLWTContext() {
return LWTContext;
}
public void setLWTContext(String lWTContext) {
LWTContext = lWTContext;
}
public String getLWTQos() {
return LWTQos;
}
public void setLWTQos(String lWTQos) {
LWTQos = lWTQos;
}
public String getSubTopic() {
return SubTopic;
}
public void setSubTopic(String subTopic) {
SubTopic = subTopic;
}
public String getSubQos() {
return SubQos;
}
public void setSubQos(String subQos) {
SubQos = subQos;
}
public String getPubTopic() {
return PubTopic;
}
public void setPubTopic(String pubTopic) {
PubTopic = pubTopic;
}
public String getPubContext() {
return PubContext;
}
public void setPubContext(String pubContext) {
PubContext = pubContext;
}
public String getPubQos() {
return PubQos;
}
public int getSetId() {
return setId;
}
public void setSetId(int setId) {
this.setId = setId;
}
public String getSetName() {
return setName;
}
public void setSetName(String setName) {
this.setName = setName;
}
public void setPubQos(String pubQos) {
PubQos = pubQos;
}
}
package top.luckysmile.mqtt.client.data;
/**
* 这里创建表,存储着表的信息
* @author minuy
*
*/
public class SqlCreatTable {
private String setTable = "create table mqtt_set(id integer primary key autoincrement ,set_name text not null,clientid char(65535) ,ip char(128) ,port char(5) ,name char(65535) ,passwd char(65535) ,lwt_topic text ,lwt_qos char(1) default '0' check (lwt_qos in ('0','1','2')) ,lwt_context text ,sub_topic text ,sub_qos char(1) default '0' check (sub_qos in ('0','1','2')) ,pub_topic text ,pub_context text ,pub_qos char(1) default '0' check (pub_qos in ('0','1','2')))";
private String sessionTable = "CREATE TABLE \"mqtt_session\" (\"id\" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,\"time\" TEXT,\"topic\" TEXT,\"context\" TEXT,\"qos\" TEXT,\"other\" TEXT)";
/**
* 创建设置表
* @return SQLite语句
*/
public String getSetTable() {
return setTable;
}
/**
* 创建会话记录表
* @return SQLite语句
*/
public String getSessionTable() {
return sessionTable;
}
}
package top.luckysmile.mqtt.client.listen;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import top.luckysmile.mqtt.client.server.MqttServerManage;
import top.luckysmile.mqtt.client.view.MQTTChatView;
/**
* 会话视图监听,每个视图一个监听,调用事件用视图对象和主题文字判断
* @author minuy
*
*/
public class ChatViewListen implements ActionListener {
MqttServerManage sm;
MQTTChatView mcv;
public ChatViewListen(MQTTChatView mqttChatView) {
this.mcv = mqttChatView;
this.sm = MqttServerManage.GetMqttServerManage();//获取服务
}
@Override
public void actionPerformed(ActionEvent arg0) {
Object clicket = arg0.getSource();
if(clicket == mcv.getJbtChatSend()) {
//发送
sm.SessionSend(mcv);
}else {
if(clicket == mcv.getJbtChatClear()) {
//清除会话消息
sm.CleanSession(mcv);
}else {
if(clicket == mcv.getJbtQuitSub()) {
//取消订阅
sm.CloseSession(mcv);
}
}
}
}
}
package top.luckysmile.mqtt.client.listen;
import java.text.SimpleDateFormat;
import java.util.Date;
import javax.swing.JOptionPane;
import org.eclipse.paho.client.mqttv3.IMqttDeliveryToken;
import org.eclipse.paho.client.mqttv3.MqttCallback;
import org.eclipse.paho.client.mqttv3.MqttMessage;
import top.luckysmile.mqtt.client.data.MqttDAO;
import top.luckysmile.mqtt.client.data.MqttMassageBeans;
import top.luckysmile.mqtt.client.server.MqttServerManage;
import top.luckysmile.mqtt.client.server.ViewOpt;
/**
* 客户端回调,收到消息,连接状态在这处理
* @author minuy
*
*/
public class MqttClientCallback implements MqttCallback {
ViewOpt vo;
MqttServerManage msm;
/**
* 回调用
* @param vo2 主视图操作
* @param cvo 管理器
*/
public MqttClientCallback(ViewOpt vo2, MqttServerManage cvo) {
this.vo = vo2;
this.msm = cvo;
}
@Override
public void connectionLost(Throwable cause) {
// 当与服务器的连接丢失时,将调用此方法。
JOptionPane.showMessageDialog(null, cause.toString(), "连接丢失!", 2);
vo.SetSta("连接丢失");
vo.setSubhead("连接丢失");//副标题
vo.SetConnetButtonStr("连接");
vo.SetLoginEnable(true);
//清空订阅
msm.SubEmpty();
//未连接
msm.setConnet(false);
}
@Override
public void messageArrived(String title, MqttMessage msg) throws Exception {
// 当消息从服务器到达时,将调用此方法。
msm.MqttReceveMassage(title,msg.toString(),String.valueOf(msg.getQos()));
//下面是保存信息
System.out.println(title+":"+msg.toString());
MqttMassageBeans massage = new MqttMassageBeans();
massage.setContext(msg.toString());
massage.setTopic(title);
massage.setQos(String.valueOf(msg.getQos()));
SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");//设置日期格式
massage.setTime(df.format(new Date()));
massage.setOther("minuy");
new MqttDAO().SaveSession(massage);
}
@Override
public void deliveryComplete(IMqttDeliveryToken token) {
// 当消息的传递已完成,且所有确认已收到时调用。对于QoS 0消息,一旦消息被提交到网络进行交付,就会调用它。对于QoS 1,在接收PUBACK时调用它,对于QoS 2,在接收PUBCOMP时调用它。令牌将与消息发布时返回的令牌相同。
System.out.println(token.toString());
vo.SetSendSta(false);//完成
}
}
package top.luckysmile.mqtt.client.listen;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JOptionPane;
import top.luckysmile.mqtt.client.server.MqttServerManage;
import top.luckysmile.mqtt.client.view.MainView;
/**
* 主视图监听
* @author minuy
*
*/
public class MqttMainViewActionListener implements ActionListener {
MqttServerManage sm;
MainView mv;
public MqttMainViewActionListener(MainView mainView) {
this.mv = mainView;
this.sm = MqttServerManage.GetMqttServerManage();//获取服务
sm.setViewOpt(mv);//设置操作视图
}
@Override
public void actionPerformed(ActionEvent e) {
Object clicked = e.getSource();
if(clicked == mv.getJbtConnect()) {
//连接
System.out.println("连接!");
sm.MqttConnet();
}else {
if(clicked == mv.getJbtSend()) {
//发送
System.out.println("发送!");
sm.MqttPubCustomTopic();
}else {
if(clicked == mv.getJbtRandId()) {
//随机ID
System.out.println("生成随机ID!");
sm.RandId();
}else {
if(clicked == mv.getJbtSubscribe()) {
System.out.println("订阅!");
sm.MqttSub();
}else {
if(clicked == mv.getJbtMoreSet()) {
System.out.println("更多!");
JOptionPane.showMessageDialog(null, "准备电子设计大赛-2019-小鱼啊小鱼", "期待", 1);
}
}
}
}
}
}
}
package top.luckysmile.mqtt.client.server;
import java.text.SimpleDateFormat;
import java.util.Date;
import top.luckysmile.mqtt.client.view.MQTTChatView;
/**
* 会话视图操作,在这里操作会话视图的界面
* @author minuy
*
*/
public class ChatViewOpt {
private static ChatViewOpt cvo = null;
private ChatViewOpt() {
}
public static ChatViewOpt getChatViewOpt() {
if(cvo!=null) {
return cvo;
}else {
cvo = new ChatViewOpt();
return cvo;
}
}
/**
* 清理会话,清除接收到的数据
*/
public void CleanSession(MQTTChatView mcv) {
mcv.getJtaMassage().setText("");
}
/**
* 添加一条消息到会话窗口
* @param msage
*/
public void AddMassage(String msage,MQTTChatView mcv,String qos) {
SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");//设置日期格式
String time = df.format(new Date());// new Date()为获取当前系统时间
String history = mcv.getJtaMassage().getText();
mcv.getJtaMassage().setText(history + time + " Qos:" + qos + "\n" + msage + "\n");
mcv.updateUI();
}
/**
* 获取发送的相关信息
* @param mcv 会话视图
* @return 数组,标题,质量,内容
*/
public String[] getSendInfo(MQTTChatView mcv) {
String[] info = new String[3];
//因为视图限制,故不再加校验
info[2] = mcv.getJtaChatSend().getText();
info[1] = String.valueOf(mcv.getJcbQos().getSelectedIndex());
info[0] = mcv.getJlbChatTopic().getText();
return info;
}
/**
* 计数器
* @param mcv
* @param x
*/
public void addBitNumber(MQTTChatView mcv,int x) {
mcv.setStatisticsN(mcv.getStatisticsN()+x);
mcv.getJlbStatistics().setText("收到的字节数:" + mcv.getStatisticsN());
}
}
package top.luckysmile.mqtt.client.server;
import java.util.Random;
/**
* 随机生成一个只有数字和字母的字符串
* @author 互联网
*
*/
public class GeneratePassword {
/**
* 随机生成密码
* @param length 密码的长度
* @return 最终生成的密码
*/
public String get (int length) {
// 最终生成的密码
String password = "";
Random random = new Random();
for (int i = 0; i < length; i ++) {
// 随机生成0或1,用来确定是当前使用数字还是字母 (0则输出数字,1则输出字母)
int charOrNum = random.nextInt(2);
if (charOrNum == 1) {
// 随机生成0或1,用来判断是大写字母还是小写字母 (0则输出小写字母,1则输出大写字母)
int temp = random.nextInt(2) == 1 ? 65 : 97;
password += (char) (random.nextInt(26) + temp);
} else {
// 生成随机数字
password += random.nextInt(10);
}
}
return password;
}
}
package top.luckysmile.mqtt.client.server;
import javax.swing.JOptionPane;
import org.eclipse.paho.client.mqttv3.MqttClient;
import org.eclipse.paho.client.mqttv3.MqttException;
/**
* 关闭连接的相关操作
* @author minuy
*
*/
public class MqttClientCloseConnet {
public MqttClientCloseConnet(MqttClient mC, final ViewOpt vo, MqttServerManage mqttServerManage) {
boolean isClose = true;
vo.SetConnetButtonEable(false);//按钮不可用
try {
mC.disconnect();
//关闭客户机释放与客户机关联的所有资源。客户端关闭后不能重用。例如,连接尝试将失败。
mC.close();
} catch (MqttException e) {
System.out.println(e.toString());
isClose = false;
JOptionPane.showMessageDialog(null, "未连接 "+e.toString(), "错误!", JOptionPane.ERROR_MESSAGE);
}
if(isClose) {
vo.SetLoginEnable(true);//设置界面可编辑
vo.SetConnetButtonEable(true);//设置按钮可用
vo.SetConnetButtonStr("连接");//设置字符
vo.SetConnetButtonEable(true);
mqttServerManage.setConnet(false);//设置状态断开
vo.SetSta("已断开");
vo.setSubhead("已断开");//设置副标题
}
}
}
package top.luckysmile.mqtt.client.server;
import javax.swing.JOptionPane;
import org.eclipse.paho.client.mqttv3.MqttClient;
import org.eclipse.paho.client.mqttv3.MqttConnectOptions;
import org.eclipse.paho.client.mqttv3.MqttException;
import org.eclipse.paho.client.mqttv3.persist.MemoryPersistence;
import top.luckysmile.mqtt.client.data.MqttSetBeans;
/**
* 客户端连接函数,连接到服务器
* @author minuy
*
*/
public class MqttClientConnet extends Thread{
MqttClient mqttClient;//回调用
MqttSetBeans set;
ViewOpt vo;
boolean isConnet;
MqttServerManage msm;
/**
* 新建一个MQTT连接
* @param setBeans 一个带设置的类
*/
public MqttClientConnet(MqttSetBeans setBeans,ViewOpt vo,MqttServerManage msm) {
this.set = setBeans;
this.vo = vo;
this.msm = msm;
}
@Override
public void run() {
//数据非空判断
if(set == null) {
return;
}
vo.SetSta("正在连接");//显示状态正在连接
vo.SetLoginEnable(false);//设置界面不可编辑
vo.SetConnetButtonEable(false);//设置按钮不可用
isConnet = true;
String port = set.getId();
String url = "tcp://" + set.getIp() + ":" + set.getPort();
MemoryPersistence persistence = new MemoryPersistence();
//设置相关信息
MqttConnectOptions connOpts = new MqttConnectOptions();
connOpts.setCleanSession(true);
//遗嘱主题不为空
if(!TextUtils.isEmpty(set.getLWTTopic())) {
if(TextUtils.isEmpty(set.getLWTContext())) {
set.setLWTContext("");
}
connOpts.setWill(set.getLWTTopic(), set.getLWTContext().getBytes(), Integer.valueOf(set.getLWTQos()), true);
}
//账号密码
if(!TextUtils.isEmpty(set.getName())) {
connOpts.setUserName(set.getName());
connOpts.setPassword(vo.getViewPasswd());
}
//新建客户端
try {
mqttClient= new MqttClient(url, port, persistence);
} catch (MqttException e) {
System.out.println(e.toString());
}
System.out.println("连接到服务器: "+"tcp://" + set.getIp() + ":" + set.getPort());
try {
mqttClient.connect(connOpts);
} catch (MqttException e) {
//连接失败
isConnet = false;
JOptionPane.showMessageDialog(null, e.toString(), "错误!", JOptionPane.ERROR_MESSAGE);
e.printStackTrace();
}
if(isConnet) {
//连接成功
vo.SetSta("已连接");//显示状态未连接
vo.SetConnetButtonEable(true);//设置按钮可用
vo.SetConnetButtonStr("断开");
msm.setMC(mqttClient);
msm.setConnet(true);
vo.setSubhead("已连接:"+url);
}else {
//连接失败
vo.SetSta("未连接");//显示状态未连接
vo.SetLoginEnable(true);//设置界面可编辑
vo.SetConnetButtonEable(true);//设置按钮可用
msm.setConnet(false);
}
}
}
package top.luckysmile.mqtt.client.server;
import javax.swing.JOptionPane;
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.MqttPersistenceException;
import top.luckysmile.mqtt.client.data.MqttSetBeans;
/**
* 发送线程,发送消息时调用
* @author minuy
*
*/
public class MqttSendPub extends Thread{
String[] info = null;
MqttClient mc;
public MqttSendPub(String[] info,MqttClient mc) {
this.info = info;
this.mc = mc;
}
public MqttSendPub(MqttSetBeans set,MqttClient mc) {
if(set == null) {
return;
}
info = new String[3];
this.info[2] = set.getPubContext();
this.info[1] = set.getPubQos();
this.info[0] = set.getPubTopic();
this.mc = mc;
}
@Override
public void run() {
if(!mc.isConnected()) {
System.out.println("没有连接!");
JOptionPane.showMessageDialog(null, "没有连接!", "失败", 2);
return;
}
String msm = info[2];
String topic = info[0];
int qos;
if(!TextUtils.isEmpty(info[1])) {
qos = Integer.valueOf(info[1]);
}else {
qos = 0;
}
if(TextUtils.isEmpty(topic)) {
System.out.println("主题异常!");
return;
}
if(TextUtils.isEmpty(msm)) {
System.out.println("消息异常!");
return;
}
MqttMessage message = new MqttMessage(info[2].getBytes());
message.setQos(qos);
try {
mc.publish(topic, message);
} catch (MqttPersistenceException e) {
System.out.println(e.toString());
} catch (MqttException e) {
System.out.println(e.toString());
}
}
}
package top.luckysmile.mqtt.client.server;
import java.util.ArrayList;
import java.util.List;
import javax.swing.JOptionPane;
import org.eclipse.paho.client.mqttv3.MqttClient;
import top.luckysmile.mqtt.client.data.MqttDAO;
import top.luckysmile.mqtt.client.data.MqttSetBeans;
import top.luckysmile.mqtt.client.listen.MqttClientCallback;
import top.luckysmile.mqtt.client.view.MQTTChatView;
import top.luckysmile.mqtt.client.view.MainView;
/**
* 服务管理器,负责调度所有服务
* @author minuy
*
*/
public class MqttServerManage {
private ViewOpt vo;//视图操作类
private ChatViewOpt cvo;//会话视图操作类
private boolean isConnet = false;//连接状态
private MqttClient MC;//客户端对象
private List<MQTTChatView> chatSession = new ArrayList<MQTTChatView>();//会话视图列表
private List<String> subTopic = new ArrayList<String>();//已订阅主题列表
private static MqttServerManage msm = null;
/**
* 单例化
*/
private MqttServerManage() {
this.cvo = ChatViewOpt.getChatViewOpt();
}
/**
* 返回一个服务管理器,在操作视图前需要调用public void setViewOpt(MainView mv)方法设置被操作的视图
* @return 一个服务管理器
*/
public static MqttServerManage GetMqttServerManage() {
if(msm != null) {
return msm;
}else {
msm = new MqttServerManage();
return msm;
}
}
/**
* 生成一个视图操作对象
* @param mv
*/
public void setViewOpt(MainView mv) {
this.vo = new ViewOpt(mv);
}
/**
* 连接MQTT服务器
*/
public void MqttConnet() {
if(isConnet) {
//断开
new MqttClientCloseConnet(MC,vo,this);
//清空订阅
SubEmpty();
}else {
//连接
MqttSetBeans set = vo.getMainViewData();//获取数据
MqttClientConnet mqttClient = new MqttClientConnet(set,vo,this);
mqttClient.start();//连接
//保存下设置
new MqttDAO().SaveSet(set);
}
}
/**
* 左边的自定义主题发送
*/
public void MqttPubCustomTopic() {
MqttSetBeans set = vo.getMainViewData();//获取数据
MqttSendPub send = new MqttSendPub(set,MC);
vo.SetSendSta(true);//发送中
send.start();
}
/**
* MQTT订阅
*/
public void MqttSub() {
MQTTChatView mcv = null;
MqttSetBeans set = vo.getMainViewData();//获取数据
boolean isCreat = false;
//防止重复订阅
System.out.println("检测重复......");
for (int i = 0; i < subTopic.size(); i++) {
//与主题列表比较
if(set.getSubTopic().equals(subTopic.get(i))) {
JOptionPane.showMessageDialog(null, "已订阅!");
return;
}
}
//看会话视图是否存在,存在则不用再创建
for (int i = 0; i < chatSession.size(); i++) {
if(set.getSubTopic().equals(chatSession.get(i).getJlbChatTopic().getText())) {
isCreat = true;
mcv = chatSession.get(i);
}
}
MqttSubServer sub = new MqttSubServer(set,vo,MC,this,isCreat,mcv);
sub.start();
//保存下设置
new MqttDAO().SaveSet(set);
}
/**
* 生成随机ID
*/
public void RandId() {
String id = new GeneratePassword().get(8);
vo.SetClictID(id);
}
/**
* 查询连接状态
* @return 连接状态,true:已连接,false:未连接
*/
public boolean isConnet() {
return isConnet;
}
/**
* 设置连接状态
* @param isConnet true:已连接,false:未连接
*/
public void setConnet(boolean isConnet) {
this.isConnet = isConnet;
}
/**
* 设置连接的客户端对象,连接成功后线程调用返回客户端对象
* @param mC 已连接的客户端
*/
public void setMC(MqttClient mC) {
MC = mC;
if(MC.isConnected()) {
MC.setCallback(new MqttClientCallback(vo,this));
System.out.println("连接成功...");
}
}
/**
* 把新建的会话视图存到列表里
* @param newView
*/
public void addSession(MQTTChatView newView) {
chatSession.add(newView);
}
/**
* 从视图列表里删除一个视图
* @param newView
*/
public void removeSession(MQTTChatView rmView) {
for (int i = 0; i < chatSession.size(); i++) {
if(chatSession.get(i) == rmView) {
chatSession.remove(i);
break;
}
}
}
/**
* 右边的自动主题发送
*/
public void SessionSend(MQTTChatView mcv) {
String[] sendData;
sendData = cvo.getSendInfo(mcv);
MqttSendPub send = new MqttSendPub(sendData,MC);
send.start();
}
/**
* 清除会话内容
* @param mcv
*/
public void CleanSession(MQTTChatView mcv) {
cvo.CleanSession(mcv);
}
/**
* 关闭会话窗口
* 取消订阅
* @param mcv
*/
public void CloseSession(MQTTChatView mcv) {
new closeTopic(vo, MC, chatSession, mcv,this);
}
/**
* 收到消息
* @param topic
* @param string
*/
public void MqttReceveMassage(String topic, String string, String qos) {
for (int i = 0; i < chatSession.size(); i++) {
if(chatSession.get(i).getJlbChatTopic().getText().equals(topic)) {
cvo.AddMassage(string, chatSession.get(i),qos);//会话
cvo.addBitNumber(chatSession.get(i),TextUtils.getStringLength(string));//计数器
break;
}
}
}
/**
* 增加一个订阅
*/
public void SubAdd(String topic) {
subTopic.add(topic);
}
/**
* 通过名字删除一个订阅
*/
public void SubDrop(String topic) {
for (int i = 0; i < subTopic.size(); i++) {
if(topic.equals(subTopic.get(i))) {
subTopic.remove(i);
}
}
}
/**
* 重建订阅列表
*/
public void SubEmpty() {
subTopic = new ArrayList<String>();
//取消订阅按钮
for (int i = 0; i < chatSession.size(); i++) {
chatSession.get(i).SetSubEnable(false);
}
}
}
package top.luckysmile.mqtt.client.server;
import javax.swing.JOptionPane;
import org.eclipse.paho.client.mqttv3.MqttClient;
import org.eclipse.paho.client.mqttv3.MqttException;
import top.luckysmile.mqtt.client.data.MqttSetBeans;
import top.luckysmile.mqtt.client.view.MQTTChatView;
/**
* 客户端订阅函数,用于订阅的相关逻辑
* @author minuy
*
*/
public class MqttSubServer extends Thread {
MqttSetBeans set;
ViewOpt vo;
MqttClient mc;
MqttServerManage msm;
boolean isCreat;
MQTTChatView mcv;
/**
* 订阅并创建会话,需要调用.start函数运行
* @param set MQTTSetBean取得的数据,其中必须包含主题信息,否则调用无效
* @param vo 视图操作类,需要实现会话窗口的创建
* @param mC 已连接的MQTT客户端,未连接出错
* @param msm 回调用,完成订阅后添加到管理器的列表里
* @param en 是否已存在会话,存在则启用,未存在则创建
* @param mcv 如果上面存在,需要用到,会启用视图
*/
public MqttSubServer(MqttSetBeans set, ViewOpt vo, MqttClient mC, MqttServerManage msm,boolean en, MQTTChatView mcv) {
this.set = set;
this.vo = vo;
this.mc = mC;
this.msm = msm;
this.isCreat = en;
this.mcv = mcv;
}
/**
* 订阅消息
*/
@Override
public void run() {
vo.setSubBtnEanle(false);//按钮不可用
//确定此客户端当前是否连接到服务器。
if(!mc.isConnected()) {
return;
}
//是否得到了设置
if(set == null) {
return;
}
boolean isOk = true;
String topic = set.getSubTopic();
int qos = Integer.valueOf(set.getSubQos());
if(TextUtils.isEmpty(topic)) {
System.out.println("主题异常!");
return;
}
if(qos>2||qos<0) {
System.out.println("SubQos异常");
qos = 0;
}
vo.setSubBtnEanle(false);
//订阅
try {
mc.subscribe(topic,qos);
} catch (NumberFormatException e) {
System.out.println(e.toString());
isOk = false;
JOptionPane.showMessageDialog(null, e.toString(), "错误!", JOptionPane.ERROR_MESSAGE);
} catch (MqttException e) {
System.out.println(e.toString());
isOk = false;
JOptionPane.showMessageDialog(null, e.toString(), "错误!", JOptionPane.ERROR_MESSAGE);
}
if(isOk&&(!isCreat)) {
//订阅成功
MQTTChatView newView = vo.CreateSession(topic);
msm.addSession(newView);
}else {
if(mcv!=null) {
mcv.SetSubEnable(true);
}
}
if(isOk) {
msm.SubAdd(topic);
}
vo.setSubBtnEanle(true);//订阅按钮可用
}
}
package top.luckysmile.mqtt.client.server;
/**
* 字符处理类,感觉随机生成,判断长度的也是这里的
* @author minuy
*
*/
public class TextUtils {
public static boolean isEmpty(String in) {
if(in == null) {
return true;
}
if(in.equals("")) {
return true;
}
return false;
}
/**
* 计算字符串真实长度,汉字2个,英文数字1个
* @param value 要计算的字符串
* @return 长度
*/
public static int getStringLength(String value) {
int valueLength = 0;
String chinese = "[\u4e00-\u9fa5]";
for (int i = 0; i < value.length(); i++) {
String temp = value.substring(i, i + 1);
if (temp.matches(chinese)) {
valueLength += 2;
} else {
valueLength += 1;
}
}
return valueLength;
}
/**
* 用 java来截取中文英文字符串,过多的用省略号显示,中文占两个
* @param str 要处理的字符串
* @param maxLength 长度
* @return 处理后的字符串
* 互联网
*/
public static String subStringCN(final String str, final int maxLength, final int minLength) {
if (str == null) {
return str;
}
String suffix = "…";
int suffixLen = suffix.length();
final StringBuffer sbuffer = new StringBuffer();
final char[] chr = str.trim().toCharArray();
int len = 0;
for (int i = 0; i < chr.length; i++) {
if (chr[i] >= 0xa1) {
len += 2;
} else {
len++;
}
}
if(len<=maxLength){
if(len<minLength)
{
String newStr = str;
for(int i=0;i<(minLength-len);i++) {
newStr = newStr + " ";
}
return newStr;
}else {
return str;
}
}
len = 0;
for (int i = 0; i < chr.length; i++) {
if (chr[i] >= 0xa1) {
len += 2;
if (len + suffixLen > maxLength) {
break;
}else {
sbuffer.append(chr[i]);
}
} else {
len++;
if (len + suffixLen > maxLength) {
break;
}else {
sbuffer.append(chr[i]);
}
}
}
sbuffer.append(suffix);
return sbuffer.toString();
}
}
package top.luckysmile.mqtt.client.server;
import java.util.regex.Pattern;
import javax.swing.JOptionPane;
import top.luckysmile.mqtt.client.data.MqttSetBeans;
import top.luckysmile.mqtt.client.view.MQTTChatView;
import top.luckysmile.mqtt.client.view.MainView;
/**
* 关于主视图的所有操作
* @author minuy
*
*/
public class ViewOpt {
MainView mv;
public ViewOpt(MainView mv) {
this.mv = mv;
}
/**
* 设置ID输入框的字符串
* @param id
*/
public void SetClictID(String id) {
mv.getJtfId().setText(id);
}
/**
* 设置视图中状态的文字
* @param sta
*/
public void SetSta(String sta) {
mv.getJlbSta().setText(sta);
}
/**
* 获取主视图左侧的所有输入数据
* @param mv 主视图
* @return 一个Mqtt设置类,当为<code>null</code>时出错!
*/
public MqttSetBeans getMainViewData() {
MqttSetBeans set = new MqttSetBeans();
String data = null;
String tips = null;
tips = "域名";
data = mv.getJtfIp().getText();
if(TextUtils.isEmpty(data)) {
JOptionPane.showMessageDialog(null, tips + "不能为空!", "错误!", JOptionPane.ERROR_MESSAGE);
return null;
}
if(!(data.equals("localhost")||Pattern.matches("[a-zA-Z0-9][-a-zA-Z0-9]{0,62}(\\.[a-zA-Z0-9][-a-zA-Z0-9]{0,62})+\\.?", data)||Pattern.matches("(25[0-5]|2[0-4]\\d|[0-1]\\d{2}|[1-9]?\\d)\\.(25[0-5]|2[0-4]\\d|[0-1]\\d{2}|[1-9]?\\d)\\.(25[0-5]|2[0-4]\\d|[0-1]\\d{2}|[1-9]?\\d)\\.(25[0-5]|2[0-4]\\d|[0-1]\\d{2}|[1-9]?\\d)", data))) {
JOptionPane.showMessageDialog(null, tips + "格式不正确!", "错误!", JOptionPane.ERROR_MESSAGE);
return null;
}
set.setIp(data);
tips = "端口号";
data = mv.getJtfPort().getText();
if(TextUtils.isEmpty(data)) {
JOptionPane.showMessageDialog(null, tips + "不能为空!", "错误!", JOptionPane.ERROR_MESSAGE);
return null;
}
if(!Pattern.matches("[1-9]\\d*", data)) {
JOptionPane.showMessageDialog(null, tips + "格式不正确!", "错误!", JOptionPane.ERROR_MESSAGE);
return null;
}
if(Integer.valueOf(data)>65535) {
JOptionPane.showMessageDialog(null, tips + "范围不正确!(1-65535)", "错误!", JOptionPane.ERROR_MESSAGE);
}
set.setPort(data);
tips = "识标符";
data = mv.getJtfId().getText();
if(TextUtils.isEmpty(data)) {
JOptionPane.showMessageDialog(null, tips + "不能为空!", "错误!", JOptionPane.ERROR_MESSAGE);
return null;
}
if(data.length()>65535) {
JOptionPane.showMessageDialog(null, tips + "长度不能大于65535!", "错误!", JOptionPane.ERROR_MESSAGE);
return null;
}
set.setId(data);
tips = "账号";
data = mv.getJtfName().getText();
if(data.length()>65535) {
JOptionPane.showMessageDialog(null, tips + "长度不能大于65535!", "错误!", JOptionPane.ERROR_MESSAGE);
return null;
}
set.setName(data);
tips = "密码";
data = String.valueOf(mv.getJpfPasswd().getPassword());
if(data.length()>65535) {
JOptionPane.showMessageDialog(null, tips + "长度不能大于65535!", "错误!", JOptionPane.ERROR_MESSAGE);
return null;
}
set.setPasswd(data);
tips = "遗嘱主题";
data = mv.getJtfLWTTopic().getText();
if(data.length()>65535) {
JOptionPane.showMessageDialog(null, tips + "长度不能大于65535!", "错误!", JOptionPane.ERROR_MESSAGE);
return null;
}
set.setLWTTopic(data);
tips = "订阅主题";
data = mv.getJtfSubscribeTopic().getText();
if(data.length()>65535) {
JOptionPane.showMessageDialog(null, tips + "长度不能大于65535!", "错误!", JOptionPane.ERROR_MESSAGE);
return null;
}
set.setSubTopic(data);
tips = "发布主题";
data = mv.getJtfContextTopic().getText();
if(data.length()>65535) {
JOptionPane.showMessageDialog(null, tips + "长度不能大于65535!", "错误!", JOptionPane.ERROR_MESSAGE);
return null;
}
set.setPubTopic(data);
//遗嘱内容
set.setLWTContext(mv.getJtfLWTContext().getText());
//消息内容
set.setPubContext(mv.getJtaContext().getText());
System.out.println(set.getPubContext());
set.setLWTQos(String.valueOf(mv.getJcbLWTQos().getSelectedIndex()));
set.setSubQos(String.valueOf(mv.getJcbTopicQos().getSelectedIndex()));
set.setPubQos(String.valueOf(mv.getJcbSendQos().getSelectedIndex()));
return set;
}
/**
* 设置连接按钮的文字
* @param str
*/
public void SetConnetButtonStr(String str) {
mv.getJbtConnect().setText(str);
}
/**
* 设置连接按钮是否可用
* @param ea
*/
public void SetConnetButtonEable(boolean ea) {
mv.getJbtConnect().setEnabled(ea);
}
/**
* 获取密码
* @return 密码
*/
public char[] getViewPasswd() {
return mv.getJpfPasswd().getPassword();
}
/**
* 设置登录面板的可编辑性
* @param en
*/
public void SetLoginEnable(boolean en) {
mv.getJtfIp().setEditable(en);
mv.getJtfPort().setEditable(en);
mv.getJtfId().setEditable(en);
mv.getJtfName().setEditable(en);
mv.getJpfPasswd().setEditable(en);
mv.getJtfLWTContext().setEditable(en);
mv.getJtfLWTTopic().setEditable(en);
mv.getJcbLWTQos().setEnabled(en);
mv.getJbtRandId().setEnabled(en);
if(en) {
SetRSendEnable(false);
}else {
SetRSendEnable(true);
}
}
/**
* 设置订阅按钮是否可按下
* @param b
*/
public void setSubBtnEanle(boolean b) {
mv.getJbtSubscribe().setEnabled(b);
}
/**
* 设置窗口副标题
* @param sub
*/
public void setSubhead(String sub) {
mv.setTitle("MQTT客户端 - " + sub);
}
/**
* 创建一个会话视图
* @param topic
* @return 一个会话视图
*/
public MQTTChatView CreateSession(String topic) {
MQTTChatView mcv = new MQTTChatView();//新建一个视图
mcv.getJlbChatTopic().setText(topic);//设置标题
topic = TextUtils.subStringCN(topic,8,8);//截取长度
mv.getJtpChat().addTab(topic, mcv);//添加到视图
return mcv;
}
/**
* 根据标题关闭一个选项卡
* @param topic
*/
public void CloseSessionWindow(String topic) {
int index = mv.getJtpChat().indexOfTab(TextUtils.subStringCN(topic, 8, 8));
if(index == -1) {
System.out.println("不存在此选项卡!");
}
mv.getJtpChat().remove(index);
}
/**
* 设置订阅和发送按钮的可用状态
* @param en
*/
public void SetRSendEnable(boolean en) {
mv.getJbtSubscribe().setEnabled(en);//订阅
mv.getJbtSend().setEnabled(en);
}
/**
* 设置发送状态,一般在发送的时候打开,收到的时候关闭
* @param en
*/
public void SetSendSta(boolean en) {
if(en) {
mv.getJlbSta().setText("...");
}else {
mv.getJlbSta().setText("");
}
}
}
package top.luckysmile.mqtt.client.server;
import java.util.List;
import javax.swing.JOptionPane;
import org.eclipse.paho.client.mqttv3.MqttClient;
import org.eclipse.paho.client.mqttv3.MqttException;
import top.luckysmile.mqtt.client.view.MQTTChatView;
/**
* 取消订阅,会话列表里的按钮最终触发的事件
* @author minuy
*
*/
public class closeTopic {
/**
* 取消订阅并关闭会话视图
* @param vo 视图操作类,用于关闭会话视图
* @param MC Mqtt客户端对象,取消订阅用
* @param chatSession 管理器的视图列表,用于查找关闭是否有效
* @param mcv 发起取消订阅请求的视图,用于搜索
* @param mqttServerManage 管理器,回调用
*/
public closeTopic(ViewOpt vo,MqttClient MC,List<MQTTChatView> chatSession,MQTTChatView mcv, MqttServerManage mqttServerManage) {
//找主题
for (int i = 0; i < chatSession.size(); i++) {
//如果会话主题和要关闭的主题相同
if(mcv.getJlbChatTopic().getText().equals(chatSession.get(i).getJlbChatTopic().getText())) {
try {
//取消订阅主题
MC.unsubscribe(mcv.getJlbChatTopic().getText());
//把主题从主题列表和视图列表中删除
mqttServerManage.SubDrop(mcv.getJlbChatTopic().getText());
mqttServerManage.removeSession(mcv);
//关闭视图
vo.CloseSessionWindow(mcv.getJlbChatTopic().getText());
} catch (MqttException e) {
System.out.println(e.toString());
JOptionPane.showMessageDialog(null, "没有订阅这个主题!","错误",2);
}
}
}
}
}
package top.luckysmile.mqtt.client.view;
import java.awt.Color;
import java.awt.Font;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import top.luckysmile.mqtt.client.listen.ChatViewListen;
/**
* 会话界面
* @author minuy
*
*/
public class MQTTChatView extends JPanel {
/**
* 消息界面
*/
private static final long serialVersionUID = 2L;
JPanel jpnChatMain;//总底子
JPanel jpnChatSend;//发送
JScrollPane jspChatMassage;//消息
JPanel jpnChatMassage;//取消订阅
JTextArea jtaMassage;//消息框
JLabel jlbChatTopic;//消息主题
JLabel jlbStatistics;//消息计数
int StatisticsN = 0;//消息计数
JLabel jlbTip;//发送使用提示
JTextArea jtaChatSend;//发送消息输入
JButton jbtChatClear;//清除输入
JButton jbtChatSend;//发送
JButton jbtQuitSub;//取消订阅
JComboBox<String> jcbQos;
String[] items = {"Qos0","Qos1","Qos2"};
Font defFont;
/**
* 创建会话界面
*/
public MQTTChatView() {
defFont = new Font("微软雅黑", Font.PLAIN, 12);
jpnChatMain = new JPanel();//总底子
jspChatMassage = new JScrollPane();//消息
jpnChatSend = new JPanel();//发送
jpnChatMassage = new JPanel();//消息
jtaMassage = new JTextArea();//消息框
jlbChatTopic = new JLabel("主题");//消息主题
jlbStatistics = new JLabel("接收到的字节数:0");//消息计数
jlbTip = new JLabel("消息会发送到该主题内哦~");//发送使用提示
jtaChatSend = new JTextArea();//发送消息输入
jbtChatClear = new JButton("清空消息");//清除输入
jbtChatSend = new JButton("发送至当前主题");//发送
jbtQuitSub = new JButton("取消订阅");
jcbQos = new JComboBox<String>(items);
InitMqttChatView();
}
private void InitMqttChatView() {
jlbChatTopic.setBounds(0, 0, 150, 25);//主题
jlbChatTopic.setFont(defFont);
jlbStatistics.setBounds(155, 0, 210, 25);//统计
jlbStatistics.setFont(defFont);
jtaMassage.setBounds(0, 0, 310, 245);
jtaMassage.setFont(defFont);
jtaMassage.setEditable(false);//设置不可编辑
jtaMassage.setLineWrap(true);// 如果内容过长。自动换行
//添加滑动条
jspChatMassage.setViewportView(jtaMassage);
jspChatMassage.setBounds(0, 25, 310, 255);
jpnChatMassage.setLayout(null);
jpnChatMassage.add(jlbChatTopic);
jpnChatMassage.add(jspChatMassage);
jpnChatMassage.add(jlbStatistics);
//发送
jlbTip.setBounds(0, 0, 150, 25);//提示
jlbTip.setForeground(Color.blue);
jlbTip.setFont(defFont);
jcbQos.setBounds(150, 0, 74, 25);
jcbQos.setFont(defFont);
jbtQuitSub.setBounds(225, 0, 80, 25);//取消订阅
jbtQuitSub.setFont(defFont);
jbtChatClear.setBounds(0, 70, 90, 25);//清除
jbtChatClear.setFont(defFont);
jbtChatSend.setBounds(185, 70, 120, 25);//发送
jbtChatSend.setFont(defFont);
jtaChatSend.setBounds(0, 27, 310, 41);//输入框
jtaChatSend.setFont(defFont);
jpnChatSend.setLayout(null);
jpnChatSend.add(jcbQos);
jpnChatSend.add(jlbTip);
jpnChatSend.add(jtaChatSend);
jpnChatSend.add(jbtChatClear);
jpnChatSend.add(jbtChatSend);
jpnChatSend.add(jbtQuitSub);
//监听
ActionListener chatAL = new ChatViewListen(this);
jbtChatClear.addActionListener(chatAL);
jbtChatSend.addActionListener(chatAL);
jbtQuitSub.addActionListener(chatAL);
jpnChatMassage.setBounds(5, 0, 310, 290);
jpnChatSend.setBounds(5, 296, 310, 110);
jpnChatMain.setLayout(null);
jpnChatMain.setBounds(0, 0, 320, 405);//总底子
jpnChatMain.add(jpnChatMassage);
jpnChatMain.add(jpnChatSend);
this.setLayout(null);
this.setBounds(0, 0, 320, 405);
this.add(jpnChatMain);
}
public JTextArea getJtaMassage() {
return jtaMassage;
}
public JTextArea getJtaChatSend() {
return jtaChatSend;
}
public JButton getJbtChatClear() {
return jbtChatClear;
}
public JButton getJbtChatSend() {
return jbtChatSend;
}
public JButton getJbtQuitSub() {
return jbtQuitSub;
}
public JLabel getJlbChatTopic() {
return jlbChatTopic;
}
public JComboBox<String> getJcbQos(){
return jcbQos;
}
/**
* 订阅状态设置
*/
public void SetSubEnable(boolean en) {
if(en) {
jbtQuitSub.setBounds(225, 0, 80, 25);//取消订阅
jbtQuitSub.setFont(defFont);
jcbQos.setBounds(150, 0, 74, 25);
jcbQos.setFont(defFont);
jpnChatSend.add(jcbQos);
jpnChatSend.add(jbtQuitSub);
jpnChatSend.updateUI();
}else {
jcbQos.setBounds(231, 0, 74, 25);
jcbQos.setFont(defFont);
jpnChatSend.remove(jbtQuitSub);
jpnChatSend.updateUI();
}
}
public JLabel getJlbStatistics() {
return jlbStatistics;
}
public int getStatisticsN() {
return StatisticsN;
}
public void setStatisticsN(int statisticsN) {
StatisticsN = statisticsN;
}
}
package top.luckysmile.mqtt.client.view;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.Toolkit;
import java.awt.event.ActionListener;
import java.awt.event.WindowEvent;
import javax.swing.BorderFactory;
import javax.swing.DefaultComboBoxModel;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JPasswordField;
import javax.swing.JTabbedPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import top.luckysmile.mqtt.client.data.MqttDAO;
import top.luckysmile.mqtt.client.data.MqttSetBeans;
import top.luckysmile.mqtt.client.listen.MqttMainViewActionListener;
import top.luckysmile.mqtt.client.server.TextUtils;
/**
* 主界面,四个板块,登录,订阅,发送和会话
* @author minuy
*
*/
public class MainView extends JFrame {
/**
* 主面板,负责登录,发送,订阅和推送
*/
private static final long serialVersionUID = 1L;
Font defFont;//默认字体
private JPanel jpnMain;//主面板
private JPanel jpnLogin;//登录面板
private JPanel jpnSubscribe;//订阅面板
private JPanel jpnPublish;//发送面板
private JPanel jpnChat;//消息面板
private JPanel jpnImage;//图片面板
private JLabel jlbIp;//IP标签
private JTextField jtfIp;//IP输入框
private JLabel jlbPort;//端口
private JTextField jtfPort;//端口输入框
private JLabel jlbId;//识标符
private JTextField jtfId;//识标符输入框
private JButton jbtRandId;//随机识标符
private JLabel jlbName;//账号
private JTextField jtfName;//账号输入框
private JLabel jlbPasswd;//密码
private JPasswordField jpfPasswd;//密码输入框
private JLabel jlbLWT;//遗言
private JTextField jtfLWTTopic;//遗言主题输入框
private JTextField jtfLWTContext;//遗言内容输入框
private JComboBox<String> jcbLWTQos;//遗言服务质量
private JButton jbtConnect;//连接按钮
private JLabel jlbSta;//连接状态
private JButton jbtMoreSet;//更多设置
private JLabel jlbTopic;//订阅主题
private JTextField jtfSubscribeTopic;//订阅主题输入框
private JComboBox<String> jcbTopicQos;//订阅服务质量
private JButton jbtSubscribe;//订阅按钮
private JLabel jlbSend;//消息发送
private JTextArea jtaContext;//消息内容
private JTextField jtfContextTopic;//消息主题输入框
private JComboBox<String> jcbSendQos;//消息服务质量
private JButton jbtSend;//发送
private JLabel jlbSendTopic;
private JLabel jlbSendsta;//消息状态指示
private JTabbedPane jtpChat;//消息列表
private JLabel jlbPicture;
String[] MqttQos = {"Qos0","Qos1","Qos2"};
DefaultComboBoxModel<String> cbmMqttQos1;
DefaultComboBoxModel<String> cbmMqttQos2;
DefaultComboBoxModel<String> cbmMqttQos3;
/**
* 创建主视图
*/
public MainView() {
defFont = new Font("微软雅黑", Font.PLAIN, 12);
cbmMqttQos1 = new DefaultComboBoxModel<String>(MqttQos);
cbmMqttQos2 = new DefaultComboBoxModel<String>(MqttQos);
cbmMqttQos3 = new DefaultComboBoxModel<String>(MqttQos);
jpnMain = new JPanel();//主面板
jpnLogin = new JPanel();//登录面板
jpnSubscribe = new JPanel();//订阅面板
jpnPublish = new JPanel();//发送面板
jpnChat = new JPanel();//消息面板
jlbIp = new JLabel("域名:");//IP标签
jtfIp = new JTextField();//IP输入框
jlbPort = new JLabel("端口:");//端口
jtfPort = new JTextField();//端口输入框
jlbId = new JLabel("识标符:");//识标符
jbtRandId = new JButton("*");
jtfId = new JTextField();//识标符输入框
jlbName = new JLabel("账号:");//账号
jtfName = new JTextField();//账号输入框
jlbPasswd = new JLabel("密码:");//密码
jpfPasswd = new JPasswordField();//密码输入框
jlbLWT = new JLabel("遗言:");//遗言
jtfLWTTopic = new JTextField();//遗言主题输入框
jtfLWTContext = new JTextField();//遗言内容输入框
jcbLWTQos = new JComboBox<String>();//遗言服务质量
jbtConnect = new JButton("连接");//连接按钮
jlbSta = new JLabel("未连接",JLabel.CENTER);//连接状态
jbtMoreSet = new JButton("更多");//更多设置
jlbTopic = new JLabel("订阅主题:");//订阅主题
jtfSubscribeTopic = new JTextField();//订阅主题输入框
jcbTopicQos = new JComboBox<String>();//订阅服务质量
jbtSubscribe = new JButton("订阅");//订阅按钮
jlbSend = new JLabel("发布消息:");//发布消息
jtaContext = new JTextArea();//消息内容
jtfContextTopic = new JTextField();//消息主题输入框
jcbSendQos = new JComboBox<String>();//消息服务质量
jlbSendTopic = new JLabel("主题:");
jbtSend = new JButton("发送");
jlbSendsta = new JLabel();
jtpChat = new JTabbedPane(JTabbedPane.LEFT);//消息列表
jlbPicture = new JLabel();
MainInit();
SetMainViewData();
//窗口使能
this.setVisible(true);
}
private void MainInit() {
//设置标题
this.setTitle("MQTT客户端");
//设置窗口可关闭,退出的方式有多种,exit和dispose
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//设置窗口大小
this.setSize(720,480);
//窗口居中
this.setLocationRelativeTo(null);
//不允许用户调整窗口大小
this.setResizable(false);
//设置容器布局方式为空布局
jpnMain.setLayout(null);
//默认是界面获得焦点
jpnMain.setFocusable(true);
/**
* 没有用,不好看
*/
//觉得单调,加张图片
//不知道加什么图片好,网上随意搜集了一幅图
jpnImage = new JPanel() {
//定义一张图片,新建一个ImageIcon对象并调用getImage方法获得一个Image对象
/**
* jpanel类不支持设置背景图,需要重写paintComponent方法
*/
private static final long serialVersionUID = 2019L;
private Image image = new ImageIcon("res/main_photo.png").getImage();
//这里系统要调用这个paintComponent方法来画这张图片,这里系统传入了一个Graphics对象(画笔),
//我们需要用这个对象来画背景图片
protected void paintComponent(Graphics g) {
//调用画笔的drawImage方法,参数是要画的图片,初始坐标,结束坐标,和在哪里画,this代表是LoginWin这
//个“画布”对象
g.drawImage(image, 0, 0, this.getWidth(), this.getHeight(), this);
}
//实现背景图
};
//设置为空布局
jpnLogin.setLayout(null);
jpnSubscribe.setLayout(null);
jpnPublish.setLayout(null);
jpnChat.setLayout(null);
jpnImage.setLayout(null);
//宽高,宽高,横竖
jlbIp.setBounds(0, 0, 35, 25);//IP:
jlbIp.setFont(defFont);
jtfIp.setBounds(35, 0, 124, 25);//输入IP
jtfIp.setFont(defFont);
jlbPort.setBounds(167, 0, 35, 25);//端口:
jlbPort.setFont(defFont);
jtfPort.setBounds(202, 0, 48, 25);//输入端口
jtfPort.setFont(defFont);
jlbId.setBounds(0, 27, 47, 25);//识标符:
jlbId.setFont(defFont);
jtfId.setBounds(47, 27, 173, 25);//输入识标符
jtfId.setFont(defFont);
jbtRandId.setBounds(225, 27, 25, 25);
jbtRandId.setFont(defFont);
jlbName.setBounds(0, 54, 35, 25);//账号:
jlbName.setFont(defFont);
jtfName.setBounds(35, 54, 100, 25);//输入账号
jtfName.setFont(defFont);
jlbPasswd.setBounds(140, 54, 35, 25);//密码:
jlbPasswd.setFont(defFont);
jpfPasswd.setBounds(175, 54, 75, 25);//输入密码
jlbLWT.setBounds(0, 81, 35, 25);//遗言:
jlbLWT.setFont(defFont);
jtfLWTTopic.setBounds(35, 81, 136, 25);//遗言主题
jtfLWTTopic.setFont(defFont);
jcbLWTQos.setBounds(176, 81, 74, 25);//遗言质量
jcbLWTQos.setFont(defFont);
jcbLWTQos.setModel(cbmMqttQos1);//遗言质量
jtfLWTContext.setBounds(35, 108, 215, 25);//遗言内容
jtfLWTContext.setFont(defFont);
jbtMoreSet.setBounds(0, 135, 70, 25);//更多
jbtMoreSet.setFont(defFont);
jlbSta.setBounds(95, 144, 60, 16);//状态
jlbSta.setForeground(Color.red);
jlbSta.setFont(defFont);
jbtConnect.setBounds(180, 135, 70, 25);//连接
jbtConnect.setFont(defFont);
jpnLogin.add(jlbIp);//IP:
jpnLogin.add(jtfIp);//输入IP
jpnLogin.add(jlbPort);//端口:
jpnLogin.add(jtfPort);//输入端口
jpnLogin.add(jlbId);//识标符:
jpnLogin.add(jtfId);//输入识标符
jpnLogin.add(jbtRandId);//随机
jpnLogin.add(jlbName);//账号:
jpnLogin.add(jtfName);//输入账号
jpnLogin.add(jlbPasswd);//密码:
jpnLogin.add(jpfPasswd);//输入密码
jpnLogin.add(jlbLWT);//遗言:
jpnLogin.add(jtfLWTTopic);//遗言主题
jpnLogin.add(jtfLWTContext);//遗言内容
jpnLogin.add(jcbLWTQos);//遗言质量
jpnLogin.add(jcbLWTQos);//遗言质量
jpnLogin.add(jbtConnect);//连接
jpnLogin.add(jlbSta);//状态
jpnLogin.add(jbtMoreSet);//更多
jlbTopic.setBounds(0, 0, 54, 25);
jlbTopic.setFont(defFont);
jtfSubscribeTopic.setBounds(0, 27, 100, 25);//订阅主题输入框
jtfSubscribeTopic.setFont(defFont);
jcbTopicQos.setBounds(176, 27, 74, 25);//订阅服务质量
jcbTopicQos.setModel(cbmMqttQos2);//设置默认质量
jcbTopicQos.setFont(defFont);
jbtSubscribe.setBounds(111, 27, 55, 25);//订阅按钮
jbtSubscribe.setEnabled(false);
jbtSubscribe.setFont(defFont);
jpnSubscribe.add(jlbTopic);
jpnSubscribe.add(jtfSubscribeTopic);
jpnSubscribe.add(jcbTopicQos);
jpnSubscribe.add(jbtSubscribe);
jlbSend.setBounds(0, 0, 54, 25);
jlbSend.setFont(defFont);
jtaContext.setBounds(0, 27, 250, 66);//消息内容
jtaContext.setFont(defFont);
jtfContextTopic.setBounds(110, 98, 140, 25);//消息主题输入框
jtfContextTopic.setFont(defFont);
jcbSendQos.setBounds(0, 98, 74, 25);//消息服务质量
jcbSendQos.setModel(cbmMqttQos3);
jcbSendQos.setFont(defFont);
jbtSend.setBounds(200, 125, 50, 25);//发送
jbtSend.setEnabled(false);
jbtSend.setFont(defFont);
jlbSendsta.setBounds(50, 125, 20, 25);//状态指示
jlbSendTopic.setBounds(78, 98, 35, 25);//主题
jlbSendTopic.setFont(defFont);
jpnPublish.add(jlbSend);
jpnPublish.add(jtaContext);
jpnPublish.add(jtfContextTopic);
jpnPublish.add(jcbSendQos);
jpnPublish.add(jbtSend);
jpnPublish.add(jlbSendTopic);
jpnPublish.add(jlbSendsta);
jtpChat.setBounds(0, 0, 400, 405);//消息列表
jtpChat.setFont(defFont);
jtpChat.setPreferredSize(new Dimension(320,405));
jlbPicture.setBounds(115, 115, 170, 170);
//实例化ImageIcon 对象
ImageIcon image = new ImageIcon("res/photo.jpg");
//得到Image对象
Image img = image.getImage();
//创建缩放版本
img = img.getScaledInstance(170,170, Image.SCALE_DEFAULT);
//替换为缩放版本
image.setImage(img);
jlbPicture.setIcon(image);
jlbPicture.setBorder(BorderFactory.createLoweredBevelBorder());
// jtpChat.addTab("会话会话", new MQTTChatView());
// jtpChat.addTab("会话会话", new MQTTChatView());
// JLabel my = new JLabel("Minuy");
// my.setBounds(100, 100, 100, 100);
// jpnChat.add(my);
//加一层图片
jpnImage.add(jtpChat);
jpnChat.add(jtpChat);//没有图片
jpnChat.add(jlbPicture);//没有图片
// jpnChat.add(jpnImage);
//增加按钮监听,监听类自己设计
ActionListener mqttMainView = new MqttMainViewActionListener(this);
jbtConnect.addActionListener(mqttMainView);
jbtRandId.addActionListener(mqttMainView);
jbtMoreSet.addActionListener(mqttMainView);
jbtSend.addActionListener(mqttMainView);
jbtSubscribe.addActionListener(mqttMainView);
//块大小
jpnLogin.setBounds(5,5,260,170);//登录模块
jpnSubscribe.setBounds(5, 175, 260, 62);//订阅
jpnPublish.setBounds(5, 242, 260, 163);//发布
jpnChat.setBounds(260, 0, 400, 405);//聊天
jpnImage.setBounds(0, 0, 400, 405);//图片
//设置边距
//jpnLogin.
//配置内容视图边框
jpnLogin.setBorder(BorderFactory.createMatteBorder(0, 0, 1, 0, Color.GRAY));
jpnSubscribe.setBorder(BorderFactory.createMatteBorder(0, 0, 1, 0, Color.GRAY));
jpnChat.setBorder(BorderFactory.createMatteBorder(0, 1, 0, 0, Color.GRAY));
//把设置好的控件全加到画布里
jpnMain.add(jpnChat);
jpnMain.add(jpnLogin);
jpnMain.add(jpnSubscribe);
jpnMain.add(jpnPublish);
//把画布放到窗口里
this.add(jpnMain);
Image icon = Toolkit.getDefaultToolkit().getImage("res/mqttorg-glow.png");
this.setIconImage(icon);
System.out.println("初始化窗口成功!");
}
/**
* 重写窗口的事件中转方法,程序是从这个方法processWindowEvent进入到窗口关闭事件的
*/
@Override
protected void processWindowEvent(WindowEvent e)
{
//这里需要对进来的WindowEvent进行判断,因为,不仅会有窗口关闭的WindowEvent进来,还可能有其他的WindowEvent进来
if (e.getID() == WindowEvent.WINDOW_CLOSING)
{
int option = JOptionPane.showConfirmDialog(null, "是否关闭?", "退出提示", JOptionPane.OK_CANCEL_OPTION);
if (option == JOptionPane.OK_OPTION)
{
//用户选择关闭程序,以上代码提示后确认传给父类处理
super.processWindowEvent(e);
}
else {
//用户选择不退出程序,这里把关闭事件截取
return;
}
}
else {
//如果是其他事件,交给父类处理
super.processWindowEvent(e);
}
}
/**
* 从数据库读取上次记录的数据
*/
private void SetMainViewData() {
//从数据库里获取数据
MqttSetBeans set = new MqttDAO().getSeting();
if(set != null) {
//判断不为空
if(!TextUtils.isEmpty(set.getId())) {
jtfId.setText(set.getId());
}
//判断不为空
if(!TextUtils.isEmpty(set.getIp())) {
jtfIp.setText(set.getIp());
}
//判断不为空
if(!TextUtils.isEmpty(set.getPort())) {
jtfPort.setText(set.getPort());
}
//判断不为空
if(!TextUtils.isEmpty(set.getName())) {
jtfName.setText(set.getName());
}
//判断不为空
if(!TextUtils.isEmpty(set.getPasswd())) {
jpfPasswd.setText(set.getPasswd());
}
//判断不为空
if(!TextUtils.isEmpty(set.getLWTTopic())) {
jtfLWTTopic.setText(set.getLWTTopic());
}
//判断不为空
if(!TextUtils.isEmpty(set.getLWTContext())) {
jtfLWTContext.setText(set.getLWTContext());
}
//判断不为空
if(!TextUtils.isEmpty(set.getSubTopic())) {
jtfSubscribeTopic.setText(set.getSubTopic());
}
//判断不为空
if(!TextUtils.isEmpty(set.getPubContext())) {
jtaContext.setText(set.getPubContext());
}
//判断不为空
if(!TextUtils.isEmpty(set.getPubTopic())) {
jtfContextTopic.setText(set.getPubTopic());
}
if(!TextUtils.isEmpty(set.getLWTQos())) {
jcbLWTQos.setSelectedIndex(Integer.valueOf(set.getLWTQos()));
}
if(!TextUtils.isEmpty(set.getSubQos())) {
jcbTopicQos.setSelectedIndex(Integer.valueOf(set.getSubQos()));
}
if(!TextUtils.isEmpty(set.getPubQos())) {
jcbSendQos.setSelectedIndex(Integer.valueOf(set.getPubQos()));
}
}
}
public JTextField getJtfId() {
return jtfId;
}
public void setJtfId(JTextField jtfId) {
this.jtfId = jtfId;
}
public JButton getJbtConnect() {
return jbtConnect;
}
public void setJbtConnect(JButton jbtConnect) {
this.jbtConnect = jbtConnect;
}
public JTextField getJtfIp() {
return jtfIp;
}
public JTextField getJtfPort() {
return jtfPort;
}
public JButton getJbtRandId() {
return jbtRandId;
}
public JTextField getJtfName() {
return jtfName;
}
public JPasswordField getJpfPasswd() {
return jpfPasswd;
}
public JTextField getJtfLWTTopic() {
return jtfLWTTopic;
}
public JTextField getJtfLWTContext() {
return jtfLWTContext;
}
public JComboBox<String> getJcbLWTQos() {
return jcbLWTQos;
}
public JLabel getJlbSendsta() {
return jlbSendsta;
}
public JLabel getJlbSta() {
return jlbSta;
}
public JButton getJbtMoreSet() {
return jbtMoreSet;
}
public JTextField getJtfSubscribeTopic() {
return jtfSubscribeTopic;
}
public JComboBox<String> getJcbTopicQos() {
return jcbTopicQos;
}
public JButton getJbtSubscribe() {
return jbtSubscribe;
}
public JTextArea getJtaContext() {
return jtaContext;
}
public JTextField getJtfContextTopic() {
return jtfContextTopic;
}
public JComboBox<String> getJcbSendQos() {
return jcbSendQos;
}
public JButton getJbtSend() {
return jbtSend;
}
public DefaultComboBoxModel<String> getCbmMqttQos1() {
return cbmMqttQos1;
}
public DefaultComboBoxModel<String> getCbmMqttQos2() {
return cbmMqttQos2;
}
public DefaultComboBoxModel<String> getCbmMqttQos3() {
return cbmMqttQos3;
}
public JTabbedPane getJtpChat() {
return jtpChat;
}
}
/*******************************************************************************
* Copyright (c) 2016 IBM Corp.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* and Eclipse Distribution License v1.0 which accompany this distribution.
*
* The Eclipse Public License is available at
* http://www.eclipse.org/legal/epl-v10.html
* and the Eclipse Distribution License is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* Contributors:
* James Sutton - Initial Contribution for Automatic Reconnect & Offline Buffering
*/
package org.eclipse.paho.client.mqttv3;
import org.eclipse.paho.client.mqttv3.internal.wire.MqttWireMessage;
/**
* A BufferedMessage contains an MqttWire Message and token
* it allows both message and token to be buffered when the client
* is in resting state
*/
public class BufferedMessage {
private MqttWireMessage message;
private MqttToken token;
public BufferedMessage(MqttWireMessage message, MqttToken token){
this.message = message;
this.token = token;
}
public MqttWireMessage getMessage() {
return message;
}
public MqttToken getToken() {
return token;
}
}
/*******************************************************************************
* Copyright (c) 2016 IBM Corp.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* and Eclipse Distribution License v1.0 which accompany this distribution.
*
* The Eclipse Public License is available at
* http://www.eclipse.org/legal/epl-v10.html
* and the Eclipse Distribution License is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* Contributors:
* James Sutton - Initial Contribution for Automatic Reconnect & Offline Buffering
*/
package org.eclipse.paho.client.mqttv3;
/**
* Holds the set of options that govern the behaviour
* of Offline (or Disconnected) buffering of messages
*/
public class DisconnectedBufferOptions {
/**
* The default size of the disconnected buffer
*/
public static final int DISCONNECTED_BUFFER_SIZE_DEFAULT = 5000;
public static final boolean DISCONNECTED_BUFFER_ENABLED_DEFAULT = false;
public static final boolean PERSIST_DISCONNECTED_BUFFER_DEFAULT = false;
public static final boolean DELETE_OLDEST_MESSAGES_DEFAULT = false;
private int bufferSize = DISCONNECTED_BUFFER_SIZE_DEFAULT;
private boolean bufferEnabled = DISCONNECTED_BUFFER_ENABLED_DEFAULT;
private boolean persistBuffer = PERSIST_DISCONNECTED_BUFFER_DEFAULT;
private boolean deleteOldestMessages = DELETE_OLDEST_MESSAGES_DEFAULT;
/**
* Constructs a new <code>DisconnectedBufferOptions</code> object using the
* default values.
*
* The defaults are:
* <ul>
* <li>The disconnected buffer is disabled</li>
* <li>The buffer holds 5000 messages</li>
* <li>The buffer is not persisted</li>
* <li>Once the buffer is full, old messages are not deleted</li>
* </ul>
* More information about these values can be found in the setter methods.
*/
public DisconnectedBufferOptions() {
// Do Nothing.
}
public int getBufferSize() {
return bufferSize;
}
public void setBufferSize(int bufferSize) {
if (bufferSize < 1) {
throw new IllegalArgumentException();
}
this.bufferSize = bufferSize;
}
public boolean isBufferEnabled() {
return bufferEnabled;
}
public void setBufferEnabled(boolean bufferEnabled) {
this.bufferEnabled = bufferEnabled;
}
public boolean isPersistBuffer() {
return persistBuffer;
}
public void setPersistBuffer(boolean persistBuffer) {
this.persistBuffer = persistBuffer;
}
public boolean isDeleteOldestMessages() {
return deleteOldestMessages;
}
public void setDeleteOldestMessages(boolean deleteOldestMessages) {
this.deleteOldestMessages = deleteOldestMessages;
}
}
package org.eclipse.paho.client.mqttv3;
/**
* Implementors of this interface will be notified when an asynchronous action completes.
*
* <p>A listener is registered on an MqttToken and a token is associated
* with an action like connect or publish. When used with tokens on the MqttAsyncClient
* the listener will be called back on the MQTT client's thread. The listener will be informed
* if the action succeeds or fails. It is important that the listener returns control quickly
* otherwise the operation of the MQTT client will be stalled.
* </p>
*/
public interface IMqttActionListener {
/**
* This method is invoked when an action has completed successfully.
* @param asyncActionToken associated with the action that has completed
*/
public void onSuccess(IMqttToken asyncActionToken );
/**
* This method is invoked when an action fails.
* If a client is disconnected while an action is in progress
* onFailure will be called. For connections
* that use cleanSession set to false, any QoS 1 and 2 messages that
* are in the process of being delivered will be delivered to the requested
* quality of service next time the client connects.
* @param asyncActionToken associated with the action that has failed
* @param exception thrown by the action that has failed
*/
public void onFailure(IMqttToken asyncActionToken, Throwable exception);
}
package org.eclipse.paho.client.mqttv3;
/**
* Provides a mechanism for tracking the delivery of a message.
*
* <p>A subclass of IMqttToken that allows the delivery of a message to be tracked.
* Unlike instances of IMqttToken delivery tokens can be used across connection
* and client restarts. This enables the delivery of a messages to be tracked
* after failures. There are two approaches
* <ul>
* <li>A list of delivery tokens for in-flight messages can be obtained using
* {@link IMqttAsyncClient#getPendingDeliveryTokens()}. The waitForCompletion
* method can then be used to block until the delivery is complete.
* <li>A {@link MqttCallback} can be set on the client. Once a message has been
* delivered the {@link MqttCallback#deliveryComplete(IMqttDeliveryToken)} method will
* be called withe delivery token being passed as a parameter.
* </ul>
* <p>
* An action is in progress until either:</p>
* <ul>
* <li>isComplete() returns true or </li>
* <li>getException() is not null. If a client shuts down before delivery is complete
* an exception is returned. As long as the Java Runtime is not stopped a delivery token
* is valid across a connection disconnect and reconnect. In the event the client
* is shut down the getPendingDeliveryTokens method can be used once the client is
* restarted to obtain a list of delivery tokens for inflight messages.</li>
* </ul>
*
*/
public interface IMqttDeliveryToken extends IMqttToken {
/**
* Returns the message associated with this token.
* <p>Until the message has been delivered, the message being delivered will
* be returned. Once the message has been delivered <code>null</code> will be
* returned.
* @return the message associated with this token or null if already delivered.
* @throws MqttException if there was a problem completing retrieving the message
*/
public MqttMessage getMessage() throws MqttException;
}
/*******************************************************************************
* Copyright (c) 2015 IBM Corp.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* and Eclipse Distribution License v1.0 which accompany this distribution.
*
* The Eclipse Public License is available at
* http://www.eclipse.org/legal/epl-v10.html
* and the Eclipse Distribution License is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* Contributors:
* Ian Craggs - initial API and implementation and/or initial documentation
*/
package org.eclipse.paho.client.mqttv3;
/**
* Implementers of this interface will be notified when a message arrives.
*
*/
public interface IMqttMessageListener {
/**
* This method is called when a message arrives from the server.
*
* <p>
* This method is invoked synchronously by the MQTT client. An
* acknowledgment is not sent back to the server until this
* method returns cleanly.</p>
* <p>
* If an implementation of this method throws an <code>Exception</code>, then the
* client will be shut down. When the client is next re-connected, any QoS
* 1 or 2 messages will be redelivered by the server.</p>
* <p>
* Any additional messages which arrive while an
* implementation of this method is running, will build up in memory, and
* will then back up on the network.</p>
* <p>
* If an application needs to persist data, then it
* should ensure the data is persisted prior to returning from this method, as
* after returning from this method, the message is considered to have been
* delivered, and will not be reproducible.</p>
* <p>
* It is possible to send a new message within an implementation of this callback
* (for example, a response to this message), but the implementation must not
* disconnect the client, as it will be impossible to send an acknowledgment for
* the message being processed, and a deadlock will occur.</p>
*
* @param topic name of the topic on the message was published to
* @param message the actual message.
* @throws Exception if a terminal error has occurred, and the client should be
* shut down.
*/
public void messageArrived(String topic, MqttMessage message) throws Exception;
}
/*******************************************************************************
* Copyright (c) 2009, 2014 IBM Corp.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* and Eclipse Distribution License v1.0 which accompany this distribution.
*
* The Eclipse Public License is available at
* http://www.eclipse.org/legal/epl-v10.html
* and the Eclipse Distribution License is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* Contributors:
* Dave Locke - initial API and implementation and/or initial documentation
*/
package org.eclipse.paho.client.mqttv3;
/**
* <p>
* 使应用程序在发生与客户机相关的异步事件时得到通知。
* 实现此接口的类可以在这两种类型的客户机上注册{@link IMqttClient#setCallback(MqttCallback)}
* 和 {@link IMqttAsyncClient#setCallback(MqttCallback)}
* </p>
* <p>
* Enables an application to be notified when asynchronous
* events related to the client occur.
* Classes implementing this interface
* can be registered on both types of client: {@link IMqttClient#setCallback(MqttCallback)}
* and {@link IMqttAsyncClient#setCallback(MqttCallback)}
* </p>
*/
public interface MqttCallback {
/**
* 当与服务器的连接丢失时,将调用此方法。
* @param 造成联系中断的原因。
*
* This method is called when the connection to the server is lost.
* @param cause the reason behind the loss of connection.
*/
public void connectionLost(Throwable cause);
/**
* <p>
* 当消息从服务器到达时,将调用此方法。
*
* <p>
* 此方法由MQTT客户机同步调用。在此方法干净地返回之前,不会将确认发送回服务器。</p>
* <p>
* 如果该方法的实现抛出一个<code>Exception</code>(异常),则客户机将被关闭。
* 当客户机下一次重新连接时,服务器将重新发送所有服务质量为 1或2的消息。</p>
* <p>
* 在运行此方法的实现时到达的任何附加消息都将在内存中生成,然后在网络上备份。</p>
* <p>
* 如果应用程序需要持久化数据,
* 那么它应该确保数据在从这个方法返回之前被持久化,
* 就像从这个方法返回之后,消息被认为已经被传递了,
* 并且是不可复制的。</p>
* <p>
* 可以发送一个新消息在这个回调的实现(例如,回应这个消息),
* 但不得断开客户端实现,
* 因为它不可能发送一个确认消息的处理,并会发生死锁。</p>
*
* @param topic 消息上主题的名称已发布到
* @param message 实际的消息。
* @throws Exception 如果发生终端错误,应该关闭客户机。
* </p>
*
* <p>
*
* This method is called when a message arrives from the server.
*
* <p>
* This method is invoked synchronously by the MQTT client. An
* acknowledgment is not sent back to the server until this
* method returns cleanly.</p>
* <p>
* If an implementation of this method throws an <code>Exception</code>, then the
* client will be shut down. When the client is next re-connected, any QoS
* 1 or 2 messages will be redelivered by the server.</p>
* <p>
* Any additional messages which arrive while an
* implementation of this method is running, will build up in memory, and
* will then back up on the network.</p>
* <p>
* If an application needs to persist data, then it
* should ensure the data is persisted prior to returning from this method, as
* after returning from this method, the message is considered to have been
* delivered, and will not be reproducible.</p>
* <p>
* It is possible to send a new message within an implementation of this callback
* (for example, a response to this message), but the implementation must not
* disconnect the client, as it will be impossible to send an acknowledgment for
* the message being processed, and a deadlock will occur.</p>
*
* @param topic name of the topic on the message was published to
* @param message the actual message.
* @throws Exception if a terminal error has occurred, and the client should be
* shut down.
* </p>
*/
public void messageArrived(String topic, MqttMessage message) throws Exception;
/**
* 当消息的传递已完成,且所有确认已收到时调用。
* 对于QoS 0消息,一旦消息被提交到网络进行交付,
* 就会调用它。对于QoS 1,在接收PUBACK时调用它,
* 对于QoS 2,在接收PUBCOMP时调用它。
* 令牌将与消息发布时返回的令牌相同。
*
* @param token 与消息关联的传递令牌。
*
* Called when delivery for a message has been completed, and all
* acknowledgments have been received. For QoS 0 messages it is
* called once the message has been handed to the network for
* delivery. For QoS 1 it is called when PUBACK is received and
* for QoS 2 when PUBCOMP is received. The token will be the same
* token as that returned when the message was published.
*
* @param token the delivery token associated with the message.
*/
public void deliveryComplete(IMqttDeliveryToken token);
}
/*******************************************************************************
* Copyright (c) 2009, 2014 IBM Corp.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* and Eclipse Distribution License v1.0 which accompany this distribution.
*
* The Eclipse Public License is available at
* http://www.eclipse.org/legal/epl-v10.html
* and the Eclipse Distribution License is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* Contributors:
* Dave Locke - initial API and implementation and/or initial documentation
*/
package org.eclipse.paho.client.mqttv3.internal;
import org.eclipse.paho.client.mqttv3.MqttTopic;
/**
* This interface exists to act as a common type for
* MqttClient and MqttMIDPClient so they can be passed to
* ClientComms without either client class need to know
* about the other.
* Specifically, this allows the MIDP client to work
* without the non-MIDP MqttClient/MqttConnectOptions
* classes being present.
*/
public interface DestinationProvider {
public MqttTopic getTopic(String topic);
}
此差异已折叠。
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册