在 eclipse galileo jee 中施用 maven 和 tomcat 运行 web 项目

在 eclipse galileo jee 中使用 maven 和 tomcat 运行 web 项目
注意, maven 是与 IDE 无关的!!!


也许看到这标题, 就知道贴子一定不好. 因为: 既然选择了 maven, 就说明这个项目与IDE是无关的, 或者说关系是不大的, maven 的定位早已经超过了 IDE 的局限.

都说 maven 和 jetty 配合是最好的, 开放和嵌入式的 jetty 自己不熟, 总是没能成功. 也做为一个摸索, 弄了下在 tomcat 中部署.

说明一下, 第一次使用 maven 的时候要保证网络(周末在家没网, 不过仓库包有一些).

在 eclipse 中部署 tomcat 项目就没必要多说了, 用不习惯的话, 以下的文字可以省掉, 从来都觉得 MyEclipse 是很优秀的! 但破解嘛, 能少用就尽量少用吧. 而且我那 1G 的内存...

下载 maven, 解压至一个自己常用的软件路径, 我喜欢放在 C:\Program Files, 建立环境变量 M2_HOME 并添加至 path (非必需! 喜欢命令行的话是很有必要的.)

在 eclipse 中安装 m2e, 地址 : http://m2eclipse.sonatype.org/sites/m2e

设置 maven 本地仓库: 首先换一个本地仓库路径(团队开发的话, 还需要建一个 nexus 服务器, 获取 jar 包的时候先在服务器上获取, 没有再去远程获取, 这样可以给团队内部减少带宽)

M2_HOME/conf/settings.xml

<!-- localRepository
| The path to the local repository maven will use to store artifacts.
|
| Default: ~/.m2/repository
<localRepository>/path/to/local/repo</localRepository>
-->
<localRepository>d:/repository</localRepository>

注意看上面的注释, 好的学习方式比枯燥的工作经验(遇到问题只会去Gg 去问 去C-c, C-v, 从来不自己想想问题出在哪)远远要实用得多!

从上面的注释我们可以看到, 默认的本地仓库在 ~/.m2/repository.


在 eclipse 中设置 maven:
Maven 要求我们须在一个 jdk 当中而不是 jre 中工作, 所以 eclipse 在启动的时候就出现一个警告, 如果想一劳永逸地解决这个问题, 需要修改 eclipse.ini :

-vm
C:/Program Files/Java/jdk1.6../jre/bin/client/jvm.dll

UNIX like 平台下是 libjvm.so. 用 locate 搜一下就出来了(有几篇国外的贴子上说的是指定 javaw, 但是 UNIX like 上是没有 javaw 的).
注意, -vm 与下面的行不要在同一行.
或者, 只写到 C:/Program Files/Java/jdk1.6../bin 也是可以.

Maven 选项中勾选 Download Artifact Sources, JavaDoc(老外的奉献精神就是好, 从不吝啬源码, 但最好查看下 license. 咱们这些天朝子民却只会索取不懂回报, 也没办法, 在天朝糊口太不容易), 断网比较多话把 Offline 也勾上, 在 Installations 中添加本地 Maven 地址
在 eclipse galileo jee 中施用 maven 和 tomcat 运行 web 项目

User Settings 中可以设置自己的个人设定(主要为团队开发时有用).

新建 Maven Project, 勾选 Create a simple Porject, 这样可以把构建的大部分工作留给自己, 像这样学习最能成长, 否则很容易被工具宠坏, 不是吗?

Group Id : 可以想成是你的域名, 这个一般是不会变的,比如 com.google
Artifact Id : 把这想成是项目名, 比如 example
Packaging : 我们想构建的是一个 web 项目, 自然是 war 啦.

--> Next (第一次想添加 Artifact 会没有值, 因为仓库现在还是空的) --> Finish

PS : 最后一步完成后, 很可能会报一些莫名其妙的错误, 得去看 .metadata/.log 或 Error Log 视图查看原因, 通常都是因为 maven 版本和 eclipse 冲突导致的, 如果是这样的话, 我的建议是只能通过命令行去敲了: mvn archetype:generate ... 再 mvn eclipse:eclpse 再导入至 eclipse, 额, 开始接触 maven 的时候, 对这些长串的命令头痛极了, 始终不明白这些到底是啥意思, 网上的贴子太多又都是复制旁人的, 要是没网查不到命令, 这些又都是maven插件完成的工作, 使用 mvn -h 一点用处都没有, 所以, 导致自己一度很烦 maven!

花点时间看看这个目录结构, 简单又清晰:
类文件放在 src/main/java 中
资源文件如一些 xml, properties 放在 /src/main/resources 中
web 所需要的文件放在 src/main/webapp 中
测试文件放在相应的 src/test 中
目标文件放在 target 中(也就是打包之后的 war文件存放位置, 开发期间是不需要的)

maven 默认使用的 jdk 1.4 构建项目, 改!
打开 Navigat 视图, 更改 .settings/org.eclipse.jdt.core.prefs.

既然打开了导航视图, 再改改一个很重要的东西吧: 添加 jee 支持, 打开 .project, 添加

<nature>org.eclipse.wst.common.modulecore.ModuleCoreNature</nature>
<nature>org.eclipse.wst.common.project.facet.core.nature</nature>

然后, 右键 项目 --> Properties --> Project Facets(上面的不加入, 这里是没有 facets 的), 勾选 Dynamic Web Module 和 Java(注意选择版本!) --> Apply --> OK

这时 .settings 目录下会多出几个文件来, .project 也会发生更改.

右键 项目 --> Properties --> Java Build Path 中把 EAR Libraries 和 Web App Libraries 去掉, 如果觉得 JavaScript Resources 这个东西有点碍眼, 在 .project 中去掉 org.eclipse.wst.jsdt.core.jsNature 和 buildCommand 下的 org.eclipse.wst.jsdt.core.javascriptValidator 即可(最好注释, 如果要在 eclipse 中写 js 这个就用得着了, 可以自动提示的).


好了, 开始整 Maven.

maven中最主要的是 pom.xml, 使用 Maven POM Editor 打开:

添加依赖包, groupId 和 artifactId 如果不知道的话(第一次谁都不可能知道)
去 mvnrepository.com/ 查(这网站真好! 通过google找到这个网站并用几次之后觉得这网站简直就是个宝藏).

<dependencies>
	<dependency>
		<groupId>org.springframework</groupId>
		<artifactId>spring-aop</artifactId>
		<version>2.5.6</version>
	</dependency>
	<dependency>
		<groupId>org.springframework</groupId>
		<artifactId>spring-orm</artifactId>
		<version>2.5.6</version>
	</dependency>
	<dependency>
		<groupId>org.springframework</groupId>
		<artifactId>spring-jdbc</artifactId>
		<version>2.5.6</version>
	</dependency>
	<dependency>
		<groupId>org.springframework</groupId>
		<artifactId>spring-web</artifactId>
		<version>2.5.6</version>
	</dependency>
	<dependency>
		<groupId>org.aspectj</groupId>
		<artifactId>aspectjrt</artifactId>
		<version>1.6.11</version>
	</dependency>
	<dependency>
		<groupId>org.aspectj</groupId>
		<artifactId>aspectjweaver</artifactId>
		<version>1.6.11</version>
	</dependency>
	<dependency>
		<groupId>org.springframework</groupId>
		<artifactId>spring-test</artifactId>
		<version>2.5.6</version>
		<scope>test</scope>
	</dependency>
	<dependency>
		<groupId>junit</groupId>
		<artifactId>junit</artifactId>
		<version>4.6</version>
		<scope>test</scope>
	</dependency>
	<dependency>
		<groupId>org.apache.struts</groupId>
		<artifactId>struts2-core</artifactId>
		<version>2.1.8</version>
	</dependency>
	<dependency>
		<groupId>org.apache.struts</groupId>
		<artifactId>struts2-json-plugin</artifactId>
		<version>2.1.8</version>
	</dependency>
	<dependency>
		<groupId>org.apache.struts</groupId>
		<artifactId>struts2-junit-plugin</artifactId>
		<version>2.1.8</version>
	</dependency>
	<dependency>
		<groupId>org.apache.struts</groupId>
		<artifactId>struts2-sitemesh-plugin</artifactId>
		<version>2.1.8</version>
	</dependency>
	<dependency>
		<groupId>org.apache.struts</groupId>
		<artifactId>struts2-spring-plugin</artifactId>
		<version>2.1.8</version>
	</dependency>
	<dependency>
		<groupId>org.hibernate</groupId>
		<artifactId>hibernate-core</artifactId>
		<version>3.3.1.GA</version>
	</dependency>
	<dependency>
		<groupId>org.hibernate</groupId>
		<artifactId>hibernate-ehcache</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>log4j</groupId>
		<artifactId>log4j</artifactId>
		<version>1.2.16</version>
	</dependency>
	<dependency>
		<groupId>org.slf4j</groupId>
		<artifactId>slf4j-log4j12</artifactId>
		<version>1.4.2</version>
	</dependency>
	<dependency>
		<groupId>c3p0</groupId>
		<artifactId>c3p0</artifactId>
		<version>0.9.1.2</version>
	</dependency>
	<dependency>
		<groupId>opensymphony</groupId>
		<artifactId>sitemesh</artifactId>
		<version>2.4.1</version>
	</dependency>
	<dependency>
		<groupId>mysql</groupId>
		<artifactId>mysql-connector-java</artifactId>
		<version>5.1.16</version>
	</dependency>
	<dependency>
		<groupId>ehcache</groupId>
		<artifactId>ehcache</artifactId>
		<version>1.2.3</version>
	</dependency>
	<dependency>
		<groupId>javax.servlet</groupId>
		<artifactId>servlet-api</artifactId>
		<version>2.5</version>
		<scope>provided</scope>
	</dependency>
	<dependency>
		<groupId>javax.servlet.jsp</groupId>
		<artifactId>jsp-api</artifactId>
		<version>2.1</version>
		<scope>provided</scope>
	</dependency>
</dependencies>


保存 pom.xml, 神奇的事情马上发生! Maven 这时会自动去远程仓库下载指定的依赖包到本地仓库并添加到项目的 classpath 中(网速慢的话耐心地等上一点时间). 而且, 以后要改版本, 更改下 version 就行了. 在这一点上 Maven 确实很对得起自己的名字!

PS : 关于 jar包的依赖, 下载完成后可以打开POM Edtior 中的 Dependency Hierarchy 及 Dependency Graph 查看, 后者需要在 preferences 中打开 "show advanced tabs in the POM editor".

添加 tomcat 支持:

<build>
	<finalName>example</finalName>
	<sourceDirectory>src/main/java</sourceDirectory>
	<outputDirectory>src/main/webapp/WEB-INF/classes</outputDirectory>
	<defaultGoal>install</defaultGoal>
	<resources>
		<resource>
			<targetPath></targetPath>
			<directory>src/main/resources</directory>
			<filtering>true</filtering>
		</resource>
	</resources>
	<plugins>
		<plugin>
			<artifactId>maven-compiler-plugin</artifactId>
			<version>2.0.2</version>
			<configuration>
				<source>1.5</source>
				<target>1.5</target>
				<encoding>UTF-8</encoding>
			</configuration>
		</plugin>
		<plugin>
			<artifactId>maven-resources-plugin</artifactId>
			<configuration>
				<encoding>UTF-8</encoding>
			</configuration>
		</plugin>
		<plugin>
			<artifactId>maven-war-plugin</artifactId>
			<configuration>
				<webappDirectory>src/main/webapp</webappDirectory>
				<warSourceDirectory>target/example-webapp</warSourceDirectory>
			</configuration>
		</plugin>
		<plugin>
			<groupId>org.codehaus.mojo</groupId>
			<artifactId>tomcat-maven-plugin</artifactId>
		</plugin>
	</plugins>
</build>


注意看 outputDirectory, webappDirectory, warSourceDirectory 这三个属性的值. 当然啦, 这里写得很过于简陋, 测试都没有, 有一点点为了构建而构建的味道!

修改 .classpath:

<?xml version="1.0" encoding="UTF-8"?>
<classpath>
	<classpathentry kind="src" output="target/classes" path="src/main/java" />
	<classpathentry kind="src" output="target/classes" path="src/main/resources"/>
	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER" />
	<classpathentry kind="con" path="org.maven.ide.eclipse.MAVEN2_CLASSPATH_CONTAINER">
		<attributes>
			<attribute name="org.eclipse.jst.component.dependency" value="/WEB-INF/lib"/>
		</attributes>
	</classpathentry>
	<classpathentry kind="output" path="target/classes" />
</classpath>


修改 .settings/org.eclipse.wst.common.component:
<?xml version="1.0" encoding="UTF-8"?>
<project-modules id="moduleCoreId" project-version="1.5.0">
    <wb-module deploy-name="example">
        <wb-resource deploy-path="/" source-path="/src/main/webapp"/>
        <wb-resource deploy-path="/WEB-INF/classes" source-path="/src/main/java"/>
        <wb-resource deploy-path="/WEB-INF/classes" source-path="/src/main/resources"/>
        <property name="context-root" value="ex"/>
        <property name="java-output-path" value="/src/main/webapp/WEB-INF/classes"/>
    </wb-module>
</project-modules>



齐活了, 发布到 tomcat:
在 eclipse galileo jee 中施用 maven 和 tomcat 运行 web 项目

启动 tomcat 访问 localhost:8080/ex 查看结果. 如果修改页面文件直接刷新页面能看到效果, 修改类文件 tomcat 会轮询加载, 多试几次 tomcat 内存会耗尽就需要重启, 修改 xml 及配置文件必须重启服务. Tomcat 的热部署就是这样. 开始觉得jetty的嵌入式招人爱了. Tomcat 7.0 开始好像也支持嵌入式了.

至此, 全部搞淀, 说实话, 太过繁琐. 要想简单也是可以的, 右键 项目 --> Run as --> Maven package, 将项目打包成 war 包, 拿着这个 war 再去发布. OMG, 热部署呢...

PS : 很多时候发布失败都是因为jar包依赖不成功导致的, 这时候就要我们仔细看看 dependency 和 Build里面的那些东西了, maven 的重点也正是这些.

有点小搞, 发布的时候居然把 tools.jar 这个 10几M 的jar包都加载进来了, 为了保证如 junit, spring-test, servlet.jar, jsp-api.jar 这一类的jar 不被包含进来, 好的方法是在项目完成后打成 war, 指定包的 scope. 但这是上线的时候应该操心的事, 现在还可以容忍. 而且, 这个 <build> 本身写得也不够好. 可以看到, 如果打成 war 包的话, 上面说的那五个包都是不存在的.

以前动不动一个项目好几十 M, 且还有那些烦人的依赖, 现在, 如果去掉比较大的 js 库,以 K 来计算. maven, 取名当之无愧!

1 楼 zhmy0129 2011-11-17  
在 eclipse galileo jee 中施用 maven 和 tomcat 运行 web 项目