一,多模塊項目的優點:
1,為什么要使用多模塊項目?
相比傳統的單體工程,使用Maven的多模塊配置,
有如下優點:
幫助項目划分模塊,鼓勵重用,
防止POM變得過於龐大,
方便某個模塊的構建,而不用每次都構建整個項目,
對某個模塊的特殊控制更為方便
2,創建項目的流程:
先創建一個空項目multimodjar,刪除無關文件,只留一個pom.xml和一個multimodjar.iml
然后在這個項目下創建module
3,pom.xml/multimodjar.iml 兩個文件的用途說明:
pom.xml: 項目對象模型(Project Object Model)的簡稱,它是Maven項目中的文件。
作用:管理源代碼/配置文件/開發者的信息和角色/問題追蹤系統/組織信息/項目授權/項目的url/項目的依賴關系等
multimodjar.iml,iml文件,infomation of module,
作用:保存了項目的配置信息,intellij idea需要從它獲取項目信息
說明:劉宏締的架構森林是一個專注架構的博客,地址:https://www.cnblogs.com/architectforest
對應的源碼可以訪問這里獲取: https://github.com/liuhongdi/
說明:作者:劉宏締 郵箱: 371125307@qq.com
二, 演示項目的相關信息
1,項目地址:
https://github.com/liuhongdi/multimodjar
2,項目功能說明:
演示了多模塊項目如何配置pom.xml打包
項目包含了4個模塊:mmweb(可執行的入口)
mmservice
mmpojo
mmrepo(數據庫)
3,項目結構:如圖:
三,配置文件說明
1,根項目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.3.3.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent> <groupId>com.multimodjar</groupId> <artifactId>demo</artifactId> <version>0.0.1-SNAPSHOT</version> <name>demo</name> <description>Demo project for Spring Boot</description> <properties> <java.version>11</java.version> </properties> <packaging>pom</packaging> <modules> <module>mmweb</module> <module>mmpojo</module> <module>mmrepo</module> <module>mmservice</module> </modules> </project>
可以看到,在根項目中,只需要添加對各個模塊的依賴
2,mmweb模塊的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.3.3.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent> <groupId>com.mmweb</groupId> <artifactId>demo</artifactId> <version>0.0.1-SNAPSHOT</version> <name>demo</name> <description>Demo project for Spring Boot</description> <properties> <java.version>11</java.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <!--mmservice begin--> <dependency> <groupId>com.mmservice</groupId> <artifactId>demo</artifactId> <version>0.0.1-SNAPSHOT</version> <scope>compile</scope> </dependency> <!--mmpojo begin--> <dependency> <groupId>com.mmpojo</groupId> <artifactId>demo</artifactId> <version>0.0.1-SNAPSHOT</version> <scope>compile</scope> </dependency> <!--thymeleaf begin--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-thymeleaf</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> <!--spring boot打包的話需要指定一個唯一的入口類--> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> <configuration> <mainClass>com.mmweb.demo.DemoApplication</mainClass> <layout>ZIP</layout> </configuration> <executions> <execution> <goals> <goal>repackage</goal> </goals> </execution> </executions> </plugin> </plugins> </build> </project>
因為mmweb是可執行的類所在模塊,所以需要專門指定執行mainClass入口類
3,mmweb的application.properties
#error server.error.include-stacktrace=always #errorlog logging.level.org.springframework.web=trace #mysql spring.datasource.url=jdbc:mysql://localhost:3306/store?characterEncoding=utf8&useSSL=false spring.datasource.username=root spring.datasource.password=lhddemo spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver #mybatis mybatis.mapper-locations=classpath:/mapper/*Mapper.xml mybatis.type-aliases-package=com.example.demo.mapper mybatis.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl #thymeleaf spring.thymeleaf.cache=false spring.thymeleaf.encoding=UTF-8 spring.thymeleaf.mode=HTML spring.thymeleaf.prefix=classpath:/templates/ spring.thymeleaf.suffix=.html
4,mmservice的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.3.3.RELEASE</version> <relativePath/> </parent> <groupId>com.mmservice</groupId> <artifactId>demo</artifactId> <version>0.0.1-SNAPSHOT</version> <name>demo</name> <description>Demo project for Spring Boot</description> <properties> <java.version>11</java.version> </properties> <dependencies> <!--mmpojo begin--> <dependency> <groupId>com.mmpojo</groupId> <artifactId>demo</artifactId> <version>0.0.1-SNAPSHOT</version> <scope>compile</scope> </dependency> <!--mmrepo begin--> <dependency> <groupId>com.mmrepo</groupId> <artifactId>demo</artifactId> <version>0.0.1-SNAPSHOT</version> <scope>compile</scope> </dependency> <!--pagehelper begin--> <dependency> <groupId>com.github.pagehelper</groupId> <artifactId>pagehelper-spring-boot-starter</artifactId> <version>1.2.12</version> </dependency> </dependencies> </project>
5,mmrepo的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.3.3.RELEASE</version> <relativePath/> </parent> <groupId>com.mmrepo</groupId> <artifactId>demo</artifactId> <version>0.0.1-SNAPSHOT</version> <name>demo</name> <description>Demo project for Spring Boot</description> <properties> <java.version>11</java.version> </properties> <dependencies> <dependency> <groupId>com.mmpojo</groupId> <artifactId>demo</artifactId> <version>0.0.1-SNAPSHOT</version> </dependency> <!--mybatis begin--> <dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter</artifactId> <version>2.1.3</version> </dependency> <!--mysql begin--> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <scope>runtime</scope> </dependency> </dependencies> </project>
6,mmpojo的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.3.3.RELEASE</version> <relativePath/> </parent> <groupId>com.mmpojo</groupId> <artifactId>demo</artifactId> <version>0.0.1-SNAPSHOT</version> <name>demo</name> <description>Demo project for Spring Boot</description> <properties> <java.version>11</java.version> </properties> </project>
7,用到的數據表的結構:
CREATE TABLE `goods` ( `goodsId` int(11) NOT NULL AUTO_INCREMENT COMMENT 'id', `goodsName` varchar(500) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL DEFAULT '' COMMENT 'name', `subject` varchar(200) NOT NULL DEFAULT '' COMMENT '標題', `price` decimal(15,2) NOT NULL DEFAULT '0.00' COMMENT '價格', `stock` int(11) NOT NULL DEFAULT '0' COMMENT 'stock', PRIMARY KEY (`goodsId`) ) ENGINE=InnoDB AUTO_INCREMENT=0 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='商品表'
四,java代碼說明
1,DemoApplication.java
@SpringBootApplication(scanBasePackages = {"com.mmservice.demo","com.mmpojo.demo","com.mmweb.demo"}) @MapperScan("com.mmrepo.demo") public class DemoApplication { public static void main(String[] args) { SpringApplication.run(DemoApplication.class, args); } }
說明:因為引入了多模塊,需要添加上掃描包的路徑
2,HomeController.java
import com.mmpojo.demo.pojo.Goods; import com.mmservice.demo.service.GoodsService; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.*; import javax.annotation.Resource; import java.util.List; import java.util.Map; @Controller @RequestMapping("/home") public class HomeController { @Resource private GoodsService goodsService; // list all goods @GetMapping("/list") @ResponseBody public List<Goods> all() { System.out.println("-------------------------list"); List<Goods> list = goodsService.getAllGoods(); return list; } //帶模板顯示商品列表 參數:第幾頁 @GetMapping("/goodslist") public String goodsList(Model model, @RequestParam(value="p",required = false,defaultValue = "1") int currentPage) { Map<String,Object> res = goodsService.getAllGoodsByPage(currentPage); model.addAttribute("pageInfo", res.get("pageInfo")); model.addAttribute("goodslist", res.get("goodslist")); return "goods/goodslist"; } }
注意import的goods/GoodsService類的路徑
3,GoodsServiceImpl.java
@Service public class GoodsServiceImpl implements GoodsService { @Resource private GoodsMapper goodsMapper; //返回全部商品 @Override public List<Goods> getAllGoods() { List<Goods> goodsList = goodsMapper.selectAllGoods(); return goodsList; } //帶分頁返回商品 @Override public Map<String,Object> getAllGoodsByPage(int currentPage) { Map<String,Object> res = new HashMap<String,Object>(); PageHelper.startPage(currentPage, 5); List<Goods> goodsList = goodsMapper.selectAllGoods(); res.put("goodslist",goodsList); PageInfo<Goods> pageInfo = new PageInfo<>(goodsList); res.put("pageInfo",pageInfo); return res; } }
4,GoodsMapper.java
@Repository @Mapper public interface GoodsMapper { List<Goods> selectAllGoods(); }
5,GoodsMapper.xml
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.mmrepo.demo.mapper.GoodsMapper"> <select id="selectAllGoods" resultType="com.mmpojo.demo.pojo.Goods"> select * from goods order by goodsId desc </select> </mapper>
6,Goods.java
public class Goods { //商品id Long goodsId; public Long getGoodsId() { return this.goodsId; } public void setGoodsId(Long goodsId) { this.goodsId = goodsId; } //商品名稱 private String goodsName; public String getGoodsName() { return this.goodsName; } public void setGoodsName(String goodsName) { this.goodsName = goodsName; } //商品標題 private String subject; public String getSubject() { return this.subject; } public void setSubject(String subject) { this.subject = subject; } //商品價格 private BigDecimal price; public BigDecimal getPrice() { return this.price; } public void setPrice(BigDecimal price) { this.price = price; } //庫存 int stock; public int getStock() { return this.stock; } public void setStock(int stock) { this.stock = stock; } public String toString(){ return " Goods:goodsId=" + goodsId +" goodsName=" + goodsName+" subject=" + subject+" price=" + price+" stock=" + stock; } }
7,goodslist.html
<!DOCTYPE html> <html lang="en"> <head > <title >商品列表</title> <!--全局通用框架樣式 begin--> <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" /> <meta charset="utf-8" /> <meta name="description" content="" /> <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0" /> </head> <body style="font-size: 12px;"> <div style="width:100%;height:10px;background:#eeeeee;font-size: 16px;" ></div> <div id="content" style="width:1040px;"> <div style="width:150px;float:left;font-size: 12px;background:#eeeeee;" ></div> <div style="width:790px;float:left;"> <!--main begin--> <div th:each="goodsone:${goodslist}"
style="border-bottom-style:solid; border-bottom-width: 1px; width:990px;height:60px;font-size:12px;overflow: hidden;border-bottom-color: #eeeeee;"> <div style="float:left;width:20px;overflow: hidden;" th:text="${goodsone.goodsId}"></div> <div style="float:left;width:200px;height:60px;overflow: hidden;" th:text="${goodsone.goodsName}"></div> <!--<div style="float:left;width:300px;overflow: hidden;" th:text="${image_one.image_sn}"></div>--> <div style="float:left;width:200px;overflow: hidden;" th:text="${goodsone.subject}"></div> <div style="float:left;width:80px;overflow: hidden;" th:text="${goodsone.price}"></div> <div style="float:left;width:100px;overflow: hidden;" th:text="${goodsone.stock}"></div> <div style="float:left;width:160px;overflow: hidden;" ></div> </div> <!--page info begin--> <div align="center"> <a class="allpage"><b th:text="'共 '+ ${pageInfo.getPages()}+ ' 頁'"></b></a> <a th:href="@{/home/goodslist/(p=${pageInfo.getNavigateFirstPage()})}" >首頁</a> <a th:if="${pageInfo.isHasPreviousPage()} == true" th:href="@{/home/goodslist/(p=${pageInfo.getPrePage()})}" >上一頁</a> | <span th:each="i,iterStat :${#numbers.sequence(pageInfo.getNavigateFirstPage(), pageInfo.getNavigateLastPage())}" > <a th:href="@{/home/goodslist/(p=${i})}" th:text=" ${i} "> </a> <span th:text=" ${iterStat.last}? '':'|' ">|</span> </span> | <a th:if="${pageInfo.isHasNextPage()} == true" th:href="@{/home/goodslist/(p=${pageInfo.getNextPage()})}" >下一頁</a> <a th:href="@{/home/goodslist/(p=${pageInfo.getNavigateLastPage()})}" >尾頁</a> </div> <!--page info end--> <!--main end--> </div> </div> </body> </html>
五,測試效果
1, 打包:
maven界面,root項目下,先執行clean
然后再執行package
即可以在mmweb項目的target目錄下看到jar包
demo-0.01-SNAPSHOT.jar,就是生成的jar包
2,運行jar包
#nohup: 讓命令在后台執行,即使終端關閉也不會退出
[root@localhost target]# nohup /usr/local/soft/jdk-12.0.2/bin/java -Xms256m -Xmx256m -jar /data/springboot2f/multimodjar/mmweb/target/demo-0.0.1-SNAPSHOT.jar >/dev/null 2>&1 & [1] 30103
如使用此命令,注意把路徑替換成自己java命令和jar包的所在路徑
3,從瀏覽器訪問:
http://127.0.0.1:8080/home/goodslist/?p=1
返回:
六,查看spring boot的版本:
. ____ _ __ _ _ /\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \ ( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \ \\/ ___)| |_)| | | | | || (_| | ) ) ) ) ' |____| .__|_| |_|_| |_\__, | / / / / =========|_|==============|___/=/_/_/_/ :: Spring Boot :: (v2.3.3.RELEASE)