到目前为止(未来有很多不可预知的事),Java应该还是企业级应用开发的首选,基于Java开发的企业级应用软件架构也是经历了一代又一代,从最初的jsp+javabean+servlet,到后来流行的MVC架构SSH,再到目前的“百花齐放”——涌现出了太多的开发框架。
在这个已经到来的“云时代”,如何让我们开发的软件具备很好的“云感知”能力呢? 不管你选择什么样的框架,什么样的技术,从我这几年的工作经验来看,大部分还是要通过软件架构层面的调整,才能让我们的软件更有生命力。
关于企业级应用开发,我将会介绍一些工具、一些架构层面的东西,希望能有助于让各位程序员能开发出能跑在云环境下的应用。今天给大家首先带来的是Maven。
maven
有将项目打好war包部置到生产环境后报各种错误的经历吗?
有到处找jar包的经历吗?
有各种jar包冲突导致的各种错误的经历吗?
也许你们都没有,但我真的遇到很多,几乎每一个项目都会遇到,直到遇到了Maven,这些大部分问题都得到了解决。
应用商店
2008年7月11日,苹果APP Store正式上线,开创了软件销售的全新模式,App Store模式的意义在于为第三方软件的提供者提供了一个统一的软件销售平台。这真的是苹果的创新成果吗?从商业角度出发,我们必须承认,但从技术上来说,Linux社区在很久很久以前,就使用了“软件仓库”来集中管理软件包,同时也通过软件层面解决了软件包之间的依赖问题。如ubuntu上的apt-get, CentOS上的yum都是非常好的软件包管理工具,它们的前提就是有一个集中存放软件的中央仓库。
这几年随着软件技术有发展,大部分开发语言都吸取了Linux的软件仓库精华,都有自己的模块(或软件)依赖管理工具,如ruby的gem,python的pip,nodejs的npm等。
Maven也解决了Java开发中最让人闹心的jar包管理问题,让开发人员不用再到处找jar包,然后复制到lib目录,添加到classpath……,当然Maven能做的事远远不止这些。
Maven是一个项目管理工具,它包含了一个项目对象模型 (Project Object Model),一组标准集合,一个项目生命周期(Project Lifecycle),一个依赖管理系统(Dependency Management System),和用来运行定义在生命周期阶段(phase)中插件(plugin)目标(goal)的逻辑。当你使用Maven的时候,你用一个明确定义的项目对象模型来描述你的项目,然后Maven可以应用横切的逻辑,这些逻辑来自一组共享的(或者自定义的)插件。
火速入门
从一开始我对本书的定义就不是一本纯技术的书,所以本节只会简单介绍Maven的使用,如果想更深入的了解Maven,请参考和Maven相关的专业书籍或google。
师傅领进门,修行在个人
jar包管理基本原理
如下图所示,Maven通过统一的存储库来保存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包一起放到版本控制工具,而现在结合公司的Repository,这些jar包就不再需要加入到版本控制工具(如SVN)中了,这大大减少了项目文件所占用的空间(这样说或许有些牵强)。
安装与配置
以Ubuntu为例,执行如下命令即完成Maven的安装:
sudo apt-get install maven
Maven配置文件默认在~/.m2/settings.xml,在配置文件中可以配置代理服务器、用户认证信息、远程仓库地址、插件仓库地址等。
详细的配置项和说明可见:http://maven.apache.org/settings.html
如果找不到这个文件,可以从Maven安装目录下conf/settings.xml文件拷贝到~/.m2/目录。
Maven的使用
在正式开始之前,先来介绍一个概念:Archetype
每个公司经过长期的技术积累,虽然是不同的项目,但项目的代码基本结构、代码的打包方式基本是相同的。
Archetype是一个Maven项目模板管理工具,我们可以把前面说的项目一些共性的东西做成一个模板,在新项目开始的时候,只可使用Archetype直接初始化项目开发环境。在本文中我们就把Archetype理解为项目模板,在写本节时,在Maven公共仓库(http://search.maven.org/)中的Archetype已达1098个,对于常见的项目,我们可以直接基于这个Archetype创建初始环境即可。
下面我们开始新建一个项目,我们基于Maven公共仓库中的Archetype:spring-mvc-archetype为基于开始我们的项目。
执行如下命令:
mvn archetype:generate -DgroupId=com.mycompany.app -DartifactId=my-app -DarchetypeGroupId=co.ntier -DarchetypeArtifactId=spring-mvc-archetype -DinteractiveMode=false
相关参数说明:
- DgroupID : Java包名
- DartifactID : 项目名称(会做为生成项目目录)
- DarchetypeGroupId: 模板所属组织ID,默认值为:org.apache.maven.archetypes(这里很容易出错哦,一定要指定模板的组织ID,要不然会报找不到模板。
- DarchetypeArtifactId:模板名称
- DinteractiveMode : 是否与maven交互,如果为true,会提示输入包名、版本号等信息,false时,都使用默认值
执行完命令后,会生成如下目录结构:
└── 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目录,执行如下命令:
cd my-app
mvn package
您将看到maven会到maven远程仓库将pom.xml中声明的依赖包下载到本地,然后执行打包。
命令执行完后,您将看到在target目录下生成了my-app.war的包,拿着这个包就可以去部署到各种java中间件上了。是不是很方便。
前面介绍过,maven并不是单纯的jar包依赖管理工具,Maven是一个项目管理工具,它包含了一个项目对象模型 (Project Object Model),因此,除了管理jar包依赖,它还包括项目管理过程中常用的很多工具。
我们可以在根目录下建立test目录,将java测试用例放到下面,然后在命令行执行mvn test
,就能看到测试结果,看测试有没有发生错误等。
对于开发人员,经常使用tomcat来开发的话,整个过程是很简单的。在刚才的my-app项目根目录执行:mvn tomcat:run
,然后打开浏览器:http://localhost:8080/my-app ,您就将看到运行结果。没想到吧,都不用安装tomcat,全部通过maven就能搞定。
如果您是在开发一个纯java模块,那就执行:mvn install
就可以把jar包发布到本地Repository,然后就可以在别的项目里引用这个jar包了,借助一些插件就可以把它发布到公司的统一Repository库中。
Maven还有很多很多的功能,本书maven就介绍到这里,详细的关于Maven的知识可以参考一些专业的书籍或官方文档。最后推荐您将下面的项目clone到本地来深入学习:
https://github.com/spring-projects/spring-mvc-showcase
git clone git://github.com/SpringSource/spring-mvc-showcase.git
国际范程序必读:
程序员的编辑器-VIM(爱就是爱)
向开源社区贡献您的代码
在github上写博客
DevOps是什么东东?
js依赖管理工具bower
JS模块化编程-requirejs