12 KiB
Raw Blame History

name, description
name description
maven-assembly 针对资金服务平台项目的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 用途: 服务独立的个性化参数 必须包含:

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配置

<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配置

<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 (项目根目录)

#!/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 (支持配置文件加载)

#!/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})"

配置文件验证

配置检查脚本

#!/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 "配置验证通过!"

打包命令

# 构建单个服务
cd fund-sys && mvn clean package

# 批量构建所有服务
cd /项目根目录 && ./scripts/services-build.sh

# 跳过测试快速构建
mvn clean package -DskipTests

# 验证打包结果
tar -tzf target/fund-sys.tar.gz | head -10

部署验证清单

构建完成后验证:

#!/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_NAMEMAIN_CLASS
  4. 多租户支持: 通过TENANT_ID参数支持共享实例和VIP专属实例
  5. 权限控制: 确保bin目录脚本具有可执行权限(755)
  6. 验证机制: 构建后使用验证脚本检查包完整性
  7. 部署目录管理: 所有部署包统一存储在项目根目录deploy/下,实现开发与部署物理分离
  8. CI/CD集成: 部署目录结构便于自动化部署和版本发布管理