java项目打包(maven+原生)

打印 上一主题 下一主题

主题 663|帖子 663|积分 1991

一、maven打包

1.1 普通jar

java -jar maven项目打包提示.jar中没有主清单属性
  1.     <build>
  2.         <finalName>${project.artifactId}</finalName>
  3.         <plugins>
  4.             <plugin>
  5.                 <groupId>org.apache.maven.plugins</groupId>
  6.                 <artifactId>maven-jar-plugin</artifactId>
  7.                 <version>3.2.0</version>
  8.                 <configuration>
  9.                     <archive>
  10.                         <manifest>
  11.                             <addClasspath>true</addClasspath>
  12.                             <mainClass>com.leon.Main</mainClass>
  13.                         </manifest>
  14.                     </archive>
  15.                 </configuration>
  16.             </plugin>
  17.         </plugins>
  18.     </build>
  19.                         
  20. 原文链接:https://blog.csdn.net/whq12789/article/details/106568531
复制代码
1.2 有依赖的jar

How can I create an executable/runnable JAR with dependencies using Maven?

1. 一个jar

最高赞
  1. <build>
  2.   <plugins>
  3.     <plugin>
  4.       <artifactId>maven-assembly-plugin</artifactId>
  5.       <configuration>
  6.         <archive>
  7.           <manifest>
  8.             <mainClass>fully.qualified.MainClass</mainClass>
  9.           </manifest>
  10.         </archive>
  11.         <descriptorRefs>
  12.           <descriptorRef>jar-with-dependencies</descriptorRef>
  13.         </descriptorRefs>
  14.       </configuration>
  15.       <executions>
  16.         <execution>
  17.           <id>make-assembly</id>
  18.           <phase>package</phase>
  19.           <goals>
  20.             <goal>single</goal>
  21.           </goals>
  22.         </execution>
  23.       </executions>
  24.     </plugin>
  25.   </plugins>
  26. </build>
复制代码
2 把依赖放入其他目录

需要两个plugin结合使用
留意

  • outputDirectory,就是天生的可运行的jar的依赖的目录
  • maven-jar-plugin的classpathPrefix,作用是生产的可运行jar的MANIFEST.MF内里的Class-Path
  • 这个方法,并不消我手动copy lib到项目内里,maven会自己从仓库内里copy
  1. <plugin>
  2.     <groupId>org.apache.maven.plugins</groupId>
  3.     <artifactId>maven-dependency-plugin</artifactId>
  4.     <executions>
  5.         <execution>
  6.             <id>copy-dependencies</id>
  7.             <phase>prepare-package</phase>
  8.             <goals>
  9.                 <goal>copy-dependencies</goal>
  10.             </goals>
  11.             <configuration>
  12.                 <outputDirectory>${project.build.directory}/lib</outputDirectory>
  13.                 <overWriteReleases>false</overWriteReleases>
  14.                 <overWriteSnapshots>false</overWriteSnapshots>
  15.                 <overWriteIfNewer>true</overWriteIfNewer>
  16.             </configuration>
  17.         </execution>
  18.     </executions>
  19. </plugin>
  20. <plugin>
  21.     <groupId>org.apache.maven.plugins</groupId>
  22.     <artifactId>maven-jar-plugin</artifactId>
  23.     <configuration>
  24.         <archive>
  25.             <manifest>
  26.                 <addClasspath>true</addClasspath>
  27.                 <classpathPrefix>lib/</classpathPrefix>
  28.                 <mainClass>theMainClass</mainClass>
  29.             </manifest>
  30.         </archive>
  31.     </configuration>
  32. </plugin>
复制代码
二、java命令打包

0、代码目录结构

projectDir\
└——  src\com\leon\xxx.java....
└——  lib\xxx.jar
└——  META-INF\MANIFEST.MF
└——  target\classes

  • 4个目录的结构都不是死的,都可以改变,但是以上的结构比较符合一样平常的项目结构
  • lib下放三方依赖
  • META-INF,一样平常是hyphen而不是underline,别记错写错。MANIFEST.MF可以写成txt,只要在参数里指定就好
1、javac编译成classes
  1. javac -encoding UTF-8 -classpath .\lib\commons-lang3-3.7.jar -d .\classes src\com\leon\Main.java
复制代码
option参数阐明-encoding UTF-8java文件中文编码-d .\target\classes将打包的class文件输出到指定目录-classpath .\lib\xxx.jar简写-cp
指定依赖的第三方jar
目录以【.\】开头或者省略【.\】似乎没关系,并不会导致固定死目录(包含本地目录好比D盘)source file参数src\......java应该能简写成目录2、验证classes的精确性
  1. java -cp target\classes;lib\commons-lang3-3.7.jar com.leon.Main abc
复制代码

  • java运行class,首先需要指定自定义的classes的位置,-cp target\classes
  • java命令的class参数要写【package的路径+class名字】,com.leon.Main
    如下
    这个路径,没有包含目录src,src仅仅是一个目录,它不在java文件的package命令内里
  1. package com.leon;
  2.         public class Main {
  3.         }
复制代码

  • 留意 -cp命令没有以【.\】开头
可能的错误


  • java.lang.NoClassDefFoundError: xxx第三方引用
    -cp要指定第三方包,lib\commons-lang3-3.7.jar,多个第三方jar以semicolon分割
3、jar打包

95%内容参考自oracle的官方文档,Packaging Programs in JAR Files
jar的命令格式以jdk的资助讲解,如下
  1. jar {ctxui}[vfmn0PMe] [jar-file] [manifest-file] [entry-point] [-C dir] files ...
复制代码
jar命令是打包,命令很类似ta
{}参数(只能选一个)

参数阐明c打包成成为jar基本不消x解压jart显示jar中的内容u更新jarx或i没试过[]参数

重要参数阐明m指定MANIFEST文件f打包的jar的名字,这个参数不传会output will go to a stdout(什么人或者为啥要go to stdout?)e可以指定class的入口。C去掉指定的目录层级。看实例。不重要参数v打包时,显示详细的信息0不压缩。不压缩的jar据oracle网站说运行更快,压缩体积更小Mjar内不要MANIFEST,为啥不要?留意:

m与f参数的顺序与[jar-file] [manifest-file]顺序是必须对应的。
精确jar命令
  1. jar cvfm Main.jar META-INF\MANIFEST.MF com\leon\Main.class -C target\classes .
复制代码
MANIFEST.MF


  • 自定义的MF文件,每行都是键值对的形式,以colon分割
    These lines show that a manifest's entries take the form of "header: value" pairs.
  • 自定义的MF文件可以写成txt,也可以.MF,文件名也可以任意,但是需要通过【m 参数+[manifest-file]】
  • 自定义的MF文件末了一行不会被写入到jar包中的MANIFEST.MF中,以是自定义的MF文件末了一行必须是空行
    来源:
    Modifying a Manifest FileWarning: The text file from which you are creating the manifest must end with a new line or carriage return. The last line will not be parsed properly if it does not end with a new line or carriage return.
  • MF文件需要以UTF-8编码
Main-Class


Main-Class: com.leon.Main
Class-Path

格式 Class-Path: jar1-name jar2-name directory-name/jar3-name

Class-Path: lib\commons-lang3-3.7.jar

  • 在某个答复上看,不能以\开头(linux是/)。没验证
  • jar包之间以空格分割
  • 我看别人打包有以【.】开头的,如下,是为了把当前文件夹也包括进去?
  1. Class-Path: . xxx1.jar xxx2.jar
复制代码
jar打包精确之后,java -jar却报错“找不到或无法加载主类 xxx”

jar包的精确结构

xxx.jar
└——  com\leon\xxx.java....
└——  META-INF\MANIFEST.MF
如果出现以上错误,很可能是jar包中目录错误,如下
xxx.jar
└——  target\classes\com\leon\xxx.java....
└——  META-INF\MANIFEST.MF
解决办法一 切换目录法

cd进入classes中package目录的上一层,以示例来说,就是target\classes
然后,jar命令打包
然后,把jar放入到符合的位置运行java -jar(主要是与第三方依赖的相对位置要放置准确)
解决办法二 -C参数(推荐)
  1. jar cvfm Main.jar META-INF\MANIFEST.MF com\leon\Main.class -C target\classes .
复制代码
留意

  • com\leon\Main.class是位于target\classes中的(这里与src目录无关)
  • -C参数末了有一个【空格+.
    参考,could not find or load main class with a jar file,中作者Log2的答复,他表明的非常清楚,两种解决办法都有提到。
可能的错误


  • 提示 xxx.jar中没有主清单属性,打开jar
    以下命令会在jar中天生默认MF,位置在xxx.jar\META-INF\MANIFEST.MF,但是内里没有Main-Class
    需要用-m或-e参数指定
    1. jar -cvf Main.jar .\classes\com\leon\Main.class
    复制代码
  • 有m选项,也自定义了MANIFEST.MF,但是jar中的MANIFEST.MF还是没有Main-Class
    看看是不是MF文件只写了一行,没有在后面跟一个空行
  • 报错 java.io.IOException: invalid header field
    前面oracle文档说了,"header: value" pairs,以是,这个报错与MF格式有关

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
回复

使用道具 举报

0 个回复

正序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

南七星之家

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表