18.Maven
18.1.介绍
- Maven 是一个项目管理工具,它包含了一个项目对象模型 (POM:Project Object Model),一组标准集合,一个项目生命周期(Project Lifecycle),一个依赖管理系统(Dependency Management System),和用来运行定义在生命周期阶段(phase)中插件(plugin)目标(goal)的逻辑。
- Maven仓库:
- 本地仓库 :用来存储从远程仓库或中央仓库下载的插件和 jar 包,项目使用一些插件或 jar 包,优先从本地仓库查找
- 默认本地仓库位置在
u
s
e
r
.
d
i
r
/
.
m
2
/
r
e
p
o
s
i
t
o
r
y
,
{user.dir}/.m2/repository,
user.dir/.m2/repository,{user.dir}表示 windows 用户目录。
- 修改方式:在MAVE_HOME/conf/settings.xml 文件中配置本地仓库位置
<settings xmlns="http://maven.apache.org/SETTINGS/1.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0 http://maven.apache.org/xsd/settings-1.0.0.xsd"> <!-- localRepository | The path to the local repository maven will use to store artifacts. | | Default: ${user.home}/.m2/repository --> <!-- 添加本地仓库 --> <localRepository>D:\repository</localRepository>
- 默认本地仓库位置在
- 远程仓库:如果本地需要插件或者 jar 包,本地仓库没有,默认去远程仓库下载。
- 远程仓库可以在互联网内也可以在局域网内。
- 设置国内 maven 镜像:因为maven中央仓库位于国外,所以如果本地仓库没有对应的 jar 包,那么需要从中央仓库去下载,速度比较慢。
- 在MAVE_HOME/conf/settings.xml 文件中配置本地仓库位置
<mirrors> <!-- mirror | Specifies a repository mirror site to use instead of a given repository. The repository that | this mirror serves has an ID that matches the mirrorOf element of this mirror. IDs are used | for inheritance and direct lookup purposes, and must be unique across the set of mirrors. | <mirror> <id>mirrorId</id> <mirrorOf>repositoryId</mirrorOf> <name>Human Readable Name for this Mirror.</name> <url>http://my.repository.com/repo/path</url> </mirror> --> <!-- 添加国内镜像 --> <mirror> <id>nexus-aliyun</id> <mirrorOf>central</mirrorOf> <name>Nexus aliyun</name> <url>http://maven.aliyun.com/nexus/content/groups/public</url> </mirror></mirrors>
- 中央仓库 :在 maven 软件中内置一个远程仓库地址
http://repo1.maven.org/maven2
,它是中央仓库,服务于整个互联网,它是由 Maven 团队自己维护,里面存储了非常全的 jar 包,它包含了世界上大部分流行的开源项目构件。
- 本地仓库 :用来存储从远程仓库或中央仓库下载的插件和 jar 包,项目使用一些插件或 jar 包,优先从本地仓库查找
18.2.环境配置
- 下载并解压Maven压缩包,到某个目录下
- 配置 MAVEN_HOME ,变量值就是你的 maven 安装 的路径(bin 目录之前一级目录)
- 通过 mvn -v 命令检查 maven 是否安装成功,看到 maven 的版本为 3.5.2 及 java 版本为 1.8 即为安装成功。
- 打开 cmd 命令,输入 mvn –v 命令
- Maven文件结构:
- bin:存放了 maven 的命令,主要是二进制文件,比如我们前面用到的 mvn tomcat:run
- boot:存放了一些 maven 本身的引导程序,如类加载器等
- conf:存放了 maven 的一些配置文件,如 setting.xml 文件
- lib:存放了 maven 本身运行所需的一些 jar 包
18.3.项目构建
18.3.1.演示
- 在桌面上新建了一个maven目录,在maven目录中新建了一个hello目录表示一个应用,编写java文件
- 报错原因是缺少一个pom.xml文件,maven在执行之前会到一个叫做pom.xml文件中读取一些数据
- 新建一个pom.xml文件
<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> <!-- 公司或者组织的唯一标志,并且配置时生成的路径也是由此生成, 如 com.companyname.project-group,maven 会将该项目打成的 jar 包放本地路径: /com/companyname/project-group --> <groupId>com.cskaoyan.project</groupId> <!-- 项目的唯一ID,一个groupId下面可能多个项目,就是依靠于artifactId来区分的 --> <artifactId>hello</artifactId> <!-- 版本号 --> <version>1.0</version> <!-- 依赖坐标 --> <dependencies> <!-- 依赖设置 --> <dependency> <!-- 依赖组织名称 --> <groupId>junit</groupId> <!-- 依赖项目名称 --> <artifactId>junit</artifactId> <!-- 依赖版本名称 --> <version>4.12</version> <!-- 依赖范围:test 包下依赖该设置,若没有此标签默认是compile --> <scope>test</scope> </dependency> </dependencies> </project>
18.3.2.Maven工程结构
- .settings:工具生成的文件
- src:源代码
- main
- java:存放项目的.java 文件
- resource:存放项目资源文件,如 spring, hibernate 配置文件
- webapp:页面素材
- test
- java:存放所有单元测试.java 文件,如 JUnit 测试类
- resource:测试资源文件
- main
- target:项目输出位置,编译后的 class 文件会输出到此目录
- pom.xml:Maven工程的配置信息,如坐标
18.3.3.项目的一键构建
- 项目往往都要经历编译、测试、运行、打包、安装 ,部署等一系列过程。
- 项目构建:指的是项目从编译、测试、运行、打包、安装 ,部署整个过程都交给 maven 进行管理,这个过程称为构建。
- 一键构建:指的是整个构建过程,使用 maven 一个命令可以轻松完成整个工作。
- 流程:清理—编译—测试—报告—打包—部署
18.3.4. Maven 工程的运行
- 进入 maven 工程目录(当前目录有 pom.xml 文件),运行 tomcat:run 命令。
18.3.5.pom.xml的基本配置
- pom.xml 是 Maven 项目的核心配置文件,位于每个工程的根目录,基本配置如下:
<project > :文件的根节点 .<modelversion > : pom.xml 使用的对象模型版本<groupId > :项目名称,一般写项目的域名<artifactId > :模块名称,子项目名或模块名称<version > :产品的版本号 .<packaging > :打包类型,一般有 jar、war、pom 等<name > :项目的显示名,常用于 Maven 生成的文档。<description > :项目描述,常用于 Maven 生成的文档<dependencies> :项目依赖构件配置,配置项目依赖构件的坐标<build> :项目构建配置,配置编译、运行插件等。
18.2.依赖管理
- Maven 的一个核心特性就是依赖管理。当我们涉及到多模块的项目(包含成百个模块或者子项目),管理依赖就变成一项困难的任务。Maven 展示出了它对处理这种情形的高度控制。传统的 WEB 项目中,我们必须将工程所依赖的 jar 包复制到工程中,导致了工程的变得很大
- maven 工程中不直接将 jar 包导入到工程中,而是通过在 pom.xml 文件中添加所需 jar包的坐标,这样就很好的避免了 jar 直接引入进来,在需要用到 jar 包的时候,只要查找 pom.xml 文件,再通过 pom.xml 文件中的坐标,到一个专门用于”存放 jar 包的仓库”(maven 仓库)中根据坐标从而找到这些 jar 包,再把这些 jar 包拿去运行。
<!-- 依赖坐标 --><dependencies> <!-- 依赖设置 --> <dependency> <!-- 依赖组织名称 --> <groupId>junit</groupId> <!-- 依赖项目名称 --> <artifactId>junit</artifactId> <!-- 依赖版本名称 --> <version>4.12</version> <!-- 依赖范围:test 包下依赖该设置,若没有此标签默认是compile --> <scope>test</scope> </dependency></dependencies>
18.3.Maven指令
- mvn compile
- compile 是 maven 工程的编译命令,作用是将 src/main/java 下的文件编译为 class 文件输出到 target目录下。
- cmd 进入命令状态,执行 mvn compile
- 查看 target 目录,class 文件已生成,编译完成。
- mvn test
- test 是 maven 工程的测试命令 mvn test,会执行 src/test/java 下的单元测试类。
- cmd 执行 mvn test 执行 src/test/java 下单元测试类
- mvn clean
- clean 是 maven 工程的清理命令,执行 clean 会删除 target 目录及内容。
- mvn package
- package 是 maven 工程的打包命令,对于 java 工程执行 package 打成 jar 包,对于 web 工程打成 war包。
- mvn install
- install 是 maven 工程的安装命令,执行 install 将 maven 打成 jar 包或 war 包发布到本地仓库。
- 从运行结果中,可以看出:当后面的命令执行时,前面的操作过程也都会自动执行,
- Maven 指令的生命周期
- maven 对项目构建过程分为三套相互独立的生命周期,注意这里说的是“三套”,而且“相互独立”,调用 clean 不会对 default、site 产生作用。
- 每个生命周期都包含一些阶段,比如 clean 包含 pre-clean 阶段、clean 阶段、post-clean 阶段。当调用 pre-clean 时,只有 pre-clean 执行;调用 clean 时,pre-clean和 clean 都会顺序执行;执行 post-clean,pre-clean、clean、post-clean 都会按照顺序执行
- 当我们调用某个指令的时候,同一套内,当前阶段生命周期指令之前的指令全部会被执行,包括其本身
- 生命周期其实就是一些指令,这三套生命周期分别是:
- Clean Lifecycle:在进行真正的构建之前进行一些清理工作。
- Default Lifecycle 构建的核心部分,编译,测试,打包,部署等等。
- validate
- compile
- test
- package
- verify
- install
- deploy
- Site Lifecycle 生成项目报告,站点,发布站点。
- Maven 生命周期不做具体实现,而实际上是插件在背后默默做这些事情,插件对生命周期做了具体的实现。
18.4.Maven 核心概念
18.4.1.坐标
- 在平面坐标系,需要定位一个点需要 x 坐标和 y 坐标,在空间坐标系需要 x、y、z 三个坐标。
- 在 Maven 中,确定唯一的一个 jar 包也需要三个坐标,groupId、artifactId、version 三个信息。
- groupId:当前的组织名称
- artifactId:当前项目的名称
- version:当前项目的当前版本
- 在每个Maven项目的pom.xml文件中,有对应的键值对来配置。
18.4.2.scope依赖范围
依赖范围 | 对于编译代码classpath有效 | 对于测试代码classpath有效 | 被打包时,对于运行的classpath有效 | 例 |
---|---|---|---|---|
compile | √ | √ | √ | log4j |
test | × | √ | × | junit |
provided | √ | √ | × | servlet-api |
runtime | × | √ | √ | JDBC Driver Implementation |
system | √ | √ | × |
- compile:编译范围,指 A 在编译时依赖 B,此范围为默认依赖范围。
- 编译范围的依赖会用在编译、测试、运行,由于运行时需要所以编译范围的依赖会被打包。
- provided:provided 依赖只有在当 JDK 或者一个容器已提供该依赖之后才使用, provided 依赖在编译和测试时需要,在运行时不需要
- 比如:servlet api 被 tomcat 容器提供,运行时不需要,打包是不会进入压缩包里
- runtime:runtime 依赖在运行和测试系统的时候需要,但在编译的时候不需要
- 比如:jdbc的驱动包。由于运行时需要所以 runtime 范围的依赖会被打包。
- test:test 范围依赖 在编译和运行时都不需要,它们只有在测试编译和测试运行阶段可用,
- 比如:junit。由于运行时不需要所以 test 范围依赖不会被打包。
- system:system 范围依赖与 provided 类似,但是你必须显式的提供一个对于本地系统中 JAR文件的路径
- 需要指定 systemPath 磁盘路径,system 依赖不推荐使用。
18.4.3.依赖传递
- 在项目中引入一个依赖,引入的该依赖又会引入其他的依赖。这种就被称作依赖的传递
- 项目一依赖项目二(第一依赖),项目二依赖commons-fileupload(第二依赖)
- 根据依赖的传递性,项目一也可以拿到commons-fileupload依赖。
第一依赖/第二依赖 | compile | test | provided | runtime |
---|---|---|---|---|
compile | compile | runtime | ||
test | test | test | ||
provided | provided | provided | ||
runtime | runtime | runtime |
- 如果第二依赖是test、provided,传递会断层,如果需要用这个依赖,必须自己再引入。
18.4.4.依赖冲突
- 某项目
- 依赖于A,A依赖于Cv5.3.3
- 依赖于B,B依赖于Cv5.3.4
- A可以理解为spring-jdbc,B可以理解为spring-context,C可以理解为spring-beans
<dependency> <groupId>org.springframework</groupId> <artifactId>spring-jdbc</artifactId> <version>5.3.3</version></dependency><dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>5.3.4</version></dependency>
- 两个依赖原则:
- 第一声明者优先
- 路径近者优先
- 解释:
- 对于这个配置,spring-jdbc和spring-context均依赖于spring-beans,二者平级,那么谁在上面就依赖于谁
- 对于下列配置,虽然spring-beans在下面,但是,spring-beans路径更短,所以spring-beans优先
<dependency> <groupId>org.springframework</groupId> <artifactId>spring-jdbc</artifactId> <version>5.3.3</version></dependency><dependency> <groupId>org.springframework</groupId> <artifactId>spring-beans</artifactId> <version>5.3.4</version></dependency>
- 依赖排除:将spring-beans排除在外,所以spring-jdbc有效
<dependency> <groupId>org.springframework</groupId> <artifactId>spring-jdbc</artifactId> <version>5.3.3</version> <exclusions> <exclusion> <groupId>org.springframework</groupId> <artifactId>spring-beans</artifactId> </exclusion> </exclusions></dependency>
- 提取常量:对于一个系列的jar包,我们建议全部都采用同一个版本,可以通过设置一个常量,固定版本,后面全部沿用该版本。
<properties> <spring.version1>5.3.4</spring.version1></properties><dependencies> <dependency> <groupId>com.cskaoyan.28ee</groupId> <artifactId>mavenProject</artifactId> <version>1.0-SNAPSHOT</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-jdbc</artifactId> <version>${spring.version1}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>${spring.version1}</version> </dependency></dependencies>
18.5.IDEA构建Maven项目
18.5.1.IDEA设置
- 打开File—Settings ,配置 maven
- 选择本地 maven 安装目录,指定 maven 安装目录下 conf 文件夹中 settings 配置文件
- 修改Maven home Directory,指定本地Maven安装目录
- 修改Using settings file,指定settings配置文件路径
- local repository,自动检测本地仓库的位置
18.5.2.创建Maven项目
- Creat New Project,选择 idea 提供好的 maven 的 web 工程模板
- 创建好以后,可以选择File—Other Settings—Settings for New Projects,再次选中Maven,然后按上述操作改好
18.6.Maven与IDEA及Tomcat的关联
- 首先,我们应该配置一个虚拟映射,到Tomcat的部署根目录,这样,在IDEA中的html等资源就会在部署的时候自动复制到部署根目录里去
- 在src—main下,新建一个webapp文件夹,该文件夹应该有个蓝色的圆点标记
- 打开Project Structure,选择module,右侧的Deployment Descriptors设置好web.xml路径,应该是src下的main文件夹下的webapp
- 在下面设置web资源目录,同样修改为src下的main文件夹下的webapp
- 设置部署根目录
- 同样,打开Project Structure,选择Artifacts,点击Web Application:Exploded—-From module,选择当前的module,点击apply。
- 每次Maven项目编译的class文件都会自动复制到Artifacts下的WEB-INF文件夹下的classes文件夹内
在maven项目中,可以在pom.xml文件中添加一对标签war,就可以免去设置artifacts
- 在src—main下,新建一个webapp文件夹,该文件夹应该有个蓝色的圆点标记
- 使用Tomcat来部署该项目
- 点击项目右上角的ScopeMainTest,选择一个本地的Tomcat来部署,修改应用的名称
- 添加jar包到编译环境
- 选择jar包,右键As a Library
- 选择jar包加载到内存中
- 在WEB-INF下新建一个lib目录,右键lib目录,Add Copy of,选择Library Files,选择需要加载的jar包
- 或者,在pom.xml文件中,添加一对标签
<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> <!-- 公司或者组织的唯一标志,并且配置时生成的路径也是由此生成, 如 com.companyname.project-group,maven 会将该项目打成的 jar 包放本地路径: /com/companyname/project-group --> <!-- 添加packaging标签 --> <packaging>war</packaging> <groupId>com.cskaoyan.project</groupId> <!-- 项目的唯一ID,一个groupId下面可能多个项目,就是依靠于artifactId来区分的 --> <artifactId>hello</artifactId> <!-- 版本号 --> <version>1.0</version> <dependencies> <dependency> <groupId>com.cskaoyan.28ee</groupId> <artifactId>mavenProject</artifactId> <version>1.0-SNAPSHOT</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-jdbc</artifactId> <version>${spring.version1}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>${spring.version1}</version> </dependency> </dependencies>
- Maven内嵌的编译器是jdk1.5版本的,有时jdk1.8的新特性Maven会报错
- 解决办法:找到settings.xml文件的profiles标签,添加如下
<profile> <id>jdk-1.8</id> <activation> <activeByDefault>true</activeByDefault> <jdk>1.8</jdk> </activation> <properties> <maven.compiler.source>1.8</maven.compiler.source> <maven.compiler.target>1.8</maven.compiler.target> <maven.compiler.compilerVersion>1.8</maven.compiler.compilerVersion> </properties> </profile>
- 或者,在pom.xml文件中,新增properties
<properties> <maven.compiler.source>1.8</maven.compiler.source> <maven.compiler.target>1.8</maven.compiler.target> <maven.compiler.compilerVersion>1.8</maven.compiler.compilerVersion> </properties>
- 解决办法:找到settings.xml文件的profiles标签,添加如下
18.7.SE和EE项目获取配置文件的方式
- SE项目配置文件的存放位置和EE项目文件的存放位置不同
- SE项目的配置文件其实可以放置在应用的根目录里面
- EE项目的配置文件必须要放置在WEB-INF或者它的子目录中。
- SE项目配置文件和EE项目配置文件存放需要两套策略。如果要获取配置文件,肯定需要去写两套代码。
public class PropertiesTest {
public static void main(String[] args) throws IOException {
//SE获取配置文件方式,一般将配置文件与src同级,相对路径是src同级目录,可以在IDEA里修改相对路径
File file = new File("application.properties");
FileInputStream fileInputStream = new FileInputStream(file);
Properties properties = new Properties();
properties.load(fileInputStream);
String username = properties.getProperty("username");
String password = properties.getProperty("password");
System.out.println(username);
System.out.println(password);
}
}
@WebServlet("/index")
public class IndexServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//EE项目获取配置文件的方式
String realPath = getServletContext().getRealPath("WEB-INF/application.properties");
FileInputStream fileInputStream = new FileInputStream(new File(realPath));
Properties properties = new Properties();
properties.load(fileInputStream);
String username = properties.getProperty("username");
String password = properties.getProperty("password");
System.out.println(username);
System.out.println(password);
}
}
- 类加载器能够将class文件加载到内存,那么它肯定知道class文件的绝对路径——-file——inputStream
- 把配置文件和class文件放在一起,那么可以利用类加载器拿到配置文件的绝对路径
public class PropertiesTest2 {
public static void main(String[] args) throws IOException {
String path = PropertiesTest2.class.getClassLoader().getResource("application.properties").getPath();
FileInputStream fileInputStream = new FileInputStream(new File(path));
//除此之外还有另外一种简便的方式
InputStream inputStream = PropertiesTest2.class.getClassLoader().getResourceAsStream("application.properties");
}
}
@WebServlet("/index2")
public class IndexServlet2 extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//拿到当前类中的类加载器
ClassLoader classLoader = IndexServlet2.class.getClassLoader();
String path = classLoader.getResource("application.properties").getPath();
FileInputStream fileInputStream = new FileInputStream(new File(path));
}
}
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/181049.html