Làm cách nào để chạy một lớp trong WAR từ dòng lệnh?


77

Tôi có một lớp Java có một chính và tôi đã từng chạy như một ứng dụng độc lập từ dòng lệnh, ví dụ:

java -jar myjar.jar params

Tôi cần đóng gói lại mã để chạy trong apache và tất cả mã của tôi, bao gồm cả lớp điểm nhập từ jar cũ, đã kết thúc trong một tệp WAR để dễ dàng chuyển vào máy chủ web.

Tuy nhiên, tôi vẫn muốn có thể chạy nó từ dòng lệnh và mã không thay đổi và tất cả đều ở đó, tôi chỉ không thể tìm ra cách làm cho nó chạy.

Đây là những gì tôi đã thử ...

Tôi cho rằng CHIẾN TRANH chỉ giống như một cái lọ, vì vậy

java -jar mywar.war params

Điều đó không thành công khi nói rằng không có lớp chính được xác định trong tệp kê khai.

Tôi đã thêm một bản kê khai vào cuộc chiến theo cách thủ công và thử lại, với hiệu ứng tương tự.

Tôi nhận thấy rằng trong cuộc chiến của mình, tôi có một thư mục có tên META-INF chứa tệp kê khai.mf, vì vậy tôi đã thêm một dòng vào phần khai báo lớp chính của mình như cách tôi làm với tệp kê khai bình thường ...

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

Điều này đã cho một noClassDefFoundError mypackage.MyEntryPointClass, đó là tiến bộ của một loại. Điều đó khiến tôi tin rằng đó chỉ là vấn đề về đường dẫn, vì vậy tôi đã thử

Manifest-Version: 1.0
Main-Class: WEB-INF.classes.mypackage.MyEntryPointClass

Bây giờ tôi gặp lỗi tương tự, nhưng với dấu vết ngăn xếp ...

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)

Tôi đã tìm kiếm trên Google một chút nhưng không thể tìm thấy bất kỳ điều gì trả lời cho câu hỏi của tôi và tôi đã đọc một số câu hỏi khác ở đây hơi khác, vì vậy tôi nghĩ tôi sẽ đăng.

Java 1.5, tôi không nghĩ rằng điều đó sẽ tạo ra bất kỳ sự khác biệt nào.


1
Bạn chưa thử điều này, nhưng còn việc thêm mục nhập 'Đường dẫn lớp' vào tệp kê khai thì sao?
Dan

Bạn có bất kỳ lý do cho điều này? Tại sao bạn không cố gắng giữ hai bản lắp ráp khác nhau - một cho web và một dưới dạng ứng dụng độc lập?
andrii

Bạn đã thử đặt một classpath trong tệp kê khai.mf có WEB-INF / các lớp và để Lớp chính dưới dạng mypackage.MyEntryPointClass chưa?
VP Murali

thử các ý tưởng classpath, không làm việc
Simon

@ Andrew, tôi có thể có hai gói khác nhau, nó chỉ có vẻ lãng phí khi nội dung của một là một superset của nội dung của người khác
Simon

Câu trả lời:


51

Tương tự như những gì Richard Detsch nhưng dễ làm theo hơn một chút (cũng hoạt động với các gói)

Bước 1: Giải nén tệp War.

jar -xvf MyWar.war

Bước 2: Chuyển vào thư mục

cd WEB-INF

Bước 3: Chạy chính của bạn với tất cả các phụ thuộc

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

câu trả lời tôi đang tìm kiếm
AdamSkywalker

Điều này có thể được thực hiện mà không cần giải nén? Môi trường tôi điều hành công việc của mình bị hạn chế chặt chẽ hơn thế này.
Sridhar Sarnobat

4
Đối với cửa sổ thay đổi : -> ;vì vậy các lệnh trên trở nên java -classpath "lib/*;classes/." my.packages.destination.FileToRunđặc biệt thay đổi
ksrb

46

Bạn có thể làm những gì Hudson (dự án tích hợp liên tục) làm. bạn tải xuống một cuộc chiến có thể được triển khai trong tomcat hoặc để thực thi bằng cách sử dụng

java -jar hudson.war

(Bởi vì nó có một công cụ Jetty được nhúng, việc chạy nó từ dòng lệnh sẽ khiến một máy chủ được khởi chạy.) Dù sao thì bằng cách nhìn vào bảng kê khai của hudson, tôi hiểu rằng họ đã đặt một lớp Chính trong thư mục gốc cho kho lưu trữ. Trong trường hợp của bạn, bố cục chiến tranh của bạn sẽ giống như sau:

dưới gốc:

  • mypackage / MyEntryPointClass.class
  • WEB-INF / lib
  • WEB-INF / lớp học
  • META-INF / MANIFEST.MF

trong khi tệp kê khai phải bao gồm dòng sau:

Main-Class: mypackage.MyEntryPointClass

hãy lưu ý rằng mypackage / MyEntryPointClass.class chỉ có thể truy cập được từ dòng lệnh và các lớp trong WEB-INF / lớp chỉ có thể truy cập từ máy chủ ứng dụng.

HTH


1
Sẽ không phản đối vì câu trả lời chứa một số thông tin tốt. Tuy nhiên, nó không trả lời câu hỏi ban đầu "... chạy như một ứng dụng độc lập từ dòng lệnh ..."
Baruch Atta

10

Chiến tranh là một ứng dụng web. Nếu bạn muốn có một bảng điều khiển / ứng dụng độc lập sử dụng lại các lớp giống như ứng dụng web của bạn, hãy cân nhắc đóng gói các lớp được chia sẻ của bạn trong một cái lọ mà bạn có thể đưa vào đó WEB-INF/lib. Sau đó sử dụng jar đó từ dòng lệnh. Vì vậy, bạn nhận được cả ứng dụng bảng điều khiển của mình và bạn có thể sử dụng các lớp giống nhau trong các servlet của mình mà không cần tạo hai gói khác nhau. Tất nhiên, điều này đúng khi chiến tranh bùng nổ.


Chắc chắn nhưng điều đó không phải lúc nào cũng có thể. Đôi khi bạn chỉ có một cuộc chiến và muốn chạy lớp chính một cách nhanh chóng.
vikingsteve

9

Để thực thi SomeClass.main (String [] args) từ tệp chiến tranh đã triển khai, hãy làm:

Bước 1: Viết lớp SomeClass.java có phương thức phương thức main tức là (public static void main (String [] args) {...})

Bước 2: Triển khai WAR của bạn

Bước 3: cd / usr / local / yourprojectsname / tomcat / webapps / projectName / WEB-INF

Bước 4: java -cp "lib / jar1.jar: lib / jar2.jar: ...: lib / jarn.jar" com.mypackage.SomeClass arg1 arg2 ... arg3

Lưu ý1: (để xem lớp SomeOtherClass.class có trong / usr / tomcat / webapps / projectName / WEB-INF / lib hay không)

run -> cd / usr / tomcat / webapps / projectName / WEB-INF / lib && find. -tên '* .jar' | trong khi đọc jarfile; làm nếu jar tf "$ jarfile" | grep SomeOtherClass.class; sau đó echo "$ jarfile"; fi; làm xong

Lưu ý 2: Viết theo tiêu chuẩn để bạn có thể xem liệu main của bạn có thực sự hoạt động hay không thông qua các câu lệnh in ra bảng điều khiển. Đây được gọi là cửa sau.

Lưu ý 3: Nhận xét ở trên của Bozhidar Bozhanov có vẻ đúng


1
điều này đúng về mặt kỹ thuật, vì vậy tôi đã cho nó +1, nhưng tôi không nghĩ giải pháp này là một ý tưởng hay. Nó yêu cầu xây dựng một classpath theo cách thủ công và rất dễ xảy ra lỗi.
JBCP

Đồng ý với JBCP ở trên. Nhưng tôi đang sử dụng Netbeans và trong đó bạn có thể yêu cầu các thuộc tính của lớp Java của mình và nó có một mục Runtime Classpath tập hợp đầy đủ classpath tuyệt đối (của tôi là 4000 ký tự :)) Khá là một cách hay để biến một số nội dung của ứng dụng web của bạn thành các lớp có thể tập lệnh.
BxlSofty

6

Quy tắc định vị các lớp trong tệp lưu trữ là vị trí của khai báo gói của tệp và vị trí của tệp trong tệp lưu trữ phải khớp với nhau. Vì lớp của bạn nằm trong WEB-INF / lớp, nó cho rằng lớp không hợp lệ để chạy trong ngữ cảnh hiện tại.

Cách duy nhất bạn có thể làm những gì bạn đang yêu cầu là đóng gói lại cuộc chiến để .classtệp nằm trong mypackagethư mục trong thư mục gốc của kho lưu trữ thay vì thư mục WEB-INF / lớp. Tuy nhiên, nếu bạn làm điều đó, bạn sẽ không thể truy cập tệp từ bất kỳ lớp web nào của mình nữa.

Nếu bạn muốn sử dụng lại lớp này trong cả chiến tranh và bên ngoài từ dòng lệnh java, hãy xem xét việc xây dựng một jar thực thi mà bạn có thể chạy từ dòng lệnh, sau đó đặt jar đó vào warthư mục WEB-INF / lib của tệp.


6

Nếu bạn đang sử dụng Maven, chỉ cần làm theo maven-war-plugintài liệu về " Làm cách nào để tạo JAR chứa các lớp trong ứng dụng web của tôi? ": Thêm <attachClasses>true</attachClasses>vào <configuration>plugin của plugin:

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

Bạn sẽ có 2 sản phẩm trong target/thư mục:

  • Chính project.war
  • Trong project-classes.jarđó chứa tất cả các lớp được biên dịch trong một jar

Sau đó, bạn sẽ có thể thực thi một lớp chính bằng phương thức cổ điển: java -cp target/project-classes.jar 'com.mycompany.MainClass' param1 param2


5

Trong dự án Maven , Bạn có thể xây dựng jar tự động bằng cách sử dụng plugin Maven War bằng cách đặt archiveClassesthành true. Ví dụ bên dưới.

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

chạy bản cài đặt sạch maven
Shondeslitch

1

cách tốt nhất nếu bạn sử dụng Spring Boot là:

1 / Tạo ServletInitializer mở rộng Lớp SpringBootServletInitializer . Với cấu hình phương thức chạy Lớp ứng dụng của bạn

2 / Tạo luôn một tệp WAR cài đặt maven

3 / Với đồ tạo tác này, bạn thậm chí có thể:

    . start application from war file with java -jar file.war

    . put your war file in your favorite Web App server (like tomcat, ...)

0

Theo Wikipedia , với tệp WAR, các lớp được tải vào classpath nằm trong thư mục "/ WEB-INF / class" và "/ WEB-INF / lib".

Bạn có thể thử chỉ cần đặt một bản sao của các lớp vào hệ thống tệp gốc của tệp zip (đó là war / jar). Tôi không chắc liệu điều đó có hiệu quả hay không.

Bạn luôn có thể tạo hai tệp riêng biệt.


đặt bản tại một địa điểm công cộng deffinitely sẽ xấu xí
Bozho

-3

Không thể chạy lớp java từ tệp WAR. Tệp WAR có cấu trúc khác với tệp Jar.

Để tìm các lớp java liên quan, hãy xuất (cách ưa thích để sử dụng kiến) chúng dưới dạng Jar đưa nó vào lib ứng dụng web của bạn.

Sau đó, bạn có thể sử dụng tệp jar như bình thường để chạy chương trình java. Lọ tương tự cũng được giới thiệu trong ứng dụng web (nếu bạn đặt lọ này trong lib ứng dụng web)

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.