441 lines
12 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

---
name: maven-assembly
description: 针对资金服务平台项目的Maven Assembly打包技能专门处理env.properties统一配置和service.properties个性化配置的合并打包生成包含bin/lib/conf目录结构的tar.gz部署包支持自动化的构建脚本。使用场景当需要生成或修改项目的Assembly配置文件、创建部署包、处理配置文件合并、进行多服务打包时自动触发。
---
# 资金服务平台 Maven Assembly 打包技能
## 触发条件
当出现以下情况时,自动应用此技能:
1. **配置文件管理相关**
- 需要创建或修改 `env.properties` 统一配置文件
- 需要创建或修改各服务的 `service.properties` 个性化配置
- 需要处理配置文件的合并和加载顺序
2. **Assembly配置相关**
- 需要生成项目的 `assembly.xml` 配置文件
- 需要配置 Maven Assembly 插件
- 需要设置打包目录结构和文件包含规则
3. **构建打包相关**
- 需要创建或修改批量构建脚本
- 需要生成包含 bin/lib/conf 目录结构的部署包
- 需要处理多服务模块的统一打包
4. **部署验证相关**
- 需要验证部署包的完整性和正确性
- 需要检查配置文件的必需参数
- 需要测试启动脚本的配置加载机制
5. **部署目录管理相关**
- 需要将所有打包产物统一存储在项目根目录的 `deploy/` 目录下
- 需要维护部署包的版本管理和清理机制
- 需要确保部署目录与开发代码的物理分离
## 项目架构概述
本技能专为资金服务平台定制,采用**统一配置 + 个性化配置**分离架构,并实现**开发代码与部署产物物理分离**
```
fundplatform/
├── deploy/ # 部署产物目录(所有打包文件统一存放)
│ ├── fund-gateway.tar.gz
│ ├── fund-sys.tar.gz
│ ├── fund-cust.tar.gz
│ └── ... 其他服务部署包
├── scripts/ # 统一脚本和配置目录
│ ├── env.properties # 统一配置(所有服务共用)
│ ├── start.sh # 启动脚本
│ ├── stop.sh # 停止脚本
│ └── build-services.sh # 自动构建脚本
├── fund-sys/ # 服务源代码目录
│ └── src/main/resources/
│ └── service.properties # 个性化配置(每服务独立)
├── fund-gateway/
│ └── src/main/resources/
│ └── service.properties
└── ... 其他服务模块
```
**核心实践原则**
- 所有部署打包文件统一存储在项目根目录的 `deploy/` 目录下
- 开发代码与部署产物物理分离便于版本管理和CI/CD集成
- 通过 `services-build.sh` 脚本自动收集各服务构建产物到统一部署目录
## 配置文件管理
### 统一配置 (env.properties)
**位置**: `scripts/env.properties`
**用途**: 所有服务共用的基础配置
**包含内容**:
- Nacos配置
- Redis配置
- 数据库连接池配置
- 日志配置
- 腾讯云COS配置
- 多租户路由配置
### 个性化配置 (service.properties)
**位置**: 各服务 `src/main/resources/service.properties`
**用途**: 服务独立的个性化参数
**必须包含**:
```properties
APP_NAME=fund-sys # 服务名称
MAIN_CLASS=com.xxx.App # 主启动类
INSTANCE_NAME= # 实例名称(可选)
TENANT_ID= # 租户ID可选
```
## 核心目录结构
每个服务打包后应包含:
```
服务名/
├── bin/ # 可执行脚本来自scripts目录
│ ├── start.sh
│ ├── stop.sh
│ ├── restart.sh
│ └── status.sh
├── lib/ # JAR文件和依赖
│ ├── 服务名-version.jar
│ └── 依赖.jar
└── conf/ # 配置文件
├── env.properties # 统一配置来自scripts/env.properties
├── service.properties # 个性化配置来自服务src/main/resources
├── application.yml
└── logback-spring.xml
```
## Assembly配置详解
### pom.xml配置
```xml
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<version>3.3.0</version>
<configuration>
<descriptors>
<descriptor>src/main/assembly/assembly.xml</descriptor>
</descriptors>
<finalName>${project.artifactId}</finalName>
</configuration>
<executions>
<execution>
<id>make-assembly</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
```
### assembly.xml配置
```xml
<assembly xmlns="http://maven.apache.org/ASSEMBLY/2.0.0">
<id>dist</id>
<formats>
<format>tar.gz</format>
</formats>
<includeBaseDirectory>true</includeBaseDirectory>
<fileSets>
<!-- bin目录使用项目根目录的统一脚本 -->
<fileSet>
<directory>${project.basedir}/../../scripts</directory>
<outputDirectory>bin</outputDirectory>
<includes>
<include>start.sh</include>
<include>stop.sh</include>
<include>restart.sh</include>
<include>status.sh</include>
</includes>
<fileMode>0755</fileMode>
</fileSet>
<!-- conf目录统一配置 + 个性化配置 -->
<fileSet>
<directory>${project.basedir}/../../scripts</directory>
<outputDirectory>conf</outputDirectory>
<includes>
<include>env.properties</include>
</includes>
</fileSet>
<fileSet>
<directory>src/main/resources</directory>
<outputDirectory>conf</outputDirectory>
<includes>
<include>service.properties</include>
<include>application.yml</include>
<include>application-*.yml</include>
<include>logback-spring.xml</include>
</includes>
</fileSet>
</fileSets>
<!-- lib目录服务JAR + 依赖 -->
<dependencySets>
<dependencySet>
<outputDirectory>lib</outputDirectory>
<useProjectArtifact>true</useProjectArtifact>
<scope>runtime</scope>
</dependencySet>
</dependencySets>
</assembly>
```
## 自动构建脚本
### services-build.sh (项目根目录)
```bash
#!/bin/bash
# 自动构建所有微服务统一输出到deploy目录
set -e
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
PROJECT_ROOT="${SCRIPT_DIR}"
DEPLOY_DIR="${PROJECT_ROOT}/deploy"
SERVICES=(
"fund-gateway"
"fund-sys"
"fund-cust"
"fund-proj"
"fund-exp"
"fund-receipt"
"fund-report"
"fund-req"
"fund-file"
)
# 确保部署目录存在
mkdir -p "${DEPLOY_DIR}"
# 清理旧的部署包(可选)
echo "清理旧部署包..."
rm -f "${DEPLOY_DIR}"/*.tar.gz
build_service() {
local service=$1
local service_dir="${PROJECT_ROOT}/${service}"
echo "=== 构建服务: ${service} ==="
if [ ! -d "${service_dir}" ]; then
echo "警告: 服务目录不存在 ${service_dir}"
return 1
fi
cd "${service_dir}"
# Maven构建
mvn clean package -DskipTests
# 检查生成的tar.gz文件并复制到统一部署目录
local tar_file=$(find target -name "${service}*.tar.gz" | head -1)
if [ -n "${tar_file}" ]; then
cp "${tar_file}" "${DEPLOY_DIR}/"
echo "✓ ${service} 构建完成: $(basename ${tar_file})"
else
echo "✗ ${service} 构建失败未找到tar.gz文件"
return 1
fi
}
# 主构建流程
echo "开始批量构建微服务..."
echo "项目根目录: ${PROJECT_ROOT}"
echo "部署输出目录: ${DEPLOY_DIR}"
echo ""
for service in "${SERVICES[@]}"; do
build_service "${service}" || {
echo "构建失败,退出"
exit 1
}
done
echo ""
echo "=== 构建完成 ==="
echo "生成的部署包:"
ls -lh "${DEPLOY_DIR}"/*.tar.gz
echo ""
echo "部署目录大小: $(du -sh "${DEPLOY_DIR}" | cut -f1)"
```
## 启动脚本增强版
### start.sh (支持配置文件加载)
```bash
#!/bin/bash
# 增强版启动脚本自动加载env.properties和service.properties
APP_HOME=$(cd "$(dirname "$0")/.." && pwd)
PID_FILE="/tmp/${INSTANCE_NAME}.pid"
# 配置文件加载函数
load_properties() {
local file=$1
if [[ -f "$file" ]]; then
while IFS='=' read -r key value; do
[[ -z "$key" || "$key" =~ ^# ]] && continue
export "$key=$value"
done < "$file"
fi
}
# 1. 加载统一配置
load_properties "${APP_HOME}/conf/env.properties"
# 2. 加载服务个性化配置(覆盖统一配置)
load_properties "${APP_HOME}/conf/service.properties"
# 3. 设置默认值
APP_NAME=${APP_NAME:-"unknown"}
INSTANCE_NAME=${INSTANCE_NAME:-${APP_NAME}}
TENANT_ID=${TENANT_ID:-""}
# 4. 查找主JAR文件
JAR_FILE=$(find "${APP_HOME}/lib" -name "${APP_NAME}*.jar" | head -1)
if [[ -z "$JAR_FILE" ]]; then
echo "错误: 未找到JAR文件 ${APP_NAME}*.jar"
exit 1
fi
# 5. 构建JVM参数
JAVA_OPTS="-Xms256m -Xmx512m"
JAVA_OPTS="$JAVA_OPTS -Dspring.config.location=${APP_HOME}/conf/"
JAVA_OPTS="$JAVA_OPTS -Dlogging.config=${APP_HOME}/conf/logback-spring.xml"
# 6. 启动应用
echo "启动服务: ${INSTANCE_NAME}"
echo "JAR文件: $(basename $JAR_FILE)"
echo "租户ID: ${TENANT_ID:-'共享实例'}"
nohup java $JAVA_OPTS -jar "$JAR_FILE" > /dev/null 2>&1 &
echo $! > "${PID_FILE}"
echo "${INSTANCE_NAME} 启动成功PID: $(cat ${PID_FILE})"
```
## 配置文件验证
### 配置检查脚本
```bash
#!/bin/bash
# validate-config.sh - 验证配置文件完整性
APP_HOME=$(cd "$(dirname "$0")/.." && pwd)
echo "=== 配置文件验证 ==="
# 检查必需文件
REQUIRED_FILES=(
"conf/env.properties"
"conf/service.properties"
"conf/application.yml"
"lib/${APP_NAME}*.jar"
)
for file_pattern in "${REQUIRED_FILES[@]}"; do
if ls "${APP_HOME}/${file_pattern}" >/dev/null 2>&1; then
echo "✓ ${file_pattern}"
else
echo "✗ ${file_pattern} (缺失)"
exit 1
fi
done
# 验证service.properties必需参数
SERVICE_CONF="${APP_HOME}/conf/service.properties"
REQUIRED_PARAMS=("APP_NAME" "MAIN_CLASS")
for param in "${REQUIRED_PARAMS[@]}"; do
if grep -q "^${param}=" "${SERVICE_CONF}"; then
value=$(grep "^${param}=" "${SERVICE_CONF}" | cut -d'=' -f2)
echo "✓ ${param}=${value}"
else
echo "✗ 缺少必需参数: ${param}"
exit 1
fi
done
echo "配置验证通过!"
```
## 打包命令
```bash
# 构建单个服务
cd fund-sys && mvn clean package
# 批量构建所有服务
cd /项目根目录 && ./scripts/services-build.sh
# 跳过测试快速构建
mvn clean package -DskipTests
# 验证打包结果
tar -tzf target/fund-sys.tar.gz | head -10
```
## 部署验证清单
构建完成后验证:
```bash
#!/bin/bash
# deployment-check.sh
TAR_FILE=$1
echo "=== 部署包验证 ==="
echo "包文件: ${TAR_FILE}"
# 结构验证
echo "目录结构:"
tar -tzf "${TAR_FILE}" | grep -E "^(bin/|lib/|conf/)" | sort
# 关键文件验证
echo "必需文件检查:"
REQUIRED=(
"bin/start.sh"
"bin/stop.sh"
"conf/env.properties"
"conf/service.properties"
)
for file in "${REQUIRED[@]}"; do
if tar -tzf "${TAR_FILE}" | grep -q "^${file}$"; then
echo "✓ ${file}"
else
echo "✗ ${file}"
exit 1
fi
done
# 权限验证
echo "脚本权限检查:"
SCRIPTS=$(tar -tzf "${TAR_FILE}" | grep "^bin/.*\.sh$")
for script in ${SCRIPTS}; do
echo "✓ ${script} (可执行)"
done
echo "验证完成!"
```
## 最佳实践
1. **配置分离**: 统一配置放`scripts/env.properties`,个性化配置放各服务`service.properties`
2. **构建脚本**: 使用统一的`services-build.sh`批量构建
3. **版本管理**: 在`service.properties`中明确指定`APP_NAME``MAIN_CLASS`
4. **多租户支持**: 通过`TENANT_ID`参数支持共享实例和VIP专属实例
5. **权限控制**: 确保bin目录脚本具有可执行权限(755)
6. **验证机制**: 构建后使用验证脚本检查包完整性
7. **部署目录管理**: 所有部署包统一存储在项目根目录`deploy/`下,实现开发与部署物理分离
8. **CI/CD集成**: 部署目录结构便于自动化部署和版本发布管理