到目前為止(未來有很多不可預知的事),Java應該還是企業(yè)級應用開發(fā)的首選随闺,基于Java開發(fā)的企業(yè)級應用軟件架構也是經(jīng)歷了一代又一代,從最初的jsp+javabean+servlet里逆,到后來流行的MVC架構SSH娇妓,再到目前的“百花齊放”——涌現(xiàn)出了太多的開發(fā)框架。
在這個已經(jīng)到來的“云時代”辫塌,如何讓我們開發(fā)的軟件具備很好的“云感知”能力呢漏策? 不管你選擇什么樣的框架,什么樣的技術臼氨,從我這幾年的工作經(jīng)驗來看掺喻,大部分還是要通過軟件架構層面的調整,才能讓我們的軟件更有生命力储矩。
關于企業(yè)級應用開發(fā)感耙,我將會介紹一些工具、一些架構層面的東西持隧,希望能有助于讓各位程序員能開發(fā)出能跑在云環(huán)境下的應用即硼。今天給大家首先帶來的是Maven。
maven
有將項目打好war包部置到生產(chǎn)環(huán)境后報各種錯誤的經(jīng)歷嗎屡拨?
有到處找jar包的經(jīng)歷嗎只酥?
有各種jar包沖突導致的各種錯誤的經(jīng)歷嗎褥实?
也許你們都沒有,但我真的遇到很多裂允,幾乎每一個項目都會遇到损离,直到遇到了Maven,這些大部分問題都得到了解決绝编。
應用商店
2008年7月11日僻澎,蘋果APP Store正式上線,開創(chuàng)了軟件銷售的全新模式十饥,App Store模式的意義在于為第三方軟件的提供者提供了一個統(tǒng)一的軟件銷售平臺窟勃。這真的是蘋果的創(chuàng)新成果嗎?從商業(yè)角度出發(fā)绷跑,我們必須承認拳恋,但從技術上來說,Linux社區(qū)在很久很久以前砸捏,就使用了“軟件倉庫”來集中管理軟件包谬运,同時也通過軟件層面解決了軟件包之間的依賴問題。如ubuntu上的apt-get垦藏, CentOS上的yum都是非常好的軟件包管理工具梆暖,它們的前提就是有一個集中存放軟件的中央倉庫。
這幾年隨著軟件技術有發(fā)展掂骏,大部分開發(fā)語言都吸取了Linux的軟件倉庫精華轰驳,都有自己的模塊(或軟件)依賴管理工具,如ruby的gem弟灼,python的pip级解,nodejs的npm等。
Maven也解決了Java開發(fā)中最讓人鬧心的jar包管理問題田绑,讓開發(fā)人員不用再到處找jar包勤哗,然后復制到lib目錄,添加到classpath……掩驱,當然Maven能做的事遠遠不止這些芒划。
Maven是一個項目管理工具,它包含了一個項目對象模型 (Project Object Model)欧穴,一組標準集合民逼,一個項目生命周期(Project Lifecycle),一個依賴管理系統(tǒng)(Dependency Management System)涮帘,和用來運行定義在生命周期階段(phase)中插件(plugin)目標(goal)的邏輯拼苍。當你使用Maven的時候,你用一個明確定義的項目對象模型來描述你的項目调缨,然后Maven可以應用橫切的邏輯映屋,這些邏輯來自一組共享的(或者自定義的)插件苟鸯。
火速入門
從一開始我對本書的定義就不是一本純技術的書,所以本節(jié)只會簡單介紹Maven的使用棚点,如果想更深入的了解Maven,請參考和Maven相關的專業(yè)書籍或google湾蔓。
師傅領進門,修行在個人
jar包管理基本原理
如下圖所示瘫析,Maven通過統(tǒng)一的存儲庫來保存jar包、插件等默责。
+---------------------+
| |
| Remote Repository |
| |
+----------^----------+
|
|
+----------------------------------------------+
| | your compute |
| | +------------+ |
| | | | |
| | +--+ Project1 | |
| +--------+---------+ | | | |
| | <--+ +------------+ |
| | Local Repository | |
| | <--+ +------------+ |
| +------------------+ | | | |
| +--+ Project2 | |
| | | |
| +------------+ |
| |
+----------------------------------------------+
同一個項目可以同時使用多個遠程存儲庫(Remote Repository)贬循,Maven在本地會有自己的一個存儲庫(Local Repository),在構建項目時桃序,Maven會將遠程存儲庫中項目所依賴的jar包杖虾、插件等下載到本地存儲庫緩存,本地的項目共享同一個存儲庫媒熊,如果Project1中使用到了junit4.0版本的jar包奇适,在Porject2中也用到時,Maven就不會再從遠程存儲庫中下載芦鳍。
在Project1和Project2中將不在存儲jar包嚷往,只在項目描述文件中聲明項目對jar包的依賴關系。以前在管理項目源代碼的時候柠衅,往往也會將這些jar包一起放到版本控制工具皮仁,而現(xiàn)在結合公司的Repository,這些jar包就不再需要加入到版本控制工具(如SVN)中了菲宴,這大大減少了項目文件所占用的空間(這樣說或許有些牽強)贷祈。
安裝與配置
以Ubuntu為例,執(zhí)行如下命令即完成Maven的安裝:
sudo apt-get install maven
Maven配置文件默認在~/.m2/settings.xml喝峦,在配置文件中可以配置代理服務器势誊、用戶認證信息、遠程倉庫地址愈犹、插件倉庫地址等键科。
詳細的配置項和說明可見:http://maven.apache.org/settings.html
如果找不到這個文件,可以從Maven安裝目錄下conf/settings.xml文件拷貝到~/.m2/目錄漩怎。
Maven的使用
在正式開始之前勋颖,先來介紹一個概念:Archetype
每個公司經(jīng)過長期的技術積累,雖然是不同的項目勋锤,但項目的代碼基本結構饭玲、代碼的打包方式基本是相同的。
Archetype是一個Maven項目模板管理工具叁执,我們可以把前面說的項目一些共性的東西做成一個模板茄厘,在新項目開始的時候矮冬,只可使用Archetype直接初始化項目開發(fā)環(huán)境。在本文中我們就把Archetype理解為項目模板次哈,在寫本節(jié)時胎署,在Maven公共倉庫(http://search.maven.org/)中的Archetype已達1098個,對于常見的項目窑滞,我們可以直接基于這個Archetype創(chuàng)建初始環(huán)境即可琼牧。
下面我們開始新建一個項目,我們基于Maven公共倉庫中的Archetype:spring-mvc-archetype為基于開始我們的項目哀卫。
執(zhí)行如下命令:
mvn archetype:generate -DgroupId=com.mycompany.app -DartifactId=my-app -DarchetypeGroupId=co.ntier -DarchetypeArtifactId=spring-mvc-archetype -DinteractiveMode=false
相關參數(shù)說明:
- DgroupID : Java包名
- DartifactID : 項目名稱(會做為生成項目目錄)
- DarchetypeGroupId: 模板所屬組織ID巨坊,默認值為:org.apache.maven.archetypes(這里很容易出錯哦,一定要指定模板的組織ID此改,要不然會報找不到模板趾撵。
- DarchetypeArtifactId:模板名稱
- DinteractiveMode : 是否與maven交互,如果為true共啃,會提示輸入包名占调、版本號等信息,false時勋磕,都使用默認值
執(zhí)行完命令后妈候,會生成如下目錄結構:
└── my-app
├── pom.xml
└── src
└── main
├── java
│ └── com
│ └── mycompany
│ └── app
│ ├── config
│ │ └── MvcConfiguration.java
│ └── controller
│ └── HomeController.java
└── webapp
├── WEB-INF
│ ├── views
│ │ └── home.jsp
│ └── web.xml
└── resources
└── style.css
這是一個spring mvc 的 hello world 程序,我們可以看到挂滓,這里并沒有看到我們所需要的相關spring的jar包苦银,我們來看看maven核心配置文件pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.mycompany.app</groupId>
<artifactId>my-app</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>war</packaging>
<name>my-app</name>
<url>http://maven.apache.org</url>
<properties>
<java.version>1.6</java.version>
<spring.version>3.1.0.RELEASE</spring.version>
<cglib.version>2.2.2</cglib.version>
</properties>
<dependencies>
<!-- Spring core & mvc -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-orm</artifactId>
<version>${spring.version}</version>
<type>jar</type>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>${spring.version}</version>
<type>jar</type>
<scope>test</scope>
</dependency>
<!-- CGLib for @Configuration -->
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib-nodep</artifactId>
<version>${cglib.version}</version>
<scope>runtime</scope>
</dependency>
<!-- Servlet Spec -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.4</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>jsp-api</artifactId>
<version>2.1</version>
<scope>provided</scope>
</dependency>
</dependencies>
<repositories>
<repository>
<id>springsource-milestones</id>
<name>SpringSource Milestones Proxy</name>
<url>https://oss.sonatype.org/content/repositories/springsource-milestones</url>
</repository>
</repositories>
<build>
<finalName>my-app</finalName>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.0.2</version>
<configuration>
<source>${java.version}</source>
<target>${java.version}</target>
</configuration>
</plugin>
</plugins>
</build>
</project>
配置文件大家一看就知道是干什么了,一開始的version赶站、packaging等屬性是定義這個項目的版本號幔虏、打包方式等,接下來的properties定義了一堆常量贝椿,后面的dependencies就是聲明項目所依賴的一些包想括,最后的build是聲明打包編譯時需要的一些插件。
接下來烙博,進入my-app目錄瑟蜈,執(zhí)行如下命令:
cd my-app
mvn package
您將看到maven會到maven遠程倉庫將pom.xml中聲明的依賴包下載到本地,然后執(zhí)行打包渣窜。
命令執(zhí)行完后铺根,您將看到在target目錄下生成了my-app.war的包,拿著這個包就可以去部署到各種java中間件上了乔宿。是不是很方便位迂。
前面介紹過,maven并不是單純的jar包依賴管理工具,Maven是一個項目管理工具掂林,它包含了一個項目對象模型 (Project Object Model)臣缀,因此,除了管理jar包依賴泻帮,它還包括項目管理過程中常用的很多工具精置。
我們可以在根目錄下建立test目錄,將java測試用例放到下面锣杂,然后在命令行執(zhí)行mvn test
氯窍,就能看到測試結果,看測試有沒有發(fā)生錯誤等蹲堂。
對于開發(fā)人員,經(jīng)常使用tomcat來開發(fā)的話贝淤,整個過程是很簡單的柒竞。在剛才的my-app項目根目錄執(zhí)行:mvn tomcat:run
,然后打開瀏覽器:http://localhost:8080/my-app 播聪,您就將看到運行結果朽基。沒想到吧,都不用安裝tomcat离陶,全部通過maven就能搞定稼虎。
如果您是在開發(fā)一個純java模塊,那就執(zhí)行:mvn install
就可以把jar包發(fā)布到本地Repository招刨,然后就可以在別的項目里引用這個jar包了霎俩,借助一些插件就可以把它發(fā)布到公司的統(tǒng)一Repository庫中。
Maven還有很多很多的功能沉眶,本書maven就介紹到這里打却,詳細的關于Maven的知識可以參考一些專業(yè)的書籍或官方文檔。最后推薦您將下面的項目clone到本地來深入學習:
https://github.com/spring-projects/spring-mvc-showcase
git clone git://github.com/SpringSource/spring-mvc-showcase.git
國際范程序必讀:
程序員的編輯器-VIM(愛就是愛)
向開源社區(qū)貢獻您的代碼
在github上寫博客
DevOps是什么東東谎倔?
js依賴管理工具bower
JS模塊化編程-requirejs