一、分模块设计与开发
1、分模块设计原因
Maven 的分模块设计主要有以下几个原因:
-
模块化管理:在大型项目中,代码量通常会非常大,如果将所有的代码都放在一个模块中,会使得项目结构复杂,不利于代码的管理和维护。通过分模块设计,可以将项目按照业务功能或者层次进行划分,每个模块负责一部分功能,模块之间通过接口进行通信,降低了模块之间的耦合度,提高了代码的可维护性。
-
并行开发:分模块设计可以支持多人或多团队并行开发。每个人或团队负责一个或多个模块的开发,可以在不影响其他模块的情况下进行开发,提高了开发效率。
-
复用性:分模块设计可以提高代码的复用性。如果一个功能在多个地方都有使用,可以将这个功能抽取出来作为一个模块,这样就可以在多个地方复用这个模块。
-
灵活性:分模块设计可以提高项目的灵活性。如果需要修改某个功能,只需要修改对应的模块即可,不需要修改整个项目。
-
易于测试:每个模块都可以单独进行测试,这样可以更早地发现问题,提高软件的质量。
-
版本控制:每个模块都可以有自己的版本号,可以单独进行版本控制和发布。
总的来说,Maven 的分模块设计可以提高项目的可维护性、开发效率、复用性、灵活性和软件质量,同时也方便了版本控制和发布。
2、示例讲解
代码示例:
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">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.3.2</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.sunny</groupId>
<artifactId>tlias-parent</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>pom</packaging>
<properties>
<maven.compiler.source>21</maven.compiler.source>
<maven.compiler.target>21</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<lombok.version>1.18.34</lombok.version>
</properties>
<dependencies>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>${lombok.version}</version>
</dependency>
</dependencies>
<!--统一管理依赖-->
<dependencyManagement>
<dependencies>
<!--JWT令牌-->
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>0.9.1</version>
</dependency>
<!--阿里云OSS依赖-->
<dependency>
<groupId>com.aliyun.oss</groupId>
<artifactId>aliyun-sdk-oss</artifactId>
<version>3.17.4</version>
</dependency>
<dependency>
<groupId>javax.xml.bind</groupId>
<artifactId>jaxb-api</artifactId>
<version>2.3.1</version>
</dependency>
<dependency>
<groupId>javax.activation</groupId>
<artifactId>activation</artifactId>
<version>1.1.1</version>
</dependency>
<dependency>
<groupId>org.glassfish.jaxb</groupId>
<artifactId>jaxb-runtime</artifactId>
<version>4.0.5</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<version>3.3.3</version>
</dependency>
</dependencies>
</dependencyManagement>
</project>
<?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">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.sunny</groupId>
<artifactId>tlias-parent</artifactId>
<version>1.0-SNAPSHOT</version>
<relativePath>../tlias-parent/pom.xml</relativePath>
</parent>
<artifactId>tlias-pojo</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<maven.compiler.source>21</maven.compiler.source>
<maven.compiler.target>21</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
</dependency>
</dependencies>
</project>
<?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">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.sunny</groupId>
<artifactId>tlias-parent</artifactId>
<version>1.0-SNAPSHOT</version>
<relativePath>../tlias-parent/pom.xml</relativePath>
</parent>
<artifactId>tlias-utils</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<maven.compiler.source>21</maven.compiler.source>
<maven.compiler.target>21</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<!--JWT令牌-->
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
</dependency>
<!--阿里云OSS依赖-->
<dependency>
<groupId>com.aliyun.oss</groupId>
<artifactId>aliyun-sdk-oss</artifactId>
</dependency>
<dependency>
<groupId>javax.xml.bind</groupId>
<artifactId>jaxb-api</artifactId>
</dependency>
<dependency>
<groupId>javax.activation</groupId>
<artifactId>activation</artifactId>
</dependency>
<dependency>
<groupId>org.glassfish.jaxb</groupId>
<artifactId>jaxb-runtime</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
</project>
<?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.sunny</groupId>
<artifactId>tlias-parent</artifactId>
<version>1.0-SNAPSHOT</version>
<relativePath>../tlias-parent/pom.xml</relativePath>
</parent>
<artifactId>tliasweb-management</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>tliasweb-management</name>
<description>tliasweb-management</description>
<url/>
<licenses>
<license/>
</licenses>
<developers>
<developer/>
</developers>
<scm>
<connection/>
<developerConnection/>
<tag/>
<url/>
</scm>
<properties>
<java.version>17</java.version>
</properties>
<dependencies>
<!--web起步依赖-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
</dependency>
<!--mybatis起步依赖-->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>3.0.3</version>
</dependency>
<!--mysql驱动-->
<dependency>
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
<scope>runtime</scope>
</dependency>
<!--lombok-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<!--springboot单元测试-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter-test</artifactId>
<version>3.0.3</version>
<scope>test</scope>
</dependency>
<!--pagehelper依赖-->
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper-spring-boot-starter</artifactId>
<version>1.4.7</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.5</version>
</dependency>
<!--fastJSON-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>2.0.50</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>com.sunny</groupId>
<artifactId>tlias-pojo</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>com.sunny</groupId>
<artifactId>tlias-utils</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<excludes>
<exclude>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</exclude>
</excludes>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<testFailureIgnore>true</testFailureIgnore>
</configuration>
</plugin>
</plugins>
</build>
</project>
注:上面代码是本人自己设计的,在这展示大多是为了留作后面回来复习用,如果是别人看的话应该会有难度去理解,毕竟少了很多代码。不过总的来说的话,实现分模块设计,就是拆分出多个Module,里面的代码是不变的,重要的是pom配置的改变,去实现父类或添加特有的依赖。
二、继承与聚合
1、继承关系实现
继承关系的说明
说明:我们大多在子类的pom文件里实现<parent>的描述,可以定义相应的父类。
继承关系实现
代码示例:
XML
<!--父类-->
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.3.2</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.sunny</groupId>
<artifactId>tlias-parent</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>pom</packaging>
<!--子类-->
<parent>
<groupId>com.sunny</groupId>
<artifactId>tlias-parent</artifactId>
<version>1.0-SNAPSHOT</version>
<relativePath>../tlias-parent/pom.xml</relativePath>
</parent>
<artifactId>tlias-pojo</artifactId>
<version>1.0-SNAPSHOT</version>
<!--子类-->
<parent>
<groupId>com.sunny</groupId>
<artifactId>tlias-parent</artifactId>
<version>1.0-SNAPSHOT</version>
<relativePath>../tlias-parent/pom.xml</relativePath>
</parent>
<artifactId>tlias-utils</artifactId>
<version>1.0-SNAPSHOT</version>
2、版本锁定功能
使用原因
Maven的版本锁定主要有以下几个原因:
-
保证构建的一致性:在软件开发过程中,我们常常会依赖许多第三方的库或者插件,这些库或者插件的版本如果不进行锁定,那么在不同的环境中(比如开发环境、测试环境、生产环境)可能会使用到不同版本的库或者插件,这就可能导致在不同环境中软件的行为不一致。通过版本锁定,可以保证在所有环境中都使用相同版本的库或者插件,从而保证构建的一致性。
-
避免版本冲突:如果我们的项目依赖了多个库,而这些库又依赖了同一个库的不同版本,那么就可能会出现版本冲突的问题。通过版本锁定,可以明确指定我们项目使用的库的版本,从而避免版本冲突。
-
避免不兼容的问题:有些库在升级版本后可能会改变API,如果我们的项目没有锁定版本,那么在更新库版本后可能会出现不兼容的问题。通过版本锁定,可以避免这种问题。
-
易于管理:通过版本锁定,可以清楚地知道项目使用的都是哪些版本的库,便于进行版本管理和升级。
因此,Maven的版本锁定是非常重要的,它可以保证构建的一致性,避免版本冲突和不兼容的问题,同时也便于管理。
使用方式
代码示例:
XML
<!--父类-->
<properties>
<maven.compiler.source>21</maven.compiler.source>
<maven.compiler.target>21</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<lombok.version>1.18.34</lombok.version>
</properties>
<dependencies>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>${lombok.version}</version>
</dependency>
</dependencies>
<!--统一管理依赖-->
<dependencyManagement>
<dependencies>
<!--JWT令牌-->
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>0.9.1</version>
</dependency>
<!--子类-->
<parent>
<groupId>com.sunny</groupId>
<artifactId>tlias-parent</artifactId>
<version>1.0-SNAPSHOT</version>
<relativePath>../tlias-parent/pom.xml</relativePath>
</parent>
<artifactId>tlias-pojo</artifactId>
<version>1.0-SNAPSHOT</version>
<dependencies>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
</dependency>
</dependencies>
自定义属性/引用属性
在Maven中,我们可以通过定义properties属性进行版本锁定。这些属性可以用来定义和管理项目中使用的各种依赖和插件版本。这样做的好处是,我们可以在一个地方集中管理所有的版本信息,然后在pom.xml文件的其他地方引用这些属性。
以下是一个使用properties属性进行版本锁定的示例:
XML
<project>
...
<properties>
<spring.version>5.0.8.RELEASE</spring.version>
<mybatis.version>3.4.6</mybatis.version>
<mysql.version>8.0.15</mysql.version>
...
</properties>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>${mybatis.version}</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>${mysql.version}</version>
</dependency>
...
</dependencies>
...
</project>
在这个示例中,我们定义了几个属性,如spring.version、mybatis.version和mysql.version,并在dependencies中引用这些属性来指定依赖的版本。这样,当我们需要升级或改变某个依赖的版本时,只需要修改对应的属性值即可,无需在整个pom.xml文件中搜索和替换。
补充:
3、聚合实现
说明
Maven的聚合是指一个Maven项目可以包含多个子项目,这个包含子项目的项目被称为聚合项目,或者叫做父项目。聚合主要是用来管理多个相关的项目,它们可以一起被构建和发布。
在Maven中,聚合是通过在父项目的POM文件中添加<modules>元素来实现的。在<modules>元素下,每个<module>元素都对应一个子项目的目录名。当在父项目目录下运行Maven命令时,这些命令会依次应用到每个子模块。
以下是一个简单的聚合实现示例:
XML
<project>
...
<packaging>pom</packaging>
<modules>
<module>module1</module>
<module>module2</module>
</modules>
...
</project>
在这个例子中,我们有一个父项目,它有两个子模块:module1和module2。这两个子模块的目录应该和父项目的POM文件在同一级目录下。当我们在父项目的目录下运行Maven命令,比如mvn install
,Maven会首先处理父项目,然后按照在<modules>元素中声明的顺序处理每个子模块。
需要注意的是,聚合和继承是Maven中两个不同的概念。聚合主要是为了同时管理和构建多个项目,而继承则是为了让子项目继承父项目的某些配置。在实际使用中,聚合和继承经常会一起使用,以实现更复杂的项目结构。
作用
Maven的聚合功能主要用于管理和构建多模块项目。其主要作用包括:
-
统一构建:当在父项目中执行Maven命令时,这些命令会依次应用到所有子模块。这样,我们可以一次性构建所有的模块,而不需要在每个模块的目录下分别执行构建命令。
-
统一管理:在父项目的POM文件中,我们可以定义一些通用的配置,比如插件的版本、编译的JDK版本等。这些配置会被所有的子模块继承,这样我们就可以在一个地方管理所有模块的这些配置。
-
便于协作:在大型的项目中,通常会有多个开发团队分别负责不同的模块。通过Maven的聚合功能,每个团队可以独立地开发和测试自己的模块,而不需要关心其他模块的细节。同时,由于所有的模块都是在同一个父项目下,所以整个项目的构建和发布也可以很容易地协调。
-
便于发布:当项目发布时,我们通常希望把所有的模块一起发布。通过Maven的聚合功能,我们可以一次性构建和发布所有的模块,而不需要分别发布每个模块。
总的来说,Maven的聚合功能可以使项目的构建、管理、协作和发布更加方便和高效。
图片说明
4、私服
说明
Maven私服(Maven Repository Manager)是一个专门用于存储、检索和管理构建工具(如Maven、Gradle等)使用的二进制软件工件和元数据的服务。它是一个中心化的资源管理系统,可以极大地提高构建的效率,减少构建的时间,并提供了一种可靠的方式来共享和发布软件工件。
Maven私服主要有以下几个作用:
-
提高构建速度:Maven在构建项目时,需要从远程仓库下载各种依赖包。如果这些依赖包在本地的Maven私服上就有,就不需要从远程仓库下载,从而可以大大提高构建的速度。
-
提供稳定的环境:有时,远程仓库可能会因为各种原因无法访问,这时就无法下载依赖包,从而导致构建失败。而Maven私服可以提供一个稳定的环境,确保构建的顺利进行。
-
共享和发布软件工件:Maven私服不仅可以用来存储第三方的依赖包,也可以用来存储和共享我们自己开发的软件工件。这样,其他项目就可以直接从私服上获取这些工件,而不需要我们手动地去分发。
-
版本控制:Maven私服可以帮助我们管理软件工件的各个版本,使得我们可以方便地回溯和定位问题。
目前,常见的Maven私服软件有Nexus、Artifactory等。
私服的上传与下载
私服的资源上传和下载是通过Maven的deploy和resolve机制来实现的。
- 上传资源:上传资源到Maven私服通常是通过Maven的deploy命令来完成的。在项目的pom.xml文件中,你需要配置distributionManagement元素,指定私服的URL。然后,你可以运行mvn deploy命令,Maven会把项目的构建结果(通常是jar或war文件)上传到私服。同时,Maven也会生成一些元数据文件(如pom.xml,checksum文件等)一并上传到私服。
你还需要在Maven的settings.xml文件中,配置私服的认证信息(用户名和密码),以便Maven可以登录到私服。
- 下载资源:下载资源从Maven私服是通过Maven的resolve机制来完成的。在项目的pom.xml文件中,你需要配置dependencies元素,声明项目的依赖。然后,当你运行Maven命令(如mvn compile或mvn package)时,Maven会自动从私服下载这些依赖。
在Maven的settings.xml文件中,你需要配置repositories元素,指定私服的URL。这样,Maven就会从这个URL下载依赖,而不是从默认的中央仓库下载。
注意,如果私服的URL需要认证,你也需要在settings.xml文件中,配置相应的认证信息。
仓库说明
在Maven私服中,我们通常会有三种类型的仓库:Hosted Repository(托管仓库)、Proxy Repository(代理仓库)和Group Repository(组仓库)。
-
Hosted Repository(托管仓库):托管仓库是私服中存储我们自己开发的工件(例如JAR,WAR,EAR文件等)的地方。当我们执行mvn deploy命令时,Maven会把构建的工件部署到托管仓库中。这种仓库可以是开放的,也可以是受保护的,只有经过身份验证的用户才能访问。
-
Proxy Repository(代理仓库):代理仓库是私服中用来缓存远程仓库中的工件的地方。当我们需要使用某个远程仓库中的工件时,Maven首先会查找代理仓库,如果代理仓库中有这个工件,就直接使用,如果没有,Maven就会从远程仓库下载这个工件,并把它缓存到代理仓库中,以便下次使用。
-
Group Repository(组仓库):组仓库是私服中用来聚合其他仓库(包括托管仓库和代理仓库)的地方。当我们配置Maven使用私服时,通常只需要配置一个组仓库的URL,Maven就可以访问到所有聚合的仓库中的工件。这样可以简化配置,也可以提高效率。
以上,这三种仓库类型可以灵活组合使用,以满足不同的需求。例如,我们可以创建一个组仓库,聚合一个托管仓库和几个代理仓库,这样就可以既能共享我们自己的工件,又能缓存远程仓库的工件。
注意:私服的上传操作我是有黑马提供的资料可以进行参考,在这就不多做解释,如果别人来看有疑惑的话,建议去搜索资料。