Vẫn có cách nào để loại trừ các tạo tác được thừa kế từ POM mẹ?


119

Các <exclusions>phần tử phụ thuộc có thể bị loại trừ bằng cách khai báo một phần tử bên trong. <dependency>Nhưng trong trường hợp này, cần loại trừ một phần tử được kế thừa từ một dự án mẹ. Một đoạn trích của POM đang được thảo luận như sau:

<project>
  <modelVersion>4.0.0</modelVersion>
  <groupId>test</groupId>
  <artifactId>jruby</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <parent>
        <artifactId>base</artifactId>
        <groupId>es.uniovi.innova</groupId>
        <version>1.0.0</version>
    </parent>

    <dependencies>      
        <dependency>
            <groupId>com.liferay.portal</groupId>
            <artifactId>ALL-DEPS</artifactId>
            <version>1.0</version>
            <scope>provided</scope>
            <type>pom</type>
        </dependency>
    </dependencies>
</project>

basetạo tác, phụ thuộc vào javax.mail:mail-1.4.jarALL-DEPSphụ thuộc vào một phiên bản khác của cùng một thư viện. Do thực tế là mail.jartừ ALL-DEPStồn tại trên môi trường thực thi, mặc dù không được xuất, nhưng lại va chạm với mail.jartồn tại trên môi trường cha, được xác định phạm vi như compile.

Một giải pháp có thể là loại bỏ mail.jar khỏi POM mẹ, nhưng hầu hết các dự án kế thừa base đều cần nó (cũng như phụ thuộc chuyển đổi cho log4j). Vì vậy, những gì tôi muốn làm là chỉ cần loại trừ thư viện của cha mẹ khỏi dự án con , vì nó có thể được thực hiện nếu baselà một phụ thuộc và không phải là pom mẹ:

...
    <dependency>
        <artifactId>base</artifactId>
        <groupId>es.uniovi.innova</groupId>
        <version>1.0.0</version>
        <type>pom<type>
        <exclusions>
          <exclusion>
             <groupId>javax.mail</groupId>
             <artifactId>mail</artifactId>
          </exclusion>
        </exclusions>
    </dependency>
...

Câu trả lời:


49

Một vài ý tưởng:

  1. Có thể đơn giản là bạn không thể kế thừa từ cha mẹ trong trường hợp đó (và khai báo một phần phụ thuộc basevới loại trừ). Không tiện dụng nếu bạn có nhiều thứ trong pom mẹ.

  2. Một điều cần kiểm tra sẽ được khai báo mailvật với phiên bản theo yêu cầu của ALL-DEPSthuộc dependencyManagementtrong pom mẹ để buộc các tụ (mặc dù tôi không chắc chắn điều này sẽ giải quyết vấn đề Phạm vi).

<dependencyManagement>
  <dependencies>
    <dependency>    
      <groupId>javax.mail</groupId>
      <artifactId>mail</artifactId>
      <version>???</version><!-- put the "right" version here -->
    </dependency>
  </dependencies>
</dependencyManagement>
  1. Hoặc bạn có thể loại trừ sự mailphụ thuộc khỏi log4j nếu bạn không sử dụng các tính năng dựa vào nó (và đây là những gì tôi sẽ làm):
<dependency>
  <groupId>log4j</groupId>
  <artifactId>log4j</artifactId>
  <version>1.2.15</version>
  <scope>provided</scope>
  <exclusions>
    <exclusion>
      <groupId>javax.mail</groupId>
      <artifactId>mail</artifactId>
    </exclusion>
    <exclusion>
      <groupId>javax.jms</groupId>
      <artifactId>jms</artifactId>
    </exclusion>
    <exclusion>
      <groupId>com.sun.jdmk</groupId>
      <artifactId>jmxtools</artifactId>
    </exclusion>
    <exclusion>
      <groupId>com.sun.jmx</groupId>
      <artifactId>jmxri</artifactId>
    </exclusion>
  </exclusions>
</dependency>
  1. Hoặc bạn có thể hoàn nguyên về phiên bản 1.2.14 của log4j thay vì phiên bản 1.2.15 dị giáo (tại sao họ không đánh dấu các phần phụ thuộc trên là tùy chọn ?!).

Cảm ơn vì đã trả lời. Nó chứa rất nhiều thông tin hữu ích. Về vấn đề 1) Như bạn đã nhận thấy sẽ không phải là tối ưu bởi vì pom mẹ không chỉ chứa các phần phụ thuộc sẽ được giải quyết chuyển tiếp nếu cơ sở được đánh dấu là phần phụ thuộc, mà còn cả báo cáo chung, quản lý nguồn và những thứ khác được sử dụng lại giữa mọi dự án trong công ty. Liên quan đến 2) Tôi đã thử nó, nhưng cũng chỉ định phạm vi của tạo tác như được cung cấp, và nó đã hoạt động :). Lúc đầu, tôi nghĩ rằng khi biên dịch được ưu tiên hơn cung cấp, nó sẽ không làm việc, nhưng may mắn thay tôi đã sai (cấu hình con POM ghi đè của cha mẹ)
Miguel

29

Bạn có thể nhóm các phần phụ thuộc của mình trong một dự án khác với cách đóng gói pomnhư được mô tả bởi Các phương pháp hay nhất của Sonatypes :

<project>
    <modelVersion>4.0.0</modelVersion>
    <artifactId>base-dependencies</artifactId>
    <groupId>es.uniovi.innova</groupId>
    <version>1.0.0</version>
    <packaging>pom</packaging>
    <dependencies>
        <dependency>
            <groupId>javax.mail</groupId>
            <artifactId>mail</artifactId>
            <version>1.4</version>
        </dependency>
    </dependencies>
</project>

và tham khảo chúng từ cha mẹ của bạn (xem phần phụ thuộc <type>pom</type>):

<project>
    <modelVersion>4.0.0</modelVersion>
    <artifactId>base</artifactId>
    <groupId>es.uniovi.innova</groupId>
    <version>1.0.0</version>
    <packaging>pom</packaging>
    <dependencies>
        <dependency>
            <artifactId>base-dependencies</artifactId>
            <groupId>es.uniovi.innova</groupId>
            <version>1.0.0</version>
            <type>pom</type>
        </dependency>
    </dependencies>
</project>

Dự án con của bạn kế thừa phần mẹ này như trước. Nhưng bây giờ, sự phụ thuộc vào thư có thể được loại trừ trong dự án con trong dependencyManagementkhối:

<project>
    <modelVersion>4.0.0</modelVersion>
    <groupId>test</groupId>
    <artifactId>jruby</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <parent>
        <artifactId>base</artifactId>
        <groupId>es.uniovi.innova</groupId>
        <version>1.0.0</version>
    </parent>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <artifactId>base-dependencies</artifactId>
                <groupId>es.uniovi.innova</groupId>
                <version>1.0.0</version>
                <exclusions>
                    <exclusion>
                        <groupId>javax.mail</groupId>
                        <artifactId>mail</artifactId>
                    </exclusion>
                </exclusions>
            </dependency>
        </dependencies>
    </dependencyManagement>
</project>

4
+1 cho điều này, mặc dù pom con nên sử dụng phần <dependencies> hơn là <dependencyManagement> vì phần sau là để quản lý các phiên bản của phụ thuộc từ bên trong pom mẹ.
Matthew Wise

1
Điều này cũng được biết đến như là BOM, aka danh mục vật liệu :-)
Pim Hazebroek

Điều này chỉ hoạt động với các phụ thuộc bắc cầu? Pom mẹ của tôi chứa log4j và nó ngăn quá trình đăng nhập của pom của tôi hoạt động bình thường.
Sridhar Sarnobat

10

Không sử dụng pom mẹ

Điều này nghe có vẻ cực đoan, nhưng cũng giống như "địa ngục thừa kế" là lý do khiến một số người quay lưng lại với Lập trình hướng đối tượng (hoặc thích bố cục hơn là kế thừa ), xóa <parent>khối có vấn đề và sao chép và dán bất cứ thứ gì <dependencies>bạn cần (nếu nhóm của bạn cung cấp cho bạn tự do này).

Nên bỏ qua giả định rằng việc chia tách những người bạn thành cha mẹ và con cái để "tái sử dụng" và "tránh việc cho thuê lại" nên được bỏ qua và bạn nên phục vụ nhu cầu tức thời của mình trước (cách chữa bệnh còn tệ hơn cả bệnh). Bên cạnh đó, dự phòng có những ưu điểm của nó - đó là tính độc lập với những thay đổi bên ngoài (tức là tính ổn định).

Điều này dễ hơn nghe nếu bạn tạo pom hiệu quả (eclipse cung cấp nó nhưng bạn có thể tạo nó từ dòng lệnh với mvn help:effective).

Thí dụ

Tôi muốn sử dụng logbacklàm ràng buộc slf4j của mình, nhưng pom mẹ của tôi bao gồm phần log4jphụ thuộc. Tôi không muốn đi và phải đẩy sự phụ thuộc của những đứa trẻ khác vào log4j xuống pom.xmltệp của riêng chúng để của tôi không bị cản trở.


1
Ghi chép lại điều này (và quy trình bạn đã làm theo) rất cẩn thận vì những người bảo trì trong tương lai cần thực hiện lại việc này nếu cần sử dụng phiên bản cập nhật của pom mẹ.
Thorbjørn Ravn Andersen

Chắc chắn ý bạn là không sử dụng phụ thuộc trong pom mẹ? Parent pom vẫn rất hữu ích để quản lý các phiên bản phụ thuộc và các plugin phổ biến. Chỉ cần sử dụng nó để phụ thuộc bơm có thể phản tác dụng - chúng ta sử dụng nó chỉ cho phải có phụ thuộc (như một bộ mới bắt đầu khởi động mùa xuân rất cần thiết cho một phụ huynh cho microservices)
Amit Goldstein

Không, tôi không nói rằng hãy sử dụng pom mẹ nhẹ. Những người khác trong nhóm của bạn sẽ không cho phép bạn cắt bớt pom mẹ vì các ứng dụng khác phụ thuộc vào rác trong pom mẹ mà bạn không muốn.
Sridhar Sarnobat

8

Xác định lại sự phụ thuộc (trong pom con) với scopehệ thống trỏ đến một bình trống:

<dependency>
    <groupId>dependency.coming</groupId>
    <artifactId>from.parent</artifactId>
    <version>0</version>
    <scope>system</scope>
    <systemPath>${project.basedir}/empty.jar</systemPath>
</dependency>

Bình chỉ có thể chứa một tệp trống duy nhất:

touch empty.txt
jar cvf empty.txt

Cảm ơn câu trả lời của bạn, trên Windows 10, tôi đã phải chạy notepad empty.classsau đó jar cvf empty.jar empty.classđể tạo một jar rỗng.
Rov

1
Có vẻ như thực hành không tốt
Piotr Żak

6

Bạn đã thử khai báo rõ ràng phiên bản mail.jar mà bạn muốn chưa? Giải pháp phụ thuộc của Maven nên sử dụng điều này để giải quyết phụ thuộc trên tất cả các phiên bản khác.

<project>
  <modelVersion>4.0.0</modelVersion>
  <groupId>test</groupId>
  <artifactId>jruby</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <parent>
        <artifactId>base</artifactId>
        <groupId>es.uniovi.innova</groupId>
        <version>1.0.0</version>
    </parent>
    <dependencies>          
        <dependency>
            <groupId>javax.mail</groupId>
            <artifactId>mail</artifactId>
            <version>VERSION-#</version>
            <scope>provided</scope>
        </dependency> 
        <dependency>
            <groupId>com.liferay.portal</groupId>
            <artifactId>ALL-DEPS</artifactId>
            <version>1.0</version>
            <scope>provided</scope>
            <type>pom</type>
        </dependency>
    </dependencies>
</project>

1
Cách tiếp cận của bạn, vì cách giải quyết # 2 của Pascal cũng hợp lệ, trên thực tế, bạn cũng đã tính đến việc phụ thuộc thư phải được khai báo như đã cung cấp. Cảm ơn bạn.
Miguel

Phạm vi được cung cấp không hoạt động với tôi. Tôi đã sử dụng thử nghiệm phạm vi, vui lòng kiểm tra câu trả lời của tôi. stackoverflow.com/a/55970293/4587961
Yan Khonski

3

Đặt cược tốt nhất là tạo các phụ thuộc mà bạn không phải lúc nào cũng muốn kế thừa là intransitive.

Bạn có thể làm điều này bằng cách đánh dấu chúng trong pom mẹ với phạm vi được cung cấp.

Nếu bạn vẫn muốn cấp độ gốc quản lý các phiên bản của các cảnh báo này, bạn có thể sử dụng <dependencyManagement>thẻ để thiết lập các phiên bản bạn muốn mà không cần kế thừa chúng một cách rõ ràng hoặc chuyển quyền thừa kế đó cho con cái.


1

Khi bạn gọi một gói nhưng không muốn một số phụ thuộc của nó, bạn có thể làm như thế này (trong trường hợp này, tôi không muốn thêm log4j cũ vì tôi cần sử dụng cái mới hơn):

<dependency>
  <groupId>package</groupId>
  <artifactId>package-pk</artifactId>
  <version>${package-pk.version}</version>

  <exclusions>
    <exclusion>
      <groupId>org.apache.logging.log4j</groupId>
      <artifactId>log4j-core</artifactId>
    </exclusion>
    <exclusion>
      <groupId>org.apache.logging.log4j</groupId>
      <artifactId>log4j-api</artifactId>
    </exclusion>
  </exclusions>
</dependency>

<!-- LOG4J -->
<dependency>
  <groupId>org.apache.logging.log4j</groupId>
  <artifactId>log4j-core</artifactId>
  <version>2.5</version>
</dependency>
<dependency>
  <groupId>org.apache.logging.log4j</groupId>
  <artifactId>log4j-api</artifactId>
  <version>2.5</version>
</dependency>

Điều này phù hợp với tôi ... nhưng tôi còn khá mới với java / maven nên nó có thể không tối ưu.


Chào mừng bạn đến với Stack Overflow, và đừng để những người thô lỗ mà tôi liên tục loại bỏ câu hỏi của tôi ngăn cản bạn đăng.
Sridhar Sarnobat

1

Tôi thực sự cần phải làm điều bẩn thỉu này ... Đây là cách

Tôi đã xác định lại những phụ thuộc đó với phạm vi test. Phạm vi providedkhông hoạt động đối với tôi.

Chúng tôi sử dụng plugin Spring Boot để tạo fat jar. Chúng tôi có chung mô-đun định nghĩa các thư viện chung, ví dụ như Springfox swagger-2. Siêu dịch vụ của tôi cần phải có cha mẹ chung (nó không muốn như vậy, nhưng các quy tắc của công ty buộc!)

Vì vậy, cha mẹ hoặc commons của tôi có pom.

<dependencyManagement>

    <!- I do not need Springfox in one child but in others ->

    <dependencies>
        <dependency>
            <groupId>io.springfox</groupId>
            <artifactId>springfox-swagger2</artifactId>
            <version>${swagger.version}</version>
            <exclusions>
                <exclusion>
                    <groupId>com.google.guava</groupId>
                    <artifactId>guava</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>io.springfox</groupId>
            <artifactId>springfox-swagger-ui</artifactId>
            <version>${swagger.version}</version>
        </dependency>
        <dependency>
            <groupId>io.springfox</groupId>
            <artifactId>springfox-bean-validators</artifactId>
            <version>${swagger.version}</version>
        </dependency>

       <!- All services need them ->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>${junit.version}</version>
        </dependency>
        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi-ooxml</artifactId>
            <version>${apache.poi.version}</version>
        </dependency>
    </dependencies>
</dependencyManagement>

Và pom siêu dịch vụ của tôi .

<name>super-service</name>
<parent>
    <groupId>com.company</groupId>
    <artifactId>common</artifactId>
    <version>1</version>
</parent>

<dependencies>

    <!- I don't need them ->

    <dependency>
        <groupId>io.springfox</groupId>
        <artifactId>springfox-swagger2</artifactId>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>io.springfox</groupId>
        <artifactId>springfox-bean-validators</artifactId>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>io.springfox</groupId>
        <artifactId>springfox-core</artifactId>
        <version>2.8.0</version>
        <scope>test</scope>
    </dependency>

    <!- Required dependencies ->

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
     <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
    </dependency>
    <dependency>
        <groupId>org.apache.poi</groupId>
        <artifactId>poi-ooxml</artifactId>
    </dependency>
</dependencies>

Đây là kích thước của hiện vật béo cuối cùng

82.3 MB (86,351,753 bytes) - redefined dependency with scope test
86.1 MB (90,335,466 bytes) - redefined dependency with scope provided
86.1 MB (90,335,489 bytes) - without exclusion

Ngoài ra câu trả lời này cũng đáng được đề cập - tôi muốn làm như vậy, nhưng tôi lười ... https://stackoverflow.com/a/48103554/4587961


0

Chúng ta có thể thêm pom mẹ làm phụ thuộc với loại pom và loại trừ nó. Bởi vì dù sao thì pom mẹ cũng được tải xuống. Điều này đã làm việc cho tôi

<dependency>
  <groupId>com.abc.boot</groupId>
  <artifactId>abc-boot-starter-parent</artifactId>
  <version>2.1.5.RELEASE</version>
  <type>pom</type>
  <exclusions>
    <exclusion>
      <groupId>com.google.code.gson</groupId>
      <artifactId>gson</artifactId>
    </exclusion>
  </exclusions>   
</dependency>
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.