物联网平台ThingsBoard开发环境构建记:从零到一的全过程与踩坑实录
物联网平台ThingsBoard开发环境构建记:从零到一的全过程与踩坑实录
前言
最近因项目需要,我们准备基于ThingsBoard开发一套医院后勤管理系统。ThingsBoard作为一款开源物联网平台,功能强大,但它的开发环境搭建并不像官方文档描述的那么“丝滑”。从源码编译到数据库初始化,再到服务启动,我们踩了不少坑。本文详细记录了整个构建过程以及遇到的七个典型问题及其解决方案,希望能为同样准备上手ThingsBoard的开发者提供一份避坑指南。
一、环境准备
在开始之前,请确保以下软件已正确安装:
| 组件 | 推荐版本 | 备注 |
|---|---|---|
| JDK | OpenJDK 17 | ThingsBoard 4.3.x 要求 JDK 17 |
| Maven | 3.6+ | 用于构建后端 |
| Node.js | 18.x 或 20.x | 用于前端编译 |
| Yarn | 1.22.x | 前端包管理器 |
| PostgreSQL | 13+ | 需要创建两个数据库 |
| Git | 最新版 | 克隆源码 |
| Docker (可选) | 20.10+ | 用于快速启动数据库 |
注意:Windows 用户强烈建议使用 WSL2 + Ubuntu 环境,可避免许多路径和脚本兼容性问题。本文的踩坑经历基于原生 Windows 环境,因此更具参考价值。
二、源码获取与编译
2.1 克隆代码
git clone https://github.com/thingsboard/thingsboard.git
cd thingsboard
2.2 配置Maven仓库镜像(关键!)
踩坑1:gradle-maven-plugin 1.0.12 找不到
编译一开始就遇到:
Plugin org.thingsboard:gradle-maven-plugin:1.0.12 or one of its dependencies could not be resolved
这个插件是 ThingsBoard 自定义的,默认 Maven 中央仓库中没有,阿里云镜像也没有。
踩坑2:org.thingsboard.langchain4j:langchain4j-bom:1.8.0-TB 找不到
同样,这个依赖也不在公共仓库中。
解决办法:在 Maven 的 settings.xml 中增加 ThingsBoard 官方仓库的镜像,让 Maven 能够从 ThingsBoard 自己的仓库中下载这些构件。
编辑你使用的 settings.xml(全局路径如 I:\apache-maven-3.9.9\conf\settings.xml,用户级路径如 C:\Users\<用户名>\.m2\settings.xml),在 <mirrors> 标签内添加:
<mirror>
<id>thingsboard-repo</id>
<mirrorOf>*</mirrorOf>
<name>thingsboard-repo</name>
<url>https://repo.thingsboard.io/artifactory/libs-release-public</url>
</mirror>
注意:<mirrorOf>*</mirrorOf> 会拦截所有仓库请求,将其重定向到 ThingsBoard 仓库。如果担心其他依赖下载变慢,可以只镜像特定的仓库 ID,但为了简单,这里用 * 也没问题,因为 ThingsBoard 仓库本身也代理了大量公共依赖。
添加后保存,重新执行编译命令即可正常下载这些专属依赖。
2.3 编译
mvn clean install -DskipTests
编译后为三个操作系统打包:
- redhat linux : thingsboard.rpm
- debian: thingsboard.deb
- windows: thingsboard-windows.zip
我使用rocky linux,并没有采用thingsboard.rpm,而是把bin, conf, control, data目录,还有两个jar包:thingsboard-4.3.1.1.jar,thingsboard-4.3.1.1-boot.jar使用7zip打包为thingsboard-linux.7z
上传到操作系统,使用如下命令解压:
7z x thingsboard-linux.7z -o/feng/thingsboard
踩坑3:gradle-maven-plugin 下载 gradle-7.3.3-bin.zip 卡死
编译过程中,edqs 模块需要执行 gradle-maven-plugin,该插件会尝试从 https://services.gradle.org/distributions/ 下载 gradle-7.3.3-bin.zip。由于网络原因,下载非常缓慢甚至卡死。
解决方法:
- 手动下载
gradle-7.3.3-bin.zip(可从腾讯云镜像或 Gradle 官网获取)。 - 放入 Gradle Wrapper 缓存目录:
C:\Users\<用户名>\.gradle\wrapper\dists\gradle-7.3.3-bin\下的某个子目录中(如6a41zxkdtcxs8rphpq6y0069z),并删除原有的.part临时文件。 - 重新编译,插件会直接使用本地缓存,跳过网络下载。
踩坑4:winsw-2.0.1-bin.exe 下载失败
编译 edqs 模块时,日志显示:
Could not find artifact com.sun.winsw:winsw:exe:bin:2.0.1
winsw 是一个用于将 Java 程序包装为 Windows 服务的工具,它的二进制文件同样不在公共仓库中。
解决方法:
- 手动下载
winsw-2.0.1-bin.exe(可从 Jenkins 仓库获取:https://repo.jenkins-ci.org/releases/com/sun/winsw/winsw/2.0.1/winsw-2.0.1-bin.exe)。 - 使用 Maven 命令将其安装到本地仓库:
mvn install:install-file -Dfile=winsw-2.0.1-bin.exe -DgroupId=com.sun.winsw -DartifactId=winsw -Dversion=2.0.1 -Dpackaging=exe -Dclassifier=bin - 重新编译,依赖解析成功。
2.4 前端说明
其实编译时前端也一块儿编译了。这里说明一下ThingsBoard 的前端,它分为两部分:ui-ngx(主 UI)和 msa/web-ui(微服务版本的 UI 包装)。后者在编译时会使用 pkg 工具将 Node.js 应用打包成可执行文件。
踩坑5:frontend-maven-plugin 自动添加代理参数
执行 mvn install 时,日志显示:
Found proxies: [netbeans-default-proxy{protocol='http', host='127.0.0.1', port=4780}]
Running 'yarn run build:prod --https-proxy=http://127.0.0.1:4780 --proxy=http://127.0.0.1:4780'
Error: Unknown arguments: https-proxy, proxy
这是因为 Maven Settings 中激活了一个名为 netbeans-default-proxy 的代理(通常由 NetBeans IDE 自动添加),导致 frontend-maven-plugin 将代理参数传递给 yarn,而 Angular CLI 不识别这些参数。
解决方法:
编辑 ~/.m2/settings.xml,找到 <proxies> 标签,将 netbeans-default-proxy 的 <active>true</active> 改为 <active>false</active>,或直接删除该 proxy 块。保存后重新编译,代理参数不再出现。
踩坑6:pkg 打包时下载 Node 二进制文件失败
编译 msa/web-ui 模块时,执行 yarn run pkg 会调用 pkg-fetch 下载 Node.js 的预编译二进制文件(例如 node-v22.17.1-win-x64 和 node-v22.17.1-linux-x64)。由于网络原因,下载经常失败,报错类似:
Error! Network error during fetch: request to https://github.com/yao-pkg/pkg-fetch/releases/download/v3.5/node-v22.17.1-linux-x64 failed
解决方法:
- 手动从 GitHub Releases 下载所需的二进制文件:
node-v22.17.1-win-x64node-v22.17.1-linux-x64
下载地址:https://github.com/yao-pkg/pkg-fetch/releases/tag/v3.5(根据日志中的 tag 版本选择)
- 设置环境变量
PKG_CACHE_PATH,指向一个你创建的缓存目录,例如:set PKG_CACHE_PATH=C:\Users\<用户名>\.pkg-cache - 在该缓存目录下创建版本子目录,如
v3.5,然后将下载的文件放入其中,并重命名为:fetched-v22.17.1-win-x64fetched-v22.17.1-linux-x64
- 重新编译
msa/web-ui,pkg 会直接从缓存中读取,不再尝试网络下载。
注意:pkg 在打包时会同时需要 Windows 和 Linux 的二进制(因为目标平台包括两者),因此两个文件都需要准备。
三、数据库初始化
3.1 准备 PostgreSQL
首先确保 PostgreSQL 服务已启动,并创建两个数据库:
CREATE DATABASE thingsboard;
CREATE DATABASE thingsboard_events;
3.2 执行初始化脚本
官方文档给出的linux命令是:
cd bin/install
./install_dev_db.sh
实际上install_dev_db.sh脚本使用了这个配置文件:conf/thingsboard.yml,其中有个错误:
value_bytes_size: "${SECURITY_API_KEY_VALUE_PREFIX:64}"
应该改为:
value_bytes_size: "${SECURITY_API_KEY_VALUE_BYTES_SIZE:64}"
thingsboard.yml包含了上百个环境变量,最好在install_dev_db.sh脚本中设置环境变量而不必再profile文件中设置环境变量:
#!/bin/bash
BASE=/feng/thingsboard
jarfile="${BASE}/thingsboard-4.3.1.1-boot.jar"
installDir=${BASE}/data
loadDemo=true
upgrade=false
# 错误处理
error_exit() {
echo -e "\033[31m[ERROR] $1\033[0m" >&2
exit 1
}
# 检查 JAR 文件
if [ ! -f "$jarfile" ]; then
error_exit "JAR file not found: $jarfile"
fi
# 环境变量
export JAVA_OPTS="$JAVA_OPTS -Dplatform=@pkg.platform@"
export LOADER_PATH="${BASE}/conf,${BASE}/extensions"
export SQL_DATA_FOLDER="${SQL_DATA_FOLDER:-/tmp}"
export SPRING_MVC_ASYNC_REQUEST_TIMEOUT="300000"
export SPRING_SERVLET_MULTIPART_MAX_FILE_SIZE="50MB"
export SPRING_SERVLET_MULTIPART_MAX_REQUEST_SIZE="50MB"
export SPRING_JPA_PROPERTIES_HIBERNATE_ORDER_BY_DEFAULT_NULL_ORDERING="last"
export SPRING_JPA_DIALECT="org.thingsboard.server.dao.ThingsboardPostgreSQLDialect"
export JAVAX_PERSISTENCE_QUERY_TIMEOUT="300000"
export SPRING_DRIVER_CLASS_NAME="org.postgresql.Driver"
export SPRING_DATASOURCE_URL="jdbc:postgresql://8.141.5.220:15432/thingsboard?connectTimeout=30&socketTimeout=30"
export SPRING_DATASOURCE_USERNAME="postgres"
export SPRING_DATASOURCE_PASSWORD="123456"
export SPRING_DATASOURCE_HIKARI_LEAK_DETECTION_THRESHOLD="0"
export SPRING_DATASOURCE_MAXIMUM_POOL_SIZE="16"
export SPRING_DATASOURCE_HIKARI_REGISTER_MBEANS="false"
export SPRING_DEDICATED_EVENTS_DATASOURCE_ENABLED="false"
export SPRING_EVENTS_DATASOURCE_DRIVER_CLASS_NAME="org.postgresql.Driver"
export SPRING_EVENTS_DATASOURCE_URL="jdbc:postgresql://8.141.5.220:15432/thingsboard_events?connectTimeout=30&socketTimeout=30"
export SPRING_EVENTS_DATASOURCE_USERNAME="postgres"
export SPRING_EVENTS_DATASOURCE_PASSWORD="123456"
export SPRING_EVENTS_DATASOURCE_HIKARI_LEAK_DETECTION_THRESHOLD="0"
export SPRING_EVENTS_DATASOURCE_MAXIMUM_POOL_SIZE="4"
export SPRING_EVENTS_DATASOURCE_HIKARI_REGISTER_MBEANS="false"
# 确保运行用户
if [ "$EUID" -eq 0 ]; then
run_user="thingsboard"
if ! id "thingsboard" &>/dev/null; then
useradd -m -s /bin/bash thingsboard
fi
# 创建日志目录并授权
mkdir -p /var/log/thingsboard
chown -R "$run_user":"$run_user" /var/log/thingsboard
mkdir -p "$installDir"
chown -R "$run_user":"$run_user" "$installDir"
mkdir -p "${BASE}/logs" 2>/dev/null
chown -R "$run_user":"$run_user" "$BASE" 2>/dev/null || true
else
run_user="$USER"
fi
echo "Using system user: $run_user"
echo "Database URL: $SPRING_DATASOURCE_URL"
echo "Starting ThingsBoard database installation..."
# 使用 su 切换用户,执行 java -cp 并指定正确的 Launcher 类
su -s /bin/bash - "$run_user" <<EOF
export JAVA_OPTS="$JAVA_OPTS"
export LOADER_PATH="$LOADER_PATH"
export SQL_DATA_FOLDER="$SQL_DATA_FOLDER"
export SPRING_MVC_ASYNC_REQUEST_TIMEOUT="$SPRING_MVC_ASYNC_REQUEST_TIMEOUT"
export SPRING_SERVLET_MULTIPART_MAX_FILE_SIZE="$SPRING_SERVLET_MULTIPART_MAX_FILE_SIZE"
export SPRING_SERVLET_MULTIPART_MAX_REQUEST_SIZE="$SPRING_SERVLET_MULTIPART_MAX_REQUEST_SIZE"
export SPRING_JPA_PROPERTIES_HIBERNATE_ORDER_BY_DEFAULT_NULL_ORDERING="$SPRING_JPA_PROPERTIES_HIBERNATE_ORDER_BY_DEFAULT_NULL_ORDERING"
export SPRING_JPA_DIALECT="$SPRING_JPA_DIALECT"
export JAVAX_PERSISTENCE_QUERY_TIMEOUT="$JAVAX_PERSISTENCE_QUERY_TIMEOUT"
export SPRING_DRIVER_CLASS_NAME="$SPRING_DRIVER_CLASS_NAME"
export SPRING_DATASOURCE_URL="$SPRING_DATASOURCE_URL"
export SPRING_DATASOURCE_USERNAME="$SPRING_DATASOURCE_USERNAME"
export SPRING_DATASOURCE_PASSWORD="$SPRING_DATASOURCE_PASSWORD"
export SPRING_DATASOURCE_HIKARI_LEAK_DETECTION_THRESHOLD="$SPRING_DATASOURCE_HIKARI_LEAK_DETECTION_THRESHOLD"
export SPRING_DATASOURCE_MAXIMUM_POOL_SIZE="$SPRING_DATASOURCE_MAXIMUM_POOL_SIZE"
export SPRING_DATASOURCE_HIKARI_REGISTER_MBEANS="$SPRING_DATASOURCE_HIKARI_REGISTER_MBEANS"
export SPRING_DEDICATED_EVENTS_DATASOURCE_ENABLED="$SPRING_DEDICATED_EVENTS_DATASOURCE_ENABLED"
export SPRING_EVENTS_DATASOURCE_DRIVER_CLASS_NAME="$SPRING_EVENTS_DATASOURCE_DRIVER_CLASS_NAME"
export SPRING_EVENTS_DATASOURCE_URL="$SPRING_EVENTS_DATASOURCE_URL"
export SPRING_EVENTS_DATASOURCE_USERNAME="$SPRING_EVENTS_DATASOURCE_USERNAME"
export SPRING_EVENTS_DATASOURCE_PASSWORD="$SPRING_EVENTS_DATASOURCE_PASSWORD"
export SPRING_EVENTS_DATASOURCE_HIKARI_LEAK_DETECTION_THRESHOLD="$SPRING_EVENTS_DATASOURCE_HIKARI_LEAK_DETECTION_THRESHOLD"
export SPRING_EVENTS_DATASOURCE_MAXIMUM_POOL_SIZE="$SPRING_EVENTS_DATASOURCE_MAXIMUM_POOL_SIZE"
export SPRING_EVENTS_DATASOURCE_HIKARI_REGISTER_MBEANS="$SPRING_EVENTS_DATASOURCE_HIKARI_REGISTER_MBEANS"
# 使用 -cp 和正确的 PropertiesLauncher 类(包含 launch 路径)
java -cp "$jarfile" \
-Dloader.main=org.thingsboard.server.ThingsboardInstallApplication \
-Dinstall.data_dir="$installDir" \
-Dinstall.load_demo=$loadDemo \
-Dspring.jpa.hibernate.ddl-auto=none \
-Dinstall.upgrade=$upgrade \
-Djava.net.preferIPv4Stack=true \
org.springframework.boot.loader.launch.PropertiesLauncher
EOF
exit_code=$?
if [ $exit_code -ne 0 ]; then
echo -e "\033[31mThingsBoard DB installation failed with exit code $exit_code!\033[0m"
if [ -f /var/log/thingsboard/thingsboard.log ]; then
echo "Last 50 lines of /var/log/thingsboard/thingsboard.log:"
tail -50 /var/log/thingsboard/thingsboard.log
fi
exit $exit_code
else
echo -e "\033[32mThingsBoard DB installation completed successfully.\033[0m"
fi
执行后的效果为:
[root@iZ2ze6qcuxrmhddeb4m9xuZ thingsboard]# rm -f /var/log/thingsboard/thingsboard.log
[root@iZ2ze6qcuxrmhddeb4m9xuZ thingsboard]# bash bin/install/install_dev_db.sh
Using system user: thingsboard
Database URL: jdbc:postgresql://8.141.5.220:15432/thingsboard?connectTimeout=30&socketTimeout=30
Starting ThingsBoard database installation...
Last login: Mon May 11 13:00:10 CST 2026
_____ _ _ ____ _
|_ _| |__ (_)_ __ __ _ ___| __ ) ___ __ _ _ __ __| |
| | | '_ \| | '_ \ / _` / __| _ \ / _ \ / _` | '__/ _` |
| | | | | | | | | | (_| \__ \ |_) | (_) | (_| | | | (_| |
|_| |_| |_|_|_| |_|\__, |___/____/ \___/ \__,_|_| \__,_|
|___/
===========================================================
:: ThingsBoard :: (v4.3.1.1)
===========================================================
ThingsBoard DB installation completed successfully.
[root@iZ2ze6qcuxrmhddeb4m9xuZ thingsboard]# cat /var/log/thingsboard/thingsboard.log
2026-05-11 13:02:38,823 [background-preinit] INFO o.h.validator.internal.util.Version - HV000001: Hibernate Validator 8.0.3.Final
2026-05-11 13:02:39,131 [main] INFO o.t.s.ThingsboardInstallApplication - Starting ThingsboardInstallApplication v4.3.1.1 using Java 17.0.14 with PID 4113505 (/feng/thingsboard/thingsboard-4.3.1.1-boot.jar started by thingsboard in /home/thingsboard)
2026-05-11 13:02:39,132 [main] INFO o.t.s.ThingsboardInstallApplication - The following 1 profile is active: "install"
2026-05-11 13:02:44,338 [main] INFO o.s.d.r.c.RepositoryConfigurationDelegate - Multiple Spring Data modules found, entering strict repository configuration mode
2026-05-11 13:02:44,339 [main] INFO o.s.d.r.c.RepositoryConfigurationDelegate - Bootstrapping Spring Data JPA repositories in LAZY mode.
2026-05-11 13:02:44,671 [main] INFO o.s.d.r.c.RepositoryConfigurationDelegate - Finished Spring Data repository scanning in 309 ms. Found 7 JPA repository interfaces.
2026-05-11 13:02:44,677 [main] INFO o.s.d.r.c.RepositoryConfigurationDelegate - Multiple Spring Data modules found, entering strict repository configuration mode
2026-05-11 13:02:44,677 [main] INFO o.s.d.r.c.RepositoryConfigurationDelegate - Bootstrapping Spring Data JPA repositories in LAZY mode.
2026-05-11 13:02:45,191 [main] INFO o.s.d.r.c.RepositoryConfigurationDelegate - Finished Spring Data repository scanning in 510 ms. Found 58 JPA repository interfaces.
2026-05-11 13:02:45,196 [main] INFO o.s.d.r.c.RepositoryConfigurationDelegate - Multiple Spring Data modules found, entering strict repository configuration mode
2026-05-11 13:02:45,196 [main] INFO o.s.d.r.c.RepositoryConfigurationDelegate - Bootstrapping Spring Data JPA repositories in LAZY mode.
2026-05-11 13:02:45,217 [main] INFO o.s.d.r.c.RepositoryConfigurationDelegate - Finished Spring Data repository scanning in 16 ms. Found 1 JPA repository interface.
2026-05-11 13:02:45,225 [main] INFO o.s.d.r.c.RepositoryConfigurationDelegate - Multiple Spring Data modules found, entering strict repository configuration mode
2026-05-11 13:02:45,225 [main] INFO o.s.d.r.c.RepositoryConfigurationDelegate - Bootstrapping Spring Data JPA repositories in LAZY mode.
2026-05-11 13:02:45,243 [main] INFO o.s.d.r.c.RepositoryConfigurationDelegate - Finished Spring Data repository scanning in 14 ms. Found 1 JPA repository interface.
2026-05-11 13:02:47,121 [main] INFO o.s.i.c.DefaultConfiguringBeanFactoryPostProcessor - No bean named 'errorChannel' has been explicitly defined. Therefore, a default PublishSubscribeChannel will be created.
2026-05-11 13:02:47,149 [main] INFO o.s.i.c.DefaultConfiguringBeanFactoryPostProcessor - No bean named 'integrationHeaderChannelRegistry' has been explicitly defined. Therefore, a default DefaultHeaderChannelRegistry will be created.
2026-05-11 13:02:49,366 [main] INFO o.s.b.w.e.tomcat.TomcatWebServer - Tomcat initialized with port 8080 (http)
2026-05-11 13:02:49,395 [main] INFO o.a.coyote.http11.Http11NioProtocol - The ["http-nio-0.0.0.0-8080"] connector has been configured to support HTTP upgrade to [h2c]
2026-05-11 13:02:49,396 [main] INFO o.a.coyote.http11.Http11NioProtocol - Initializing ProtocolHandler ["http-nio-0.0.0.0-8080"]
2026-05-11 13:02:49,400 [main] INFO o.a.catalina.core.StandardService - Starting service [Tomcat]
2026-05-11 13:02:49,401 [main] INFO o.a.catalina.core.StandardEngine - Starting Servlet engine: [Apache Tomcat/10.1.52]
2026-05-11 13:02:49,529 [main] INFO o.a.c.c.C.[Tomcat].[localhost].[/] - Initializing Spring embedded WebApplicationContext
2026-05-11 13:02:49,530 [main] INFO o.s.b.w.s.c.ServletWebServerApplicationContext - Root WebApplicationContext: initialization completed in 10251 ms
2026-05-11 13:02:50,710 [main] INFO o.h.jpa.internal.util.LogHelper - HHH000204: Processing PersistenceUnitInfo [name: default]
2026-05-11 13:02:51,014 [main] INFO org.hibernate.Version - HHH000412: Hibernate ORM core version 6.6.44.Final
2026-05-11 13:02:51,128 [main] INFO o.h.c.i.RegionFactoryInitiator - HHH000026: Second-level cache disabled
2026-05-11 13:02:51,497 [main] INFO com.zaxxer.hikari.HikariDataSource - HikariPool-1 - Starting...
2026-05-11 13:02:52,416 [main] INFO com.zaxxer.hikari.pool.HikariPool - HikariPool-1 - Added connection org.postgresql.jdbc.PgConnection@14ca4b4d
2026-05-11 13:02:52,423 [main] INFO com.zaxxer.hikari.HikariDataSource - HikariPool-1 - Start completed.
2026-05-11 13:02:52,742 [main] INFO o.hibernate.orm.connections.pooling - HHH10001005: Database info:
Database JDBC URL [Connecting through datasource 'HikariDataSource (HikariPool-1)']
Database driver: undefined/unknown
Database version: 12.0
Autocommit mode: undefined/unknown
Isolation level: undefined/unknown
Minimum pool size: undefined/unknown
Maximum pool size: undefined/unknown
2026-05-11 13:02:54,442 [main] INFO o.s.o.j.p.SpringPersistenceUnitInfo - No LoadTimeWeaver setup: ignoring JPA class transformer
2026-05-11 13:03:01,020 [main] INFO o.h.e.t.j.p.i.JtaPlatformInitiator - HHH000489: No JTA platform available (set 'hibernate.transaction.jta.platform' to enable JTA platform integration)
2026-05-11 13:03:01,049 [main] INFO o.s.o.j.LocalContainerEntityManagerFactoryBean - Initialized JPA EntityManagerFactory for persistence unit 'default'
2026-05-11 13:03:04,868 [main] INFO o.t.s.d.a.CachedAttributesService - Going to use directExecutor for the local cache type caffeine
2026-05-11 13:03:05,908 [main] INFO o.t.s.d.s.NamedParameterJdbcTemplateConfiguration - Set jdbcTemplate query timeout [30] second(s)
2026-05-11 13:03:06,934 [main] INFO o.s.b.a.w.s.WelcomePageHandlerMapping - Adding welcome page: class path resource [public/index.html]
2026-05-11 13:03:10,555 [main] INFO o.s.b.a.e.web.EndpointLinksResolver - Exposing 1 endpoint beneath base path '/actuator'
2026-05-11 13:03:11,474 [main] INFO o.s.i.endpoint.EventDrivenConsumer - Adding {logging-channel-adapter:_org.springframework.integration.errorLogger} as a subscriber to the 'errorChannel' channel
2026-05-11 13:03:11,475 [main] INFO o.s.i.c.PublishSubscribeChannel - Channel 'application.errorChannel' has 1 subscriber(s).
2026-05-11 13:03:11,482 [main] INFO o.s.i.endpoint.EventDrivenConsumer - started bean '_org.springframework.integration.errorLogger'
2026-05-11 13:03:11,544 [main] INFO o.a.coyote.http11.Http11NioProtocol - Starting ProtocolHandler ["http-nio-0.0.0.0-8080"]
2026-05-11 13:03:11,568 [main] INFO o.s.b.w.e.tomcat.TomcatWebServer - Tomcat started on port 8080 (http) with context path '/'
2026-05-11 13:03:11,630 [main] INFO o.t.s.ThingsboardInstallApplication - Started ThingsboardInstallApplication in 34.404 seconds (process running for 36.787)
2026-05-11 13:03:11,706 [main] INFO o.t.s.i.ThingsboardInstallService - Starting ThingsBoard Installation...
2026-05-11 13:03:11,707 [main] INFO o.t.s.i.ThingsboardInstallService - Installing DataBase schema for entities...
2026-05-11 13:03:11,707 [main] INFO o.t.s.s.i.SqlAbstractDatabaseSchemaService - Installing SQL DataBase schema part: schema-entities.sql
2026-05-11 13:03:12,061 [main] INFO o.t.s.s.i.SqlAbstractDatabaseSchemaService - Installing SQL DataBase schema indexes part: schema-entities-idx.sql
2026-05-11 13:03:12,187 [main] INFO o.t.s.s.i.SqlEntityDatabaseSchemaService - Installing SQL DataBase schema PostgreSQL specific indexes part: schema-entities-idx-psql-addon.sql
2026-05-11 13:03:12,292 [main] INFO o.t.s.s.i.SqlEntityDatabaseSchemaService - Installing SQL DataBase schema views: schema-views.sql
2026-05-11 13:03:12,370 [main] INFO o.t.s.s.i.SqlEntityDatabaseSchemaService - Installing SQL DataBase schema functions: schema-functions.sql
2026-05-11 13:03:12,484 [main] INFO o.t.s.s.i.SqlAbstractDatabaseSchemaService - Successfully executed query: DROP VIEW IF EXISTS device_info_view CASCADE;
2026-05-11 13:03:17,538 [main] INFO o.t.s.s.i.SqlAbstractDatabaseSchemaService - Successfully executed query: CREATE OR REPLACE VIEW device_info_view AS SELECT * FROM device_info_active_attribute_view;
2026-05-11 13:03:22,541 [main] INFO o.t.s.i.ThingsboardInstallService - Installing DataBase schema for timeseries...
2026-05-11 13:03:22,542 [main] INFO o.t.s.s.i.SqlAbstractDatabaseSchemaService - Installing SQL DataBase schema part: schema-ts-psql.sql
2026-05-11 13:03:22,667 [main] INFO o.t.s.s.i.SqlAbstractDatabaseSchemaService - Successfully executed query: CREATE TABLE IF NOT EXISTS ts_kv_indefinite PARTITION OF ts_kv DEFAULT;
2026-05-11 13:03:27,671 [main] INFO o.t.s.i.ThingsboardInstallService - Loading system data...
2026-05-11 13:03:28,320 [main] INFO o.s.d.j.r.query.QueryEnhancerFactory - Hibernate is in classpath; If applicable, HQL parser will be used.
2026-05-11 13:03:32,160 [main] INFO c.d.oss.driver.api.core.uuid.Uuids - PID obtained through native call to getpid(): 4113505
2026-05-11 13:03:34,834 [main] INFO org.owasp.validator.html.Policy - Attempting to load AntiSamy policy from an input stream.
2026-05-11 13:03:35,102 [main] WARN org.owasp.validator.html.Policy - The directive "noopenerAndNoreferrerAnchors" is enabled by default, but disabled in this policy. It is recommended to leave it enabled to prevent reverse tabnabbing attacks.
2026-05-11 13:03:36,353 [main] INFO o.t.s.s.i.DefaultSystemDataLoaderService - Creating JWT admin settings...
2026-05-11 13:03:36,368 [main] INFO o.t.s.s.s.a.j.s.DefaultJwtSettingsService - Saving new JWT admin settings. From this moment, the JWT parameters from YAML and ENV will be ignored
2026-05-11 13:03:36,409 [main] INFO o.t.s.service.install.InstallScripts - Loading system widgets
2026-05-11 13:04:30,801 [main] INFO o.t.s.service.install.InstallScripts - Loading system SCADA symbols
2026-05-11 13:05:01,007 [main] INFO o.t.s.s.i.DefaultSystemDataLoaderService - Creating default notification configs for system admin
2026-05-11 13:05:01,372 [main] INFO o.t.s.s.i.DefaultSystemDataLoaderService - Creating default notification configs for all tenants
2026-05-11 13:05:09,923 [main] INFO o.t.s.service.install.InstallScripts - Loading system images and resources...
2026-05-11 13:05:10,001 [main] INFO o.t.s.d.resource.BaseResourceService - Creating system resource gateway-management-extension.js
2026-05-11 13:05:11,821 [main] INFO o.t.s.d.resource.BaseResourceService - Creating system resource gateways_dashboard.json
2026-05-11 13:05:11,855 [main] INFO o.t.s.i.ThingsboardInstallService - Loading demo data...
2026-05-11 13:05:14,901 [sql-log-1-thread-1] INFO o.t.s.dao.sql.TbSqlBlockingQueue - Queue-1 [TS] queueSize [0] totalAdded [17] totalSaved [17] totalFailed [0]
2026-05-11 13:05:14,938 [sql-log-1-thread-1] INFO o.t.s.dao.sql.TbSqlBlockingQueue - Queue-1 [TS Latest] queueSize [0] totalAdded [17] totalSaved [17] totalFailed [0]
2026-05-11 13:05:15,836 [main] INFO o.t.s.i.ThingsboardInstallService - Installation finished successfully!
2026-05-11 13:05:15,849 [main] INFO o.s.b.w.e.tomcat.GracefulShutdown - Commencing graceful shutdown. Waiting for active requests to complete
2026-05-11 13:05:15,851 [tomcat-shutdown] INFO o.a.coyote.http11.Http11NioProtocol - Pausing ProtocolHandler ["http-nio-0.0.0.0-8080"]
2026-05-11 13:05:15,857 [tomcat-shutdown] INFO o.s.b.w.e.tomcat.GracefulShutdown - Graceful shutdown complete
2026-05-11 13:05:15,858 [main] INFO o.a.coyote.http11.Http11NioProtocol - Stopping ProtocolHandler ["http-nio-0.0.0.0-8080"]
2026-05-11 13:05:15,900 [main] INFO o.s.i.endpoint.EventDrivenConsumer - Removing {logging-channel-adapter:_org.springframework.integration.errorLogger} as a subscriber to the 'errorChannel' channel
2026-05-11 13:05:15,900 [main] INFO o.s.i.c.PublishSubscribeChannel - Channel 'application.errorChannel' has 0 subscriber(s).
2026-05-11 13:05:15,901 [main] INFO o.s.i.endpoint.EventDrivenConsumer - stopped bean '_org.springframework.integration.errorLogger'
2026-05-11 13:05:15,931 [sql-queue-0-attributes-6-thread-1] INFO o.t.s.dao.sql.TbSqlBlockingQueue - [Attributes] Queue polling was interrupted
2026-05-11 13:05:15,932 [sql-queue-0-attributes-6-thread-1] INFO o.t.s.dao.sql.TbSqlBlockingQueue - [Attributes] Queue polling completed
2026-05-11 13:05:15,932 [sql-queue-1-attributes-7-thread-1] INFO o.t.s.dao.sql.TbSqlBlockingQueue - [Attributes] Queue polling was interrupted
2026-05-11 13:05:15,932 [sql-queue-1-attributes-7-thread-1] INFO o.t.s.dao.sql.TbSqlBlockingQueue - [Attributes] Queue polling completed
2026-05-11 13:05:15,932 [sql-queue-2-attributes-8-thread-1] INFO o.t.s.dao.sql.TbSqlBlockingQueue - [Attributes] Queue polling was interrupted
2026-05-11 13:05:15,932 [sql-queue-2-attributes-8-thread-1] INFO o.t.s.dao.sql.TbSqlBlockingQueue - [Attributes] Queue polling completed
2026-05-11 13:05:15,932 [sql-queue-1-ts latest-13-thread-1] INFO o.t.s.dao.sql.TbSqlBlockingQueue - [TS Latest] Queue polling was interrupted
2026-05-11 13:05:15,932 [sql-queue-1-ts latest-13-thread-1] INFO o.t.s.dao.sql.TbSqlBlockingQueue - [TS Latest] Queue polling completed
2026-05-11 13:05:15,933 [sql-queue-1-ts-10-thread-1] INFO o.t.s.dao.sql.TbSqlBlockingQueue - [TS] Queue polling was interrupted
2026-05-11 13:05:15,933 [sql-queue-1-ts-10-thread-1] INFO o.t.s.dao.sql.TbSqlBlockingQueue - [TS] Queue polling completed
2026-05-11 13:05:15,933 [sql-queue-2-ts latest-14-thread-1] INFO o.t.s.dao.sql.TbSqlBlockingQueue - [TS Latest] Queue polling was interrupted
2026-05-11 13:05:15,933 [sql-queue-2-ts latest-14-thread-1] INFO o.t.s.dao.sql.TbSqlBlockingQueue - [TS Latest] Queue polling completed
2026-05-11 13:05:15,933 [sql-queue-0-ts-9-thread-1] INFO o.t.s.dao.sql.TbSqlBlockingQueue - [TS] Queue polling was interrupted
2026-05-11 13:05:15,933 [sql-queue-0-ts-9-thread-1] INFO o.t.s.dao.sql.TbSqlBlockingQueue - [TS] Queue polling completed
2026-05-11 13:05:15,934 [sql-queue-2-ts-11-thread-1] INFO o.t.s.dao.sql.TbSqlBlockingQueue - [TS] Queue polling was interrupted
2026-05-11 13:05:15,934 [sql-queue-2-ts-11-thread-1] INFO o.t.s.dao.sql.TbSqlBlockingQueue - [TS] Queue polling completed
2026-05-11 13:05:15,934 [sql-queue-0-ts latest-12-thread-1] INFO o.t.s.dao.sql.TbSqlBlockingQueue - [TS Latest] Queue polling was interrupted
2026-05-11 13:05:15,934 [sql-queue-0-ts latest-12-thread-1] INFO o.t.s.dao.sql.TbSqlBlockingQueue - [TS Latest] Queue polling completed
2026-05-11 13:05:15,938 [sql-queue-0-events-3-thread-1] INFO o.t.s.dao.sql.TbSqlBlockingQueue - [Events] Queue polling was interrupted
2026-05-11 13:05:15,938 [sql-queue-0-events-3-thread-1] INFO o.t.s.dao.sql.TbSqlBlockingQueue - [Events] Queue polling completed
2026-05-11 13:05:15,938 [sql-queue-1-events-4-thread-1] INFO o.t.s.dao.sql.TbSqlBlockingQueue - [Events] Queue polling was interrupted
2026-05-11 13:05:15,938 [sql-queue-1-events-4-thread-1] INFO o.t.s.dao.sql.TbSqlBlockingQueue - [Events] Queue polling completed
2026-05-11 13:05:15,938 [sql-queue-2-events-5-thread-1] INFO o.t.s.dao.sql.TbSqlBlockingQueue - [Events] Queue polling was interrupted
2026-05-11 13:05:15,939 [sql-queue-2-events-5-thread-1] INFO o.t.s.dao.sql.TbSqlBlockingQueue - [Events] Queue polling completed
2026-05-11 13:05:15,939 [sql-queue-0-edge events-2-thread-1] INFO o.t.s.dao.sql.TbSqlBlockingQueue - [Edge Events] Queue polling was interrupted
2026-05-11 13:05:15,939 [sql-queue-0-edge events-2-thread-1] INFO o.t.s.dao.sql.TbSqlBlockingQueue - [Edge Events] Queue polling completed
2026-05-11 13:05:15,941 [main] INFO o.s.o.j.LocalContainerEntityManagerFactoryBean - Closing JPA EntityManagerFactory for persistence unit 'default'
2026-05-11 13:05:15,946 [main] INFO com.zaxxer.hikari.HikariDataSource - HikariPool-1 - Shutdown initiated...
2026-05-11 13:05:16,002 [main] INFO com.zaxxer.hikari.HikariDataSource - HikariPool-1 - Shutdown completed.
在 Windows 环境下,正确的路径是:
cd windows\install
install_dev_db.bat
踩坑7:数据库连接拒绝
执行 install_dev_db.bat 后,出现如下错误:
org.postgresql.util.PSQLException: Connection to localhost:5432 refused.
这是因为 install_dev_db.bat 默认读取的是 conf\thingsboard.yml 中的数据库配置,而不是windows\conf\thingsboard.yml, conf\thingsboard.yml 文件中的连接信息可能与你本地环境不符(例如密码不是 postgres),需要修改。
尝试直接修改配置文件:编辑 conf\thingsboard.yml,将数据库 URL、用户名、密码改为正确的值。但这样会污染打包后的配置,且每次重新编译都会被覆盖。
最佳解决方案:使用环境变量
ThingsBoard 的配置文件中大量使用了 ${SPRING_DATASOURCE_URL:...} 这种占位符,我们可以通过设置环境变量来覆盖默认值,无需修改任何配置文件。
在 Windows 下,通过系统环境变量或命令行临时设置:
set SPRING_DATASOURCE_URL=jdbc:postgresql://localhost:5432/thingsboard
set SPRING_DATASOURCE_USERNAME=postgres
set SPRING_DATASOURCE_PASSWORD=your_password
set SPRING_EVENTS_DATASOURCE_URL=jdbc:postgresql://localhost:5432/thingsboard_events
set SPRING_EVENTS_DATASOURCE_USERNAME=postgres
set SPRING_EVENTS_DATASOURCE_PASSWORD=your_password
设置完成后,再次运行 install_dev_db.bat,初始化成功。
踩坑8:数据库不存在
即使连接成功,仍可能遇到:
FATAL: database "thingsboard" does not exist
这是因为初始化脚本不会自动创建数据库,需要手动创建。按照 3.1 节中的 SQL 语句提前创建好 thingsboard 和 thingsboard_events 即可。
四、启动服务
4.1 启动后端
方式一:使用 Maven 插件(开发调试推荐)
cd application
mvn spring-boot:run
方式二:运行打包后的 JAR
cd application/target
java -jar thingsboard-4.3.1.1-boot.jar
上面提到thingsboard.yml定义了上百个环境变量,尤其是数据库配置使用了通用的SPRING配置,这会影响其他spring程序,所以,应该直接编写一个启动脚本,在脚本中独立定义重要环境变量。
LINUX下startup.sh的全部代码为:
#!/usr/bin/env bash
# 注意:脚本文件应保存为 UTF-8 编码(无需 BOM),并在 Linux 下运行
# ========== 可配置变量 ==========
SERVICE_NAME="thingsboard-4.3.1.1-boot"
JAR_PATH="${SERVICE_NAME}.jar"
# JVM 参数(数组)
JVM_ARGS=(
'-Dfile.encoding=UTF-8'
'-Xmx256m'
'-Xms128m'
)
# ================================
# ---------- 终端设置----------
# 设置窗口标题(部分终端支持,如 xterm、gnome-terminal 等)
echo -ne "\033]0;${SERVICE_NAME}\007"
# 设置前景色(绿色)和背景色(黑色)
if command -v tput >/dev/null 2>&1; then
tput setaf 2 # 绿色前景
tput setab 0 # 黑色背景
tput clear
else
echo -ne "\033[32;40m" # 绿字黑底
clear
fi
# 调整终端窗口大小(部分终端支持,可忽略错误)
if command -v resize >/dev/null 2>&1; then
resize -s 50 200 2>/dev/null || true
fi
# ---------- 环境变量----------
export HTTP_BIND_ADDRESS="0.0.0.0"
export HTTP_BIND_PORT="8080"
# Redis
export REDIS_HOST="8.141.5.220"
export REDIS_PORT="6379"
export REDIS_DB="0"
export REDIS_PASSWORD=""
export REDIS_USERNAME=""
# Updates
export UPDATES_ENABLED="true"
# CORS
export TB_CORS_ALLOWED_ORIGIN_PATTERNS="*"
export TB_CORS_ALLOWED_METHODS="*"
export TB_CORS_ALLOWED_HEADERS="*"
export TB_CORS_MAX_AGE="1800"
export TB_CORS_ALLOW_CREDENTIALS="true"
# Spring
export SPRING_MVC_ASYNC_REQUEST_TIMEOUT="30000"
export SPRING_JPA_DIALECT="org.thingsboard.server.dao.ThingsboardPostgreSQLDialect"
export JAVAX_PERSISTENCE_QUERY_TIMEOUT="30000"
export SPRING_DRIVER_CLASS_NAME="org.postgresql.Driver"
export SPRING_DATASOURCE_URL="jdbc:postgresql://8.141.5.220:15432/thingsboard"
export SPRING_DATASOURCE_USERNAME="postgres"
export SPRING_DATASOURCE_PASSWORD="123456"
export SPRING_EVENTS_DATASOURCE_DRIVER_CLASS_NAME="org.postgresql.Driver"
export SPRING_EVENTS_DATASOURCE_URL="jdbc:postgresql://8.141.5.220:15432/thingsboard_events"
export SPRING_EVENTS_DATASOURCE_USERNAME="postgres"
export SPRING_EVENTS_DATASOURCE_PASSWORD="123456"
# Transport
export HTTP_ENABLED="true"
export HTTP_REQUEST_TIMEOUT="60000"
export HTTP_MAX_REQUEST_TIMEOUT="300000"
export HTTP_TRANSPORT_MAX_PAYLOAD_SIZE_LIMIT_CONFIGURATION="/api/v1/*/rpc/**=65536;/api/v1/**=52428800"
export MQTT_ENABLED="true"
export MQTT_BIND_ADDRESS="0.0.0.0"
export MQTT_BIND_PORT="1883"
# 关闭网关仪表盘同步
export TB_GATEWAY_DASHBOARD_SYNC_ENABLED="false"
# Device connectivity
export DEVICE_CONNECTIVITY_HTTP_ENABLED="true"
export DEVICE_CONNECTIVITY_HTTP_HOST=""
export DEVICE_CONNECTIVITY_HTTP_PORT="2080"
export DEVICE_CONNECTIVITY_HTTPS_ENABLED="false"
export DEVICE_CONNECTIVITY_HTTPS_HOST=""
export DEVICE_CONNECTIVITY_HTTPS_PORT="443"
export DEVICE_CONNECTIVITY_MQTT_ENABLED="true"
export DEVICE_CONNECTIVITY_MQTT_HOST=""
export DEVICE_CONNECTIVITY_MQTT_PORT="1883"
export DEVICE_CONNECTIVITY_MQTTS_ENABLED="false"
export DEVICE_CONNECTIVITY_MQTTS_HOST=""
export DEVICE_CONNECTIVITY_MQTTS_PORT="8883"
export DEVICE_CONNECTIVITY_MQTTS_CA_ROOT_CERT="cafile.pem"
# MQTT Client
export TB_MQTT_CLIENT_RETRANSMISSION_MAX_ATTEMPTS="3"
export TB_MQTT_CLIENT_RETRANSMISSION_INITIAL_DELAY_MILLIS="5000"
export TB_MQTT_CLIENT_RETRANSMISSION_JITTER_FACTOR="0.15"
# ---------- 检查 Java 环境 ----------
if ! command -v java &> /dev/null; then
echo -e "\033[31m错误:未找到 Java 运行环境,请先安装 JDK 或 JRE。\033[0m"
exit 1
fi
# ---------- 检查 JAR 文件 ----------
if [ ! -f "$JAR_PATH" ]; then
echo -e "\033[31m错误:找不到 $JAR_PATH 文件。\033[0m"
exit 1
fi
# ---------- 后台启动应用 ----------
LOG_FILE="${SERVICE_NAME}.log"
echo -e "\033[32m后台启动 $SERVICE_NAME 应用,日志输出到 $LOG_FILE ...\033[0m"
nohup java "${JVM_ARGS[@]}" -jar "$JAR_PATH" > "$LOG_FILE" 2>&1 &
echo $! > "${SERVICE_NAME}.pid"
echo -e "\033[32m$SERVICE_NAME 已启动,PID=$(cat ${SERVICE_NAME}.pid),日志文件: $(pwd)/${LOG_FILE},请立即使用tail -f $(pwd)/${LOG_FILE} 查看启动日志\033[0m"
启动后的效果:
[root@iZ2ze6qcuxrmhddeb4m9xuZ thingsboard]# sh startup.sh
后台启动 thingsboard-4.3.1.1-boot 应用,日志输出到 thingsboard-4.3.1.1-boot.log ...
thingsboard-4.3.1.1-boot 已启动,PID=259581,日志文件: /feng/thingsboard/thingsboard-4.3.1.1-boot.log,请立即使用tail -f /feng/thingsboard/thingsboard-4.3.1.1-boot.log 查看启动日志
[root@iZ2ze6qcuxrmhddeb4m9xuZ thingsboard]# tail -f /feng/thingsboard/thingsboard-4.3.1.1-boot.log
===========================================================
:: ThingsBoard :: (v4.3.1.1)
===========================================================
2026-05-11T15:01:44.213+08:00 INFO 259581 --- [ main] o.t.server.ThingsboardServerApplication : Starting ThingsboardServerApplication v4.3.1.1 using Java 17.0.14 with PID 259581 (/feng/thingsboard/thingsboard-4.3.1.1-boot.jar started by root in /feng/thingsboard)
2026-05-11T15:01:44.228+08:00 INFO 259581 --- [ main] o.t.server.ThingsboardServerApplication : No active profile set, falling back to 1 default profile: "default"
2026-05-11T15:01:45.552+08:00 WARN 259581 --- [ main] o.s.c.annotation.AnnotationTypeMapping : Support for convention-based annotation attribute overrides is deprecated and will be removed in Spring Framework 7.0. Please annotate the following attributes in @org.thingsboard.server.config.annotations.ApiOperation with appropriate @AliasFor declarations: [hidden, requestBody, responses]
......
检查进程:
ps -aux | grep things
检查端口:
netstat -nltp | grep 8080
WINDOWS下的启动脚本startup.ps1的全部代码为:
<#
注意文件编码要设置为 UTF-8 BOM,否则会显示中文乱码
#>
# ========== 可配置变量 ==========
$serviceName = "thingsboard-4.3.1.1-boot" # 服务名称(用于标题、提示和 JAR 文件名)
$jarPath = "target\$serviceName.jar" # JAR 文件路径
$jvmArgs = @( # JVM 参数数组(易修改)
'-Dfile.encoding=UTF-8',
'-Xmx256m',
'-Xms128m'
)
# ================================
# 设置控制台编码为 UTF-8
$OutputEncoding = [console]::InputEncoding = [console]::OutputEncoding = New-Object System.Text.UTF8Encoding
# 设置窗口标题
$Host.UI.RawUI.WindowTitle = $serviceName
# 设置缓冲区大小(宽度200,高度2000)
$Host.UI.RawUI.BufferSize = New-Object Management.Automation.Host.Size(200, 2000)
# 设置窗口大小(宽度200,高度50,可根据屏幕调整)
$Host.UI.RawUI.WindowSize = New-Object Management.Automation.Host.Size(200, 50)
# 设置颜色(黑底绿字)
$Host.UI.RawUI.ForegroundColor = "Green"
$Host.UI.RawUI.BackgroundColor = "Black"
Clear-Host
# 检查 Java 环境
java -version 2>&1 | Out-Null
if ($LASTEXITCODE -ne 0) {
Write-Host "未找到 Java 运行环境,请先安装 JDK 或 JRE。"
Write-Host "按任意键继续..." -NoNewline
$null = $Host.UI.RawUI.ReadKey("NoEcho,IncludeKeyDown")
exit 1
}
# 检查目标 JAR 文件是否存在
if (-not (Test-Path $jarPath)) {
Write-Host "错误:找不到 $jarPath 文件。"
Write-Host "按任意键继续..." -NoNewline
$null = $Host.UI.RawUI.ReadKey("NoEcho,IncludeKeyDown")
exit 1
}
# ---------- 添加数据库连接环境变量 ----------
$env:SPRING_DATASOURCE_URL = "jdbc:postgresql://localhost:5432/thingsboard"
$env:SPRING_DATASOURCE_USERNAME = "postgres"
$env:SPRING_DATASOURCE_PASSWORD = "123456"
$env:SPRING_EVENTS_DATASOURCE_URL = "jdbc:postgresql://localhost:5432/thingsboard_events"
$env:SPRING_EVENTS_DATASOURCE_USERNAME = "postgres"
$env:SPRING_EVENTS_DATASOURCE_PASSWORD = "123456"
$env:REDIS_PASSWORD = "123456"
$env:REDIS_HOST = "localhost"
$env:REDIS_PORT = "6379"
# -----------------------------------------
# 启动应用(使用展开的 JVM 参数)
Write-Host "启动 $serviceName 应用..."
java $jvmArgs -jar $jarPath
# 暂停
Write-Host "按任意键继续..." -NoNewline
$null = $Host.UI.RawUI.ReadKey("NoEcho,IncludeKeyDown")
踩坑9:启动时仍然连接数据库失败
执行 mvn spring-boot:run 时,发现它读取的是 application\src\main\resources\thingsboard.yml,而不是 target 目录下的配置文件。而源码中的 thingsboard.yml 同样使用了环境变量占位符,但此时我们之前设置的环境变量可能已经失效(例如在新的命令行窗口中)。
解决方法:在启动命令前重新设置环境变量,或者将环境变量持久化到系统变量中。也可以直接在 IDEA 的运行配置中填入环境变量。
为方便起见,我们编写一个启动脚本 start-thingsboard.bat:
@echo off
set SPRING_DATASOURCE_URL=jdbc:postgresql://localhost:5432/thingsboard
set SPRING_DATASOURCE_USERNAME=postgres
set SPRING_DATASOURCE_PASSWORD=your_password
set SPRING_EVENTS_DATASOURCE_URL=jdbc:postgresql://localhost:5432/thingsboard_events
set SPRING_EVENTS_DATASOURCE_USERNAME=postgres
set SPRING_EVENTS_DATASOURCE_PASSWORD=your_password
cd application
mvn spring-boot:run

每次启动时执行该脚本即可。
4.2 启动前端(可选)
如果你想单独调试前端,可以运行:
cd ui-ngx
yarn start
前端开发服务器默认运行在 http://localhost:4200,会自动代理 API 请求到 http://localhost:8080。
五、验证安装
后端启动成功后,访问 http://localhost:8080,使用默认账号登录:
- 系统管理员:
sysadmin@thingsboard.org/sysadmin - 租户管理员:
tenant@thingsboard.org/tenant
如果能看到仪表板页面,恭喜你,ThingsBoard 开发环境已经搭建完成!

六、总结与建议
踩坑汇总
| 问题 | 原因 | 解决方案 |
|---|---|---|
| gradle-maven-plugin 或 langchain4j-bom 找不到 | 依赖在 ThingsBoard 私有仓库,公共镜像没有 | 在 settings.xml 中添加 thingsboard-repo 镜像 |
| gradle-7.3.3-bin.zip 下载卡死 | 网络访问国外 Gradle 分发服务器慢 | 手动下载并放入 Gradle 缓存目录 |
| winsw-2.0.1-bin.exe 下载失败 | 依赖不在公共仓库 | 手动下载并用 mvn install:install-file 安装 |
| frontend-maven-plugin 自动添加代理参数 | Maven Settings 中存在激活的代理 | 禁用或删除 settings.xml 中的代理配置 |
| pkg 打包时下载 Node 二进制失败 | 网络问题,GitHub 访问慢 | 设置 PKG_CACHE_PATH,手动下载并重命名文件放入缓存 |
| 数据库初始化连接拒绝 | 配置文件中的数据库连接信息不正确 | 使用环境变量覆盖配置 |
| 数据库不存在 | 初始化脚本不会自动创建数据库 | 手动创建 thingsboard 和 thingsboard_events |
| mvn spring-boot:run 连接失败 | 未传递环境变量 | 在启动命令前设置环境变量 |
开发环境最佳实践
-
优先配置 ThingsBoard 仓库镜像:编译前就在
settings.xml中加上 ThingsBoard 官方镜像,避免后续大量依赖缺失。 -
手动处理外部二进制依赖:对于
winsw、pkg-fetch这类网络依赖,提前下载并放置到正确位置,可以节省大量时间。 -
使用环境变量而非修改配置文件:ThingsBoard 的设计非常灵活,几乎所有配置都支持环境变量覆盖。这样既能保持源码干净,又能适应不同环境。
-
为 Windows 环境准备脚本:将常用的环境变量设置、编译、启动命令封装成
.bat脚本,避免重复输入。 -
善用 Maven 排除模块:如果某些模块(如
edqs、msa/web-ui)编译特别困难,可以用-pl '!edqs' -pl '!msa/web-ui'跳过,不影响核心功能。 -
保持 JDK 和 Node 版本一致:ThingsBoard 4.3.x 要求 JDK 17 和 Node 18+,版本不匹配会导致各种奇怪错误。
-
遇到问题时查看官方社区:ThingsBoard 的 GitHub Issues 和 Stack Overflow 上有大量现成答案,善用搜索。
下一步计划
搭建好开发环境后,我们将基于 ThingsBoard 进行二次开发,实现:
- 物联中台(设备接入、设备管理)
- 数据中台(多源数据汇聚、统一 API)
- 维修管理、资产管理、医废管理等业务模块
后续我会继续分享定制开发过程中的经验,欢迎关注。
最后:如果你在搭建过程中遇到其他问题,欢迎在评论区留言交流。如果觉得本文有帮助,别忘了点赞、收藏、分享!
更多推荐



所有评论(0)