maven學習二(dependencies)


在前面一篇文章maven學習一(HelloWorld工程)已經對maven有了基本介紹,本文開始介紹maven依賴,通過如何如何增加log4j來學習maven的dependencies

no-dependencies模式

首先介紹maven不加如何配置情況下default的模式。在前面HelloWorld的App.java里添加log4j:

$ vim src/main/java/com/firefoxbug/www/App.java
package com.firefoxbug.www;

import org.apache.log4j.Logger;

public class App
{
    public static void main( String[] args )
    {
        Logger logger = Logger.getLogger(App.class);
        logger.info( "Hello World!" );
    }
}

# 增加log4j配置
$ mkdir src/main/resources/ && vim log4j.properties
# Root logger option
log4j.rootLogger=DEBUG, stdout, file

# Redirect log messages to console
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target=System.out
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%L - %m%n

# Redirect log messages to a log file, support file rolling.
log4j.appender.file=org.apache.log4j.RollingFileAppender
log4j.appender.file.File=/tmp/logcount.log
log4j.appender.file.MaxFileSize=5MB
log4j.appender.file.MaxBackupIndex=10
log4j.appender.file.layout=org.apache.log4j.PatternLayout
log4j.appender.file.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%L - %m%n

$ mvn package # 這里必然是會報錯的,因為找不到Logger庫

接下來在pom.xml里描述對log4j的依賴:

$ vim pom.xml
<dependencies>
  ....
    <dependency>
        <groupId>log4j</groupId>
        <artifactId>log4j</artifactId>
        <version>1.2.17</version>
    </dependency>
  ...
 </dependencies>

$ mvn package -Dmaven.test.skip=true # 再次編譯能過
$ mvn dependency:tree # 查看所有依賴
...
[INFO] +- junit:junit:jar:3.8.1:test
[INFO] \- log4j:log4j:jar:1.2.17:compile
...

但是運行的時候報錯,原因還是找不到log4j的庫,原因是因為生成的jar包里不包含log4j相關的庫,而且$CLASSPATH里也沒有log4j的lib。

$java -cp target/HelloWorld-1.0-SNAPSHOT.jar com.firefoxbug.www.App
Exception in thread "main" java.lang.NoClassDefFoundError: org/apache/log4j/Logger
    at com.firefoxbug.www.App.main(App.java:9)
Caused by: java.lang.ClassNotFoundException: org.apache.log4j.Logger
...

一種解法就是把log4j的包下載下來,然后運行時指定classpath

$ cd /tmp/ 
$ wget https://archive.apache.org/dist/logging/log4j/1.2.17/log4j-1.2.17.tar.gz
$ tar -zxvf log4j-1.2.17.tar.gz
$ java -cp "target/HelloWorld-1.0-SNAPSHOT.jar:/tmp/apache-log4j-1.2.17/log4j-1.2.17.jar:" com.firefoxbug.www.App

試想一下,運行時log4j是找到了,但是一旦jar包發布出去到線上,而線上機器並沒有配置運行時的log4j呢?這時候maven就可以配置one-jar模式,把所有外部依賴jar包都打進一個包。

one-jar/jar-with-dependencies模式

修改工程下面的maven配置,配置成jar-with-dependencies模式。

$ vim ~/pom.xml
<project>
    ...
    <build>
        <sourceDirectory>src/main/java</sourceDirectory>
        <plugins>
            <plugin>
                <artifactId>maven-assembly-plugin</artifactId>
                <configuration>
                    <descriptorRefs>
                        <descriptorRef>jar-with-dependencies</descriptorRef>
                    </descriptorRefs>
                </configuration>
                <executions>
                    <execution>
                        <id>make-assembly</id>
                        <phase>package</phase>
                        <goals>
                            <goal>attached</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>
    ...
</project>

再次用maven編譯,就會發現target下面多了一個HelloWorld-1.0-SNAPSHOT-jar-with-dependencies.jar,這個包里面就包含了外部依賴的class文件

$ mvn clean && mvn package
$ java -cp "target/HelloWorld-1.0-SNAPSHOT-jar-with-dependencies.jar" com.firefoxbug.www.App
2016-01-10 21:59:27 INFO  App:10 - Hello World!

其實可以嘗試吧*-jar-with-dependencies.jar解壓出來就會發現里面已經包含了org/apache/log4j的所有class文件。

muti-jar/copy-dependencies模式

上面的one-jar模式會把所有的外部依賴都打包到一個jar包里,但是如果我不想把外部的dependencies打入我的jar包,而且又要能夠解決所有運行時依賴。maven也提供了一種muti-jar/copy-dependencies模式。

$ vim pom.xml
<project>
    ...
    <build>
        <sourceDirectory>src/main/java</sourceDirectory>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-dependency-plugin</artifactId>
                <executions>
                    <execution>
                        <id>copy</id>
                        <phase>package</phase>
                        <goals>
                            <goal>copy-dependencies</goal>
                        </goals>
                        <configuration>
                            <outputDirectory>
                                ${project.build.directory}
                            </outputDirectory>
                        </configuration>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>
    ...
</project>

再次用maven clean、package后,發現在target下面會獨立出現HelloWorld-1.0-SNAPSHOT.jar和log4j-1.2.17.jar

$ mvn clean && mvn package
$ java -cp "target/HelloWorld-1.0-SNAPSHOT.jar:target/log4j-1.2.17.jar" com.firefoxbug.www.App
2016-01-10 22:25:26 INFO  App:10 - Hello World!

總結

maven編譯打包可以支持三種模式,分別如下:

  1. no-dependencies: 這種模式下target下面不會出現任何依賴的包,必須手動指定-classpath設置所在環境的依賴包路徑;
  2. with-dependencies: 這種模式會把所有外部依賴的包都打進一個jar包,只需要把jar包發布到線上即可運行;
  3. copy-dependencies: 這種模式會把外部依賴的jar包都獨立生成到target/下面,運行時候手動指定-classpath;

from: http://www.firefoxbug.com/index.php/archives/2816/


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM