Skip to main content

创建项目/添加微服务git操作流程

说明:

1.创建group

gitlab创建gruop来管理整个项目(例如前端、后端项目),如果已存在,则跳过此步骤

  • git首页 --> Groups --> Yours groups --> New group

2. 创建总git库(父模块)

在创建好的group下,创建项目的总git库,用于管理各个微服务,然后拉取到本地,如果已存在,则跳过此步骤

  • 在创建好的group下 --> New project

3. 创建微服务git库(子模块)

在创建好的group下,创建需要添加的微服务git库

  • 在创建好的group下 --> New project

4. 创建快速生成微服务模块脚本

  • 在本地刚拉取的父工程目录下创建 generate-module.sh 文件,内容如下(此脚本用于快速生成微服务模版,方便快速开发):
#!/usr/bin/env bash

#
# 模块项目结构生成脚本
#

MODULE_VERSION="0.0.1-SNAPSHOT"
BASE_PACKAGE_NAME="cn.dxsuite"
PROJECT_PACKAGE_NAME="${BASE_PACKAGE_NAME}"

check_data_source_type () {
if ! [[ "$1" =~ ^(mysql|mongo|es)?$ ]]; then
printf "\e[91m数据源类型无效\e[0m\n\n"
exit 1
fi
}

check_package_name () {
if ! [[ "$1" =~ ^([a-z][0-9a-z]*\.)*[a-z][0-9a-z]*$ ]]; then
printf "\e[91m包名格式不正确\e[0m\n\n"
exit 1
fi
}

get_data_source_dependency () {
case "$1" in
mysql)
printf "\n api(\"cn.dxsuite.commons:commons-jpa:%s\")\n" "${MODULE_VERSION}"
;;
mongo)
printf "\n api(\"cn.dxsuite.commons:commons-mongo:%s\")\n" "${MODULE_VERSION}"
;;
es)
;;
esac
printf ""
}

# 设置模块名称
printf "\n\e[96m模块名称:\e[0m"
read -r MODULE_NAME

if ! [[ "${MODULE_NAME}" =~ ^([a-z][0-9a-z]*-)*[a-z][0-9a-z]*$ ]]; then
printf "\e[91m模块名应由英文小写字母、数字、横线组成,以英文开头,且不出现连续的横线\e[0m\n\n"
exit 1
fi

# 设置基础包名
printf "\e[96m基础包名\e[36m(默认:%s)\e[96m:\e[0m" "${BASE_PACKAGE_NAME}"
read -r BASE_PACKAGE_NAME_INPUT

if ! [ "${BASE_PACKAGE_NAME_INPUT}" == "" ]; then
BASE_PACKAGE_NAME="${BASE_PACKAGE_NAME_INPUT}"
PROJECT_PACKAGE_NAME="${BASE_PACKAGE_NAME}"
fi

check_package_name "${BASE_PACKAGE_NAME}"

# 设置项目包名
printf "\e[96m项目包名:\e[0m"
read -r PROJECT_PACKAGE_NAME_INPUT

if ! [ "${PROJECT_PACKAGE_NAME_INPUT}" == "" ]; then
PROJECT_PACKAGE_NAME="${BASE_PACKAGE_NAME}.${PROJECT_PACKAGE_NAME_INPUT}"
fi

check_package_name "${PROJECT_PACKAGE_NAME}"
PROJECT_PACKAGE_PATH="${PROJECT_PACKAGE_NAME//\.//}"

# 设置模块包名
MODULE_PACKAGE_NAME="${MODULE_NAME//-/}"
printf "\e[96m模块包名\e[36m(默认:%s)\e[96m:\e[0m" "${MODULE_PACKAGE_NAME}"
read -r PACKAGE_NAME_INPUT

if ! [ "${PACKAGE_NAME_INPUT}" == "" ]; then
MODULE_PACKAGE_NAME="${PACKAGE_NAME_INPUT}"
fi

check_package_name "${MODULE_PACKAGE_NAME}"
PACKAGE_PATH="${MODULE_PACKAGE_NAME//\.//}"

# 设置数据源类型
printf "\e[96m数据源类型\e[36m(mysql|mongo|es)\e[0m\n"
printf "\e[96m 命令领域:\e[0m"
read -r DATA_SOURCE_TYPE_COMMAND
check_data_source_type "${DATA_SOURCE_TYPE_COMMAND}"
printf "\e[96m 查询领域:\e[0m"
read -r DATA_SOURCE_TYPE_QUERY
check_data_source_type "${DATA_SOURCE_TYPE_QUERY}"

printf "\n\e[36m以下路径及文件将被创建:\e[0m\n"
printf "\n \e[1;92m%s\e[0;32m" "${MODULE_NAME}"
printf "\n ├─ \e[1;92m%s\e[0;32m" "${MODULE_NAME}"
printf "\n │ ├─ src/main"
printf "\n │ │ ├─ java/${PROJECT_PACKAGE_PATH}/\e[1;92m%s\e[0;32m/..." "${PACKAGE_PATH}"
printf "\n │ │ └─ resources"
printf "\n │ └─ build.gradle.kts"
printf "\n ├─ \e[1;92m%s\e[0;32m-command-api" "${MODULE_NAME}"
printf "\n │ ├─ src/main"
printf "\n │ │ ├─ java/${PROJECT_PACKAGE_PATH}/\e[1;92m%s\e[0;32m/command/..." "${PACKAGE_PATH}"
printf "\n │ │ └─ resources"
printf "\n │ └─ build.gradle.kts"
printf "\n ├─ \e[1;92m%s\e[0;32m-command" "${MODULE_NAME}"
printf "\n │ ├─ src/main"
printf "\n │ │ ├─ java/${PROJECT_PACKAGE_PATH}/\e[1;92m%s\e[0;32m/command/..." "${PACKAGE_PATH}"
printf "\n │ │ └─ resources"
printf "\n │ └─ build.gradle.kts"
printf "\n ├─ \e[1;92m%s\e[0;32m-query-api" "${MODULE_NAME}"
printf "\n │ ├─ src/main"
printf "\n │ │ ├─ java/${PROJECT_PACKAGE_PATH}/\e[1;92m%s\e[0;32m/query/..." "${PACKAGE_PATH}"
printf "\n │ │ └─ resources"
printf "\n │ └─ build.gradle.kts"
printf "\n ├─ \e[1;92m%s\e[0;32m-query" "${MODULE_NAME}"
printf "\n │ ├─ src/main"
printf "\n │ │ ├─ java/${PROJECT_PACKAGE_PATH}/\e[1;92m%s\e[0;32m/query/..." "${PACKAGE_PATH}"
printf "\n │ │ └─ resources"
printf "\n │ └─ build.gradle.kts"
printf "\n ├─ README.md"
printf "\n ├─ .editorconfig"
printf "\n ├─ .gitignore"
printf "\n ├─ settings.gradle.kts"
printf "\n └─ build.gradle.kts\e[0m\n"

printf "\n\e[96m确定要创建以上路径及文件吗?(确定:Y;取消:N)\e[0m"
read -r CONFIRM_INPUT

echo ""

if [ "${CONFIRM_INPUT}" != "Y" ] && [ "${CONFIRM_INPUT}" != "y" ]; then
printf "\e[33m已取消\e[0m\n\n"
exit 0
fi

# 清理已生成的目录结构
rm -rf "${MODULE_NAME:?}/${MODULE_NAME}"
rm -rf "${MODULE_NAME:?}/${MODULE_NAME}-command-api"
rm -rf "${MODULE_NAME:?}/${MODULE_NAME}-command"
rm -rf "${MODULE_NAME:?}/${MODULE_NAME}-query-api"
rm -rf "${MODULE_NAME:?}/${MODULE_NAME}-query"

# 构建项目目录结构
mkdir -p "${MODULE_NAME}"/{"${MODULE_NAME}","${MODULE_NAME}"-command-api,"${MODULE_NAME}"-command,"${MODULE_NAME}"-query-api,"${MODULE_NAME}"-query}/src/{main,test}/{java,resources}

# 构建共通模块项目源代码目录结构
mkdir -p "${MODULE_NAME}"/"${MODULE_NAME}"/src/{main,test}/java/"${PROJECT_PACKAGE_PATH}"/"${PACKAGE_PATH}"/{dto,entity,vo}

# 构建命令领域模块项目源代码目录结构
mkdir -p "${MODULE_NAME}"/"${MODULE_NAME}"-command-api/src/{main,test}/java/"${PROJECT_PACKAGE_PATH}"/"${PACKAGE_PATH}"/command/{api,dto,entity,vo}
mkdir -p "${MODULE_NAME}"/"${MODULE_NAME}"-command/src/{main,test}/java/"${PROJECT_PACKAGE_PATH}"/"${PACKAGE_PATH}"/command/{controller,repository,service,service/impl}

# 构建查询领域模块项目源代码目录结构
mkdir -p "${MODULE_NAME}"/"${MODULE_NAME}"-query-api/src/{main,test}/java/"${PROJECT_PACKAGE_PATH}"/"${PACKAGE_PATH}"/query/{api,dto,entity,vo}
mkdir -p "${MODULE_NAME}"/"${MODULE_NAME}"-query/src/{main,test}/java/"${PROJECT_PACKAGE_PATH}"/"${PACKAGE_PATH}"/query/{controller,repository,service,service/impl}

# 创建 Gradle 配置文件
touch "${MODULE_NAME}"/README.md
touch "${MODULE_NAME}"/.editorconfig
touch "${MODULE_NAME}"/.gitignore
touch "${MODULE_NAME}"/settings.gradle.kts
touch "${MODULE_NAME}"/build.gradle.kts
touch "${MODULE_NAME}"/"${MODULE_NAME}"/build.gradle.kts
touch "${MODULE_NAME}"/"${MODULE_NAME}"-command-api/build.gradle.kts
touch "${MODULE_NAME}"/"${MODULE_NAME}"-command/build.gradle.kts
touch "${MODULE_NAME}"/"${MODULE_NAME}"-query-api/build.gradle.kts
touch "${MODULE_NAME}"/"${MODULE_NAME}"-query/build.gradle.kts

# 设置 README.md 文件内容
echo "# ${MODULE_NAME}" > "${MODULE_NAME}"/README.md

# 设置 .editorconfig 文件内容
echo "root = true

[*]
charset = utf-8
indent_style = space
indent_size = 4
trim_trailing_whitespace = true
end_of_line = lf
insert_final_newline = true

[*.{css,scss,js,jsx,json}]
indent_size = 2

[*.{bat,cmd}]
end_of_line = crlf" > "${MODULE_NAME}"/.editorconfig

# 设置 .gitignore 文件内容
echo ".gradle
**/build
**/node_modules

**/*.log
**/*.log.gz
**/*.pid

.idea
**/*.iml
**/.classpath
**/.project
**/.settings
**/.vscode

**/.DS_Store
**/desktop.ini
**/Thumbs.db

**/~\$*.xlsx
**/~\$*.docx
**/~\$*.pptx

**/*.hprof" > "${MODULE_NAME}"/.gitignore

# 设置 settings.gradle.kts 配置文件
echo "rootProject.name = \"${MODULE_NAME}\"
include(\"${MODULE_NAME}\")
include(\"${MODULE_NAME}-command-api\")
include(\"${MODULE_NAME}-command\")
include(\"${MODULE_NAME}-query-api\")
include(\"${MODULE_NAME}-query\")" > "${MODULE_NAME}"/settings.gradle.kts

# 设置 build.gradle.kts 配置文件
echo "plugins {
id(\"java\")
id(\"java-library\")
id(\"maven-publish\")
id(\"idea\")
}

group = \"${PROJECT_PACKAGE_NAME}\"

allprojects {
apply(plugin = \"java\")
apply(plugin = \"java-library\")
apply(plugin = \"maven-publish\")
apply(plugin = \"idea\")

version = \"${MODULE_VERSION}\"

java {
sourceCompatibility = JavaVersion.VERSION_1_8
targetCompatibility = JavaVersion.VERSION_1_8
}

idea {
module {
isDownloadJavadoc = true
isDownloadSources = true
}
}
}

subprojects {
group = \"${PROJECT_PACKAGE_NAME}.${MODULE_NAME}\"

repositories {
mavenLocal()
if (hasProperty(\"dxsuite.nexus.url\")) {
maven {
url = uri(property(\"dxsuite.nexus.url\") as String)
credentials {
username = property(\"dxsuite.nexus.username\") as String
password = property(\"dxsuite.nexus.password\") as String
}
}
}
mavenCentral()
}

dependencies {
annotationProcessor(\"javax.annotation:javax.annotation-api:1.3.2\")
annotationProcessor(\"org.springframework.boot:spring-boot-configuration-processor:2.4.5\")
annotationProcessor(\"org.projectlombok:lombok:1.18.18\")
annotationProcessor(\"com.querydsl:querydsl-apt:4.4.0:jpa\")
testImplementation(\"cn.dxsuite.commons:commons-junit:0.0.1-SNAPSHOT\");
}

tasks {
withType(Test::class) {
useJUnitPlatform()
}
getByName<Jar>(\"jar\") {
enabled = true
duplicatesStrategy = DuplicatesStrategy.INCLUDE
archiveClassifier.set(\"resources\")
from(sourceSets.main.get().resources) {
include(\"**/*\")
}
}
}

publishing {
publications {
create<MavenPublication>(\"mavenJava\") {
from(components[\"java\"])
}
}
}
}

publishing {
publications {
create<MavenPublication>(\"mavenJava\") {
}
}
}" > "${MODULE_NAME}"/build.gradle.kts

# 设置 {MODULE_NAME}/{MODULE_NAME}/build.gradle.kts 配置文件
echo "dependencies {
api(\"${BASE_PACKAGE_NAME}.commons:commons-core:${MODULE_VERSION}\")
}" > "${MODULE_NAME}"/"${MODULE_NAME}"/build.gradle.kts

# 设置 {MODULE_NAME}/{MODULE_NAME}-command-api/build.gradle.kts 配置文件
echo "dependencies {$(get_data_source_dependency "${DATA_SOURCE_TYPE_COMMAND}")
api(\"${PROJECT_PACKAGE_NAME}.${MODULE_NAME}:${MODULE_NAME}:${MODULE_VERSION}\")
}" > "${MODULE_NAME}"/"${MODULE_NAME}"-command-api/build.gradle.kts

# 设置 {MODULE_NAME}/{MODULE_NAME}-command/build.gradle.kts 配置文件
echo "dependencies {
implementation(\"${PROJECT_PACKAGE_NAME}.${MODULE_NAME}:${MODULE_NAME}-command-api:${MODULE_VERSION}\")
}" > "${MODULE_NAME}"/"${MODULE_NAME}"-command/build.gradle.kts

# 设置 {MODULE_NAME}/{MODULE_NAME}-query-api/build.gradle.kts 配置文件
echo "dependencies {$(get_data_source_dependency "${DATA_SOURCE_TYPE_QUERY}")
api(\"${PROJECT_PACKAGE_NAME}.${MODULE_NAME}:${MODULE_NAME}:${MODULE_VERSION}\")
}" > "${MODULE_NAME}"/"${MODULE_NAME}"-query-api/build.gradle.kts

# 设置 {MODULE_NAME}/{MODULE_NAME}-query/build.gradle.kts 配置文件
echo "dependencies {
implementation(\"${PROJECT_PACKAGE_NAME}.${MODULE_NAME}:${MODULE_NAME}-query-api:${MODULE_VERSION}\")
}" > "${MODULE_NAME}"/"${MODULE_NAME}"-query/build.gradle.kts

printf "\e[36m完成\e[0m\n\n"
  • 执行以下命令,根据提示输入微服务模块名称完成微服务模块创建
# 将文件设置可执行
chmod +x ./generate-module.sh

# 创建微服务 根据提示输入微服务名称,最后确认完成创建
./generate-module.sh

5. 将本地微服务文件于远端git库关联

  • 进入刚创建的文服务文件夹,然后执行以下命令初始化git仓库
# 初始化git
git init

# 使本地文件夹与远端git仓库关联
git remote add origin git@gitlab.dxsuite.cn:git-test/git-sub-project.git

#拉取远程线上代码
git pull origin master

# 将当前改动进行提交
git add .

# 提交全部并加上注释
git commit -am 'project-init'

# 把所有的东西都推送到远程服务器上
git push --set-upstream origin master

6. 将新建微服务添作为子模块添加到上面的父模块git下

# 返回到项目工程根目录下,执行 git submodule add <子项目git url 子项目本地路径>
# 例如:
git submodule add git@gitlab.xxx.git ./sub-module

7. 最后推送到远端服务器即可

# 提交全部并加上注释
git commit -am 'init'

# 推送远端
git push