TheNEXUS

1.7. Att jämföra Maven med Ant

Författarna till den här boken har inget intresse av att skapa en fejd mellanApache Ant och Apache Maven, men vi är också medvetna om det faktum att de flesta organisationer måste fatta ett beslut mellan de två standardlösningarna: Apache Ant och Apache Maven. I det här avsnittet jämför och kontrasterar vi verktygen.

Ant utmärker sig för byggprocessen, det är ett byggsystem modellerat efter make med mål och beroenden. Varje mål består av en uppsättning instruktioner som är kodade i XML. Det finns en copy uppgift och enjavac uppgift samt en jar uppgift. När du använder Ant förser du Antw med specifika instruktioner för att kompilera och paketera ditt resultat. Titta på följande exempel på en enkel build.xml-fil:

En enkel Ant build.xml-fil.

<project name="my-project" default="dist" basedir="."> <description> simple example build file </description> <!-- set global properties for this build --> <property name="src" location="src/main/java"/> <property name="build" location="target/classes"/> <property name="dist" location="target"/> <target name="init"> <!-- Create the time stamp --> <tstamp/> <!-- Create the build directory structure used by compile --> <mkdir dir="${build}"/> </target> <target name="compile" depends="init" description="compile the source " > <!-- Compile the java code from ${src} into ${build} --> <javac srcdir="${src}" destdir="${build}"/> </target> <target name="dist" depends="compile" description="generate the distribution" > <!-- Create the distribution directory --> <mkdir dir="${dist}/lib"/> <!-- Put everything in ${build} into the MyProject-${DSTAMP}.jar file --> <jar jarfile="${dist}/lib/MyProject-${DSTAMP}.jar" basedir="${build}"/> </target> <target name="clean" description="clean up" > <!-- Delete the ${build} and ${dist} directory trees --> <delete dir="${build}"/> <delete dir="${dist}"/> </target></project>

I det här enkla Ant-exemplet kan du se hur du måste tala om för Antex exakt vad den ska göra. Det finns ett kompileringsmål som innehåller javacuppgiften som kompilerar källkoden i katalogen src/main/java till katalogen thetarget/classes. Du måste tala om för Ant exakt var din källa finns, var du vill att den resulterande bytekoden ska lagras och hur du ska paketera allt detta i en JAR-fil. Även om det finns en del nya utvecklingar som hjälper till att göra Ant mindre procedurell, är en utvecklares erfarenhet av Ant att koda ett procedurellt språk skrivet i XML.

Kontrastera det föregående Ant-exemplet med ett Maven-exempel. För att skapa en JAR-fil från en Java-källa i Maven behöver du bara skapa en enkel pom.xml, placera din källkod i${basedir}/src/main/java och sedan köra mvn install från kommandoraden. Ett exempel på en Maven pom.xml som ger samma resultat som den enkla Ant-fil som anges i En enkel Ant build.xml-fil visas iA Sample Maven pom.xml.

A Sample Maven pom.xml.

<project> <modelVersion>4.0.0</modelVersion> <groupId>org.sonatype.mavenbook</groupId> <artifactId>my-project</artifactId> <version>1.0</version></project>

Det är allt du behöver i din pom.xml. Om du kör mvn install frånkommandoraden kommer du att bearbeta resurser, kompilera källkod, utföra unittests, skapa en JAR och installera JAR:n i ett lokalt arkiv för återanvändning i andra projekt. Utan ändringar kan du köra mvn siteoch sedan hitta en index.html-fil i target/site som innehåller länkar till JavaDoc och några rapporter om din källkod.

Det här är visserligen det enklaste möjliga exempelprojektet som inte innehåller något mer än en del källkod och som producerar en enkel JAR. Det är ett projekt som nära följer Maven-konventionerna och som inte kräver några beroenden eller anpassningar. Om vi vill börja anpassa beteendet kommer vår pom.xml att växa i storlek, och i de största projekten kan du se samlingar av mycket komplexa Maven POMs som innehåller en hel del anpassningar av insticksmoduler och förklaringar av beroenden. Men även när projektets POM-filer blir mer omfattande innehåller de en helt annan typ av information än byggfilen för ett projekt av samma storlek som använder Ant. Maven POM-filer innehåller deklarationer: ”Detta är ett JAR-projekt” och ”Källkoden finns i src/main/java”. Ant-byggfiler innehåller uttryckliga instruktioner: ”Detta är ett projekt”, ”Källkoden finns i src/main/java”, ”Kör javakontrollen i den här katalogen”, ”Lägg resultaten i target/classes”, ”Skapa en JAR från ….” osv. Medan Ant var tvungen att vara explicit om processen fanns det något ”inbyggt” i Maven som bara visste var källkoden fanns och hur den skulle bearbetas.

Skillnaderna mellan Ant och Maven i det här exemplet är:

  • Apache Ant

    • Ant har inga formella konventioner som en gemensam projektkatalogstruktur eller standardbeteende. Du måste tala om för Ant exakt var källkoden ska hittas och var du ska placera utdata. Informella konventioner har uppstått med tiden, men de har inte kodifierats i produkten.
    • Ant är procedurell. Du måste tala om för Ant exakt vad han ska göra och när han ska göra det. Du måste säga åt den att kompilera, sedan kopiera och sedan komprimera.
    • Ant har ingen livscykel. Du måste definiera mål och målberoenden. Du måste knyta en sekvens av uppgifter till varje mål manuellt.
  • Apache Maven

    • Maven har konventioner. Den vet var din källkod finns eftersom du följde konventionen. Mavens Compiler-plugin lägger bytekoden i target/classes och producerar en JAR-fil i target.
    • Maven är deklarativ. Allt du behövde göra var att skapa en pom.xml-fil och lägga din källa i standardkatalogen. Maven tog hand om resten.
    • Maven har en livscykel som anropades när du utförde mvn install. Detta kommando uppmanade Maven att utföra en serie sekventiella livscykelfaser tills den nådde livscykelfasen install. Som en bieffekt av denna resa genom livscykeln utförde Maven ett antal standardinsticksmoduler som gjorde saker som att kompilera och skapa en JAR.

Maven har inbyggd intelligens om vanliga projektuppgifter i form av Maven-insticksmoduler. Om du vill skriva och utföra enhetstester behöver du bara skriva testerna, placera dem i${basedir}/src/test/java, lägga till ett testscoped beroende, antingen TestNG eller JUnit, och köra mvn test. Om du vill distribuera en webbapplikation och inte ett JAR behöver du bara ändra din projekttyp till war och lägga din docroot i${basedir}/src/main/webapp. Visst kan du göra allt detta medAnt, men då måste du skriva instruktionerna från grunden. I Ant måste du först ta reda på var JUnit JAR-filen ska finnas. Sedan måste du skapa en classpath som innehåller JUnitJAR-filen. Sedan skulle du tala om för Ant var den ska leta efter testkällkod, skriva ett mål som kompilerar testkällkoden till bytekod och utföra enhetstesterna med JUnit.

Och utan stödtekniker som antlibs och Ivy (även med dessa stödtekniker) har Ant känslan av en c`ustom proceduralbuild. En effektiv uppsättning Maven POMs i ett projekt som följer Mavens antagna konventioner har förvånansvärt lite XML jämfört med Ant-alternativet. En annan fördel med Maven är att man kan förlita sig på Maven-plugins som delas av många. Alla använder Maven Surefire-pluginet för enhetstestning, och om någon lägger till stöd för ett nytt ramverk för enhetstestning kan du få nya möjligheter i ditt eget bygge genom att bara öka versionen av ett visst Maven-plugin i ditt projekts POM.

Beslutet att använda Maven eller Ant är inte binärt och Ant har fortfarande en plats i ett komplext bygge. Om ditt nuvarande bygge innehåller någon mycket kundanpassad process, eller om du har skrivit några Ant-skript för att slutföra en specifik process på ett specifikt sätt som inte kan anpassas till Maven-standarderna, kan du fortfarande använda dessa skript med Maven. Ant är tillgänglig som ett grundläggande insticksprogram för Maven. Anpassade Maven-plugins kan implementeras i Ant, och Maven-projekt kan konfigureras för att exekveraAnt-skript inom Maven-projektets livscykel.

Leave a Reply