Въведение в 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: Изпълнява модулните тестове (обикновено се използва JUnit) в директорията src / test
  • package: Пакетира компилирания код в неговия разпространим формат (JAR, WAR и др.)
  • integration-test: Обработва и разгръща пакета, ако е необходимо, в среда, в която могат да се изпълняват тестове за интеграция
  • install: Инсталира пакета в локалното хранилище за използване като зависимост в други проекти на вашата локална машина
  • deploy: Извършено в среда за интеграция или освобождаване, копира окончателния пакет в отдалеченото хранилище за споделяне с други разработчици и проекти

Предлагат се много други фази на жизнения цикъл. Вижте Ресурси за повече подробности.

Тези фази илюстрират предимствата на препоръчаните практики, насърчавани от Maven 2: след като разработчикът се запознае с основните фази на жизнения цикъл на Maven 2, той трябва да се чувства спокойно с фазите на жизнения цикъл на всеки проект на Maven.

Фазата на жизнения цикъл извиква приставките, които са му необходими, за да свършат работата. Извикването на фаза на жизнения цикъл автоматично извиква и всички предишни фази на жизнения цикъл. Тъй като фазите на жизнения цикъл са ограничени по брой, лесни за разбиране и добре организирани, запознаването с жизнения цикъл на нов проект Maven 2 е лесно.

Преходни зависимости

Един от акцентите на Maven 2 е преходното управление на зависимостта. Ако някога сте използвали инструмент като urpmi на Linux кутия, ще знаете какви са преходните зависимости. С Maven 1 трябва да декларирате всеки JAR, който ще е необходим, пряко или косвено, от вашето приложение. Например можете ли да изброите JAR-ите, необходими на приложение за хибернация? С Maven 2 не е нужно. Просто кажете на Maven от кои библиотеки имате нужда и Maven ще се погрижи за библиотеките, от които се нуждаят вашите библиотеки (и т.н.).

Да предположим, че искате да използвате Hibernate във вашия проект. Просто бихте добавили нова зависимост към dependenciesраздела в pom.xml, както следва:

  hibernate hibernate 3.0.3 compile 

И това е! Не е нужно да търсите наоколо, за да знаете в кои други JAR-и (и в кои версии) трябва да стартирате Hibernate 3.0.3; Maven ще го направи вместо вас!

XML структурата за зависимости в Maven 2 е подобна на тази, използвана в Maven 1. Основната разлика е scopeтагът, който е обяснен в следващия раздел.

Обхвати на зависимостта

В реално корпоративно приложение може да не се наложи да включите всички зависимости в внедреното приложение. Някои JAR са необходими само за модулно тестване, докато други ще бъдат предоставени по време на изпълнение от сървъра на приложенията. Използвайки техника, наречена обхват на зависимостите , Maven 2 ви позволява да използвате определени JAR само когато наистина се нуждаете от тях и ги изключва от пътя на класа, когато не.

Maven предоставя четири обхвата на зависимост:

  • compile: Зависимостта от обхвата на компилация е достъпна във всички фази. Това е стойността по подразбиране.
  • provided: Осигурена зависимост се използва за компилиране на приложението, но няма да бъде внедрена. Бихте използвали този обхват, когато очаквате JDK или сървърът на приложения да предоставят JAR. API на сървлета са добър пример.
  • runtime: Зависимостите от обхвата на изпълнение не са необходими за компилация, а само за изпълнение, като например драйвери за JDBC (Java Database Connectivity).
  • test: Зависимостите от тестовия обхват са необходими само за компилиране и стартиране на тестове (например JUnit).

Проектна комуникация

Важна част от всеки проект е вътрешната комуникация. Въпреки че не е сребърен куршум, уебсайтът на централизирания технически проект може да направи дълъг път към подобряване на видимостта в екипа. С минимални усилия можете да създадете и стартирате уебсайт за професионално качество на уебсайта за много малко време.

Това отнема съвсем ново измерение, когато генерацията на сайтове на Maven е интегрирана в процес на компилация, използвайки непрекъсната интеграция или дори автоматични нощни компилации. Типичен сайт на Maven може да публикува всеки ден:

  • Обща информация за проекта като хранилища на източници, проследяване на дефекти, членове на екипа и др.
  • Единични тестове и отчети за покритие на теста
  • Автоматичен преглед на кода и с Checkstyle и PMD
  • Информация за конфигурация и версии
  • Зависимости
  • Javadoc
  • Изходен код в индексиран и препратен HTML формат
  • Списък на членовете на екипа
  • И още много

Още веднъж всеки разумен разработчик на Maven веднага ще разбере къде да търси, за да се запознае с нов проект на Maven 2.

Практически пример

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класа е проста JavaBean. В 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; } }