mirror of
				https://github.com/YunaiV/ruoyi-vue-pro.git
				synced 2025-10-31 18:49:06 +08:00 
			
		
		
		
	feat: 【IoT 物联网】新增简单类型处理器配置和处理器,优化 JSON 解析问题
This commit is contained in:
		| @ -0,0 +1,33 @@ | |||||||
|  | package cn.iocoder.yudao.module.iot.framework.mybatis.config; | ||||||
|  |  | ||||||
|  | import cn.iocoder.yudao.module.iot.framework.mybatis.handler.SimpleObjectTypeHandler; | ||||||
|  | import jakarta.annotation.PostConstruct; | ||||||
|  | import jakarta.annotation.Resource; | ||||||
|  | import lombok.extern.slf4j.Slf4j; | ||||||
|  | import org.apache.ibatis.session.SqlSessionFactory; | ||||||
|  | import org.apache.ibatis.type.TypeHandlerRegistry; | ||||||
|  | import org.springframework.context.annotation.Configuration; | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * 简单类型处理器配置 | ||||||
|  |  * 注册自定义的类型处理器,避免 JSON 解析错误 | ||||||
|  |  * | ||||||
|  |  * @author 芋道源码 | ||||||
|  |  */ | ||||||
|  | @Slf4j | ||||||
|  | @Configuration | ||||||
|  | public class SimpleTypeHandlerConfig { | ||||||
|  |  | ||||||
|  |     @Resource | ||||||
|  |     private SqlSessionFactory sqlSessionFactory; | ||||||
|  |  | ||||||
|  |     @PostConstruct | ||||||
|  |     public void registerTypeHandlers() { | ||||||
|  |         TypeHandlerRegistry registry = sqlSessionFactory.getConfiguration().getTypeHandlerRegistry(); | ||||||
|  |  | ||||||
|  |         // 注册简单的 Object 类型处理器,避免 JSON 解析问题 | ||||||
|  |         registry.register(java.lang.Object.class, new SimpleObjectTypeHandler()); | ||||||
|  |  | ||||||
|  |         log.info("简单类型处理器注册完成,避免 JSON 解析错误"); | ||||||
|  |     } | ||||||
|  | } | ||||||
| @ -0,0 +1,39 @@ | |||||||
|  | package cn.iocoder.yudao.module.iot.framework.mybatis.handler; | ||||||
|  |  | ||||||
|  | import org.apache.ibatis.type.BaseTypeHandler; | ||||||
|  | import org.apache.ibatis.type.JdbcType; | ||||||
|  |  | ||||||
|  | import java.sql.CallableStatement; | ||||||
|  | import java.sql.PreparedStatement; | ||||||
|  | import java.sql.ResultSet; | ||||||
|  | import java.sql.SQLException; | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * 简单的 Object 类型处理器 | ||||||
|  |  * 直接返回字符串,避免 JSON 解析问题 | ||||||
|  |  * | ||||||
|  |  * @author 芋道源码 | ||||||
|  |  */ | ||||||
|  | public class SimpleObjectTypeHandler extends BaseTypeHandler<Object> { | ||||||
|  |  | ||||||
|  |     @Override | ||||||
|  |     public void setNonNullParameter(PreparedStatement ps, int i, Object parameter, JdbcType jdbcType) | ||||||
|  |             throws SQLException { | ||||||
|  |         ps.setString(i, parameter.toString()); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     @Override | ||||||
|  |     public Object getNullableResult(ResultSet rs, String columnName) throws SQLException { | ||||||
|  |         return rs.getString(columnName); // 直接返回字符串 | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     @Override | ||||||
|  |     public Object getNullableResult(ResultSet rs, int columnIndex) throws SQLException { | ||||||
|  |         return rs.getString(columnIndex); // 直接返回字符串 | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     @Override | ||||||
|  |     public Object getNullableResult(CallableStatement cs, int columnIndex) throws SQLException { | ||||||
|  |         return cs.getString(columnIndex); // 直接返回字符串 | ||||||
|  |     } | ||||||
|  | } | ||||||
| @ -66,8 +66,15 @@ | |||||||
|         DESCRIBE product_property_${productId} |         DESCRIBE product_property_${productId} | ||||||
|     </select> |     </select> | ||||||
|  |  | ||||||
|  |     <resultMap id="IotDevicePropertyRespVOMap" | ||||||
|  |                type="cn.iocoder.yudao.module.iot.controller.admin.device.vo.property.IotDevicePropertyRespVO"> | ||||||
|  |         <result property="value" column="value" | ||||||
|  |                 typeHandler="cn.iocoder.yudao.module.iot.framework.mybatis.handler.SimpleObjectTypeHandler"/> | ||||||
|  |         <result property="updateTime" column="update_time" javaType="java.lang.Long"/> | ||||||
|  |     </resultMap> | ||||||
|  |  | ||||||
|     <select id="selectListByHistory" |     <select id="selectListByHistory" | ||||||
|             resultType="cn.iocoder.yudao.module.iot.controller.admin.device.vo.property.IotDevicePropertyRespVO"> |             resultMap="IotDevicePropertyRespVOMap"> | ||||||
|         SELECT ${@cn.hutool.core.util.StrUtil@toUnderlineCase(reqVO.identifier)} AS `value`, ts AS update_time |         SELECT ${@cn.hutool.core.util.StrUtil@toUnderlineCase(reqVO.identifier)} AS `value`, ts AS update_time | ||||||
|         FROM device_property_${reqVO.deviceId} |         FROM device_property_${reqVO.deviceId} | ||||||
|         WHERE ${@cn.hutool.core.util.StrUtil@toUnderlineCase(reqVO.identifier)} IS NOT NULL |         WHERE ${@cn.hutool.core.util.StrUtil@toUnderlineCase(reqVO.identifier)} IS NOT NULL | ||||||
|  | |||||||
| @ -68,7 +68,13 @@ public class IotMqttUpstreamHandler { | |||||||
|  |  | ||||||
|         log.info("[handle][设备认证成功,建立连接,客户端 ID: {},用户名: {}]", clientId, username); |         log.info("[handle][设备认证成功,建立连接,客户端 ID: {},用户名: {}]", clientId, username); | ||||||
|  |  | ||||||
|         // 2. 设置异常和关闭处理器 |         // 2. 设置心跳处理器(监听客户端的 PINGREQ 消息) | ||||||
|  |         endpoint.pingHandler(v -> { | ||||||
|  |             log.debug("[handle][收到客户端心跳,客户端 ID: {}]", clientId); | ||||||
|  |             // Vert.x 会自动发送 PINGRESP 响应,无需手动处理 | ||||||
|  |         }); | ||||||
|  |  | ||||||
|  |         // 3. 设置异常和关闭处理器 | ||||||
|         endpoint.exceptionHandler(ex -> { |         endpoint.exceptionHandler(ex -> { | ||||||
|             log.warn("[handle][连接异常,客户端 ID: {},地址: {}]", clientId, connectionManager.getEndpointAddress(endpoint)); |             log.warn("[handle][连接异常,客户端 ID: {},地址: {}]", clientId, connectionManager.getEndpointAddress(endpoint)); | ||||||
|             cleanupConnection(endpoint); |             cleanupConnection(endpoint); | ||||||
| @ -77,7 +83,7 @@ public class IotMqttUpstreamHandler { | |||||||
|             cleanupConnection(endpoint); |             cleanupConnection(endpoint); | ||||||
|         }); |         }); | ||||||
|  |  | ||||||
|         // 3. 设置消息处理器 |         // 4. 设置消息处理器 | ||||||
|         endpoint.publishHandler(message -> { |         endpoint.publishHandler(message -> { | ||||||
|             try { |             try { | ||||||
|                 processMessage(clientId, message.topicName(), message.payload().getBytes()); |                 processMessage(clientId, message.topicName(), message.payload().getBytes()); | ||||||
| @ -100,7 +106,7 @@ public class IotMqttUpstreamHandler { | |||||||
|             } |             } | ||||||
|         }); |         }); | ||||||
|  |  | ||||||
|         // 4. 设置订阅处理器 |         // 5. 设置订阅处理器 | ||||||
|         endpoint.subscribeHandler(subscribe -> { |         endpoint.subscribeHandler(subscribe -> { | ||||||
|             // 提取主题名称列表用于日志显示 |             // 提取主题名称列表用于日志显示 | ||||||
|             List<String> topicNames = subscribe.topicSubscriptions().stream() |             List<String> topicNames = subscribe.topicSubscriptions().stream() | ||||||
| @ -115,22 +121,22 @@ public class IotMqttUpstreamHandler { | |||||||
|             endpoint.subscribeAcknowledge(subscribe.messageId(), grantedQoSLevels); |             endpoint.subscribeAcknowledge(subscribe.messageId(), grantedQoSLevels); | ||||||
|         }); |         }); | ||||||
|  |  | ||||||
|         // 5. 设置取消订阅处理器 |         // 6. 设置取消订阅处理器 | ||||||
|         endpoint.unsubscribeHandler(unsubscribe -> { |         endpoint.unsubscribeHandler(unsubscribe -> { | ||||||
|             log.debug("[handle][设备取消订阅,客户端 ID: {},主题: {}]", clientId, unsubscribe.topics()); |             log.debug("[handle][设备取消订阅,客户端 ID: {},主题: {}]", clientId, unsubscribe.topics()); | ||||||
|             endpoint.unsubscribeAcknowledge(unsubscribe.messageId()); |             endpoint.unsubscribeAcknowledge(unsubscribe.messageId()); | ||||||
|         }); |         }); | ||||||
|  |  | ||||||
|         // 6. 设置 QoS 2消息的 PUBREL 处理器 |         // 7. 设置 QoS 2消息的 PUBREL 处理器 | ||||||
|         endpoint.publishReleaseHandler(endpoint::publishComplete); |         endpoint.publishReleaseHandler(endpoint::publishComplete); | ||||||
|  |  | ||||||
|         // 7. 设置断开连接处理器 |         // 8. 设置断开连接处理器 | ||||||
|         endpoint.disconnectHandler(v -> { |         endpoint.disconnectHandler(v -> { | ||||||
|             log.debug("[handle][设备断开连接,客户端 ID: {}]", clientId); |             log.debug("[handle][设备断开连接,客户端 ID: {}]", clientId); | ||||||
|             cleanupConnection(endpoint); |             cleanupConnection(endpoint); | ||||||
|         }); |         }); | ||||||
|  |  | ||||||
|         // 8. 接受连接 |         // 9. 接受连接 | ||||||
|         endpoint.accept(false); |         endpoint.accept(false); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  | |||||||
| @ -103,7 +103,6 @@ yudao: | |||||||
|           port: 1883 |           port: 1883 | ||||||
|           max-message-size: 8192 |           max-message-size: 8192 | ||||||
|           connect-timeout-seconds: 60 |           connect-timeout-seconds: 60 | ||||||
|           keep-alive-timeout-seconds: 300 |  | ||||||
|           ssl-enabled: false |           ssl-enabled: false | ||||||
|  |  | ||||||
| --- #################### 日志相关配置 #################### | --- #################### 日志相关配置 #################### | ||||||
|  | |||||||
		Reference in New Issue
	
	Block a user
	 haohao
					haohao