Lập trình quán

Thảo luận về lập trình

Maven căn bản

Posted by thinhnv2 on April 14, 2013

1. Maven là gì:

Hiểu một cách đơn giản maven là một công cụ build phổ biến trong thế giới lập trình Java. Theo định nghĩa chính thức Apache Maven ((http://maven.apache.org/) ), maven là công cụ toàn diện về quản lý dự án phần mềm. Dựa trên mô hình đối tượng dự án  (project object model – POM) maven có thể quản lý build, tạo báo cáo và tài liệu cho dự án từ thông tin lưu trữ tập trung (trong file pom)

2. Cài đặt maven (đảm bảo máy phải có java trước) áp dụng cho máy chạy windows

a.  Vào trang chủ của maven để download, tính đến thời điểm bài viết này phiên bản mới nhất là 3.0.5

download_maven

b. Giải nén ra thư mục vừa download vào vị trí mà bạn dễ quản lý:

cau_truc_thu_muc_maven

c.  Thiết lập biến môi trường trỏ tới maven

Click chuột phải vào Computer chọn Property:

moi_truong1

Tiếp theo chọn Advaned property

moi_truong_2

Tiếp chọn Environment variables:

moi_truong_3

Chọn new… để tạo biến môi trường mới

moi_truong_4

Điền thông tin đúng như sau, phần đường dẫn thay đổi theo vị trí bạn vừa giải nén maven

moi_truong_5

Điền thông tin đúng như sau, phần đường dẫn thay đổi theo vị trí bạn vừa giải nén maven

moi_truong_6

Chú ý bạn nhập %MAVEN_HOME% phân tách với các biến khác bằng ;

Mở command dos để test cài đặt:

Đánh mvn -v nếu xuất hiện thông tin về maven như sau việc cài đặt thành công, nếu xuất hiện lỗi kiểm tra lại xem biến môi trường bạn gõ đúng không:

test_installation

3. Tạo project HelloWorld với Maven

3. Tạo dự án

Chúng ta sẽ tạo project maven đầu tiên sử dụng cơ chế archetype của maven. Archetype trong maven được định nghĩa như là mẫu hay mô hình gốc mà từ đó tất cả các dự án cùng kiểu có thể tạo ra. Do vậy nó được xem như là template của dự án. Mở command line nhập như sau:

simple_project1

Mvn ở đây được gọi là lệnh của maven, archetype:generate được gọi là đích Maven để tạo ra một dự án mẫu. Các cặp  -Dname=value là những đối số được đấy tới đích.

Sau gõ enter maven sẽ tải những file cần thiết từ server máy bạn phải kết nối với mạng khi sử dụng maven

Nếu xuất hiện dòng yêu cầu nhập số, gõ Enter để lấy số mặc định (archetype tạo ra nhiều template dự án ở đây ta sẽ tạo ra một dự án java căn bản mặc định)

simple_project2

Gõ enter nếu yêu cầu nhập thông tin version

simple_project3

Gõ enter để confirm lại thông tin:

simple_project4

Nếu màn hình dos báo build success bạn đã tạo ra dự án maven thành công:

simple_project5

Maven đã tạo ra thư mục và file ở vị trí chạy dòng lệnh dos, đây là cấu trúc thư mục vừa tạo ra:

simple_project_structure

1 Maven Archetype plugin đã tạo một thư mục simple phù hợp với tham số artifactId. Đây gọi là thư mục gốc của project.

2 Mọi project maven đều phải có mô hình đối tượng dự án (Project Object Model – POM) thể hiện trong một file là pom.xml.  File này mô tả dự án, cấu hình plugin và khai báo sự phụ thuộc của dự án.

3 Source code và tài nguyên của dự án (chẳng hạn như ảnh) được đặt trong thư mục src/main. Trong tình huống đơn giản này chỉ bao gồm một vài lớp java. Trong các dự án có thể bao gồm gốc của một dự án web. Trong dự án java các lớp java nằm trong thư mục src/main/java và tài nguyên nằm trong thư mục src/main/resources

4 Test case của dự án nằm trong thư mục src/test/. Dưới thư mục các lớp java chẳng hạn JUnit hoặc TestNG được đặt trong thư mục src/test/java và tài nguyên nằm trong src/test/resources

Đây là file Java tạo ra:

App

Như vậy archetype đã tạo một dự án đơn giản nhất: in ra dòng Hello World ra thiết bị xuất chuẩn.

3.2 Build dự án vừa tạo ra

Trên command line, gõ cd simple để di chuyển vào thư mục gốc của dự án sau đó gõ mvn install (sau khi gõ lệnh này maven sẽ sinh ta thư mục target chứa những file được build)

simple_build

Như vậy bạn đã vừa tạo biên dịch, kiểm tra đóng gói và cài đặt dự án Maven đơn giản nhất. Để chứng tỏ chương trình vừa tạo ra làm việc được chạy từ dòng lệnh:

simple_result

3.3 Kiểm tra file pom vừa tạo ra

Mở file pom.xml trong dự án simple vừa tạo.

simple_pom

File pom chứa tất cả các thông tin về dự án. Hiểu file pom là điều quan trọng đối với người mới tiếp cận maven.

Chúng ta sẽ xem từng phần tử trong file pom để giúp bạn làm quen với cơ bản về POM:

  • project Đây là phần tử trên cùng trong tất cả các file pom.xml
  • modelVersion Phần tử này chỉ ra phiên bản của mô hình đối tượng mà file POM sử dụng. Phiên bản của bản thân mô hình đối tượng rất ít thay đổi nhưng nó là bắt buộc  để đảm bảo tính ổn định khi các nhà phát triển Maven nghĩ rằng nó cần thiết để thay đổi mô hình.
  • groupId : Phần tử này chỉ ra định danh duy nhất của nhóm hoặc tổ chức tạo ra dự án. groupId là một trong định danh chính của một dự án được đặt tên dựa theo domain đầy đủ của tổ chức của bạn. Ví dụ ở đây: org.sonatype.mavenbook.simple
  • artifactId: Phần tử này tên gốc của artifact chính được tạo ra bởi dự án. Artifact chính cho một dự án chính điển hình là một file Jar. Một artifact điển hình được tạo ra bởi Maven sẽ có hình thức <artifactId>-<version>.<extension> (ví dụ simple-1.0-SNAPSHOT.jar trong tình huống dự án này).  (Định nghĩa về artifact: trong thuật ngữ phần mềm nói chung, một ‘artifact’ là một thứ gì đó được tạo ra bởi quá trình phát triển phần mềm, cho dù là một tài liệu liên quan đến phần mềm hoặc một file thực thi. Trong thuật ngữ của Maven, artifact là kết quả của quá trình build trong maven, nói chung là một fie jar, hay war trong dự án web hoặc một file thực thi khác. Một artifact trong maven được xác định bởi một hệ tọa độ gồm groupId, artifactId và version. Maven sử dụng groupId, artifactId và version để xác định sự phụ thuộc (thường là các file jar khác ) cần để build và chạy code của bạn.)
  • package: Phần tử này chỉ kiểu đóng gói được sử dụng bởi artifact này (ví dụ JAR, WAR, EAR vân vân)
  • version: Phần tử này chỉ ra phiên bản của artifact được tạo ra bởi dự án. Bạn sẽ thường xuyên nhìn thấy chữ SNAPSHOT trong phiên bản, chỉ ra rằng dự án đang ở trong giai đoạn phát triển.
  • name: Phần tử này chỉ ra tên của dự án. Điều này được sử dụng trong tài liệu được tạo ra bởi maven.
  • url:Phần tử này chỉ ra trang của dự án có thể được tìm thấy. Điều này được sử dụng trong tài liệu được tạo ra bởi maven.
  • description: Phần tử này cung cấp phần mô tả ngắn gọn về dự án. Điều này được sử dụng trong tài liệu được tạo ra bởi maven.

4. Cài đăt m2eclipse (plugin của maven cho eclipse)

Vào trang http://eclipse.org/m2e/download/  tìm link update site của m2eclipse rồi cài đặt như bình thường cho các plugin của eclipse:

m2eclipse_install

5. Một vài khái niệm căn bản về maven:

5.1 Plugin và đích của maven:

Trong ví dụ trước chúng ta đã đánh mvn archetype:generate. Ở đây archetype là plugin của maven còn generate là đích của plugin. Đích là một đơn vị công việc của maven, một plugin có thể bao gồm nhiều đích. Một vài ví dụ về plugin của maven như plugin jar có đích để tạo file jar.

5.2 Vòng đời trong maven: Maven lifecycle

Chúng ta đã chạy mvn install trong ví dụ trên. Dòng lệnh này không chỉ ra plugin mà chỉ ra một một giai đoạn trong vòng đời của Maven thường được gọi là vòng đời build của maven. Vòng đời build bao gồm chuỗi thứ tự các giai đoạn tham gia vào quá trình build của dự án. Các plugin có thể gắn vào các giai đoạn này. Thông thường khi thực thi một giai đoạn trong vòng đời build nó sẽ thực thi các giai đoạn trước đó. Ví dụ trong tình huống này các giai đoạn trước install sẽ được gọi bao gồm các giai đoạn compile source code thành các file classes với đích compile của plugin compiler.
Đây là một giai đoạn và đích của các plugin gắn kèm (đích của plugin thường được gọi dưới dạng plugin:đích)
sample_lifecycle

5.3 Tọa độ trong Maven:

Như đã được đề cập ở trên thông thường một dự án được xác định bởi 3 thông số khai báo trong file pom.xml là groupId, artifactId và version. Các thông số này tạo thành tọa độ của maven và không có dự án nào trong maven giống nhau về cả 3 thông số này. Tóm lại tọa độ trong maven sẽ được diễn tả như sau groupId:artifactId:version, ví dụ: mavenbook:my-app:jar:1.0-SNAPSHOT

5.4 Repository trong Maven (Nơi lưu trữ artifact của maven):

Maven sử dụng một nơi lưu trữ từ xa(ví dụ http://repo1.maven.org/) để lưu trữ plugin và các thư viện công cộng dùng chung. Và nó sẽ download khi dự án bạn cần về một nơi lưu trữ cục bộ (ví dụ C:\Users\Admin\.m2\repository) và nếu local repository đã có rồi thì maven không cần download nữa.

5.5 Quản lý sự phụ thuộc trong maven:

Ở dự án bạn tạo trước đó bạn đã khai báo phụ thuộc vào jUnit (với tọa độ junit: junit:3.8.1) maven sẽ dựa thông tin này để download về local nếu chưa có. Quản lý sự phụ thuộc là một đặc điểm tuyệt vời trong Maven. Nếu dự án của bạn phụ thuộc vào thư viện mà thư viện này lại phụ thuộc vào 5 hoặc 10 thư viện khác (ví dụ như Spring) bạn chỉ cần khai thư viện mà bạn phụ thuộc trực tiếp việc còn lại Maven sẽ tự lo cho bạn.

6. Tạo dự án maven bằng m2eclipse:

Phần này chúng ta sẽ tạo ra một project về thời tiết sử dụng Yahoo! Weather RSS Feed bằng m2eclipse. Ứng dụng sẽ lấy zipcode do người sử dụng nhập vào và truy xuất dữ liệu từ Yahoo . Sau đó phân tích kết quả và in kết quả ra màn hình.
Mở eclipse (bạn phải cài đặt m2eclipse như hướng dẫn ở trên.). Chọn New Project chọn kiểu project là Maven:
weather_1

Click Next, ở màn hình tiếp theo, tick vào checkbox create a simple project (dự án mà chúng ta muốn tạo vẫn chỉ là ứng java căn bản nên không cần chọn template khác):

weather_2
Click vào Next chúng ta sẽ chuyển sang màn hình điền thông tin quan trọng cho dự án maven, nhập vào thông tin như bên dưới:
weather_3

Cuối cùng click Finish để hoàn tất quá trình tạo project
Như chúng ta đã biết plugin Compiler sẽ biên dịch tất cả source code java và copy file classes vào thư mục target/classes. Mặc định plugin giả định code java phải tuân thủ Java 1.3 và nhắm tới máy ảo Java 1.1. Chúng ta sẽ thay đổi điều này để hướng tới Java 1.5.
Mở file pom.xml của dự án vừa tạo, chuyển sang tab pom.xml để xem nội dung của file:

tab_pom

Bổ sung thêm phần build như sau:
weather_4

Ứng dụng thời tiết của chúng ta có 3 nhiệm vụ: truy xuất dữ liệu XML từ Yahoo Weather, phân tich dữ liệu và xuất thông tin đã được định dạng ra màn hình. Để phân tích file XML chúng ta cần đến thư viện Dom4j, Jaxen. Velocity là thư viện để định dạng kết quả ra màn hình. Log4j để viết ra log. Để bổ sung sự phụ thuộc vào thư viện này, chúng ta sẽ cần tới các thông tin groupId, artifactId, versionId của thư viện. Chúng ta vào trang http://mvnrepository.com/ gõ tên thư viện chúng ta sẽ lấy thông tin mà thư viện chúng ta cần.

search_2
Chọn phiên bản mới và ổn định nhất:
search_3
Copy phần thông tin groupId, artifactId và version vào file pom.xml trong eclipse:
search_4
Làm tương tự cho các thư viện khác, file pom.xml sau khi thêm sự phụ thuộc:
add_dependency

Chú ý: khi gõ code trong file pom.xml tận dụng gợi ý code của eclipse.
Lớp đầu tiên chúng ta sẽ là lớp Weather chứa thông tin vị trí của báo cáo thời tiết và các thông tin khác như độ ẩm. Tất cả các lớp chúng ta tạo sẽ nằm trong package com.sonatype.mavenbook. Nhắc lại source/main/java trong maven chứa code java.

public class Weather {

private String city;

private String region;

private String country;

private String condition;

private String temp;

private String chill;

private String humidity;

public Weather() {

}

/**

* <br>

* @return  city

*/

public String getCity() {

return city;

}

/**

*<br>

* @param city the city to set

*/

public void setCity(String city) {

this.city = city;

}

/**

* <br>

* @return  region

*/

public String getRegion() {

return region;

}

/**

*<br>

* @param region the region to set

*/

public void setRegion(String region) {

this.region = region;

}

/**

* <br>

* @return  country

*/

public String getCountry() {

return country;

}

/**

*<br>

* @param country the country to set

*/

public void setCountry(String country) {

this.country = country;

}

/**

* <br>

* @return  condition

*/

public String getCondition() {

return condition;

}

/**

*<br>

* @param condition the condition to set

*/

public void setCondition(String condition) {

this.condition = condition;

}

/**

* <br>

* @return  temp

*/

public String getTemp() {

return temp;

}

/**

*<br>

* @param temp the temp to set

*/

public void setTemp(String temp) {

this.temp = temp;

}

/**

* <br>

* @return  chill

*/

public String getChill() {

return chill;

}

/**

*<br>

* @param chill the chill to set

*/

public void setChill(String chill) {

this.chill = chill;

}

/**

* <br>

* @return  humidity

*/

public String getHumidity() {

return humidity;

}

/**

*<br>

* @param humidity the humidity to set

*/

public void setHumidity(String humidity) {

this.humidity = humidity;

}

}
Lớp Weather chỉ là bean chứa thông tin thời tiết lấy từ Yahoo Weather.
Tiếp theo chúng ta sẽ tạo lớp Main.java là điểm đầu vào của chương trình.
Tạo file YahooRetriever.java. Lớp đơn giản này mở ra UrlConnection tới Yahoo!Weather API và trả về InputStream.

package org.sonatype.mavenbook.weather;

import java.io.InputStream;

import java.net.URL;

import java.net.URLConnection;

import org.apache.log4j.Logger;

/**

* <H3>YahooRetriever</H3>

*

* @author ThinhNV2

* @since Apr 14, 2013

*/

public class YahooRetriever {

private static Logger log = Logger.getLogger(YahooRetriever.class);

public InputStream retrieve(String zipcode) throws Exception {

log.info(“Retrieving Weather Data”);

String url = “http://weather.yahooapis.com/forecastrss?p=&#8221; + zipcode;

URLConnection conn = new URL(url).openConnection();

return conn.getInputStream();

}

}

Để phân tích kết quả nhận được tạo lớp YahooParser.java.

package org.sonatype.mavenbook.weather;

import java.io.InputStream;

import java.util.HashMap;

import java.util.Map;

import org.apache.log4j.Logger;

import org.dom4j.Document;

import org.dom4j.DocumentFactory;

import org.dom4j.io.SAXReader;

/**

* <H3>YahooParser</H3>

*

* @author ThinhNV2

* @since Apr 14, 2013

*/

public class YahooParser {

private static Logger log = Logger.getLogger(YahooParser.class);

public Weather parse(InputStream inputStream) throws Exception {

Weather weather = new Weather();

log.info(“Creating XML Reader”);

SAXReader xmlReader = createXmlReader();

Document doc = xmlReader.read(inputStream);

log.info(“Parsing XML Response”);

weather.setCity(doc.valueOf(“/rss/channel/y:location/@city”));

weather.setRegion(doc.valueOf(“/rss/channel/y:location/@region”));

weather.setCountry(doc.valueOf(“/rss/channel/y:location/@country”));

weather.setCondition(doc.valueOf(“/rss/channel/item/y:condition/@text”));

weather.setTemp(doc.valueOf(“/rss/channel/item/y:condition/@temp”));

weather.setChill(doc.valueOf(“/rss/channel/y:wind/@chill”));

weather.setHumidity(doc.valueOf(“/rss/channel/y:atmosphere/@humidity”));

return weather;

}

private SAXReader createXmlReader() {

Map<String, String> uris = new HashMap<String, String>();

uris.put(“y”, “http://xml.weather.yahoo.com/ns/rss/1.0&#8243;);

DocumentFactory factory = new DocumentFactory();

factory.setXPathNamespaceURIs(uris);

SAXReader xmlReader = new SAXReader();

xmlReader.setDocumentFactory(factory);

return xmlReader;

}

}

Đây là lớp phức tạp nhất trong ứng dụng này. Lớp này sử dụng Dom4j để phân tích dữ liệu Xml và Jaxen hỗ trợ khả năng Xpath để trích xuất thông tin cụ thể. Đầu tiên chúng ta cần tạo đối tượng SAXReader với thông tin về không gian tên. Từ đối tượng này chúng ta sẽ có được đối tượng org.dom4j.Document. Từ đó chúng ta trích xuất thông tin mong muốn sử dụng cú pháp Xpath.

Chúng ta cần định dạng đối tượng Weather nhận được  sau quá trình phân tích bằng việc tạo lớp YahooFormatter:

package org.sonatype.mavenbook.weather;

import java.io.InputStreamReader;

import java.io.Reader;

import java.io.StringWriter;

import org.apache.log4j.Logger;

import org.apache.velocity.VelocityContext;

import org.apache.velocity.app.Velocity;

/**

* <H3>WeatherFormat</H3>

*

* @author ThinhNV2

* @since Apr 14, 2013

*/

public class WeatherFormatter {

private static Logger log = Logger.getLogger(WeatherFormatter.class);

public String format(Weather weather) throws Exception {

log.info(“Formatting Weather Data”);

Reader reader = new InputStreamReader(getClass().getClassLoader()

.getResourceAsStream(“output.vm”));

VelocityContext context = new VelocityContext();

context.put(“weather”, weather);

StringWriter writer = new StringWriter();

Velocity.evaluate(context, writer, “”, reader);

return writer.toString();

}

}

Lớp WeatherFormatter sử dụng Velocity để phản hồi theo template. Phương thức format lấy đối tượng Weather là đối số đầu vào và xuất thông tin dưới dạng String đã được định dạng. Điều đầu tiên của phương thức format là tải template của Velocity từ classpath có tên là output.vm. Lúc đó chúng ta tạo VelocityContext được bố trí với đối tượng Weather có tên là weather. Một StringWriter được tạo ra để giữ kết quả việc trộn template. Template được đánh giá bằng việc gọi Velocity.evaluate() và kết quả trả về như là String.

Cuối cùng chúng ta tạo lớp Main như là điểm đầu vào của chương trình.

public class Main {

private String zip;

/**

* Description

*

* @param args

*/

public static void main(String[] args) {

// Configure Log4J

PropertyConfigurator.configure(Main.class.getClassLoader().getResource(

“log4j.properties”));

// Read the Zip Code from the Command-line (if none supplied, use 60202)

String zipcode = “60202″;

try {

zipcode = args[0];

// Start the program

new Main(zipcode).start();

} catch (Exception e) {

}

}

public Main(String zip) {

this.zip = zip;

}

public void start() throws Exception {

// Retrieve Data

InputStream dataIn = new YahooRetriever().retrieve( zip );

// Parse Data

Weather weather = new YahooParser().parse( dataIn );

// Format (Print) Data

System.out.print( new WeatherFormatter().format( weather ) );

}

}

Trong lớp Main chúng ta sẽ nhận zipcode từ người dùng nhập vào. Nếu có lỗi xảy ra chúng ta sẽ sử dụng zipcode mặc định 60202

Để chạy được ứng dụng chúng ta cần bố sung một số file tài nguyên: lớp Main cấu hình Log4j với một tài nguyên nằm trên classpath có tên là log4j.properties, và WeatherFormatter tìm một template của Velocity có tên là output.vm cũng nằm trong classpath.

Đầu tiên tạo file log4j.properties ở trong src/main/resources với nội dung sau:

# Set root category priority to INFO and its only appender to CONSOLE.

log4j.rootCategory=INFO, CONSOLE

# CONSOLE is set to be a ConsoleAppender using a PatternLayout.

log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender

log4j.appender.CONSOLE.Threshold=INFO

log4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayout

log4j.appender.CONSOLE.layout.ConversionPattern=%-4r %-5p %c{1} %x – %m%n

Log4j sẽ in kết quả ra màn hình console sử dụng PatternLayout.

Cuối cùng tạo file output.vm cũng ở trong src/main/resources

*********************************

Current Weather Conditions for:

${weather.city}, ${weather.region}, ${weather.country}

Temperature: ${weather.temp}

Condition: ${weather.condition}

Humidity: ${weather.humidity}

Wind Chill: ${weather.chill}

*********************************

File output.vm đang tham chiếu đến đối tượng weather chúng ta đã đẩy vào VelocityContext trong lớp WeatherFormatter ở trên. Cú pháp ${weather.city} là cú pháp ngắn gọn truy xuất thuộc tính city của đối tượng weather.

Chạy maven install bằng việc click chuột phải lên dự án, chọn Run As, sau đó chọn Maven Install:

Maven_install

Xem console để xem có lỗi hay không

maven_console

Sau đó chạy file Main như bình thường, chúng ta sẽ nhận kết quả thời tiết từ zipcode 60202 nếu chúng ta không truyền vào thông qua đối số command line.

weather_5

Chúc mừng bạn đã tạo dự án maven bằng m2eclipse.

Source code

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

 
Follow

Get every new post delivered to your Inbox.

%d bloggers like this: