发表于: 2018-03-09 18:29:35
3 662
今天学习的内容总结
接着昨天的写的,还是一样的。
三、编写测试代码
在之前我们已经知道了,测试代码和主代码不在一起,这样的好处是是项目的结构更加清晰。
在编写测用例之前,所以我们需要继续创建文件夹:src/test/java
而实际上,要进行单元测试,需要依赖一个JUnit的构件,所以我们要为Hello World添加一个JUnit依赖。在POM中添加如下?
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.7</version>
<scope>test</scope>
</dependency>
</dependencies>
由上面可以知道,所有需要的依赖,都放在了dependencies
元素的下面,同时依赖里相关的配置都需要在放在dependency
元素里面。
我们也都知道,通过groupId和artifactId可以找到这个构件,但是这个貌似有一点不同,因为他的groupId只有一个Junit!!在本地的仓库里面也没有找到!好吧,其实是有一个中央仓库。
【知识点】仓库
何为Maven仓库?
- 仓库中存在构建项目的组件和各种各样的依赖。
- 构件完成后生成的构件也可以安装或部署到仓库中,用
install
命令。
仓库严格的分为两种类型,一种是本地一种是远程。
本地仓库
本地仓库指的是从远程仓库下载的安装在你自己本地的仓库
本地仓库的位置是可以改变的,修改maven安装目录下的conf文件夹下的setting.xml文件,即可
【注】有的人建议把这个文件复制一份放在本地的仓库中,这样的好处,就是只有当前用户,是这个配置,此电脑的其他用户,在使用的试试,本地仓库就是他们自己设置的地址,或者是默认的。
将本地项目的构件安装到maven仓库中,如何去做呢?
项目根目录中,运行mvn clean install
[INFO] Scanning for projects...[INFO] [INFO] ------------------------------------------------------------------------[INFO] Building Maven Hello World Project 1.0-SNAPSHOT[INFO] ------------------------------------------------------------------------[INFO] [INFO] --- maven-clean-plugin:2.5:clean (default-clean) @ hello-world ---[INFO] Deleting /home/dreamer/workspace/hello-world/target[INFO] [INFO] --- maven-resources-plugin:2.6:resources (default-resources) @ hello-world ---[WARNING] Using platform encoding (UTF-8 actually) to copy filtered resources, i.e. build is platform dependent![INFO] skip non existing resourceDirectory /home/dreamer/workspace/hello-world/src/main/resources[INFO] [INFO] --- maven-compiler-plugin:3.1:compile (default-compile) @ hello-world ---[INFO] Changes detected - recompiling the module![WARNING] File encoding has not been set, using platform encoding UTF-8, i.e. build is platform dependent![INFO] Compiling 1 source file to /home/dreamer/workspace/hello-world/target/classes[INFO] [INFO] --- maven-resources-plugin:2.6:testResources (default-testResources) @ hello-world ---[WARNING] Using platform encoding (UTF-8 actually) to copy filtered resources, i.e. build is platform dependent![INFO] skip non existing resourceDirectory /home/dreamer/workspace/hello-world/src/test/resources[INFO] [INFO] --- maven-compiler-plugin:3.1:testCompile (default-testCompile) @ hello-world ---[INFO] Nothing to compile - all classes are up to date[INFO] [INFO] --- maven-surefire-plugin:2.12.4:test (default-test) @ hello-world ---[INFO] No tests to run.[INFO] [INFO] --- maven-jar-plugin:2.4:jar (default-jar) @ hello-world ---[INFO] Building jar: /home/dreamer/workspace/hello-world/target/hello-world-1.0-SNAPSHOT.jar[INFO] [INFO] --- maven-install-plugin:2.4:install (default-install) @ hello-world ---[INFO] Installing /home/dreamer/workspace/hello-world/target/hello-world-1.0-SNAPSHOT.jar to /home/dreamer/document/maven_local/com/mycom/app/hello-world/1.0-SNAPSHOT/hello-world-1.0-SNAPSHOT.jar[INFO] Installing /home/dreamer/workspace/hello-world/pom.xml to /home/dreamer/document/maven_local/com/mycom/app/hello-world/1.0-SNAPSHOT/hello-world-1.0-SNAPSHOT.pom[INFO] ------------------------------------------------------------------------[INFO] BUILD SUCCESS[INFO] ------------------------------------------------------------------------[INFO] Total time: 1.620 s[INFO] Finished at: 2018-03-09T15:52:32+08:00[INFO] Final Memory: 16M/203M[INFO] ------------------------------------------------------------------------
在本地仓库中,真的找到了!
不妨我们更加深入探讨一下,为什么它的输出目录就是本地仓库下的com/mycom/app
为什么它的名字是这种格式和jar呢?
从源码出发,看一下他到此经历了什么。
private static final char PATH_SEPARATOR = '/';
private static final char GROUP_SEPARATOR = '.';
private static final char ARTIFACT_SEPARATOR = '-';
public String pathOf( Artifact artifact )
{
ArtifactHandler artifactHandler = artifact.getArtifactHandler();
StringBuilder path = new StringBuilder( 128 );
path.append( formatAsDirectory( artifact.getGroupId() ) ).append( PATH_SEPARATOR );
path.append( artifact.getArtifactId() ).append( PATH_SEPARATOR );
path.append( artifact.getBaseVersion() ).append( PATH_SEPARATOR );
path.append( artifact.getArtifactId() ).append( ARTIFACT_SEPARATOR ).append( artifact.getVersion() );
if ( artifact.hasClassifier() )
{
path.append( ARTIFACT_SEPARATOR ).append( artifact.getClassifier() );
}
if ( artifactHandler.getExtension() != null && artifactHandler.getExtension().length() > 0 )
{
path.append( GROUP_SEPARATOR ).append( artifactHandler.getExtension() );
}
return path.toString();
}
private String formatAsDirectory( String directory )
{
return directory.replace( GROUP_SEPARATOR, PATH_SEPARATOR );
}
我们从上面的源码可以看出,一个构件是怎么输出到准确的位置的。
- 首先,先将构件的groupId中的
.
替换成/
,同时在后面加了一个/
,这时的path=“com/mycom/app/"
- 然后得到构件的ArtifactId和BaseVersion,将其添加到了,path的后面。此时
path="com/mycom/app/hello-world/1.0-SNAPSHOT/
- 再获取一遍artifactId和version,按如下格式拼接
artifactId-version-
然后再添加到中去,此时的path="com/mycom/app/hello-world/1.0-SNAPSHOT/hello-world-1.0-SNAPSHOT
- 检查构件否有classifier,如果有,就继续用
-
连接。 - 检查构件的extension,若extension存在,则加上句点分隔符和extension。可以看到extension是从artifactHandler而给artifact获取,artifactHandler是由项目的packaging决定,也就是packaging决定了构件的扩展名。
【疑】经过以上的源码分析,由于第2步中,获取的是baseVersion。(baseVersion是专门为快照版本准备的,version为1.0-SNAPSHOT的构件,其baseVersion就是1.0),所以应该是目录的结构应该是1.0才对?为何文件夹是1.0-SNAPSHOT?
中央仓库
最原始的本地仓库是空的,Maven至少需要一个可用的远程仓库,远程仓库指的是除本地仓库以外的任何其他的仓库,可以通过file://
和http://
等协议访问。
远程仓库的配置信息,其实在我们安装maven的时候就存在了,不信把M2_HOME/lib/maven-model-builder-3..jar
解压,访问org/apache/maven/model/pom-4.0.0.xml
就可以看到:
<repositories>
<repository>
<id>central</id>
<name>Central Repository</name>
<url>https://repo.maven.apache.org/maven2</url>
<layout>default</layout>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
</repositories>
仔细的分析一下,maven的中央仓库地址发现更改了,(但是之前的http://repo1.maven.org/maven2 也能用),布局是默认的,也就是之前的源码分析,下面的<snapshots> <enabled>
元素则是设置成了false,这个意思就是,不会从该仓库下载快照版本的构件。
远程仓库的配置
了解了很多了,但是我们只有一个默认的中央仓库还是不够的,还需要一个远程仓库,这个远程仓库该如何配置呢?肯定还是在项目的pom.xml中设置!继续在pom.xml
中添加代码如下:
<repositories>
<repository>
<id>jboss</id>
<name>JBoss Repository</name>
<url>http://repository.jboss.com/maven2</url>
<releases>
<enabled>true</enabled>
</releases>
<snapshots>
<enabled>false</enabled>
</snapshots>
<layout>default</layout>
</repository>
</repositories>
这些素估计你都能看懂吧,其中,releases的enabled值是true,表示开启JBoss仓库的发布版本下载支持。。
<snapshots>
和<release>
元素除了enabled,他们还包括另外两个子元素updatePolicy和checksumPolicy
<snapshots>
<enabled>true</enabled>
<updatePolicy>daily</updatePolicy>
<checksumPolicy>ignore</checksumPolicy></snapshots>
<updatePolicy>
表示的是Maven从远程仓库检查更新的频率,默认值是daily,其他值为never always(每构建都会检查更新) interval:X(每个X分钟检查一次更新。(x为任意证整数)
<checksumPolicy>
用来配置Maven检查检验和文件的策略。当构件被部署到Maven仓库的时候,会同时部署对应的校验和文件。如果校验失败,值为warn时,会打印出警告信息,fail时会让构建失败,ignore使得它忽视这个错误。
部署到远程仓库
在一个公司中,大家肯定要共用一些依赖,这些依赖和构建在别的仓库上市不存在的,于是创建了私服,这时出现了一个问题,如何将开发中生成的构件部署到仓库中呢?
还是需要修改项目的pom.xml文件,这时我们应该添加的元素是<distributionManagement>具体代码如下:
<distributionManagement>
<repository>
<id>proj-releases</id>
<name>Proj Release Repository</name>
<url>http://192.168.1.1000/content/repositories/proj-releases</url>
</repository>
<snapshotRepository>
<id>proj-snapshots</id>
<name>Proj Snapshot Repository</name>
<url>http://192.168.1.100/content/repositories/proj-snapshots</url>
</snapshotRepository>
</distributionManagement>
由上面可以见到,包含两个版本,一个是发布版本的构件的仓库,一个是快照版本的仓库。
通过mvn clean deploy
来进行部署.
测试代码
呼,终于所有的都弄完了,现在开始写代码吧。在src/test/java下创建文件HelloWorldTest.java代码如下:
package com.mycom.app.helloworld;import static org.junit.Assert.assertEquals;import org.junit.Test;public class HelloWorldTest{
@ Test public void testSayHello(){
HelloWorld helloWorld = new HelloWorld(); String result = helloWorld.sayHello();
assertEquals("Hello World",result);
}
}
【疑】在这里的package 和导入的两个包在哪里呢?为何没有找到?
自我答疑,我们导入了junit,这个包在本地仓库的junit/junit/4.7的jar包中,我觉得这就是maven的好处吧,他把仓库的地方和项目的地方结合在了一起,这样直接导入org.junit.Test 通过pom就可以找到了!真的很神奇!
【疑】在package中,本来是导的hello-world,但是出错,不允许,该怎么办?
关于里面的Junit的内容可以先不理,只看代码理解就可以了。
运行mvn clean test
进行测试。
成功了!
[INFO] Scanning for projects...[INFO] [INFO] ------------------------------------------------------------------------[INFO] Building Maven Hello World Project 1.0-SNAPSHOT[INFO] ------------------------------------------------------------------------[INFO] [INFO] --- maven-clean-plugin:2.5:clean (default-clean) @ hello-world ---[INFO] Deleting /home/dreamer/workspace/hello-world/target[INFO] [INFO] --- maven-resources-plugin:2.6:resources (default-resources) @ hello-world ---[WARNING] Using platform encoding (UTF-8 actually) to copy filtered resources, i.e. build is platform dependent![INFO] skip non existing resourceDirectory /home/dreamer/workspace/hello-world/src/main/resources[INFO] [INFO] --- maven-compiler-plugin:3.1:compile (default-compile) @ hello-world ---[INFO] Changes detected - recompiling the module![WARNING] File encoding has not been set, using platform encoding UTF-8, i.e. build is platform dependent![INFO] Compiling 1 source file to /home/dreamer/workspace/hello-world/target/classes[INFO] [INFO] --- maven-resources-plugin:2.6:testResources (default-testResources) @ hello-world ---[WARNING] Using platform encoding (UTF-8 actually) to copy filtered resources, i.e. build is platform dependent![INFO] skip non existing resourceDirectory /home/dreamer/workspace/hello-world/src/test/resources[INFO] [INFO] --- maven-compiler-plugin:3.1:testCompile (default-testCompile) @ hello-world ---[INFO] Changes detected - recompiling the module![WARNING] File encoding has not been set, using platform encoding UTF-8, i.e. build is platform dependent![INFO] Compiling 1 source file to /home/dreamer/workspace/hello-world/target/test-classes[INFO] [INFO] --- maven-surefire-plugin:2.12.4:test (default-test) @ hello-world ---[INFO] Surefire report directory: /home/dreamer/workspace/hello-world/target/surefire-reports-------------------------------------------------------
T E S T S-------------------------------------------------------Running com.mycom.app.helloworld.HelloWorldTestTests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.076 secResults :Tests run: 1, Failures: 0, Errors: 0, Skipped: 0[INFO] ------------------------------------------------------------------------[INFO] BUILD SUCCESS[INFO] ------------------------------------------------------------------------[INFO] Total time: 2.054 s[INFO] Finished at: 2018-03-09T17:52:45+08:00[INFO] Final Memory: 16M/199M[INFO] ------------------------------------------------------------------------
需要注意的是,他先下载了junit-4.7.pom和junit-4.7.jar,上图没有显示是因为我执行了几次,已经下载过了。
四、打包
终于到了这一时刻,将项目编译、测试之后,下一个重要的命令就是打包(package)此项目中没有制定打包类型,前面所说的就是用默认类型jar包。
使用命令mvn clean package
输出如下:
[INFO] Scanning for projects...[INFO] [INFO] ------------------------------------------------------------------------[INFO] Building Maven Hello World Project 1.0-SNAPSHOT[INFO] ------------------------------------------------------------------------[INFO] [INFO] --- maven-clean-plugin:2.5:clean (default-clean) @ hello-world ---[INFO] Deleting /home/dreamer/workspace/hello-world/target[INFO] [INFO] --- maven-resources-plugin:2.6:resources (default-resources) @ hello-world ---[WARNING] Using platform encoding (UTF-8 actually) to copy filtered resources, i.e. build is platform dependent![INFO] skip non existing resourceDirectory /home/dreamer/workspace/hello-world/src/main/resources[INFO] [INFO] --- maven-compiler-plugin:3.1:compile (default-compile) @ hello-world ---[INFO] Changes detected - recompiling the module![WARNING] File encoding has not been set, using platform encoding UTF-8, i.e. build is platform dependent![INFO] Compiling 1 source file to /home/dreamer/workspace/hello-world/target/classes[INFO] [INFO] --- maven-resources-plugin:2.6:testResources (default-testResources) @ hello-world ---[WARNING] Using platform encoding (UTF-8 actually) to copy filtered resources, i.e. build is platform dependent![INFO] skip non existing resourceDirectory /home/dreamer/workspace/hello-world/src/test/resources[INFO] [INFO] --- maven-compiler-plugin:3.1:testCompile (default-testCompile) @ hello-world ---[INFO] Changes detected - recompiling the module![WARNING] File encoding has not been set, using platform encoding UTF-8, i.e. build is platform dependent![INFO] Compiling 1 source file to /home/dreamer/workspace/hello-world/target/test-classes[INFO] [INFO] --- maven-surefire-plugin:2.12.4:test (default-test) @ hello-world ---[INFO] Surefire report directory: /home/dreamer/workspace/hello-world/target/surefire-reports-------------------------------------------------------
T E S T S-------------------------------------------------------Running com.mycom.app.helloworld.HelloWorldTestTests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.055 secResults :Tests run: 1, Failures: 0, Errors: 0, Skipped: 0[INFO] [INFO] --- maven-jar-plugin:2.4:jar (default-jar) @ hello-world ---[INFO] Building jar: /home/dreamer/workspace/hello-world/target/hello-world-1.0-SNAPSHOT.jar[INFO] ------------------------------------------------------------------------[INFO] BUILD SUCCESS[INFO] ------------------------------------------------------------------------[INFO] Total time: 2.098 s[INFO] Finished at: 2018-03-09T18:05:29+08:00[INFO] Final Memory: 17M/202M[INFO] ------------------------------------------------------------------------
现在,我仅仅将项目主代码打包成了hello-world-1.0-SNAPSHOT.jar`,并输出到了/target/文件夹中,如何让其他项目也能用此包呢?
有两种方法,第一种将此jar包放在其他项目的classpath中,(在刚开始设置了classpath有一项就是本目录下,所以将它放在其他项目的目录下就好了)
第二种则是使用mvn clean install
就可以直接使用了!
其实使用install命令就会执行前面的所有命令。
运行
默认打包生成的jar文件是不能直接运行的,因为带有main方法的累心不会添加到manifect中(打开jar文件中的META-INF/MANIFEST.MF文件,无法看到Main-Class一行)为了生成可执行的jar文件,需要借助maven-shade-plugin
这个是插件!
明天
1. 开始学习插件,插件的配置等
2. Archetype学一下?
3. 熟悉IDEA,
一定要完成这几个,今天学的慢的原因,是我写文章写到一半不小心退了,没有自动保存,又重新写的。。。
问题
1. 在编写代码的时候,为什么在完全不同的两个文件夹下面,都可以直接导入,并成功运行?
自我答疑:我们导入了junit,这个包在本地仓库的junit/junit/4.7的jar包中,我觉得这就是maven的好处吧,他把仓库的地方和项目的地方结合在了一起,这样直接导入org.junit.Test 通过pom就可以找到了!真的很神奇!
这或许就是maven吧。。。。强大。。pom。。。强大。。。这pom竟如此恐怖如斯?
收货
收货多多
评论