- Sử dụng maven-shade-plugin ======================
(1) Thêm plugin sau vào file pom.xml của dự án:
<build>
<plugins>
<!-- Maven Shade Plugin -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.2.0</version>
<configuration>
<createDependencyReducedPom>true</createDependencyReducedPom>
</configuration>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<transformers>
<transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
<!-- Tên đầy đủ của lớp chính -->
<mainClass>com.healchow.consumer.Main</mainClass>
</transformer>
</transformers>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
(2) Sử dụng lệnh package của Maven để đóng gói dự án;
(3) Sau khi đóng gói xong, bạn sẽ thấy file JAR được tạo trong thư mục target của dự án;
(4) Nếu không có lỗi, bạn có thể chạy file JAR này bằng lệnh java -jar xxxx.jar.
Lưu ý: Phương pháp này được thực hiện trên hệ điều hành Mac OS trong IDE, trong thư mục jar/META-INF/ đôi khi sẽ xuất hiện các file như:
ECLIPSEF.SF ECLIPSE.RSA, và khi chạy lệnh java -jar xxx.jar, sẽ ném ra lỗi sau:
Error: A JNI error has occurred, please check your installation and try again
Exception in thread "main" java.lang.SecurityException: Invalid signature file digest for Manifest main attributes
at sun.security.util.SignatureFileVerifier.processImpl(SignatureFileVerifier.java:330)
at sun.security.util.SignatureFileVerifier.process(SignatureFileVerifier.java:263)
at java.util.jar.JarVerifier.processEntry(JarVerifier.java:318)
at java.util.jar.JarVerifier.update(JarVerifier.java:230)
at java.util.jar.JarFile.initializeVerifier(JarFile.java:383)
at java.util.jar.JarFile.getInputStream(JarFile.java:450)
at sun.misc.URLClassPath$JarLoader$2.getInputStream(URLClassPath.java:977)
at sun.misc.Resource.cachedInputStream(Resource.java:77)
at sun.misc.Resource.getByteBuffer(Resource.java:160)
at java.net.URLClassLoader.defineClass(URLClassLoader.java:454)
at java.net.URLClassLoader.access$100(URLClassLoader.java:73)
at java.net.URLClassLoader$1.run(URLClassLoader.java:368)
at java.net.URLClassLoader$1.run(URLClassLoader.java:362)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(URLClassLoader.java:361)
at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:335)
at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
at sun.launcher.LauncherHelper.checkAndLoadMain(LauncherHelper.java:495)
Cách giải quyết: Xóa thủ công các file META-INF/*.RSA META-INF/*.DSA META-INF/*.SF trong file JAR, sau đó sẽ có thể chạy được.
- Khuyến nghị: Sử dụng maven-assembly-plugin =============================
(1) Thêm plugin sau vào file pom.xml của dự án:
<build>
<plugins>
<!-- Maven Assembly Plugin -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<version>2.4.1</version>
<configuration>
<!-- lấy tất cả các phụ thuộc của dự án -->
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
<!-- MainClass trong mainfest tạo một jar có thể thực thi -->
<archive>
<manifest>
<mainClass>com.healchow.consumer.Main</mainClass>
</manifest>
</archive>
</configuration>
<executions>
<!-- cấu hình trình thực thi -->
<execution>
<id>make-assembly</id>
<!-- gắn vào vòng đời của lệnh package -->
<phase>package</phase>
<goals>
<!-- chỉ chạy một lần -->
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
(2) Sử dụng lệnh package của Maven để đóng gói dự án;
(3) Sau khi đóng gói xong, bạn sẽ thấy file JAR được tạo trong thư mục target của dự án, trong đó xxx-jar-with-dependencies.jar là file JAR chứa các thư viện phụ thuộc, file kia không chứa các thư viện phụ thuộc;
(4) Sử dụng lệnh java -jar xxxx.jar để chạy file JAR này.
- Mở rộng: Cài đặt file JAR cục bộ vào kho Maven ========================
Lệnh như sau:
mvn install:install-file -Dfile=base-util-1.0.RELEASE.jar -DgroupId=com.healchow -DartifactId=base-util -Dversion=1.0.RELEASE -Dpackaging=jar
Các lệnh khác, tham khảo bài viết này: Các lệnh thường dùng của Maven.
- Mở rộng: Tạo file JAR thủ công ==============
Điểm mấu chốt để tạo một file JAR có thể thực thi là: làm cho lệnh java -jar biết phương thức chính trong file JAR thuộc lớp nào - cần cấu hình tên đầy đủ của lớp chính.
Các bước như sau:
(1) Đóng gói dự án đã chỉ định:
Vào thư mục gốc của dự án, lấy hệ điều hành Linux làm ví dụ:
Tên dự án là
java-test, thư mục chứa nó là/data/project/java-test;Tên đầy đủ của lớp chứa phương thức main là
com.healchow.test.Main:
# Vào thư mục gốc của dự án:
cd /data/project
# Chạy lệnh đóng gói:
jar cvfe test.jar java-test.com.healchow.test.Main java-test
Giải thích lệnh trên: Đóng gói tất cả các file trong thư mục java-test vào test.jar, và chỉ định tên đầy đủ của lớp chính, ở đây cần chỉ định thư mục chứa lớp chính.
Về cách sử dụng khác của lệnh
jar, tham khảo như sau:# Cách dùng: jar {ctxui}[vfmn0PMe] [jar-file] [manifest-file] [entry-point] [-C dir] files ... # Tùy chọn: -c Tạo mới một file nén -t Liệt kê các thư mục trong file nén -x Trích xuất các (hoặc tất cả) file đã chỉ định từ file nén -u Cập nhật file nén hiện có -v Tạo đầu ra chi tiết trên đầu ra tiêu chuẩn -f Chỉ định tên file nén -m Bao gồm thông tin bản kê khai từ file bản kê khai đã chỉ định -n Sau khi tạo file nén mới, thực hiện chuẩn hóa Pack200 -e Chỉ định điểm vào ứng dụng cho ứng dụng độc lập được đóng gói vào file jar có thể thực thi -0 Chỉ lưu trữ; không sử dụng bất kỳ nén ZIP nào -P Giữ lại các thành phần '/' (đường dẫn tuyệt đối) và ".." (thư mục cha) trong tên file -M Không tạo file bản kê khai cho các mục -i Tạo thông tin chỉ mục cho file jar đã chỉ định -C Thay đổi thành thư mục đã chỉ định và bao gồm các file sau # Nếu bất kỳ file nào là thư mục, nó sẽ được xử lý đệ quy. # Thứ tự chỉ định tên file bản kê khai, tên file nén và tên điểm vào phải giống với thứ tự chỉ định các dấu 'm', 'f' và 'e'. Ví dụ 1: Đóng gói hai file lớp vào một file nén có tên classes.jar: jar cvf classes.jar Foo.class Bar.class Ví dụ 2: Sử dụng file bản kê khai hiện có 'mymanifest' và đóng gói tất cả các file trong thư mục foo/ vào 'classes.jar': jar cvfm classes.jar mymanifest -C foo/ .
(2) Chạy file JAR:
Mở file JAR được tạo ở bước trước bằng phần mềm giải nén, kiểm tra file META-INF/MANIFEST.MF, nếu nó có Main-Class: com.healchow.test.Main, nghĩa là đóng gói thành công.
# Trong thư mục hiện tại, chạy file JAR:
java -jar test.jar
- Mở rộng: Một số cách chạy file JAR trên Linux =======================
5.1. Cách chặn
java -jar xxx.jar
Đặc điểm: Cửa sổ phiên bản terminal hiện tại bị chặn, có thể nhấn CTRL + C để ngắt chương trình, hoặc đóng cửa sổ phiên bản - lúc này chương trình JAR sẽ kết thúc.
5.2. Cách chạy nền
# Chạy nền thông qua ký tự "&":
java -jar xxx.jar &
Đặc điểm: Cửa sổ phiên bản terminal hiện tại không bị chặn, nhưng nếu đóng cửa sổ hiện tại, chương trình sẽ kết thúc.
5.3. Cách chạy nền liên tục
# Chạy nền thông qua lệnh "nohup":
nohup java -jar xxx.jar &
Lệnh nohup là lệnh chạy không ngắt kết nối.
Đặc điểm: Khi người dùng thoát hoặc đóng terminal, việc chạy chương trình không bị ảnh hưởng.
Lưu ý: Khi chạy tác vụ bằng lệnh nohup, theo mặc định, tất cả đầu ra của tác vụ này sẽ được chuyển hướng đến file nohup.out, trừ khi chỉ định file đầu ra khác. Cách chỉ định file đầu ra là:
# Chuyển hướng đầu ra đến file xxx.log:
nohup java -jar xxx.jar > xxx.log &
Ký tự > là ký tự chuyển hướng, thực hiện: chuyển hướng tất cả thông tin đầu ra của lệnh trước nó vào file sau, thay vì hiển thị trên màn hình.
5.4. Các lệnh mở rộng khác
① Sử dụng lệnh jobs để xem tác vụ chạy nền, sẽ chỉ định một số cho mỗi tác vụ.
② Sử dụng lệnh fg để đưa tác vụ nền có số chỉ định về điều khiển nền, ví dụ: fg 10 - đưa tác vụ số 10 về nền.
③ Xem tiến trình chiếm dụng một cổng nhất định:
netstat -nlp | grep 2181 # Kết quả dưới đây cho thấy tiến trình có pid=18434 là tiến trình java đang chiếm dụng cổng 2181 tcp 0 0 :::2181 :::* LISTEN 18434/java