【功能完善】IoT: 集成 Vert.x 支持,重构 HTTP 插件为 Vert.x 插件

This commit is contained in:
安浩浩 2025-01-07 23:13:57 +08:00
parent cde6ebf921
commit 77b89aad77
12 changed files with 355 additions and 288 deletions

View File

@ -67,6 +67,7 @@
<bizlog-sdk.version>3.0.6</bizlog-sdk.version> <bizlog-sdk.version>3.0.6</bizlog-sdk.version>
<mqtt.version>1.2.5</mqtt.version> <mqtt.version>1.2.5</mqtt.version>
<pf4j-spring.version>0.9.0</pf4j-spring.version> <pf4j-spring.version>0.9.0</pf4j-spring.version>
<vertx.version>4.4.0</vertx.version>
<!-- 三方云服务相关 --> <!-- 三方云服务相关 -->
<okio.version>3.5.0</okio.version> <okio.version>3.5.0</okio.version>
<okhttp3.version>4.11.0</okhttp3.version> <okhttp3.version>4.11.0</okhttp3.version>
@ -613,6 +614,19 @@
<version>${pf4j-spring.version}</version> <version>${pf4j-spring.version}</version>
</dependency> </dependency>
<!-- Vert.x 核心依赖 -->
<dependency>
<groupId>io.vertx</groupId>
<artifactId>vertx-core</artifactId>
<version>${vertx.version}</version>
</dependency>
<!-- Vert.x Web 模块 -->
<dependency>
<groupId>io.vertx</groupId>
<artifactId>vertx-web</artifactId>
<version>${vertx.version}</version>
</dependency>
</dependencies> </dependencies>
</dependencyManagement> </dependencyManagement>

View File

@ -64,6 +64,16 @@
<artifactId>yudao-spring-boot-starter-excel</artifactId> <artifactId>yudao-spring-boot-starter-excel</artifactId>
</dependency> </dependency>
<!-- Vert.x 核心依赖 -->
<dependency>
<groupId>io.vertx</groupId>
<artifactId>vertx-core</artifactId>
</dependency>
<!-- Vert.x Web 模块 -->
<dependency>
<groupId>io.vertx</groupId>
<artifactId>vertx-web</artifactId>
</dependency>
<!-- MQTT --> <!-- MQTT -->
<dependency> <dependency>
<groupId>org.eclipse.paho</groupId> <groupId>org.eclipse.paho</groupId>

View File

@ -196,10 +196,8 @@ public class PluginInstanceServiceImpl implements PluginInstanceService {
.collect(Collectors.toMap(PluginInfoDO::getPluginKey, Function.identity())); .collect(Collectors.toMap(PluginInfoDO::getPluginKey, Function.identity()));
// 3. 获取本机 IP MAC 地址 // 3. 获取本机 IP MAC 地址
LinkedHashSet<InetAddress> localAddressList = NetUtil.localAddressList(t -> t instanceof Inet4Address); String ip = NetUtil.getLocalhostStr();
LinkedHashSet<String> ipList = NetUtil.toIpList(localAddressList); String mac = NetUtil.getLocalMacAddress();
String ip = ipList.stream().findFirst().orElse("127.0.0.1");
String mac = NetUtil.getMacAddress(localAddressList.stream().findFirst().orElse(null));
String mainId = MAIN_ID + "-" + mac; String mainId = MAIN_ID + "-" + mac;
// 4. 遍历插件列表并保存为插件实例 // 4. 遍历插件列表并保存为插件实例

View File

@ -0,0 +1,81 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<parent>
<artifactId>yudao-module-iot-plugin</artifactId>
<groupId>cn.iocoder.boot</groupId>
<version>2.2.0-snapshot</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>yudao-module-iot-http-plugin</artifactId>
<name>${project.artifactId}</name>
<version>2.2.0-snapshot</version>
<description>物联网 插件模块 - http 插件</description>
<build>
<plugins>
<plugin>
<artifactId>maven-jar-plugin</artifactId>
<version>2.4</version>
<configuration>
<archive>
<manifestEntries>
<Plugin-Id>${plugin.id}</Plugin-Id>
<Plugin-Class>${plugin.class}</Plugin-Class>
<Plugin-Version>${plugin.version}</Plugin-Version>
<Plugin-Provider>${plugin.provider}</Plugin-Provider>
<Plugin-Description>${plugin.description}</Plugin-Description>
<Plugin-Dependencies>${plugin.dependencies}</Plugin-Dependencies>
</manifestEntries>
</archive>
</configuration>
</plugin>
<plugin>
<artifactId>maven-deploy-plugin</artifactId>
<configuration>
<skip>true</skip>
</configuration>
</plugin>
<plugin>
<artifactId>maven-shade-plugin</artifactId>
<version>3.4.1</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<shadedArtifactAttached>true</shadedArtifactAttached>
<shadedClassifierName>shaded</shadedClassifierName>
<transformers>
<transformer>
<mainClass>cn.iocoder.yudao.module.iot.HttpPluginSpringbootApplication</mainClass>
</transformer>
</transformers>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>org.pf4j</groupId>
<artifactId>pf4j-spring</artifactId>
<version>0.9.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.34</version>
<scope>provided</scope>
</dependency>
</dependencies>
<properties>
<plugin.class>cn.iocoder.yudao.module.iot.plugin.HttpVertxPlugin</plugin.class>
<plugin.version>0.0.1</plugin.version>
<plugin.id>http-plugin</plugin.id>
<plugin.description>http-plugin-0.0.1</plugin.description>
<plugin.provider>ahh</plugin.provider>
</properties>
</project>

View File

@ -1,5 +1,5 @@
plugin.id=http-plugin plugin.id=http-plugin
plugin.class=cn.iocoder.yudao.module.iot.plugin.HttpPlugin plugin.class=cn.iocoder.yudao.module.iot.plugin.HttpVertxPlugin
plugin.version=0.0.1 plugin.version=0.0.1
plugin.provider=ahh plugin.provider=ahh
plugin.dependencies= plugin.dependencies=

View File

@ -21,7 +21,7 @@
<properties> <properties>
<!-- 插件相关 --> <!-- 插件相关 -->
<plugin.id>http-plugin</plugin.id> <plugin.id>http-plugin</plugin.id>
<plugin.class>cn.iocoder.yudao.module.iot.plugin.HttpPlugin</plugin.class> <plugin.class>cn.iocoder.yudao.module.iot.plugin.HttpVertxPlugin</plugin.class>
<plugin.version>0.0.1</plugin.version> <plugin.version>0.0.1</plugin.version>
<plugin.provider>ahh</plugin.provider> <plugin.provider>ahh</plugin.provider>
<plugin.description>http-plugin-0.0.1</plugin.description> <plugin.description>http-plugin-0.0.1</plugin.description>
@ -30,27 +30,6 @@
<build> <build>
<plugins> <plugins>
<!-- DOESN'T WORK WITH MAVEN 3 (I defined the plugin metadata in properties section)
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>properties-maven-plugin</artifactId>
<version>1.0-alpha-2</version>
<executions>
<execution>
<phase>initialize</phase>
<goals>
<goal>read-project-properties</goal>
</goals>
<configuration>
<files>
<file>plugin.properties</file>
</files>
</configuration>
</execution>
</executions>
</plugin>
-->
<plugin> <plugin>
<groupId>org.apache.maven.plugins</groupId> <groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-antrun-plugin</artifactId> <artifactId>maven-antrun-plugin</artifactId>
@ -118,6 +97,29 @@
<skip>true</skip> <skip>true</skip>
</configuration> </configuration>
</plugin> </plugin>
<!-- <plugin>-->
<!-- <groupId>org.apache.maven.plugins</groupId>-->
<!-- <artifactId>maven-shade-plugin</artifactId>-->
<!-- <version>3.4.1</version>-->
<!-- <executions>-->
<!-- <execution>-->
<!-- <phase>package</phase>-->
<!-- <goals>-->
<!-- <goal>shade</goal>-->
<!-- </goals>-->
<!-- <configuration>-->
<!-- <shadedArtifactAttached>true</shadedArtifactAttached>-->
<!-- <shadedClassifierName>shaded</shadedClassifierName>-->
<!-- <transformers>-->
<!-- <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">-->
<!-- <mainClass>cn.iocoder.yudao.module.iot.HttpPluginSpringbootApplication</mainClass>-->
<!-- </transformer>-->
<!-- </transformers>-->
<!-- </configuration>-->
<!-- </execution>-->
<!-- </executions>-->
<!-- </plugin>-->
</plugins> </plugins>
</build> </build>
@ -145,10 +147,15 @@
<version>${lombok.version}</version> <version>${lombok.version}</version>
<scope>provided</scope> <scope>provided</scope>
</dependency> </dependency>
<!-- Vert.x 核心依赖 -->
<dependency> <dependency>
<groupId>io.netty</groupId> <groupId>io.vertx</groupId>
<artifactId>netty-all</artifactId> <artifactId>vertx-core</artifactId>
<version>4.1.63.Final</version> <!-- 版本可根据需要调整 --> </dependency>
<!-- Vert.x Web 模块 -->
<dependency>
<groupId>io.vertx</groupId>
<artifactId>vertx-web</artifactId>
</dependency> </dependency>
<!-- MQTT --> <!-- MQTT -->
<dependency> <dependency>

View File

@ -1,153 +0,0 @@
package cn.iocoder.yudao.module.iot.plugin;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import cn.iocoder.yudao.module.iot.api.device.DeviceDataApi;
import cn.iocoder.yudao.module.iot.api.device.dto.DeviceDataCreateReqDTO;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelFutureListener;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.handler.codec.http.*;
import io.netty.util.CharsetUtil;
/**
* 基于 Netty HTTP 处理器用于接收设备上报的数据并调用主程序的 DeviceDataApi 接口进行处理
* <p>
* 1. 请求格式JSON 格式地址为 POST /sys/{productKey}/{deviceName}/thing/event/property/post
* 2. 返回结果JSON 格式包含统一的 codedataidmessagemethodversion 字段
*/
public class HttpHandler extends SimpleChannelInboundHandler<FullHttpRequest> {
private final DeviceDataApi deviceDataApi;
public HttpHandler(DeviceDataApi deviceDataApi) {
this.deviceDataApi = deviceDataApi;
}
@Override
protected void channelRead0(ChannelHandlerContext ctx, FullHttpRequest request) {
// 期望的路径格式: /sys/{productKey}/{deviceName}/thing/event/property/post
// 使用 "/" 拆分路径
String uri = request.uri();
String[] parts = uri.split("/");
/*
拆分结果示例:
parts[0] = ""
parts[1] = "sys"
parts[2] = productKey
parts[3] = deviceName
parts[4] = "thing"
parts[5] = "event"
parts[6] = "property"
parts[7] = "post"
*/
boolean isCorrectPath = parts.length == 8
&& "sys".equals(parts[1])
&& "thing".equals(parts[4])
&& "event".equals(parts[5])
&& "property".equals(parts[6])
&& "post".equals(parts[7]);
if (!isCorrectPath) {
writeResponse(ctx, HttpResponseStatus.NOT_FOUND, "Not Found");
return;
}
String productKey = parts[2];
String deviceName = parts[3];
// 从请求中获取原始数据尝试解析请求数据为 JSON 对象
String requestBody = request.content().toString(CharsetUtil.UTF_8);
JSONObject jsonData;
try {
jsonData = JSONUtil.parseObj(requestBody);
} catch (Exception e) {
JSONObject res = createResponseJson(
400,
new JSONObject(),
null,
"请求数据不是合法的 JSON 格式: " + e.getMessage(),
"thing.event.property.post",
"1.0"
);
writeResponse(ctx, HttpResponseStatus.BAD_REQUEST, res.toString());
return;
}
String id = jsonData.getStr("id", null);
try {
// 调用主程序的接口保存数据
DeviceDataCreateReqDTO createDTO = DeviceDataCreateReqDTO.builder()
.productKey(productKey)
.deviceName(deviceName)
.message(jsonData.toString())
.build();
deviceDataApi.saveDeviceData(createDTO);
// 构造成功响应内容
JSONObject successRes = createResponseJson(
200,
new JSONObject(),
id,
"success",
"thing.event.property.post",
"1.0"
);
writeResponse(ctx, HttpResponseStatus.OK, successRes.toString());
} catch (Exception e) {
JSONObject errorRes = createResponseJson(
500,
new JSONObject(),
id,
"The format of result is error!",
"thing.event.property.post",
"1.0"
);
writeResponse(ctx, HttpResponseStatus.INTERNAL_SERVER_ERROR, errorRes.toString());
}
}
/**
* 创建标准化的响应 JSON 对象
*
* @param code 响应状态码业务层面的
* @param data 返回的数据对象JSON
* @param id 请求的 id可选
* @param message 返回的提示信息
* @param method 返回的 method 标识
* @param version 返回的版本号
* @return 构造好的 JSON 对象
*/
private JSONObject createResponseJson(int code, JSONObject data, String id, String message, String method, String version) {
JSONObject res = new JSONObject();
res.set("code", code);
res.set("data", data != null ? data : new JSONObject());
res.set("id", id);
res.set("message", message);
res.set("method", method);
res.set("version", version);
return res;
}
/**
* 向客户端返回 HTTP 响应的辅助方法
*
* @param ctx 通道上下文
* @param status HTTP 响应状态码网络层面的
* @param content 响应内容JSON 字符串或其他文本
*/
private void writeResponse(ChannelHandlerContext ctx, HttpResponseStatus status, String content) {
// 设置响应头为 JSON 类型和正确的编码
FullHttpResponse response = new DefaultFullHttpResponse(
HttpVersion.HTTP_1_1,
status,
Unpooled.copiedBuffer(content, CharsetUtil.UTF_8)
);
response.headers().set(HttpHeaderNames.CONTENT_TYPE, "application/json; charset=UTF-8");
response.headers().set(HttpHeaderNames.CONTENT_LENGTH, response.content().readableBytes());
// 发送响应并在发送完成后关闭连接
ctx.writeAndFlush(response).addListener(ChannelFutureListener.CLOSE);
}
}

View File

@ -1,94 +0,0 @@
package cn.iocoder.yudao.module.iot.plugin;
import cn.iocoder.yudao.module.iot.api.device.DeviceDataApi;
import cn.iocoder.yudao.module.iot.api.ServiceRegistry;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.codec.http.*;
import lombok.extern.slf4j.Slf4j;
import org.pf4j.PluginWrapper;
import org.pf4j.Plugin;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
@Slf4j
public class HttpPlugin extends Plugin {
private static final int PORT = 8092;
private ExecutorService executorService;
private DeviceDataApi deviceDataApi;
public HttpPlugin(PluginWrapper wrapper) {
super(wrapper);
// 初始化线程池
this.executorService = Executors.newSingleThreadExecutor();
}
@Override
public void start() {
log.info("HttpPlugin.start()");
// 重新初始化线程池确保它是活跃的
if (executorService.isShutdown() || executorService.isTerminated()) {
executorService = Executors.newSingleThreadExecutor();
}
// ServiceRegistry 中获取主程序暴露的 DeviceDataApi 接口实例
deviceDataApi = ServiceRegistry.getService(DeviceDataApi.class);
if (deviceDataApi == null) {
log.error("未能从 ServiceRegistry 获取 DeviceDataApi 实例,请确保主程序已正确注册!");
return;
}
// 异步启动 Netty 服务器
executorService.submit(this::startHttpServer);
}
@Override
public void stop() {
log.info("HttpPlugin.stop()");
// 停止线程池
executorService.shutdownNow();
}
/**
* 启动 HTTP 服务
*/
private void startHttpServer() {
EventLoopGroup bossGroup = new NioEventLoopGroup(1);
EventLoopGroup workerGroup = new NioEventLoopGroup();
try {
ServerBootstrap bootstrap = new ServerBootstrap();
bootstrap.group(bossGroup, workerGroup)
.channel(NioServerSocketChannel.class)
.childHandler(new ChannelInitializer<>() {
@Override
protected void initChannel(Channel channel) {
channel.pipeline().addLast(new HttpServerCodec());
channel.pipeline().addLast(new HttpObjectAggregator(65536));
// 将从 ServiceRegistry 获取的 deviceDataApi 传入处理器
channel.pipeline().addLast(new HttpHandler(deviceDataApi));
}
});
// 绑定端口并启动服务器
ChannelFuture future = bootstrap.bind(PORT).sync();
log.info("HTTP 服务器启动成功,端口为: {}", PORT);
future.channel().closeFuture().sync();
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
log.warn("HTTP 服务启动被中断", e);
} finally {
bossGroup.shutdownGracefully();
workerGroup.shutdownGracefully();
}
}
}

View File

@ -0,0 +1,105 @@
package cn.iocoder.yudao.module.iot.plugin;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import cn.iocoder.yudao.module.iot.api.device.DeviceDataApi;
import cn.iocoder.yudao.module.iot.api.device.dto.DeviceDataCreateReqDTO;
import io.vertx.core.Handler;
import io.vertx.ext.web.RequestBody;
import io.vertx.ext.web.RoutingContext;
import lombok.extern.slf4j.Slf4j;
@Slf4j
public class HttpVertxHandler implements Handler<RoutingContext> {
private final DeviceDataApi deviceDataApi;
public HttpVertxHandler(DeviceDataApi deviceDataApi) {
this.deviceDataApi = deviceDataApi;
}
@Override
public void handle(RoutingContext ctx) {
String productKey = ctx.pathParam("productKey");
String deviceName = ctx.pathParam("deviceName");
RequestBody requestBody = ctx.body();
JSONObject jsonData;
try {
jsonData = JSONUtil.parseObj(requestBody.asJsonObject());
} catch (Exception e) {
JSONObject res = createResponseJson(
400,
new JSONObject(),
null,
"请求数据不是合法的 JSON 格式: " + e.getMessage(),
"thing.event.property.post",
"1.0");
ctx.response()
.setStatusCode(400)
.putHeader("Content-Type", "application/json; charset=UTF-8")
.end(res.toString());
return;
}
String id = jsonData.getStr("id", null);
try {
// 调用主程序的接口保存数据
DeviceDataCreateReqDTO createDTO = DeviceDataCreateReqDTO.builder()
.productKey(productKey)
.deviceName(deviceName)
.message(jsonData.toString())
.build();
deviceDataApi.saveDeviceData(createDTO);
// 构造成功响应内容
JSONObject successRes = createResponseJson(
200,
new JSONObject(),
id,
"success",
"thing.event.property.post",
"1.0");
ctx.response()
.setStatusCode(200)
.putHeader("Content-Type", "application/json; charset=UTF-8")
.end(successRes.toString());
} catch (Exception e) {
JSONObject errorRes = createResponseJson(
500,
new JSONObject(),
id,
"The format of result is error!",
"thing.event.property.post",
"1.0");
ctx.response()
.setStatusCode(500)
.putHeader("Content-Type", "application/json; charset=UTF-8")
.end(errorRes.toString());
}
}
/**
* 创建标准化的响应 JSON 对象
*
* @param code 响应状态码业务层面的
* @param data 返回的数据对象JSON
* @param id 请求的 id可选
* @param message 返回的提示信息
* @param method 返回的 method 标识
* @param version 返回的版本号
* @return 构造好的 JSON 对象
*/
private JSONObject createResponseJson(int code, JSONObject data, String id, String message, String method,
String version) {
JSONObject res = new JSONObject();
res.set("code", code);
res.set("data", data != null ? data : new JSONObject());
res.set("id", id);
res.set("message", message);
res.set("method", method);
res.set("version", version);
return res;
}
}

View File

@ -0,0 +1,70 @@
package cn.iocoder.yudao.module.iot.plugin;
import cn.iocoder.yudao.module.iot.api.ServiceRegistry;
import cn.iocoder.yudao.module.iot.api.device.DeviceDataApi;
import io.vertx.core.Vertx;
import io.vertx.ext.web.Router;
import io.vertx.ext.web.handler.BodyHandler;
import org.pf4j.Plugin;
import org.pf4j.PluginWrapper;
import lombok.extern.slf4j.Slf4j;
@Slf4j
public class HttpVertxPlugin extends Plugin {
private static final int PORT = 8092;
private Vertx vertx;
private DeviceDataApi deviceDataApi;
public HttpVertxPlugin(PluginWrapper wrapper) {
super(wrapper);
}
@Override
public void start() {
log.info("HttpVertxPlugin.start()");
// 获取 DeviceDataApi 实例
deviceDataApi = ServiceRegistry.getService(DeviceDataApi.class);
if (deviceDataApi == null) {
log.error("未能从 ServiceRegistry 获取 DeviceDataApi 实例,请确保主程序已正确注册!");
return;
}
// 初始化 Vert.x
vertx = Vertx.vertx();
Router router = Router.router(vertx);
// 处理 Body
router.route().handler(BodyHandler.create());
// 设置路由
router.post("/sys/:productKey/:deviceName/thing/event/property/post")
.handler(new HttpVertxHandler(deviceDataApi));
// 启动 HTTP 服务器
vertx.createHttpServer()
.requestHandler(router)
.listen(PORT, http -> {
if (http.succeeded()) {
log.info("HTTP 服务器启动成功,端口为: {}", PORT);
} else {
log.error("HTTP 服务器启动失败", http.cause());
}
});
}
@Override
public void stop() {
log.info("HttpVertxPlugin.stop()");
if (vertx != null) {
vertx.close(ar -> {
if (ar.succeeded()) {
log.info("Vert.x 关闭成功");
} else {
log.error("Vert.x 关闭失败", ar.cause());
}
});
}
}
}

View File

@ -212,4 +212,9 @@ iot:
# 保持连接 # 保持连接
keepalive: 60 keepalive: 60
# 清除会话(设置为false,断开连接,重连后使用原来的会话 保留订阅的主题,能接收离线期间的消息) # 清除会话(设置为false,断开连接,重连后使用原来的会话 保留订阅的主题,能接收离线期间的消息)
clearSession: true clearSession: true
# 插件配置
pf4j:
pluginsDir: ${user.home}/plugins # 插件目录

View File

@ -45,7 +45,7 @@ spring:
primary: master primary: master
datasource: datasource:
master: master:
url: jdbc:mysql://127.0.0.1:3307/ruoyi-vue-pro?useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true&nullCatalogMeansCurrent=true # MySQL Connector/J 8.X 连接的示例 url: jdbc:mysql://chaojiniu.top:23306/ruoyi-vue-pro?useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true&nullCatalogMeansCurrent=true # MySQL Connector/J 8.X 连接的示例
# url: jdbc:mysql://127.0.0.1:3306/ruoyi-vue-pro?useSSL=true&allowPublicKeyRetrieval=true&useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai # MySQL Connector/J 5.X 连接的示例 # url: jdbc:mysql://127.0.0.1:3306/ruoyi-vue-pro?useSSL=true&allowPublicKeyRetrieval=true&useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai # MySQL Connector/J 5.X 连接的示例
# url: jdbc:postgresql://127.0.0.1:5432/ruoyi-vue-pro # PostgreSQL 连接的示例 # url: jdbc:postgresql://127.0.0.1:5432/ruoyi-vue-pro # PostgreSQL 连接的示例
# url: jdbc:oracle:thin:@127.0.0.1:1521:xe # Oracle 连接的示例 # url: jdbc:oracle:thin:@127.0.0.1:1521:xe # Oracle 连接的示例
@ -53,8 +53,8 @@ spring:
# url: jdbc:dm://127.0.0.1:5236?schema=RUOYI_VUE_PRO # DM 连接的示例 # url: jdbc:dm://127.0.0.1:5236?schema=RUOYI_VUE_PRO # DM 连接的示例
# url: jdbc:kingbase8://127.0.0.1:54321/test # 人大金仓 KingbaseES 连接的示例 # url: jdbc:kingbase8://127.0.0.1:54321/test # 人大金仓 KingbaseES 连接的示例
# url: jdbc:postgresql://127.0.0.1:5432/postgres # OpenGauss 连接的示例 # url: jdbc:postgresql://127.0.0.1:5432/postgres # OpenGauss 连接的示例
username: root username: ruoyi-vue-pro
password: ahh@123456 password: ruoyi-@h2ju02hebp
# username: sa # SQL Server 连接的示例 # username: sa # SQL Server 连接的示例
# password: Yudao@2024 # SQL Server 连接的示例 # password: Yudao@2024 # SQL Server 连接的示例
# username: SYSDBA # DM 连接的示例 # username: SYSDBA # DM 连接的示例
@ -63,17 +63,25 @@ spring:
# password: Yudao@2024 # OpenGauss 连接的示例 # password: Yudao@2024 # OpenGauss 连接的示例
slave: # 模拟从库,可根据自己需要修改 slave: # 模拟从库,可根据自己需要修改
lazy: true # 开启懒加载,保证启动速度 lazy: true # 开启懒加载,保证启动速度
url: jdbc:mysql://127.0.0.1:3307/ruoyi-vue-pro?useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true&nullCatalogMeansCurrent=true url: jdbc:mysql://chaojiniu.top:23306/ruoyi-vue-pro?useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true&nullCatalogMeansCurrent=true
username: ruoyi-vue-pro
password: ruoyi-@h2ju02hebp
tdengine: # IOT 数据库
# lazy: true # 开启懒加载,保证启动速度
url: jdbc:TAOS-RS://chaojiniu.top:6041/ruoyi_vue_pro
driver-class-name: com.taosdata.jdbc.rs.RestfulDriver
username: root username: root
password: ahh@123456 password: taosdata
druid:
validation-query: SELECT SERVER_STATUS() # TDengine 数据源的有效性检查 SQL
# Redis 配置。Redisson 默认的配置足够使用,一般不需要进行调优 # Redis 配置。Redisson 默认的配置足够使用,一般不需要进行调优
data: data:
redis: redis:
host: 127.0.0.1 # 地址 host: chaojiniu.top # 地址
port: 6379 # 端口 port: 6379 # 端口
database: 0 # 数据库索引 database: 15 # 数据库索引
# password: dev # 密码,建议生产环境开启 password: fsknKD7UvQYZsyf2hXXn # 密码,建议生产环境开启
--- #################### 定时任务相关配置 #################### --- #################### 定时任务相关配置 ####################
@ -175,8 +183,10 @@ logging:
cn.iocoder.yudao.module.crm.dal.mysql: debug cn.iocoder.yudao.module.crm.dal.mysql: debug
cn.iocoder.yudao.module.erp.dal.mysql: debug cn.iocoder.yudao.module.erp.dal.mysql: debug
cn.iocoder.yudao.module.iot.dal.mysql: debug cn.iocoder.yudao.module.iot.dal.mysql: debug
cn.iocoder.yudao.module.iot.dal.tdengine: DEBUG
cn.iocoder.yudao.module.ai.dal.mysql: debug cn.iocoder.yudao.module.ai.dal.mysql: debug
org.springframework.context.support.PostProcessorRegistrationDelegate: ERROR # TODO 芋艿先禁用Spring Boot 3.X 存在部分错误的 WARN 提示 org.springframework.context.support.PostProcessorRegistrationDelegate: ERROR # TODO 芋艿先禁用Spring Boot 3.X 存在部分错误的 WARN 提示
com.taosdata: DEBUG # TDengine 的日志级别
debug: false debug: false
@ -259,7 +269,7 @@ justauth:
iot: iot:
emq: emq:
# 账号 # 账号
username: anhaohao username: haohao
# 密码 # 密码
password: ahh@123456 password: ahh@123456
# 主机地址 # 主机地址
@ -271,4 +281,18 @@ iot:
# 保持连接 # 保持连接
keepalive: 60 keepalive: 60
# 清除会话(设置为false,断开连接,重连后使用原来的会话 保留订阅的主题,能接收离线期间的消息) # 清除会话(设置为false,断开连接,重连后使用原来的会话 保留订阅的主题,能接收离线期间的消息)
clearSession: true clearSession: true
# MQTT-RPC 配置
mqtt:
broker: tcp://chaojiniu.top:1883
username: haohao
password: ahh@123456
clientId: mqtt-rpc-server-${random.int}
requestTopic: rpc/request
responseTopicPrefix: rpc/response/
# 插件配置
pf4j:
pluginsDir: /Users/anhaohao/code/gitee/ruoyi-vue-pro/plugins # 插件目录