Sự khác biệt giữa biên dịch phạm vi maven và được cung cấp cho bao bì JAR


260

Sự khác biệt giữa phạm vi maven compileprovidedkhi tạo tác được xây dựng dưới dạng JAR là gì? Nếu đó là WAR, tôi hiểu - hiện vật sẽ được bao gồm hoặc không có trong WEB-INF / lib. Nhưng trong trường hợp JAR thì không vấn đề gì - không bao gồm phụ thuộc. Họ phải ở trên classpath khi phạm vi của họ là compilehoặc provided. Tôi biết rằng providedsự phụ thuộc không mang tính bắc cầu - nhưng nó chỉ là một sự khác biệt?

Câu trả lời:


289

Từ Maven Đốc :

  • biên dịch

    Đây là phạm vi mặc định, được sử dụng nếu không được chỉ định. Biên dịch phụ thuộc có sẵn trong tất cả các đường dẫn của dự án. Hơn nữa, những phụ thuộc đó được tuyên truyền cho các dự án phụ thuộc.

  • cung cấp

    Điều này giống như biên dịch, nhưng chỉ ra rằng bạn mong đợi JDK hoặc một thùng chứa cung cấp sự phụ thuộc khi chạy. Ví dụ: khi xây dựng một ứng dụng web cho Phiên bản Java Enterprise, bạn sẽ đặt sự phụ thuộc vào API Servlet và API Java EE có liên quan đến phạm vi được cung cấp vì bộ chứa web cung cấp các lớp đó. Phạm vi này chỉ có sẵn trên đường biên dịch và biên dịch thử nghiệm, và không có tính bắc cầu.

Tóm tắt lại

  • phụ thuộc không phải là bắc cầu (như bạn đã đề cập)
  • phạm vi được cung cấp chỉ khả dụng trên đường dẫn biên dịch và kiểm tra, trong khi phạm vi biên dịch có sẵn trong tất cả các đường dẫn lớp.
  • cung cấp phụ thuộc không được đóng gói

5
Vâng tôi biết. Nhưng tôi suy nghĩ về sự khác biệt trong phạm vi trong JAR packagingbối cảnh. Maven doc không đề cập đến nó. Tôi sử dụng Maven một thời gian, nhưng tôi đã tự hỏi về nó :) Vì vậy, dường như trong JAR packagingbối cảnh, không có bất kỳ sự khác biệt nào giữa compileprovided(ngoại trừ chuyển đổi phụ thuộc). Tôi có đúng không
emstol

3
@Jacob có nghĩa là "trong khi phạm vi biên dịch có sẵn trong tất cả các đường dẫn lớp ."?
Geek

1
Tôi nghĩ rằng "KHÔNG Transitive" là một bước ngoặt lớn ở đây. Bởi vì địa ngục phụ thuộc là thứ mà các nhà phát triển phải đối mặt rất thường xuyên và Phạm vi được cung cấp ngăn chặn nó xảy ra và gây rối với các phiên bản khác là rất quan trọng.
Seetharamani Tmr

2
Tôi nghĩ rằng sự khác biệt là về giai đoạn đóng gói. Với trình biên dịch, nó sẽ bao gồm jar trong cuộc chiến cuối cùng hoặc jar (chẳng hạn như jar thực thi khởi động mùa xuân), và được cung cấp có thể không có kết quả. Bởi vì jar được cung cấp có thể được cung cấp bởi bộ chứa web (chẳng hạn như đặt trong thư mục ext lib), nó không nằm trong gói chiến tranh nếu không bị phụ thuộc bởi các phạm vi, biên dịch, thời gian chạy khác.
Addo Zhang

1
@emstol Quay trở lại câu hỏi ban đầu của bạn, bạn đã đúng rằng trong trường hợp JAR, các phụ thuộc không được đóng gói bên trong chính JAR. Nhưng trong maven, bao bì JAR có nghĩa là bạn muốn nó được sử dụng làm thư viện. Ngay khi bạn nhập nó trong một số dự án maven khác, các phụ thuộc bắc cầu sẽ được đưa ra nếu phạm vi là compilevà sẽ không có nếu phạm vi là provided.
LeoLuz

291

Biên dịch nghĩa là bạn cần JAR để biên dịch và chạy ứng dụng. Đối với một ứng dụng web, ví dụ, JAR sẽ được đặt trong thư mục WEB-INF / lib.

Được cung cấp có nghĩa là bạn cần JAR để biên dịch, nhưng tại thời điểm chạy đã có JAR được cung cấp bởi môi trường nên bạn không cần nó được đóng gói với ứng dụng của bạn. Đối với một ứng dụng web, điều này có nghĩa là tệp JAR sẽ không được đặt vào thư mục WEB-INF / lib.

Đối với một ứng dụng web, nếu máy chủ ứng dụng đã cung cấp JAR (hoặc chức năng của nó), thì hãy sử dụng "được cung cấp" nếu không sử dụng "biên dịch".

Dưới đây là tài liệu tham khảo.


11
Bạn không trả lời câu hỏi của OP? ' Điều gì khác biệt trong việc sử dụng biên dịch phạm vi maven và được cung cấp khi tạo tác được xây dựng dưới dạng JAR ? 'Lưu ý rằng tác giả tuyên bố rõ ràng rằng họ biết sự khác biệt khi đóng gói là chiến tranh.
Alberto

Tôi có thể sử dụng được cung cấp nếu tôi đang tham khảo một JAR khác được triển khai trên cùng một máy chủ ứng dụng không ??
Samy Omar

1
Vì vậy, để rõ ràng, một phụ thuộc được cung cấp không được thêm vào đường dẫn lớp khi mvn exec:javađược chạy, nhưng một phụ thuộc được biên dịch là.
Jamie

Tôi đã hỏi câu hỏi này - stackoverflow.com/questions/37360132/ Tên Vấn đề đã được giải quyết bằng cách thay đổi phạm vi từ cung cấp sang biên dịch. Nhưng tôi không thấy bất kỳ sự khác biệt nào giữa jar được biên dịch với phạm vi "được cung cấp" và jar được biên dịch với phạm vi "biên dịch". Bạn có thể giải thích tại sao?
Pavel_K


22

Nếu bạn dự định tạo một tệp JAR duy nhất với tất cả các phụ thuộc của nó (xxxx-all.jar điển hình), thì cung cấp phạm vi có vấn đề, bởi vì các lớp trong phạm vi này sẽ không được gói trong JAR kết quả.

Xem maven-assembly-plugin để biết thêm thông tin


7
cung cấp phụ thuộc ==> phụ thuộc sẽ KHÔNG được đóng gói.
Gab 是

3
Sự nhầm lẫn của OP được giải quyết rõ ràng khi bạn đóng gói maven-assembly-plugin, điều thú vị là các câu trả lời được bình chọn nhiều nhất không đề cập đến nó.
Henrique G. Abreu

Tôi không hiểu câu trả lời này. Nó trông giống như một bình luận.
Revierpost

11
  • biên dịch

Cung cấp vào đường dẫn lớp, không thêm phụ thuộc này vào bình cuối cùng nếu đó là bình thường; nhưng thêm bình này vào bình nếu bình cuối cùng là bình duy nhất (ví dụ: bình thực thi)

  • cung cấp

Sự phụ thuộc sẽ có sẵn trong môi trường thời gian chạy, vì vậy đừng thêm phụ thuộc này trong mọi trường hợp; thậm chí không trong một jar duy nhất (tức là jar thực thi, v.v.)


3

Đối với tệp jar, sự khác biệt nằm ở đường dẫn được liệt kê trong tệp MANIFEST.MF có trong tệp jar nếu addClassPath được đặt thành true trong cấu hình maven-jar-plugin. Phụ thuộc 'biên dịch' sẽ xuất hiện trong bảng kê khai, 'phụ thuộc' sẽ không.

Một trong những thú cưng của tôi là hai từ này nên có cùng một thì. Hoặc được biên dịch và cung cấp, hoặc biên dịch và cung cấp.


0

Khi bạn đặt phạm vi maven là provided, điều đó có nghĩa là khi plugin chạy, phiên bản phụ thuộc thực tế được sử dụng sẽ phụ thuộc vào phiên bản Apache Maven mà bạn đã cài đặt.


0

Nếu tệp jar giống như tệp jar khởi động mùa xuân thực thi thì phạm vi của tất cả các phụ thuộc phải compilebao gồm tất cả các tệp jar.

Nhưng nếu tệp jar được sử dụng trong các gói hoặc ứng dụng khác thì không cần bao gồm tất cả các phụ thuộc trong tệp jar vì các gói hoặc ứng dụng này có thể tự cung cấp các phụ thuộc khác.

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.