Merge pull request '增加了数据库初始化脚本处理' (#4) from develop-framework into main-framework
Reviewed-on: #4
This commit is contained in:
commit
d790992125
14
.vscode/launch.json
vendored
Normal file
14
.vscode/launch.json
vendored
Normal file
@ -0,0 +1,14 @@
|
||||
{
|
||||
"configurations": [
|
||||
{
|
||||
"type": "java",
|
||||
"name": "Spring Boot-PlatformApplication<platform>",
|
||||
"request": "launch",
|
||||
"cwd": "${workspaceFolder}",
|
||||
"mainClass": "com.yfd.platform.PlatformApplication",
|
||||
"projectName": "platform",
|
||||
"args": "",
|
||||
"envFile": "${workspaceFolder}/.env"
|
||||
}
|
||||
]
|
||||
}
|
||||
8
framework/db-init/README.md
Normal file
8
framework/db-init/README.md
Normal file
@ -0,0 +1,8 @@
|
||||
# db-init 目录说明
|
||||
|
||||
- `sql/base-schema.sql`:数据库结构(表、索引、约束),由 mysqldump 导出或手写维护。
|
||||
- `sql/base-data.sql`:初始化数据(字典、角色、菜单、管理员等),由 mysqldump 导出或手写维护。
|
||||
- `scripts/export.ps1`:Windows 导出脚本;将当前库结构与指定白名单数据导出到 sql 目录。
|
||||
- `scripts/import.ps1`:Windows 导入脚本;将 sql 中的结构与数据导入到目标库。
|
||||
|
||||
请参考 `../docs/数据库初始方案.md` 获取完整流程与约束。
|
||||
100
framework/db-init/scripts/export.ps1
Normal file
100
framework/db-init/scripts/export.ps1
Normal file
@ -0,0 +1,100 @@
|
||||
param(
|
||||
[string]$DB_HOST = '43.138.168.68',
|
||||
[int]$DB_PORT = 3306,
|
||||
[string]$DB_NAME = 'frameworkdb2023',
|
||||
[string]$DB_USER = 'root',
|
||||
[string]$DB_PASSWORD = 'ylfw20230626@'
|
||||
)
|
||||
|
||||
# 确保输出目录存在
|
||||
$outputDir = Join-Path $PSScriptRoot '..\sql'
|
||||
if (!(Test-Path $outputDir)) {
|
||||
New-Item -ItemType Directory -Path $outputDir | Out-Null
|
||||
}
|
||||
|
||||
# 构建输出文件路径
|
||||
$schemaFile = Join-Path $outputDir "base-schema.sql"
|
||||
$dataFile = Join-Path $outputDir "base-data.sql"
|
||||
|
||||
# 构建 mysqldump 命令参数
|
||||
$commonArgs = @(
|
||||
"--host=$hostName",
|
||||
"--port=$port",
|
||||
"--user=$user",
|
||||
"--routines",
|
||||
"--triggers",
|
||||
"--single-transaction",
|
||||
"--set-charset",
|
||||
"--default-character-set=utf8mb4"
|
||||
)
|
||||
|
||||
if ($password) {
|
||||
$commonArgs += "--password=$password"
|
||||
}
|
||||
|
||||
Write-Host "开始导出数据库结构和数据..."
|
||||
Write-Host "数据库: $database"
|
||||
Write-Host "主机: $hostName:$port"
|
||||
Write-Host "用户: $user"
|
||||
Write-Host "输出目录: $outputDir"
|
||||
Write-Host ""
|
||||
|
||||
# 导出数据库结构(仅结构,不包含数据)
|
||||
Write-Host "正在导出数据库结构到: $schemaFile"
|
||||
try {
|
||||
$schemaArgs = $commonArgs + @(
|
||||
"--no-data",
|
||||
"--result-file=$schemaFile",
|
||||
$database
|
||||
)
|
||||
|
||||
& mysqldump @schemaArgs
|
||||
|
||||
if ($LASTEXITCODE -eq 0) {
|
||||
Write-Host "✓ 数据库结构导出成功" -ForegroundColor Green
|
||||
} else {
|
||||
throw "mysqldump 返回错误代码: $LASTEXITCODE"
|
||||
}
|
||||
} catch {
|
||||
Write-Error "导出数据库结构失败: $_"
|
||||
exit 1
|
||||
}
|
||||
|
||||
# 导出数据(仅数据,不包含结构)
|
||||
Write-Host ""
|
||||
Write-Host "正在导出数据到: $dataFile"
|
||||
try {
|
||||
$dataArgs = $commonArgs + @(
|
||||
"--no-create-info",
|
||||
"--skip-triggers",
|
||||
"--result-file=$dataFile",
|
||||
$database
|
||||
)
|
||||
|
||||
& mysqldump @dataArgs
|
||||
|
||||
if ($LASTEXITCODE -eq 0) {
|
||||
Write-Host "✓ 数据导出成功" -ForegroundColor Green
|
||||
} else {
|
||||
throw "mysqldump 返回错误代码: $LASTEXITCODE"
|
||||
}
|
||||
} catch {
|
||||
Write-Error "导出数据失败: $_"
|
||||
exit 1
|
||||
}
|
||||
|
||||
Write-Host ""
|
||||
Write-Host "数据库导出完成!" -ForegroundColor Green
|
||||
Write-Host "结构文件: $schemaFile"
|
||||
Write-Host "数据文件: $dataFile"
|
||||
|
||||
# 显示文件大小
|
||||
if (Test-Path $schemaFile) {
|
||||
$schemaSize = (Get-Item $schemaFile).Length
|
||||
Write-Host "结构文件大小: $([math]::Round($schemaSize/1KB, 2)) KB"
|
||||
}
|
||||
|
||||
if (Test-Path $dataFile) {
|
||||
$dataSize = (Get-Item $dataFile).Length
|
||||
Write-Host "数据文件大小: $([math]::Round($dataSize/1KB, 2)) KB"
|
||||
}
|
||||
46
framework/db-init/scripts/import.ps1
Normal file
46
framework/db-init/scripts/import.ps1
Normal file
@ -0,0 +1,46 @@
|
||||
param(
|
||||
[string]$DB_HOST = '43.138.168.68',
|
||||
[int]$DB_PORT = 3306,
|
||||
[string]$DB_NAME = 'frameworkdb2025',
|
||||
[string]$DB_USER = 'root',
|
||||
[string]$DB_PASSWORD = 'ylfw20230626@'
|
||||
)
|
||||
|
||||
$ErrorActionPreference = 'Stop'
|
||||
$env:MYSQL_PWD = $DB_PASSWORD
|
||||
|
||||
$schemaPath = Join-Path $PSScriptRoot '..\sql\base-schema.sql'
|
||||
$dataPath = Join-Path $PSScriptRoot '..\sql\base-data.sql'
|
||||
|
||||
function Invoke-MySqlFile([string]$filePath) {
|
||||
Write-Host ("Processing SQL file: {0}" -f $filePath)
|
||||
$sql = Get-Content -Raw $filePath
|
||||
# Strip UTF-8 BOM if present
|
||||
$bom = [char]0xFEFF
|
||||
if ($sql.StartsWith($bom)) { $sql = $sql.Substring(1) }
|
||||
# Sanitize dump headers and environment-specific statements
|
||||
$lines = $sql -split "`r?`n"
|
||||
$cleanLines = $lines | Where-Object {
|
||||
$t = $_.Trim()
|
||||
if ($t -eq '') { return $false }
|
||||
if ($t -match '^(--|/\*|\*/|/\*!|[-]+$)') { return $false }
|
||||
if ($t -match '^USE\s+') { return $false }
|
||||
if ($t -match '^CREATE\s+DATABASE') { return $false }
|
||||
return $true
|
||||
}
|
||||
$cleanSql = ($cleanLines -join "`n")
|
||||
if ([string]::IsNullOrWhiteSpace($cleanSql)) {
|
||||
Write-Warning ("Sanitized script is empty, skipping: {0}" -f $filePath)
|
||||
return
|
||||
}
|
||||
Write-Host ("Importing via mysql from: {0}" -f $filePath)
|
||||
$cleanSql | & mysql -h $DB_HOST -P $DB_PORT -u $DB_USER $DB_NAME
|
||||
if ($LASTEXITCODE -ne 0) {
|
||||
throw ("Import failed for {0} with exit code {1}" -f $filePath, $LASTEXITCODE)
|
||||
}
|
||||
}
|
||||
|
||||
Invoke-MySqlFile $schemaPath
|
||||
Invoke-MySqlFile $dataPath
|
||||
|
||||
Write-Host 'Import completed'
|
||||
@ -46,26 +46,6 @@ git push -u origin develop-framework
|
||||
- 检查 CI 构建通过、代码评审通过后合并。
|
||||
- 合并策略建议:`Squash` 或 `Rebase and merge` 保持主分支提交整洁。
|
||||
|
||||
- 方式二:命令行快速合并(仅在无保护、需要紧急修复时使用)
|
||||
```
|
||||
# 确保主分支最新
|
||||
git checkout main-framework
|
||||
git pull --ff-only
|
||||
|
||||
# 将主分支变更应用到开发分支,减少合并冲突
|
||||
git checkout develop-framework
|
||||
git rebase main-framework
|
||||
# 解决冲突后:
|
||||
# git add <files>
|
||||
# git rebase --continue
|
||||
|
||||
# 回到主分支并合并(优先快进)
|
||||
git checkout main-framework
|
||||
git merge --ff-only develop-framework || git merge --no-ff develop-framework
|
||||
|
||||
# 推送主分支
|
||||
git push origin main-framework
|
||||
```
|
||||
|
||||
## 版本与标签(发布规范)
|
||||
- 采用语义化版本:`vMAJOR.MINOR.PATCH`(示例:`v1.0.0`)。
|
||||
134
framework/docs/数据库初始方案.md
Normal file
134
framework/docs/数据库初始方案.md
Normal file
@ -0,0 +1,134 @@
|
||||
# 数据库初始方案(framework)
|
||||
|
||||
## 目标
|
||||
- 在 `framework` 目录下建立 `db-init` 初始化目录,保存基础结构与基础数据。
|
||||
- 支持从 MySQL 导出一份“初始化用”的基线数据,并在应用启动时自动检测是否已初始化;若未初始化,自动导入。
|
||||
- 过程可重复、可审计、可在 `dev` 与 `server` 环境下安全运行。
|
||||
|
||||
## 目录结构规划
|
||||
- `framework/db-init/`
|
||||
- `sql/`
|
||||
- `base-schema.sql`:基础库结构(表、索引、约束);可由 `mysqldump --no-data` 导出。
|
||||
- `base-data.sql`:初始化数据(字典、默认角色、管理员等);可由 `mysqldump --no-create-info` 导出或手写。
|
||||
- `scripts/`
|
||||
- `export.ps1`:Windows 导出脚本(PowerShell)。
|
||||
- `import.ps1`:Windows 导入脚本(PowerShell)。
|
||||
- `export.sh`:Linux/Mac 导出脚本(可选)。
|
||||
- `import.sh`:Linux/Mac 导入脚本(可选)。
|
||||
- `README.md`:说明如何导出/导入、注意事项与环境变量。
|
||||
|
||||
## MySQL 导出策略
|
||||
- 推荐使用 `mysqldump` 分离结构与数据,以便初始化时灵活控制:
|
||||
- 结构:`mysqldump -h$DB_HOST -P$DB_PORT -u$DB_USER -p$DB_PASSWORD --no-data --databases $DB_NAME > sql/base-schema.sql`
|
||||
- 数据:`mysqldump -h$DB_HOST -P$DB_PORT -u$DB_USER -p$DB_PASSWORD --no-create-info --databases $DB_NAME --tables <白名单表> > sql/base-data.sql`
|
||||
- 数据白名单建议包含:
|
||||
- 字典/配置表(如 `sys_dict`, `sys_config`)
|
||||
- 权限/角色/菜单(如 `sys_user`(仅管理员)、`sys_role`, `sys_menu`, `sys_user_role`, `sys_role_menu`)
|
||||
- 地区或静态映射表(如有)
|
||||
- 机密信息与动态数据不导出:
|
||||
- 排除审计日志、任务运行记录、业务动态表等。
|
||||
|
||||
## 导入策略
|
||||
- 应用启动时进行“初始化检测”:
|
||||
- 建议引入标记表:`app_init`(单行),字段 `initialized boolean`, `version varchar`,或在 `sys_config` 中维护 `init_done` 键。
|
||||
- 检测逻辑:
|
||||
- 若标记不存在或值为 `false`,视为未初始化。
|
||||
- 若存在且为 `true`,跳过初始化。
|
||||
- 导入步骤(未初始化时):
|
||||
- 执行 `base-schema.sql`(若目标库为空或需校正结构时)。
|
||||
- 执行 `base-data.sql`(插入/更新缺失的基线数据,注意幂等性)。
|
||||
- 更新标记为已初始化,并记录版本与时间戳。
|
||||
- 幂等性建议:
|
||||
- 数据插入使用“存在则跳过/更新”策略(`INSERT ... ON DUPLICATE KEY UPDATE` 或先查询再写入)。
|
||||
- 避免覆盖已有业务数据;仅在缺失时补充。
|
||||
|
||||
## Spring Boot 集成方案
|
||||
- 方案 A(轻量):在后端增加初始化 Runner
|
||||
- 新增一个 `@Component` 实现 `ApplicationRunner` 或 `CommandLineRunner` 的 `DataInitializer`。
|
||||
- 启动时:检查标记 → 未初始化则依次执行 `sql/base-schema.sql` 与 `sql/base-data.sql`。
|
||||
- SQL 执行方式:
|
||||
- 直接通过 JDBC 读取并执行 SQL 文件(分号切分、事务包裹、失败回滚)。
|
||||
- 或调用外部 `mysql` 命令(需服务器已安装 `mysql` 客户端,适合运维环境)。
|
||||
- Profile 控制:默认仅在 `server` 或 `dev` 首次运行时启用;可通过配置 `app.init.enabled=true/false` 控制。
|
||||
- 方案 B(推荐中长期):引入数据库版本管理工具
|
||||
- `Flyway` 或 `Liquibase` 管理结构与数据变更;将初始化作为 `V1__base.sql` 脚本。
|
||||
- 优点:变更有版本与校验,部署一致性更强;缺点:需要改造现有 SQL 并纳入流水线。
|
||||
|
||||
## 配置示例
|
||||
- `application-server.yml` 中添加:
|
||||
```
|
||||
app:
|
||||
init:
|
||||
enabled: true
|
||||
schema: classpath:db-init/sql/base-schema.sql
|
||||
data: classpath:db-init/sql/base-data.sql
|
||||
marker-table: app_init
|
||||
marker-version: v1.0.0
|
||||
```
|
||||
- 路径策略:
|
||||
- 若以资源方式打包,建议将 `db-init/sql` 复制到 `src/main/resources/db-init/sql`。
|
||||
- 或保留在项目根并通过绝对/相对路径访问(需考虑部署路径与权限)。
|
||||
|
||||
## 脚本示例(Windows PowerShell)
|
||||
- `framework/db-init/scripts/export.ps1`
|
||||
```
|
||||
param(
|
||||
[string]$DB_HOST = "43.138.168.68",
|
||||
[int]$DB_PORT = 3306,
|
||||
[string]$DB_NAME = "frameworkdb2025",
|
||||
[string]$DB_USER = "root",
|
||||
[string]$DB_PASSWORD = "ylfw20230626@"
|
||||
)
|
||||
|
||||
$env:MYSQL_PWD = $DB_PASSWORD
|
||||
|
||||
# 导出结构
|
||||
mysqldump -h $DB_HOST -P $DB_PORT -u $DB_USER --no-data --databases $DB_NAME > ../sql/base-schema.sql
|
||||
|
||||
# 按需导出数据(示例表名可调整)
|
||||
mysqldump -h $DB_HOST -P $DB_PORT -u $DB_USER --no-create-info $DB_NAME sys_dict sys_config sys_role sys_menu sys_user sys_user_role sys_role_menu > ../sql/base-data.sql
|
||||
|
||||
Write-Host "Export completed: base-schema.sql & base-data.sql"
|
||||
```
|
||||
- `framework/db-init/scripts/import.ps1`
|
||||
```
|
||||
param(
|
||||
[string]$DB_HOST = "127.0.0.1",
|
||||
[int]$DB_PORT = 3306,
|
||||
[string]$DB_NAME = "platform",
|
||||
[string]$DB_USER = "root",
|
||||
[string]$DB_PASSWORD = "root"
|
||||
)
|
||||
|
||||
$env:MYSQL_PWD = $DB_PASSWORD
|
||||
|
||||
mysql -h $DB_HOST -P $DB_PORT -u $DB_USER $DB_NAME < ../sql/base-schema.sql
|
||||
mysql -h $DB_HOST -P $DB_PORT -u $DB_USER $DB_NAME < ../sql/base-data.sql
|
||||
|
||||
Write-Host "Import completed"
|
||||
```
|
||||
|
||||
## 启动时自动初始化的实现建议(代码思路)
|
||||
- 创建 `DataInitializer`:
|
||||
- 读取 `app.init.enabled`;若为 `false` 则直接返回。
|
||||
- 使用 `JdbcTemplate` 或 `EntityManager` 查询 `marker-table` 状态。
|
||||
- 若未初始化:
|
||||
- 读取并执行 `schema`、`data` 指定的 SQL 文件;分批执行并开启事务。
|
||||
- 写入标记表 `initialized=true, version=marker-version, ts=now()`。
|
||||
- 并发保护:
|
||||
- 使用数据库锁或单例启动(例如基于 `SELECT ... FOR UPDATE` 或分布式锁)避免多实例重复初始化。
|
||||
- 失败回滚与告警:
|
||||
- 执行失败时回滚事务并记录日志,提示人工介入;避免部分写入。
|
||||
|
||||
## 运维与审计
|
||||
- 对 `sql/base-data.sql` 的修改应评审并走 PR,避免带入敏感数据。
|
||||
- CI 提示:
|
||||
- 在 `server` 构建流水线中,可增加“初始化脚本语法检查”(如用 `mysql --dry-run` 或解析器)。
|
||||
- 版本管理:
|
||||
- 在 `db-init/README.md` 中记录每次更新目的与影响;或使用 `Flyway` 版本号管理。
|
||||
|
||||
## 下一步落地
|
||||
- 我可以为你:
|
||||
- 搭建 `framework/db-init` 目录与示例脚本、README。
|
||||
- 在后端新增 `DataInitializer` 组件与配置项,支持 `dev/server` 下自动初始化。
|
||||
- 可选集成 `Flyway`,将初始化脚本迁移为 `V1__base.sql` 并接入 CI。
|
||||
@ -0,0 +1,17 @@
|
||||
package com.yfd.platform.config;
|
||||
|
||||
import lombok.Data;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
@Data
|
||||
@Configuration
|
||||
@ConfigurationProperties(prefix = "app.init")
|
||||
public class AppInitProperties {
|
||||
private boolean enabled = false;
|
||||
private String schema;
|
||||
private String data;
|
||||
// 用于判断是否已初始化:默认检查是否存在核心表
|
||||
private String markerTable = "sys_user";
|
||||
private String markerVersion = "v1.0.0";
|
||||
}
|
||||
@ -0,0 +1,129 @@
|
||||
package com.yfd.platform.config;
|
||||
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.boot.ApplicationArguments;
|
||||
import org.springframework.boot.ApplicationRunner;
|
||||
import org.springframework.context.annotation.Profile;
|
||||
import org.springframework.core.Ordered;
|
||||
import org.springframework.core.annotation.Order;
|
||||
import org.springframework.core.io.ByteArrayResource;
|
||||
import org.springframework.core.io.Resource;
|
||||
import org.springframework.core.io.ResourceLoader;
|
||||
import org.springframework.core.io.support.EncodedResource;
|
||||
import org.springframework.jdbc.datasource.init.ScriptUtils;
|
||||
import org.springframework.jdbc.datasource.init.ScriptException;
|
||||
import org.springframework.jdbc.datasource.init.ScriptStatementFailedException;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.stream.Collectors;
|
||||
import org.springframework.util.StreamUtils;
|
||||
import java.sql.Connection;
|
||||
import java.sql.DatabaseMetaData;
|
||||
import java.sql.ResultSet;
|
||||
|
||||
@Slf4j
|
||||
@Component
|
||||
@Profile({"dev","server"})
|
||||
@RequiredArgsConstructor
|
||||
@Order(Ordered.HIGHEST_PRECEDENCE)
|
||||
public class DataInitializer implements ApplicationRunner {
|
||||
|
||||
private final DataSource dataSource;
|
||||
private final AppInitProperties properties;
|
||||
private final ResourceLoader resourceLoader;
|
||||
|
||||
@Override
|
||||
public void run(ApplicationArguments args) throws Exception {
|
||||
if (!properties.isEnabled()) {
|
||||
log.info("[DataInit] 自动初始化已关闭 app.init.enabled=false");
|
||||
return;
|
||||
}
|
||||
|
||||
try (Connection conn = dataSource.getConnection()) {
|
||||
boolean initialized = tableExists(conn, properties.getMarkerTable());
|
||||
if (initialized) {
|
||||
log.info("[DataInit] 检测到标记表已存在: {},跳过初始化", properties.getMarkerTable());
|
||||
return;
|
||||
}
|
||||
|
||||
log.info("[DataInit] 未检测到标记表: {},开始导入 schema 与 data", properties.getMarkerTable());
|
||||
executeIfPresent(conn, properties.getSchema());
|
||||
executeIfPresent(conn, properties.getData());
|
||||
log.info("[DataInit] 导入完成。marker={} version={}", properties.getMarkerTable(), properties.getMarkerVersion());
|
||||
} catch (Exception ex) {
|
||||
log.error("[DataInit] 初始化失败: {}", ex.getMessage(), ex);
|
||||
throw ex;
|
||||
}
|
||||
}
|
||||
|
||||
private boolean tableExists(Connection conn, String tableName) {
|
||||
if (tableName == null || tableName.isEmpty()) return false;
|
||||
try {
|
||||
DatabaseMetaData meta = conn.getMetaData();
|
||||
try (ResultSet rs = meta.getTables(conn.getCatalog(), null, tableName, null)) {
|
||||
return rs.next();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.warn("[DataInit] 检查表存在异常: {}", e.getMessage());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private void executeIfPresent(Connection conn, String location) throws Exception {
|
||||
if (location == null || location.isEmpty()) return;
|
||||
Resource resource = resourceLoader.getResource(location);
|
||||
if (!resource.exists()) {
|
||||
log.warn("[DataInit] 资源不存在: {}", location);
|
||||
return;
|
||||
}
|
||||
log.info("[DataInit] 执行脚本: {}", location);
|
||||
// 读取并清理脚本首部的 BOM 和危险语句(CREATE DATABASE / USE schema)
|
||||
String sql = StreamUtils.copyToString(resource.getInputStream(), StandardCharsets.UTF_8);
|
||||
if (sql != null && !sql.isEmpty()) {
|
||||
// 移除 UTF-8 BOM(\uFEFF)
|
||||
if (sql.charAt(0) == '\uFEFF') {
|
||||
sql = sql.substring(1);
|
||||
}
|
||||
// 移除 "USE xxx;" 和 "CREATE DATABASE" 等与连接无关的语句
|
||||
sql = sql.lines()
|
||||
.filter(line -> {
|
||||
String raw = line;
|
||||
String t = raw.trim();
|
||||
String u = t.toUpperCase();
|
||||
// 过滤与连接无关或可能引发解析问题的语句/注释
|
||||
if (u.startsWith("USE ")) return false;
|
||||
if (u.startsWith("CREATE DATABASE")) return false;
|
||||
if (t.startsWith("--")) return false; // 单行注释
|
||||
if (t.startsWith("/*") || t.startsWith("*/")) return false; // 多行注释行
|
||||
if (t.startsWith("/*!")) return false; // MySQL 版本注释
|
||||
if (t.matches("^-+$")) return false; // 分隔线
|
||||
return true;
|
||||
})
|
||||
.collect(Collectors.joining("\n"));
|
||||
}
|
||||
if (sql != null && !sql.trim().isEmpty()) {
|
||||
try {
|
||||
ScriptUtils.executeSqlScript(conn, new EncodedResource(new ByteArrayResource(sql.getBytes(StandardCharsets.UTF_8)), StandardCharsets.UTF_8));
|
||||
} catch (ScriptStatementFailedException e) {
|
||||
String preview = sql.lines()
|
||||
.filter(s -> !s.trim().isEmpty())
|
||||
.limit(10)
|
||||
.collect(Collectors.joining("\n"));
|
||||
log.error("[DataInit] SQL语句执行失败: {}\n前10行预览:\n{}", e.getMessage(), preview);
|
||||
throw e;
|
||||
} catch (ScriptException e) {
|
||||
String preview = sql.lines()
|
||||
.filter(s -> !s.trim().isEmpty())
|
||||
.limit(10)
|
||||
.collect(Collectors.joining("\n"));
|
||||
log.error("[DataInit] 脚本执行失败: {}\n前10行预览:\n{}", e.getMessage(), preview);
|
||||
throw e;
|
||||
}
|
||||
} else {
|
||||
log.warn("[DataInit] 脚本在清理后为空,跳过执行: {}", location);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -24,6 +24,8 @@ import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.boot.ApplicationArguments;
|
||||
import org.springframework.boot.ApplicationRunner;
|
||||
import org.springframework.core.Ordered;
|
||||
import org.springframework.core.annotation.Order;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.List;
|
||||
@ -34,6 +36,7 @@ import java.util.List;
|
||||
*/
|
||||
@Component
|
||||
@RequiredArgsConstructor
|
||||
@Order(Ordered.LOWEST_PRECEDENCE)
|
||||
public class JobRunner implements ApplicationRunner {
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(JobRunner.class);
|
||||
|
||||
@ -1,168 +0,0 @@
|
||||
|
||||
|
||||
|
||||
# 此配置文件只是用作展示所有配置项, 不可不直接使用
|
||||
|
||||
|
||||
spring:
|
||||
# REDIS数据库配置
|
||||
redis:
|
||||
# [必须修改] Redis服务器IP, REDIS安装在本机的,使用127.0.0.1
|
||||
host: 127.0.0.1
|
||||
# [必须修改] 端口号
|
||||
port: 6379
|
||||
# [可选] 数据库 DB
|
||||
database: 6
|
||||
# [可选] 访问密码,若你的redis服务器没有设置密码,就不需要用密码去连接
|
||||
password:
|
||||
# [可选] 超时时间
|
||||
timeout: 10000
|
||||
# [可选] 一个pool最多可分配多少个jedis实例
|
||||
poolMaxTotal: 1000
|
||||
# [可选] 一个pool最多有多少个状态为idle(空闲)的jedis实例
|
||||
poolMaxIdle: 500
|
||||
# [可选] 最大的等待时间(秒)
|
||||
poolMaxWait: 5
|
||||
# [可选] jdbc数据库配置, 项目使用sqlite作为数据库,一般不需要配置
|
||||
datasource:
|
||||
# 使用mysql 打开23-28行注释, 删除29-36行
|
||||
name: wvp
|
||||
url: jdbc:mysql://127.0.0.1:3306/wvp?useUnicode=true&characterEncoding=UTF8&rewriteBatchedStatements=true
|
||||
username:
|
||||
password:
|
||||
type: com.alibaba.druid.pool.DruidDataSource
|
||||
driver-class-name: com.mysql.cj.jdbc.Driver
|
||||
# name: eiot
|
||||
# url: jdbc:sqlite::resource:wvp.sqlite
|
||||
# username:
|
||||
# password:
|
||||
# type: com.alibaba.druid.pool.DruidDataSource
|
||||
# driver-class-name: org.sqlite.JDBC
|
||||
max-active: 1
|
||||
min-idle: 1
|
||||
|
||||
# [可选] WVP监听的HTTP端口, 网页和接口调用都是这个端口
|
||||
server:
|
||||
port: 18080
|
||||
# [可选] HTTPS配置, 默认不开启
|
||||
ssl:
|
||||
# [可选] 是否开启HTTPS访问
|
||||
enabled: false
|
||||
# [可选] 证书文件路径,放置在resource/目录下即可,修改xxx为文件名
|
||||
key-store: classpath:xxx.jks
|
||||
# [可选] 证书密码
|
||||
key-password: password
|
||||
# [可选] 证书类型, 默认为jks,根据实际修改
|
||||
key-store-type: JKS
|
||||
|
||||
# 作为28181服务器的配置
|
||||
sip:
|
||||
# [必须修改] 本机的IP, 必须是网卡上的IP,用于sip下协议栈监听ip,如果监听所有设置为0.0.0.0
|
||||
monitor-ip: 0.0.0.0
|
||||
# [必须修改] 本机的IP
|
||||
ip: 192.168.0.100
|
||||
# [可选] 28181服务监听的端口
|
||||
port: 5060
|
||||
# 根据国标6.1.2中规定,domain宜采用ID统一编码的前十位编码。国标附录D中定义前8位为中心编码(由省级、市级、区级、基层编号组成,参照GB/T 2260-2007)
|
||||
# 后两位为行业编码,定义参照附录D.3
|
||||
# 3701020049标识山东济南历下区 信息行业接入
|
||||
# [可选]
|
||||
domain: 4401020049
|
||||
# [可选]
|
||||
id: 44010200492000000001
|
||||
# [可选] 默认设备认证密码,后续扩展使用设备单独密码, 移除密码将不进行校验
|
||||
password: admin123
|
||||
# [可选] 心跳超时时间, 建议设置为心跳周期的三倍
|
||||
keepalive-timeout: 255
|
||||
# [可选] 国标级联注册失败,再次发起注册的时间间隔。 默认60秒
|
||||
register-time-interval: 60
|
||||
# [可选] 云台控制速度
|
||||
ptz-speed: 50
|
||||
# TODO [可选] 收到心跳后自动上线, 重启服务后会将所有设备置为离线,默认false,等待注册后上线。设置为true则收到心跳设置为上线。
|
||||
# keepalliveToOnline: false
|
||||
|
||||
#zlm 默认服务器配置
|
||||
media:
|
||||
# [可选] zlm服务器唯一id,用于触发hook时区别是哪台服务器,general.mediaServerId
|
||||
id:
|
||||
# [必须修改] zlm服务器的内网IP
|
||||
ip: 192.168.0.100
|
||||
# [可选] 返回流地址时的ip,置空使用 media.ip
|
||||
stream-ip:
|
||||
# [可选] wvp在国标信令中使用的ip,此ip为摄像机可以访问到的ip, 置空使用 media.ip
|
||||
sdp-ip:
|
||||
# [可选] zlm服务器的hook所使用的IP, 默认使用sip.ip
|
||||
hook-ip:
|
||||
# [必须修改] zlm服务器的http.port
|
||||
http-port: 80
|
||||
# [可选] zlm服务器的http.sslport, 置空使用zlm配置文件配置
|
||||
http-ssl-port:
|
||||
# [可选] zlm服务器的rtmp.port, 置空使用zlm配置文件配置
|
||||
rtmp-port:
|
||||
# [可选] zlm服务器的rtmp.sslport, 置空使用zlm配置文件配置
|
||||
rtmp-ssl-port:
|
||||
# [可选] zlm服务器的 rtp_proxy.port, 置空使用zlm配置文件配置
|
||||
rtp-proxy-port:
|
||||
# [可选] zlm服务器的 rtsp.port, 置空使用zlm配置文件配置
|
||||
rtsp-port:
|
||||
# [可选] zlm服务器的 rtsp.sslport, 置空使用zlm配置文件配置
|
||||
rtsp-ssl-port:
|
||||
# [可选] 是否自动配置ZLM, 如果希望手动配置ZLM, 可以设为false, 不建议新接触的用户修改
|
||||
auto-config: true
|
||||
# [可选] zlm服务器的hook.admin_params=secret
|
||||
secret: 035c73f7-bb6b-4889-a715-d9eb2d1925cc
|
||||
# [可选] zlm服务器的general.streamNoneReaderDelayMS
|
||||
stream-none-reader-delay-ms: 18000 # 无人观看多久自动关闭流, -1表示永不自动关闭,即 关闭按需拉流
|
||||
# 启用多端口模式, 多端口模式使用端口区分每路流,兼容性更好。 单端口使用流的ssrc区分, 点播超时建议使用多端口测试
|
||||
rtp:
|
||||
# [可选] 是否启用多端口模式, 开启后会在portRange范围内选择端口用于媒体流传输
|
||||
enable: true
|
||||
# [可选] 在此范围内选择端口用于媒体流传输,
|
||||
port-range: 30000,30500 # 端口范围
|
||||
# [可选] 国标级联在此范围内选择端口发送媒体流,
|
||||
send-port-range: 30000,30500 # 端口范围
|
||||
# 录像辅助服务, 部署此服务可以实现zlm录像的管理与下载, 0 表示不使用
|
||||
record-assist-port: 0
|
||||
|
||||
# [可选] 日志配置, 一般不需要改
|
||||
logging:
|
||||
file:
|
||||
name: logs/wvp.log
|
||||
max-history: 30
|
||||
max-size: 10MB
|
||||
total-size-cap: 300MB
|
||||
level:
|
||||
com.genersoft.iot: debug
|
||||
com.genersoft.iot.vmp.storager.dao: info
|
||||
com.genersoft.iot.vmp.gb28181: info
|
||||
# [根据业务需求配置]
|
||||
user-settings:
|
||||
# [可选] 自动点播, 使用固定流地址进行播放时,如果未点播则自动进行点播, 需要rtp.enable=true
|
||||
auto-apply-play: false
|
||||
# [可选] 部分设备需要扩展SDP,需要打开此设置
|
||||
senior-sdp: false
|
||||
# 保存移动位置历史轨迹:true:保留历史数据,false:仅保留最后的位置(默认)
|
||||
save-position-history: false
|
||||
# 点播等待超时时间,单位:毫秒
|
||||
play-timeout: 3000
|
||||
# 等待音视频编码信息再返回, true: 可以根据编码选择合适的播放器,false: 可以更快点播
|
||||
wait-track: false
|
||||
# 是否开启接口鉴权
|
||||
interface-authentication: true
|
||||
# 接口鉴权例外的接口, 即不进行接口鉴权的接口,尽量详细书写,尽量不用/**,至少两级目录
|
||||
interface-authentication-excludes:
|
||||
- /api/v1/**
|
||||
# 推流直播是否录制
|
||||
record-push-live: true
|
||||
# 是否将日志存储进数据库
|
||||
logInDatebase: true
|
||||
|
||||
# 在线文档: swagger-ui(生产环境建议关闭)
|
||||
swagger-ui:
|
||||
enabled: true
|
||||
|
||||
# 版本信息, 不需修改
|
||||
version:
|
||||
version: "@project.version@"
|
||||
description: "@project.description@"
|
||||
artifact-id: "@project.artifactId@"
|
||||
@ -10,12 +10,12 @@ spring:
|
||||
druid:
|
||||
master:
|
||||
driverClassName: com.mysql.cj.jdbc.Driver
|
||||
url: jdbc:mysql://43.138.168.68:3306/frameworkdb2023?useUnicode=true&characterEncoding=UTF8&rewriteBatchedStatements=true
|
||||
url: jdbc:mysql://43.138.168.68:3306/frameworkdb2025?useUnicode=true&characterEncoding=UTF8&rewriteBatchedStatements=true
|
||||
username: root
|
||||
password: ylfw20230626@
|
||||
slave:
|
||||
driverClassName: com.mysql.cj.jdbc.Driver
|
||||
url: jdbc:mysql://43.138.168.68:3306/frameworkdb2023?useUnicode=true&characterEncoding=UTF8&rewriteBatchedStatements=true
|
||||
url: jdbc:mysql://43.138.168.68:3306/frameworkdb2025?useUnicode=true&characterEncoding=UTF8&rewriteBatchedStatements=true
|
||||
username: root
|
||||
password: ylfw20230626@
|
||||
|
||||
@ -50,6 +50,16 @@ login:
|
||||
login-code:
|
||||
# 验证码类型配置 查看 LoginProperties 类
|
||||
code-type: arithmetic
|
||||
|
||||
# 启动自动数据库初始化(仅 dev/server):
|
||||
app:
|
||||
init:
|
||||
enabled: false
|
||||
schema: classpath:db-init/sql/min-schema.sql
|
||||
# data 文件可选;为避免复杂 dump 解析问题,先不导入
|
||||
# data:
|
||||
marker-table: sys_user
|
||||
marker-version: v1.0.0
|
||||
# 登录图形验证码有效时间/分钟
|
||||
expiration: 2
|
||||
# 验证码高度
|
||||
|
||||
@ -10,9 +10,9 @@ spring:
|
||||
druid:
|
||||
master:
|
||||
driverClassName: com.mysql.cj.jdbc.Driver
|
||||
url: jdbc:mysql://43.138.168.68:3306/framework2023?useUnicode=true&characterEncoding=UTF8&rewriteBatchedStatements=true
|
||||
url: jdbc:mysql://43.138.168.68:3306/frameworkdb2025?useUnicode=true&characterEncoding=UTF8&rewriteBatchedStatements=true
|
||||
username: root
|
||||
password: zhengg7QkXa<gRqqQ2023
|
||||
password: ylfw20230626@
|
||||
|
||||
mvc:
|
||||
pathmatch:
|
||||
@ -41,3 +41,13 @@ file-space: #项目文档空间
|
||||
useravatar: D:\demoproject\useravatar\ #用户头像
|
||||
system: D:\demoproject\system\ #系统文档根目录,用于头像等静态资源
|
||||
|
||||
# 启动自动数据库初始化(仅 dev/server):
|
||||
app:
|
||||
init:
|
||||
enabled: true
|
||||
schema: classpath:db-init/sql/min-schema.sql
|
||||
# data 文件可选;为避免复杂 dump 解析问题,先不导入
|
||||
# data:
|
||||
marker-table: sys_user
|
||||
marker-version: v1.0.0
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user