没有比人更高的山

Appfuse中文教程0

现在的Web应用开发人员是幸福的,有如此多的选择,Web层有Sturts2、JSF、Spring MVC、Tapestry等,持久层可以选择Hibernate、iBATIS或者JPA等,还有极为强大的Spring作为粘合剂,完美地运行时自动创 建所需的一切对象(依赖注入)。然而我们这些开发人员也是不幸的,因为要让一切完美的运行有太多太多的配置——XML、Annotation甚至是 Properties文件。当开始一个新项目时,要搭建起一个能正常运行、能真正简化开发、能真正实现模块化开发的Web应用开发骨架太难了,更不用说还 要加入DbUnit等自动测试框架。

但是有了Appfuse,一切变得简单起来,Appfuse是一个开源的Web应用骨架生成工具,支持上文提到的任何一种开发工具的组合,包括Web Services、工作流、任务调度等,能方便的生成Web开发中常用CRUD骨架,够诱人了吧。

吹了这么多,Appfuse其实很简单,你甚至不需要下载,因为她实质上是一个Maven插件,你运行mvn命令时,maven会自动帮你搞定任何事情,也就是说你只需要知道命令就行了,而且实际上你也不需要记住命令,http://appfuse.org/display/APF/AppFuse+QuickStart+-+Chinese 这个页面可以帮助你生成命令,而且是中文的,虽然翻译得不怎么样,不过看得懂。

选择好你需要的Web框架,将它帮你生成的mvn命令直接复制到命令行中,如果你已经按http://appfuse.org/display/APF/Development+Environment 配置好了环境变量的话,你可以看到maven开始下载一切需要的东西了。其实配置环境变量没有说得那么复杂,只需要将JDK、Maven、MySQL的bin目录都加入到path里面就行了,linux的用户请自己摸索一下,我不是很懂。

其实上面这些如果你是标准SSH(Struts2+Spring+Hibernate架构)还有一个选择就是Springside, 国人开发的,异常不错,强烈推荐,个人认为在SSH方面比Appfuse要更好一些。不过Appfuse还有个绝招,它还提供了一个VMWare 虚拟机镜像,可以直接下下来,里面已经装好了Subversion(版本控制), CruiseControl(持续集成工具) 和Trac(bug追踪工具以及wiki),不过我没有尝试,不知道具体使用起来怎么样。

第一篇就到这里,要知后事如何,且听下回分解。

VN:F [1.7.5_995]
Rating: 4.0/10 (2 votes cast)
VN:F [1.7.5_995]
Rating: -1 (from 1 vote)

maven中文教程——一个简单的应用实例0

我突然有个想法,我们使用hibernate search来构建一个全文检索(本文的内容不会重点放在hibernate search,对此感兴趣可以下载本文的代码)。假设我们的数据库中有一些数码相机的数据,对于这些数据的维护采用hibernate,这样我们可以使用hibernate search架设一个全文检索系统,以提供更好的产品检索服务。

心动不如行动,马上动手吧。

第一步,在命令行中敲入“mvn archetype:generate”,这个命令好处是可以不用我们记那么多的参数,在前面的文章中我已经说明了。

第二步,选择 “internal -> maven-archetype-quickstart ()”这一项,自需要选择编号,我这里的编号是17,这个号码在每个电脑上可能有不同。

第三部,按照提示输入相关信息,之后,maven即生成了项目的结构,如下:
Define value for groupId: : com.zhlwish
Define value for artifactId: : jpastudy
Define value for version:  1.0-SNAPSHOT: :
Define value for package:  com.zhlwish: : com.zhlwish.jpastudy
Confirm properties configuration:
groupId: com.zhlwish
artifactId: jpastudy
version: 1.0-SNAPSHOT
package: com.zhlwish.jpastudy
 Y: : y

第四步,修改pom.xml文件,增加依赖项,我们使用mysql数据,那么需要增加mysql的jdbc驱动依赖,我们在mvn的仓库(如:http://mvnrepository.com/)找到对应的版本。同样找到hibernate-core、hibernate-search,因为hibernate-search还依赖于hibernate-annotation,因此我们也要把这些项目加入到依赖中。整个文件变成如下:
<dependencies>
  <!– 测试 –>
  <dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <version>3.8.1</version>
    <scope>test</scope>
  </dependency>

  <!– MySQL 驱动 –>
  <dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>5.1.6</version>
  </dependency>

  <!– Hibernate –>
  <dependency>
    <groupId>org.hibernate</groupId>
    <artifactId>hibernate-core</artifactId>
    <version>3.3.1.GA</version>
  </dependency>
  <dependency>
    <groupId>org.hibernate</groupId>
    <artifactId>hibernate-annotations</artifactId>
    <version>3.4.0.GA</version>
  </dependency>
  <dependency>
    <groupId>org.hibernate</groupId>
    <artifactId>hibernate-search</artifactId>
    <version>3.1.0.GA</version>
  </dependency>

  <dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>slf4j-simple</artifactId>
    <version>1.4.2</version>
  </dependency>

  <dependency>
    <groupId>javassist</groupId>
    <artifactId>javassist</artifactId>
    <version>3.4.GA</version>
  </dependency>

  <!– lucene –>
  <dependency>
    <groupId>org.apache.lucene</groupId>
    <artifactId>lucene-snowball</artifactId>
    <version>2.4.0</version>
  </dependency>
  <dependency>
    <groupId>org.apache.lucene</groupId>
    <artifactId>lucene-analyzers</artifactId>
    <version>2.4.0</version>
  </dependency>
</dependencies>

第五步,加入代码,然后运行“mvn compile”编译程序,结果发现出现错误“(请使用 -source 5 或更高版本以启用泛型)”,因为我们用到了泛型和annotation,这些都是jdk5才具有的新特性,我们需要设置compile插件,具体可以参考Setting the -source and -target of the Java Compiler,根据说明,我们继续向pom文件中加入:
<build>
   <plugins>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-compiler-plugin</artifactId>
        <configuration>
          <source>5</source>
          <target>5</target>
        </configuration>
      </plugin>
   </plugins>
</build>

第六步,运行“mvn complie”,这次编译成功过了哦。运行“mvn package”,在target目录下生成了jpastudy-1.0-SNAPSHOT.jar,但是我们还不能直接运行这个jar,因为所有的运行时依赖没有加入到classpath中。

第七步,我们想将所有的依赖库都打包,直接交给用户,这样用户不需要在做其他设置了,这里需要使用Assembly插件了,其说明参考Pre-defined Descriptor Files,这个参考文件也说明了有四种默认定义的打包方式,我们选择jar-with-dependencies,继续添加pom文件,在<plugins>节点下添加如下内容:
<plugin>
   <artifactId>maven-assembly-plugin</artifactId>
   <configuration>
      <descriptorRefs>
         <descriptorRef>jar-with-dependencies</descriptorRef>
      </descriptorRefs>
   </configuration>
</plugin>

第八步,首先清理一下前面生成的一些东西,运行“mvn clean”,然后运行“mvn assembly:assembly”(具体请参见本系列文章第一篇),在target目录中生成了jpastudy-1.0-SNAPSHOT-jar-with-dependencies.jar。好!

第九步,可以来看我们的成果了,打开MySQL数据库,运行“java -cp target/jpastudy-1.0-SNAPSHOT-jar-with-dependencies.jar com.zhlwish.jpastudy.App”,输出结果了吧:
一共检索到3条数据:
产品名称 | 产品型号
Cannon   | 1000D
Cannon   | 450D
Cannon   | 500D

我的工作完成了,大家只需要从google code的svn上checkout代码,然后运行第八步和第九步的命令就行了,把包的依赖关系和生命周期交给maven吧。本文代码svn地址:http://zhlwish.googlecode.com/svn/trunk/

VN:F [1.7.5_995]
Rating: 8.0/10 (1 vote cast)
VN:F [1.7.5_995]
Rating: 0 (from 0 votes)

maven中文教程——坐标与包依赖管理0

maven用“坐标(Coordinate)”这个词来唯一标识一个库文件,所谓“坐标”就是库文件的“主键”(借用一下数据库的概念),而且这个“主键”是个复合组件,包含四个部分:groupId, artifactId, version和packaging,分别对应pom文件中的下面四个结点:

<groupId>com.zhlwish</groupId>   项目开发组织标识
<artifactId>simple</artifactId>  项目标识(一般是项目名称)
<packaging>jar</packaging>       打包类型(可能是jar、war、ear)
<version>1.0-SNAPSHOT</version>  版本(按照apache版本命名规则来命名,一般为“主版本.次版本.增量版本-限定版本号”)

snapshot、release、latest是maven中常用的三个“限定版本号”,snapshot表示项目正处于活动的开发状态;latest是指项目的最新的发布版,或者最近被发布到仓库的快照版(snapshot);release是指仓库中的最后一个非快照版本。

maven最强大的地方就是能够对库文件(俗称“包、package”)的依赖进行管理。对于一个应用项目而言,不可避免的会引入很多第三方的类库。如一个项目采用struts2开发,使用struts2的2.1.6版本,而这个struts2又依赖于apache commons的某些包,如果我们不使用maven开发的话,需要下载这么多库文件,然后全部copy到项目的classpath路径下面,当依赖的第三方库越来越多,而且很多还有传递依赖,每当Java虚拟机抛出class not found exceptions时头都大了,而且一旦库升级,随之而来的又是一大堆问题。另外,如果我们将库文件纳入到版本库的管理中,也会造成版本库的急剧增大。

maven的出现解决了这个问题。她可以很好的管理这些问题,包括传递依赖。我们在pom文件里面加入:

<dependencies>
    <dependency>
      <groupId>log4j</groupId>
      <artifactId>log4j</artifactId>
      <version>1.2.14</version>
    </dependency>
    <dependency>
      <groupId>dom4j</groupId>
      <artifactId>dom4j</artifactId>
      <version>1.6.1</version>
    </dependency>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>3.8.1</version>
      <scope>test</scope>
    </dependency>
<dependencies>

上面代码的意思是我们为项目添加了log4j和dom4j以及junit的依赖,我们不用去找这些jar文件然后复制到classpath里面了,maven会自动去找这些包(本地或者远程仓库),每个dependency结点下面就是一个库文件的“主键”。

对于最后一个还有一个scope结点,标识了这个库文件的使用范围,有如下五种,其中compile是默认的:
compile:编译需要,在pachakge生命周期阶段如果使用”mvn assembly:assembly”命令,所有的包都会一起导出
provided:编译期间需要,但是由于部署环境中已经存在,打包时就不用输出了,如servlet.jar,在开发时编译需要的,但是部署到servlet容器中后,servlet容器肯定有这个库文件,所以就不用打包输出。
test:编译测试代码和运行测试期间需要
runtime:运行期间需要,但是编译期间不需要
system:表示这个包由jvm或者jdk提供

关于scope的详细说明请参考《Maven dependency and repository》

VN:F [1.7.5_995]
Rating: 0.0/10 (0 votes cast)
VN:F [1.7.5_995]
Rating: 0 (from 0 votes)

maven中文教程——构建的生命周期0

maven的支持者在提及maven的优点的时候总会提到这么一点,那就是maven是有生命周期的,而ant没有,你需要手工的编写target,然后编写每个target中的任务。

其实在我看来这个是纠缠概念,所谓的maven生命周期实际上是构建过程的生命周期。在ant中你需要手动的设定文件夹的结果,告诉ant哪个是源代码文件夹、哪个是测试代码文件夹,哪个是目标文件夹等等,因此对于使用ant每个项目都有不一样的代码。因为maven已经将项目的文件夹结构固定好了,不用程序员再指定,所以就可以将编译、打包、部署等这样一些过程都可以做成自动化的,也就是所谓的maven的生命周期。

其实,完全可以自定义ant的target来实现maven所谓的“生命周期”这个概念。

构建即俗称building(team-building也是一种构建),我的理解是在java开发中构建组要是指编译源代码、打包、部署、运行这样一个完整的过程,很多时候这个过程被IDE封装成了一个run按钮,当你写完代码按下run的时候,IDE会将所有的事情做完,对于coder,这一系列过程是透明的。

那又会有同学要问了,既然IDE已经可以做这些事情了,而且不用我操心,我干嘛需要maven呢?一方面,在持续集成和自动化构建过程中显然不可能去用IDE封装好的这一套,这里非得使用ant或者maven不可;另一方面,maven的最核心功能并不是这个而是包依赖的管理。

maven中默认的生命周期阶段可以参考《maven权威指南》chapter10 构建生命周期,我们会常用的有这么一些,你可以使用“mvn 生命周期的阶段名称”这样的命令来用maven自动构建:

  1. validate 验证项目是否正确,以及所有为了完整构建必要的信息是否可用
  2. compile 编译项目的源代码
  3. test-compile 编译测试源代码
  4. test 运行单元测试
  5. package 将编译好的代码打包成可发布的格式,如war、jar、ear等
  6. install 安装包到本地仓库,以备其他项目可用
  7. deploy 将本地包发布到远程仓库(一般是开发团队搭建的maven私服)
  8. site 生成项目文档和报道,和apache的一般网站风格很相似,这一点太强大了

maven的生命周期其实是“约定优于配置”这个思想的最好体现,觉得ant脚本难写的朋友可以感受一下maven的强大。

VN:F [1.7.5_995]
Rating: 0.0/10 (0 votes cast)
VN:F [1.7.5_995]
Rating: 0 (from 0 votes)

maven中文教程——命令0

这是我第二遍学习maven了,决定写一些东西记录一下,以防像第一次学习之后全部忘光光的情况出现,另外也是告诉自己,必须坚持记录学习进展,不能荒废了这一片净土。

看到这个题目,有人会告诉我《Maven权威指南》,我看了一些,但是一开头就被“mvn archetype:create -DgroupId=org.sonatype.mavenbook.ch03 -DartifactId=simple -DpackageName=org.sonatype.mavenbook”这样的命令吓到了,与其去记这么复杂的命令,我还不如回去用ant,最近apache不是又整出个ivy,也可以管理版本依赖么?简简单单,多好。直到我偶然浏览一篇springside论坛一篇帖子,里面写到:

“其实谁都有菜鸟的的阶段,不过我们要学习的话,不要总是看重运行结果,要学习整个的过程和细节。比如很多人都头痛的maven,就是一个学习的好机会,我第一次学习maven也是下载ss后才迫使自己学习的,当时也是隐隐的骂,觉得太费劲了。但是当你真正的做过之后才发现,很多时候我们讨厌的事物,恰巧是我们没有真正了解和操作前的误区。直言不讳地说,那些自称是菜鸟而不愿以使用maven的人很可能不是菜鸟,而是懒鸟。如果你是懒鸟,请暂时不要再研究springside了,因为影响你日后发展的主要原因很可能就是懒惰而不是技术。 ”

仔细想了一下,觉得很有道理,学习嘛,都有循序渐进的过程,一开始遇到问题很正常,如果不能坚持,永远学不到真正的东西。于是,从maven开始。

回头看这个命令mvn archetype:create(省略了后面的参数),其中archetype是一个插件(plugin)的名字,而create是这个插件的一个任务(task),这个插件都有哪些任务可以用mvn help:describe -Dplugin=archetype 这个命令来查看,同样,help是一个插件,describe是一个任务的名字,maven里面的参数传递采用“-D”这种Java用来设置系统属性的方式,mvn这个脚本只是把这个参数传递给java的类了。

同样如果需要查看help插件的详细信息,可以使用mvn help:describe -Dplugin=help,如果需要查看详细的参数信息,则需要再加上-Dfull参数,即mvn help:describe -Dplugin=archetype -Dfull=true

创建了一个项目之后,可以使用maven的其他命令来执行编译、构建、发布过程了,对于一些常用的命令,maven也有简写形式,如mvn compile:compile可以简写为mvn compile

常用的有这么一些:
mvn compile 编译项目源代码
mvn test-compile 编译测试代码
mvn test 运行测试
mvn package 打包应用
mvn install 将应用发布到本地仓库
mvn deploy 复制最终的包至远程仓库,共享给其它开发人员和项目供其他项目使用

上面的这些命令究竟对应着哪些插件的任务,可以参见《maven权威指南》Chapter 10.构建生命周期

VN:F [1.7.5_995]
Rating: 0.0/10 (0 votes cast)
VN:F [1.7.5_995]
Rating: 0 (from 0 votes)


Switch to our mobile site