---
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
org.apache.maven.plugins
maven-assembly-plugin
3.3.0
src/main/assembly/assembly.xml
${project.artifactId}
make-assembly
package
single
```
### assembly.xml配置
```xml
dist
tar.gz
true
${project.basedir}/../../scripts
bin
start.sh
stop.sh
restart.sh
status.sh
0755
${project.basedir}/../../scripts
conf
env.properties
src/main/resources
conf
service.properties
application.yml
application-*.yml
logback-spring.xml
lib
true
runtime
```
## 自动构建脚本
### 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集成**: 部署目录结构便于自动化部署和版本发布管理