441 lines
12 KiB
Markdown
441 lines
12 KiB
Markdown
---
|
||
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集成**: 部署目录结构便于自动化部署和版本发布管理 |