子模块是独立的maven项目,它们共享父项目的属性。
所有子项目都可以用一个命令来构建,因为它位于父项目中。
定义项目之间的关系更容易。
<?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.2.BUILD-SNAPSHOT</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.lidihuo</groupId>
<artifactId>spring-boot-example</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>spring-boot-multi-module-project</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
</properties>
<packaging>pom</packaging>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.1.RELEASE</version>
<type>pom</type>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</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>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
<repositories>
<repository>
<id>spring-milestones</id>
<name>Spring Milestones</name>
<url>https://repo.spring.io/milestone</url>
</repository>
<repository>
<id>spring-snapshots</id>
<name>Spring Snapshots</name>
<url>https://repo.spring.io/snapshot</url>
<snapshots>
<enabled>true</enabled>
</snapshots>
</repository>
</repositories>
<pluginRepositories>
<pluginRepository>
<id>spring-milestones</id>
<name>Spring Milestones</name>
<url>https://repo.spring.io/milestone</url>
</pluginRepository>
<pluginRepository>
<id>spring-snapshots</id>
<name>Spring Snapshots</name>
<url>https://repo.spring.io/snapshot</url>
<snapshots>
<enabled>true</enabled>
</snapshots>
</pluginRepository>
</pluginRepositories>
<modules>
<module>module1</module>
<module>module2</module>
</modules>
</project>
<packaging>pom</packaging>
<modules>
<module>module1</module>
<module>module2</module>
</modules>
<?xml version="1.0"?>
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.lidihuo</groupId>
<artifactId>spring-boot-multi-module-project</artifactId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<groupId>com.lidihuo</groupId>
<artifactId>module1</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>module1</name>
<url>http://maven.apache.org</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>
在以下示例中,我们创建了一个名为 spring-boot-multimodule的maven项目。这是主要应用程序。在主应用程序中,我们创建了五个模块,如下所示:
应用
模型
存储库
service-api
service-impl
Spring-boot-multimodule
├── pom.xml
│ └── REDME.adoc
├── application
│ ├── pom.xml
│ └── src
│ └── main
│ ├── java
│ │ └── sample
│ │ └── multimodule
│ │ ├── SampleWebJspApplication.java
│ │ └── web
│ │ └── WelcomeController.java
│ └── resources
│ ├── application.properties
│ └── templates
│ └── welcome
│ └── show.html
├── model
│ ├── pom.xml
│ └── src
│ └── main
│ └── java
│ └── sample
│ └── multimodule
│ └── domain
│ └── entity
│ └── Account.java
|
├── repository
│ ├── pom.xml
│ └── src
│ └── main
│ └── java
│ └── sample
│ └── multimodule
│ └── repository
│ └── AccountRepository.java
├── service-api
│ ├── pom.xml
│ └── src
│ └── main
│ └── java
│ └── sample
│ └── multimodule
│ └── service
│ └── api
│ ├── AccountNotFoundException.java
│ └── AccountService.java
└── service-impl
├── pom.xml
└── src
└── main
└── java
└── sample
└── multimodule
└── service
└── impl
└── AccountServiceImpl.java
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<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">
<modelVersion>4.0.0</modelVersion>
<!-- Spring IO Platform is the parent of the generated application to
be able to use Spring Boot and all its default configuration -->
<parent>
<groupId>io.spring.platform</groupId>
<artifactId>platform-bom</artifactId>
<version>2.0.1.RELEASE</version>
</parent>
<groupId>sample.multimodule</groupId>
<artifactId>sample.multimodule</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>pom</packaging>
<name>Parent - Pom Aggregator</name>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<!-- Spring Boot dependencies -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
</project>
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<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">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>sample.multimodule</groupId>
<artifactId>sample.multimodule</artifactId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<artifactId>sample.multimodule.application</artifactId>
<packaging>jar</packaging>
<name>Project Module - Application</name>
<dependencies>
<!-- Project modules -->
<dependency>
<groupId>sample.multimodule</groupId>
<artifactId>sample.multimodule.service.impl</artifactId>
<version>${project.version}</version>
</dependency>
<!-- Spring Boot dependencies -->
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-jasper</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<!-- Spring Boot plugins -->
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
package sample.multimodule;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.orm.jpa.EntityScan;
@SpringBootApplication
public class SampleWebJspApplication
{
public static void main(String[] args) throws Exception
{
SpringApplication.run(SampleWebJspApplication.class, args);
}
}
package sample.multimodule.web;
import java.util.Date;
import java.util.Map;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import sample.multimodule.domain.entity.Account;
import sample.multimodule.service.api.AccountService;
@Controller
public class WelcomeController
{
@Value("${application.message:Hello World}")
private String message = "Hello World";
@Autowired
protected AccountService accountService;
@RequestMapping("/")
public String welcome(Map<String, Object> model)
{
// Trying to obtain 23 account
Account account = accountService.findOne("23");
if(account == null){
// if there's some problem creating account, return show view with error status
model.put("message", "Error getting account!");
model.put("account", "");
return "welcome/show";
}
// return show view with 23 account info
String accountInfo = "Your account number is ".concat(account.getNumber());
model.put("message", this.message);
model.put("account", accountInfo);
return "welcome/show";
}
@RequestMapping("foo")
public String foo(Map<String, Object> model) {
throw new RuntimeException("Foo");
}
}
<!DOCTYPE HTML>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<title>Spring Boot Multimodule</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
</head>
<body>
<div>
<b>Message: </b>
<span th:text="${message}" />
</div>
<div>
<b>Your account: </b>
<span th:text="${account}" />
</div>
</body>
</html>
# Application messages
application.message = Hello User!
dummy.type = type-inside-the-war
# Spring Thymeleaf config
spring.thymeleaf.cache = false
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<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">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>sample.multimodule</groupId>
<artifactId>sample.multimodule</artifactId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<artifactId>sample.multimodule.model</artifactId>
<packaging>jar</packaging>
<name>Project Module - Model</name>
<description>Module that contains all Entities and Visual Objects to be used in the project. It doesn't have any dependencies.
</description>
</project>
下创建一个名称为
Account 的类。
package sample.multimodule.domain.entity;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
@Entity
public class Account
{
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private long id;
private String number;
private String type;
private String creditCardNumber;
/**
* Create an empty account.
*/
public Account() {
}
/**
* Create a new account.
*
* @param number
* the account number
* @param id
* the account id
*/
public Account(long id, String number) {
this.number = number;
this.id = id;
}
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getNumber() {
return number;
}
public void setNumber(String number) {
this.number = number;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public String getCreditCardNumber() {
return creditCardNumber;
}
public void setCreditCardNumber(String creditCardNumber) {
this.creditCardNumber = creditCardNumber;
}
}
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<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">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>sample.multimodule</groupId>
<artifactId>sample.multimodule</artifactId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<artifactId>sample.multimodule.repository</artifactId>
<packaging>jar</packaging>
<name>Project Module - Repository</name>
<description>Module that contains all repositories to be used in the project. Depends of Model Module.</description>
<dependencies>
<!-- Project modules -->
<dependency>
<groupId>sample.multimodule</groupId>
<artifactId>sample.multimodule.model</artifactId>
<version>${project.version}</version>
</dependency>
<!-- Spring Boot dependencies -->
<dependency>
<groupId>org.hsqldb</groupId>
<artifactId>hsqldb</artifactId>
<scope>runtime</scope>
</dependency>
</dependencies>
</project>
package sample.multimodule.repository;
import org.springframework.data.domain.*;
import org.springframework.data.repository.*;
import org.springframework.stereotype.Repository;
import sample.multimodule.domain.entity.Account;
@Repository
public interface AccountRepository extends CrudRepository<Account, Long>
{
Account findByNumber(String number);
}
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<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">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>sample.multimodule</groupId>
<artifactId>sample.multimodule</artifactId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<artifactId>sample.multimodule.service.api</artifactId>
<packaging>jar</packaging>
<name>Project Module - Service API</name>
<description>Module that contains API of all project services. Depends of Model Module.</description>
<dependencies>
<!-- Project Modules -->
<dependency>
<groupId>sample.multimodule</groupId>
<artifactId>sample.multimodule.model</artifactId>
<version>${project.version}</version>
</dependency>
</dependencies>
</project>
package sample.multimodule.service.api;
public class AccountNotFoundException extends RuntimeException
{
private static final long serialVersionUID = -3891534644498426670L;
public AccountNotFoundException(String accountId)
{
super("No such account with id: " + accountId);
}
}
package sample.multimodule.service.api;
import java.util.List;
import sample.multimodule.domain.entity.Account;
public interface AccountService
{
/**
* Finds the account with the provided account number.
*
* @param number The account number
* @return The account
* @throws AccountNotFoundException if no such account exists.
*/
Account findOne(String number) throws AccountNotFoundException;
/**
* Creates a new account.
* @param number
* @return created account
*/
Account createAccountByNumber(String number);
}
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<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">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>sample.multimodule</groupId>
<artifactId>sample.multimodule</artifactId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<artifactId>sample.multimodule.service.impl</artifactId>
<packaging>jar</packaging>
<name>Project Module - Service Implementation</name>
<description>Module that contains services implementation defined on Service API module. Depends of Repository Module and Service API Module.</description>
<dependencies>
<!-- Project Modules -->
<dependency>
<groupId>sample.multimodule</groupId>
<artifactId>sample.multimodule.repository</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>sample.multimodule</groupId>
<artifactId>sample.multimodule.service.api</artifactId>
<version>${project.version}</version>
</dependency>
</dependencies>
</project>
下创建一个名称为
AccountServiceImpl 的类。
package sample.multimodule.service.impl;
import java.util.ArrayList;
import java.util.List;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import sample.multimodule.domain.entity.Account;
import sample.multimodule.repository.AccountRepository;
import sample.multimodule.service.api.AccountService;
import sample.multimodule.service.api.AccountNotFoundException;
@Service
public class AccountServiceImpl implements AccountService
{
@Value("${dummy.type}")
private String dummyType;
@Autowired
private AccountRepository accountRepository;
/**
* {@inheritDoc}
* <p/>
* Dummy method for testing purposes.
*
* @param number The account number. Set 0000 to get an {@link AccountNotFoundException}
*/
@Override
public Account findOne(String number) throws AccountNotFoundException {
if(number.equals("0000")) {
throw new AccountNotFoundException("0000");
}
Account account = accountRepository.findByNumber(number);
if(account == null){
account = createAccountByNumber(number);
}
return account;
}
@Override
public Account createAccountByNumber(String number) {
Account account = new Account();
account.setNumber(number);
return accountRepository.save(account);
}
public String getDummyType() {
return dummyType;
}
public void setDummyType(String dummyType) {
this.dummyType = dummyType;
}
}