mqtt初始优化

This commit is contained in:
2025-05-13 21:37:56 +08:00
parent 342284d12c
commit 9e32234ca4
36 changed files with 74 additions and 194 deletions

View File

@@ -12,8 +12,6 @@ import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.util.StringUtils;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import java.util.UUID;
@Slf4j
@@ -24,9 +22,6 @@ public class MqttConfig {
private final MqttProperties mqttProperties;
private final MqttCallbackHandler mqttCallbackHandler;
// No @Autowired here. This field will be set by the mqttClientBean() method.
private MqttClient mqttClient;
@Bean
public MqttConnectOptions mqttConnectOptions() {
MqttConnectOptions options = new MqttConnectOptions();
@@ -46,45 +41,9 @@ public class MqttConfig {
@Bean
public MqttClient mqttClientBean(MqttConnectOptions mqttConnectOptions) throws MqttException {
String clientId = mqttProperties.getClientIdPrefix() + UUID.randomUUID().toString().replace("-", "");
// Create the client instance
MqttClient client = new MqttClient(mqttProperties.getBrokerUrl(), clientId, new MemoryPersistence());
client.setCallback(mqttCallbackHandler);
mqttCallbackHandler.setMqttClient(client);
// Assign the created client to the instance field for @PostConstruct/@PreDestroy usage
this.mqttClient = client;
return client; // Return it to be managed by Spring as a bean
}
@PostConstruct
public void connect() {
try {
if (this.mqttClient != null && !this.mqttClient.isConnected()) {
log.info("Attempting to connect to MQTT broker: {} with client ID: {}", mqttProperties.getBrokerUrl(), this.mqttClient.getClientId());
// Pass the MqttConnectOptions bean directly to the connect method
this.mqttClient.connect(mqttConnectOptions());
} else if (this.mqttClient == null) {
log.error("MqttClient instance is null (was not set by mqttClientBean), cannot connect.");
}
} catch (MqttException e) {
log.error("Error connecting to MQTT broker: ", e);
}
}
@PreDestroy
public void disconnect() {
try {
if (this.mqttClient != null && this.mqttClient.isConnected()) {
log.info("Disconnecting from MQTT broker: {}", this.mqttClient.getServerURI());
this.mqttClient.disconnect();
log.info("Successfully disconnected from MQTT broker.");
}
if (this.mqttClient != null) {
// Ensure close is called even if disconnect fails or was not connected
this.mqttClient.close();
}
} catch (MqttException e) {
log.error("Error disconnecting/closing MQTT client: ", e);
}
return client;
}
}

View File

@@ -0,0 +1,73 @@
package com.yupi.project.mqtt;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.eclipse.paho.client.mqttv3.MqttClient;
import org.eclipse.paho.client.mqttv3.MqttConnectOptions;
import org.eclipse.paho.client.mqttv3.MqttException;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.context.ApplicationListener;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.stereotype.Component;
@Slf4j
@Component
@RequiredArgsConstructor
public class MqttConnectionManager implements ApplicationListener<ContextRefreshedEvent>, DisposableBean {
private final MqttClient mqttClient;
private final MqttConnectOptions mqttConnectOptions;
// private final MqttProperties mqttProperties; // Injected if needed for logging brokerUrl, or get from mqttClient.getServerURI()
@Override
public void onApplicationEvent(ContextRefreshedEvent event) {
// Ensure this logic runs only once, for the root application context
if (event.getApplicationContext().getParent() == null) {
connectToMqtt();
}
}
private void connectToMqtt() {
try {
if (mqttClient != null && !mqttClient.isConnected()) {
log.info("Attempting to connect to MQTT broker: {} with client ID: {}", mqttClient.getServerURI(), mqttClient.getClientId());
mqttClient.connect(mqttConnectOptions);
// Subscription logic is handled by MqttCallbackHandler.connectComplete
// which is triggered by the Paho client library upon successful connection.
} else if (mqttClient == null) {
log.error("MqttClient bean is null, cannot connect.");
}
} catch (MqttException e) {
log.error("Error connecting to MQTT broker: ", e);
// Consider retry logic or specific actions based on requirements
}
}
@Override
public void destroy() throws Exception {
disconnectFromMqtt();
}
private void disconnectFromMqtt() {
try {
if (mqttClient != null && mqttClient.isConnected()) {
log.info("Disconnecting from MQTT broker: {}", mqttClient.getServerURI());
mqttClient.disconnect();
log.info("Successfully disconnected from MQTT broker.");
}
} catch (MqttException e) {
log.error("Error disconnecting from MQTT broker: ", e);
} finally {
try {
if (mqttClient != null) { // No need to check isOpen(), close() handles its state.
log.info("Closing MQTT client for client ID: {}", mqttClient.getClientId());
mqttClient.close();
log.info("MQTT client closed successfully for client ID: {}", mqttClient.getClientId());
}
} catch (MqttException e) {
// Log if close() itself throws an exception, though it's less common if called after disconnect or on an unopen client.
log.error("Error closing MQTT client: ", e);
}
}
}
}

View File

@@ -1,57 +0,0 @@
{
"groups": [
{
"name": "mqtt",
"type": "com.yupi.project.config.properties.MqttProperties",
"sourceType": "com.yupi.project.config.properties.MqttProperties"
}
],
"properties": [
{
"name": "mqtt.broker-url",
"type": "java.lang.String",
"sourceType": "com.yupi.project.config.properties.MqttProperties"
},
{
"name": "mqtt.client-id-prefix",
"type": "java.lang.String",
"sourceType": "com.yupi.project.config.properties.MqttProperties"
},
{
"name": "mqtt.command-topic-base",
"type": "java.lang.String",
"sourceType": "com.yupi.project.config.properties.MqttProperties"
},
{
"name": "mqtt.connection-timeout",
"type": "java.lang.Integer",
"sourceType": "com.yupi.project.config.properties.MqttProperties"
},
{
"name": "mqtt.default-qos",
"type": "java.lang.Integer",
"sourceType": "com.yupi.project.config.properties.MqttProperties"
},
{
"name": "mqtt.keep-alive-interval",
"type": "java.lang.Integer",
"sourceType": "com.yupi.project.config.properties.MqttProperties"
},
{
"name": "mqtt.password",
"type": "java.lang.String",
"sourceType": "com.yupi.project.config.properties.MqttProperties"
},
{
"name": "mqtt.status-topic-base",
"type": "java.lang.String",
"sourceType": "com.yupi.project.config.properties.MqttProperties"
},
{
"name": "mqtt.username",
"type": "java.lang.String",
"sourceType": "com.yupi.project.config.properties.MqttProperties"
}
],
"hints": []
}

View File

@@ -1,6 +0,0 @@
spring:
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/my_db
username: root
password: 123456

View File

@@ -1,62 +0,0 @@
spring:
application:
name: mqtt-charging-system
# DataSource Config
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://yuyun-us1.stormrain.cn:3306/mqtt_power?useUnicode=true&characterEncoding=utf-8&serverTimezone=Asia/Shanghai
username: root
password: mysql_a4MQ4P
mvc:
pathmatch:
matching-strategy: ANT_PATH_MATCHER
# session 失效时间(秒)
session:
timeout: 86400
server:
port: 7529
servlet:
context-path: /api
session:
timeout: 86400 # 设置session的过期时间单位为秒这里设置为1天
mybatis-plus:
configuration:
map-underscore-to-camel-case: true
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
global-config:
db-config:
logic-delete-field: isDelete # 全局逻辑删除的实体字段名(since 3.3.0,配置后可以忽略不配置步骤2)
logic-delete-value: 1 # 逻辑已删除值(默认为 1)
logic-not-delete-value: 0 # 逻辑未删除值(默认为 0)
# Logging configuration
logging:
level:
# Set root logger level (e.g., INFO, WARN, ERROR, DEBUG)
root: INFO
# Set specific package levels
com.yupi.project: DEBUG # Example: Set your project's base package to DEBUG
org.springframework.web: INFO # Set Spring Web logging level
org.springframework.security: DEBUG # Enable Spring Security DEBUG logging
org.mybatis: INFO # Set MyBatis logging level
# ... other specific loggers
#file:
#name: logs/application.log # Log file name
#path: ./logs # Log file path
#pattern:
#console: "%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n"
#file: "%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n"
# ===================================================================
# MQTT Configurations
# ===================================================================
mqtt:
broker-url: tcp://broker.emqx.io:1883
username: # Public broker, no credentials specified for connection
password: # Public broker, no credentials specified for connection
client-id-prefix: backend-yupi-mqtt-power- # Unique client ID prefix for our project
default-qos: 1 # Default Quality of Service (0, 1, 2)
connection-timeout: 30 # Connection timeout in seconds
keep-alive-interval: 60 # Keep alive interval in seconds
command-topic-base: yupi_mqtt_power_project/robot/command # Prefixed base topic for sending commands
status-topic-base: yupi_mqtt_power_project/robot/status # Prefixed base topic for receiving status

View File

@@ -1 +0,0 @@
我的项目 by 程序员鱼皮 https://github.com/liyupi

View File

@@ -1,26 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.yupi.project.mapper.UserMapper">
<resultMap id="BaseResultMap" type="com.yupi.project.model.entity.User">
<id property="id" column="id" jdbcType="BIGINT"/>
<result property="userName" column="userName" jdbcType="VARCHAR"/>
<result property="userAccount" column="userAccount" jdbcType="VARCHAR"/>
<result property="userAvatar" column="userAvatar" jdbcType="VARCHAR"/>
<result property="gender" column="gender" jdbcType="TINYINT"/>
<result property="userRole" column="userRole" jdbcType="VARCHAR"/>
<result property="userPassword" column="userPassword" jdbcType="VARCHAR"/>
<result property="createTime" column="createTime" jdbcType="TIMESTAMP"/>
<result property="updateTime" column="updateTime" jdbcType="TIMESTAMP"/>
<result property="isDelete" column="isDelete" jdbcType="TINYINT"/>
</resultMap>
<sql id="Base_Column_List">
id,userName,userAccount,
userAvatar,gender,userRole,
userPassword,createTime,updateTime,
isDelete
</sql>
</mapper>