很多時候,我們需要對編寫的程序進行打包,這個時候,我們可以借助一些項目構建工具,如maven, sbt, ant等,這里我使用的是maven。
打包成可執行有主類的jar包(jar包中無依賴)
以下是配置打包成可執行,帶主類的jar包:
<project> ... <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-jar-plugin</artifactId> ... <configuration> <archive> <manifest> <addClasspath>true</addClasspath> <mainClass>fully.qualified.MainClass</mainClass> <!-- 你的主類名 --> </manifest> </archive> </configuration> ... </plugin> </plugins> </build>
But, 雖然現在把程序打包成了jar文件,也可以運行,但是,這個jar包是沒有包含依賴的,因此,如果這個程序有其他依賴,那么在運行這個程序的時候,需要指定類目錄,並且要把所有的依賴都放到類目錄下去,手動添加依賴到類目錄下,簡直就是惡夢。。。
我曾經就這么干過,它少一個依賴,我就手動加一個到類目錄,少一個,加一個,少一個,加一個,當我加了大概有10幾個之后,而且還看不到盡頭。。。簡直要瘋的節奏,然后想起之前用sbt打包,也是可以把依賴添加到jar包,心情頓時好轉,趕緊google,於是找到google到了maven的官網…。順便說一下,雖然我們google的時候,會搜索到很多結果,但很多時候,我們最好選擇合適的結果進行閱讀,我的一般順序是:官方優先,StackExchange。。。
打包成帶依賴的jar包
配置
不加main類而帶依賴的jar包
編輯pom.xml文件,內容如下:
<project> [...] <build> [...] <plugins> <plugin> <artifactId>maven-assembly-plugin</artifactId> <version>3.0.0</version> <configuration> <descriptorRefs> <descriptorRef>jar-with-dependencies</descriptorRef> </descriptorRefs> </configuration> <executions> <execution> <id>make-assembly</id> <!-- this is used for inheritance merges --> <phase>package</phase> <!-- bind to the packaging phase --> <goals> <goal>single</goal> </goals> </execution> </executions> </plugin> [...] </project>
加main類也帶依賴的jar包
編輯pom.xml文件,內容如下:
<project> <build> <plugins> <!--(start) for package jar with dependencies --> <plugin> <artifactId>maven-assembly-plugin</artifactId> <version>3.0.0</version> <configuration> <archive> <manifest> <mainClass>Main</mainClass> </manifest> </archive> <descriptorRefs> <descriptorRef>jar-with-dependencies</descriptorRef> </descriptorRefs> </configuration> <executions> <execution> <id>make-assembly</id> <!-- this is used for inheritance merges --> <phase>package</phase> <!-- bind to the packaging phase --> <goals> <goal>single</goal> </goals> </execution> </executions> </plugin> <!--(end) for package jar with dependencies --> </plugins> </build> </project>
值得注意的是,不要像以下那樣修改pom.xml文件,那樣雖然不會報錯,但生成的jar包中的MANIFEST.MF
中沒有主類,這樣的jar包無法直接運行。
<project> [...] <build> [...] <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-jar-plugin</artifactId> ... <configuration> <archive> <manifest> <addClasspath>true</addClasspath> <mainClass>fully.qualified.MainClass</mainClass> <!-- 你的主類名 --> </manifest> </archive> </configuration> ... </plugin> <plugin> <artifactId>maven-assembly-plugin</artifactId> <version>3.0.0</version> <configuration> <descriptorRefs> <descriptorRef>jar-with-dependencies</descriptorRef> </descriptorRefs> </configuration> <executions> <execution> <id>make-assembly</id> <!-- this is used for inheritance merges --> <phase>package</phase> <!-- bind to the packaging phase --> <goals> <goal>single</goal> </goals> </execution> </executions> </plugin> [...] </project>
打包
使用以下命令打包:
mvn package
就像官方網站說的,” this is pretty simple! “
然而,當在運行操作hdfs的jar包時,我出現了以下問題:
Exception in thread "main" java.io.IOException: No FileSystem for scheme: hdfs at org.apache.hadoop.fs.FileSystem.getFileSystemClass(FileSystem.java:2660) at org.apache.hadoop.fs.FileSystem.createFileSystem(FileSystem.java:2667) at org.apache.hadoop.fs.FileSystem.access$200(FileSystem.java:94) at org.apache.hadoop.fs.FileSystem$Cache.getInternal(FileSystem.java:2703) at org.apache.hadoop.fs.FileSystem$Cache.get(FileSystem.java:2685) at org.apache.hadoop.fs.FileSystem.get(FileSystem.java:373) at sentry.magic.fs.Dfs.<init>(Dfs.java:20) at sentry.magic.fs.CheckFlumeIsCompleted.<init>(CheckFlumeIsCompleted.java:26) at Main.main(Main.java:26)
好在有位仁兄[2]也遇到了這個問題,從而使得問題解決。解決方法如下:
FileSystem dfs = null; Configuration conf = new Configuration(); public Dfs(URI uri) throws IOException { // 必須有下面這一句 conf.set("fs.hdfs.impl","org.apache.hadoop.hdfs.DistributedFileSystem"); // 必須有上面那一句 dfs = FileSystem.get(uri,conf); }
除了他之種方法之外,我也自己摸索出了一種方法,經過實踐,也是可行的,我的方法如下:
找到打包好的jar包,然后使用歸檔管理器打開這個jar包,即“open with archive manager”,找到META-INFO/services
目錄,再找到這個目錄下的org.apache.Hadoop.fs.FileSystem
文件,編輯這個文件,在文件末尾加上一行:
org.apache.hadoop.hdfs.DistributedFileSystem
但是,這么修改jar的方法,不太合適,因為每生成一次,需要修改一次,所以,建議暫時使用前面那種解決方法。
參考文獻:
[1] https://maven.apache.org/plugins/maven-assembly-plugin/usage.html
[2] http://www.cnblogs.com/justinzhang/p/4983673.html