如何从命令行在WAR中运行类?

时间:2009-12-03 21:16:32

标签: java jar war

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

java -jar myjar.jar params

我需要重新打包代码才能在apache下运行,我的所有代码(包括旧jar中的入口点类)最终都在WAR文件中,以便轻松地进入Web服务器。

但是,我仍然希望能够从命令行运行它并且代码没有改变并且全部在那里,我只是无法弄清楚如何让它运行。

这是我试过的......

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

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)

我已经google了一下,但找不到任何能回答我问题的内容,而且我在这里读了几个略有不同的问题,所以我想我会发帖。

Java 1.5,不是我认为应该有所不同。

11 个答案:

答案 0 :(得分:31)

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

执行的战争
java -jar hudson.war

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

在root下:

  • mypackage / MyEntryPointClass.class
  • WEB-INF / lib
  • WEB-INF /类
  • META-INF / MANIFEST.MF

虽然清单应包含以下行:

Main-Class: mypackage.MyEntryPointClass

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

HTH

答案 1 :(得分:26)

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

第1步:打开War文件。

cd WEB-INF

第2步:进入目录

java -classpath "lib/*:classes/." my.packages.destination.FileToRun

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

web

答案 2 :(得分:10)

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

答案 3 :(得分:8)

从已部署的war文件执行SomeClass.main(String [] args):

步骤1:编写具有主方法方法的类SomeClass.java,即(public static void main(String [] args){...})

第2步:部署你的战争

第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&& 找 。 -name'* .jar'|读取jarfile;如果jar tf“$ jarfile”| grep SomeOtherClass.class;然后回显“$ jarfile”;网络连接;完成

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

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

答案 4 :(得分:6)

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

你可以做的唯一方法是重新打包战争,以便.class文件位于存档根目录中的mypackage目录而不是WEB-INF / classes目录。但是,如果您这样做,您将无法再从任何Web类访问该文件。

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

答案 5 :(得分:4)

Maven项目中,您可以通过将archiveClasses设置为true,使用Maven War plugin自动构建jar。示例如下。

<plugin>
       <groupId>org.apache.maven.plugins</groupId>
       <artifactId>maven-war-plugin</artifactId>
       <configuration>
        <archiveClasses>true</archiveClasses>
       </configuration>
</plugin>

答案 6 :(得分:2)

如果您使用的是Maven,请按照关于“How do I create a JAR containing the classes in my webapp?”的maven-war-plugin文档进行操作:将 <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本身
  • 包含jar中所有已编译类的project-classes.jar

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

答案 7 :(得分:1)

使用Spring Boot的最佳方法是:

1 /创建ServletInitializer扩展 SpringBootServletInitializer 类 。使用方法 configure 来运行您的应用程序类

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, ...)

答案 8 :(得分:0)

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

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

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

答案 9 :(得分:0)

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

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

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

答案 10 :(得分:-3)

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

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

然后你可以正常使用jar文件来运行java程序。在web应用程序中也引用了相同的jar(如果你把这个jar放在web应用程序库中)