子模块是独立的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; } }