乐趣区

撸一个Java脚手架一统团队项目结构风格

虽然 maven 已经提供了 maven-archetype-webapp、maven-archetype-quickstart 等项目骨架帮助我们快速构建项目架构,但是默认提供的 archetype 初始化的项目架构并不能满足开发需求,这时候就有必要自己写一个满足项目需求的 archetype 了

使用自定义 archrtype 生成的项目结构图

为了激发阅读兴趣,先放一张使用自定义 archetype 生成项目的项目结构图

基本上的类都是 archetype 生成的

archetype 是什么

可以简单的理解为模板工具类,通过 archetype 我们可以快速的生成项目的基本架构。比如我们使用 idea 创建一个 maven web 项目时,常常会选择 maven-archetype-webapp 模板来初始化项目,使用 maven-archetype-webapp 生成的项目中包括 webapp 目录,里面包含 web 的配置文件

archetype 的组成

要想写一个自定义archetype,首先得知道一个 archetype 的组成。archetype 由四部分组成:

  • prototype files 原型文件

位于 src/main/resources/archetype-resource 目录下。prototype files 原型文件可以理解为多模块中的子模块或是单模块工程中的源文件 [即 src 文件]。这些原型文件在使用对应archetype 生成项目时被生成

  • archetype-metadata.xml

位于 src/main/resources/META-INF/maven/ 目录下。该配置文件中主要列出了原型文件以及使用 archetype 生成模板工程需要的参数

  • prototype pom

位于 src/main/resources/archetype-resources 目录下。这个 pom 文件会出现在 archetype 创建的模板工程中,如果是单模块工程,则是对整个项目的依赖管理;如果是多模块工程,该 pom 是总 pom 文件,该文件中会定义项目的子模块以及对子模块的依赖进行管理等,子模块 pom 定义在子模块下,子模块 pom 文件只管理子模块的依赖。

  • archetype pom
    位于自定义 archetype 工程的根目录下。这是 archetype 工程项目的 pom 文件,里面一般没什么东西,不会出现在 archetype 创建的模板工程中

superman[自定义 archetype]结构说明

  • superman项目结构图


包含了 archetype 的四个组成部分,两个 pom 文件,一个 archtype-metadata 文件和五个原型文件 [__rootArtifactId__-*],其中__rootArtifactId__ 在生成模板工程时会被传入的值替代

  • archtype-metadata 配置文件

    • 1. 定义使用 archetype 生成模板工程需要传入的参数

      <!-- 需要输入的属性 -->
          <requiredProperties>
              <requiredProperty key="groupId">
                  <!-- 默认的 groupId-->
                  <defaultValue>com.h2t.test</defaultValue>
              </requiredProperty>
              <requiredProperty key="artifactId">
                  <!-- 默认的 artifactId-->
                  <defaultValue>demo</defaultValue>
              </requiredProperty>
              <requiredProperty key="package">
                  <!-- 默认的包名和 groupId 一样 -->
                  <defaultValue>${groupId}</defaultValue>
              </requiredProperty>
          </requiredProperties>

      ${}标识的变量都是通过 maven 中的命令行传进来的

    • 2. 定义原型文件

          <module id="${rootArtifactId}-web" name="${rootArtifactId}-web" dir="__rootArtifactId__-web">
                  <fileSets>
                      <fileSet filtered="true" encoding="UTF-8" packaged="true">
                          <directory>src/main/java</directory>
                          <includes>
                              <include>**/*.*</include>
                          </includes>
                      </fileSet>
                      <fileSet filtered="true" encoding="UTF-8" packaged="true">
                          <directory>src/test/java</directory>
                          <includes>
                              <include>**/*.*</include>
                          </includes>
                      </fileSet>
                      <fileSet encoding="UTF-8">
                          <directory>src/main/resources</directory>
                          <includes>
                              <include>**/*.*</include>
                          </includes>
                      </fileSet>
                      <fileSet encoding="UTF-8">
                          <directory>src/test/resources</directory>
                          <includes>
                              <include>**/*.*</include>
                          </includes>
                      </fileSet>
                  </fileSets>
              </module>

      module属性介绍:
      id:子模块工程的 artifactId
      dir:子模块工程源文件在archetype-resources 里对应的directory

name:子模块的名字.

  • prototype pom 文件

    • 1. 定义了五个子模块

          <!-- 项目子模块 -->
          <modules>
              <module>${rootArtifactId}-common</module>
              <module>${rootArtifactId}-dao</module>
              <module>${rootArtifactId}-service</module>
              <module>${rootArtifactId}-web</module>
              <module>${rootArtifactId}-model</module>
          </modules>
    • 子模块依赖版本统一管理

      <dependencyManagement>
                  <!--modules-->
                  <dependency>
                      <groupId>${groupId}</groupId>
                      <artifactId>${rootArtifactId}-common</artifactId>
                      <version>${version}</version>
                  </dependency>
      
                  <dependency>
                      <groupId>${groupId}</groupId>
                      <artifactId>${rootArtifactId}-dao</artifactId>
                      <version>${version}</version>
                  </dependency>
      
                  <dependency>
                      <groupId>${groupId}</groupId>
                      <artifactId>${rootArtifactId}-service</artifactId>
                      <version>${version}</version>
                  </dependency>
      
                  <dependency>
                      <groupId>${groupId}</groupId>
                      <artifactId>${rootArtifactId}-model</artifactId>
                      <version>${version}</version>
                  </dependency>
              </dependencies>
          </dependencyManagement>

      子模块所需依赖都定义在该 pom 中,子模块使用依赖时不需要 <version> 标签

  • 原型文件以 web 模块说明


就是一个简单的 maven 工程,里面写了使用 archetype 生成模板项目的类


附:superman archetype 代码


快速开始【superman archetype 使用指南】

  • 1. 下载源码

    git clone https://github.com/TiantianUpup/superman.git
  • 2. 打开 superman 工程,将其安装到本地仓库

运行如下命令

mvn clean install
  • 3. 使用自定义 archetype 初始化项目

    mvn archetype:generate 
    -DgroupId=com.h2t.test 
    -DartifactId=superman-demo 
    -Dversion=1.0.0-SNAPSHOT 
    -DarchetypeGroupId=com.h2t.study 
    -DarchetypeArtifactId=superman -DarchetypeVersion=0.0.1-SNAPSHOT -X -DarchetypeCatalog=local

    参数说明
    -DgroupId组 ID,默认项目的包名的组 ID 相同
    DartifactId:项目唯一标识符,即项目名称
    -DarchetypeGroupId:superman 的组 ID,值不需要进行修改

-DarchetypeArtifactId:superman 的 artifactId,值不需要进行改变

  • 4. 移动配置文件

因为使用 archetype 生成项目时会将 resource 下面的文件丢失,所以目前将配置文件放在了 web 模块下的 resource 包下,创建项目成功后需手动将文件移动到 web 模块下的 resource 文件夹下,并将 resource 文件成标记成Resources Root

  • 5. 修改 resource 文件夹下的配置文件

该文件夹下有 application.propertieslogback.propertieslogback-spring.xml 三个配置文件

  • application.properties配置文件的修改

application.properties 主要是 SpringMyBatisPlus 和数据库的配置信息

spring.datasource.url=jdbc:mysql://localhost:3306/your_database?characterEncoding=UTF8&serverTimezone=UTC
spring.datasource.username=root
spring.datasource.password=your password
修改数据库、密码,默认用户名为 `root`
```
mybatis-plus.mapper-locations=classpath*:/mapper/*.xml  
# mybatis-plus.type-aliases-package=
```
指定 `MybatisPlus` 实体类别名的包,即 `model` 模块的 `po` 层包名,默认 `MybatiPlus` 的 `mapper` 文件保存在 `resource` 下的 `mapper` 文件夹下,可自行修改
  • logback.properties配置文件的修改

logback.properties定义了 error 级别日志和 info 级别日志的保存地址

LOG_ERROR_HOME=  
LOG_INFO_HOME=
  • logback-spring.xml配置文件的修改

logback-spring.xml主要是日志输出规则的定义,若为 windows 系统无需进行修改,若为 linux osmac os,则需修改日志保存地址

    <fileNamePattern>${LOG_ERROR_HOME}//%d.log</fileNamePattern>
将 `//` 修改为 `/`
  • 6 使用代码生成器生成 controllerservicedaopo 层代码

代码生成器类位于 service 模块下的 generator 包下,只需要初始化几个字段值运行就可以生成相应的代码。在运行前首先在项目根目录下创建一个 mp-generator-output 文件夹,该文件夹的名字和 OUTPUT_DIR 字段值保持一致

  • PACKAGE_NAME

生成代码的包名,和项目的包名一致,负责复制过去代码会有一些小问题
OUTPUT_DIR
生成代码保存文件地址,默认保存在项目下的mp-generator-output 文件夹下,可以修改为自定义保存地址

  • AUTHOR

注释中作者的名字

  • DRIVER_NAME

数据库驱动

  • HOST

数据库主机号

  • PORT

数据库端口

  • DATABASE

数据库名字

  • USERNAME

数据库用户名

  • PASSWORD

数据库密码

  • 7. 将生成的代码移动到对应模块对应包下

    • controller文件夹

实体类对应的 Controller,将该目录下的类移到web 模块下的 controller 包下

  • mapper文件夹

实体类对应的 DAO 层,该目录下包含 xml 文件和对应实体的接口类,将 xml 文 件移到 dao 模块 resource 下的mapper 文件夹下,需自行建立 mapper 文件夹,将接口移到 dao 模块下的 mapper 包下并在接口类上添加 @Mapper 注解,需自行建立 mapper包。同时将 resource 文件夹标记成Resources root

  • service 对应实体类接口

    - `impl` 对应实体类接口实现类
    
将 `service` 目录下的接口移到 `service` 模块下的 `service` 包下,`impl` 目录下的类移到 `service` 模块下的 `service.impl` 包下
  • po 文件夹

将该目录下的类移到 model 模块下的 po 包下,并修改继承关系,统一继承 BasePO 类,因为 BasePO 类 包含了 idgmtCreategmtModifieddeleted 这些数据库基本字段,需将生成的实体类手动删除这些重复字段。同时自动生成的 po 类缺失了 @TableName@TableField 注解需手动补充。注解的使用方式可参考 BasePO

  • 8. 修改 web 模块 aspect 包下的环绕通知

    @Around("execution(* yourpackage.controller..*(..))")

    该切面主要用于拦截 controller 层返回的结果,将其封装成统一结果返回

  • 9 启动项目

web模块下的 Runner 类为启动类,运行该类即可启动,默认端口为 8081


附:superman archetype 生成 demo 工程地址

欢迎 fork 与 star[划重点],由于开发经验有限,有些地方可能考虑不周,欢迎提 bug。并且该 archetype 只定义了一些基础功能,欢迎提需求。


退出移动版