Tutorial do Apache Maven
*1. Introdução *
A construção de um projeto de software geralmente consiste em tarefas como baixar dependências, colocar jarros adicionais em um caminho de classe, compilar código-fonte em código binário, executar testes, empacotar código compilado em artefatos implementáveis, como arquivos JAR, WAR e ZIP, e implantar esses artefatos para um servidor de aplicativos ou repositório.
https://maven.apache.org [Apache Maven] automatiza essas tarefas, minimizando o risco de humanos cometerem erros ao criar o software manualmente e separar o trabalho de compilar e empacotar nosso código do de construção de código.
Neste tutorial, exploraremos essa ferramenta poderosa para descrever, criar e gerenciar projetos de software Java usando uma informação central - o Pject (Modelo de Objeto de Projeto) - que é escrita em XML.
===* 2. Por que usar o Maven? *
Os principais recursos do Maven são:
-
configuração simples do projeto que segue as práticas recomendadas: O Maven tenta evitar o máximo de configuração possível, fornecendo modelos de projeto (chamados archetypes)
-
gerenciamento de dependências: inclui atualização automática, download e validação da compatibilidade, além de relatar o fechamento de dependências (também conhecidas como dependências transitivas)
-
isolamento entre dependências do projeto e plug-ins: com o Maven, as dependências do projeto são recuperadas dos repositórios dependency enquanto as dependências de qualquer plugin são recuperadas dos repositórios _plugin, _ resultando em menos conflitos quando os plugins começam a baixar dependências adicionais
-
Sistema de repositório central: As dependências do projeto podem ser carregadas a partir do sistema de arquivos local ou repositórios públicos, como Maven Central
*Para aprender a instalar o Maven no seu sistema, verifique o link:/install-maven-on-windows-linux-mac [este tutorial sobre Baeldung].*
*3. Modelo de Objeto do Projeto *
A configuração de um projeto do Maven é feita por meio de um POM (Project Object Model) _, representado por um arquivo _pom.xml. O POM descreve o projeto, gerencia dependências e configura plugins para a construção do software.
O POM também define os relacionamentos entre os módulos de projetos com vários módulos. Vejamos a estrutura básica de um arquivo POM típico:
<project>
<modelVersion>4.0.0</modelVersion>
<groupId>org.</groupId>
<artifactId>org.</artifactId>
<packaging>jar</packaging>
<version>1.0-SNAPSHOT</version>
<name>org.</name>
<url>http://maven.apache.org</url>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
//...
</plugin>
</plugins>
</build>
</project>
Vamos dar uma olhada mais de perto nessas construções.
====* 3.1 Identificadores de projeto *
O Maven usa um conjunto de identificadores, também chamados de coordenadas, para identificar exclusivamente um projeto e especificar como o artefato do projeto deve ser empacotado:
-
groupId - um nome base exclusivo da empresa ou grupo que criou o projeto
-
artifactId - um nome exclusivo do projeto
-
version - uma versão do projeto *packaging - um método de empacotamento (por exemplo, WAR _/ JAR / ZIP_)
Os três primeiros (groupId: artifactId: version) se combinam para formar o identificador exclusivo e são o mecanismo pelo qual você especifica quais versões de bibliotecas externas (por exemplo, JARs) que seu projeto utilizará.
====* 3.2 Dependências *
Essas bibliotecas externas que um projeto usa são chamadas de dependências. O recurso de gerenciamento de dependências no Maven garante o download automático dessas bibliotecas de um repositório central, para que você não precise armazená-las localmente.
Esse é um recurso essencial do Maven e oferece os seguintes benefícios:
-
usa menos armazenamento, reduzindo significativamente o número de downloads de repositórios remotos
-
faz o check-out de um projeto mais rápido
-
fornece uma plataforma eficaz para a troca de artefatos binários dentro da sua organização e além, sem a necessidade de criar artefatos a partir da fonte todas as vezes
Para declarar uma dependência em uma biblioteca externa, você precisa fornecer o groupId, artifactId e a version da biblioteca. Vamos dar uma olhada em um exemplo:
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>4.3.5.RELEASE</version>
</dependency>
À medida que o Maven processa as dependências, ele baixa a biblioteca do Spring Core no seu repositório local do Maven.
3.3 Repositórios
Um repositório no Maven é usado para armazenar artefatos de construção e dependências de vários tipos. O repositório local padrão está localizado na pasta .m2/repository, no diretório inicial do usuário.
Se um artefato ou um plug-in estiver disponível no repositório local, o Maven o utilizará. Caso contrário, ele é baixado de um repositório central e armazenado no repositório local. O repositório central padrão é Maven Central.
Algumas bibliotecas, como o servidor JBoss, não estão disponíveis no repositório central, mas estão disponíveis em um repositório alternativo. Para essas bibliotecas, você precisa fornecer a URL para o repositório alternativo dentro do arquivo pom.xml:
<repositories>
<repository>
<id>JBoss repository</id>
<url>http://repository.jboss.org/nexus/content/groups/public/</url>
</repository>
</repositories>
*Observe que você pode usar vários repositórios em seus projetos.*
3.4 Propriedades
As propriedades personalizadas podem ajudar a facilitar a leitura e a manutenção do arquivo pom.xml. No caso de uso clássico, você usaria propriedades customizadas para definir versões para as dependências do seu projeto.
*As propriedades do Maven são espaços reservados para valores e estão acessíveis em qualquer lugar dentro de um _pom.xml_ usando a notação _ $ \ {name} _* , onde _name_ é a propriedade.
Vamos ver um exemplo:
<properties>
<spring.version>4.3.5.RELEASE</spring.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring.version}</version>
</dependency>
</dependencies>
Agora, se você deseja atualizar o Spring para uma versão mais recente, precisará alterar apenas o valor dentro da marca de propriedade <spring.version> e todas as dependências que usam essa propriedade em suas marcas _ <versão> _ serão atualizadas.
As propriedades também são frequentemente usadas para definir variáveis de caminho de construção:
<properties>
<project.build.folder>${project.build.directory}/tmp/</project.build.folder>
</properties>
<plugin>
//...
<outputDirectory>${project.resources.build.folder}</outputDirectory>
//...
</plugin>
* 3.5 Construir*
A seção build também é uma seção muito importante do Maven POM. Ela fornece informações sobre o Maven goal padrão, o diretório do projeto compilado e o nome final do aplicativo. A seção build padrão é assim:
<build>
<defaultGoal>install</defaultGoal>
<directory>${basedir}/target</directory>
<finalName>${artifactId}-${version}</finalName>
<filters>
<filter>filters/filter1.properties</filter>
</filters>
//...
</build>
*A pasta de saída padrão para artefatos compilados é nomeada _target_ e o nome final do artefato compactado consiste em _artifactId_ e _version_, mas você pode alterá-lo a qualquer momento.*
3.6 Usando Profiles
Outro recurso importante do Maven é o suporte a profiles. Um profile é basicamente um conjunto de valores de configuração. Usando profiles, você pode personalizar a construção para diferentes ambientes, como Produção/Teste/Desenvolvimento:
<profiles>
<profile>
<id>production</id>
<build>
<plugins>
<plugin>
//...
</plugin>
</plugins>
</build>
</profile>
<profile>
<id>development</id>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<build>
<plugins>
<plugin>
//...
</plugin>
</plugins>
</build>
</profile>
</profiles>
Como você pode ver no exemplo acima, o perfil padrão está definido como development. Se você deseja executar o production profile, pode usar o seguinte comando Maven:
mvn clean install -Pproduction
*4. Ciclos de vida do Maven Build *
Toda compilação do Maven segue um lifecycle especificado. Você pode executar vários lifecycle goals, incluindo aqueles para compilar o código do projeto, criar um package, _ e _install o arquivo no repositório de dependência local do Maven.
====* 4.1 Fases do ciclo de vida *
A lista a seguir mostra as fases mais importantes do lifecycle do Maven:
-
validate - verifica a correção do projeto
-
compile - compila o código fonte fornecido em artefatos binários
-
test - executa testes de unidade
-
package - empacota o código compilado em um arquivo morto
-
integration-test - executa testes adicionais, que exigem o empacotamento
-
verify - verifica se o pacote é válido
-
install - instala o arquivo do pacote no repositório local do Maven *deploy - implanta o arquivo do pacote em um servidor ou repositório remoto
====* 4.2 Plugins e Goals *
Um Maven plugin é uma coleção de um ou mais goals. Os objetivos são executados em fases, o que ajuda a determinar a ordem em que os goals são executados.
A rica lista de plug-ins oficialmente suportados pelo Maven está disponível em here. Há também um artigo interessante sobre como vincular:/executable-jar-with-maven [construa um JAR executável no Baeldung] usando vários plugins.*
Para entender melhor quais goals são executados em quais fases, por padrão, consulte default Maven lifecycle bindings.
Para passar por qualquer uma das fases acima, basta chamar um comando:
mvn <phase>
Por exemplo, mvn clean install removerá os arquivos jar/war/zip criados anteriormente e as classes compiladas (_clean) _ e executará todas as fases necessárias para instalar o novo archive (_install) _.
*Observe que os _goals_ fornecidos pelo _plugins_ podem ser associados a diferentes fases do _lifecycle _.*
*5. Seu primeiro projeto Maven *
Nesta seção, usaremos a funcionalidade de linha de comando do Maven para criar um projeto Java.
====* 5.1. Gerando um projeto Java simples *
Para construir um projeto Java simples, vamos executar o seguinte comando:
mvn archetype:generate
-DgroupId=org.
-DartifactId=org..java
-DarchetypeArtifactId=maven-archetype-quickstart
-DinteractiveMode=false
O groupId é um parâmetro que indica o grupo ou indivíduo que criou um projeto, que geralmente é um nome de domínio da empresa invertido. O artifactId é o nome do pacote base usado no projeto e usamos o _archetype padrão.
Como não especificamos a versão e o tipo de embalagem, eles serão definidos com os valores padrão - a versão será definida como 1.0-SNAPSHOT, _ e a embalagem será definida como _jar.
*Se você não souber quais parâmetros fornecer, sempre poderá especificar __interactiveMode __ = _ true_, para que o Maven solicite todos os parâmetros necessários.*
Após a conclusão do comando, temos um projeto Java contendo uma classe App.java, que é apenas um programa simples "Hello World", na pasta src/main/java.
Também temos um exemplo de classe de teste em src/test/java. O pom.xml deste projeto será semelhante a este:
<project>
<modelVersion>4.0.0</modelVersion>
<groupId>org.</groupId>
<artifactId>org..java</artifactId>
<packaging>jar</packaging>
<version>1.0-SNAPSHOT</version>
<name>org..java</name>
<url>http://maven.apache.org</url>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.1.2</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>
Como você pode ver, a dependência junit é fornecida por padrão.
5.2 Compilando e empacotando um projeto
O próximo passo é compilar o projeto:
mvn compile
O Maven percorrerá todas as fases lifecycle necessárias para a fase compile para criar as fontes do projeto. Se você deseja executar apenas a fase test, pode usar:
mvn test
Agora vamos chamar a fase package, que produzirá o arquivo jar do archive compilado:
mvn package
5.3. Executando um aplicativo
Finalmente, vamos executar nosso projeto Java com o exec-maven-plugin. Vamos configurar os plugins necessários no pom.xml:
<build>
<sourceDirectory>src</sourceDirectory>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.6.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>1.5.0</version>
<configuration>
<mainClass>org..java.App</mainClass>
</configuration>
</plugin>
</plugins>
</build>
O primeiro plugin, maven-compiler-plugin, é responsável por compilar o código-fonte usando Java versão 1.8. O exec-maven-plugin pesquisa o mainClass em nosso projeto.
Para executar o aplicativo, executamos o seguinte comando:
mvn exec:java
*6. Projetos com vários módulos *
O mecanismo no Maven que lida com projetos com vários módulos (também chamados de aggregator projects) é chamado de Reactor.
O Reactor coleta todos os módulos disponíveis para compilar, depois classifica os projetos na ordem correta de compilação e, finalmente, os constrói um por um.
Vamos ver como criar um projeto pai com vários módulos.
====* 6.1 Criar projeto pai *
Primeiro de tudo, precisamos criar um projeto pai. Para criar um novo projeto com o nome _parent-project, usamos o seguinte comando:
mvn archetype:generate -DgroupId=org. -DartifactId=parent-project
Em seguida, atualizamos o tipo de embalagem dentro do arquivo pom.xml para indicar que este é um módulo parent:
<packaging>pom</packaging>
====* 6.2 Criar projetos de submódulo *
Na próxima etapa, criamos projetos de submódulo a partir do diretório parent-project:
cd parent-project
mvn archetype:generate -DgroupId=org. -DartifactId=core
mvn archetype:generate -DgroupId=org. -DartifactId=service
mvn archetype:generate -DgroupId=org. -DartifactId=webapp
Para verificar se criamos os submódulos corretamente, procuramos no arquivo parent-project pom.xml, onde devemos ver três módulos:
<modules>
<module>core</module>
<module>service</module>
<module>webapp</module>
</modules>
Além disso, uma seção pai será adicionada no pom.xml de cada submódulo:
<parent>
<groupId>org.</groupId>
<artifactId>parent-project</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
====* 6.3. Ativar gerenciamento de dependências no projeto pai *
O gerenciamento de dependências é um mecanismo para centralizar as informações de dependência de um projeto pai do módulo muti e de seus filhos.
Quando você possui um conjunto de projetos ou módulos que herdam um pai comum, é possível colocar todas as informações necessárias sobre as dependências no arquivo pom.xml comum. Isso simplificará as referências aos artefatos nos POMs filhos.
Vamos dar uma olhada no exemplo de pom.xml de um pai:
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>4.3.5.RELEASE</version>
</dependency>
//...
</dependencies>
</dependencyManagement>
Ao declarar a versão spring-core no pai, todos os sub-módulos que dependem de spring-core podem declarar a dependência usando apenas o groupId e artifactId, e a versão será herdada:
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
</dependency>
//...
</dependencies>
Além disso, você pode fornecer exclusões para gerenciamento de dependências no pom.xml do pai, para que bibliotecas específicas não sejam herdadas pelos módulos filhos:
<exclusions>
<exclusion>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
</exclusion>
</exclusions>
Por fim, se um módulo filho precisar usar uma versão diferente de uma dependência gerenciada, você poderá substituir a versão gerenciada no arquivo pom.xml da criança:
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>4.2.1.RELEASE</version>
</dependency>
*Observe que, embora os módulos filhos sejam herdados do projeto pai, um projeto pai não possui necessariamente nenhum módulo agregado. Por outro lado, um projeto pai também pode agregar projetos que não herdam dele.*
Para obter mais informações sobre herança e agregação por favor, consulte esta documentação.
6.4. Atualizando os submódulos e construindo um projeto
Podemos alterar o tipo packaging de cada submódulo. Por exemplo, vamos alterar o packaging do módulo webapp para WAR atualizando o arquivo pom.xml:
<packaging>war</packaging>
Agora podemos testar a compilação do nosso projeto usando o comando mvn clean install. A saída dos logs do Maven deve ser semelhante a esta:
[INFO] Scanning for projects...
[INFO] Reactor build order:
[INFO] parent-project
[INFO] core
[INFO] service
[INFO] webapp
//.............
[INFO] -----------------------------------------
[INFO] Reactor Summary:
[INFO] -----------------------------------------
[INFO] parent-project .................. SUCCESS [2.041s]
[INFO] core ............................ SUCCESS [4.802s]
[INFO] service ......................... SUCCESS [3.065s]
[INFO] webapp .......................... SUCCESS [6.125s]
[INFO] -----------------------------------------
7. Conclusão
Neste artigo, discutimos alguns dos recursos mais populares da ferramenta de compilação Apache Maven.
Todos os exemplos de código no Baeldung são criados usando o Maven, para que você possa facilmente verificar nosso GitHub website do projeto para ver várias configurações do Maven.