Maven: cách ghi đè phần phụ thuộc do thư viện thêm vào


116

Đây là vấn đề chung của tôi:

Dự án P của tôi phụ thuộc vào A phụ thuộc vào B phụ thuộc vào C phụ thuộc vào phiên bản 1.0.1 của D.

Đã xảy ra sự cố với phiên bản 1.0.1 của D và tôi muốn buộc sử dụng mô-đun khác. Tôi không biết làm thế nào để khai báo điều này trong POM của dự án của mình vì tôi chưa thêm trực tiếp phụ thuộc vào D. Đó là C khai báo sự phụ thuộc vào D.

Quan trọng: Trong trường hợp này, không chỉ phiên bản bị thay đổi, mà cả nhóm & tạo tác. Vì vậy, vấn đề không chỉ là ghi đè phiên bản của phụ thuộc, mà còn là loại trừ một mô-đun và bao gồm một mô-đun khác.

Trong trường hợp cụ thể, D là StAX có 1.0.1 có lỗi . Theo ghi chú trong lỗi, "các vấn đề đã được giải quyết bằng cách thay thế stax-api-1.0.1 (maven GroupId = stax) bằng stax-api-1.0-2 (maven GroupId = javax.xml.stream)" vì vậy tôi Tôi đang cố gắng đó.

Do đó, D = stax: stax-api: jar: 1.0.1 và C = org.apache.xmlbeans: xmlbeans: jar: 2.3.0

Tôi đang sử dụng maven 2.0.9 trong trường hợp có vấn đề.

Đầu ra của phụ thuộc mvn: cây "

mvn dependency:tree
[..snip..]
[INFO] +- org.apache.poi:poi-ooxml:jar:3.6:compile
[INFO] |  +- org.apache.poi:poi-ooxml-schemas:jar:3.6:compile
[INFO] |  |  +- org.apache.xmlbeans:xmlbeans:jar:2.3.0:compile
[INFO] |  |  |  \- stax:stax-api:jar:1.0.1:compile

Trong POM của dự án của tôi, tôi có phụ thuộc sau vào "A":

<dependency>
    <groupId>org.apache.poi</groupId>
    <artifactId>poi</artifactId>
    <version>3.6</version>
</dependency>
<dependency>
    <groupId>org.apache.poi</groupId>
    <artifactId>poi-ooxml</artifactId>
    <version>3.6</version>
</dependency>

Cảm ơn trước.

Câu trả lời:


100

Chỉ cần chỉ định phiên bản trong pom hiện tại của bạn. Phiên bản được chỉ định ở đây sẽ ghi đè phiên bản khác.

Buộc một phiên bản
Một phiên bản sẽ luôn được tôn trọng nếu nó được khai báo trong POM hiện tại với một phiên bản cụ thể - tuy nhiên, cần lưu ý rằng điều này cũng sẽ ảnh hưởng đến các pom khác ở hạ lưu nếu bản thân nó phụ thuộc vào việc sử dụng các phụ thuộc bắc cầu.


Tài nguyên :


5
không rõ làm cách nào tôi có thể chỉ định phiên bản vì tôi không khai báo phụ thuộc vào D. Ngoài ra, liên kết đầu tiên bạn cung cấp có "Tài liệu này mô tả phần còn lại của các yêu cầu về quản lý phụ thuộc CHƯA được triển khai cho Maven 2.0, đặc biệt là liên quan đến phụ thuộc bắc cầu. " ở trên cùng.
wishihadabettername

@wishihadabettername, Như đã nói trong các tài liệu khác: "Bạn rõ ràng có thể thêm một phụ thuộc vào D 2.0 A để buộc việc sử dụng D 2.0"
Colin Hebert

1
Bạn thực sự sao chép mục nhập <dependency> rất giống nhau trong pom của riêng bạn. Trong phần phụ thuộc của bạn, hãy chỉ định một <version> mà bạn muốn. Điều đó sẽ ghi đè bất kỳ phiên bản nào được sử dụng bởi các phần phụ thuộc "sâu hơn".
Keith Tyler

27

Ngoài ra, bạn có thể loại trừ phần phụ thuộc mà bạn không muốn. STAX được bao gồm trong JDK 1.6, vì vậy nếu bạn đang sử dụng 1.6, bạn có thể loại trừ nó hoàn toàn.

Ví dụ dưới đây của tôi hơi sai đối với bạn - bạn chỉ cần một trong hai loại trừ nhưng tôi không chắc cái nào. Có nhiều phiên bản khác của Stax, trong ví dụ dưới đây, tôi đang nhập A đã nhập B đã nhập C & D mà mỗi phiên bản (thông qua các phụ thuộc bắc cầu hơn) đã nhập các phiên bản khác nhau của Stax. Vì vậy, trong sự phụ thuộc của tôi vào 'A', tôi đã loại trừ cả hai phiên bản của Stax.

<dependency>
  <groupId>a.group</groupId>
  <artifactId>a.artifact</artifactId>
  <version>a.version</version>
  <exclusions>
    <!--  STAX comes with Java 1.6 -->
    <exclusion>
      <artifactId>stax-api</artifactId>
      <groupId>javax.xml.stream</groupId>
    </exclusion>
    <exclusion>
      <artifactId>stax-api</artifactId>
      <groupId>stax</groupId>
    </exclusion>
  </exclusions>
<dependency>

1
Cần phải lưu ý rằng sự phụ thuộc bắc cầu này có thể được sử dụng và việc loại trừ có thể gây ra lỗi xây dựng nếu cần.
Bernhard Colby

Nếu bạn đang sử dụng JDK hiện đại (tức là 1.6+) và bạn cần phiên bản stax cũ hơn nhiều được bao gồm thông qua phụ thuộc bắc cầu, có thể bạn sẽ gặp phải tất cả các loại vấn đề về trình tải lớp thời gian chạy khủng khiếp. Lời khuyên của tôi: hãy sử dụng một trong JDK. Nếu bạn gặp "lỗi xây dựng", bạn đang dựa vào một API cổ của một số dạng cần được nâng cấp. Hoặc: lùi JDK của bạn về 1,5. Chúc may mắn với điều đó.
scot

11

Những gì bạn đặt bên trong </dependencies>thẻ của root pom sẽ được bao gồm bởi tất cả các mô-đun con của root pom. Nếu tất cả các mô-đun của bạn sử dụng sự phụ thuộc đó, đây là cách để đi.

Tuy nhiên, nếu chỉ 3 trong số 10 mô-đun con của bạn sử dụng một số phụ thuộc nào đó, bạn không muốn phụ thuộc này được đưa vào tất cả các mô-đun con của mình. Trong trường hợp đó, bạn chỉ có thể đặt phụ thuộc vào bên trong </dependencyManagement>. Điều này sẽ đảm bảo rằng bất kỳ mô-đun con nào cần phần phụ thuộc đều phải khai báo nó trong tệp pom của riêng chúng, nhưng chúng sẽ sử dụng cùng một phiên bản của phần phụ thuộc đó như được chỉ định trong </dependencyManagement>thẻ của bạn .

Bạn cũng có thể sử dụng </dependencyManagement>để sửa đổi phiên bản được sử dụng trong phụ thuộc bắc cầu, vì phiên bản được khai báo trong tệp pom cao nhất là phiên bản sẽ được sử dụng. Điều này có thể hữu ích nếu dự án A của bạn bao gồm một dự án bên ngoài B v1.0 bao gồm một dự án bên ngoài C v1.0 khác. Đôi khi nó xảy ra rằng một vi phạm bảo mật được tìm thấy trong dự án C v1.0 được sửa trong v1.1, nhưng các nhà phát triển của B chậm cập nhật dự án của họ để sử dụng v1.1 của C. Trong trường hợp đó, bạn chỉ cần khai báo phụ thuộc vào C v1.1 trong root pom bên trong dự án của bạn `, và mọi thứ sẽ tốt (giả sử rằng B v1.0 vẫn có thể biên dịch với C v1.1).


10

Tôi cũng gặp sự cố khi kiểm duyệt phần phụ thuộc trong thư viện của bên thứ ba. Tôi đã sử dụng cách tiếp cận của scot với loại trừ nhưng tôi cũng đã thêm sự phụ thuộc với phiên bản mới hơn trong pom. (Tôi đã sử dụng Maven 3.3.3)

Vì vậy, đối với ví dụ về stAX, nó sẽ giống như sau:

<dependency>
  <groupId>a.group</groupId>
  <artifactId>a.artifact</artifactId>
  <version>a.version</version>
  <exclusions>
    <!--  STAX comes with Java 1.6 -->
    <exclusion>
      <artifactId>stax-api</artifactId>
      <groupId>javax.xml.stream</groupId>
    </exclusion>
    <exclusion>
      <artifactId>stax-api</artifactId>
      <groupId>stax</groupId>
    </exclusion>
  </exclusions>
<dependency>

<dependency>
    <groupId>javax.xml.stream</groupId>
    <artifactId>stax-api</artifactId>
    <version>1.0-2</version>
</dependency>

1

Câu trả lời được chấp nhận là đúng nhưng tôi muốn thêm hai xu của mình. Tôi đã gặp phải một vấn đề trong đó tôi có một dự án A có một dự án B làm phụ thuộc. Cả hai dự án đều sử dụng slf4j nhưng dự án B sử dụng log4j trong khi dự án A sử dụng logback. Dự án B sử dụng slf4j 1.6.1, trong khi dự án A sử dụng slf4j 1.7.5 (do phụ thuộc logback 1.2.3 đã được bao gồm).

Sự cố: Dự án A không thể tìm thấy một hàm tồn tại trên slf4j 1.7.5, sau khi kiểm tra tab phân cấp phụ thuộc của eclipe, tôi phát hiện ra rằng trong quá trình xây dựng, nó đã sử dụng slf4j 1.6.1 từ dự án B, thay vì sử dụng slf4j 1.7.5 của logback .

Tôi đã giải quyết vấn đề bằng cách thay đổi thứ tự của các phần phụ thuộc vào dự án A pom, khi tôi di chuyển mục nhập dự án B xuống dưới mục nhập logback thì maven bắt đầu xây dựng dự án bằng slf4j 1.7.5.

Chỉnh sửa: Thêm phụ thuộc slf4j 1.7.5 trước khi phụ thuộc Dự án B cũng hoạt động.

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.