1. 为什么需要搭建 datart 二开环境
datart 这个项目,做数据可视化的同学应该都听过。它算是我见过国内开源BI里代码结构比较清爽的一个,后端基于 Spring Boot,前端基于 React + Vite,整套链路不复杂,拿来改一改做企业内部的看板平台,比从零写省太多事。但正因为是开源项目,文档里关于“怎么把环境跑起来做二次开发”的部分一直写得比较简单,很多人在环境这步就卡住了。
我自己在搭这套二开环境的时候,前后折腾了大半天,踩了不少坑。有的是因为版本选的太新,有的是因为配置项没理解透,还有的是前端代理和后端跨域之间互相牵扯。后来理清楚之后发现,其实整个流程可以拆成几条清晰的线:后端起来、前端起来、数据库通、联调通。今天就把这套完整的过程整理出来,包括我选型时的考量和后来排过的坑,给后面做二开的朋友一条好走的捷径。
这套内容适合谁?适合已经会用 Git、懂一点 Java 和 React 基础、准备在 datart 上做定制功能的研发同学。如果你是纯部署使用,不打算改代码,那直接找官方镜像跑即可,不需要看这篇。
2. 二开前的准备工作
2.1 版本选型是第一步,也是大部分人翻车的地方
datart 的仓库里,master 分支在不断迭代,但开源项目的通病是:主干分支不一定比稳定标签好用。我第一次直接拉了 master,结果前端依赖安装时有一堆版本兼容报错,折腾了半小时才意识到问题不在环境,而在代码版本本身。
我的建议是不要追求最新。去 GitHub 仓库的 Tags 页面找一个 release 版本,像我这边用的就是 1.0.0-rc.2 这个版本。这个版本整体比较稳,前后端配套完善,社区讨论也多,遇到问题搜得到答案。如果你所在团队有特殊需求必须用某个提交,那至少也要确认前端 package.json 里的依赖是可以正常安装的再动手。
这里顺便说一个选版本的小技巧:看 release 页面的发布时间和配套说明。如果 release 说明里明确写了“前端构建通过”“后端启动验证通过”之类的字样,说明作者至少自己跑通了一遍,这种版本踩坑概率会小很多。
2.2 本地环境需要准备哪些东西
datart 前后端分离,整套环境的依赖项如下:
| 组件 | 版本建议 | 用途说明 |
|---|---|---|
| JDK | 1.8 或 8u 以上 | datart 后端基于 Spring Boot 2.x,JDK 8 完全够用 |
| Maven | 3.6 以上 | 后端依赖管理和构建 |
| Node.js | 14.x 或 16.x | 前端构建环境,太新的版本反而容易出问题 |
| npm / yarn | npm 6+ 或 yarn 1.x | 前端包管理工具 |
| MySQL | 5.7 或 8.0 | 主数据库,datart 默认使用 MySQL |
| Redis | 5.0 以上 | 缓存,部分功能强依赖 Redis |
| IDE | IDEA 或 VS Code | 后端 IDEA,前端 VS Code 即可 |
有两点要特别提醒。第一,Node.js 版本不要一上来就装 18 或 20,虽然新版功能多,但 datart 的 webapp 里不少旧依赖在新版本下会有兼容问题,我实测 16.x 是最稳妥的。第二,如果把 MySQL 和 Redis 都放在 Docker 里跑,注意 Docker 的容器时间要和宿主机保持一致,否则后端启动时会因为时间戳校验问题报错(这个后面在排查章节再展开)。
2.3 拉取代码与目录结构速览
确定好版本后,直接拉代码:
git clone https://github.com/running-elephant/datart.git cd datart git checkout 1.0.0-rc.2拉下来之后先花五分钟把目录结构过一遍,不要急着启动。datart 的代码组织比较清晰:
bin目录:启动脚本、数据库初始化脚本等config目录:配置文件模板,里面包含application.yml的样例core目录:后端核心逻辑server目录:启动入口和控制器层webapp目录:前端工程pom.xml:后端 Maven 聚合配置
我第一次看这个目录的时候有点懵,因为很多开源项目会单独建一个backend目录放后端代码,datart 直接把它落在了根目录,这个刚开始会不习惯。记住一条核心线:前端在webapp,后端就是根目录这一堆 Maven 模块,两者通过 HTTP API 通信,理清这条线后面联调就顺了。
3. 后端环境搭建与启动
3.1 初始化数据库是第一步,顺序不能反
很多人习惯先把后端代码跑起来再说数据库,这顺序在 datart 这里是行不通的。datart 启动时一定会连数据库做表结构校验,如果没有库和表,启动直接会失败。
我用的方式是先用 MySQL 创建一个独立库,然后导入官方提供的初始化脚本。脚本位置在bin目录下,文件名一般是datart.sql或类似的名字,具体以实际拉下来的版本为准:
CREATE DATABASE IF NOT EXISTS datart DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; USE datart; SOURCE /你的本地路径/datart/bin/datart.sql;注意字符集要使用utf8mb4,不要用utf8。datart 里有存 JSON 字段,utf8mb4对表情符号和特殊字符支持更好,直接用utf8后续导入数据或者展示图表时会出现问号乱码。
导入完成后,可以验证一下核心表是否存在:
USE datart; SHOW TABLES;正常的表数量会有几十张,包括user、organization、source、view、chart、dashboard等核心表。如果你看到只有寥寥几张表,大概率是脚本没执行完整,重新执行一次。
3.2 修改配置文件,核心就这几处
数据库准备好之后,打开config目录下的application.yml(有些版本叫application-demo.yml,作用一样),需要关注和修改的地方其实不多:
spring: datasource: url: jdbc:mysql://localhost:3306/datart?useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Shanghai&useSSL=false&allowPublicKeyRetrieval=true username: root password: 你的数据库密码 redis: host: localhost port: 6379 password: 如果你的 Redis 设置了密码就填,否则留空 server: port: 8080有几个配置细节值得展开说一下。serverTimezone=Asia/Shanghai一定要加,否则后端连接 MySQL 时会报时间区错误。allowPublicKeyRetrieval=true是 MySQL 8.0 连接时需要的参数,如果你用 5.7 不加也行,但加了也没坏处,索性一起写上。
另外 datart 还有一个datart.security.token相关的配置,控制 JWT 的 token 密钥和过期时间。如果是团队协作开发,建议每个人都生成一个自己的密钥,否则别人用你的接口文档调试时会因为 token 不匹配而失败。
3.3 Maven 构建与启动
配置文件改好后,回到项目根目录:
mvn clean install -DskipTests第一次构建会比较慢,Maven 要把所有依赖下载到本地仓库。这里有个网络上的建议:如果 Maven 下载依赖卡住,优先检查是不是镜像源问题,换成阿里云的 Maven 镜像会快很多。配置方式是在settings.xml中增加镜像地址,这个属于 Maven 基础操作,不再赘述。
构建完成后,启动入口有两个方式。一种是在 IDE 中运行datart-server模块下的启动类,类名一般是ServerApplication或类似名称;另一种是在命令行中执行:
java -jar server/target/datart-server.jar看到日志中打印出Started ServerApplication in xx seconds,并且没有异常堆栈,说明后端启动成功了。此时在浏览器访问http://localhost:8080/api/v1/health,如果返回一串 JSON 或正常的响应内容,说明后端基础健康检查通过。
后端启动这个阶段有几个高频报错,先写在前面给各位提个醒:
- 如果报数据库连接失败,优先检查数据库名、用户名和密码是否匹配;
- 如果报
user表不存在,说明初始化脚本没执行成功,重新执行一次; - 如果报端口占用,直接改
server.port或者把占用进程关掉。
4. 前端环境搭建与启动
4.1 前端依赖安装,最容易出问题的环节
后端启动只是个开始,前端环境搭建是二开过程中的重头戏。进入webapp目录:
cd webapp npm install这里我第一次安装时踩了个大坑。因为网络原因,npm install跑到一半失败,报各种依赖版本冲突。后来我换成了 yarn 才顺利安装完成。这不是说 yarn 比 npm 好多少,而是 yarn 的缓存机制和依赖解析策略在这种老项目里表现更稳定。如果你也遇到了 npm 安装失败的问题,不妨直接试 yarn:
yarn install依赖安装成功后,启动开发服务器:
npm run start或:
yarn start启动成功后,终端会打印出开发服务器的访问地址。datart 前端默认端口不是 3000,也不是 8080,而是 7000。浏览器访问http://localhost:7000,能看到 datart 的登录页面,说明前端起来了。
4.2 前端代理配置,解决跨域问题的关键
这里有一个非常关键的配置,你要能打开登录页不代表能正常登录。因为前端跑在 7000 端口,后端跑在 8080 端口,如果前端直接向后端发请求,浏览器会因跨域拦截导致登录失败。
datart 前端的构建工具是 Vite,代理配置在vite.config.ts文件中。开发环境下,Vite 会在本地启动一个代理服务,将请求转发到后端。默认配置长这样:
server: { host: '0.0.0.0', port: 7000, proxy: { '/api': { target: 'http://localhost:8080', changeOrigin: true } } }也就是说,当你前端访问/api/v1/...时,Vite 会把请求转发到http://localhost:8080,从而避免跨域问题。大多数情况下这个配置不用改,后端 IP 变了才需要跟着变。
如果是团队协作开发,你在 A 电脑改前端,后端在 B 电脑,那么目标地址就要改成 B 电脑的 IP。在这种模式下,changeOrigin这个参数必须保持为true,否则请求头里的 Host 信息会不对,后端可能无法正确处理。
4.3 首次登录与默认账号
前后端都启动后,在登录页输入默认账号密码。datart 默认的管理员账号一般是admin,初始密码也是admin(具体以官方文档为准,不同版本有差异)。登录成功后,你会进入 datart 的主界面,可以看到数据源管理、视图构建和仪表板等功能模块。
到这一步,一套最小的二开环境就算跑通了。你可以去数据源配置页面,连一个自己的业务库,然后试着创建视图、拖拽出一个图表。这个闭环跑通之后,你后续改代码、加功能,就有一个可用的验证环境了。
5. Redi s与缓存问题的前置处理
5.1 为什么 datart 离不开 Redis
很多人在搭环境时会忽略 Redis,等到运行某些功能报错了才回去补。datart 在多个核心场景依赖 Redis 做缓存:
- 数据源的元数据缓存;
- 图表查询结果缓存;
- 部分权限和会话信息管理。
如果你本地没有装 Redis,后端虽然能启动,但到了实际执行查询、刷新视图这类操作时,会遇到各种缓存异常,报错信息五花八门,最常见的是Caused by: redis.clients.jedis.exceptions.JedisConnectionException。
解决方法很简单,本地装一个 Redis,或者用 Docker 快速起一个:
docker run -d --name datart-redis -p 6379:6379 redis:6如果 Redis 设置了密码,要在application.yml中同步修改,不要只改一处。我见过有同事改了数据库密码忘了改 Redis 密码,结果缓存服务一直连不上,排错了大半天。
5.2 Redis 连接不上怎么办
Redis 连接不上,常见的排查步骤:
- 先确认 Redis 服务是否启动:
redis-cli ping,返回PONG说明正常; - 确认端口是否被占用或监听地址是否正确。Redis 默认只监听本机
127.0.0.1,如果你把 Redis 放到 Docker 里,宿主机访问要用-p 6379:6379做映射; - 确认
application.yml中的spring.redis.host和port是否指向正确地址。
如果你用的是 Docker 容器作为数据库和缓存,还要注意一个问题:容器内的服务之间存在网络通信,需要用容器名或自定义网络来解析地址,不要直接写localhost。
6. 前后端联调中的关键问题实录
6.1 Token 机制与登录态保持
后端启动后,第一次登录时前端会调用登录接口,后端会返回一个 token,前端将它保存在本地(通常是 localStorage)。后续的所有请求都会在请求头中带上这个 token,后端拦截器校验通过后才会放行。
二开过程中,如果你经常使用 Swagger 或 Postman 调试接口,记得先通过登录接口拿到 token,然后在调试工具中配置请求头:
Authorization: Bearer 你的token不要手动把 token 拼到 URL 参数里,datart 后端只从请求头读取,拼在 URL 上不仅没用,还可能被日志采集下来,有一定安全风险。
6.2 前端页面注册流程的定制
datart 默认的注册逻辑是允许用户自助注册账号。在企业内部二开时,这个功能通常要关掉,改为管理员统一创建账号。相关开关在后端配置项里:
datart: user: register: false将注册开关设为false后,前端登录页会隐藏“注册”入口,只能通过管理员在后台创建用户。我实际改过这个配置,确实生效。如果你还想做更细的权限控制,比如指定某些组织下的用户才能注册,那就需要改后端逻辑了,这在二开中属于比较典型的定制场景。
6.3 联调时前端改了代码不生效
这个问题很常见,不一定是你代码写错了。Vite 开发服务器会热更新,但某些深层依赖修改后不会触发自动重载。我常用的办法是,改完代码手动刷新页面还不生效时,直接重启开发服务器:
# 在 webapp 目录下,Ctrl + C 退出 yarn start另外一个容易忽略的点是:datart 前端部分代码是动态加载的,浏览器缓存可能导致你改了代码看不到效果。打开开发者工具,Network 面板里勾选 Disable cache,或者直接强制刷新(Ctrl+Shift+R)。
6.4 后端热部署配置
前端有 Vite 的热更新,后端其实也可以配置热部署。Spring Boot 官方提供了spring-boot-devtools,在pom.xml中引入后,修改 Java 代码时,IDEA 中按 Ctrl + F9 可以快速重新编译,省去重启整个应用的等待时间。
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-devtools</artifactId> <optional>true</optional> </dependency>实际体验来看,devtools 对中小项目的编译速度提升很明显。但它有个缺点:会监听所有 classpath 文件变化,偶尔会触发无意义的重启。如果你发现 IDE 卡顿或者频繁重启,可以在配置里排除掉不需要监听的目录:
spring: devtools: restart: exclude: static/**,public/**7. 常见问题与排查技巧实录
7.1 数据库连接失败与编码问题
这个错误应该是出现频率最高的。排查步骤非常简单:
- 确认 MySQL 服务已启动;
- 在命令行用账号密码连一下库:
mysql -uroot -p,看能不能进去; - 确认 datart 库名与
application.yml中填写的是否一致; - 确认字符集是否为
utf8mb4,如果不是,重新建库或修改字符集。
另外,MySQL 8.0 默认认证插件是caching_sha2_password,有些旧版本的 JDBC 驱动不兼容,报错信息会出现Public Key Retrieval is not allowed。解决方案就是在 URL 上加上allowPublicKeyRetrieval=true和useSSL=false,我在 3.2 节里已经提过,这里再强调一次,因为这个参数太容易忽略了。
7.2 前端编译报错与依赖冲突
前端编译报错的表现形式很多,常见的有:
ERESOLVE unable to resolve dependency tree:依赖树解析失败。这种情况最常见的解法是改 npm 配置或者直接用 yarn;TypeError: Cannot read properties of undefined:多半是版本不兼容导致的 API 变化,检查关键依赖的版本号;Node.js version xxx is not supported:Node 版本太新或太旧,切换到 14.x 或 16.x。
如果你在安装依赖时遇到了 prisma、sharp 这类包含二进制文件的原生模块,还需要注意本机是否安装了 Python 环境和 C++ 编译工具链。Windows 用户在安装这类依赖时经常会二次报错,建议仔细看 npm 或者 yarn 的报错提示,缺什么补什么。
7.3 IDEA 启动后端时报错合集
IDEA 启动后端,最常见的错误有两种:
Error creating bean with name 'xxx':这个一般是 Spring 容器初始化某个 Bean 失败。点开完整堆栈,看最底下Caused by那一行,通常是数据库连不上或者配置项缺失;Port 8080 was already in use:端口被占用。终端执行lsof -i:8080(Mac/Linux)或netstat -ano | findstr 8080(Windows),找到占用进程,关掉或者改后端端口。
在这里我有一个习惯,每次新环境启动后端时,都会用一个干净的日志输出方式:
mvn spring-boot:run -pl server -am -Dspring-boot.run.profiles=dev这样可以在启动时指定 profile,日志也会按模块输出,排查问题比直接跑 jar 包清晰很多。
7.4 数据导入导出异常
datart 支持数据源的导入导出功能,有一个很隐蔽的坑:如果本地的时区与数据库的时区不一致,导入数据后时间字段会出现偏移。解决方案是在数据库连接串上明确指定serverTimezone=Asia/Shanghai,并且 MySQL 容器内部也要设置正确的时区。
如果你的 MySQL 跑在 Docker 里,可以在启动容器时加上环境变量:
docker run -d --name mysql-datart \ -e MYSQL_ROOT_PASSWORD=你的密码 \ -e TZ=Asia/Shanghai \ -p 3306:3306 \ mysql:5.7这个参数不加,哪怕后端配置了serverTimezone,容器默认的 UTC 时区也会给数据写入带来各种奇怪的时间问题。
7.5 常见问题速查表
| 现象 | 可能原因 | 解决方案 |
|---|---|---|
| 后端启动报 Unable to connect to MySQL | 数据库未启动或账号密码错误 | 核对连接串与账号权限 |
| 前端登录一直转圈 | 后端未启动,或代理配置错误 | 检查后端进程与 vite.config.ts |
| 图标加载不出来 | 前端构建不完整 | 重新执行 yarn install && yarn start |
| 图表查询超时 | Redis 未配置或查询过慢 | 启动 Redis,检查查询 SQL 性能 |
| 注册按钮消失 | datart.user.register设为 false | 按需调整配置 |
| 时间字段偏移 | MySQL 容器时区不为亚洲时区 | 增加 TZ=Asia/Shanghai 环境变量 |
| 依赖安装失败 | Node 版本过新或过旧 | 切换 Node 14/16 |
8. 二开过程中的一些实操心得
8.1 先跑通再改代码
二开最忌讳上来就想改代码。先把原始项目完整跑通一次,能够正常登录、建数据源、画图表,再开始动刀。这样你能充分理解数据从哪来、接口怎么流转、界面怎么渲染,后面改起来才不会抓瞎。
我见过不少刚开始做二开的人,在环境都还没完全跑通的情况下就直接修改权限逻辑,结果改出来的功能自己都不清楚为什么生效或不生效,后期排查非常痛苦。这不是技术能力的问题,而是对系统全局认知不够。
8.2 从最小闭环开始做定制
做完环境验证后,建议的第一个二开需求选一个小的、端到端的功能点。比如在仪表板增加一个自定义背景色设置,或者修改用户列表的分页大小。这个闭环涉及前端菜单入口、后端 API、数据库存储,做完后你就对 datart 的整体开发链路有了本能的熟悉感,远比读源码来得快。
8.3 保留一份干净的基线环境
二开做久了,你会发现改来改去,环境越跑越脏。依赖冲突、配置混乱、数据被测试数据污染,各种问题接踵而至。我的做法是维护一份干净的基线:单独用一个目录存放未改动的原始代码,本地数据库保持一个干净的备份脚本,每次大改前用这份基线重新起一套环境,确保问题的根源在自己的代码里,而不是环境里。
9. 二开场景扩展思路
一套环境跑通之后,可以做的事情就很灵活了。datart 本身的能力边界在于它是一套通用的可视化框架,具体到某个行业的术语、交互方式、数据模型,都需要二开来补齐。
比较常见的二开方向包括:
- 登录对接企业内部统一认证,比如 OAuth2 或 CAS;
- 数据源类型扩展,适配公司内部自研的存储引擎;
- 图表类型的定制,在原有基础上增加特定行业的图表;
- 权限模型调整,把 datart 的组织权限与业务系统的角色体系打通;
- 前端主题改造,让 UI 风格与公司产品保持一致。
这里每个方向都有不少文章可以做,但无论哪个方向,前提都是你能独立把环境跑起来、看明白数据流。环境搭建这块敲门砖过了,后面的二开就回到了日常开发的节奏,难度反而没那么大了。
最后再分享一个小经验:在配置环境的过程中,每一步操作尽量记录到自己的笔记里,尤其是命令和配置项。因为二开不是一次性的,团队里新同学入职、换电脑、代码回滚,都需要重新搭环境。你手里的这份记录,就是团队里最宝贵的实操文档。我自己的这套环境搭建笔记,前前后后帮团队四个人省掉了重复踩坑的时间,这也是我今天写这篇文章的初衷。