1 Maven简介
1.1 Maven是什么
Maven 是一个用于构建和管理 Java 项目的工具。它提供了一种标准化的项目结构和构建流程,可以自动化地处理项目的依赖管理、编译、测试、打包和部署等任务。
Maven 使用一个基于 XML 的配置文件(pom.xml)来描述项目的结构和依赖关系。
Maven的本质是一个项目管理工具,将项目开发和管理过程抽象成一个项目对象模型(POM)
POM(Project Object Model):项目对象模型
1.2 Maven的作用
主要作用:
- 项目构建:提供标准的、跨平台的自动化项目构建方式
- 依赖管理:方便快捷的管理项目依赖的资源(jar包),避免资源间的版本冲突问题
- 统一开发结构:提供标准的、统一的项目结构
1.3 Maven主要特点
- 依赖管理:Maven 可以自动下载和管理项目所需的依赖库,简化了项目的构建和部署过程。
- 构建生命周期:Maven 定义了一套标准的构建生命周期,包括编译、测试、打包、部署等阶段,可以通过简单的命令来执行这些阶段。
- 插件系统:Maven 提供了丰富的插件系统,可以扩展和定制项目的构建过程。
- 多模块支持:Maven 支持将一个大型项目拆分为多个模块,每个模块可以独立构建和测试,也可以作为其他模块的依赖。
- 中央仓库:Maven 提供了一个中央仓库,包含了大量的开源库和组件,可以方便地搜索和下载这些库。
1.4 Maven仓库
- 仓库:用于存储资源,包含各种jar包
- 仓库分类:
- 本地仓库(Local Repository):自己电脑上存储资源的仓库(默认在用户的主目录下的 .m2 文件夹中),连接远程仓库获取资源
- 远程仓库:非本机电脑上的仓库,为本地仓库提供资源
- 中央仓库(Central Repository):Maven团队维护,存储所有资源的仓库。Maven 默认配置了中央仓库作为主要的远程仓库
- 私服:部门/公司范围内存储资源的仓库,从中央仓库获取资源
- 私服的作用:
- 保存具有版权的资源,包含购买或自主研发的jar
- 中央仓库中的jar都是开源的,不能存储具有版权的资源
- 一定范围内共享资源,仅对内部开放,不对外共享
- 保存具有版权的资源,包含购买或自主研发的jar
除了中央仓库(远程仓库)和本地仓库,Maven 还支持自定义远程仓库。你可以在项目的配置文件(pom.xml)中添加其他远程仓库的配置,以便下载非中央仓库中的依赖。例如,你可以添加私有仓库或第三方仓库的配置。
1.5 坐标
-
什么是坐标?
- Maven中的坐标用于描述仓库中资源的位置
- https://repo1.maven.org/maven2/
-
Maven坐标主要组成
- groupld:定义当前Maven项目隶属组织名称(通常是域名反写,例如:org.mybatis)
- artifactld:定义当前Maven项目名称(通常是模块名称,例如CRM、SMS)
- version:定义当前项目版本号
- packaging:定义该项目的打包方式,默认为jar
-
Maven坐标的作用
- 使用唯一标识,唯一性定位资源位置,通过该标识可以将资源的识别与下载工作交由机器完成
2 Maven的安装与配置
2.1 Maven的安装
1)Maven是使用Java编写的,使用Maven前,需要配置好JDK环境,配置好JAVA_HOME
2)下载Maven压缩包解压即安装成功
3)配置MAVEN_HOME
4)将MAVEN_HOME配置到环境变量Path下面,如 :
%MAVEN_HOME%/bin
5)查看Maven版本
2.2 本地仓库配置
Maven启动后,会自动保存下载到的资源(一般为jar包)到本地仓库
- 默认的本地仓库位置
<localRepository>${user.home}/.m2/repository</localRepository>
- 建议自定义本地仓库位置
打开${MAVEN_HOME}\conf\settings.xml文件,配置如下
<localRepository>D:\sofeware\apache-maven-3.6.0\mvn_resp</localRepository>
说明:
mvn_resp目录需要我们自行创建
2.3 镜像仓库配置
- Maven默认连接的中央仓库配置
<repositories>
<repository>
<id>central</id>
<name>Central Repository</name>
<url>http://repo.maven.apache.org/maven2</url>
<layout>default</layout>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
</repositories>
注意:
由于网络原因或仓库维护问题,有时候从默认的远程仓库下载依赖可能会出现问题。在这种情况下,你可以尝试切换到其他可靠的远程仓库或使用镜像仓库来加速下载。
- 在 settings.xml 文件在配置阿里云镜像仓库
<mirrors>
<!-- 配置具体的仓库的下载镜像 -->
<mirror>
<!-- 此镜像的唯一标识符,用来区分不同的mirror元素-->
<id>alimaven</id>
<!-- 镜像名称 -->
<name>aliyun maven</name>
<!-- 镜像URL -->
<url>http://maven.aliyun.com/nexus/content/groups/public/</url>
<!-- 对哪种仓库进行镜像,简单来说就是替代哪个仓库(我们这里是替代中央仓库)-->
<mirrorOf>central</mirrorOf>
</mirror>
</mirrors>
3 IDEA集成Maven
File --> Settings --> Build, Execution, Deployment --> Build Tools --> Maven
4 Maven项目的创建
4.1 手动创建Macen模块
File --> Project Structure --> 选择 Modules --> 点击➕号 --> New Module --> 选择 Maven --> Next -->
点击 FINISH --> APPLY --> OK
创建好的Maven模块如下:
4.2 使用原型创建Maven模块
File --> Project Structure --> 选择 Modules --> 点击➕号 --> New Module --> 选择 Maven
Next -->
Next -->
点击 FINISH --> APPLY --> OK
创建好补齐项目结合后的Maven模块如下:
4.3 使用原型创建web模块
File --> Project Structure --> 选择 Modules --> 点击➕号 --> New Module --> 选择 Maven
Next -->
Next -->
点击 FINISH --> APPLY --> OK
创建好补齐项目结合后的Maven模块如下:
4.4 Maven配置Tomcat7插件
pom.xml
<build>
<plugins>
<plugin>
<groupId>org.apache.tomcat.maven</groupId>
<artifactId>tomcat7-maven-plugin</artifactId>
<version>2.1</version>
<configuration>
<port>80</port>
<path>/</path>
</configuration>
</plugin>
</plugins>
</build>
5 依赖管理
依赖管理其实就是管理项目所依赖的第三方资源(jar包、插件…)
-
传统导入jar包方法
- 下载jar包
- 复制jar包到项目(一般在根目录下会创建lib目录)
- 将jar包加入到工作环境
-
使用Maven以后
直接在pom.xml导入相应坐标即可
Maven 提供了强大的依赖管理功能,可以帮助项目自动下载和管理所需的依赖库。
5.1 依赖库坐标(Dependency Coordinates)
在 Maven 中,每个依赖库都有一个唯一的坐标来标识,包括组织(Group)、名称(Artifact)和版本(Version)等信息。坐标通常以以下格式表示:<groupId>:<artifactId>:<version>
。
例如:
<!-- 配置当前项目所有的jar包 -->
<dependencies>
<!-- 配置具体的依赖 -->
<dependency>
<!-- 依赖所属群组id -->
<groupId>mysql</groupId>
<!-- 依赖所属项目id -->
<artifactId>mysql-connector-java</artifactId>
<!-- 依赖版本号 -->
<version>5.1.34</version>
</dependency>
</dependencies>
5.2 依赖传递
依赖库传递性(Dependency Transitivity):Maven 支持依赖库之间的传递性关系。当一个依赖库 A 依赖于另一个依赖库 B,Maven 会自动下载和管理依赖库 B,并将其添加到项目的类路径中。这样,可以通过声明项目对依赖库 A 的依赖,间接地管理依赖库 B
依赖的传递性
- 直接依赖:在当前项目中通过依赖配置建立的依赖关系
- 间接依赖:被依赖的资源如果依赖与其他的资源,当前项目间接依赖于其他资源
5.3 依赖传递冲突
依赖库冲突解决(Dependency Conflict Resolution):当项目中存在多个依赖库对同一个库的不同版本有依赖时,可能会导致冲突。Maven 会根据一定的规则来解决依赖库冲突,默认情况下,会选择最近的版本。可以通过在 POM 文件中显式声明依赖库的版本,或者使用 Maven 提供的冲突解决机制来解决冲突。
Maven 提供的冲突解决机制
- 路径优先:当依赖中出现相同的资源,层级越深,优先级越低,层级越浅,优先级越高
- 声明优先:当资源在相同层级被依赖时,配置顺序靠前的覆盖配置顺序靠后的
- 特殊优先:当同级配置了相同资源的不同版本,后配置的覆盖先配置的
5.4 可选依赖
可以使用可选依赖(Optional Dependencies)来声明一些可选的依赖库。可选依赖是指在某些特定的情况下,项目可能需要使用的依赖库,但并不是必需的。
例如,当项目需要与某个特定的第三方库进行集成时,可以将该库声明为可选依赖。这样,在构建项目时,如果用户选择了与该库集成的选项,Maven 会自动下载和管理该库的依赖。如果用户不需要该库的集成功能,可以不包含该可选依赖,从而减少项目的依赖和构建时间。
简单来说,可选依赖就是指对外隐藏当前所依赖的资源——不透明
要声明可选依赖,可以在项目的 POM 文件中使用 <dependencies>
元素下的 <dependency>
元素,并在其中使用 <optional>
元素来指定依赖库的可选性。
例如:
<!-- 配置当前项目所有的jar包 -->
<dependencies>
<!-- 配置具体的依赖 -->
<dependency>
<!-- 依赖所属群组id -->
<groupId>junit</groupId>
<!-- 依赖所属项目id -->
<artifactId>junit</artifactId>
<!-- 依赖版本号 -->
<version>4.12</version>
<!-- 标记为可选依赖 -->
<optional>true</optional>
</dependency>
</dependencies>
声明为可选依赖。当构建项目时,如果需要使用该库,可以在命令行或构建配置中明确指定该依赖。
例如,使用以下命令构建项目时,可选依赖将被包含:
mvn clean install -DincludeOptional=true
注意:
可选依赖并不会自动传递给其他依赖库。如果某个依赖库依赖于可选依赖,需要显式地将可选依赖声明为该依赖库的直接依赖。这样,当该依赖库被使用时,可选依赖才会被自动下载和管理。
5.5 排除依赖
可以使用排除依赖(Exclusions)来排除项目中不需要的依赖库。排除依赖可以帮助减少项目的依赖冲突和依赖数量,从而简化项目的构建和管理。
简单来说,排除依赖是指主动断开所依赖的资源,被排除的资源无需指定版本——不需要
要排除依赖,可以在项目的 POM 文件中使用 <dependencies>
元素下的 <dependency>
元素,并在其中使用 <exclusions>
元素来指定要排除的依赖库。
例如:
<!-- 配置当前项目所有的jar包 -->
<dependencies>
<!-- 配置具体的依赖 -->
<dependency>
<!-- 依赖所属群组id -->
<groupId>junit</groupId>
<!-- 依赖所属项目id -->
<artifactId>junit</artifactId>
<!-- 依赖版本号 -->
<version>4.12</version>
<!-- 排除依赖 -->
<exclusions>
<exclusion>
<groupId>org.hamcrest</groupId>
<artifactId>hamcrest-core</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
在上面的示例中,junit
依赖被声明,并且排除了 hamcrest-core
依赖。当构建项目时,Maven 会自动排除 hamcrest-core
依赖,不会将其包含在项目中。
排除依赖可以用于解决依赖冲突的问题。当项目中存在多个依赖库,它们依赖于同一个库的不同版本时,可能会导致冲突。通过排除其中一个版本,可以确保项目使用的是所需的版本,避免冲突。
注意:
排除依赖只会影响当前依赖的传递性依赖。如果其他依赖库也依赖于被排除的库,需要在相应的依赖声明中进行排除。此外,排除依赖也可能导致功能缺失或不完整,因此需要谨慎使用。
使用排除依赖可以帮助简化项目的依赖管理,但需要根据实际需求和项目的特点来决定是否使用排除依赖。应仔细考虑依赖冲突和功能需求,确保排除依赖不会对项目的功能和稳定性产生负面影响。
5.6 依赖范围 scope
依赖库范围(Dependency Scope):Maven 支持为依赖库指定不同的范围,以控制依赖库在不同阶段的使用。
作用范围:
- 主程序范围有效(main目录内生效)
- 测试程序范围有效(test目录内生效)
- 是否参与打包(package指令范围内)
常用的依赖库范围包括:
compile
:默认范围,表示依赖库在编译、测试和运行时都可用。test
:表示依赖库仅在测试阶段可用,不会被打包到最终的构建结果中。provided
:表示依赖库由运行环境提供,例如 Java EE 容器中的 API。runtime
:表示依赖库仅在运行时可用,不会被编译和测试阶段使用。
scope | 主代码 | 测试代码 | 打包 | 示例 |
---|---|---|---|---|
compile(默认) | ✔ | ✔ | ✔ | log4j |
test | ✔ | junit | ||
provided | ✔ | ✔ | servlet-api | |
runtime | ✔ | jdbc |
compile > test > provided > runtime
可以通过在 <dependency>
元素中使用 <scope>
元素来指定依赖库的范围
例如:
<!-- 配置当前项目所有的jar包 -->
<dependencies>
<!-- 配置具体的依赖 -->
<dependency>
<!-- 依赖所属群组id -->
<groupId>mysql</groupId>
<!-- 依赖所属项目id -->
<artifactId>mysql-connector-java</artifactId>
<!-- 依赖版本号 -->
<version>5.1.34</version>
<!-- 依赖范围 -->
<scope>runtime</scope>
</dependency>
</dependencies>
5.7 依赖范围的传递性
- 带有依赖范围的资源在进行传递时,作用范围将会受到影响
间接依赖\直接依赖 | compile | test | provided | runtime |
---|---|---|---|---|
compile | compile | test | provided | runtime |
test | ||||
provided | ||||
runtime | runtime | test | provided | tuntime |
解读:
直接依赖compile 、间接依赖 compile ==> 最终 compile
直接依赖test 、间接依赖 compile ==> 最终 test
直接依赖compile 、间接依赖 runtime ==> 最终 runtime
5.9 生命周期与插件
5.9.1 项目构建生命周期
项目构建周期(Build Lifecycle)是 Maven 中定义的一组标准构建阶段(Build Phase)的顺序集合。
通过定义和配置构建周期,可以按照一定的顺序执行这些构建阶段,从而完成项目的构建过程。
Maven 的标准构建周期包括三个主要的构建阶段:
- clean 阶段:该阶段用于清理项目,删除之前构建生成的文件和目录。主要的构建目标包括 clean。
- default(或称为 build)阶段:该阶段是项目构建的核心阶段,包括编译代码、运行测试、打包等任务。主要的构建目标包括 validate、compile、test、package、install、deploy。
- site 阶段:该阶段用于生成项目的站点文档和报告。主要的构建目标包括 site、site-deploy。
clean生命周期
- pre-clean:执行一些需要在clean之前完成的工作
- clean:移除所有上一次构建生成的文件
- post-clean:执行一些需要在clean之后立刻完成的工作
defalut生命周期
常用的
- compile(编译):编译项目源代码
- test-compile(编译测试源码):编译测试源代码到测试目标目录
- test(测试):使用合适的单元测试框架进行测试,例如junit
- package(打包):将编译后的代码打包成可分发的文件,例如JAR、WAR或EAR
- install(安装):安装项目包到本地仓库,这样项目包可以用到其他本地项目的依赖中
site生命周期
- pre-site:执行一些需要生成站点文档之前完成的工作
- site:生成项目的站点文档
- post-site:执行一些需要生成站点文档之后完成的工作,并且为部署做准备
- site-deploy:将生成的站点文档部署到特点的服务器上
在执行 Maven 构建时,默认情况下会按照上述构建周期的顺序依次执行各个构建阶段。例如,执行 mvn clean install
命令会先执行 clean 阶段,然后执行 default 阶段中的 install (并且在defalut阶段中所有在install之前的生命周期都会执行)。
IDEA中提供的生命周期快捷键
5.9.2 插件
- 插件和生命周期内的阶段绑定,在执行到对应生命周期时执行对应的插件功能
- 默认maven在各个生命周期上绑定有预设的功能
- 通过插件可以自定义其他功能
Maven 提供了一些常用的插件:
maven-compiler-plugin
:用于编译 Java 代码。maven-surefire-plugin
:用于运行单元测试。maven-jar-plugin
:用于打包项目为 JAR 文件。maven-war-plugin
:用于打包项目为 WAR 文件。maven-deploy-plugin
:用于将构建结果部署到远程仓库
插件使用的语法:
mvn [plugin-name]:[goal-name]
例如:
一个Java工程可以使用maven-compiler-plugin 的compile-gila 编译
mvn compiler:compile
IDEA中提供的插件快捷键
5.10 常用插件
maven-compiler-plugin
设置maven编译的JDK版本,maven3默认使用的是jdk1.5,maven2默认使用的是jdk1.3
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.10.1</version>
<configuration>
<source>1.8</source><!-- 源代码使用的JDK版本 -->
<target>1.8</target><!-- 需要生成的目标class文件的编译版本 -->
<encoding>UTF-8</encoding><!-- 字符集编码 -->
</configuration>
</plugin>
</plugins>
</build>
注意pom中需要放入如下属性
<properties>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
</properties>
或者
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
</properties>
Scala源码编译为class 插件
<!-- 该插件用于将 Scala 代码编译成 class 文件 -->
<plugin>
<groupId>net.alchim31.maven</groupId>
<artifactId>scala-maven-plugin</artifactId>
<version>3.2.2</version>
<executions>
<execution>
<!-- 声明绑定到 maven 的 compile 阶段 -->
<goals>
<goal>compile</goal>
<goal>testCompile</goal>
</goals>
</execution>
</executions>
</plugin>
Tomcat7插件
在pom中加入该插件,可以通过插件和命令启动项目,不用将项目部署到tomcat里了
<build>
<plugins>
<plugin>
<groupId>org.apache.tomcat.maven</groupId>
<artifactId>tomcat7-maven-plugin</artifactId>
<version>2.1</version>
<configuration>
<port>80</port>
<path>/clear</path>
<finalName>clear</finalName>
</configuration>
</plugin>
</plugins>
</build>
注意:
如果是一个web项目,则该项目的打包方式为war,加入如下
<packaging>war</packaging>
打war包插件
<build>
<plugins>
<!-- maven-war-plugin:mvn install可以将项目打成war包 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<configuration>
<warName>test</warName>
<webResources>
<resource>
<filtering>true</filtering>
<!-- 需要打包的目标文件路径 -->
<directory>src/main/webapp/WEB-INF</directory>
<!-- 指定build资源具体目录,默认是base directory -->
<targetPath>WEB-INF</targetPath>
<!-- 打包的文件叫什么 -->
<includes>
<include>web.xml</include>
</includes>
</resource>
</webResources>
</configuration>
</plugin>
</plugins>
</build>
打jar包插件
<!--maven的打包插件-->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<!-- 将项目打包成可执行的 JAR 文件,并包含所有的依赖项-->
<artifactId>maven-assembly-plugin</artifactId>
<version>3.1.1</version>
<configuration>
<descriptorRefs>
<!-- 将所有依赖项打包到生成的 JAR 文件中 -->
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
<archive>
<manifest>
<!-- mainClass标签填写主程序入口-->
<addClasspath>true</addClasspath>
<mainClass>com.clear.wordcount.JavaSparkWordCount</mainClass>
</manifest>
</archive>
</configuration>
<executions>
<execution>
<id>make-assembly</id>
<!-- 绑定到package生命周期-->
<phase>package</phase>
<goals>
<!-- 只运行一次 -->
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
Maven-jar-plugin
Maven-jar-plugin是Maven自带的一个插件,它主要用于将项目打包成jar包,一般情况下,Maven执行package命令时就会默认调用该插件完成jar包生成的工作。
使用该插件可以实现以下功能:
- 生成标准格式的jar包;该jar包可以直接部署到Maven的本地仓库或远程仓库
- 过滤构建输出文件;
- 指定程序入口;
- 指定manifest文件;
- 设置jar包的依赖项,用于引用其他组件等等。
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>2.4</version>
<configuration>
<archive>
<manifest>
<!-- mainClass标签填写主程序入口-->
<mainClass>com.clear.demo1.CreateFileUtil</mainClass>
<addClasspath>true</addClasspath>
<classpathPrefix>lib/</classpathPrefix>
</manifest>
<!-- 滤掉target目录下所有文件 -->
<excludes>
<exclude>target</exclude>
</excludes>
</archive>
<classesDirectory>
</classesDirectory>
</configuration>
</plugin>
6 Maven环境下分模块开发与设计
在 Maven 中进行分模块设计与开发可以帮助组织和管理项目的结构和依赖关系。下面是一些在 Maven 中进行分模块设计与开发的常见做法和建议:
- 模块划分:根据项目的功能和业务需求,将项目划分为多个独立的模块。每个模块应该具有清晰的职责和功能边界,可以根据模块的功能进行划分,例如将业务逻辑、数据访问、界面展示等功能划分为不同的模块。
- Maven 多模块项目:使用 Maven 的多模块项目(Multi-module Project)功能来组织和管理模块。在 Maven 的项目结构中,可以将每个模块作为一个子项目(Module)来管理,每个子项目都有自己的独立的目录结构和配置文件。
- 父子模块关系:在 Maven 的多模块项目中,可以使用父子模块关系来管理模块之间的依赖关系。通过在父项目的 pom.xml 文件中定义子模块,可以统一管理子模块的版本和依赖关系,确保模块之间的一致性和协作。
- 模块间依赖管理:在每个模块的 pom.xml 文件中,定义模块之间的依赖关系。可以使用 Maven 的依赖管理功能来管理模块之间的依赖,确保模块之间的依赖关系正确和一致。
- 模块独立开发:每个模块可以由专门的团队或开发者负责开发和维护,确保模块的独立性和自治性。每个模块可以有自己的代码、测试和文档,可以独立进行构建、测试和发布。
- 模块集成测试:在进行模块集成时,可以使用 Maven 的集成测试功能来进行测试和验证。可以定义一个专门的模块用于进行模块间的集成测试,确保模块之间的协作和交互正常。
- 模块文档和文档:为每个模块编写清晰的文档和说明,包括模块的功能、接口、使用方法等。这有助于其他开发者理解和使用模块,并提供必要的支持和维护。
通过在 Maven 中进行分模块设计与开发,可以更好地组织和管理项目的结构和依赖关系,提高项目的可维护性和可扩展性。同时,也有助于团队协作和并行开发,提高开发效率和质量。
例如,现在我们有一个ssm的项目,包含pojo、dao、service、controller等包,我们现在要将这个模块划分为多个小的模块
6.1 pojo 模块划分
主要工作
- 1)新建模块
- 2)拷贝原始项目中对应的相关内容到ssm_pojo模块中(有则拷贝,无则忽略)
- 实体类
- 配置文件
1 创建模块
2 拷贝原项目中pojo,拷贝完成如下
3 编译pojo模块,若无报错,pojo模块拆分成功
6.2 dao 模块划分
主要工作
- 1)新建模块
- 2)拷贝原始项目中对应的相关内容到ssm_dao模块中(有则拷贝,无则忽略)
- 数据层接口
- 配置文件
- 在pom.xml中引入相关坐标
- **直接依赖于ssm_pojo(**在此之前必须对ssm_pojo模块进行install指令,安装模块jar到本地仓库)
1 创建模块
2 解决资源问题
即将pojo模块中的pom坐标加入到当前模块的pom中(以资源的形式加载pojo中可能会使用到的资源)
如下:
<!--导入资源文件pojo-->
<dependency>
<groupId>com.clear</groupId>
<artifactId>ssm_pojo</artifactId>
<version>1.0</version>
</dependency>
3 拷贝原项目中dao,拷贝完成如下
4 编译dao模块,若无报错,dao模块拆分成功
如下遇到如下错误
[ERROR] Failed to execute goal on project ssm_dao: Could not resolve dependencies for project com.clear:ssm_dao:jar:1.0:
说明本地仓库中没有pojo模块资源,坐标加载失败,我们只需要为pojo模块执行install命令即可
6.3 service 模块划分
主要工作
- 1)新建模块
- 2)拷贝原始项目中对应的相关内容到ssm_service模块中(有则拷贝,无则忽略)
- 业务层接口和实现类
- 配置文件
- 在pom.xml中引入相关坐标
- 直接依赖于ssm_dao(在此之前必须对ssm_dao模块进行install指令,安装模块jar到本地仓库)
- 间接依赖于ssm_pojo(由ssm_dao模块负责依赖关系的建立)
1 新建模块
2 解决资源问题
即将dao模块中的pom坐标加入到当前模块的pom中(以资源的形式加载dao中可能会使用到的资源)
如下:
<!--导入资源文件dao-->
<dependency>
<groupId>com.clear</groupId>
<artifactId>ssm_dao</artifactId>
<version>1.0</version>
</dependency>
3 拷贝原项目中service,拷贝完成如下
4 编译service模块,若无报错,service模块拆分成功
6.4 controller 模块划分
主要工作
- 1)新建模块
- 2)拷贝原始项目中对应的相关内容到ssm_controller模块中(有则拷贝,无则忽略)
- 表现层类
- 配置文件
- 在pom.xml中引入相关坐标
- 直接依赖于ssm_service(在此之前必须对ssm_service模块进行install指令,安装模块jar到本地仓库)
- 间接依赖于ssm_dao、ssm_pojo
1 新建模块
2 解决资源问题
即将service模块中的pom坐标加入到当前模块的pom中(以资源的形式加载service中可能会使用到的资源)
如下:
<!--导入资源文件service-->
<dependency>
<groupId>com.clear</groupId>
<artifactId>ssm_service</artifactId>
<version>1.0</version>
</dependency>
3 拷贝原项目中controller,拷贝完成如下
4 编译controller模块,若无报错,controller模块拆分成功
7 聚合
7.1 多模块的构建维护问题
比如我们前面拆分的ssm项目,拆分成了ssm_controller、ssm_service、ssm_dao、ssm_pojo
依赖关系:ssm_controller --> ssm_service --> ssm_dao --> ssm_pojo
如果我们现在ssm_dao模块更新了(install了以后),可能会产生问题
解决思路:
我们用一个新的模块,管理ssm_controller、ssm_service、ssm_dao、ssm_pojo这四个模块,我们只需要install这个模块,其他四个模块就会被更新
演示:
1 新建管理模块
2 删除无用的src
因为我们这个模块是用于管理的,只需要pom.xml即可,如下
3 配置pom.xml
<!-- 定义该工程用于构建管理 -->
<packaging>pom</packaging>
<!-- 管理的工程列表 -->
<modules>
<!-- 具体的工程名称 -->
<!-- 这里的书写顺序影响不大:maven会自动处理 -->
<module>../ssm_controller</module>
<module>../ssm_dao</module>
<module>../ssm_pojo</module>
<module>../ssm_service</module>
</modules>
7.2 聚合总结
-
作用:聚合用于快速构建maven工程,一次性构建多个项目/模块
-
制作聚合管理模块的方式:
-
创建一个空模块,打包类型定义为pom
-
<packaging>pom</packaging>
-
定义当前模块进行构建操作时管理的其他模块名称
-
例如:
-
<modules> <module>../ssm_controller</module> <module>../ssm_dao</module> <module>../ssm_pojo</module> <module>../ssm_service</module> </modules>
-
-
注意:参与聚合操作的模块的最终执行顺序与模块间的依赖有关系,与配置顺序有关
-
8 继承
8.1 继承与聚合的联系
- 作用:
- 聚合用于快速构建项目
- 继承用于快速配置
- 相同点:
- 聚合和继承的pom.xml 文件打包方式均为pom,可以将两种关系制作到同一个pom.xml文件中
- 聚合和继承均属于设计型模块,并无实际的模块内容
- 不同点:
- 聚合是在当前模块中配置关系,聚合可以感知到参与聚合的模块有哪些
- 继承是在子模块中配置关系,父模块无法感知哪些子模块继承了自己
8.2 dependence依赖在继承中的体现
基本用法:
- 在父模块中的 <dependencyManagement> 标签下声明若干个依赖,只声明不使用
- 在子模块中的 <parent> 标签下指定该子模块的父模块
- 在子模块的 <dependencies> 标签下直接使用 父模块中 <dependencyManagement> 标签下声明的依赖(不用填写version版本)
演示:
1)父模块中声明出依赖
<!-- 父模块中声明出依赖:进行依赖管理 -->
<dependencyManagement>
<!-- 具体所有的依赖,父模块只声明不使用,子模块中需要直接调用即可 -->
<dependencies>
<!--添加slf4j日志api-->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.20</version>
</dependency>
<!--添加logback-classic依赖-->
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.2.3</version>
</dependency>
<!--添加logback-core依赖-->
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-core</artifactId>
<version>1.2.3</version>
</dependency>
</dependencies>
</dependencyManagement>
2)子模块中指定自己的父模块,并在子模块中引用依赖
<!-- 指定自己的父模块 -->
<parent>
<artifactId>ssm</artifactId>
<groupId>com.clear</groupId>
<version>1.0</version>
</parent>
<dependencies>
<!-- 引用父模块中声明的依赖 -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<!-- 引入父模块中声明的依赖,不需要指定version-->
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-core</artifactId>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
</dependency>
</dependencies>
8.3 plugin在继承中的体现
基本用法:
- 在父模块中的 <pluginManagement> 标签下声明若干个插件,只声明不使用
- 在子模块中的 <parent> 标签下指定该子模块的父模块
- 在子模块的 <plugins> 标签下直接使用 父模块中 <pluginManagement> 标签下声明的插件(不用填写version版本)
演示:
1)父模块中声明出插件
<pluginManagement><!-- 只声明,不直接引入,子模块需要直接引入即可 -->
<plugins>
<!--maven的打包插件-->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<!-- 将项目打包成可执行的 JAR 文件,并包含所有的依赖项-->
<artifactId>maven-assembly-plugin</artifactId>
<version>3.1.1</version>
<executions>
<execution>
<id>make-assembly</id>
<!-- 绑定到package生命周期-->
<phase>package</phase>
<goals>
<!-- 只运行一次 -->
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
<!-- 该插件用于将 Scala 代码编译成 class 文件 -->
<plugin>
<groupId>net.alchim31.maven</groupId>
<artifactId>scala-maven-plugin</artifactId>
<version>3.2.2</version>
<executions>
<execution>
<!-- 声明绑定到 maven 的 compile 阶段 -->
<goals>
<goal>compile</goal>
<goal>testCompile</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</pluginManagement>
2)子模块中指定自己的父模块,并在子模块中引用插件
<parent>
<artifactId>mrs</artifactId>
<groupId>com.clear</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<build>
<plugins>
<!-- 引入父模块中声明的plugin(子模块引入时不需要声明配置和版本,直接引用即可)-->
<plugin>
<groupId>net.alchim31.maven</groupId>
<artifactId>scala-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
9 属性
在 Maven 中,属性(Properties)是一种用于定义和引用可重用值的机制。属性可以在 Maven 的配置文件中定义,并在其他地方引用和使用。
属性类别
- 自定义属性
- 内置属性
- Setting属性
- Java系统属性
- 环境变量属性
9.1 自定义属性
自定义属性:可以定义自己的属性,用于在 POM 文件中引用和使用。等同于定义变量,方便对依赖版本的维护
定义格式:
<properties>
<spring.version>5.2.1.RELEASE</spring.version>
</properties>
调用格式:
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring.version}</version>
</dependency>
9.2 内置属性
内置属性:使用maven内置属性,快速配置
调用格式:
${basedir}
${version}
9.3 Setting属性
使用Maven配置文件setting.xml的标签属性,用于动态配置
调用格式:
${settings.localRepository}
9.4 Java系统属性
可以读取Java系统属性
调用格式:
${user.home}
系统属性查询方式:
mvn help:system
9.5 版本统一的重要性
错误示例:
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.2.1.RELEASE</version>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.5</version>
</dependency>
<!-- spring整合jdbc -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>5.1.9.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.1.9.RELEASE</version>
</dependency>
我们发现spring相关的依赖,有些为 5.2.1.RELEASE,又有一些为 5.1.9.RELEASE,这种版本不一致的问题,在生产中可能会遇到意想不到的错误
正确示例:
<!-- 自定义属性-->
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
<spring.version>5.2.1.RELEASE</spring.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.5</version>
</dependency>
<!-- spring整合jdbc -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>${spring.version}</version>
</dependency>
</dependencies>
10 版本管理
10.1 工程版本
- SNAPSHOT(快照版本)
项目开发过程中,为方便团队合作,解决模块间相互依赖和时时更新的问题,开发者对每个模块进行构建的时候,输出的临时性版本叫快照版本(测试阶段版本)
快照版本会随着开发的进展不断更新
- RELEASE(发布版本)
- 项目开发到进入阶段里程碑后,向团队外部发布较为稳定的版本,这种版本所对应的构建文件是稳定的,即便后续进行功能的开发,也不会影响当前发布的内容,这种版本叫发布版本
10.2 工程版本号约定
-
约定规范:
- <主版本>.<次版本>.<增量版本>.<里程牌版本>
- 主版本:表示项目重大架构的变更,如:Spring5相较于spring4的变更
- 此版本:表示有较大的功能增加和变化,或者全面系统的修复漏洞
- 增量版本:表示有重大漏洞的修复
- 里程牌版本:表明一个版本的里程牌(版本内部)。这样的版本同下一个正式版相比,相对来说是不稳定的
-
示例:
- 5.2.1.RELEASE
11 资源配置(资源配置多文件维护)
Maven 的资源管理是指在项目构建过程中,如何管理和处理项目中的资源文件。资源文件可以包括配置文件、静态资源、模板文件等。
Maven 提供了一种标准的方式来管理和处理项目中的资源文件。在 Maven 项目中,通常将资源文件放置在 src/main/resources
目录下。这些资源文件会被 Maven 自动复制到生成的构建目录(如 target/classes
)中,以便在运行时可以访问到这些资源文件。
Maven 会根据资源文件的类型进行不同的处理:
- 对于普通的文本文件,Maven 会直接将其复制到构建目录中,不做任何修改。
- 对于二进制文件(如图片、字体等),Maven 会直接将其复制到构建目录中,不做任何修改。
- 对于一些特殊的资源文件(如属性文件(properties等)、XML 文件等),Maven 可以对其进行一些处理,例如替换变量、合并文件等。你可以使用 Maven 的资源过滤功能来实现这些处理。
问题引入:
在开发中,我们会面临多个依赖的版本问题,我们可以通过自定义属性来管理,如下
<!-- 自定义属性-->
<properties>
<spring.version>5.2.1.RELEASE</spring.version>
<junit.version>4.12</junit.version>
</properties>
<!-- 通过自定义属性快捷控制下面坐标的版本-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>${junit.version}</version>
<scope>test</scope>
</dependency>
但是像 properties 格式文件以往我们是无从下手的,如下
# MySQL Server 配置
server.port=3306
# 数据库连接配置
database.url=jdbc:mysql://localhost:3306/db1
database.username=root
database.password=123456
配置文件中使用pom属性
解决方式:
我们在这种配置文件(如 properties)的各种属性可以抽取到pom.xml 中的自定义属性中,然后中配置文件引入即可
如下:
修改后的pom.xml
<!-- 自定义属性-->
<properties>
<spring.version>5.2.1.RELEASE</spring.version>
<junit.version>4.12</junit.version>
<jdbc.url>jdbc:mysql://localhost:3306/db1</jdbc.url>
</properties>
修改后的properties
# MySQL Server 配置
server.port=3306
# 数据库连接配置
database.url=${jdbc.url}
database.username=root
database.password=123456
注意:
此时我们的配置文件properties 中使用的 自定义属性还未生效,需要在pom中加入如下
<build>
<!-- 配置资源文件对应信息-->
<resources>
<resource>
<!-- 指定资源配置文件所在目录:模块名/src/main/resources-->
<directory>ssm_dao/src/main/resources</directory>
<!-- 也可以怎么写-->
<!--<directory>${project.basedir}/src/main/resources</directory>-->
<filtering>true</filtering>
</resource>
</resources>
</build>
如果测试目录test中的resouces目录中的资源文件也想引用pom中的自定义属性,可以在pom加入如下
<build>
<!-- 配置测试资源文件对应信息-->
<testResources>
<testResource>
<directory>${project.basedir}/src/test/resources</directory>
<filtering>true</filtering>
</testResource>
</testResources>
</build>
配置文件中使用pom属性基本格式
- 作用:
在任意配置文件中加载pom文件中属性(包括自定义属性、内置属性等)
- 在配置文件中的调用格式:
${属性名}
- 开启配置文件加载pom属性:
<build>
<!-- 配置资源文件对应信息-->
<resources>
<resource>
<!-- 设定配置文件对应的位置目录,支持使用属性动态设置路径 -->
<directory>${project.basedir}/src/main/resources</directory>
<!-- 开启对配置文件的资源加载过滤 -->
<filtering>true</filtering>
</resource>
</resources>
</build>
12 多环境开发配置
为什么要配置多环节开发配置。例如说,我们在开发中使用的 jdbc.url为 jdbc:mysql://localhost:3306/db1,测试环境使用的jdbc.url为 jdbc:mysql://192.168.188.128:3306/db1 ,那么我们可能需要去修改pom或配置文件,这样显得很麻烦。可以通过多环境开发配置解决
12.1 多环节开发配置基本格式
- 作用:
我们可以加载指定的环境配置
- 调用格式:
mvn 指令 -P 环境定义ID
例如:
开发环境打包jar
mvn install -P dev_env
测试环境打包jar
mvn install -P test_env
12.1 多环节开发配置演示
pom
<!-- 创建多环境-->
<profiles>
<!-- 定义具体的环境:开发环境-->
<profile>
<!-- 定义环境对应的唯一id-->
<id>dev_env</id>
<!-- 定义环境中换用的属性(即定义不同环境中各自不同的属性) -->
<properties>
<jdbc.url>jdbc:mysql://localhost:3306/db1</jdbc.url>
</properties>
<!-- 设置默认启动(即该环境为默认的环境,触发使用命令手动指定环境)-->
<activation>
<activeByDefault>true</activeByDefault>
</activation>
</profile>
<!-- 定义具体的环境:测试环境-->
<profile>
<!-- 定义环境对应的唯一id-->
<id>test_env</id>
<!-- 定义环境中换用的属性(即定义不同环境中各自不同的属性) -->
<properties>
<jdbc.url>jdbc:mysql://192.168.188.128:3306/db1</jdbc.url>
</properties>
</profile>
</profiles>
调用测试:
打包项目(默认使用的是开发环境)
mvn install
使用测试环境打包项目
mvn install -P test_env