Maven을 사용하여 최종 JAR 파일 내의 라이브러리 폴더에 필요한 모든 JAR 파일을 어떻게 넣습니까?


104

독립 실행 형 응용 프로그램에서 Maven을 사용하고 있으며 여기 답변 중 하나에서 언급했듯이 JAR 파일의 모든 종속성을 라이브러리 폴더 안에 패키징하고 싶습니다.

Maven을 사용하여 종속성이있는 실행 가능한 JAR을 어떻게 만들 수 있습니까?

최종 JAR 파일에 maven-shade-plugin.m2 폴더의 Maven 계층과 같은 폴더 형태로 종속성을 넣는 것과는 달리 JAR 파일로 종속성을 포함하는 라이브러리 폴더가 있어야 합니다.

글쎄, 실제로 현재 구성은 내가 원하는 것을 수행하지만 응용 프로그램을 실행할 때 JAR 파일을로드하는 데 문제가 있습니다. 수업을로드 할 수 없습니다.

내 구성은 다음과 같습니다.

<plugins>

    <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-dependency-plugin</artifactId>
        <executions>
            <execution>
                <id>copy-dependencies</id>
                <phase>prepare-package</phase>
                <goals>
                    <goal>copy-dependencies</goal>
                </goals>
                <configuration>
                    <outputDirectory>${project.build.directory}/classes/lib</outputDirectory>
                    <overWriteReleases>false</overWriteReleases>
                    <overWriteSnapshots>false</overWriteSnapshots>
                    <overWriteIfNewer>true</overWriteIfNewer>
                </configuration>
            </execution>
        </executions>
    </plugin>

    <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-jar-plugin</artifactId>
        <configuration>
            <archive>
                <manifest>
                    <addClasspath>true</addClasspath>
                    <classpathPrefix>lib/</classpathPrefix>
                    <mainClass>com.myapp.MainClass</mainClass>
                </manifest>
            </archive>
        </configuration>
    </plugin>

    <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-compiler-plugin</artifactId>
        <configuration>
            <source>1.6</source>
            <target>1.6</target>
        </configuration>
    </plugin>

    <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-dependency-plugin</artifactId>
        <executions>
            <execution>
                <id>install</id>
                <phase>install</phase>
                <goals>
                    <goal>sources</goal>
                </goals>
            </execution>
        </executions>
    </plugin>

    <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-resources-plugin</artifactId>
        <version>2.5</version>
        <configuration>
            <encoding>UTF-8</encoding>
        </configuration>
    </plugin>

</plugins>

프로젝트는 Eclipse에서 잘 실행되고 JAR 파일은 원하는대로 최종 JAR 파일 내의 라이브러리 폴더에 저장되지만 대상 폴더에서 최종 JAR 파일을 실행하면 항상 다음을 얻습니다 ClassNotFoundException.

Exception in thread "main" java.lang.NoClassDefFoundError: org/springframework/context/ApplicationContext
Caused by: java.lang.ClassNotFoundException: org.springframework.context.ApplicationContext
        at java.net.URLClassLoader$1.run(Unknown Source)
        at java.security.AccessController.doPrivileged(Native Method)
        at java.net.URLClassLoader.findClass(Unknown Source)
        at java.lang.ClassLoader.loadClass(Unknown Source)
        at sun.misc.Launcher$AppClassLoader.loadClass(Unknown Source)
        at java.lang.ClassLoader.loadClass(Unknown Source)
Could not find the main class: com.myapp.MainClass. Program will exit.

이 예외를 어떻게 수정할 수 있습니까?


1
항아리를 실행하는 데 어떤 명령을 사용합니까? 아마 당신은 maven exec 플러그인을 선호 할 수 있습니까?
Andrey Borisov

POM 파일과 비교할 때 예외 메시지가 오래 되었습니까? 메인 클래스 com.myapp.MainClass가 아닌 com.tastycafe.MainClass.
Duncan Jones

@Duncan 존스, 문제를 붙여 복사, 내가 질문 편집
마흐무드 살레

3
jar 내부에 jar를 넣으려면 Java의 표준 클래스 로더가이를 이해할 수 없습니다.
Thorbjørn Ravn Andersen

lib 폴더에 있지만 JAR 외부에 Maven 종속성을 배치하는 방법은 무엇입니까?
ed22

답변:


81

다음은 내 솔루션입니다. 그것이 당신을 위해 작동하는지 테스트하십시오.

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-dependency-plugin</artifactId>
    <executions>
        <execution>
            <id>copy-dependencies</id>
            <phase>prepare-package</phase>
            <goals>
                <goal>copy-dependencies</goal>
            </goals>
            <configuration>
                <outputDirectory>${project.build.directory}/classes/lib</outputDirectory>
                <overWriteReleases>false</overWriteReleases>
                <overWriteSnapshots>false</overWriteSnapshots>
                <overWriteIfNewer>true</overWriteIfNewer>
            </configuration>
        </execution>
    </executions>
</plugin>

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-jar-plugin</artifactId>
    <configuration>
        <archive>
            <manifest>
                <addClasspath>true</addClasspath>
                <!-- <classpathPrefix>lib</classpathPrefix> -->
                <!-- <mainClass>test.org.Cliente</mainClass> -->
            </manifest>
            <manifestEntries>
                <Class-Path>lib/</Class-Path>
            </manifestEntries>
        </archive>
    </configuration>
</plugin>

첫 번째 플러그인은 모든 종속성을 target / classes / lib 폴더에 넣고 두 번째 플러그인은 최종 JAR 파일에 라이브러리 폴더를 포함하고 파일을 구성 Manifest.mf합니다.

하지만 JAR 파일을로드하려면 사용자 정의 클래스 로딩 코드를 추가해야합니다.

또는 사용자 정의 클래스 로딩을 방지하기 위해 "$ {project.build.directory} / lib를 사용할 수 있지만이 경우 최종 JAR 파일 내에 종속성이 없어 목적에 맞지 않습니다.

질문을받은 지 2 년이 지났습니다. 그럼에도 불구하고 중첩 된 JAR 파일의 문제는 지속됩니다. 누군가에게 도움이되기를 바랍니다.


1
사용법 : mvn install, cd target, java -jar MyJarFile-1.0.jar
djb

내가 뭘 그리워? 그러면 "lib /"와 lib 폴더의 모든 단일 jar가 포함 된 매니페스트 클래스 경로 항목이 생성됩니다. 이것은 의도 된 것인가? 왜?
gapvision

2
나는 $ {project.build.directory}에 "$ {project.build.directory} / 클래스 / lib 디렉토리를"/ lib 디렉토리 변경 후 그것은 일
라젠 드라 Thorat을

1
불행하게도 제공된대로 선언 된 종속성이 포함됩니다.
Philippe Gioseffi

@Rajendra 감사는, 그게 도움 : $ {project.build.directory} / lib 디렉토리
Mindaugas의 K.을

30

업데이트 :

<build> 
  <plugins> 
    <plugin> 
    <artifactId>maven-dependency-plugin</artifactId> 
    <executions> 
      <execution> 
        <phase>install</phase> 
          <goals> 
            <goal>copy-dependencies</goal> 
          </goals> 
          <configuration> 
             <outputDirectory>${project.build.directory}/lib</outputDirectory> 
          </configuration> 
        </execution> 
      </executions> 
    </plugin> 
  </plugins> 
</build> 

4
이것은 jar 외부에 lib 폴더를 넣습니다 (제가 원하는 것이 아닙니다). 항아리 안에 lib를 넣는 것보다 낫습니까? 이 경우 응용 프로그램을 클라이언트에 전달하는 방법은 무엇입니까?
Mahmoud Saleh

이제 더 분명해졌습니다. Google 검색을 해보겠습니다. 하지만 실행 가능한 jar 파일 내의 지정된 폴더에 모든 종속성 jar 파일을 복사하려는 이유를 알고 싶습니다. 모든 종속성 jar 파일이 jar 파일 내에있는 경우 lib 폴더에서 찾아야하는 이유는 무엇입니까?
Ahmet Karakaya

23

가장 간단하고 효율적인 방법은 다음과 같은 uber 플러그인을 사용하는 것입니다.

          <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-shade-plugin</artifactId>
            <executions>
                <execution>
                    <phase>package</phase>
                    <goals>
                        <goal>shade</goal>
                    </goals>
                </execution>
            </executions>
            <configuration>
                <finalName>uber-${artifactId}-${version}</finalName>
            </configuration>
        </plugin>

하나의 JAR 파일에서 모두 비정규 화됩니다.


내 현재 구성에 추가하여 사용 하시겠습니까? 그리고이 플러그인은 정확히 무엇을합니까?
Mahmoud Saleh

15
내 jar 파일이 이렇게 보이기를 원하지 않습니다. netbean이하는 것처럼 jar 파일 내의 lib 폴더에 모든 종속성을 갖고 싶습니다.
Mahmoud Saleh

12

실행 포장 받는다는 플러그인은 정확히 그 목적을 위해 사용할 수 있습니다 특정 폴더에 JAR 파일로 모든 종속성을 포함하는 독립형 자바 응용 프로그램을 만드는.

섹션 pom.xml내부에 다음을 추가하기 만하면됩니다 <build><plugins>( mainClass그에 따라 값을 바꾸십시오 ).

<plugin>
    <groupId>de.ntcomputer</groupId>
    <artifactId>executable-packer-maven-plugin</artifactId>
    <version>1.0.1</version>
    <configuration>
        <mainClass>com.example.MyMainClass</mainClass>
    </configuration>
    <executions>
        <execution>
            <goals>
                <goal>pack-executable-jar</goal>
            </goals>
        </execution>
    </executions>
</plugin>

내장 된 JAR 파일은 다음 위치에 target/<YourProjectAndVersion>-pkg.jar당신이 실행 한 후 mvn package. 모든 컴파일 시간 및 런타임 종속성은 lib/JAR 파일 내의 폴더에 포함 됩니다.

면책 조항 : 나는 플러그인의 작성자입니다.


나는 그것을 시도하고 그것이 작동한다고 말할 수 있습니다 ... 당신이 말했듯이,이 플러그인은 라이브러리 (jars)가있는 jar 파일을 jar의 lib 디렉토리에 만듭니다 ... 구성은 정말 쉽습니다 .. 나는 그것이 무엇이라고 생각합니다. 이 질문의 작성자는 예상하고 있습니다 ... 내 투표를 줄 것입니다 ... 내가 찾은 유일한 단점 (이것이 내가 그것을 사용할 수 없었던 이유입니다), 실행하는 데 지연이 있습니다. jar 및 응용 프로그램이 표시됩니다 (약 20 초). 아마도 사용자 정의 클래스 로더에 libs를 등록하는 프로세스 때문일 것입니다 ...하지만 훌륭한 접근 방식이며 훌륭한 플러그인입니다 ...
Adam M. Gamboa G.


3

방법은 다음과 같습니다.

    <plugin>
            <artifactId>maven-assembly-plugin</artifactId>
            <version>2.2</version>
            <configuration>
                <appendAssemblyId>false</appendAssemblyId>
                <descriptorRefs>
                    <descriptorRef>jar-with-dependencies</descriptorRef>
                </descriptorRefs>
                <archive>
                    <manifest>
                        <mainClass>com.project.MainClass</mainClass>
                    </manifest>
                </archive>
            </configuration>
        </plugin>

그런 다음 실행합니다.

mvn assembly:assembly

1
assemblyJAR의 "target / classes"에있는 모든 것을 넣을 것이므로 항상 미리 컴파일을해야합니다 . 이렇게하면 JAR에 최근에 소스 코드에서 변경 한 사항이 모두 포함됩니다. 따라서 다음과 같이해야합니다 mvn clean compile assembly:assembly..
naXa 2014 년

2

질문에 대한 답을 찾았습니다.

http://padcom13.blogspot.co.uk/2011/10/creating-standalone-applications-with.html

lib 폴더에 종속 lib 파일을 가져올뿐만 아니라 unix 및 dos 실행 파일이 모두 포함 된 bin 디렉터도 제공됩니다.

실행 파일은 궁극적으로 모든 종속 라이브러리를 나열하는 -cp 인수로 java를 호출합니다.

전체 부지는 대상 폴더 내의 appasembly 폴더에 있습니다. 서사시.

============= 예 저는 이것이 오래된 스레드라는 것을 알고 있지만 여전히 검색 결과가 높아지고 있으므로 저 같은 사람에게 도움이 될 것이라고 생각했습니다.


1

이것은 분명히 클래스 경로 문제입니다. IDE 외부에서 프로그램을 실행할 때 클래스 경로가 약간 변경되어야한다는 점을 고려하십시오. IDE가 프로젝트의 루트 폴더에 상대적인 다른 JAR을로드하기 때문입니다. 반면 최종 JAR의 경우 일반적으로 그렇지 않습니다.

이러한 상황에서 내가 좋아하는 것은 JAR을 수동으로 빌드하는 것입니다. 최대 5 분이 걸리며 항상 문제가 해결됩니다. 나는 당신이 이것을 권장하지 않습니다. Maven을 사용하는 방법을 찾는 것이 그 목적입니다.


@SoboLAN JAR을 수동으로 빌드하는 것은 여기서 해결책이 아닙니다. 의도는 "manual"의 정반대 인 Maven을 사용하는 것입니다!
Duncan Jones

@DuncanJones 당신이 완전히 옳습니다. 나는 그가 그것을하기 위해 Maven을 사용하는 것이 좋습니다. 그러나 나는 그것에 대한 경험이 없으며 어떤 솔루션을 추천 해야할지 정확히 알지 못했습니다. 나는 이것을 반영하기 위해 내 대답을 편집했습니다.
Radu Murzea
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.