我的网站使用SpringSide 2.0开发,在SpringSide 2.0中,默认使用的是XFire来提供WebService,但是我按照文档进行操作,结果却失败了。于是我向江南白衣请教,白衣推荐我使用CXF的最新版本,于是我到官方网站下载了CXF的最新版,按照示例来了一遍,很快就成功了。由此可见,使用CXF不仅简单,而且成功率高。因此,我在这里把我的经验和大家分享。
第一步 ,下载CXF的最新版本,下载地址如下图:
第二步 ,将CXF中的lib文件夹中的下列jar文件拷贝到我们项目的webapp/WEB-INF/lib目录下:
geronimo-activation_1.1_spec-1.0-M1.jar (or Sun's Activation jar)
geronimo-annotation_1.0_spec-1.1.jar (JSR 250)
geronimo-javamail_1.4_spec-1.0-M1.jar (or Sun's JavaMail jar)
geronimo-servlet_2.5_spec-1.1-M1.jar (or Sun's Servlet jar)
geronimo-ws-metadata_2.0_spec-1.1.1.jar (JSR 181)
jaxb-api-2.0.jar
jaxb-impl-2.0.5.jar
jaxws-api-2.0.jar
neethi-2.0.jar
saaj-api-1.3.jar
saaj-impl-1.3.jar
stax-api-1.0.1.jar
wsdl4j-1.6.1.jar
wstx-asl-3.2.1.jar
XmlSchema-1.2.jar
xml-resolver-1.2.jar
cxf-2.0-incubator.jar
这里有一些包我的项目中本身已经带有了,只不过CXF中提供的版本要更新一些。把这些包拷贝到项目中后,可以删除项目中的较低的版本,同时删除所有和XFire有关的包。当然,不删除也可以,因为我试过了,就算项目中存在多个不同版本的包,也不会发生冲突。
当然,光拷贝这些包到项目中,还不能保证开发的顺利进行,还需要在Eclipse中设置项目的库,如下图:
在这里,我不得不说一下另外一个问题,那就是启动Tomcat服务器的时候,经常发生java.lang.OutOfMemoryError: PermGen space异常,出现这个异常是什么原因呢?在网上搜到的答案是这样的:PermGen space的全称是Permanent Generation space,是指内存的永久保存区域,这块内存主要是被JVM存放Class和Meta信息的,Class在被Loader时就会被放到PermGen space中,它和存放类实例(Instance)的Heap区域不同,GC(Garbage Collection)不会在主程序运行期对PermGen space进行清理,所以如果你的应用中有很多CLASS的话,就很可能出现PermGen space错误,这种错误常见在web服务器对JSP进行pre compile的时候。如果你的WEB APP下都用了大量的第三方jar, 其大小超过了jvm默认的大小(4M)那么就会产生此错误信息了。
本来,使用SpringSide 2.0就已经包含了许多的第三方包,容易出现这个问题,现在加入CXF依赖的这些包,就不可避免要出现这个问题了。这个问题的解决方法有两个,其一是不使用SUN的JDK。当然,我也懒得去下载一个别的JDK,因此就选择了第二个方法,那就是修改Tomcat的启动文件。
找到SpringSide2.0\misc\servers\tomcat-5.5.17\bin文件夹下的catalina.bat文件,使用记事本打开,找到如下行:
set JAVA_OPTS=
将这一行进行修改,加入启动参数,如下:
set JAVA_OPTS=%JAVA_OPTS% -Xms512m -Xmx1024m -XX:MaxNewSize=512m -XX:MaxPermSize=512m -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager -Djava.util.logging.config.file="%CATALINA_BASE%\conf\logging.properties":noJuli
解决了以上这些问题,就可以正式使用CXF了。
第三步,修改webapp/WEB-INF/web.xml文件,将以前的
< servlet-name >xfire </ servlet-name >
< servlet-class >org.codehaus.xfire.spring.XFireSpringServlet </ servlet-class >
</ servlet >
< servlet-mapping >
< servlet-name >xfire </ servlet-name >
< url-pattern >/service/* </ url-pattern >
</ servlet-mapping >
修改为:
< servlet-name >cxf </ servlet-name >
< servlet-class >org.apache.cxf.transport.servlet.CXFServlet </ servlet-class >
</ servlet >
< servlet-mapping >
< servlet-name >cxf </ servlet-name >
< url-pattern >/service/* </ url-pattern >
</ servlet-mapping >
即可。
第四步 ,定义一个提供WebService的接口。在我的项目中,我准备只提供一个WebService,即IndexService,这个服务中提供多个方法来分别满足索引服务器的各种功能。目前,我还只开发到了用户注册模块,需要向索引服务器提交用户数据,因此,暂时提供一个addUser方法作为示例,如下:
import javax.jws.WebService;
import com.yumdays.model.SUser;
@WebService
public interface IndexService {
public boolean addUser(SUser user,String adminName,String adminPassword);
}
而它的实现类如下:
import com.yumdays.model.SUser;
import javax.jws.WebService;
@WebService(endpointInterface = "com.yumdays.service.IndexService")
public class IndexServiceImpl implements IndexService {
public boolean addUser(SUser user, String adminName, String adminPassword) {
// TODO 自动生成方法存根
return false;
}
}
第五步,在项目的src/resource/spring目录下,删除所有和XFire有关的配置文件,添加一个cxf-beans.xml文件,其内容如下:
< beans xmlns ="http://www.springframework.org/schema/beans"
xmlns:xsi ="http://www.w3.org/2001/XMLSchema-instance"
xmlns:jaxws ="http://cxf.apache.org/jaxws"
xsi:schemaLocation ="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd" >
< import resource ="classpath:META-INF/cxf/cxf.xml" />
< import resource ="classpath:META-INF/cxf/cxf-extension-soap.xml" />
< import resource ="classpath:META-INF/cxf/cxf-servlet.xml" />
< bean id ="indexServiceBean" class ="com.yumdays.service.IndexServiceImpl" />
< jaxws:endpoint id ="indexService" implementor ="#indexServiceBean" address ="/IndexService" />
</ beans >
现在,重新构建项目,部署,启动Tomcat,就可以通过访问 http://www.yumdays.com/service/IndexService?wsdl 来测试该WebService是否成功被部署了。如下图:
第六步 ,创建客户端,这一步非常的容易,只需要下面这样的配置:
< beans xmlns ="http://www.springframework.org/schema/beans"
xmlns:xsi ="http://www.w3.org/2001/XMLSchema-instance"
xmlns:jaxws ="http://cxf.apache.org/jaxws"
xsi:schemaLocation ="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd" >
< import resource ="classpath:META-INF/cxf/cxf.xml" />
< import resource ="classpath:META-INF/cxf/cxf-extension-soap.xml" />
< import resource ="classpath:META-INF/cxf/cxf-servlet.xml" />
< bean id ="client" class ="com.yumdays.service.IndexService" factory-bean ="clientFactory" factory-method ="create" />
< bean id ="clientFactory" class ="org.apache.cxf.jaxws.JaxWsProxyFactoryBean" >
< property name ="serviceClass" value ="com.yumdays.service.IndexService" />
< property name ="address" value ="http://www.yumdays.com/service/IndexService" />
</ bean >
</ beans >
就可以获得一个名称为client的bean,通过该bean,就可以非常方便的访问索引服务器提供的功能。