创建项目

创建一个 SpringBoot 项目非常的简单,简单到这里根本不用再提。你可以在使用 IDEA 新建项目时直接选择 Spring Initlalize 创建一个 Spring Boot 项目,也可以使用 Spring 官方提供的 Spring Boot 项目生成页面得到一个项目。

下面介绍一下使用 Spring 官方生成的方式,如果你已经有了一个 Spring Boot 项目,这部分可以直接跳过

  1. 打开 https://start.spring.io/

  2. 填写 groupArtifact 信息,选择依赖(我选择了 Spring Web 和 Lombok )。

  3. 点击 Generate 按钮下载项目。

  4. 打开下载的项目,删除无用的 .mvn 文件夹,mvnwmvnw.cmdHELP.md 文件。

到这里已经得到了一个 Spring Boot 初始项目了,我们直接导入到 IDEA 中,看一眼 pom.xml 的内容。

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.5.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.wdbyte</groupId>
<artifactId>springboot-module-demo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>springboot-module-demo</name>
<description>Demo project for Spring Boot</description> <properties>
<java.version>1.8</java.version>
</properties> <dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency> <dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies> <build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>

把目录结构调整成自己想要的结构,然后添加 controllerentity 用于测试。

ProductController 类源代码。

@RestController
@RequestMapping("/product")
public class ProductController { /**
* 获取商品列表
*
* @return
*/
@GetMapping("/list")
public Map list() {
// 模拟查询商品逻辑
Product product = new Product();
product.setProductName("小米粥");
product.setProductPrice(new BigDecimal(2.0));
product.setProductStock(100); Map<String, Object> resultMap = new HashMap<>();
resultMap.put("code", 000);
resultMap.put("message", "成功");
resultMap.put("data", Arrays.asList(product));
return resultMap;
}
}

Product 类源代码。

@Data
public class Product {
/** 商品名称. */
private String productName;
/** 商品价格. */
private BigDecimal productPrice;
/** 商品库存。 */
private int productStock;
}

模块化

借助 IDEA 工具可以快速的把项目改造成 maven 多模块,这里我们把准备测试 demo 拆分为 common 和 web 两个模块,common 模块存放实体类。web 模块存放 controller 层(这里项目虽小,拆分只是为了演示)。话不多说,直接开始。

  1. 配置主 pom.xml 打包方式 为 pom

    <?xml version="1.0" encoding="UTF-8"?>
    <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <!-- 配置主 pom 打包方式为 pom -->
    <packaging>pom</packaging>
    ....
    ....
  2. 创建 common 模块

    项目直接 new -> module。

    选择 maven -> next,填写模块名称。

    继续 next 完成模块创建。

  3. 创建 web 模块

    web 模块的创建和 common 模块如出一辙,不再赘述。完成两个模块的创建之后,你会发现你的主 pom.xml 文件里自动添加了 module 部分。

    <modules>
    <module>product-common</module>
    <module>product-web</module>
    </modules>
  4. 移动代码到指定模块

    移动 Product.javaproduct-common 模块,其他部分代码和 resource 部分直接移动到 product-web 模块,移动完后你的代码结构是这个样子。

到这里,多模块已经拆分完成了, 但是 ProductController 代码里的红色警告让你发现事情还没有结束。

依赖管理

处理依赖问题

你发现了代码里的红色警告,不过你也瞬间想到了是因为把 Product 类移动到了 product-common 模块,导致这里引用不到了。

然后你查看了下 product-common 模块的 pom.xml 里的内容。

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>springboot-module-demo</artifactId>
<groupId>com.wdbyte</groupId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>product-common</artifactId>
</project>

机智的在 Product-web 模块的 pom.xml 里引入 product-common,手起键落,轻松搞定。

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>springboot-module-demo</artifactId>
<groupId>com.wdbyte</groupId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>product-web</artifactId>
<dependencies>
<dependency>
<groupId>com.wdbyte</groupId>
<artifactId>product-common</artifactId>
</dependency>
</dependencies>
</project>

满心欢喜的你快速的点击 Build-> Build Project,得到的 Error 警告刺痛了顶着黑眼圈的你。

不过你还是迅速定位了问题,查看 maven 依赖,你发现是因为没有指定 product-common 依赖的版本号。

原来如此,因为没有指定版本号,我们指定上不就完事了嘛。在最外层的主 pom.xml 中添加 <dependencyManagement> 添加上指定依赖和要指定的版本号。

    <dependencyManagement>
<dependencies>
<dependency>
<groupId>com.wdbyte</groupId>
<artifactId>product-common</artifactId>
<version>0.0.1-SNAPSHOT</version><!-- maven 打包默认 0.0.1-SNAPSHOT 版本 -->
</dependency>
</dependencies>
</dependencyManagement>

刷新 maven ,发现项目已经不报错了,编译成功,运行启动类,熟悉的 Spring logo 又出现在眼前。

优化依赖

是的,Spring Boot 应用在改造成多模块后成功运行了起来,但是你貌似发现一个问题,模块 common 和模块 web 都继承了主 pom ,主 pom 中有 Lombok 、Spring Boot Web 和 Spring Boot Test 依赖,而 common 模块里只用到了 Lombok 啊,却一样继承了 Spring Boot 其他依赖,看来还是要改造一把。

  1. 只有 common 模块用到的依赖移动到 common 模块。

    <?xml version="1.0" encoding="UTF-8"?>
    <project xmlns="http://maven.apache.org/POM/4.0.0"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
    <artifactId>springboot-module-demo</artifactId>
    <groupId>com.wdbyte</groupId>
    <version>0.0.1-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>
    <artifactId>product-common</artifactId>
    <dependencies>
    <dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <optional>true</optional>
    </dependency>
    </dependencies>
    </project>
  2. 只有 web 模块用到的依赖移动到 web 模块。

    <?xml version="1.0" encoding="UTF-8"?>
    <project xmlns="http://maven.apache.org/POM/4.0.0"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
    <artifactId>springboot-module-demo</artifactId>
    <groupId>com.wdbyte</groupId>
    <version>0.0.1-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>
    <artifactId>product-web</artifactId> <dependencies>
    <dependency>
    <groupId>com.wdbyte</groupId>
    <artifactId>product-common</artifactId>
    </dependency> <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
    </dependency> <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-test</artifactId>
    <scope>test</scope>
    <exclusions>
    <exclusion>
    <groupId>org.junit.vintage</groupId>
    <artifactId>junit-vintage-engine</artifactId>
    </exclusion>
    </exclusions>
    </dependency>
    </dependencies>
    </project>
  3. 抽取用到的版本号到 <properties>,这里抽取 common 模块的依赖版本。

    到这里最外层主 pom 的内容是这样的。

    <?xml version="1.0" encoding="UTF-8"?>
    <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <packaging>pom</packaging>
    <modules>
    <module>product-common</module>
    <module>product-web</module>
    </modules>
    <parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.2.5.RELEASE</version>
    <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.wdbyte</groupId>
    <artifactId>springboot-module-demo</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>springboot-module-demo</name>
    <description>Demo project for Spring Boot</description> <properties>
    <java.version>1.8</java.version>
    <product-common.version>0.0.1-SNAPSHOT</product-common.version>
    </properties> <dependencyManagement>
    <dependencies>
    <dependency>
    <groupId>com.wdbyte</groupId>
    <artifactId>product-common</artifactId>
    <version>${product-common.version}</version>
    </dependency>
    </dependencies>
    </dependencyManagement> <build>
    <plugins>
    <plugin>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-maven-plugin</artifactId>
    </plugin>
    </plugins>
    </build>
    </project>

看似完美,重新 Build-> Build Project ,发现一切正常,运行发现一切正常,访问正常。

打包编译

好了,终于到了最后一步了,你感觉到胜利的曙光已经照到了头顶,反射出耀眼的光芒。接着就是 mvn package

[INFO] springboot-module-demo ............................. SUCCESS [  2.653 s]
[INFO] product-common ..................................... FAILURE [ 2.718 s]
[INFO] product-web ........................................ SKIPPED
[INFO] ------------------------------------------------------------------------
[INFO] BUILD FAILURE
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 6.084 s
[INFO] Finished at: 2020-03-19T08:15:52+08:00
[INFO] Final Memory: 22M/87M
[INFO] ------------------------------------------------------------------------
[ERROR] Failed to execute goal org.springframework.boot:spring-boot-maven-plugin:2.2.5.RELEASE:repackage (repackage) on project product-common: Execution repackage of goal org.springframework.boot:spring-boot-m
aven-plugin:2.2.5.RELEASE:repackage failed: Unable to find main class -> [Help 1]
[ERROR]

ERROR 让你伤心了,但是你还是从报错中寻找到了一些蛛丝马迹,你看到是 spring-boot-maven-plugin 报出的错误。重新审视你的主 pom 发现 <build> 编译插件用到了 spring-boot-maven-plugin。

    <build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>

略加思索后将这段移动到 web 模块的 pom,因为这是 Spring Boot 的打包方式,现在放在主 pom 中所有的模块都会继承到,那么对于 common 模块来说是肯定不需要的。

移动后重新打包,不管你是运行命令 mvn package 还是双击 IDEA 中的 maven 管理中的 package ,想必这时候你都已经打包成功了

web 模块下的目录 target 里也可以看到打包后的 jar 文件 product-web-0.0.1-SNAPSHOT.jar。可以使用 java 命令直接运行。

$ \springboot-module-demo\product-web\target>java -jar product-web-0.0.1-SNAPSHOT.jar

  .   ____          _            __ _ _
/\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
\\/ ___)| |_)| | | | | || (_| | ) ) ) )
' |____| .__|_| |_|_| |_\__, | / / / /
=========|_|==============|___/=/_/_/_/
:: Spring Boot :: (v2.2.5.RELEASE) 2020-03-19 08:33:03.337 INFO 15324 --- [ main] com.wdbyte.Application : Starting Application v0.0.1-SNAPSHOT on DESKTOP-8SCFV4M with PID 15324 (C:\Users\83981\Desktop\springboot-mod
ule-demo\product-web\target\product-web-0.0.1-SNAPSHOT.jar started by 83981 in C:\Users\83981\Desktop\springboot-module-demo\product-web\target)
2020-03-19 08:33:03.340 INFO 15324 --- [ main] com.wdbyte.Application : No active profile set, falling back to default profiles: default
2020-03-19 08:33:04.410 INFO 15324 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat initialized with port(s): 8080 (http)
2020-03-19 08:33:04.432 INFO 15324 --- [ main] o.apache.catalina.core.StandardService : Starting service [Tomcat]
2020-03-19 08:33:04.432 INFO 15324 --- [ main] org.apache.catalina.core.StandardEngine : Starting Servlet engine: [Apache Tomcat/9.0.31]
2020-03-19 08:33:04.493 INFO 15324 --- [ main] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring embedded WebApplicationContext
2020-03-19 08:33:04.493 INFO 15324 --- [ main] o.s.web.context.ContextLoader : Root WebApplicationContext: initialization completed in 1107 ms
2020-03-19 08:33:04.636 INFO 15324 --- [ main] o.s.s.concurrent.ThreadPoolTaskExecutor : Initializing ExecutorService 'applicationTaskExecutor'
2020-03-19 08:33:04.769 INFO 15324 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat started on port(s): 8080 (http) with context path ''
2020-03-19 08:33:04.772 INFO 15324 --- [ main] com.wdbyte.Application : Started Application in 1.924 seconds (JVM running for 2.649)
2020-03-19 08:33:07.087 INFO 15324 --- [extShutdownHook] o.s.s.concurrent.ThreadPoolTaskExecutor : Shutting down ExecutorService 'applicationTaskExecutor'

想必少了点什么,多模块不仅为了结构清晰,更是为了其他项目可以复用模块(如 common 模块),现在这个时候如果你新打开了一个项目,依赖 common 发现是引用不到的,因为你需要把模块安装到本地仓库。可以点击 IDEA -> Maven -> install,也可以通过 maven 命令。

# -Dmaven.test.skip=true 跳过测试
# -U 强制刷新
# clean 清理缓存
# install 安装到本地仓库
$ \springboot-module-demo> mvn -Dmaven.test.skip=true -U clean install

重新引入发现没有问题了。

文中代码已经上传到 Github: https://github.com/niumoo/springboot

这篇文章到这里就结束了,如果你觉得不错可以关注我的公众号一起交流。

公众号满载干货童叟无欺

最详细的 Spring Boot 多模块开发与排坑指南的更多相关文章

  1. Spring boot 多模块项目 + Swagger 让你的API可视化

    Spring boot 多模块项目 + Swagger 让你的API可视化 前言 手写 Api 文档的几个痛点: 文档需要更新的时候,需要再次发送一份给前端,也就是文档更新交流不及时. 接口返回结果不 ...

  2. Spring Boot Web应用开发 CORS 跨域请求支持:

    Spring Boot Web应用开发 CORS 跨域请求支持: 一.Web开发经常会遇到跨域问题,解决方案有:jsonp,iframe,CORS等等CORS与JSONP相比 1. JSONP只能实现 ...

  3. Spring Boot 多模块项目创建与配置 (一) (转)

    Spring Boot 多模块项目创建与配置 (一) 最近在负责的是一个比较复杂项目,模块很多,代码中的二级模块就有9个,部分二级模块下面还分了多个模块.代码中的多模块是用maven管理的,每个模块都 ...

  4. Spring Boot 多模块项目创建与配置 (一)

    最近在负责的是一个比较复杂项目,模块很多,代码中的二级模块就有9个,部分二级模块下面还分了多个模块.代码中的多模块是用maven管理的,每个模块都使用spring boot框架.之前有零零散散学过一些 ...

  5. Spring Boot 多模块项目创建与配置 (转)

    转载:https://www.cnblogs.com/MaxElephant/p/8205234.html 最近在负责的是一个比较复杂项目,模块很多,代码中的二级模块就有9个,部分二级模块下面还分了多 ...

  6. Maven 搭建spring boot多模块项目(附源码),亲测可以,感谢原创

    原创地址:https://segmentfault.com/a/1190000005020589 我的DEMO码云地址,持续添加新功能: https://gitee.com/itbase/Spring ...

  7. Maven 搭建spring boot多模块项目

    Maven 搭建spring boot多模块项目 备注:所有项目都在idea中创建 1.idea创建maven项目 1-1: 删除src,target目录,只保留pom.xml 1-2: 根目录pom ...

  8. Spring Boot 企业级应用开发实战 刘伟东-2018年3月第一版

    Spring会自动搜索某些路径下的Java类 并将这些类注册微Bean实例,这样就省去了所有Bean都配置在XML的麻烦 Spring会适当地将显示指定路径下的的类全部注册微Spring Bean . ...

  9. 图书-技术-SpringBoot:《Spring Boot 企业级应用开发实战》

    ylbtech-图书-技术-SpringBoot:<Spring Boot 企业级应用开发实战> Spring Boot 企业级应用开发实战,全书围绕如何整合以 Spring Boot 为 ...

随机推荐

  1. [洛谷P3369] 普通平衡树 Treap & Splay

    这个就是存一下板子...... 题目传送门 Treap的实现应该是比较正经的. 插入删除前驱后继排名什么的都是平衡树的基本操作. #include<cstdio> #include< ...

  2. unittest(11)- get_data自定义取某几条测试数据

    在get_data中定义取全部用例和取部分用例两种模式 # 1. http_request.py import requests class HttpRequest: def http_request ...

  3. navicat 导出查询结果

    请依照下列步骤:(Windows 版本) 例子:导出查询结果到一个文本文件 在执行查询之后,保存查询及在工具栏点击导出向导/导出. 按照导出向导的步骤指导你完成 设置导出文件格式(步骤 1) 设置目标 ...

  4. sql性能优化浅谈

    sql性能优化总结: 最近随着数据越来越多,数据库性能问题暴露的越来越严重.几百万,上千万,甚至过亿的数据处理速度会非常的慢. 下面对工作中遇到的问题做下总结,希望以后能对日后的工作有所帮助. 不同的 ...

  5. JMeter之BeanShell断言---获取时间戳

    1.创建线程组,创建一个BeanShell Sampler,在其中编写BeanShell脚本. 2.在Jmeter中,可以利用${__time(,)}时间戳函数来获取十位的时间戳,如: vars.pu ...

  6. python 学员管理系统

    需求: 用户角色,讲师\学员, 用户登陆后根据角色不同,能做的事情不同,分别如下 讲师视图 管理班级,可创建班级,根据学员qq号把学员加入班级 可创建指定班级的上课纪录,注意一节上课纪录对应多条学员的 ...

  7. H2O theme for Jekyll

    正如我在微博上所说的,使用Jekyll半年以来一直没有令我满意的主题模板,所以开始计划自己写一套好看又好用的主题模板.设计之初就明确了极简主义,风格采用扁平化了,通过卡片式设计来进行区块分明的布局,参 ...

  8. 使用Google BBR加速 VPS

    0X00 预备知识 在使用Google BBR之前,我们首先要了解它是什么. 了解计算机网络的人都知道,在TCP连接中,由于需要维持连接的可靠性,引入了拥塞控制和流量管理的方法.Google BBR就 ...

  9. Docker实战之Zookeeper集群

    1. 概述 这里是 Docker 实战系列第四篇.主要介绍分布式系统中的元老级组件 Zookeeper. ZooKeeper 是一个开源的分布式协调服务,是 Hadoop,HBase 和其他分布式框架 ...

  10. linux同步当前网络时间

    [root@root ~]# yum install -y ntpdate 执行:ntpdate[root@root ~]# ntpdate 120.24.81.91或[root@root ~]# n ...