จะแยกโมดูลออกจากเครื่องปฏิกรณ์ Maven ได้อย่างไร?


100

เรามีโครงการ Maven 2 ที่มีโมดูลมากมายอยู่ในนั้น ตัวอย่าง:

<modules>
  <module>common</module>
  <module>foo</module>
  <module>data</module>
  <module>bar</module>
  ... more ...
</module>

สมมติว่าโมดูล "ข้อมูล" ใช้เวลาในการสร้างและเราต้องการยกเว้นเมื่อโครงการสร้างโดยเซิร์ฟเวอร์ CI ปัจจุบันเราใช้ไฟล์ pom.xml สองไฟล์เพื่อให้บรรลุสิ่งนี้ หนึ่งมีโมดูลทั้งหมดอยู่ในนั้นและอีกโมดูลหนึ่งมีโมดูลทั้งหมดยกเว้นโมดูลที่สามารถเว้นไว้สำหรับ CI ได้ แต่มันค่อนข้างน่ารำคาญเพราะบางครั้งเราลืมใส่โมดูลใหม่ลงในทั้งสองไฟล์

มีวิธีแก้ปัญหาที่ไม่ต้องการรายการโมดูลสองรายการแยกกันหรือไม่?

คำตอบ:


73

วิธีที่ง่ายที่สุดอาจใช้profilesดังนี้:

<project>
  ...
  <modules>
    <module>common</module>
    <module>foo</module>
    <module>bar</module>
  <modules>
  ...
  <profiles>
    <profile>
      <id>expensive-modules-to-build</id>
      <modules>
        <module>data</module>
      </modules>
    </profile>
  </profiles>
</project>

จากนั้นคุณควรตรวจสอบวิธีเปิดใช้งานโปรไฟล์


คุณจะทำอย่างไรถ้าคุณต้องการให้ข้อมูลเกิดขึ้นก่อนที่จะเกิดขึ้นทั่วไป? ในกรณีนี้โมดูลโปรไฟล์จะถูกวางไว้หลังโมดูลเริ่มต้นตามลำดับเครื่องปฏิกรณ์ มีรูปแบบการบังคับสั่งซื้อหรือไม่?
Peter Kahn

9
ลำดับของโมดูลไม่ใช่ลำดับที่จะปรากฏในเครื่องปฏิกรณ์ วิธีเดียวที่จะส่งผลต่อคำสั่งคือการสร้างการอ้างอิงระหว่างโมดูลนั่นคือการใช้แท็ก <dependency> คุณไม่สามารถพึ่งพาคำสั่งการประกาศสำหรับสิ่งนี้ได้
SaM

7
@SaM จริงๆแล้วในขณะที่ Maven 3.0.5 เครื่องปฏิกรณ์จะคำนึงถึงลำดับใน 'โมดูล'แม้ว่าคำสั่งที่กำหนดโดยการอ้างอิงจะมีลำดับความสำคัญสูงกว่า
hellodanylo

สิ่งนี้จะทำลายปลั๊กอินอื่น ๆ ที่ไม่สามารถตรวจพบโมดูลในโปรไฟล์แม้ว่าโปรไฟล์จะถูกเปิดใช้งาน
ก็ตาม

146

ด้วย Maven 3.2.1 ตอนนี้คุณสามารถใช้-pl !<module_name>,!<module_name>เพื่อแยกโมดูลบางโมดูลออกจากโครงสร้างเครื่องปฏิกรณ์

ดูคำขอคุณสมบัตินี้: https://issues.apache.org/jira/browse/MNG-5230


ปลอดภัยไหมที่จะเปลี่ยนจาก 3.0.4 เป็น 3.2.1 หรือมีการเปลี่ยนแปลงที่มากขึ้น?
ม.ค.

ฉันย้ายจาก 3.1 เป็น 3.2.1 โดยไม่มีปัญหาใด ๆ แต่พูดตามตรงคุณจะต้องสร้างเพื่อให้เข้าใจ
Yogesh_D

31
อย่าลืมหนีเครื่องหมายตกใจบนบรรทัดคำสั่งเชลล์ มีความหมายพิเศษมากดูเช่นunix.stackexchange.com/questions/3747/…
Pavel

5
น่าเสียดายที่ขณะนี้มีปัญหาที่เปิดอยู่ในปลั๊กอิน Jenkins maven-project ที่ไม่รองรับการยกเว้นโมดูลเครื่องปฏิกรณ์: issue.jenkins-ci.org/browse/JENKINS-26472
Nick Vanderhoven

1
@Pavel: หรือแค่ใช้-แทน!เช่น-pl -<module_name>
msa

45

นอกจากนี้ยังสามารถระบุโปรเจ็กต์ที่จะสร้างในบรรทัดคำสั่ง mvn สิ่งนี้จะลบความจำเป็นในการแยก pom แต่คุณจะต้องเปลี่ยนการกำหนดค่า CI ทุกครั้งที่มีโมดูลใหม่แทน

-pl,--projects <arg>                Comma-delimited list of specified
                                    reactor projects to build instead
                                    of all projects. A project can be
                                    specified by [groupId]:artifactId
                                    or by its relative path.

อาจจะเป็นการรวมกันของแฟล็กนี้และ--also-make-dependentsหรือ--also-makeจะลดภาระการบำรุงรักษานี้อีกครั้ง

-am,--also-make                     If project list is specified, also
                                    build projects required by the
                                    list
-amd,--also-make-dependents         If project list is specified, also
                                    build projects that depend on
                                    projects on the list

สิ่งนี้มีปัญหาเหมือนกับการใช้ปอมสองตัวแยกกัน เราต้องวางตำแหน่งที่เรากำหนดโมดูล นั่นคือสิ่งที่ฉันพยายามหลีกเลี่ยง
kayahr

นี่เป็นทางออกที่ดี ไม่ต้องอัพปอม mvn clean install -pl mysubproject
nicolas-f

22

ฉันคิดว่าคุณต้องการให้บิลด์เริ่มต้นสร้างทุกอย่างโดยไม่คำนึงถึงความเร็วเพื่อให้นักพัฒนาใหม่สามารถเริ่มต้นได้อย่างรวดเร็วโดยไม่ต้องทำความเข้าใจเกี่ยวกับ POM มากมาย คุณสามารถใช้โปรไฟล์เช่นนี้:

<modules>
    <module>common</module>
    <module>foo</module>
    <module>bar</module>
  </modules>
  ...
  <profiles>
    <profile>
      <id>expensive-modules-to-build</id>
      <activation>
         <activeByDefault>true</activeByDefault>
      </activation>
      <modules>
        <module>data</module>
      </modules>
    </profile>
  </profiles>
</project>

ปัญหานี้คือถ้านักพัฒนาระบุโปรไฟล์อื่นในบรรทัดคำสั่งแสดงว่าexpensive-modules-to-buildจะไม่รวมอยู่ด้วย (เว้นแต่ผู้พัฒนาจะระบุด้วย) ทำให้จำได้ยากว่าจะต้องใส่โปรไฟล์ใดบ้าง

นี่คือวิธีที่แฮ็ก โปรไฟล์ทั้งสองจะรวมอยู่ด้วยเสมอเนื่องจากมีไฟล์ pom.xml อยู่เสมอ ดังนั้นหากต้องการยกเว้นโมดูลราคาแพงคุณสามารถใช้-P!full-buildในบรรทัดคำสั่ง

<profiles>
    <profile>
        <id>full-build</id>
        <activation>
            <file>
                <exists>pom.xml</exists>
            </file>
        </activation>
        <modules>
            <module>data</module>
        </modules>
    </profile>
    <profile>
        <id>short-build</id>
        <activation>
            <file>
                <exists>pom.xml</exists>
            </file>
        </activation>
        <modules>
           <module>common</module>
           <module>foo</module>
           <module>bar</module>
        </modules>
    </profile>
</profiles>

คำตอบที่ดี แต่คุณต้องการสองโปรไฟล์ในตัวอย่างโค้ดที่ 2 หรือไม่? โปรไฟล์เดียวจากตัวอย่างโค้ดที่ 1 ที่มีองค์ประกอบการเปิดใช้งานที่เปลี่ยนแปลงจะไม่ทำงานใช่หรือไม่
Arend v. Reinersdorff

1
@ Arendv.Reinersdorff ใช่อย่างไรก็ตามคำตอบนี้ยังใช้ได้กับโปรไฟล์อื่น ๆ ในโครงสร้างที่คุณอาจต้องการรวมไว้เป็นค่าเริ่มต้น โดยรวมแล้วฉันคิดว่าคำตอบอื่น ๆ-pl !<module_name>,!<module_name>ดีกว่าคำตอบ เก่านี้
artbristol

1
เคล็ดลับการเปิดใช้งานที่ดี มันช่วยแก้ปัญหา <activeByDefault> ที่ใช้งานไม่ได้ตลอดเวลา!
Gab

7

แนวคิดอีกประการหนึ่ง: โมดูลเครื่องปฏิกรณ์สามารถซ้อนกันได้ดังนั้นจึงควรจัดกลุ่มโมดูลที่สร้างเร็วและช้าของคุณเป็นปอมแยกจากกันจากนั้นจึงเพิ่มปอมตัวรวบรวมอื่นที่มีสองตัวนี้เป็นโมดูล จากนั้นเซิร์ฟเวอร์ CI ของคุณสามารถอ้างอิงได้เฉพาะ pom ที่มีโมดูลการสร้างที่รวดเร็ว

<artifactId>fast</artifactId>
<modules>
    <module>fast-a</module>
    <module>fast-b</module>
    <module>fast-c</module>
</module>

<artifactId>all</artifactId>
<modules>
    <module>fast</module>
    <module>slow</module>
</module>

1

คุณอาจจะใช้ Maven โปรไฟล์ ในสภาพแวดล้อมการสร้างของเราเราได้สร้างโปรไฟล์quickที่ปิดใช้งานปลั๊กอินจำนวนมากและทดสอบการดำเนินการ

สิ่งนี้ทำได้โดย

    <profile>
        <id>quick</id>
        <properties>
            <skipTests>true</skipTests>
            <!-- others... -->
        </properties>   
        <build>
            <plugins>
                 <!-- configuration... -->
            </plugins>
        </build>
    </profile>

จากนั้นเราก็เรียกมาเวนด้วยวิธีต่อไปนี้

mvn groupId:artifactId:goal -P quick

คุณอาจปิดการใช้งานการรวบรวมและปลั๊กอินมาตรฐานอื่น ๆ ใน pom ของโมดูลของคุณเพื่อเร่งความเร็ว


2
ใช่สำหรับการปิดใช้งานการทดสอบนี้ใช้งานได้ดี แต่ฉันจะใช้โปรไฟล์เพื่อแยกโมดูลโดยไม่ต้องมีรายการโมดูลสองรายการแยกกันใน pom ได้อย่างไร เท่าที่ฉันรู้ฉันต้องใส่รายการโมดูลทั้งหมดลงในส่วนโปรไฟล์เดียวและรายการโมดูลสร้างด่วนในส่วนโปรไฟล์อื่น ๆ ดังนั้นนี่จึงมีปัญหาเหมือนกับการใช้ปอมสองตัวแยกกัน: ฉันมีรายการโมดูลสองรายการที่ต้องดูแล
kayahr

การยกเว้นโมดูลไม่ใช่วิธีการทำสิ่งต่างๆใน maven จริงๆและประสบการณ์ของฉันกับ maven นั้นดีกว่าที่จะยึดติดกับวิธีการทำสิ่งต่าง ๆ มิฉะนั้นคุณจะประสบปัญหามากมาย ... ดังนั้นสิ่งที่ฉันเสนอจริงๆคือไม่ ถอดโมดูลออก แต่เพื่อให้โมดูลนี้ใช้เวลาน้อยลง
9

ปัญหาของ maven คือ 'วิธีการทำสิ่งต่างๆ' มักไม่สอดคล้องกับ 'วิธีการทำสิ่งต่างๆในโลกแห่งความเป็นจริง' ทำให้ maven มีประสบการณ์ที่น่าสงสารและเจ็บปวด นักพัฒนาสามารถทำได้ดีในการฝึกอบรม UX
Ed Randall

0

ไม่ตรงกับคำตอบที่คนเหล่านี้ต้องการ สถานการณ์ของฉันคือฉันต้องการปรับใช้ปอมแม่เท่านั้น ฉันกำลังใช้spring-boot-thin-layoutโมดูลย่อยในโมดูลลูก สิ่งนี้ต้องใช้โมดูลพาเรนต์ในโรงงานประดิษฐ์ ฉันเพิ่มสิ่งต่อไปนี้ลงในโครงการของฉัน ช่วยให้สามารถข้ามinstallและ / หรือdeployเฟสได้

ในพ่อแม่ของฉันปอม:

<properties>
    <disable.install>true</disable.install>
    <disable.deploy>true</disable.deploy>
    <enable.deployAtEnd>true</enable.deployAtEnd>
</properties>

<profiles>
    <profile>
        <id>deploy-parent</id>
        <activation>
            <activeByDefault>true</activeByDefault>
        </activation>
        <properties>
            <disable.install>true</disable.install>
            <disable.deploy>true</disable.deploy>
            <deployAtEnd>${enable.deployAtEnd}</deployAtEnd>
        </properties>
        <build>
            <finalName>${project.version}</finalName>
        </build>
    </profile>
</profiles>

และในลูกของฉัน pom (s) หรือโมดูลใด ๆ ที่คุณไม่ต้องการปรับใช้กับผู้ปกครอง:

<properties>
    <maven.install.skip>${disable.install}</maven.install.skip>
    <maven.deploy.skip>${disable.deploy}</maven.deploy.skip>
    <deployAtEnd>${enable.deployAtEnd}</deployAtEnd>
</properties>

ดังนั้นเมื่อฉันรันmvn deployบน pom แม่อย่างมีประสิทธิภาพมันจะรวบรวมโมดูลทั้งหมดไม่เรียกใช้การติดตั้งกับสิ่งใด ๆ จากนั้นในตอนท้ายปรับใช้โมดูลใด ๆ ที่ไม่มี<maven.deploy.skip>${disable.deploy}</maven.deploy.skip>ในคุณสมบัติของมัน ดังนั้นในกรณีของฉันทำให้ใช้งานพาเรนต์เท่านั้น

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.