提问人:Simon 提问时间:12/4/2009 更新时间:10/20/2023 访问量:262922
如何从命令行在 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 服务器。
但是,我仍然希望能够从命令行运行它,并且代码没有更改并且全部在那里,我只是不知道如何让它运行。
这是我尝试过的......
我以为 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)
我已经用谷歌搜索了一会儿,但找不到任何可以回答我的问题的东西,我在这里阅读了其他几个略有不同的问题,所以我想我会发帖。
Java 1.5,我不认为这有什么不同。
答:
在存档文件中查找类的规则是,文件的包声明的位置和文件在存档中的位置必须匹配。由于您的类位于 WEB-INF/classes 中,因此它认为该类在当前上下文中运行无效。
您可以按照要求执行任务的唯一方法是重新打包 war,以便文件位于存档根目录的目录中,而不是 WEB-INF/classes 目录中。但是,如果这样做,您将无法再从任何 Web 类访问该文件。.class
mypackage
如果你想在战争中和外部通过 java 命令行重用这个类,请考虑构建一个可以从命令行运行的可执行 jar,然后将该 jar 放在文件的 WEB-INF/lib 目录中。war
战争是一个网络应用程序。如果要让控制台/独立应用程序重用与 Web 应用程序相同的类,请考虑将共享类打包到 jar 中,可以将其放入 .然后从命令行使用该 jar。
因此,您可以获得两个控制台应用程序,并且可以在 servlet 中使用相同的类,而无需创建两个不同的包。
当然,当战争爆发时,情况确实如此。WEB-INF/lib
评论
好吧,根据维基百科,使用 WAR 文件,加载到类路径中的类位于“/WEB-INF/classes”和“/WEB-INF/lib”目录中。
您可以尝试简单地将类的副本放在 zip 文件的根文件系统上(这就是 war/jar 是什么)。我不确定这是否可行。
您始终可以只创建两个单独的文件。
评论
您可以执行 Hudson(持续集成项目)所做的工作。 您下载了一个可以在 Tomcat 中部署或使用
java -jar hudson.war
(因为它有一个嵌入式 Jetty 引擎,所以从命令行运行它会导致服务器启动。无论如何,通过查看 hudson 的清单,我了解到他们在存档的根目录中放置了一个 Main 类。在你的情况下,你的战争布局应该是这样的:
在根目录下:
- mypackage/MyEntryPointClass.class
- WEB-INF/库
- WEB-INF/类
- 元 INF/清单。分子式
而清单应包括以下行:
Main-Class: mypackage.MyEntryPointClass
请注意,mypackage/MyEntryPointClass.class 只能从命令行访问,而 WEB-INF/classes 下的类只能从应用程序服务器访问。
HTH型
评论
在 Maven 项目中,您可以使用 Maven War 插件自动构建 jar,方法是将 设置为 。示例如下。archiveClasses
true
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<configuration>
<archiveClasses>true</archiveClasses>
</configuration>
</plugin>
评论
要从已部署的 war 文件执行,请执行以下操作:SomeClass.main(String [] args)
- 编写具有 main 方法方法的类,即 (public static void main(String[] args) {...}
SomeClass.java
) - 部署 WAR
cd /usr/local/<yourprojectsname>/tomcat/webapps/projectName/WEB-INF
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:写入标准输出,以便您可以通过控制台的 print 语句查看您的主文件是否实际有效。这称为后门。
注3:Bozhidar Bozhanov的上述评论似乎是正确的
评论
无法从 WAR 文件运行 java 类。WAR 文件的结构与 Jar 文件不同。
要查找相关的 Java 类,请导出(首选使用 ant 的方式)它们,就像 Jar 将其放入 Web 应用程序库中一样。
然后,您可以像往常一样使用jar文件来运行java程序。Web 应用程序中也引用了相同的 jar(如果您将此 jar 放在 Web 应用程序库中)
类似于 Richard Detsch,但更容易遵循(也适用于软件包)
第 1 步:解压缩 War 文件。
jar -xvf MyWar.war
第 2 步:移动到目录中
cd WEB-INF
第 3 步:使用所有依赖项运行主数据库
java -classpath "lib/*:classes/." my.packages.destination.FileToRun
评论
: -> ;
java -classpath "lib/*;classes/." my.packages.destination.FileToRun
如果您使用的是 Maven,只需按照有关“如何创建包含 Web 应用程序中的类的 JAR”的文档进行操作:将 <attachClasses>true</attachClasses>
添加到插件的maven-war-plugin
<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>
文件夹中将有 2 个产品:target/
- 本身
project.war
- 在一个 jar 中包含所有已编译的类
project-classes.jar
然后,您将能够使用经典方法执行主类:java -cp target/project-classes.jar 'com.mycompany.MainClass' param1 param2
使用 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, ...)
作为替代选项,将 rest 服务包含在文件中,以通过 url 触发应用程序逻辑。将文件部署到所需的任何 Web/应用程序服务器上。war
war
然后,您可以通过任何基于命令行的 HTTP 客户端(如在 Linux 上)启动应用程序。curl
缺点:通常这些 HTTP 客户端在不同的操作系统上是不同的。这在很多情况下并不重要。您也可以在 Windows 上安装。curl
使用 docker 的解决方案:
docker run --rm -it -v ${PWD}:/usr/local/tomcat/webapps -p 8080:8080 tomcat
这是 Windows 语法 - 对于 Linux/Mac,请将 ${PWD} 替换为 $(pwd)。
.war 文件是一个 Java Servlet Web 应用程序归档文件,它应该在所谓的 servlet 容器中运行,这实际上意味着 Apache Tomcat。最简单的方法是简单地运行 Tomcat,我们可以使用 docker 和上述命令来完成。不幸的是,我没有运气运行我试图运行的(旧版)应用程序 - 我认为这是 Servlet-API 版本的不匹配。
评论