<link rel="stylesheet" href="https://csdnimg.cn/release/blogv2/dist/mdeditor/css/editerView/kdoc_html_views-1a98987dfd.css">
    <link rel="stylesheet" href="https://csdnimg.cn/release/blogv2/dist/mdeditor/css/editerView/ck_htmledit_views-25cebea3f9.css">
            <div id="content_views" class="htmledit_views">
                <p id="main-toc"><strong>目录</strong></p> 

一、前言

1.1 为什么需要掌握多模块打包

二、工程模块概述

2.1 前后端不分离

2.2 部署方式多样化

2.3 单模块向多模块演进

三、单模块打包构建

3.1 环境准备

3.1.1 创建测试用的单模块工程

3.1.2 多环境配置文件

3.1.3 新增测试接口

3.2 pom配置详解

3.2.1 添加基础依赖

3.2.2 多环境配置

3.2.3 包含工程目录中的其他配置文件

3.2.4 打包验证

3.3 pom关键标签说明

四、多模块打包构建

4.1 拆分目标

4.2 各模块依赖管理

4.2.1 根pom依赖

4.2.2 pt-dao 模块

4.2.3 pt-service模块

4.2.4 pt-web 模块

4.2.5 接口测试

4.2.6 修改web模块打包文件文件

4.2.7 构建最终的jar包

4.3 springboot 打包插件补充

4.3.1 指定打包目录

4.3.2 指定主启动类

五、写在文末


一、前言

项目打包是项目进行服务器部署的最后一关,对于一个springboot项目来说,功能开发完成后,需要将代码编译、打包、并部署到服务器上进行验证和测试,以maven为例,使用大家熟悉的mvn命令即可完成本地的打包构建,但事实上真的这么简单吗?

1.1 为什么需要掌握多模块打包

很多同学在开发过程中并不关心项目最终是如何发布到服务器上的,因为工程中关于打包的配置文件繁琐并且零碎,基本上来说,项目的框架搭建完成之后,后面再也不会改动了,所以开发人员只需要在完成开发之后,使用maven命令进行打包就好了,问题是,假如后续在工程模块中增添或删减了某些文件,再次打包时可能就会出现意想不到的问题,如果没有对项目打包构建有一定的储备,很难排查问题,给整个项目的推进带来效率问题。

其次,关于模块打包,涉及到的点比较多,尤其是关于打包的配置、插件等,平时开发中几乎不涉及,但是在某些场景下一旦合理运用,可以解决很多意想不到的问题,因此有必要系统全面的了解和掌握关于模块打包的操作实践。

二、工程模块概述

以Java项目的工程模块为例进行说明,从早期的前后端一个工程搞定,到今天普遍使用的前后端分离的模式,从早期流行的承载式tomcat容器部署到如今更简洁的jar包部署,不同的事情,不同的工程部署模式,也为项目在最终打包构建的模式上带来了不同的变化。

2.1 前后端不分离

早些年像一些jsp的项目比较喜欢在一个工程中同时做前后端的代码开发,最终需要打包部署到tomcat上运行。而前后端分离之后,打包相关的配置文件中就不用再理会前端的文件,从后端的角度讲,部署的方式叶更灵活了,不仅可以使用war包部署到tomcat,也可以使用其他的容器像jetty,嵌入式tomcat以运行jar的方式部署。

2.2 部署方式多样化

当前后端分离的模式主键被很多互联网公司开始使用后,项目部署的方式叶更灵活,war,或jar都可以,承载式tomcat或嵌入式容器,为了满足部署中越来越灵活的需求,工程中的各种文件和配置也需要在构建打包时进行更多多样化的定制,从这个角度讲,对于工程模块打包构建的要求也主键增高。

2.3 单模块向多模块演进

为了快速响应业务的变化,很多公司在起步时往往采用单体或单模块的工程目录,这样的好处就是开发快速,打包部署简单,出了问题容易定位排查,但是随着业务的逐渐壮大,以及团队规模的增加,项目必然面临服务化的改造,改造中为了更好的管控工程代码,一般都会面临多模块的拆分,一旦涉及到拆分,必然需要重新规划和设计多模块的打包部署方式。

三、单模块打包构建

下面以一个实际案例进行说明,将对单模块的maven项目涉及到打包相关的技术点进行详细的阐述。

3.1 环境准备

3.1.1 创建测试用的单模块工程

创建一个maven项目,为单模块工程,目录结构如下:

关于工程及各模块说明:

  • controller,对外接口的class包目录;
  • service,核心业务实现类包目录;
  • entity,数据库实体对象包目录;
  • dao,操作数据库增删改查相关的接口类目录;
  • mybatis,操作数据的xml文件目录;
  • static,存放静态资源的目录;
  • application配置文件;
  • logback,日志文件;

3.1.2 多环境配置文件

开发过程中,为了区分不同的环境,可以在resources目录下创建多个配置文件,以dev,prod等结尾命名,然后利用配置激活的方式让具体某个配置文件生效,比如在上面的目录中,我们创建了3个配置文件,分别为:

  • application.yml,
  • application-dev.yml,
  • application-pro.yml,
  • -dev为开发中使用的配置,-pro为生产环境使用;

三个配置文件主要内容如下: 

application.yml

该配置文件一般配置一些公共的信息,比如mybatis的配置等


 
 
  1. spring:
  2. profiles:
  3. active: dev

application-dev.yml

该配置文件为开发环境使用的配置


 
 
  1. server:
  2. port: 8082
  3. spring:
  4. #数据库连接配置
  5. datasource:
  6. url: jdbc:mysql: //IP:3306/biz-db?&useSSL=false
  7. driver-class-name: com.mysql.jdbc.Driver
  8. username: root
  9. password: root
  10. people:
  11. username: devuser
  12. password: 123456
  13. # mybatis配置
  14. mybatis:
  15. mapper-locations: classpath:mybatis /*.xml
  16. type-aliases-package: com.congge.entity
  17. configuration:
  18. map-underscore-to-camel-case: true
  19. # showSql 控制台打印sql日志
  20. logging:
  21. level:
  22. com:
  23. congge:
  24. dao: debug

application-pro.yml

该配置文件为生产环境使用的配置


 
 
  1. server:
  2. port: 8083
  3. spring:
  4. people:
  5. username: prouser
  6. password: 123456

3.1.3 新增测试接口

为了后面验证效果,在工程中增加一个测试的接口,从接口到实现依次如下:

UserController


 
 
  1. @RequestMapping("/user")
  2. @RestController
  3. public class UserController {
  4. @Autowired
  5. private PeopleInfo peopleInfo;
  6. @Autowired
  7. private UserService userService;
  8. //localhost:8082/user/getById?id=001
  9. @GetMapping("/getById")
  10. public User getById (@RequestParam String id){
  11. System.out.println(peopleInfo.getUsername() + " --- " + peopleInfo.getPassword());
  12. return userService.getById(id);
  13. }
  14. }

UserService


 
 
  1. @Service
  2. public class UserService {
  3. @Autowired
  4. private UserDao userDao;
  5. public User getById (String userId){
  6. return userDao.selectById(userId);
  7. }
  8. }

3.2 pom配置详解

3.2.1 添加基础依赖

以springboot+mybatis+mysql为例进行说明,导入如下基本的jar


 
 
  1. <dependencies>
  2. <dependency>
  3. <groupId>org.springframework.boot</groupId>
  4. <artifactId>spring-boot-starter-web</artifactId>
  5. </dependency>
  6. <dependency>
  7. <groupId>org.projectlombok</groupId>
  8. <artifactId>lombok</artifactId>
  9. <version> 1.18 .8</version>
  10. <scope>provided</scope>
  11. </dependency>
  12. <dependency>
  13. <groupId>org.slf4j</groupId>
  14. <artifactId>slf4j-api</artifactId>
  15. <version> 1.7 .25</version>
  16. </dependency>
  17. <dependency>
  18. <groupId>ch.qos.logback</groupId>
  19. <artifactId>logback-classic</artifactId>
  20. <version> 1.2 .10</version>
  21. </dependency>
  22. <dependency>
  23. <groupId>mysql</groupId>
  24. <artifactId>mysql-connector-java</artifactId>
  25. <version> 5.1 .46</version>
  26. </dependency>
  27. <!-- 集成mybatis -->
  28. <dependency>
  29. <groupId>org.mybatis.spring.boot</groupId>
  30. <artifactId>mybatis-spring-boot-starter</artifactId>
  31. <version> 1.3 .1</version>
  32. </dependency>
  33. <!-- druid数据库连接池组件 -->
  34. <dependency>
  35. <groupId>com.alibaba</groupId>
  36. <artifactId>druid-spring-boot-starter</artifactId>
  37. <version> 1.1 .10</version>
  38. </dependency>
  39. </dependencies>

3.2.2 多环境配置

在maven项目中,为了能够方便的切换多环境配置,需要在根pom中引入profiles标签,以上述的工程配置为例,假如这里需要在dev环境生效,pom中添加的配置如下,如果还有更多的环境,在外层的profiles标签中添加新的profile标签即可;


 
 
  1. <!-- 多环境配置 -->
  2. <profiles>
  3. <profile>
  4. <id>dev</id>
  5. <activation>
  6. <!-- 是否默认启用 -->
  7. <activeByDefault> true</activeByDefault>
  8. </activation>
  9. <properties>
  10. <!-- 环境标签变量,在yaml中会被用到 -->
  11. <environment>dev</environment>
  12. </properties>
  13. </profile>
  14. <profile>
  15. <id>pro</id>
  16. <activation>
  17. <activeByDefault> false</activeByDefault>
  18. </activation>
  19. <properties>
  20. <environment>pro</environment>
  21. </properties>
  22. </profile>
  23. </profiles>

3.2.3 包含工程目录中的其他配置文件

一般来说,我们希望打出来的包可以直接运行,比如这里最终打出来的包作为一个jar包,业务逻辑中需要用到resources目录下的所有文件,因此需要在打包的时候将这些配置文件全部包含进去,此时只需要在pom中通过标签进行包含即可,涉及到的主要标签就是resources,具体添加的配置文件如下:


 
 
  1. <build>
  2. <resources>
  3. <!-- 将所有application开头的yaml文件排除,可以排除多个 -->
  4. <resource>
  5. <directory>src/main/resources</directory>
  6. <excludes>
  7. <exclude>application*.yml</exclude>
  8. </excludes>
  9. </resource>
  10. <!-- 根据激活条件引入打包所需的配置文件,可以引入多个 -->
  11. <resource>
  12. <directory>src/main/resources</directory>
  13. <filtering> true</filtering>
  14. <includes>
  15. <include>application.yml</include>
  16. <include>application-${environment}.yml</include>
  17. <include>logback.xml</include>
  18. <include>mybatis /*.xml</include>
  19. </includes>
  20. </resource>
  21. </resources>
  22. <plugins>
  23. <plugin>
  24. <groupId>org.springframework.boot</groupId>
  25. <artifactId>spring-boot-maven-plugin</artifactId>
  26. </plugin>
  27. </plugins>
  28. </build>

3.2.4 打包验证

执行完成上述的操作后,通过maven命令进行打包构建,完成后通过解压包可以看到这个包包含了运行需要的所有文件,即上面的resources标签中包含的文件,以及运行时依赖的jar;

本地直接通过java -jar命令,就可以直接启动并运行这个jar包

3.3 pom关键标签说明

通过上面的案例初步了解了基于springboot的单模块工程进行maven打包构建的基本步骤,为了对maven打包相关的技术点有更深入的了解,这里对pom文件中常见的几个标签做一个详细的说明。

四、多模块打包构建

随着项目的服务化拆分,单模块必然会向多模块演变,多模块拆分之后,从模块管理、依赖管理、打包构建等,相对单模块来说,都会变得越来越复杂,但这也是必须要面对的过程,仍然以上述的单模块工程为例,将其进行拆分成多个子模块(或者是多个单模块工程);

4.1 拆分目标

将上述单模块拆成为3个子模块,分别为:

  • pt-dao,存放数据库映射实体对象以及与数据库交互的接口类;
  • pt-service,核心业务实现模块;
  • pt-web,对外的rest-api模块;

4.2 各模块依赖管理

4.2.1 根pom依赖

在多模块的项目中,为了统一管理各模块的jar包依赖版本,在pom文件中引入 dependencyManagement 这个标签,在标签内部引入各个模块中需要依赖的jar包,这样子模块中就不需要再单独定义某个依赖jar的版本了。


 
 
  1. <parent>
  2. <groupId>org.springframework.boot</groupId>
  3. <artifactId>spring-boot-starter-parent</artifactId>
  4. <version> 2.3 .2.RELEASE</version>
  5. <relativePath/>
  6. </parent>
  7. <!--统一定义版本号-->
  8. <properties>
  9. <lomok.version> 1.18 .8</lomok.version>
  10. <slf4j.version> 1.7 .25</slf4j.version>
  11. <logback.version> 1.2 .10</logback.version>
  12. <mysql.version> 5.1 .46</mysql.version>
  13. <mybatis.version> 1.3 .1</mybatis.version>
  14. <druid.version> 1.1 .10</druid.version>
  15. </properties>
  16. <!--统一版本依赖管理-->
  17. <dependencyManagement>
  18. <dependencies>
  19. <dependency>
  20. <groupId>org.springframework.boot</groupId>
  21. <artifactId>spring-boot-starter-web</artifactId>
  22. </dependency>
  23. <dependency>
  24. <groupId>org.projectlombok</groupId>
  25. <artifactId>lombok</artifactId>
  26. <version>${lomok.version}</version>
  27. <scope>provided</scope>
  28. </dependency>
  29. <dependency>
  30. <groupId>org.slf4j</groupId>
  31. <artifactId>slf4j-api</artifactId>
  32. <version>${slf4j.version}</version>
  33. </dependency>
  34. <dependency>
  35. <groupId>ch.qos.logback</groupId>
  36. <artifactId>logback-classic</artifactId>
  37. <version>${logback.version}</version>
  38. </dependency>
  39. <dependency>
  40. <groupId>mysql</groupId>
  41. <artifactId>mysql-connector-java</artifactId>
  42. <version>${mysql.version}</version>
  43. </dependency>
  44. <dependency>
  45. <groupId>org.mybatis.spring.boot</groupId>
  46. <artifactId>mybatis-spring-boot-starter</artifactId>
  47. <version>${mybatis.version}</version>
  48. </dependency>
  49. <dependency>
  50. <groupId>com.alibaba</groupId>
  51. <artifactId>druid-spring-boot-starter</artifactId>
  52. <version>${druid.version}</version>
  53. </dependency>
  54. <dependency>
  55. <groupId>com.congge</groupId>
  56. <artifactId>pt-dao</artifactId>
  57. <version> 1.0-SNAPSHOT</version>
  58. </dependency>
  59. <dependency>
  60. <groupId>com.congge</groupId>
  61. <artifactId>pt-service</artifactId>
  62. <version> 1.0-SNAPSHOT</version>
  63. </dependency>
  64. <dependency>
  65. <groupId>com.congge</groupId>
  66. <artifactId>pt-web</artifactId>
  67. <version> 1.0-SNAPSHOT</version>
  68. </dependency>
  69. </dependencies>
  70. </dependencyManagement>

4.2.2 pt-dao 模块

该模块,主要是定义实体类,以及dao文件,因此需要把mybatis相关的依赖引入,可以看到在子模块中,只需要引入根pom中的jar的版本号即可,后续当整个工程需要对jar进行升级的时候只需修改根pom中的版本号即可。


 
 
  1. <dependencies>
  2. <dependency>
  3. <groupId>org.projectlombok</groupId>
  4. <artifactId>lombok</artifactId>
  5. <version>${lomok.version}</version>
  6. <scope>provided</scope>
  7. </dependency>
  8. <dependency>
  9. <groupId>mysql</groupId>
  10. <artifactId>mysql-connector-java</artifactId>
  11. <version>${mysql.version}</version>
  12. </dependency>
  13. <dependency>
  14. <groupId>org.mybatis.spring.boot</groupId>
  15. <artifactId>mybatis-spring-boot-starter</artifactId>
  16. <version>${mybatis.version}</version>
  17. </dependency>
  18. </dependencies>

添加配置文件

需要将连接数据库相关的配置文件迁移到当前的模块resources目录下

模块安装

pt-service模块以及后续其他模块中需要引用pt-dao中的类,需要将其以jar包形式发布到仓库中,直接使用 mvn install即可,得到如下的文件

4.2.3 pt-service模块

该模块主要为业务实现相关,引入如下基本依赖,这里需要将上述安装到本地仓库中的pt-dao的jar引入;


 
 
  1. <dependencies>
  2. <dependency>
  3. <groupId>org.springframework.boot</groupId>
  4. <artifactId>spring-boot-starter-web</artifactId>
  5. </dependency>
  6. <!--引入对dao的依赖-->
  7. <dependency>
  8. <groupId>com.congge</groupId>
  9. <artifactId>pt-dao</artifactId>
  10. </dependency>
  11. </dependencies>

将业务实现类UserService迁移过来,如果你的service模块还有其他的配置文件,可以继续添加;

4.2.4 pt-web 模块

该模块主要提供对外的rest-api,导入基础依赖,由于web模块需要调用service模块的方法,所以引入service模块的依赖坐标;


 
 
  1. <dependencies>
  2. <dependency>
  3. <groupId>org.springframework.boot</groupId>
  4. <artifactId>spring-boot-starter-web</artifactId>
  5. <version>${boot-web.version}</version>
  6. </dependency>
  7. <dependency>
  8. <groupId>com.congge</groupId>
  9. <artifactId>pt-service</artifactId>
  10. </dependency>
  11. </dependencies>

4.2.5 接口测试

上面的步骤全部做完后,启动web工程

启动完成后,浏览器调用上述的测试接口,可以看到能够正常查询到数据库数据;

 到这里,一个多模块的项目就搭建完成,那么如何进行打包并放到服务器部署呢?

4.2.6 修改web模块打包文件文件

一般来说,springboot工程最终打成一个jar包即可,做法也比较简单,这里提供一种最简单的方式,只需要在web模块的pom文件中添加如下配置,即通过web模块来构建最终的jar包,和单模块类似,在resources标签中将需要打包到最终jar包中的文件包含进去;


 
 
  1. <!--多模块打包:只需在启动类所在模块的POM文件:指定打包插件 -->
  2. <build>
  3. <plugins>
  4. <plugin>
  5. <!--该插件主要用途:构建可执行的JAR -->
  6. <groupId>org.springframework.boot</groupId>
  7. <artifactId>spring-boot-maven-plugin</artifactId>
  8. <executions>
  9. <execution>
  10. <goals>
  11. <!--可以把依赖的包都打包到生成的Jar包中-->
  12. <goal>repackage</goal>
  13. </goals>
  14. </execution>
  15. </executions>
  16. </plugin>
  17. </plugins>
  18. <resources>
  19. <!-- 根据激活条件引入打包所需的配置文件,可以引入多个 -->
  20. <resource>
  21. <directory>src/main/resources</directory>
  22. <filtering> true</filtering>
  23. <includes>
  24. <include>application.yml</include>
  25. <include>logback.xml</include>
  26. <include> static/help.txt</include>
  27. </includes>
  28. </resource>
  29. </resources>
  30. </build>

4.2.7 构建最终的jar包

通过maven命令,或者在idea下面的总工程的位置通过点击package进行打包

打包完成后,进入到web模块下,可以看到构建完成的最终jar包,通过java -jar命令即可启动服务;

4.3 springboot 打包插件补充

4.3.1 指定打包目录

spring-boot-maven-plugin这个插件并非maven自身的插件,而是springboot自带的插件,是为了方便开发者快速构建包的时候引用,关于这个插件,这里再补充一个小功能,就是指定最终的打包文件所在目录,这个对于自动化构建时很有用,方便编写脚本时快速定位到打包的文件目录,只需在里面添加如下配置即可:

4.3.2 指定主启动类

我们知道springboot工程启动的时候其入口就是main的主程序,事实上在多模块开发中,可能你的项目并非像我这样的聚合工程,比如web模块和service模块各自独立,那么service模块自身也可能最终作为一个java进程运行在服务器上,此时,如果在web模块打出的jar中不指定启动类可能会引发其他的问题,此时,只需要在spring-boot-maven-plugin这个插件坐标中像下面这样指定一下主启动类即可;


 
 
  1. <plugin>
  2. <groupId>org.springframework.boot</groupId>
  3. <artifactId>spring-boot-maven-plugin</artifactId>
  4. <configuration>
  5. <!-- 指定该Main Class为全局的唯一入口 -->
  6. <mainClass>com.congge.MultiApp</mainClass>
  7. <layout>ZIP</layout>
  8. </configuration>
  9. <executions>
  10. <execution>
  11. <goals>
  12. <goal>repackage</goal><!--可以把依赖的包都打包到生成的Jar包中-->
  13. </goals>
  14. </execution>
  15. </executions>
  16. </plugin>

五、写在文末

关于springboot多模块构建打包的内容,涉及到的技术本身并不算复杂,但是这里却牵涉到很多与maven相关的技术点,比如maven的版本管理,依赖传递,父子模块继承,以及maven打包插件等众多的内容相互交织在一起,如果要搞清里面的关系,还需要对maven相关的技术做深入的了解和学习,而这些内容在实际开发过程中基本属于一劳永逸的事情,希望对看到的伙伴有用,本篇到此结束,感谢观看。

Logo

旨在为数千万中国开发者提供一个无缝且高效的云端环境,以支持学习、使用和贡献开源项目。

更多推荐