繁体   English   中英

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

[英]How do I run a class in a WAR from the command line?

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

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,不是我认为应该有什么不同。

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

第 1 步:解开 War 文件。

jar -xvf MyWar.war

第二步:进入目录

cd WEB-INF

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

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

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

java -jar hudson.war

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

在根下:

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

而清单应包括以下行:

Main-Class: mypackage.MyEntryPointClass

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

HTH

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

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

  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:写入标准输出,以便您可以通过控制台的打印语句查看您的主要内容是否确实有效。 这称为后门。

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

如果您使用的是 Maven,只需遵循maven-war-plugin文档中关于“ 如何在我的 web 应用程序中创建包含类的 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

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

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

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

Maven项目中,您可以通过将archiveClasses设置为true来使用Maven War 插件自动构建 jar。 下面举例。

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

如果您使用 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, ...)

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

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

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

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

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

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

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

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

然后就可以正常使用jar文件运行java程序了。 在 web app 中也引用了同一个 jar(如果你把这个 jar 放在 web app lib 中)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM