Maven
使用工具: eclipse,jdk1.8,maven2.2
一, Maven简介
Maven 是Apache组织中一个颇为成功的开源项目,Maven 主要服务基于java 平台的项目构建,依赖管理和项目信息管理.无论是小型的开源类库项目,还是大型的企业级应用;无论是传统的瀑布式开发,还是流行的敏捷开发,Maven都能很好的应用.
项目构建工具
项目构建: 项目的编译,单元测试,生成文档,打包和部署.
Ant 构建
- 最早的构建工具,基于 IDE, 大概是 2000 年有的,当时是最流行 java 构建工具,不过 它的 XML 脚本编写格式让 XML 文件特别大。对工程构建过程中的过程控制特别好。
Maven (java)
- 项目对象模型,通过其描述信息来管理项目的构建,报告和文档的软件项目管理工具。 它填补了 Ant 缺点,Maven 第一次支持了从网络上下载的功能,仍然采用 xml 作为配置文 件格式。Maven 专注的是依赖管理,使用 Java 编写。
Gradle
- 属于结合以上两个的优点,它继承了 Ant 的灵活和 Maven 的生命周期管理,它最后被 google 作为了 Android 御用管理工具。它最大的区别是不用 XML 作为配置文件格式,采 用了 DSL 格式,使得脚本更加简洁。
Maven 的四大特性
1. 依赖管理系统 ( jar 项目的多模块 )
Maven 为 Java 世界引入了一个新的依赖管理系统 jar 包管理, jar 升级时修改配置文 件即可。在 Java 世界中,可以用 groupId、artifactId、version 组成的 Coordination(坐 标)唯一标识一个依赖。
任何基于 Maven 构建的项目自身也必须定义这三项属性,生成的包可以是 Jar 包,也 可以是 war 包或者 jar 包。一个典型的依赖引用如下所示:
<dependency>
<groupId>javax.servlet</groupId> com.baidu
<artifactId>javax.servlet-api</artifactId> ueditor echarts
<version>3.1.0</version>
</dependency>
坐标的理解
Maven 坐标为各种组件引入了秩序,任何一个组件都必须明确定义自己的坐标。
- groupId定义当前 Maven 项目隶属的实际项目-公司名称。(jar 包所在仓库路径) 由于 Maven 中模块的概念,因此一个实际项目往往会被划分为很多模块。 比如 spring 是 一个实际项目,其对应的 Maven 模块会有很多,如 spring-core,spring-webmvc 等。
- artifactId该元素定义实际项目中的一个 Maven 模块-项目名, 推荐的做法是使用实际项目 名称作为 artifactId 的前缀。 比如: spring-bean, spring-webmvc 等。
- version该元素定义 Maven 项目当前所处的版本。
2. 多模块构建
项目复查时 dao service controller 层分离将一个项目分解为多个模块已经是很通用 的一种方式。 ? 在 Maven 中需要定义一个 parent POM 作为一组 module 的聚合 POM。在该 POM 中可以使用 <modules> 标签来定义一组的模块。parent POM 不会有什么实际构建产出。 而 parent POM 中的 build 配置以及依赖配置都会自动继承给子 module。
3. 一致的项目结构 ( 不同的IDE 项目机构是一致 )
Ant 时代大家创建 Java 项目目录时比较随意,然后通过 Ant 配置指定哪些属于 source, 那 些 属 于 testSource 等 。 而 Maven 在 设 计 之 初 的 理 念 就 是 Conversion over configuration(约定大于配置)。其制定了一套项目目录结构作为标准的 Java 项目结构, 解决不同 ide 带来的文件目录不一致问题。
4. 一致的构建模型和插件机制 ( 通过 pom 配置 tomcat , jetty 插件 )
<plugin>
<groupId>org.mortbay.jetty</groupId>
<artifactId>maven-jetty-plugin</artifactId>
<version>6.1.25</version>
<configuration>
<scanIntervalSeconds>10</scanIntervalSeconds>
<contextPath>/test</contextPath>
</configuration>
</plugin>
二, Maven 的安装配置及目录构建
1. Maven 的安装配置
- 检查 JDK 的安装
- 下载解压Maven ( 地址:http://maven.apache.org/download.html )
- 配置Maven 环境变量 解压后把 Maven 的根目录配置到系统环境变量中 MAVEN_HOME,将 bin 目录配置到 path 变量中。 注:maven 解压后存放的目录不要包含中文和空格
- 检查Maven 是否安装成功 ( mvn -v )
2. Maven 目录结构
2.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
http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
?
<groupId>com.mohen</groupId>
<artifactId>maven01</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
?
<name>maven01</name>
<url>http://maven.apache.org</url>
?
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>
?
<!--
根目录下的第一个子元素 ModelVersion 指定当前 Pom 模型的版本,对于 Maven3
来说,它只能是 4.0.0 。指定了当前 Maven 模型的版本号,对于 Maven2 和 Maven3
来说,它只能是 4.0.0
?
Version X.X.X-里程碑
比如:1.0.0-SNAPSHOT
第一个 X 大版本 有重大变革
第二个 X 小版本 修复 bug,增加功能
第三个 X 更新
?
里程碑版本:
SNAPSHOT (快照,开发版)
alpha(内部测试)
beta(公开测试)
Release | RC( 发布版)
GA(正常版本)
?
使用 name 标签声明一个对于用户更为友好的项目名称,虽然不是必须的,但还是推
荐为每个 Pom 声明 name,以方便信息交流。
-->
2.2 编写主函数
package com.mohen.demo;
?
public class Hello{
public static void main(String[] args) {
System.out.println("hello maven");
}
}
2.3 cmd 下编译并运行
cmd 下面, 进入项目的根目录
2.3.1 编译Java文件
mvn compile
2.3.2 执行main 方法
mvn exec:java -Dexec.mainClass="com.mohen.demo.Hello"
注:
第一次下载会比较慢,要修改maven 加压之后的conf 目录下的 settings.xml.
1.1.修改默认仓库位置 ? 打开 maven 目录 -> conf -> settings.xml ? 添加仓库位置配置 ? <localRepository>F:/m2/repository</localRepository> 注:仓库位置改为自己本机的指定目录,"/"不要写反 1.2.更换阿里镜像,加快依赖下载
<mirror>
<id>nexus-aliyun</id>
<mirrorOf>central</mirrorOf>
<name>Nexus aliyun</name>
<url>http://maven.aliyun.com/nexus/content/groups/public</url>
</mirror>
1.3 编译不成功可能的原因
- 不是使用管理员权限执行 dos 命令
- JDK 环境配置有问题,重装 JDK
- 代码编写时,类里面没设置包名(如果编译时类没加包名,执行时也不需要加包名)
三, Eclipse 下配置Maven 环境
eclipse 默认情况下已经集成了 maven 插件,但对于 maven 的环境我们这里还需要 进行相应的环境配置。
1. 修改Maven 版本
操作步骤 : Window --> Preferences --> Maven
选择 Installations --> Add,添加 maven,勾选新添加的 maven 版本
2. 修改setting.xml 配置文件
选择User Settings, 修改 maven 的配置文件的位置
3. 建立项目
左侧空白右键,选择 New --> Project--> 搜索 Maven,选择 Maven Project
使用默认的工作空间,然后Next , 选择Maven 项目的模板
添加Artifact Id
Maven 项目建立后,需要修改maven 项目相关环境
3.1 修改 jre 环境为 1.8
- 3.1.1选择项目,右键选择 Build Path-->Configure Build Path,设置 jre 的环境
- 3.1.2 修改 Java 编译的等级,与当前环境中的 jre 环境一致
- 3.1.3 启动项目
选中项目 选择 Run As --> maven build
设置对应的命令
执行成功
注: 第一次执行该命令报错时,将jre 运行环境添加 maven 环境参数
环境调整
3.2 修改web 环境 ( web 项目需要配置 )
- 3.2.1 修改java 1.5 -> 1.8
- 3.2.2 修改domnamic web module 2.3 到 3.0
项目右击选择 Properties,选择 Project Facets
eclipse 不能直接修改 Web 版本,可直接在配置文件(工作空间的 settings)中修改:
修改完后刷新即可.
4. 添加web项目部署插件(jetty / tomcat )
4.1 jetty 插件配置
<build>
<finalName>test</finalName>
<plugins>
<plugin>
<groupId>org.mortbay.jetty</groupId>
<artifactId>maven-jetty-plugin</artifactId>
<version>6.1.25</version>
<configuration>
<!-- 热部署,每 10 秒扫描一次 -->
<scanIntervalSeconds>10</scanIntervalSeconds>
<!-- 可指定当前项目的站点名 -->
<contextPath>/test</contextPath>
<connectors>
<connector
implementation="org.mortbay.jetty.nio.SelectChannelConnector">
<port>9090</port> <!-- 设置启动的端口号 -->
</connector>
</connectors>
</configuration>
</plugin>
</plugins>
</build>
启动项目
选中项目 选择 Run As --> maven build
在Goals:( 输入命令) jetty : run
启动 jetty 服务器,也可以输入命令 jetty:run -D jetty.port=9090 启动服务浏览器访问
4.2 tomcat 插件配置
<plugin>
<groupId>org.apache.tomcat.maven</groupId>
<artifactId>tomcat7-maven-plugin</artifactId>
<version>2.2</version>
<configuration>
<!-- <port>8081</port> -->
<path>/test</path>
<uriEncoding>UTF-8</uriEncoding>
<finalName>test </finalName>
<server>tomcat8</server>
</configuration>
</plugin>
启动项目 选中项目 run as -->maven build -->goals,输入命令 tomcat7:run
5. Maven 仓库的基本概念
Maven 依赖仓库:https://mvnrepository.com/
当第一次运行 Maven 命令的时候, 你需要有网, 因为它需要从网上下载一 些文件。 那么它从哪里下载呢? 它是从 Maven 默认的远程库下载的。 这个远程仓库由 Maven 的核心插件和可供下载的 jar 文件。
对于 Maven 来说, 仓库只分为两类: 本地仓库和远程仓库。
当 Maven 根据坐标寻找构件的时候,它首先会查看本地仓库,如果本地仓库存在,则 直接使用; 如果本地没有,Maven 就会去远程仓库查找,发现需要的构件之后,下载到本 地仓库再使用。 如果本地仓库和远程仓库都没有,Maven 就会报错。
远程仓库分为三种: 中央仓库,私服, 其他公共库。
- 中央仓库是默认配置下,Maven 下载 jar 包的地方。
- 私服是另一种特殊的远程仓库,为了节省带宽和时间,应该在局域网内架设一个私有的 仓库服务器,用其代理所有外部的远程仓库。 内部的项目还能部署到私服上供其他项目使 用。
- 一般来说,在 Maven 项目目录下,没有诸如 lib/这样用来存放依赖文件的目录。 当 Maven 在执行编译或测试时,如果需要使用依赖文件,它总是基于坐标使用本地仓库的依 赖文件。
5.1 中央仓库
由于原始的本地仓库是空的,maven 必须知道至少一个可用的远程仓库,才能执行 maven 命令的时候下载到需要的构件。中央仓库就是这样一个默认的远程仓库。 maven-model-builder-3.3.9.jar maven 自动的 jar 中 包含了一个 超级 POM。定义 了默认中央仓库的位置。 中央仓库包含了 2000 多个开源项目,接收每天 1 亿次以上的访问。
5.2 私服
私服是一种特殊的远程仓库,它是架设在局域网内的仓库服务, 私服代理广域网上的 远程仓库,供局域网内的 maven 用户使用。 当 maven 需要下载构件时, 它去私服当中 找,如果私服没有, 则从外部远程仓库下载,并缓存在私服上, 再为 maven 提供。 此外,一些无法从外部仓库下载的构件也能从本地上传到私服提供局域网中其他人使用.
四, Maven 环境下多模块项目构建
使用maven 提供的多模块构建的特性完成 maven 环境下多个模块的项目的管理与构建.
项目组织
- mohen_par 根项目
- mohen_dao dao级别的项目
- mohen_service service级别的项目
- mohen_web web 级别的项目 注:切换工作空间,Maven 的相关配置需要重新设置
1. mohen_par 根级别项目 ( 父项目 )
1.1 选择 Maven Project
1.2 勾选复选框,跳过模板的选择
1.3 设置项目相关信息,Packaging 选择 pom
2. 创建子项目 mohen_dao
2.1 选中 mohen_par 后 选择新建 Maven Module 模块项目
2.2 设置子项目的名称
2.3 选择快速创建 Java 普通项目
2.4 设置子项目的包名
3. 创建子项目 mohen_service
步骤如上,建立 mohen_service 子项目 mohen_par、mohen_dao、mohen_service 三个项目建立后,建立 web 层子项目 mohen_web
4. mohen_dao 添加方法
package com.mohen_dao;
?
public class UserDao {
public static void add() {
System.out.println("dao add...");
}
}
5. 修改 mohen_service 的 pom 文件,添加 dao 的 jar 依赖
<dependency>
<groupId>com.mohen</groupId>
<artifactId>mohen_dao</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
Service 添加方法
package com.mohen_service;
import com.mohen_dao.UserDao;
public class UserService {
public static void add() {
UserDao.add();
System.out.println("service add...");
}
}
6. 创建 mohen_web
选中 mohen_par ,新建 Maven Module 模块 ,选择 webapp 类型项目
根项目中引用子项目的模块
<!-- servlet 配置 -->
<modules>
<module>mohen_dao</module>
<module>mohen_service</module>
<module>mohen_web</module>
</modules>
修改父项目与子项目的 jre 环境及 web 项目的版本,分别右键项目,选择 Properties,选择 Build Path,设置 jre 环境;web 项目需要去工作空间中设置 web 版本。(前面有具体的步骤) ? 修改根项目 pom 配置,添加 servlet 的 jar 包依赖
<!-- servlet 配置 -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.0.1</version>
<scope>provided</scope>
</dependency>
添加编译环境插件(可以不加)
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.3.2</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
<encoding>UTF-8</encoding>
</configuration>
</plugin>
</plugins>
</build>
7. 修改 mohen_web 的 pom 文件,添加 service 的 jar 依赖
<dependency>
<groupId>com.mohen</groupId>
<artifactId>mohen_service</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
添加 source 文件夹(如果没自动生成,就手动创建)
编写测试 servlet
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.mohen_service.UserService;
?
@WebServlet(urlPatterns="/userAction.do")
public class UserAction extends HttpServlet {
private static final long serialVersionUID = 1661933106038150349L;
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
doPost(req, resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
System.out.println("user servlet ...");
UserService.add();
}
}
添加 tomcat 插件
<plugins>
<!-- tomcat7 插件 -->
<plugin>
<groupId>org.apache.tomcat.maven</groupId>
<artifactId>tomcat7-maven-plugin</artifactId>
<version>2.1</version>
<configuration>
<!-- <port>8080</port> -->
<path>/web</path>
<uriEncoding>UTF-8</uriEncoding>
<finalName>web </finalName>
<server>tomcat7</server>
</configuration>
</plugin>
</plugins>
选中父项目 右键 run as -> maven install ,执行安装
安装成功
启动 tomcat tomcat7:run
效果 浏览器输入:http://localhost:8080/web/userAction.do
五, Maven 项目的打包操作
对于企业级项目,无论是进行本地测试,还是测试环境测试以及最终的项目上线,都会 涉及项目的打包操作,对于每个环境下项目打包时,对应的项目所有要的配置资源就会有所 区别,实现打包的方式有很多种,可以通过 ant,获取通过 idea 自带的打包功能实现项目打 包,但当项目很大并且需要的外界配置很多时,此时打包的配置就会异常复杂,对于 maven 项目,我们可以用 pom.xml 配置的方式来实现打包时的环境选择,相比较其他形式打包 工具,通过 maven 只需要通过简单的配置,就可以轻松完成不同环境下项目的整体打包。 ? 比如下面这样一个项目,项目中配置了不同环境下项目所需要的配置文件,这时候需要 完成不同环境下的打包操作,此时通过修改 pom.xml 如下:
<!-- 打包环境配置 开发环境 测试环境 正式环境 -->
<profiles>
<profile>
<id>dev</id>
<properties>
<env>dev</env>
</properties>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
</profile>
<profile>
<id>test</id>
<properties>
<env>test</env>
</properties>
</profile>
<profile>
<id>product</id>
<properties>
<env>product</env>
</properties>
</profile>
</profiles>
对于项目资源文件的配置放在 build 中
<resources>
<resource>
<directory>src/main/resources/${env}</directory>
</resource>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.xml</include>
<include>**/*.properties</include>
<include>**/*.tld</include>
</includes>
<filtering>false</filtering>
</resource>
</resources>
此时对应打包命令,选中项目,右键 run as,选择 maven build 输入命令 ? clean compile package -Dmaven.test.skip=true ? 打包默认环境(开发环境)并且跳过 maven 测试操作 ? clean compile package -Ptest -Dmaven.test.skip=true ? 打包测试环境并且跳过 maven 测试操作 ? clean compile package -Pproduct -Dmaven.test.skip=true ? 打包生产环境并且跳过 maven 测试操作
六, Maven 依赖的基本概念
1. 依赖的基本配置
根元素 project 下的 dependencies 可以包含多个 dependence 元素,以声明多个依赖。每个依赖都应该包含以下元素:
- groupId, artifactId, version : 依赖的基本坐标, 对于任何一个依赖来说,基本坐标是最重要的, Maven 根据坐标才能找到需要的依赖。
- Type: 依赖的类型,大部分情况下不需要声明。 默认值为 jar
- Scope: 依赖范围(compile,test,provided,runtime,system)compile: 编译依赖范围。如果没有指定,就会默认使用该依赖范围。使用此依赖范围的 Maven 依赖,对于编译、测试、运行三种 classpath 都有效。test: 测试依赖范围。使用此依赖范围的 Maven 依赖,只对于测试 classpath有效,在编译主代码或者运行项目的使用时将无法使用此类依赖。典型的例子就是 JUnit,它只有在编译测试代码及运行测试的时候才需要。provided: 已提供依赖范围。使用此依赖范围的 Maven 依赖,对于编译和测试 classpath 有效,但在运行时无效。典型的例子是 servlet-api,编译和测试项目的时候需要该依赖,但在运行项目的时候,由于容器已经提供,就不需要Maven 重复地引入一遍(如:servlet-api)。runtime: 运行时依赖范围。使用此依赖范围的 Maven 依赖,对于测试和运行classpath 有效,但在编译主代码时无效。典型的例子是 JDBC 驱动实现,项目主代码的编译只需要 JDK 提供的 JDBC 接口,只有在执行测试或者运行项目的时候才需要实现上述接口的具体 JDBC 驱动。system: 系统依赖范围。该依赖与三种 classpath 的关系,和 provided 依赖范围完全一致。但是,使用 system 范围依赖时必须通过 systemPath 元素显式地指定依赖文件的路径。由于此类依赖不是通过 Maven 仓库解析的,而且往往与本机系统绑定,可能造成构建的不可移植,因此应该谨慎使用。
- Optional: 标记依赖是否可选.
- Exclusions: 用来排除传递性依赖。
2. 依赖的范围
首先需要知道,Maven 在编译项目主代码的时候需要使用一套 classpath。 比如:编译项目代码的时候需要用到 spring-core, 该文件以依赖的方式被引入到 classpath 中。 其次, Maven 在执行测试的时候会使用另外一套 classpath。 如:junit。最后在实际运行项目时,又会使用一套 classpath, spring-core 需要在该 classpath中,而 junit 不需要。 ? 那么依赖范围就是用来控制依赖与这三种 classpath(编译 classpath,测试 classpath, 运行时 classpath)的关系, Maven 有以下几种依赖范围:( 上面Scope中的5种 )
3. 传递性依赖
传递依赖机制, 让我们在使用某个 jar 的时候就不用去考虑它依赖了什么。也不用担心引入多余的依赖。 Maven 会解析各个直接依赖的 POM,将那些必要的间接依赖,以传递性依赖的形式引入到当前项目中。 注意: 传递依赖有可能产生冲突!! ? 冲突场景 A-->B--->C (2.0) ? A-->E--->C (1.0) ? 如果 A 下同时存在两个不同 version 的 C,冲突!!(选取同时适合 A、B 的版本)