Maven 2 소개

Maven은 엔터프라이즈 Java 프로젝트를위한 인기있는 오픈 소스 빌드 도구로, 빌드 프로세스에서 많은 노력을 덜어 주도록 설계되었습니다. Maven은 예를 들어 Ant 또는 기존의 make 파일에서 사용되는 작업 기반 접근 방식이 아닌 프로젝트 구조 및 내용이 설명되는 선언적 접근 방식을 사용합니다. 이를 통해 회사 전체의 개발 표준을 시행하고 빌드 스크립트를 작성하고 유지하는 데 필요한 시간을 줄일 수 있습니다.

Maven 1에서 사용하는 선언적 라이프 사이클 기반 접근 방식은 많은 경우 기존 빌드 기술에서 근본적으로 벗어나 있으며 Maven 2는 이와 관련하여 훨씬 더 나아갑니다. 이 기사에서는 Maven 2의 기본 원칙 중 일부를 살펴본 다음 작업 예제를 단계별로 살펴 봅니다. Maven 2의 기본 사항부터 살펴 보겠습니다.

프로젝트 개체 모델

Maven 2 프로젝트의 핵심은 프로젝트 개체 모델 (또는 줄여서 POM)입니다. 여기에는 버전 관리 및 구성 관리, 종속성, 애플리케이션 및 테스트 리소스, 팀 구성원 및 구조 등에 대한 정보를 포함하여 프로젝트에 대한 자세한 설명이 포함되어 있습니다. POM은 프로젝트 홈 디렉토리 에있는 XML 파일 ( pom.xml ) 형식을 취합니다 . 간단한 pom.xml 파일은 다음과 같습니다.

 4.0.0 com.javaworld.hotels HotelDatabase war 1.0-SNAPSHOT Maven Quick Start Archetype //maven.apache.org   junit junit 3.8.1 test   

Maven 2 디렉토리 구조

Maven의 힘의 대부분은 권장하는 표준 관행에서 비롯됩니다. 이전에 Maven 프로젝트에서 작업 한 적이있는 개발자는 즉시 새 프로젝트의 구조와 구성에 익숙해 질 것입니다. 각 프로젝트에 대한 디렉토리 구조, 규칙 및 사용자 정의 된 Ant 빌드 스크립트를 재창조하는 데 시간을 낭비 할 필요가 없습니다. 특정 목적을 위해 특정 디렉토리 위치를 재정의 할 수 있지만 몇 가지 이유로 가능한 한 표준 Maven 2 디렉토리 구조를 존중해야합니다.

  • POM 파일을 더 작고 간단하게 만듭니다.
  • 프로젝트를 더 쉽게 이해하고 떠날 때 프로젝트를 유지해야하는 가난한 사람의 삶을 더 쉽게 만듭니다.
  • 플러그인 통합이 더 쉬워집니다.

표준 Maven 2 디렉토리 구조는 그림 1에 나와 있습니다. 프로젝트 홈 디렉토리에는 POM (pom.xml)과 두 개의 하위 디렉토리 (모든 소스 코드의 경우 src와 생성 된 아티팩트의 대상)가 있습니다.

src 디렉토리에는 여러 하위 디렉토리가 있으며 각 하위 디렉토리에는 명확하게 정의 된 용도가 있습니다.

  • src / main / java : Java 소스 코드가 여기에 있습니다 (이상하게도 충분합니다!)
  • src / main / resources : 애플리케이션에 필요한 기타 리소스
  • src / main / filters : 속성 파일 형식의 리소스 필터. 런타임에만 알려진 변수를 정의하는 데 사용할 수 있습니다.
  • src / main / config : 구성 파일
  • src / main / webapp : WAR 프로젝트의 웹 애플리케이션 디렉토리
  • src / test / java : 단위 테스트
  • src / test / resources : 단위 테스트에 사용할 리소스이지만 배포되지는 않습니다.
  • src / test / filters : 단위 테스트에 사용되지만 배포되지 않을 리소스 필터
  • src / site : Maven 프로젝트 웹 사이트를 생성하는 데 사용되는 파일

프로젝트 수명주기

프로젝트 라이프 사이클은 Maven 2의 핵심입니다. 대부분의 개발자는 컴파일, 테스트 및 배포와 같은 빌드 단계 개념에 익숙합니다. Ant에는 이와 같은 이름을 가진 대상이 있습니다. Maven 1에서는 해당 플러그인이 직접 호출됩니다. 예를 들어 Java 소스 코드를 컴파일하기 위해 java플러그인이 사용됩니다.

$maven java:compile

Maven 2에서이 개념은 잘 알려진 잘 정의 된 수명주기 단계 집합으로 표준화됩니다 (그림 2 참조). 플러그인을 호출하는 대신 Maven 2 개발자는 수명주기 단계를 호출합니다 $mvn compile..

더 유용한 Maven 2 수명주기 단계 중 일부는 다음과 같습니다.

  • generate-sources: 응용 프로그램에 필요한 추가 소스 코드를 생성합니다. 일반적으로 적절한 플러그인을 사용하여 수행됩니다.
  • compile: 프로젝트 소스 코드 컴파일
  • test-compile: 프로젝트 단위 테스트를 컴파일합니다.
  • test: src / test 디렉토리에서 단위 테스트 (일반적으로 JUnit 사용)를 실행합니다.
  • package: 배포 가능한 형식 (JAR, WAR 등)으로 컴파일 된 코드를 패키징합니다.
  • integration-test: 통합 테스트를 실행할 수있는 환경으로 필요한 경우 패키지를 처리하고 배포합니다.
  • install: 로컬 시스템의 다른 프로젝트에서 종속성으로 사용하기 위해 패키지를 로컬 저장소에 설치합니다.
  • deploy: 통합 또는 릴리스 환경에서 완료, 다른 개발자 및 프로젝트와 공유하기 위해 최종 패키지를 원격 저장소에 복사합니다.

다른 많은 수명주기 단계를 사용할 수 있습니다. 자세한 내용은 리소스를 참조하십시오.

이 단계는 Maven 2에서 권장하는 권장 사례의 이점을 보여줍니다. 개발자가 주요 Maven 2 수명주기 단계에 익숙해지면 Maven 프로젝트의 수명주기 단계에 익숙해 져야합니다.

라이프 사이클 단계는 작업을 수행하는 데 필요한 플러그인을 호출합니다. 수명주기 단계를 호출하면 이전 수명주기 단계도 자동으로 호출됩니다. 수명주기 단계는 수에 제한이 있고 이해하기 쉽고 잘 구성되어 있으므로 새로운 Maven 2 프로젝트의 수명주기에 익숙해지는 것이 쉽습니다.

전 이적 종속성

Maven 2의 하이라이트 중 하나는 전 이적 종속성 관리입니다. Linux 상자에서 urpmi 와 같은 도구를 사용한 적이 있다면 전 이적 종속성이 무엇인지 알게 될 것입니다. Maven 1에서는 애플리케이션에서 직접 또는 간접적으로 필요한 모든 JAR을 선언해야합니다. 예를 들어, Hibernate 애플리케이션에 필요한 JAR을 나열 할 수 있습니까? Maven 2를 사용하면 그럴 필요가 없습니다. Maven에 필요한 라이브러리 알려 주면 Maven이 라이브러리에 필요한 라이브러리를 처리합니다.

프로젝트에서 Hibernate를 사용한다고 가정 해보십시오. dependencies다음과 같이 pom.xml 의 섹션에 새 종속성을 추가하기 만하면 됩니다.

  hibernate hibernate 3.0.3 compile 

그리고 그게 다야! Hibernate 3.0.3을 실행하는 데 필요한 다른 JAR (및 버전)을 알기 위해 주위를 둘러 볼 필요가 없습니다. Maven이 해줄 것입니다!

Maven 2의 종속성에 대한 XML 구조는 Maven 1에서 사용 된 것과 유사합니다. 주요 차이점은 scope다음 섹션에서 설명 하는 태그입니다.

종속성 범위

실제 엔터프라이즈 응용 프로그램에서는 배포 된 응용 프로그램에 모든 종속성을 포함 할 필요가 없습니다. 일부 JAR은 단위 ​​테스트에만 필요하고 다른 일부는 애플리케이션 서버에서 런타임에 제공됩니다. 종속성 범위 지정 이라는 기술을 사용하여 Maven 2에서는 실제로 필요할 때만 특정 JAR을 사용할 수 있으며 필요하지 않은 경우 클래스 경로에서 제외 할 수 있습니다.

Maven은 네 가지 종속성 범위를 제공합니다.

  • compile: A compile-scope dependency is available in all phases. This is the default value.
  • provided: A provided dependency is used to compile the application, but will not be deployed. You would use this scope when you expect the JDK or application server to provide the JAR. The servlet APIs are a good example.
  • runtime: Runtime-scope dependencies are not needed for compilation, only for execution, such as JDBC (Java Database Connectivity) drivers.
  • test: Test-scope dependencies are needed only to compile and run tests (JUnit, for example).

Project communication

An important part of any project is internal communication. While it is not a silver bullet, a centralized technical project Website can go a long way towards improving visibility within the team. With minimal effort, you can have a professional-quality project Website up and running in very little time.

This takes a whole new dimension when the Maven site generation is integrated into a build process using continuous integration or even automatic nightly builds. A typical Maven site can publish, on a daily basis:

  • General project information such as source repositories, defect tracking, team members, etc.
  • Unit test and test coverage reports
  • Automatic code reviews and with Checkstyle and PMD
  • Configuration and versioning information
  • Dependencies
  • Javadoc
  • Source code in indexed and cross-referenced HTML format
  • Team member list
  • And much more

Once again, any Maven-savvy developer will immediately know where to look to become familiar with a new Maven 2 project.

A practical example

Now that we have seen a few of the basic notions used in Maven 2, let's see how it works in the real world. The rest of this tutorial examines how we would use Maven 2 on a simple Java Enterprise Edition project. The demo application involves an imaginary (and simplified) hotel database system. To demonstrate how Maven handles dependencies between projects and components, this application will be built using two components (see Figure 3):

  • A business logic component: HotelDatabase.jar
  • A Web application component: HotelWebApp.war

You can download the source code to follow along with the tutorial in Resources.

Set up your project environment

We start by configuring your work environment. In real-world projects, you will often need to define and configure environment or user-specific parameters that should not be distributed to all users. If you are behind a firewall with a proxy, for example, you need to configure the proxy settings so that Maven can download JARs from repositories on the Web. For Maven 1 users, the build.properties and project.properties files do this job. In Maven 2, they have been replaced by a settings.xml file, which goes in the $HOME/.m2 directory. Here is an example:

     http scott tiger 8080 my.proxy.url    

Create a new project with the archetype plug-in

The next step is to create a new Maven 2 project template for the business logic component. Maven 2 provides the archetype plug-in, which builds an empty Maven 2-compatible project directory structure. This plug-in proves convenient for getting a basic project environment up and running quickly. The default archetype model will produce a JAR library project. Several other artifact types are available for other specific project types, including Web applications, Maven plug-ins, and others.

Run the following command to set up your HotelDatabase.jar project:

mvn archetype:create -DgroupId=com.javaworld.hotels - DartifactId=HotelDatabase -Dpackagename=com.javaworld.hotels

Now you have a brand new Maven 2 project directory structure. Switch to the HotelDatabase directory to continue the tutorial.

Implementing the business logic

이제 비즈니스 로직을 구현합니다. Hotel클래스는 간단한 자바 빈즈이다. 이 HotelModel클래스 findAvailableCities()는 사용 가능한 도시를 나열하는 findHotelsByCity()메서드 와 지정된 도시의 모든 호텔을 나열 하는 메서드의 두 가지 서비스를 구현 합니다. 간단한 메모리 기반 HotelModel클래스 구현은 다음과 같습니다.

package com.javaworld.hotels.model;

import java.util.ArrayList; import java.util.List;

import com.javaworld.hotels.businessobjects.Hotel;

public class HotelModel {

/** * The list of all known cities in the database. */ private static String[] cities = { "Paris", "London", }; /** * The list of all hotels in the database. */ private static Hotel[] hotels = { new Hotel("Hotel Latin","Quartier latin","Paris",3), new Hotel("Hotel Etoile","Place de l'Etoile","Paris",4), new Hotel("Hotel Vendome","Place Vendome","Paris",5), new Hotel("Hotel Hilton","Trafalgar Square","London",4), new Hotel("Hotel Ibis","The City","London",3), }; /** * Returns the hotels in a given city. * @param city the name of the city * @return a list of Hotel objects */ public List findHotelsByCity(String city){ List hotelsFound = new ArrayList(); for(Hotel hotel : hotels) { if (hotel.getCity().equalsIgnoreCase(city)) { hotelsFound.add(hotel); } } return hotelsFound; } /** * Returns the list of cities in the database which have a hotel. * @return a list of city names */ public String[] findAvailableCities() { return cities; } }