Як запустити клас у WAR із командного рядка?


77

У мене є клас Java, який має основний, і я раніше запускався як самостійний додаток із командного рядка, наприклад

java -jar myjar.jar params

Мені потрібно було перепакувати код, щоб він працював під apache, і весь мій код, включаючи клас точки входу зі старого jar, потрапив у файл WAR для зручності внесення на веб-сервер.

Однак я все ще хочу мати можливість запускати його з командного рядка, і код не змінився, і все там є, я просто не можу зрозуміти, як змусити його запуститися.

Ось що я спробував ...

Я припускав, що ВІЙНА була просто як баночка

java -jar mywar.war params

Це невдале твердження, що в маніфесті не визначено основного класу.

Я вручну додав маніфест до війни і спробував ще раз із тим самим ефектом.

Я помітив, що під час моєї війни у ​​мене була папка під назвою META-INF, що містить manifest.mf, тому я додав до неї рядок, що оголошує мій основний клас як до звичайного маніфесту ...

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

Це дало a 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, не те, що я думаю, що це має щось змінити.


1
Не пробували цього, але як щодо того, щоб додати запис "Клас-шлях" до маніфесту?
Дан

Чи є у вас причини для цього? Чому б вам не спробувати зберегти дві різні збірки - одну для Інтернету та одну як самостійну програму?
andrii

Ви намагалися помістити шлях до класу в manifest.mf, який мав WEB-INF / класи, і залишити Main-Class як mypackage.MyEntryPointClass?
Murali VP

спробував ідею classpath, не спрацював
Саймон

@Andrew, я міг би мати два різні пакети, це просто здається марнотратним, коли вміст одного є надмножином вмісту іншого
Саймон

Відповіді:


51

Подібно до того, що Річард Діч, але з дещо легшим для наслідування (працює також з пакетами)

Крок 1: Розгорніть файл війни.

jar -xvf MyWar.war

Крок 2: перейдіть до каталогу

cd WEB-INF

Крок 3: Запустіть ваш main з усіма залежностями

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

відповідь, яку я шукав,
AdamSkywalker

Чи можна це зробити без розпакування? Середовище, на якому я працюю, є більш жорстким, ніж це.
Шрідхар Сарнобат

4
Для змін Windows, таким : -> ;чином, наведена вище команда стає java -classpath "lib/*;classes/." my.packages.destination.FileToRunспеціально
зміненою

47

Ви можете робити те, що робить Хадсон (проект безперервної інтеграції). ви завантажуєте війну, яку можна розгорнути в tomcat або виконати за допомогою

java -jar hudson.war

(Оскільки він має вбудований движок Jetty, його запуск із командного рядка спричиняє запуск сервера.) У будь-якому випадку, переглядаючи маніфест Гудзона, я розумію, що вони кладуть Main-клас у кореневий каталог архіву. У вашому випадку ваш військовий макет повинен виглядати так:

під корінь:

  • mypackage / MyEntryPointClass.class
  • WEB-INF / lib
  • WEB-INF / заняття
  • META-INF / MANIFEST.MF

тоді як маніфест повинен містити такий рядок:

Main-Class: mypackage.MyEntryPointClass

зверніть увагу, що до mypackage / MyEntryPointClass.class можна отримати доступ лише з командного рядка, а класи в розділі WEB-INF / класи доступні лише з сервера додатків.

HTH


1
Не буду проти, тому що відповідь містить деяку корисну інформацію. Однак це не відповідає на вихідне запитання "... запустити як самостійний додаток із командного рядка ..."
Baruch Atta

10

Війна - це веб-додаток. Якщо ви хочете, щоб консоль / автономна програма повторно використовувала ті самі класи, що й у веб-програмі, розгляньте можливість упаковки спільних класів у банку, яку ви можете вставити WEB-INF/lib. Потім використовуйте цю банку з командного рядка. Таким чином ви отримуєте як консольний додаток, так і можете використовувати однакові класи у своїх сервлетах, не роблячи двох різних пакетів. Це, звичайно, вірно, коли війна вибухає.


Звичайно, але це не завжди можливо. Іноді у вас лише війна, і ви хотіли б швидко керувати основним класом.
vikingsteve

9

Щоб виконати SomeClass.main (String [] аргументи) з розгорнутого файлу війни:

Крок 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 && find. -ім'я '* .jar' | під час читання jarfile; робити, якщо jar tf "$ jarfile" | grep SomeOtherClass.class; потім луна "$ jarfile"; fi; зроблено

Примітка 2. Запишіть у стандартний вихід, щоб ви могли побачити, чи справді ваш основний файл працює через оператори друку на консолі. Це називається чорними дверима.

Примітка3: Викладений вище коментар Божидара Божанова видається правильним


1
це технічно правильно, тому я дав йому +1, але я вважаю, що це рішення не є гарною ідеєю. Це вимагає побудови шляху до класу вручну і дуже схильне до помилок.
JBCP

Погоджуючись з JBCP вище. Але я використовую Netbeans, і там ви можете запитати властивості вашого класу Java, і в ньому є запис Runtime Classpath, який збирає повний абсолютний шлях до класу (мій - 4000 символів :)) Цілком приємний спосіб перетворити деякі внутрішні елементи ваш веб-додаток у скриптові класи.
BxlSofty

6

Правила розміщення класів в архівному файлі полягають у тому, що розташування декларації пакета файлу та розташування файлу в архіві повинні збігатися. Оскільки ваш клас знаходиться в WEB-INF / класах, він вважає, що клас неприпустимий для запуску в поточному контексті.

Єдиний спосіб, як ти можеш зробити те, що ти просиш, - перепакувати війну так .class файл знаходився в mypackageкаталозі в кореневій частині архіву, а не в каталозі WEB-INF / класів. Однак якщо ви це зробите, ви більше не зможете отримати доступ до файлу з будь-якого з ваших веб-класів.

Якщо ви хочете повторно використовувати цей клас як у війну, так і за межами командного рядка Java, розгляньте можливість побудови виконуваного jar, який можна запустити з командного рядка, а потім помістіть цей jar в warкаталог WEB-INF / lib файлу.


6

Якщо ви використовуєте Maven, просто дотримуйтесь maven-war-pluginдокументації щодо " Як створити 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>

У вас буде 2 товари в target/папці:

  • Сам project.warпо собі
  • project-classes.jar, Який містить всі скомпільовані класи в банку

Тоді ви зможете виконати основний клас, використовуючи класичний метод: java -cp target/project-classes.jar 'com.mycompany.MainClass' param1 param2


5

У проекті Maven ви можете автоматично створювати jar за допомогою плагіна Maven War , встановивши archiveClassesзначення true. Приклад нижче.

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

run maven clean install
Shondeslitch

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

0

Ну, згідно з Вікіпедією , у файлі WAR класи, які завантажуються у шлях до класу, знаходяться в каталозі "/ WEB-INF / classes" та "/ WEB-INF / lib".

Ви можете спробувати просто помістити копію класів у кореневу файлову систему zip-файлу (а це те, що таке війна / jar). Я не впевнений, що це спрацює.

Ви завжди можете просто створити два окремі файли.


розміщення копій у громадському місці, безумовно, було б потворним
Божо,

-3

Неможливо запустити клас Java із файлу WAR. Файли WAR мають іншу структуру, ніж файли Jar.

Щоб знайти відповідні класи Java, експортуйте їх (найкращий спосіб використання ant), як Jar помістив у вашу бібліотеку веб-програми.

Тоді ви можете використовувати файл jar як звичайно для запуску програми Java. Цю ж банку також згадували у веб-програмі (якщо помістити цю банку в lib веб-програми)

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.