NET战舰世界数据端口是否有Maven替代品或端口

/ template-maven
项目语言:JAVA
权限:read-only(如需更高权限请先加入项目)
template-maven/
Index: resource.xml
===================================================================
--- resource.xml (revision 0)
+++ resource.xml (revision 2)
@@ -0,0 +1,57 @@
+&?xml version=&1.0& encoding=&UTF-8&?&
&not-init&Not initialized.&/not-init&
&connecting&Connecting.&/connecting&
&reconnecting&Reconnecting.&/reconnecting&
&connected&Connected.&/connected&
&heartbeating&Heartbeating.&/heartbeating&
&receiveing&Receiveing.&/receiveing&
&closeing&Closing.&/closeing&
&closed&Closed.&/closed&
&unknown-host&Unknown host(Invalid IP or can't determine IP from hostname)&/unknown-host&
&port-error&Invalid port(not integer in 0~65535)&/port-error&
&connect-refused&Connection refused.(Target port not in listening)&/connect-refused&
&no-route&No route to target.(Address not exist, target computer not alive, route setting error, or physical line break)&/no-route&
&receive-timeout&Receive timeout.(read-timeout parameter too short or target computer's heartbeat stoped)&/receive-timeout&
&close-by-peer&Connection closed by peer.(Server closed our socket.)&/close-by-peer&
&reset-by-peer&Connection reset by peer.(Server reset our socket, maybe server process abnormal terminated)&/reset-by-peer&
&connection-closed&Connection already closed.&/connection-closed&
&communication-error&Communication error.&/communication-error&
&connect-error&Connect error, &/connect-error&
&send-error&Send message error, &/send-error&
&receive-error&Receive message error, &/receive-error&
&close-error&Connection close error, &/close-error&
&no-listener&No listener registed to handle event&/no-listener&
&dispatch-message-fail&Message dispatch fail.&/dispatch-message-fail&
&illegal-call&Illegal call.(Should not call this method)&/illegal-call&
&logining&Logining&/logining&
&login-error&Exception occurs while login,&/login-error&
&send-error&The message is sent falsely.&/send-error&
&connect-timeout&The login is unsuccessful.&/connect-timeout&
&structure-error&The login is unsuccessful, because the structure of connection message is wrong.&/structure-error&
&nonlicetsp-id&The login is unsuccessful, because SP_ID is nonlicet.&/nonlicetsp-id&
&sp-error&The login is unsuccessful, because SP is wrong.&/sp-error&
&version-error&The login is unsuccessful, because the version is higher.&/version-error&
&other-error&The login is unsuccessful, other error.&/other-error&
&heartbeat-abnormity&Heartbeat is abnormity(Beacause the heartbeat was sent time after time,but there was not return or the return value was unsuccessful).&/heartbeat-abnormity&
&submit-input-error&The parameter of submit message is wrong&/submit-input-error&
&connect-input-error&The parameter of login message is wrong&/connect-input-error&
&cancel-input-error&The parameter of cancel message is wrong&/cancel-input-error&
&query-input-error&The parameter of query mesaage is wrong&/query-input-error&
&deliver-repinput-error&The parameter of response message for answering the deliver message sent by SMC is wrong&/deliver-repinput-error&
&active-repinput-error&The parameter of response mesaage for answering the active message sent by SMC is wrong&/active-repinput-error&
&smc-message-error&The message that is sent by SMC is wrong&/smc-message-error&
&int-scope-error& less than 0 or larger than 255.&/int-scope-error&
&string-length-great& length is larger than &/string-length-great&
&string-null&
value is null.&/string-null&
&value-error&
is unequal to 0 or 1&/value-error&
&fee-usertype-error&the value of fee_UserType is less than 0 or larger than 3.&/fee-usertype-error&
&registered-delivery-error&the value of registered_Delivery is less than 0 or larger than 2.&/registered-delivery-error&
&pk-total-error&the value of pk_Total is less than 1 or larger than 255.&/pk-total-error&
&pk-number-error&the value of pk_Number is less than 1 or larger than 255.&/pk-number-error&
&/smproxy&
+&/config&
\ No newline at end of file
Index: resource_zh.xml
===================================================================
--- resource_zh.xml (revision 0)
+++ resource_zh.xml (revision 2)
@@ -0,0 +1,63 @@
+&?xml version=&1.0& encoding=&GB2312& ?&
&not-init&\u8fde\u63a5\u5c1a\u672a\u521d\u59cb\u&/not-init&
&connecting&\u6b63\u5728\u8fde\u63a5\u3002&/connecting&
&reconnecting&\u6b63\u5728\u91cd\u8fde\u3002&/reconnecting&
&connected&\u8fde\u63a5\u5efa\u7acb\uf\u3002&/connected&
&heartbeating&\u6b63\u\u\u8df3\u6d88\u606f\u3002&/heartbeating&
&receiveing&\u6b63\u\u\u606f\u3002&/receiveing&
&closeing&\u6b63\u\u95ed\u8fde\u63a5\u3002&/closeing&
&closed&\u8fde\u63a5\u6b63\u5e38\u5173\u95ed\u3002&/closed&
&unknown-host&\u672a\u77e5\u4e3b\u673a\u3002(\u9519\u8bef\u7684IP\u\ud\u80fd\ue\u4e3b\u673a\u540d\u5f97\u\u5e94\u7684IP\u\u3002)&/unknown-host&
&port-error&\u7aef\u53e3\u53f7\u9519\u8bef\u3002(\u4e0d\u662f0~6\u56f4\u\u\u3002)&/port-error&
&connect-refused&\u8fde\u63a5\u88ab\u5bf9\u65b9\u62d2\u7edd\u3002(\u8fde\u63a5\u5bf9\u65b9\ua\u7aef\u53e3\u4e0d\u\u542c\u72b6\u)&/connect-refused&
&no-route&\u6ca1\ua\u\u\u7684\u8def\u(\u\u4e0d\u5b58\u\u5bf9\u65b9\u672a\u5f00\u673a\u3001\u8def\ud\u901a\u\u\u7ebf\u8def\uc)&/no-route&
&receive-timeout&\u63a5\u\u606f\u8d85\u65f6\u3002(\u8bf7\u786e\u8ba4\u8bbe\u7f6e\u7684read-timeout\u53c2\u\u4e8e\u670d\u52a1\u\u8df3\u53d1\u\u~3\u500d\uff0c\u5e76\u786e\u8ba4\u670d\u52a1\uf\u\u786e\u53d1\u51fa\u5fc3\u8df3\u6d88\u606f\u3002)&/receive-timeout&
&close-by-peer&\u8fde\u63a5\u88ab\u5bf9\u65b9\u5173\u95ed\u3002(\u670d\u52a1\u5668\u7aef\u4e3b\u52a8\u\u95ed\u4e86\u6211\u4eec\u4e4b\u95f4\u7684\u8fde\u63a5\u\u68c0\u67e5\u670d\u52a1\ud\u7f6e\u662f\u\u786e\uff0c\u662f\u\u63a5\u\u\u\u3002)&/close-by-peer&
&reset-by-peer&\u8fde\u63a5\u88ab\u5bf9\u65b9\u91cd\u7f6e\u3002(\u670d\u52a1\u5668\u7aef\u975e\u6b63\u5e38\u5173\u95ed\u4e86\u8fde\u63a5\uff0c\u53ef\u80fd\u662f\u670d\u52a1\u8fdb\u7a0b\u975e\u6b63\u5e38\u9000\u51fa\u4e86\ub\u5982\uff1acall dump\u6216\u88ab\u7ba1\ukill\u)&/reset-by-peer&
&connection-closed&\u8fde\u63a5\u5df2\u7ecf\u5173\u95ed\u3002&/connection-closed&
&communication-error&\u901a\u4fe1\u5f02\u5e38\u3002&/communication-error&
&connect-error&\u5efa\u7acb\u8fde\u63a5\u\uff1a&/connect-error&
&send-error&\u53d1\u\u606f\u\uff1a&/send-error&
&receive-error&\u63a5\u\u606f\u\u3002&/receive-error&
&close-error&\u5173\u95ed\u8fde\u63a5\u51fa\u&/close-error&
&checksum-error&\uc\u548c\u9519\u8bef\u3002&/checksum-error&
&no-listener&\u6ca1\u\u518c\u4e3b\u52a8\u6d88\u606f\u76d1\u542c\u5668\uff0c\u800c\u53c8\u\u4e00\u4e2a\u4e3b\u52a8\u6d88\u606f\u3002&/no-listener&
&dispatch-message-fail&\u6d88\u606f\u8c03\u5ea6\u\u3002(\u5bf9\u65b9\u6d88\u606f\u60f3\u\u8fbe\uf\u8bae\u81ea\u52a8\u673a\u\u65b9\u627e\u4e0d\u)&/dispatch-message-fail&
&illegal-call&\u4e0d\u5e94\u8be5\u51fa\u73b0\u\u(\u4f8b\u\u\u534f\u8bae\u5c42\u8c03\ub\u5efa\u5b50\u534f\u8bae\u5c42\uff0c\u\u4f4e\u534f\u8bae\u5c42\u6ca1\ua\u4e49close()\u65b9\u6cd5\u3002)&/illegal-call&
&logining&\u6b63\ub\u5f55&/logining&
&login-error&\u767b\u5f55\u8fc7\u7a0b\u51fa\u73b0\u5f02\u5e38\uff1a&/login-error&
&send-error&\u6d88\u606f\u53d1\u\u8bef&/send-error&
&connect-timeout&\u767b\u5f55\u4e0d\uf&/connect-timeout&
&structure-error&\u767b\u5f55\u4e0d\uf:\u767b\u5f55\u6d88\u606f\u7ed3\u&/structure-error&
&nonlicetsp-id&\u767b\u5f55\u4e0d\uf:\u975e\u6cd5SP_ID&/nonlicetsp-id&
&sp-error&\u767b\u5f55\u4e0d\uf:SP\u8ba4\u8bc1\u9519&/sp-error&
&version-error&\u767b\u5f55\u4e0d\uf:\uc\u592a\u9ad8&/version-error&
&other-error&\u767b\u5f55\u4e0d\uf:\u\u9519\u8bef&/other-error&
&heartbeat-abnormity&\u5fc3\u8df3\u5f02\u5e38(\u5fc3\u8df3\u53d1\u51fa\u591a\u6b21\uff0c\u6ca1\u\u56de\u503c\u\u56de\uc\u4e3a\u4e0d\uf)&/heartbeat-abnormity&
&submit-input-error&\u53d1\u9001\u77ed\u4fe1\u6d88\u606f\u53c2\u\u\u8bef&/submit-input-error&
&connect-input-error&\u767b\u5f55\u6d88\u606f\u53c2\u\u\u8bef&/connect-input-error&
&cancel-input-error&\u\u77ed\u4fe1\u8bf7\u6c42\u6d88\u606f\u53c2\u\u\u8bef&/cancel-input-error&
&query-input-error&\u53d1\u9001\u77ed\u4fe1\u72b6\u\u8be2\u8bf7\u6c42\u53c2\u\u\u8bef&/query-input-error&
&deliver-repinput-error&\u5bf9\u4e0b\u53d1\u7684\u77ed\u4fe1\u54cd\u5e94\u6d88\u606f\u53c2\ua\u4e49\u6709\u8bef&/deliver-repinput-error&
&active-repinput-error&\u5b9a\u4e49\u54cd\u5e94\u6fc0\u6d3b\u8bf7\u6c42\u\u606f\u53c2\u\u\u8bef&/active-repinput-error&
&smc-message-error&SMC\u53d1\u\u\u6d88\u606f\u9519\u8bef&/smc-message-error&
&int-scope-error&\u5c0f\u4e8e0\u\u4e8e255&/int-scope-error&
&string-length-great&\u957f\u5ea6\ue&/string-length-great&
&string-null&\u503c\u4e3a\u7a7a&/string-null&
&value-error&\u4e0d\u7b49\u4e8e0\u62161&/value-error&
&fee-usertype-error&fee_UserType\uc\u5c0f\u4e8e0\u\u4e8e3&/fee-usertype-error&
&registered-delivery-error&registered_Delivery\uc\u5c0f\u4e8e0\u\u4e8e2&/registered-delivery-error&
&pk-total-error&pk_Total\uc\u5c0f\u4e8e1\u\u4e8e255&/pk-total-error&
&pk-number-error&pk_Number\uc\u5c0f\u4e8e1\u\u4e8e255&/pk-number-error&
&forward_input_error&\u8f6c\u53d1\u8bf7\u6c42\u6d88\u606f\u8f93\u\u\u8bef&/forward_input_error&
&mtrouteupdate_input_error&mt_route_update\u8bf7\u6c42\u6d88\u606f\u8f93\u\u\u8bef&/mtrouteupdate_input_error&
&morouteupdate_input_error&mo_route_update\u8bf7\u6c42\u6d88\u606f\u8f93\u\u\u8bef&/morouteupdate_input_error&
&needreport_error&NeedReport\uc\u4e0d\u4e3a0\u62161&/needreport_error&
&priority_error&Priority\uc\u5c0f\u4e8e0\u\u4e8e9&/priority_error&
&desttermid_error&\u77ed\u6d88\u606f\u63a5\u\ua\u\u4e8e100&/desttermid_error&
&/smproxy&
+&/config&
Index: resource_zh_back.xml
===================================================================
--- resource_zh_back.xml (revision 0)
+++ resource_zh_back.xml (revision 2)
@@ -0,0 +1,63 @@
+&?xml version=&1.0& encoding=&GB2312& ?&
&not-init&连接尚未初始化。&/not-init&
&connecting&正在连接。&/connecting&
&reconnecting&正在重连。&/reconnecting&
&connected&连接建立成功。&/connected&
&heartbeating&正在发送心跳消息。&/heartbeating&
&receiveing&正在接收消息。&/receiveing&
&closeing&正在关闭连接。&/closeing&
&closed&连接正常关闭。&/closed&
&unknown-host&未知主机。(错误的IP地址或不能根据主机名得到对应的IP地址。)&/unknown-host&
&port-error&端口号错误。(不是0~65535范围内的整数。)&/port-error&
&connect-refused&连接被对方拒绝。(连接对方指定端口不在监听状态。)&/connect-refused&
&no-route&没有通向该地址的路由。(地址不存在、对方未开机、路由不通或者物理线路故障)&/no-route&
&receive-timeout&接收消息超时。(请确认设置的read-timeout参数大于服务器心跳发送频率的2~3倍,并确认服务器是否正确发出心跳消息。)&/receive-timeout&
&close-by-peer&连接被对方关闭。(服务器端主动地关闭了我们之间的连接。请检查服务器配置是否正确,是否有接入方地址限制。)&/close-by-peer&
&reset-by-peer&连接被对方重置。(服务器端非正常关闭了连接,可能是服务进程非正常退出了。例如:call dump或被管理员kill掉。)&/reset-by-peer&
&connection-closed&连接已经关闭。&/connection-closed&
&communication-error&通信异常。&/communication-error&
&connect-error&建立连接失败:&/connect-error&
&send-error&发送消息失败:&/send-error&
&receive-error&接收消息失败。&/receive-error&
&close-error&关闭连接出错。&/close-error&
&checksum-error&效验和错误。&/checksum-error&
&no-listener&没有注册主动消息监听器,而又收到一个主动消息。&/no-listener&
&dispatch-message-fail&消息调度失败。(对方消息想要到达的协议自动机在我方找不到。)&/dispatch-message-fail&
&illegal-call&不应该出现的调用。(例如在最高协议层调用创建子协议层,或最低协议层没有定义close()方法。)&/illegal-call&
&logining&正在登录&/logining&
&login-error&登录过程出现异常:&/login-error&
&send-error&消息发送有误&/send-error&
&connect-timeout&登录不成功&/connect-timeout&
&structure-error&登录不成功:登录消息结构错&/structure-error&
&nonlicetsp-id&登录不成功:非法SP_ID&/nonlicetsp-id&
&sp-error&登录不成功:SP认证错&/sp-error&
&version-error&登录不成功:版本太高&/version-error&
&other-error&登录不成功:其它错误&/other-error&
&heartbeat-abnormity&心跳异常(心跳发出多次,没有返回值或返回的值为不成功)&/heartbeat-abnormity&
&submit-input-error&发送短信消息参数输入有误&/submit-input-error&
&connect-input-error&登录消息参数输入有误&/connect-input-error&
&cancel-input-error&删除短信请求消息参数输入有误&/cancel-input-error&
&query-input-error&发送短信状态查询请求参数输入有误&/query-input-error&
&deliver-repinput-error&对下发的短信响应消息参数定义有误&/deliver-repinput-error&
&active-repinput-error&定义响应激活请求的消息参数输入有误&/active-repinput-error&
&smc-message-error&SMC发送过来的消息错误&/smc-message-error&
&int-scope-error&小于0或大于255&/int-scope-error&
&string-length-great&长度大于&/string-length-great&
&string-null&值为空&/string-null&
&value-error&不等于0或1&/value-error&
&fee-usertype-error&fee_UserType的值小于0或大于3&/fee-usertype-error&
&registered-delivery-error&registered_Delivery的值小于0或大于2&/registered-delivery-error&
&pk-total-error&pk_Total的值小于1或大于255&/pk-total-error&
&pk-number-error&pk_Number的值小于1或大于255&/pk-number-error&
&forward_input_error&转发请求消息输入参数有误&/forward_input_error&
&mtrouteupdate_input_error&mt_route_update请求消息输入参数有误&/mtrouteupdate_input_error&
&morouteupdate_input_error&mo_route_update请求消息输入参数有误&/morouteupdate_input_error&
&needreport_error&NeedReport的值不为0或1&/needreport_error&
&priority_error&Priority的值小于0或大于9&/priority_error&
&desttermid_error&短消息接收号码个数大于100&/desttermid_error&
&/smproxy&
+&/config&
\ No newline at end of file
(C)&&2013&&Alibaba&&Inc.&&All&&rights&&resvered.
Powered by2526272829303112345678910111213141516171819202122232425262728293012345
随笔 - 3936
文章 - 404
评论 - 179
留言簿(52)
阅读排行榜
评论排行榜下次自动登录
现在的位置:
& 综合 & 正文
Maven的安装、配置及使用入门
本书代码下载
大家可以从我的网站下载本书的代码:http://www.juvenxu.com/mvn-in-action/,也可以通过我的网站与我取得联系,欢迎大家与我交流任何关于本书的问题和关于Maven的问题。
咖啡与工具
本书相当一部分的内容是在苏州十全街边的Solo咖啡馆完成的,老板Yin亲手烘焙咖啡豆、并能做出据说是苏州最好的咖啡,这小桥流水畔的温馨小屋能够帮我消除紧张和焦虑,和Yin有一句没一句的聊天也是相当的轻松。Yin还教会了我如何自己研磨咖啡豆、手冲滴率咖啡,让我能够每天在家里也能享受香气四溢的新鲜咖啡。
本书的书稿是使用Git和Unfuddle(http://unfuddle.com/)进行管理的,书中的大量截图是通过Jing(http://www.techsmith.com/jing/)制作的。
2010年10月于苏州Solo咖啡
感谢费晓峰,是你最早让我学习使用Maven,并在我开始学习的过程中给予了不少帮助。
感谢Maven开源社区特别是Maven的创立者Jason Van Zyl,是你们一起创造了如此优秀的开源工具,造福了全世界这么多的开发人员。
感谢我的家人,一年来,我的大部分原来属于你们的业余时间都给了这本书,感谢你们的理解和支持。
感谢二少、Garin、Sutra、JTux、红人、linux_china、Chris、Jdonee、zc0922、还有很多Maven中文社区的朋友,你们给了本书不少建议,并在我写作过程中不断鼓励我和支持我,你们是我写作最大的动力之一。
最后感谢本书的策划编辑杨福川和曾珊,我从你们身上学到了很多,你们是最专业的、最棒的。
第1章 Maven简介
何为Maven/2
为什么需要Maven/4
Maven与极限编程/7
被误解的Maven/8
1.1 何为Maven
Maven这个词可以翻译为“知识的积累”,也可以翻译为“专家”或“内行”。本书将介绍Maven这一跨平台的项目管理工具。作为Apache组织中的一个颇为成功的开源项目,Maven主要服务于基于Java平台的项目构建、依赖管理和项目信息管理。无论是小型的开源类库项目,还是大型的企业级应用;无论是传统的瀑布式开发,还是流行的敏捷模式,Maven都能大显身手。
不管你是否意识到,构建(build)是每一位程序员每天都在做的工作。早上来到公司,我们做的第一件事情就是从源码库签出最新的源码,然后进行单元测试,如果发现失败的测试,会找相关的同事一起调试,修复错误代码。接着回到自己的工作上来,编写自己的单元测试及产品代码,我们会感激IDE随时报出的编译错误提示。
忙到午饭时间,代码编写得差不多了,测试也通过了,开心地享用午餐,然后休息。下午先在昏昏沉沉中开了个例会,会议结束后喝杯咖啡继续工作。刚才在会上经理要求看测试报告,于是找了相关工具集成进IDE,生成了像模像样的测试覆盖率报告,接着发了一封电子邮件给经理,松了口气。谁料QA小组又发过来了几个bug,没办法,先本地重现再说,于是熟练地用IDE生成了一个WAR包,部署到Web容器下,启动容器。看到熟悉的界面了,遵循bug报告,一步步重现了bug……快下班的时候,bug修好了,提交代码,通知 QA小组,在愉快中结束了一天的工作。
仔细总结一下,我们会发现,除了编写源代码,我们每天有相当一部分时间花在了编译、运行单元测试、生成文档、打包和部署等烦琐且不起眼的工作上,这就是构建。如果我们现在还手工这样做,那成本也太高了,于是有人用软件的方法让这一系列工作完全自动化,使得软件的构建可以像全自动流水线一样,只需要一条简单的命令,所有烦琐的步骤都能够自动完成,很快就能得到最终结果。
Maven是优秀的构建工具
前面介绍了Maven的用途之一是服务于构建,它是一个异常强大的构建工具,能够帮我们自动化构建过程,从清理、编译、测试到生成报告,再到打包和部署。我们不需要也不应该一遍又一遍地输入命令,一次又一次地点击鼠标,我们要做的是使用Maven配置好项目,然后输入简单的命令(如mvn clean install),Maven会帮我们处理那些烦琐的任务。
Maven是跨平台的,这意味着无论是在Windows上,还是在Linux或者Mac上,都可以使用同样的命令。
我们一直在不停地寻找避免重复的方法。设计的重复、编码的重复、文档的重复,当然还有构建的重复。Maven最大化地消除了构建的重复,抽象了构建生命周期,并且为绝大部分的构建任务提供了已实现的插件,我们不再需要定义过程,甚至不需要再去实现这些过程中的一些任务。最简单的例子是测试,我们没必要告诉Maven去测试,更不需要告诉Maven如何运行测试,只需要遵循Maven 的约定编写好测试用例,当我们运行构建的时候,这些测试便会自动运行。
想象一下,Maven抽象了一个完整的构建生命周期模型,这个模型吸取了大量其他的构建脚本和构建工具的优点,总结了大量项目的实际需求。如果遵循这个模型,可以避免很多不必要的错误,可以直接使用大量成熟的Maven插件来完成我们的任务(很多时候我们可能都不知道自己在使用Maven插件)。此外,如果有非常特殊的需求,我们也可以轻松实现自己的插件。
Maven还有一个优点,它能帮助我们标准化构建过程。在Maven之前,十个项目可能有十种构建方式;有了Maven之后,所有项目的构建命令都是简单一致的,这极大地避免了不必要的学习成本,而且有利于促进项目团队的标准化。
综上所述,Maven作为一个构建工具,不仅能帮我们自动化构建,还能够抽象构建过程,提供构建任务实现;它跨平台,对外提供了一致的操作接口,这一切足以使它成为优秀的、流行的构建工具。
Maven不仅仅是构建工具
Java不仅是一门,还是一个平台,通过JRuby和Jython,我们可以在Java平台上编写和运行Ruby和Python程序。我们也应该认识到,Maven不仅是构建工具,还是一个依赖管理工具和项目信息管理工具。它提供了中央仓库,能帮我们自动下载构件。
在这个开源的年代里,几乎任何Java应用都会借用一些第三方的开源类库,这些类库都可通过依赖的方式引入到项目中来。随着依赖的增多,版本不一致、版本冲突、依赖臃肿等问题都会接踵而来。手工解决这些问题是十分枯燥的,幸运的是 Maven提供了一个优秀的解决方案,它通过一个坐标系统准确地定位每一个构件(artifact),也就是通过一组坐标Maven能够找到任何一个 Java类库(如jar文件)。Maven给这个类库世界引入了经纬,让它们变得有秩序,于是我们可以借助它来有序地管理依赖,轻松地解决那些繁杂的依赖问题。
Maven还能帮助我们管理原本分散在项目中各个角落的项目信息,包括项目描述、开发者列表、版本控制系统地址、许可证、缺陷管理系统地址等。这些微小的变化看起来很琐碎,并不起眼,但却在不知不觉中为我们节省了大量寻找信息的时间。除了直接的项目信息,通过Maven自动生成的站点,以及一些已有的插件,我们还能够轻松获得项目文档、测试报告、静态分析报告、源码版本日志报告等非常具有价值的项目信息。
Maven还为全世界的Java开发者提供了一个免费的中央仓库,在其中几乎可以找到任何的流行开源类库。通过一些Maven的衍生工具(如Nexus),我们还能对其进行快速地搜索。只要定位了坐标,Maven就能够帮我们自动下载,省去了手工劳动。
使用Maven还能享受一个额外的好处,即Maven对于项目目录结构、测试用例命名方式等内容都有既定的规则,只要遵循了这些成熟的规则,用户在项目间切换的时候就免去了额外的学习成本,可以说是约定优于配置(Convention Over Configuration)。
1.2 为什么需要Maven
Maven不是Java领域唯一的构建管理的解决方案。本节将通过一些简单的例子解释Maven的必要性,并介绍其他构建解决方案,如IDE、Make和Ant,并将它们与Maven进行比较。
组装PC和品牌PC
笔者初中时开始接触计算机,到了高中时更是梦寐以求希望拥有一台自己的计算机。我的第一台计算机是赛扬733的,选购是一个漫长的过程,我先阅读了大量的杂志以了解各类配件的优劣,CPU、内存、主板、显卡,甚至声卡,我都仔细地挑选,后来还跑了很多商家,调货、讨价还价,组装好后自己装操作系统和驱动程序……虽然这花费了我大量时间,但我很享受这个过程。可是事实证明,装出来的机器稳定性不怎么好。
一年前我需要配一台工作站,这时候我已经没有太多时间去研究电脑配件了。我选择了某知名PC供应商的在线商店,大概浏览了一下主流的机型,选择了我需要的配置,然后下单、付款。接着PC供应商帮我组装电脑、安装操作系统和驱动程序。一周后,物流公司将电脑送到我的家里,我接上显示器、电源、鼠标和键盘就能直接使用了。这为我节省了大量时间,而且这台电脑十分稳定,商家在把电脑发送给我之前已经进行了很好的测试。对了,我还能享受两年的售后服务。
使用脚本建立高度自定义的构建系统就像买组装PC,耗时费力,结果也不一定很好。当然,你可以享受从无到有的乐趣,但恐怕实际项目中无法给你那么多时间。使用Maven就像购买品牌PC,省时省力,并能得到成熟的构建系统,还能得到来自于Maven社区的大量支持。唯一与购买品牌PC不同的是,Maven是开源的,你无须为此付费。如果有兴趣,你还能去了解Maven是如何工作的,而我们无法知道那些PC巨头的商业秘密。
IDE不是万能的
当然,我们无法否认优秀的IDE能大大提高开发效率。当前主流的IDE如Eclipse和NetBeans等都提供了强大的文本编辑、调试甚至重构功能。虽然使用简单的文本编辑器和命令行也能完成绝大部分开发工作,但很少有人愿意那样做。然而,IDE是有其天生缺陷的:
IDE依赖大量的手工操作。编译、测试、代码生成等工作都是相互独立的,很难一键完成所有工作。手工劳动往往意味着低效,意味着容易出错。
很难在项目中统一所有的IDE配置,每个人都有自己的喜好。也正是由于这个原因,一个在机器A上可以成功运行的任务,到了机器B的IDE中可能就会失败。
我们应该合理利用IDE,而不是过多地依赖它。对于构建这样的任务,在IDE中一次次地点击鼠标是愚蠢的行为。Maven是这方面的专家,而且主流IDE都集成了Maven,我们可以在IDE中方便地运行Maven执行构建。
Make也许是最早的构建工具,它由Stuart Feldman于1977年在Bell实验室创建。Stuart Feldman也因此于2003年获得了ACM国际计算机组织颁发的软件系统奖。目前Make有很多衍生实现,包括最流行的GNU Make和BSD Make,还有Windows平台的Microsoft nmake等。
Make由一个名为Makefile的脚本文件驱动,该文件使用Make自己定义的语法格式。其基本组成部分为一系列规则(Rules),而每一条规则又包括目标(Target)、依赖(Prerequisite)和命令(Command)。Makefile的基本结构如下:
&span style="font-size:"&TARGET… : PREREQUISITE…
Make通过一系列目标和依赖将整个构建过程串联起来,同时利用本地命令完成每个目标的实际行为。Make的强大之处在于它可以利用所有系统的本地命令,尤其是UNIX/Linux系统,丰富的功能、强大的命令能够帮助Make快速高效地完成任务。
但是,Make将自己和操作系统绑定在一起了。也就是说,使用Make,就不能实现(至少很难)跨平台的构建,这对于Java来说是非常不友好的。此外,Makefile的语法也成问题,很多人抱怨Make构建失败的原因往往是一个难以发现的空格或Tab使用错误。
Ant不是指蚂蚁,而是意指“另一个整洁的工具”(Another Neat Tool),它最早用来构建著名的Tomcat,其作者James Duncan Davidson创作它的动机就是因为受不了Makefile的语法格式。我们可以将Ant看成是一个Java版本的Make,也正因为使用了Java,Ant是跨平台的。此外,Ant使用XML定义构建脚本,相对于Makefile来说,这也更加友好。
与Make类似,Ant有一个构建脚本build.xml,如下所示:
&?xml version="1.0"?&
&project name="Hello" default="compile"&
&target name="compile" description="compile the Java source code to class files"&
&mkdir dir="classes"/&
&javac srcdir="." destdir="classes"/&
&target name="jar" depends="compile" description="create a Jar file "&
&jar destfile="hello.jar"&
&fileset dir="classes" includes="**/*.class"/&
&manifest&
&attribute name="Main.Class" value="HelloProgram"/&
&/manifest&
&/project&
build.xml的基本结构也是目标(target)、依赖(depends),以及实现目标的任务。比如在上面的脚本中,jar目标用来创建应用程序jar文件,该目标依赖于compile目标,后者执行的任务是创建一个名为classes的文件夹,编译当前目录的java文件至classes目录。compile目标完成后,jar目标再执行自己的任务。Ant有大量内置的用Java实现的任务,这保证了其跨平台的特质,同时,Ant也有特殊的任务exec来执行本地命令。
和Make一样,Ant也都是过程式的,开发者显式地指定每一个目标,以及完成该目标所需要执行的任务。针对每一个项目,开发者都需要重新编写这一过程,这里其实隐含着很大的重复。Maven是声明式的,项目构建过程和过程各个阶段所需的工作都由插件实现,并且大部分插件都是现成的,开发者只需要声明项目的基本元素,Maven就执行内置的、完整的构建过程。这在很大程度上消除了重复。
Ant是没有依赖管理的,所以很长一段时间Ant用户都不得不手工管理依赖,这是一个令人头疼的问题。幸运的是,Ant用户现在可以借助Ivy管理依赖。而对于Maven用户来说,依赖管理是理所当然的,Maven不仅内置了依赖管理,更有一个可能拥有全世界最多Java开源软件包的中央仓库,Maven用户无须进行任何配置就可以直接享用。
不重复发明轮子
【该小节内容整理自网友Arthas最早在Maven中文MSN的群内的讨论,在此表示感谢】
小张是一家小型民营软件公司的程序员,他所在的公司要开发一个新的Web项目。经过协商,决定使用Spring、iBatis和Tapstry。jar包去哪里找呢?公司里估计没有人能把Spring、iBatis和Tapstry所使用的jar包一个不少地找出来。大家的做法是,先到Spring的站点上去找一个spring.with.dependencies,然后去iBatis的网站上把所有列出来的jar包下载下来,对Tapstry、Apache commons等执行同样的操作。项目还没有开始,WEB.INF/lib下已经有近百个jar包了,带版本号的、不带版本号的、有用的、没用的、相冲突的,怎一个“乱”字了得!
在项目开发过程中,小张不时地发现版本错误和版本冲突问题,他只能硬着头皮逐一解决。项目开发到一半,经理发现最终部署的应用的体积实在太大了,要求小张去掉一些没用的jar包,于是小张只能加班加点地一个个删……
小张隐隐地觉得这些依赖需要一个框架或者系统来进行管理。
小张喜欢学习流行的技术,前几年Ant十分流行,他学了,并成为了公司这方面的专家。小张知道,Ant打包,无非就是创建目录,复制文件,编译源代码,使用一堆任务,如copydir、fileset、classpath、ref、target,然后再jar、zip、war,打包就成功了。
项目经理发话了:“兄弟们,新项目来了,小张,你来写Ant脚本!”
“是,保证完成任务!”接着,小张继续创建一个新的XML文件。 …… 不知道他是否想过,在他写的这么多的Ant脚本中,有多少是重复劳动,有多少代码会在一个又一个项目中重现。既然都差不多,有些甚至完全相同,为什么每次都要重新编写?
终于有一天,小张意识到了这个问题,想复用Ant脚本,于是在开会时他说:“以后就都用我这个规范的Ant脚本吧,新的项目只要遵循我定义的目录结构就可以了。”经理听后觉得很有道理:“嗯,确实是个进步。”
这时新来的研究生发言了:“经理,用Maven吧,这个在开源社区很流行,比Ant更方便。”小张一听很惊讶,Maven真比自己的“规范化Ant”强大?其实他不知道自己只是在重新发明轮子,Maven已经有一大把现成的插件,全世界都在用,你自己不用写任何代码!
为什么没有人说“我自己写的代码最灵活,所以我不用Spring,我自己实现IoC;我不用Hibernate,我自己封装JDBC”?
1.3 Maven与极限编程
极限编程(XP)是近些年在软件行业红得发紫的敏捷开发方法,它强调拥抱变化。该软件开发方法的创始人Kent Beck提出了XP所追求的价值、实施原则和推荐实践。下面看一下Maven是如何适应XP的。
首先看一下Maven如何帮助XP团队实现一些核心价值:
简单。Maven暴露了一组一致、简洁的操作接口,能帮助团队成员从原来的高度自定义的、复杂的构建系统中解脱出来,使用Maven现有的成熟的、稳定的组件也能简化构建系统的复杂度。
交流与反馈。与版本控制系统结合后,所有人都能执行最新的构建并快速得到反馈。此外,自动生成的项目报告也能帮助成员了解项目的状态,促进团队的交流。
此外,Maven更能无缝地支持或者融入到一些主要的XP实践中:
测试驱动开发(TDD)。TDD强调测试先行,所有产品都应该由测试用例覆盖。而测试是Maven生命周期的最重要的组成部分之一,并且Maven有现成的成熟插件支持业界流行的测试框架,如JUnit和TestNG。
十分钟构建。十分钟构建强调我们能够随时快速地从源码构建出最终的产品。这正是Maven所擅长的,只需要一些配置,之后用一条简单的命令就能让Maven帮你清理、编译、测试、打包、部署,然后得到最终的产品。
持续集成(CI)。CI强调项目以很短的周期(如15分钟)集成最新的代码。实际上,CI的前提是源码管理系统和构建系统。目前业界流行的CI服务器如Hudson和CruiseControl都能很好地和Maven进行集成。也就是说,使用Maven后,持续集成会变得更加方便。
富有信息的工作区。 这条实践强调开发者能够快速方便地了解到项目的最新状态。当然,Maven并不会帮你把测试覆盖率报告贴到墙上,也不会在你的工作台上放个鸭子告诉你构建失败了。不过使用Maven发布的项目报告站点,并配置你需要的项目报告,如测试覆盖率报告,都能帮你把信息推送到开发者眼前。
上述这些实践并非只在XP中适用。事实上,除了其他敏捷开发方法如SCRUM之外,几乎任何软件开发方法都能借鉴这些实践。也就是说,Maven几乎能够很好地支持任何软件开发方法。
例如,在传统的瀑布模型开发中,项目依次要经历需求开发、分析、设计、编码、测试和集成发布阶段。从设计和编码阶段开始,就可以使用Maven来建立项目的构建系统。在设计阶段,也完全可以针对设计开发测试用例,然后再编写代码来满足这些测试用例。然而,有了自动化构建系统,我们可以节省很多手动的测试时间。此外,尽早地使用构建系统集成团队的代码,对项目也是百利而无一害。最后,Maven还能帮助我们快速地发布项目。
第2章 Maven的安装和配置
第1章介绍了Maven是什么,以及为什么要使用Maven,我们将从本章实际开始实际接触Maven。本章首先将介绍如何在主流的操作系统下安装Maven,并详细解释Maven的安装文件;其次还会介绍如何在主流的IDE中集成Maven,以及Maven安装的最佳实践。
2.1 在Windows上安装Maven
2.2 在基于Unix的系统上安装Maven
2.3 安装目录分析
2.4 设置HTTP代理
2.5 安装m2eclipse
2.6 安装NetBeans Maven插件
2.7 Maven安装最佳实践
2.1 在Windows上安装Maven
2.1.1 检查JDK安装
在安装Maven之前,首先要确认你已经正确安装了JDK。Maven可以运行在JDK 1.4及以上的版本上。本书的所有样例都基于JDK 5及以上版本。打开Windows的命令行,运行如下的命令来检查你的Java安装:
C:\Users\Juven Xu&echo %JAVA_HOME%
C:\Users\Juven Xu&java -version
结果如图2-1所示:
图2-1 Windows中检查Java安装
上述命令首先检查环境变量JAVA_HOME是否指向了正确的JDK目录,接着尝试运行java命令。如果Windows无法执行java命令,或者无法找到JAVA_HOME环境变量。你就需要检查Java是否安装了,或者环境变量是否设置正确。关于环境变量的设置,请参考2.1.3节。
2.1.2 下载Maven
请访问Maven的下载页面:,其中包含针对不同平台的各种版本的Maven下载文件。对于首次接触Maven的读者来说,推荐使用Maven 3.0,,因此下载apache-maven-3.0-bin.zip。当然,如果你对Maven的源代码感兴趣并想自己构建Maven,还可以下载apache-maven-3.0
-src.zip。该下载页面还提供了md5校验和(checksum)文件和asc数字签名文件,可以用来检验Maven分发包的正确性和安全性。
在本书编写的时候,Maven 2的最新版本是2.2.1,Maven 3基本完全兼容Maven 2,而且较之于Maven 2它性能更好,还有不少功能的改进,如果你之前一直使用Maven 2,现在正犹豫是否要升级,那就大可不必担心了,快点尝试下Maven 3吧!
2.1.3 本地安装
将安装文件解压到你指定的目录中,如:
D:\bin&jar xvf "C:\Users\Juven Xu\Downloads\apache-maven-3.0--bin.zip"
这里的Maven安装目录是D:\bin\apache-maven-3.0,接着需要设置环境变量,将Maven安装配置到操作系统环境中。
打开系统属性面板(桌面上右键单击“我的电脑”→“属性”),点击高级系统设置,再点击环境变量,在系统变量中新建一个变量,变量名为M2_HOME,变量值为Maven的安装目录D:\bin\apache-maven-3.0。点击确定,接着在系统变量中找到一个名为Path的变量,在变量值的末尾加上%M2_HOME%\,注意多个值之间需要有分号隔开,然后点击确定。至此,环境变量设置完成,详细情况如图2-2所示:
图2-2 Windows中系统环境变量配置
这里需要提一下的是Path环境变量,当我们在cmd中输入命令时,Windows首先会在当前目录中寻找可执行文件或脚本,如果没有找到,Windows会接着遍历环境变量Path中定义的路径。由于我们将%M2_HOME%\bin添加到了Path中,而这里%M2_HOME%实际上是引用了我们前面定义的另一个变量,其值是Maven的安装目录。因此,Windows会在执行命令时搜索目录D:\bin\apache-maven-3.0\bin,而mvn执行脚本的位置就是这里。
明白了环境变量的作用,现在打开一个新的cmd窗口(这里强调新的窗口是因为新的环境变量配置需要新的cmd窗口才能生效),运行如下命令检查Maven的安装情况:
C:\Users\Juven Xu&echo %M2_HOME%
C:\Users\Juven Xu&mvn -v
运行结果如图2-3所示:
图2-3 Windows中检查Maven安装
第一条命令echo %M2_HOME%用来检查环境变量M2_HOME是否指向了正确的Maven安装目录;而mvn –version执行了第一条Maven命令,以检查Windows是否能够找到正确的mvn执行脚本。
2.1.4 升级Maven
Maven还比较年轻,更新比较频繁,因此用户往往会需要更新Maven安装以获得更多更酷的新特性,以及避免一些旧的bug。
在Windows上更新Maven非常简便,只需要下载新的Maven安装文件,解压至本地目录,然后更新M2_HOME环境变量便可。例如,假设Maven推出了新版本3.1,我们将其下载然后解压至目录D:\bin\apache-maven-3.1,接着遵照前一节描述的步骤编辑环境变量M2_HOME,更改其值为D:\bin\apache-maven-3.1。至此,更新就完成了。同理,如果你需要使用某一个旧版本的Maven,也只需要编辑M2_HOME环境变量指向旧版本的安装目录。
2.2 在基于Unix的系统上安装Maven
Maven是跨平台的,它可以在任何一种主流的操作系统上运行,本节将介绍如何在基于Unix的系统(包括Linux、Mac OS以及FreeBSD等)上安装Maven。
2.2.1 下载和安装
首先,与在Windows上安装Maven一样,需要检查JAVA_HOME环境变量以及Java命令,细节不再赘述,命令如下:
juven@juven-ubuntu:~$ echo $JAVA_HOME
juven@juven-ubuntu:~$ java –version
运行结果如图2-4所示:
图2-4 Linux中检查Java安装
接着到http://maven.apache.org/download.html下载Maven安装文件,如apache-maven-3.0-bin.tar.gz,然后解压到本地目录:
juven@juven-ubuntu:bin$ tar -xvzf apache-maven-3.0-bin.tar.gz
现在已经创建好了一个Maven安装目录apache-maven-3.0,虽然直接使用该目录配置环境变量之后就能使用Maven了,但这里我更推荐做法是,在安装目录旁平行地创建一个符号链接,以方便日后的升级:
juven@juven-ubuntu:bin$ ln -s apache-maven-3.0 apache-maven
juven@juven-ubuntu:bin$ ls -l
lrwxrwxrwx 1 juven juven
15:43 apache-maven -& apache-maven-3.0
drwxr-xr-x 6 juven juven -20 15:39 apache-maven-3.0
接下来,我们需要设置M2_HOME环境变量指向符号链接apache-maven-,并且把Maven安装目录下的bin/文件夹添加到系统环境变量PATH中去:
juven@juven-ubuntu:bin$ export M2_HOME=/home/juven/bin/apache-maven
juven@juven-ubuntu:bin$ export PATH=$PATH:$M2_HOME/bin
一般来说,需要将这两行命令加入到系统的登录shell脚本中去,以我现在的Ubuntu 8.10为例,编辑~/.bashrc文件,添加这两行命令。这样,每次启动一个终端,这些配置就能自动执行。
至此,安装完成,我们可以运行以下命令检查Maven安装:
juven@juven-ubuntu:bin$ echo $M2_HOME
juven@juven-ubuntu:bin$ mvn –version
运行结果如图2-5所示:
图2-5 Linux中检查Maven安装
2.2.2 升级Maven
在基于Unix的系统上,可以利用符号链接这一工具来简化Maven的升级,不必像在Windows上那样,每次升级都必须更新环境变量。
前一小节中我们提到,解压Maven安装包到本地之后,平行地创建一个符号链接,然后在配置环境变量时引用该符号链接,这样做是为了方便升级。现在,假设我们需要升级到新的Maven 3.1版本,同理,将安装包解压到与前一版本平行的目录下,然后更新符号链接指向3.1版的目录便可:
juven@juven-ubuntu:bin$ rm apache-maven
juven@juven-ubuntu:bin$ ln -s apache-maven-3.1/ apache-maven
juven@juven-ubuntu:bin$ ls -l
lrwxrwxrwx 1 juven juven
16:13 apache-maven -& apache-maven-3.1 /
drwxr-xr-x 6 juven juven -20 15:39 apache-maven-3.0drwxr-xr-x 2 juven juven -20 16:09 apache-maven-3.1
同理,可以很方便地切换到Maven的任意一个版本。现在升级完成了,可以运行mvn -v进行检查。
2.3 安装目录分析
本章前面的内容讲述了如何在各种操作系统中安装和升级Maven。现在我们来仔细分析一下Maven的安装文件。
2.3.1 M2_HOME
前面我们讲到设置M2_HOME环境变量指向Maven的安装目录,本书之后所有使用M2_HOME的地方都指代了该安装目录,让我们看一下该目录的结构和内容:
LICENSE.txt
NOTICE.txt
README.txt
Bin: 该目录包含了mvn运行的脚本,这些脚本用来配置Java命令,准备好classpath和相关的Java系统属性,然后执行Java命令。其中mvn是基于UNIX平台的shell脚本,mvn.bat是基于Windows平台的bat脚本。在命令行输入任何一条mvn命令时,实际上就是在调用这些脚本。该目录还包含了mvnDebug和mvnDebug.bat两个文件,同样,前者是UNIX平台的shell脚本,后者是windows的bat脚本。那么mvn和mvnDebug有什么区别和关系呢?打开文件我们就可以看到,两者基本是一样的,只是mvnDebug多了一条MAVEN_DEBUG_OPTS配置,作用就是在运行Maven时开启debug,以便调试Maven本身。此外,该目录还包含m2.conf文件,这是classworlds的配置文件,稍微会介绍classworlds。
Boot: 该目录只包含一个文件,以maven 3.0为例,该文件为plexus-classworlds-2.2.3.jar。plexus-classworlds是一个类加载器框架,相对于默认的java类加载器,它提供了更丰富的语法以方便配置,Maven使用该框架加载自己的类库。更多关于classworlds的信息请参考。对于一般的Maven用户来说,不必关心该文件。
Conf: 该目录包含了一个非常重要的文件settings.xml。直接修改该文件,就能在机器上全局地定制Maven的行为。一般情况下,我们更偏向于复制该文件至~/.m2/目录下(这里~表示用户目录),然后修改该文件,在用户范围定制Maven的行为。本书的后面将会多次提到该settings.xml,并逐步分析其中的各个元素。
Lib: 该目录包含了所有Maven运行时需要的Java类库,Maven本身是分模块开发的,因此用户能看到诸如mavn-core-3.0.jar、maven-model-3.0.jar之类的文件,此外这里还包含一些Maven用到的第三方依赖如common-cli-1.2.jar、google-collection-1.0.jar等等。(对于Maven 2来说,该目录只包含一个如maven-2.2.1-uber.jar的文件原本各为独立JAR文件的Maven模块和第三方类库都被拆解后重新合并到了这个JAR文件中)。可以说,这个lib目录就是真正的Maven。关于该文件,还有一点值得一提的是,用户可以在这个目录中找到Maven内置的超级POM,这一点在8.5小节详细解释。其他:
LICENSE.txt记录了Maven使用的软件许可证Apache License Version 2.0; NOTICE.txt记录了Maven包含的第三方软件;而README.txt则包含了Maven的简要介绍,包括安装需求及如何安装的简要指令等等。
2.3.2 ~/.m2
在讲述该小节之前,我们先运行一条简单的命令:mvn help:system。该命令会打印出所有的Java系统属性和环境变量,这些信息对我们日常的编程工作很有帮助。这里暂不解释help:system涉及的语法,运行这条命令的目的是为了让Maven执行一个真正的任务。我们可以从命令行输出看到Maven会下载maven-help-plugin,包括pom文件和jar文件。这些文件都被下载到了Maven本地仓库中。
现在打开用户目录,比如当前的用户目录是C:\Users\Juven Xu\,你可以在Vista和Windows7中找到类似的用户目录。如果是更早版本的Windows,该目录应该类似于C:\Document and Settings\Juven Xu\。在基于Unix的系统上,直接输入cd
回车,就可以转到用户目录。为了方便,本书统一使用符号 ~ 指代用户目录。
在用户目录下,我们可以发现.m2文件夹。默认情况下,该文件夹下放置了Maven本地仓库.m2/repository。所有的Maven构件(artifact)都被存储到该仓库中,以方便重用。我们可以到~/.m2/repository/org/apache/maven/plugins/maven-help-plugins/目录下找到刚才下载的maven-help-plugin的pom文件和jar文件。Maven根据一套规则来确定任何一个构件在仓库中的位置,这一点本书第6章将会详细阐述。由于Maven仓库是通过简单文件系统透明地展示给Maven用户的,有些时候可以绕过Maven直接查看或修改仓库文件,在遇到疑难问题时,这往往十分有用。
默认情况下,~/.m2目录下除了repository仓库之外就没有其他目录和文件了,不过大多数Maven用户需要复制M2_HOME/conf/settings.xml文件到~/.m2/settings.xml。这是一条最佳实践,我们将在本章最后一小节详细解释。
2.4 设置HTTP代理
有时候你所在的公司由于安全因素考虑,要求你使用通过安全认证的代理访问因特网。这种情况下,就需要为Maven配置HTTP代理,才能让它正常访问外部仓库,以下载所需要的资源。
首先确认自己无法直接访问公共的Maven中央仓库,直接运行命令ping repo1.maven.org可以检查网络。如果真的需要代理,先检查一下代理服务器是否畅通,比如现在有一个IP地址为218.14.227.197,端口为3128的代理服务,我们可以运行telnet 218.14.227.197 3128来检测该地址的该端口是否畅通。如果得到出错信息,需要先获取正确的代理服务信息;如果telnet连接正确,则输入ctrl+],然后q,回车,退出即可。
检查完毕之后,编辑~/.m2/settings.xml文件(如果没有该文件,则复制$M2_HOME/conf/settings.xml)。添加代理配置如下:
&settings&
&id&my-proxy&/id&
&active&true&/active&
&protocol&http&/protocol&
&host&218.14.227.197&/host&
&port&3128&/port&
&username&***&/username&
&password&***&/password&
&nonProxyHosts&repository.mycom.com|*.google.com&/nonProxyHosts&
&/proxies&
&/settings&
这段配置十分简单,proxies下可以有多个proxy元素,如果你声明了多个proxy元素,则默认情况下第一个被激活的proxy会生效。这里声明了一个id为my-proxy的代理,active的值为true表示激活该代理,protocol表示使用的代理协议,这里是http。当然,最重要的是指定正确的主机名(host元素)和端口(port元素)。上述XML配置中我注释掉了username、password、nonProxyHost几个元素,当你的代理服务需要认证时,就需要配置username和password。nonProxyHost元素用来指定哪些主机名不需要代理,可以使用
| 符号来分隔多个主机名。此外,该配置也支持通配符,如*.google.com表示所有以google.com结尾的域名访问都不要通过代理。
2.5 安装m2eclipse
Eclipse是一款非常优秀的IDE。除了基本的语法标亮、代码补齐、XML编辑等基本功能外,最新版的Eclipse还能很好地支持重构,并且集成了JUnit、CVS、Mylyn等各种流行工具。可惜Eclipse默认没有集成对Maven的支持。幸运的是,由Maven之父Jason Van Zyl创立的Sonatype公司建立了m2eclipse项目,这是Eclipse下的一款十分强大的Maven插件,可以访问
了解更多该项目的信息。
本小节将先介绍如何安装m2eclipse插件,本书后续的章节会逐步介绍m2eclipse插件的使用。
现在我以Eclipse 3.6为例逐步讲解m2eclipse的安装。启动Eclipse之后,在菜单栏中选择Help,然后选择Install New Software…,接着你会看到一个Install对话框,点击Work with:字段边上的Add按钮,你会得到一个新的Add Repository对话框,在Name字段中输入m2e,Location字段中输入,然后点击OK。Eclipse会下载m2eclipse安装站点上的资源信息。等待资源载入完成之后,我们再将其全部展开,就能看到图2-6所示的界面:
m2eclipse的核心安装资源列表
如图显示了m2eclipse的核心模块Maven Integration for Eclipse (Required),选择后点击Next &,Eclipse会自动计算模块间依赖,然后给出一个将被安装的模块列表,确认无误后,继续点击Next &,这时我们会看到许可证信息,m2eclipse使用的开源许可证是Eclipse Public License v1.0,选择I accept the terms of the license
agreements,然后点击Finish,接着就耐心等待Eclipse下载安装这些模块,如图2-7所示:
图2-7:m2eclipse安装进度
除了核心组件之外,m2eclipse还提供了一组额外组件,主要是为了方便与其它工具如Subversion进行集成,这些组件的安装地址为。使用前面类似的安装方法,我们可以看到如图2-8的组件列表:
图2-8:m2eclipse的额外组件安装资源列表
下面简单解释一下这些组件的用途:
Maven SCM handler for Subclipse
(Optional):Subversion是非常流行的版本管理工具,该模块能够帮助我们直接从Subversion服务器签出Maven项目,不过前提是需要首先安装Subclipse()。
Maven SCM Integration (Optional):Eclipse环境中Maven与SCM集成核心的模块,它利用各种SCM工具如SVN实现Maven项目的签出和具体化等操作。
2. 不重要的
Maven issue tracking configurator for Mylyn 3.x (Optional):该模块能够帮助我们使用POM中的缺陷跟踪系统信息连接Mylyn至服务器。
Maven SCM handler for Team/CVS (Optional):该模块帮助我们从CVS服务器签出Maven项目,如果你还在使用CVS,就需要安装它。
Maven Integration for WTP (Optional):使用该模块可以让Eclipse自动读取POM信息并配置WTP项目。、
M2eclipse Extensions Development Support (Optional):用来支持扩展m2eclipse,一般用户不会用到。
Project configurators for commonly used maven plugins (temporary):一个临时的组件,用来支持一些Maven插件与Eclipse的集成,建议安装。
读者可以根据自己的需要安装相应组件,具体步骤不再赘述。
待安装完毕后,重启Eclipse,现在让我们验证一下m2eclipse是否正确安装了。首先,点击菜单栏中的Help,然后选择About Eclipse,在弹出的对话框中,点击Installation Details按钮,会得到一个对话框,在Installed Software标签栏中,检查刚才我们选择的模块是否在这个列表中,如图2-9所示:
图2-9m2eclipse安装结果
如果一切没问题,我们再检查一下Eclipse现在是否已经支持创建Maven项目,依次点击菜单栏中的File→New→Other,在弹出的对话框中,找到Maven一项,再将其展开,你应该能够看到如图2-10所示的对话框:
图2-10 Eclipse中创建Maven项目向导
如果一切正常,说明m2eclipse已经正确安装了。
最后,关于m2eclipse的安装,需要提醒的一点是,你可能会在使用m2eclipse时遇到类似这样的错误:
09-10-6 上午01时14分49秒: Eclipse is running in a JRE, but a JDK is required
Some Maven plugins may not work when importing projects or updating source folders.
这是因为Eclipse默认是运行在JRE上的,而m2eclipse的一些功能要求使用JDK,解决方法是配置Eclipse安装目录的eclipse.ini文件,添加vm配置指向JDK,如:
--launcher.XXMaxPermSize
D:\java\jdk1.6.0_07\bin\javaw.exe
-Dosgi.requiredJavaVersion=1.5
2.6 安装NetBeans Maven插件
本小节会先介绍如何在NetBeans上安装Maven插件,后面的章节中还会介绍NetBeans中具体的Maven操作。
首先,如果你正在使用NetBeans 6.7及以上版本,那么Maven插件已经预装了。你可以检查Maven插件安装,点击菜单栏中的工具,接着选择插件,在弹出的插件对话框中选择已安装标签,你应该能够看到Maven插件,如图2-11所示:
图2-11 已安装的NetBeans Maven插件
如果你在使用NetBeans 6.7之前的版本,或者由于某些原因NetBeans Maven插件被卸载了,那么你就需要安装NetBeans Maven插件,下面我们以NetBeans 6.1为例,介绍Maven插件的安装。
同样,点击菜单栏中的工具,选择插件,在弹出的插件对话框中选择可用插件标签,接着在右边的搜索框内输入Maven,这时你会在左边的列表中看到一个名为Maven的插件,选择该插件,然后点击下面的安装按钮,如图2-12所示:
图2-12 安装NetBeans Maven插件
接着在随后的对话框中根据提示操作,阅读相关许可证并接受,NetBeans会自动帮我们下载并安装Maven插件,结束之后会提示安装完成,之后再点击插件对话框的已安装标签,就能看到已经激活的Maven插件。
最后,为了确认Maven插件确实已经正确安装了,可以看一下NetBeans是否已经拥有创建Maven项目的相关菜单。在菜单栏中选择文件,然后选择新建项目,这时应该能够看到项目类别中有Maven一项,选择该类别,右边会相应地显示Maven项目和基于现有POM的Maven项目,如图2-13所示:
图2-13 NetBeans中创建Maven项目向导
如果你能看到类似的对话框,说明NetBeans Maven已经正确安装了。
2.7 Maven安装最佳实践
本节介绍一些在安装Maven过程中不是必须的,但十分有用的实践。
2.7.1 设置MAVEN_OPTS环境变量
本章前面介绍Maven安装目录时我们了解到,运行mvn命令实际上是执行了Java命令,既然是运行Java,那么运行Java命令可用的参数当然也应该在运行mvn命令时可用。这个时候,MAVEN_OPTS环境变量就能派上用场。
我们通常需要设置MAVEN_OPTS的值为:-Xms128m -Xmx512m,因为Java默认的最大可用内存往往不能够满足Maven运行的需要,比如在项目较大时,使用Maven生成项目站点需要占用大量的内存,如果没有该配置,我们很容易得到java.lang.OutOfMemeoryError。因此,一开始就配置该变量是推荐的做法。
关于如何设置环境变量,请参考前面设置M2_HOME环境变量的做法,尽量不要直接修改mvn.bat或者mvn这两个Maven执行脚本文件。因为如果修改了脚本文件,升级Maven时你就不得不再次修改,一来麻烦,二来容易忘记。同理,我们应该尽可能地不去修改任何Maven安装目录下的文件。
2.7.2 配置用户范围settings.xml
Maven用户可以选择配置$M2_HOME/conf/settings.xml或者~/.m2/settings.xml。前者是全局范围的,整台机器上的所有用户都会直接受到该配置的影响,而后者是用户范围的,只有当前用户才会受到该配置的影响。
我们推荐使用用户范围的settings.xml,主要原因是为了避免无意识地影响到系统中的其他用户。当然,如果你有切实的需求,需要统一系统中所有用户的settings.xml配置,当然应该使用全局范围的settings.xml。
除了影响范围这一因素,配置用户范围settings.xml文件还便于Maven升级。直接修改conf目录下的settings.xml会导致Maven升级不便,每次升级到新版本的Maven,都需要复制settings.xml文件,如果使用~/.m2目录下的settings.xml,就不会影响到Maven安装文件,升级时就不需要触动settings.xml文件。
2.7.3 不要使用IDE内嵌的Maven
无论是Eclipse还是NetBeans,当我们集成Maven时,都会安装上一个内嵌的Maven,这个内嵌的Maven通常会比较新,但不一定很稳定,而且往往也会和我们在命令行使用的Maven不是同一个版本。这里有会出现两个潜在的问题:首先,较新版本的Maven存在很多不稳定因素,容易造成一些难以理解的问题;其次,除了IDE,我们也经常还会使用命令行的Maven,如果版本不一致,容易造成构建行为的不一致,这是我们所不希望看到的。因此,我们应该在IDE中配置Maven插件时使用与命令行一致的Maven。
在m2eclipse环境中,点击菜单栏中的Windows,然后选择Preferences,在弹出的对话框中,展开左边的Maven项,选择Installation子项,在右边的面板中,我们能够看到有一个默认的Embedded Maven安装被选中了,点击Add…然后选择我们的Maven安装目录M2_HOME,添加完毕之后选择这一个外部的Maven,如图2-14所示:
图2-14 在Eclipse中使用外部Maven
NetBeans Maven插件默认会侦测PATH环境变量,因此会直接使用与命令行一致的Maven环境。依次点击菜单栏中的工具→选项→其他→Maven标签栏,你就能看到如图2-15所示的配置:
图2-15 在NetBeans中使用外部Maven
本章详细介绍了在各种操作系统平台上安装Maven,并对Maven安装目录进行了深入的分析,在命令行的基础上,本章又进一步介绍了Maven与主流IDE Eclipse及NetBeans的集成,本章最后还介绍了一些与Maven安装相关的最佳实践。本书下一章会创建一个Hello World项目,带领读者配置和构建Maven项目。
第3章 Maven使用入门
到目前为止,我们已经大概了解并安装好了Maven,现在,我们开始创建一个最简单的Hello World项目。如果你是初次接触Maven,我建议你按照本章的内容一步步地编写代码并执行,可能你会碰到一些概念暂时难以理解,不用着急,记下这些疑难点,相信本书的后续章节会帮你逐一解答。
3.1 编写POM
3.2 编写主代码
3.3 编写测试代码
3.4 打包和运行
3.5 使用Archetype生成项目骨架
3.6 m2eclipse简单使用
3.7 NetBeans Maven插件简单使用
3.1 编写POM
就像Make的Makefile,Ant的build.xml一样,Maven项目的核心是pom.xml。POM(Project
Object Model,项目对象模型)定义了项目的基本信息,用于描述项目如何构建,声明项目依赖,等等。现在我们先为Hello World项目编写一个最简单的pom.xml。
首先创建一个名为hello-world的文件夹(本书中各章的代码都会对应一个以ch开头的项目),打开该文件夹,新建一个名为pom.xml的文件,输入其内容如代码清单3-1:
代码清单3-1:Hello World的POM
&span style="font-size:"&&?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/maven-v4_0_0.xsd"&
&modelVersion&4.0.0&/modelVersion&
&groupId&com.juvenxu.mvnbook&/groupId&
&artifactId&hello-world&/artifactId&
&version&1.0-SNAPSHOT&/version&
&name&Maven Hello World Project&/name&
&/project&
代码的第一行是XML头,指定了该xml文档的版本和编码方式。紧接着是project元素,project是所有pom.xml的根元素,它还声明了一些POM相关的命名空间及xsd元素,虽然这些属性不是必须的,但使用这些属性能够让第三方工具(如IDE中的XML编辑器)帮助我们快速编辑POM。
根元素下的第一个子元素modelVersion指定了当前POM模型的版本,对于Maven2及Maven 3来说,它只能是4.0.0。
这段代码中最重要的是groupId,artifactId和version三行。这三个元素定义了一个项目基本的坐标,在Maven的世界,任何的jar、pom或者war都是以基于这些基本的坐标进行区分的。
groupId定义了项目属于哪个组,这个组往往和项目所在的组织或公司存在关联,譬如你在googlecode上建立了一个名为myapp的项目,那么groupId就应该是com.googlecode.myapp,如果你的公司是mycom,有一个项目为myapp,那么groupId就应该是com.mycom.myapp。本书中所有的代码都基于groupId com.juvenxu.mvnbook。
artifactId定义了当前Maven项目在组中唯一的ID,我们为这个Hello World项目定义artifactId为hello-world,本书其他章节代码会被分配其他的artifactId。而在前面的groupId为com.googlecode.myapp的例子中,你可能会为不同的子项目(模块)分配artifactId,如:myapp-util、myapp-domain、myapp-web等等。
顾名思义,version指定了Hello World项目当前的版本——1.0-SNAPSHOT。SNAPSHOT意为快照,说明该项目还处于开发中,是不稳定的版本。随着项目的发展,version会不断更新,如升级为1.0、1.1-SNAPSHOT、1.1、2.0等等。本书的6.5小节会详细介绍SNAPSHOT,第13章介绍如何使用Maven管理项目版本的升级发布。
最后一个name元素声明了一个对于用户更为友好的项目名称,虽然这不是必须的,但我还是推荐为每个POM声明name,以方便信息交流。
没有任何实际的Java代码,我们就能够定义一个Maven项目的POM,这体现了Maven的一大优点,它能让项目对象模型最大程度地与实际代码相独立,我们可以称之为解耦,或者正交性,这在很大程度上避免了Java代码和POM代码的相互影响。比如当项目需要升级版本时,只需要修改POM,而不需要更改Java代码;而在POM稳定之后,日常的Java代码开发工作基本不涉及POM的修改。
3.2 编写主代码
项目主代码和测试代码不同,项目的主代码会被打包到最终的构件中(比如jar),而测试代码只在运行测试时用到,不会被打包。默认情况下,Maven假设项目主代码位于src/main/java目录,我们遵循Maven的约定,创建该目录,然后在该目录下创建文件com/juvenxu/mvnbook/helloworld/HelloWorld.java,其内容如代码清单3-2:
代码清单3-2:Hello World的主代码
&span style="font-size:"&package com.juvenxu.mvnbook.
public class HelloWorld
public String sayHello()
return "Hello Maven";
public static void main(String[] args)
System.out.print( new HelloWorld().sayHello() );
这是一个简单的Java类,它有一个sayHello()方法,返回一个String。同时这个类还带有一个main方法,创建一个HelloWorld实例,调用sayHello()方法,并将结果输出到控制台。
关于该Java代码有两点需要注意。首先,在95%以上的情况下,我们应该把项目主代码放到src/main/java/目录下(遵循Maven的约定),而无须额外的配置,Maven会自动搜寻该目录找到项目主代码。其次,该Java类的包名是com.juvenxu.mvnbook.helloworld,这与我们之前在POM中定义的groupId和artifactId相吻合。一般来说,项目中Java类的包都应该基于项目的groupId和artifactId,这样更加清晰,更加符合逻辑,也方便搜索构件或者Java类。
代码编写完毕后,我们使用Maven进行编译,在项目根目录下运行命令 mvn clean compile ,我们会得到如下输出:
&span style="font-size:"&[INFO] Scanning for projects...
[INFO] ------------------------------------------------------------------------
[INFO] Building Maven Hello World Project
task-segment: [clean, compile]
[INFO] ------------------------------------------------------------------------
[INFO] [clean:clean {execution: default-clean}]
[INFO] Deleting directory D:\code\hello-world\target
[INFO] [resources:resources {execution: default-resources}]
[INFO] skip non existing resourceDirectory D: \code\hello-world\src\main\resources
[INFO] [compiler:compile {execu
【上篇】【下篇】

我要回帖

更多关于 战舰世界数据端口 的文章

 

随机推荐