簡體   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