POM是什么?
1、像Make的Makefile、Ant的build.xml一样,Maven项目的核心是pom.xml
2、POM (Project Object Model, 项目对象模型) 定义了项目的基本信息,用于描述项目如何构建,声明项目依赖等等
如何编写一个Hello World的POM?
新建一个名为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/maven/-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.juvenxu.mvnbook</groupId>
<artifactId>hello-world</artifactId>
<version>1.0-SNAPSHOT</version>
<name>Maven Hello World Project</name>
</project>
对楼上的配置进行解释
1、代码的第一行是XML头,指定了该xml文档的版本和编码方式
2、紧接着的project元素,project是所有pom.xml的根元素,它还声明了一些POM相关的命名空间及xsd元素(虽然这些属性不是必须的,但使用这些属性能够让第三方工具,如IDE中的XML编辑器,帮助我们快速编辑POM)
3、根元素下的第一个子元素modelVersion指定了当前POM模型的版本,对于Maven2及Maven3来说,它只能是4.0.0
4、最重要的groupId、artifactId和version,这三个元素定义了一个项目基本的坐标,在Maven的世界,任何的jar、pom或者war都是以基于这些基本的坐标进行区分的
groupId是什么意思?
groupId定义了项目属于哪个组,这个组往往和项目所在的组织或公司存在关联,比如在googlecode上建立了一个名为myapp的项目,那么groupId就应该是com.googlecode.myapp
artifactId是什么意思?
artifactId用于定义该项目下的某个模块,比如myapp-util、myapp-domain、myapp-web等
version是什么意思?
version指定了Hello World项目当前的版本——1.0.SNAPSHOT
SNAPSHOT是什么意思?
SNAPSHOT意为快照,说明该项目还处于开发中,是不稳定的版本。随着项目的发展,version会不断更新,如升级为1.0、1.1-SNAPSHOT、1.1、2.0等
最后的是name是什么意思?
最后的name元素声明了一个对于用户更为友好的项目名称,虽然这不是必须的,但还是推荐为每个POM声明name,以方便信息交流
Maven中的项目主代码和测试代码分别是指?
1、项目的主代码会被打包到最终构建中(如jar)
2、项目的测试代码只在运行测试时用到,不会被打包
3、默认情况下,Maven假设项目主代码位于src/main/java目录,测试代码位于src/test/java
关于Java代码有两点需要注意
1、应该把项目主代码放到src/main/java目录下(遵循Maven的约定),而无需额外的配置,Maven会自动搜寻该目录找到项目主代码
2、该Java类的包名是com.juvenxu.mvnbook.helloworld,这与之前在POM中定义的groupId和artifactId相吻合,一般来说,项目中Java类的包都应该基于项目的groupId和artifactId,这样更加清晰、更加符合逻辑,也方便搜索构件或者Java类
在项目根目录下运行命令 mvn clean compile
1、clean命令告诉Maven清理输出目录target,就是删除target目录
2、compile命令告诉Maven编译项目主代码
3、默认情况,Maven构建的所有输出都在target/目录中,compile任务将项目主代码编译至target/classes目录,(target\classes\com\juvenxu\mvnbook\helloworld\HelloWorld.class)
4、执行任务顺序是: clean:clean任务、resources:resources任务、compile:compile任务,resources任务是处理项目资源(src/main/resources、src/test/resources)
上面提到的clean:clean、resources:resources、compile:compile是指?
格式应该是:插件:插件目标
比如clean:clean是clean插件的clean目标,以此类推
引入JUnit依赖
在Java世界中,由Kent Beck和Erich Gamma建立的Junit是事实上的单元测试标准,要使用JUnit,首先需要为Hello World项目添加一个JUnit依赖,修改项目的POM如下:
<?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/maven/-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.juvenxu.mvnbook</groupId>
<artifactId>hello-world</artifactId>
<version>1.0-SNAPSHOT</version>
<name>Maven Hello World Project</name>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.7</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>
对上面配置进行解释
1、配置中添加了dependencies元素,该元素下可以包含多个dependency元素
2、添加junit坐标,Maven自动下载junit-4.7.jar
3、scope元素指的是依赖范围
依赖范围是指?
1、若依赖范围为test表示该依赖只对测试有效,换句话说,测试代码中import JUnit代码是没问题的,但是如果在主代码中用import JUnit代码,就会造成编译错误。
2、若不声明依赖范围,那么默认值就是compile,表示该依赖对主代码和测试代码都有效
一个典型的单元测试包含三个步骤
1、准备测试类及数据
2、执行要测试的行为
3、检查结果
另外JUnit3中,约定所有需要执行测试的方法都以test开头,JUnit4中,测试方法都以@Test 进行标注
执行mvn clean test
执行该命令会依次执行如下任务:
任务名 |
插件和版本号 |
Clean |
Maven-clean-plugin:2.5 |
Resources |
Maven-resources-plugin:2.6 |
Compile |
Maven-compile-plugin:2.5.1 |
testResources |
Maven-resources-plugin:2.6 |
testCompile |
Maven-compile-plugin:2.5.1 |
Test |
Maven-surefire-plugin:2.12.4 |
之后就是Surefire report directory: target\surefire-reports
执行测试,测试完成后会在target\surefire-reports下生成测试报告,一个.txt文件一个.xml文件,测试报告显示一共运行了多少测试,失败多少,出错了多少,跳过了多少
打包和运行 mvn clean package
1、默认打包类型jar,会执行jar:jar任务
2、将主代码打包成hello-world-1.0-SNAPSHOP.jar
3、也可以使用finalName来自定义该文件的名称
如何让其他的Maven项目直接引用自己的jar? mvn clean install
1、执行安装任务install:install
2、将该项目的pom和jar安装到本地仓库,便于其他maven项目引用
直接使用mvn clean install命令打包的jar文件无法直接执行,虽然有main方法
因为带有main方法的类信息不会添加到manifest中(打开jar文件中的META-INF/MANIFEST.MF文件,将无法看到Main-Class一行)
那么如何解决jar文件有main方法但是不能执行这一问题
为了生成可执行的jar文件,需要借助maven-shade-plugin,配置该插件如下:
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>1.2</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<transformers>
<transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
<mainClass>com.juvenxu.mvnbook.helloworld.HelloWorld</mainClass>
</transformer>
</transformers>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
plugin元素在POM中的相对位置应该是<project> <build> <plugins>下面
配置<mainClass>com.juvenxu.mvnbook.helloworld.HelloWorld</mainClass>,项目在打包时会将该信息放到MANIFEST中
现在执行mvn clean install
在target目录下会生成两个jar:
hello-world-1.0-SNAPSHOT.jar,可执行的jar
orginal-hello-world-1.0-SNAPSHOT.jar,原始的jar
打开hello-world-1.0-SNAPSHOT.jar的META-INF/MANIFEST.MF,可以看到如下这样一行信息: Main-Class: com.juvenxu.mvnbook.helloworld.HelloWorld
现在,在项目根目录下执行: java -jar original-hello-world-1.0-SNAPSHOT.jar 结果是:Hello Maven