78

我有一个具有 main 的 Java 类,我曾经从命令行作为独立应用程序运行,例如

java -jar myjar.jar params

我需要重新打包代码以在 apache 下运行,并且我的所有代码,包括旧 jar 中的入口点类,最终都保存在一个 WAR 文件中,以便于部署到 Web 服务器中。

但是,我仍然希望能够从命令行运行它并且代码没有改变并且都在那里,我只是不知道如何让它运行。

这是我尝试过的...

我认为战争就像一个罐子,所以

java -jar mywar.war params

未能说明清单中没有定义主类。

我手动将清单添加到战争中并再次尝试,效果相同。

我注意到在我的战争中,我有一个名为 META-INF 的文件夹,其中包含一个 manifest.mf,所以我在其中添加了一行来声明我的主类,就像我对普通清单一样......

Manifest-Version: 1.0
Main-Class: mypackage.MyEntryPointClass

这给出了一个noClassDefFoundError mypackage.MyEntryPointClass,这是一种进步。这让我相信这只是一个路径问题,所以我尝试了

Manifest-Version: 1.0
Main-Class: WEB-INF.classes.mypackage.MyEntryPointClass

我现在得到同样的错误,但是有一个堆栈跟踪......

Exception in thread "main" java.lang.NoClassDefFoundError: WEB-INF/classes/mypackage/MyEntryPointClass (wrong name: mypackage/MyEntryPointClass)
        at java.lang.ClassLoader.defineClass1(Native Method)
        at java.lang.ClassLoader.defineClass(Unknown Source)
        at java.security.SecureClassLoader.defineClass(Unknown Source)
        at java.net.URLClassLoader.defineClass(Unknown Source)
        at java.net.URLClassLoader.access$100(Unknown Source)
        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)
        at java.lang.ClassLoader.loadClassInternal(Unknown Source)

我已经用谷歌搜索了一下,但找不到任何可以回答我的问题的东西,我在这里阅读了其他几个略有不同的问题,所以我想我会发布。

Java 1.5,并不是我认为应该有任何区别。

4

11 回答 11

59

类似于 Richard Detsch,但更容易理解(也适用于包)

第 1 步:解开 War 文件。

jar -xvf MyWar.war

第二步:进入目录

cd WEB-INF

第 3 步:运行所有依赖项的 main

java -classpath "lib/*:classes/." my.packages.destination.FileToRun
于 2015-10-21T18:20:25.000 回答
49

您可以做Hudson(持续集成项目)所做的事情。您下载可以部署在 tomcat 中或使用执行的战争

java -jar hudson.war

(因为它有一个嵌入式 Jetty 引擎,从命令行运行它会导致服务器启动。)无论如何,通过查看 hudson 的清单,我了解到他们将 Main 类放在存档的根目录中。在您的情况下,您的战争布局应如下所示:

在根下:

  • mypackage/MyEntryPointClass.class
  • WEB-INF/库
  • WEB-INF/类
  • 元信息/清单.MF

而清单应包括以下行:

Main-Class: mypackage.MyEntryPointClass

请注意 mypackage/MyEntryPointClass.class 只能从命令行访问,WEB-INF/classes 下的类只能从应用服务器访问。

高温高压

于 2010-09-27T14:33:31.603 回答
10

战争是一个网络应用程序。如果您想让控制台/独立应用程序重用与您的 webapp 相同的类,请考虑将您的共享类打包在一个 jar 中,您可以将其放入WEB-INF/lib. 然后从命令行使用该 jar。因此,您获得了两个控制台应用程序,并且可以在您的 servlet 中使用相同的类,而无需制作两个不同的包。当然,战争爆发时也是如此。

于 2009-12-03T21:25:00.823 回答
9

要从SomeClass.main(String [] args)已部署的 war 文件执行,请执行以下操作:

  1. 编写SomeClass.java具有主要方法方法的类,即(public static void main(String[] args) {...}
  2. 部署你的 WAR
  3. cd /usr/local/<yourprojectsname>/tomcat/webapps/projectName/WEB-INF
  4. java -cp "lib/jar1.jar:lib/jar2.jar: ... :lib/jarn.jar" com.mypackage.SomeClass arg1 arg2 ... arg3

注意1:查看课程SomeOtherClass.class是否正在/usr/tomcat/webapps/<projectName>/WEB-INF/lib运行:

cd /usr/tomcat/webapps/projectName/WEB-INF/lib && 
find . -name '*.jar' | while read jarfile; do if jar tf "$jarfile" | grep SomeOtherClass.class; then echo "$jarfile"; fi; done 

注意 2:写入标准输出,以便您可以通过打印语句到控制台查看您的 main 是否实际工作。这称为后门。

注3:Bozhidar Bozhanov 的上述评论似乎是正确的

于 2012-04-05T00:52:28.370 回答
9

如果您使用的是 Maven,只需按照maven-war-plugin有关“如何创建包含我的 webapp 中的类的 JAR? ”的文档:添加<attachClasses>true</attachClasses><configuration>插件中:

<project>
  ...
  <artifactId>mywebapp</artifactId>
  <version>1.0-SNAPSHOT</version>
  ...
  <build>
    <plugins>
      <plugin>
    <artifactId>maven-war-plugin</artifactId>
    <version>2.6</version>
    <configuration>
      <attachClasses>true</attachClasses>
    </configuration>
      </plugin>
    </plugins>
  </build>
  ...
</project>

您将在target/文件夹中有 2 个产品:

  • project.war本身_
  • 其中project-classes.jar包含 jar 中的所有已编译类

然后您将能够使用经典方法执行主类:java -cp target/project-classes.jar 'com.mycompany.MainClass' param1 param2

于 2016-02-16T09:31:48.160 回答
6

在档案文件中定位类的规则是文件的包声明的位置和档案中文件的位置必须匹配。由于您的类位于 WEB-INF/classes 中,因此它认为该类在当前上下文中运行无效。

您可以按照您的要求进行操作的唯一方法是重新打包战争,以便该.class文件位于mypackage存档根目录中的目录中,而不是 WEB-INF/classes 目录中。但是,如果您这样做,您将无法再从您的任何网络课程中访问该文件。

如果您想从 java 命令行在战争和外部重用这个类,请考虑构建一个可以从命令行运行的可执行 jar,然后将该 jar 放在war文件的 WEB-INF/lib 目录中。

于 2009-12-03T21:24:48.640 回答
5

Maven项目中,您可以使用Maven War 插件自动构建 jar,方法是设置archiveClassestrue. 下面的例子。

<plugin>
       <groupId>org.apache.maven.plugins</groupId>
       <artifactId>maven-war-plugin</artifactId>
       <configuration>
        <archiveClasses>true</archiveClasses>
       </configuration>
</plugin>
于 2011-04-20T11:47:06.480 回答
2

如果您使用 Spring Boot,最好的方法是:

1/ 创建一个 ServletInitializer 扩展SpringBootServletInitializer类。使用方法配置运行您的应用程序类

2/始终生成一个 Maven 安装WAR文件

3/ 有了这个神器,你甚至可以:

    . start application from war file with java -jar file.war

    . put your war file in your favorite Web App server (like tomcat, ...)
于 2020-03-25T10:50:20.113 回答
0

好吧,根据Wikipedia的说法,使用 WAR 文件,加载到类路径中的类位于“/WEB-INF/classes”和“/WEB-INF/lib”目录中。

您可以尝试简单地将类的副本放在 zip 文件的根文件系统上(这就是 war/jar)。我不确定这是否可行。

您始终可以只创建两个单独的文件。

于 2009-12-03T21:26:28.230 回答
0

作为替代选项,war将其余服务包含到文件中,以通过 url 触发应用程序逻辑。将文件部署war到您想要的任何 Web/应用程序服务器上。

然后,您可以通过任何基于命令行的 HTTP 客户端(例如curl在 Linux 上)启动您的应用程序。

缺点:通常这些 HTTP 客户端在不同的操作系统上是不同的。这对很多情况来说并不重要。您也可以curl在 Windows 上安装。

于 2021-08-11T07:23:39.977 回答
-3

无法从 WAR 文件运行 java 类。WAR 文件与 Jar 文件具有不同的结构。

要查找相关的 java 类,请将它们导出(使用 ant 的首选方式)作为 Jar 放入您的 Web 应用程序库中。

然后就可以正常使用jar文件来运行java程序了。Web 应用程序中也引用了相同的 jar(如果您将此 jar 放在 Web 应用程序库中)

于 2015-06-08T09:57:11.007 回答