本篇文章一步一步构建以下模块:
-- parent
-- boot-starter // 启动模块, 只有这个模块有启动类和配置文件 (依赖api模块)
-- boot-api // 接口模块, 也可以取名web,看个人喜好(依赖service模块)
-- boot-service // 业务模块,写核心的业务逻辑(依赖repository模块和third-party模块)
-- boot-repository // 访问数据库持久层模块
-- boot-third-party // 调用第三方接口
-- boot-common // 枚举等公共类 (被所有模块依赖)
创建父项目
什么依赖不加,然后删除多余的文件,只留一个pom文件:
并修改pom文件:
1、添加 pom
2、artifactId 可以添加 - parent 结尾。
3、删除其他不需要的信息。
最后长这个样子:
<?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>3.5.4</version>
<relativePath/>
</parent>
<groupId>com.congvee</groupId>
<artifactId>weather-parent</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>weather</name>
<description>Demo project for Spring Boot</description>
<packaging>pom</packaging>
<properties>
<java.version>17</java.version>
</properties>
</project>
添加模块
以添加starter模块为例子,其他模块都一样,唯一区别是 starter模块保留启动类和配置文件。
package name 可以在 weather 和 starter 添加个点,后面包扫描路径配置成 com.congvee.weather
整个过程可以先不添加依赖,后面我们统一添加,将不必要的文件删掉。
修改pom文件:
1、将weather-parent作为父
2、将其他的信息删掉
最后长这个样子:
<?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>com.congvee</groupId>
<artifactId>weather-parent</artifactId>
<version>0.0.1-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<artifactId>weather-starter</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>weather-starter</name>
<description>weather-starter</description>
</project>
同时父pom文件,将starter模块添加进来:
<modules>
<module>weather-starter</module>
</modules>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>com.congvee</groupId>
<artifactId>weather-starter</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
</dependencies>
</dependencyManagement>
后续将所有模块的所有用到的组件 统一 声明到 父pom中,并锁定版本,子模块引用的时候是不需要指定版本的。
使starter模块工作
父pom除了引入子模块依赖,额外声明以下依赖:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<version>3.5.4</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.38</version>
</dependency>
starter模块引入依赖:
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
start模块启动类配置扫描包路径:
package com.congvee.weather.starter;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication(scanBasePackages = "com.congvee.weather") // 关键
public class WeatherStarterApplication {
public static void main(String[] args) {
SpringApplication.run(WeatherStarterApplication.class, args);
}
}
注意只有 starter模块才有配置文件,所有的配置统统配置到starter模块中。
然后尝试启动项目,能正常启动即可,starter模块配置结束。
使 api 模块工作
按照前面的添加模块示例,添加 weather-api 模块,并引入依赖:
<dependencies>
<!-- 不推荐直接引入 spring-boot-starter-web, 会包含一堆不需要的东西 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
</dependencies>
还需要在 starter 模块中添加 api 模块作为依赖:
<dependency>
<groupId>com.congvee</groupId>
<artifactId>weather-api</artifactId>
</dependency>
声明 HelloController 测试:
@RestController
@RequestMapping("/api/hello")
public class HelloController {
@GetMapping
public String hello() {
return "Hello, World!";
}
}
说明 api 模块也可以正常运行。
使 service 模块工作
按照前面创建模块的示例创建 weather-service模块。
添加依赖:
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
</dependency>
</dependencies>
api模块需要添加service依赖:
<dependency>
<groupId>com.congvee</groupId>
<artifactId>weather-service</artifactId>
</dependency>
声明 HelloService:
@Service
public class HelloService {
public String sayHello() {
return "Hello, World! service";
}
}
在 api 模块中调用:
@RestController
@RequestMapping("/api/hello")
@RequiredArgsConstructor
public class HelloController {
private final HelloService helloService;
@GetMapping
public String hello() {
return helloService.sayHello();
}
}
说明service模块可以正常工作。
使 repository 模块工作
父pom声明新依赖:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
<version>3.5.4</version>
</dependency>
<dependency>
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
<version>9.3.0</version>
</dependency>
<dependency>
<groupId>org.flywaydb</groupId>
<artifactId>flyway-core</artifactId>
<version>11.7.2</version>
</dependency>
<dependency>
<groupId>org.flywaydb</groupId>
<artifactId>flyway-mysql</artifactId>
<version>11.7.2</version>
</dependency>
repository模块同样引入依赖:
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
</dependency>
<dependency>
<groupId>org.flywaydb</groupId>
<artifactId>flyway-core</artifactId>
</dependency>
<dependency>
<groupId>org.flywaydb</groupId>
<artifactId>flyway-mysql</artifactId>
</dependency>
</dependencies>
service模块引入 repository模块:
<dependency>
<groupId>com.congvee</groupId>
<artifactId>weather-repository</artifactId>
</dependency>
然后声明sql文件存放在 repository 模块的 resource目录下的 db/migration 下,声明实体和Repository,这里就不过多讲述,可以参考之前的文章,关键词:springboot-data-jpa 和 flyway。
配置则放在 starter 模块中:
spring.datasource.url=jdbc:mysql://localhost:3306/multi-module
spring.datasource.username=root
spring.datasource.password=lkjhgfds
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.jpa.database-platform=org.hibernate.dialect.MySQL8Dialect
spring.jpa.show-sql=true
这里还要做一个配置,还需要再启动类添加注解:
@EnableJpaRepositories(basePackages = "com.congvee.weather.repository")
@EntityScan(basePackages = "com.congvee.weather.repository")
Spring Boot 默认不会自动扫描其他模块的 Repository 接口,必须显式加 @EnableJpaRepositories
然后在service模块中调用:
@Slf4j
@Service
@RequiredArgsConstructor
public class HelloService {
private final UserRepository userRepository;
public String sayHello() {
List<UserEntity> all = userRepository.findAll();
log.info("All users: {}", all);
return "Hello, World! service";
}
}
正常打印信息,则说明repository模块也正常工作。
使 common 模块正常工作
common 模块主要存放常量,枚举等公共的类。
在common模块中定义工具类。
public class Utils {
public static Integer add(int a, int b) {
return a + b;
}
}
然后 service 模块引入 common 模块:
<dependency>
<groupId>com.congvee</groupId>
<artifactId>weather-common</artifactId>
</dependency>
这样使用即可:
@Slf4j
@Service
@RequiredArgsConstructor
public class HelloService {
public String sayHello() {
Integer add = Utils.add(1, 2);
log.info("add result: " + add);
return "Hello, World! service";
}
}