安装maven插件
老版本eclipse使用maven需要自己安装插件具体步骤可以百度m2eeclipse插件,新版本eclipse已经集成了maven。
安装完毕检查User Settings是否指定maven的配置文件,如果没有需要自己手动选择maven配置。
创建maven项目
点击finish完成创建。
结构如下:
发现比正常结构丢失了两个源文件夹,src/main/java;src/test/java,这是因为构建时maven默认使用的jdk1.5,而eclipse配置的jdk默认版本可能不一样,导致了这样的问题。
看下图:
我的eclipse默认的是1.7
而maven默认是1.5,查看项目buildpath发现jre显示为1.5,实际是1.7。。。
我们手动修改下buildpath的jre,或者直接移除掉(eclipse中的maven项目不推荐去手动调整jdk,通常我们在pom.xml中调整编译插件,然后右键maven-updateProject,eclipse会自己调整依赖jdk版本),点击完成即可恢复缺失的源文件夹。
完成后如下图:
pom.xml配置
根据需要配置项目的依赖构件,插件最少配置有一个编译插件,否则运行maven命令时默认将以jdk1.5去编译执行。除非你手动修改项目buildpath更改jdk版本并且不使用maven命令去编译(runas...javaApplication),但不推荐这样做,因为maven项目每次右键updateProjec时eclipse会自动修改jdk组件为pom.xml的插件指定的版本,即使pom没有配置编译插件,那么将是默认的jdk1.5。
eclipse中开发maven项目不推荐配置tomcat服务器插件,因为你的项目中将会多出一些依赖,如servlet-api等..,推荐直接buildpath中添加eclipse配置的tomcat server组件,我们会省去很多麻烦。
另外要注意tomcat容器的运行环境要跟pom.xml中指定jdk版本一致,因为我们的项目是以pom中指定的编译插件版本去编译的,编译后交给tomcat容器去执行,tomcat会根据你配置时指定的jre去运行它自己,然后它再去执行项目,如果你给tomcat配置的jre与pom指定的不一致,那么很有可能项目运行不起来。
项目打包
可以直接右键export-war把项目打包成war包,去放到服务器去执行,也可以执行maven的打包命令去打包,它是以pom指定的packaging来打包的。
两种方式没有区别,第一种打包方式在打包时会把maven中的所有依赖jar文件全部放在WEB-INF/lib文件夹中,以及src/main中的资源及编译后的class文件放在classes目录中,这是标准的tomcat目录结构。第二种我并没有测试,我猜测最后打包的结果应该是一样的,另外注意第二种方式的打包时如果是要在tomcat容器下运行并且依赖中有servlet-api等tomcat容器中已经包含的jar构件的话请给它加上scope标签,并指定为provided,只在编译的classpath中加载和使用,打包的时候不会包含在目标包中,否则当你部署到tomcat容器运行时将会报错。
推荐第一种方式非常简单:
finish即可完成。
问题总结
今天在做公司项目迁移到maven时,发现一个奇怪的问题,分享给大家。
项目中有一个java源文件,不知道哪位同事不小心手误还是怎么回事,在这个文件中发现他import了一个com.sun.xml.internal.ws.developer.MemberSubmissionAddressing,然后导致maven编译一致报错,找不到com.sun.xml.internal.ws.developer程序包,这个包是jdk中的一个api,不知道什么用,但它确实是在我的项目jdk下,我能找的到他,但maven一直报错,很郁闷。
然后百度有人说在pom.xml编译插件中加上
<compilerArguments>
<bootclasspath>${JAVA_HOME}/jre/lib/rt.jar</bootclasspath> </compilerArguments>
然后问题就解决了,但是为什么解决了呢?继续百度,然后找到了这个篇文章,http://blog.csdn.net/smilingleo/article/details/5005538
很奇怪的bootclasspath参数
尝试下面代码:
import sun.util.resources.LocaleData; public class SunTest{ public SunTest(){ } }
编译时报错:
C:/Temp>javac -verbose SunTest.<a href="http://lib.csdn.net/base/javase" class='replace_word' title="Java SE知识库" target='_blank' style='color:#df3434; font-weight:bold;'>Java</a> [解析开始时间 SunTest.java] [解析已完成时间 63ms] [源文件的搜索路径: .] [类文件的搜索路径: C:/Java/jdk1.6/jre/lib/resources.jar,C:/Java/jdk1.6/jre/lib/ rt.jar,C:/Java/jdk1.6/jre/lib/sunrsasign.jar,C:/Java/jdk1.6/jre/lib/jsse.jar,C:/ Java/jdk1.6/jre/lib/jce.jar,C:/Java/jdk1.6/jre/lib/charsets.jar,C:/Java/jdk1.6/j re/classes,C:/Java/jdk1.6/jre/lib/ext/dnsns.jar,C:/Java/jdk1.6/jre/lib/ext/local edata.jar,C:/Java/jdk1.6/jre/lib/ext/sunjce_provider.jar,C:/Java/jdk1.6/jre/lib/ ext/sunmscapi.jar,C:/Java/jdk1.6/jre/lib/ext/sunpkcs11.jar,.] SunTest.java:1: 找不到符号 符号: 类 LocaleData 位置: 软件包 sun.util.resources import sun.util.resources.LocaleData; ^ [正在装入 java/lang/Object.class(java/lang:Object.class)] [正在检查 SunTest] [总时间 187ms] 1 错误
添加javac编译参数,指定bootclasspath,编译错误消失:
C:/Temp>javac -bootclasspath C:/Java/jdk1.6/jre/lib/rt.jar -verbose SunTest.java [解析开始时间 SunTest.java] [解析已完成时间 15ms] [源文件的搜索路径: .] [类文件的搜索路径: C:/Java/jdk1.6/jre/lib/rt.jar,C:/Java/jdk1.6/jre/lib/ext/dns ns.jar,C:/Java/jdk1.6/jre/lib/ext/localedata.jar,C:/Java/jdk1.6/jre/lib/ext/sunj ce_provider.jar,C:/Java/jdk1.6/jre/lib/ext/sunmscapi.jar,C:/Java/jdk1.6/jre/lib/ ext/sunpkcs11.jar,.] [正在装入 sun/util/resources/LocaleData.class(sun/util/resources:LocaleData.clas s)] [正在装入 java/lang/Object.class(java/lang:Object.class)] [正在检查 SunTest] [已写入 SunTest.class] [总时间 192ms]
编译错误问题的原因是bootClassLoader没有找到sun.util.resources.LocaleData这个类,从sun的文档中得知,sun不鼓励开发人员直接使用sun.*里面的代码,主要的原因是sun.*里面的代码就是实现jvm的底层代码,是平台相关的,而且相关实现随着版本升级随时可能会被替换,代码的稳定性、一致性等等都存在问题。
但是这并不是问题的关键。从verbose信息中可以看出,两次编译过程中搜索路径(classpath)中都包含rt.jar,但是为什么显式地指定一下-bootclasspath之后就会让bootclassloader加载sun.*呢?
没有找到答案,可能只有得到sun sdk的源码才能发现问题的原因。
这个讨论比较有价值:http://forums.sun.com/thread.jspa?threadID=5356024&start=0