下载Maven
我们使用的是最新apache-maven-3.9.6的版本,idea使用的是2023.1的版本。
配置Maven
要点:一定要将Maven工具解压到一个没有中文的路径下!
配置环境变量
必须要配置JAVA_HOME和MAVEN_HOME的环境变量。在Maven工具的bin目录下的mvn文件中多次使用这两个环境变量。
配置步骤:
我的电脑--->右键属性--->高级系统设置--->环境变量--->系统变量
点新建--->
创建JAVA_HOME环境变量
1.变量名: JAVA_HOME
2.变量值: C:\Program Files\Java\jdk-17
创建MAVEN_HOME环境变量
1.变量名: MAVEN_HOME
2.变量值: D:\apache-maven-3.9.6 (Maven工具所在的目录,bin的上一级目录)
点path--->编辑--->新建
1.%JAVA_HOME%\bin
2.%MAVEN_HOME%\bin
3.--->确定--->确定--->确定
打开cmd窗口,输入 mvn -v
Apache Maven 3.9.6 (c9616018c7a021c1c39be70fb2843d6f5f9b8a1c)
Maven home: D:\apache-maven-3.9.6
Java version: 17.0.6, vendor: Oracle Corporation, runtime: C:\Program Files\Java\jdk-17
Default locale: zh_CN, platform encoding: GBK
OS name: "windows 10", version: "10.0", arch: "amd64", family: "windows"
有以上输出则表明配置环境变量成功。
配置Maven工具参数
打开D:\apache-maven-3.9.6\conf\settings.xml文件,进行本地仓库,远程仓库和JDK参数设置。
配置本地仓库,将注释中53行的代码提取出注释,放置在第55行,设置本地仓库的地址路径。如果已有本地仓库则直接指定地址,如果没有本地仓库则指定一个目录,在idea配置后会自动生成目录。
配置远程仓库
找到结束标签,将以下代码贴在其前面。
<!--配置阿里远程仓库-->
<mirror>
<id>alimaven</id>
<name>aliyun maven</name>
<url>http://maven.aliyun.com/nexus/content/groups/public/</url>
<mirrorOf>central</mirrorOf>
</mirror>
远程仓库配置后,经常出现以下bug,连网去点try...就行,如果还是出现try...,就需要到本地仓库中,搜索last*,将出现的所有文件都删除后,再来点try...就行。
配置JDK属性
在标签中进行配置,一定要小心,找到结束标签,在其前面配置以下代码。因为在标签中全部是注释,粘到哪里都在注释中,只有找到结束标签前才是注释外的,配置才会生效。
<profile>
<id>jdk17</id>
<activation>
<activeByDefault>true</activeByDefault>
<jdk>17</jdk>
</activation>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
<maven.compiler.compilerVersion>17</maven.compiler.compilerVersion>
</properties>
</profile>
为Idea2023当前打开的工作区集成maven
打开idea2023,具体步骤如下:
File--->settings--->Build,Execution,Depolyment--->Build Tools--->Maven
Maven home path(Maven工具所在的目录,bin的上一级目录): D:\apache-maven-3.9.6
勾选Override选项
User settings file(Maven工具的核心配置文件): D:\apache-maven-3.9.2\conf\settings.xml
Local repository(本地仓库,antlr的上一级目录): D:\repository
Maven--->Importing--->配置JDK的版本
Runner
VM Options:-DarchetypeCatalog=internal (在新建模块时使用本地模板)
JRE: 17
Repositories(刷新本地仓库的索引): 选中本地仓库,点Update
为Idea2023新建项目集成Maven
File--->New Projects Setup--->Settings for New Project
同3.2.2的步骤再来一遍
基于Maven开发JavaSE的项目
File--->new--->Project--->Empty Project
Location:D:\course\10-Maven\code
Name:mavenall
--->Create
ctrl+alt+shift+s:打开项目结构窗口
Project:设置JDK版本为17
Modules:
---> New Module
Build system: Maven
Advanced Settings
GroupId:com.bjpowernode
ArtifactId:maven_001_javase
--->Create
观察Sources和Dependcies选项的JDK版本,都为17
--->ok
补齐目录
在test目录上右键--->new Directory--->resouces
修改pom.xml文件
添加单元测试的依赖
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
</dependencies>
切记:点M刷新依赖
开发Hello.java类
public class Hello {
//加法运算
public int sum(int num1,int num2){
return num1 + num2;
}
//乘法运算
public int mul(int num1,int num2){
return num1 * num2;
}
}
开发测试类
public class MyTest {
/**
* 测试功能由测试方法来实现
* 测试方法的规范
* 1)访问权限是public
* 2)方法没有返回值void
* 3)方法名称自 定义,推荐以test开头
* 4)方法没有参数
* 5)使用@Test注解声明是测试方法
*/
@Test
public void testSum(){
Hello hello = new Hello();
System.out.println(hello.sum(3,6));
}
@Test
public void testMul(){
Hello hello = new Hello();
System.out.println(hello.mul(3,6));
}
}
基于Maven开发JavaWeb的项目
删除maven_001_javaSE.iml文件(如果此文件位于项目目录下,则必须删除,如果在本模块目录下,就不需要删除)
ctrl+alt+shift+s:打开结构窗口
Modules选项上---> + --->new Module
Maven Archetype选项
Archetype: maven-archetype-webapp
Advanced Settings 选项卡
GroupId: com.bjpowernode
ArtifactId: maven_002_javaweb
Version: 1.0.0
--->Create
观察Sources和Dependcies选项的JDK版本
--->ok
修改目录
补齐缺失的所有目录
添加package: com.bjpowernode.controller
修改pom.xml文件
删除远程访问的名称
<name>maven_002_javaweb Maven Webapp</name>
<url>http://maven.apache.org</url>
2. 添加依赖
<!--添加Servlet的依赖-->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>4.0.1</version>
</dependency>
3. 删除项目构建名称
<build>
<finalName>maven_002_javaweb</finalName>
</build>
切记: 点M刷新按钮
修改web.xml文件
ctrl+alt+shift+s:打开结构窗口
点web ---> - --->yes ---> Apply
--->web.xml --->ok --->ok
修改jsp页面
删除index.jsp页面
在webapp目录下新建index.jsp和main.jsp
开发index.jsp页面 访问服务器
开发Servlet
@WebServlet("/demo")
public class DemoServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("我来过.........");
//跳 回 main.jsp
request.getRequestDispatcher("/main.jsp").forward(request,response);
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
}
}
添加tomcat测试运行
部署长名称的项目.
导入Maven的项目
拷贝一个现有的Maven项目maven_002_javaweb,改名为 maven_002_javawebnew
进入到maven_002_javawebnew项目中删除target目录和.gitignore文件
打开pom.xml文件,更改artifactId的名称为maven_002_javawebnew.
ctrl+alt+shift+s:打开项目结构窗口
--->Import Moudle --->选中要导入的项目---> ok
选中 Import module from external model
Maven
---> Create ---> ok
部署运行测试功能
Maven的依赖管理
在JAVA开发中,项目的依赖管理是一项重要任务。通过合理管理项目的依赖关系,我们可以有效的管理第三方库,模块的引用及版本控制。而Maven作为一个强大的构建工具和依赖管理工具,为我们提供了便捷的方式来管理项目的依赖。
什么是依赖范围
Maven的依赖构件包含一个依赖范围的属性。这个属性描述的是三套classpath的控制,即编译、测试、运行。这说白了就是添加的jar包起作用的范围。 maven提供了以下几种依赖范围:compile,test,provided.runtime,system。
分别介绍如下:
compile
编译依赖范围,如果没有指定,默认使用该依赖范围,对于编译、测试、运行3种classpath都有效。
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.3.24</version>
<scope>compile</scope>
</dependency>
</dependencies>
test
测试依赖范围,使用此依赖范围的maven依赖,只对编译测试、运行测试的classpath有效,在编译主代码、运行项目时无法使用此类依赖。比如junit,它只有在编译测试代码及运行测试的时候才需要。
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
</dependencies>
provided
已提供依赖范围。表示项目的运行环境中已经提供了所需要的构件,对于此依赖范围的maven依赖,对于编译源码、编译测试、运行测试中classpath有效,但在运行时无效。比如上面说到的servlet-api,这个在编译和测试的时候需要用到,但是在运行的时候,web容器已经提供了,就不需要maven帮忙引入了。
<dependencies>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>4.0.1</version>
<scope>provided</scope>
</dependency>
</dependencies>
runtime
运行时依赖范围,使用此依赖范围的maven依赖,对于测试和运行项目的classpath有效,但在编译时无效,比如jdbc驱动实现,项目代码编译的时候只需要提供JDK提供的JDBC接口,运行的时候才需要具体的jdbc驱动实现。
<dependencies>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.32</version>
<scope>runtime</scope>
</dependency>
</dependencies>
system
系统依赖范围,该依赖与3中classpath的关系,和provided依赖范围完全一致。但是,使用system范围的依赖时必须通过systemPath元素显示第指定依赖文件的路径。这种依赖直接依赖于本地路径中的构件,可能每个开发者机器中构件的路径不一致,所以如果使用这种写法,你的机器中可能没有问题,别人的机器中就会有问题,所以建议谨慎使用。
<dependencies>
<dependency>
<groupId>com.bjpowernode</groupId>
<artifactId>maven_001_javase</artifactId>
<version>1.0-SNAPSHOT</version>
<scope>system</scope>
<systemPath>D:/repository/com/bjpowernode/maven_001_javase/1.0-SNAPSHOT/maven_001_javase-1.0-SNAPSHOT.jar</systemPath>
</dependency>
</dependencies>
总结如下图:
什么是依赖传递
依赖具有传递性。 Maven 的依赖传递机制是指:不管 Maven 项目存在多少间接依赖,POM 中都只需要定义其直接依赖,不必定义任何间接依赖,这在一定程序上简化 了POM 的配置。假项目A依赖项目B,项目B依赖项目C,则A----->直接依赖B,B----->直接依赖C,A----->间接依赖C。
直接依赖和间接依赖是一个相对的概念。直接在项目中配置的依赖称为直接依赖,通过添加依赖关联进来的依赖称为间接依赖。1是项目的直接依赖,2是1的直接依赖,2是项目的间接依赖,以此类推。如图
依赖范围对依赖传递的影响
B 是 A 的直接依赖,C 是 A 的间接依赖,根据 Maven 的依赖传递机制,间接依赖 C 会以传递性依赖的形式引入到 A 中,但这种引入并不是无条件的,它会受到依赖范围的影响。
图示依赖传递关系:
规范化依赖传递的结果:
交叉部分的单元格的取值为传递性依赖的依赖范围,若交叉单元格取值为 “-”,则表示该传递性依赖不能被传递。通过上表,可以总结出以下规律:
当间接依赖的范围是 compile 时,与直接依赖的范围一致;
当间接依赖的范围是 test 或 provided时,传递性依赖不会被传递;
当间接依赖的范围是 runtime 时,传递性依赖的范围与直接依赖的范围一致,但 compile 例外,此时传递性依赖的范围为 runtime。
依赖冲突
什么是依赖冲突
在 Maven 项目中,依赖通常被定义在项目的 pom.xml 文件中。当多个依赖项引入了不同版本的相同库时,就会发生依赖冲突。这可能是因为项目的直接依赖和间接依赖导致了同一库的多个版本存在于类路径中。每个显式声明的类包都会依赖于一些其它的隐式类包,这些隐式的类包会被maven间接引入进来,从而造成类包冲突。
依赖冲突的解决方案
Maven可以通过以下途径解决依赖冲突。
版本锁定
在父工程中使用dependencyManagement 进行版本锁定,dependencyManagement可以统一管理整个项目的版本号,确保应用的各个项目的依赖和版本一致。 dependencyManagement只是声明依赖,并不自动实现引入,因此子项目需要显示的声明需要用的依赖,便可以忽略版本号。如果排斥父工程中定义的版本号,可以显示的进行版本号声明。
子工程使用父工程锁定的版本号
子工程使用自定义的版本号,只要重新声明即可
父工程不使用标签,则子工程跟父工程完全保持一致。子工程不需要显示依赖任何jar包。
短路径优先
引入路径短者优先,顾名思义,当一个间接依赖存在多条引入路径时,引入路径短的会被解析使用。如图
声明优先
如果存在短路径,则优先选择短路径,如果路径相同的情况下,先声明者优先,POM 文件中依赖声明的顺序决定了间接依赖会不会被解析使用,顺序靠前的优先使用。如图。
代码示例:
注意去掉标签,否则会因为依赖范围的影响导致效果无法显示。
特殊优先(后来者居上)
同一个pom.xml文件中进行了多次依赖jar包不同版本的配置,后面的覆盖前面的配置。这种情况比较少见。
可选依赖
maven_03项目可选择是否传递间接依赖junit_4.13,主动权在当前项目maven_03中。如果当前项目被依赖到其它项目中,当前项目可以拒绝交出间接依赖项。例如maven_02添加了maven_03的依赖,maven_03可以自主设置其依赖项junit_4.13是否被间接传递。true 为不传递间接依赖,那么在maven_02项目中就没有junit_4.13的依赖。默认是false,是传递间接依赖。
代码示例:
排除依赖
是当前项目是否主动断开其依赖项目的间接依赖。也就是控制当前项目是否使用其直接依赖传递下来的接间依赖。在maven_02项目中添加maven_03项目的依赖,但不要maven_03项目中的junit_4.13的依赖,可以选择排除依赖。这样可以保证当前项目依赖的纯净性。
排除依赖使用 exclusions 元素排除依赖,说明如下:
exclusions 元素下可以包含若干个 exclusion 子元素,用于排除若干个间接依赖,该元素包含两个子元素:groupId 和 artifactId,用来确定需要排除的间接依赖的坐标信息
exclusion 元素中只需要设置 groupId 和 artifactId 就可以确定需要排除的依赖,无需指定版本version
如图
代码示例:
可选依赖和排除依赖的区别
排除依赖和可选依赖都能在项目中将间接依赖排除在外,但两者实现机制却完全不一样。
可选依赖是自己决定是否向外提供间接依赖(maven_03设置拒绝提供间接依赖junit)
排除依赖是主动拒绝添加直接依赖关联的间接依赖(maven_02项目设置排除maven_03的junit依赖)
可选依赖的优先级高于排除依赖
若对于同一个间接依赖同时使用排除依赖和可选依赖进行设置,那么可选依赖的取值必须为 false,否则排除依赖无法生效。
如果用一个生活中的例子可能更易懂一些。
国民党(maven_02)抓住了共产党人(依赖了maven_03),要求供出联系人名单(maven_03中依赖的junit_4.13),最终结果是没有得到联系人名单(不依赖jjunit_4.13)。
可选依赖:是maven_03共产党人死活不说联系人的名单junit_4.13(可选,我选择不说)。
排除依赖:是maven_02国民党不要共产党人提供的联系人名单(排除,我就是不要你的名单, 估计你是乱说的)。
刷新依赖的8种方式
在idea中有时候会出现刷新延时的情况,那么需要进行手工刷新依赖。
点击M刷新按钮。
点Maven窗口的Reload All Maven Projects。
Build--->ReBuild Project 重新构建项目的同时刷新所有依赖。
点击本项目的pom.xml文件--->右键--->Maven--->Reload Project 刷新本项目的依赖。
打开pom.xml文件,全选,拷贝,删除,关闭,打开,粘贴.物理刷新pom.xml文件 。
Invalidate Caches--->全选--->Invalidate and Restart 清空idea的缓存并重启idea刷新依赖。
打开本地仓库,搜索last,全选删除,点Maven的刷新全部依赖的按钮。
在7的步骤后执行File--->settings--->Build,Execution,Deployment--->Build Tools--->Maven--->Repositories--->选中本地仓库--->update--->ok。
资源文件的指定
src/main/java 和 src/test/java 这两个目录中的所有*.java 文件会分别在 comile 和 test-comiple 阶段被编译,编译结果分别放到了 target/classes 和 targe/test-classes 目录中,但是这两个目录中的其他文件(后缀是.properties或.xml等文件)都会被忽略掉(编译后丢失),如果需要把 src 目录下的除.java之外的文件包放到 target/classes 目录,作为输出的 jar 一部分。需要指定资源文件位置。以下内容放到标签中。简单来说就是在resources目录下的*.propert