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