京山游侠

专注技术,拒绝扯淡
posts - 50, comments - 868, trackbacks - 0, articles - 0
  BlogJava :: 首页 :: 新随笔 :: 联系 :: 聚合  :: 管理
在前面的随笔中,我讲了我的网站架构,这样的架构决定了我的网站中必须得用到WebService。比如,在用户注册的时候,用户数据主要是保存在内容服务器中,但是同时也要将部分数据提交到索引服务器中,这时,就可以让内容服务器访问索引服务器提供的WebService来提交数据;还可以让内容服务器通过定时任务,访问索引服务器的WebService来提交统计数据。

我的网站使用SpringSide 2.0开发,在SpringSide 2.0中,默认使用的是XFire来提供WebService,但是我按照文档进行操作,结果却失败了。于是我向江南白衣请教,白衣推荐我使用CXF的最新版本,于是我到官方网站下载了CXF的最新版,按照示例来了一遍,很快就成功了。由此可见,使用CXF不仅简单,而且成功率高。因此,我在这里把我的经验和大家分享。

第一步,下载CXF的最新版本,下载地址如下图:
01.PNG


第二步,将CXF中的lib文件夹中的下列jar文件拷贝到我们项目的webapp/WEB-INF/lib目录下:
commons-logging-1.1.jar
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中设置项目的库,如下图:
03.png

在这里,我不得不说一下另外一个问题,那就是启动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>
  
<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>
  
<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方法作为示例,如下:
package com.yumdays.service;

import javax.jws.WebService;
import com.yumdays.model.SUser;

@WebService
public interface IndexService {
    
public boolean addUser(SUser user,String adminName,String adminPassword);
}

而它的实现类如下:
package com.yumdays.service;

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文件,其内容如下:

<?xml version="1.0" encoding="UTF-8"?>
<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是否成功被部署了。如下图:
02.PNG


第六步,创建客户端,这一步非常的容易,只需要下面这样的配置:
<?xml version="1.0" encoding="UTF-8"?>
<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,就可以非常方便的访问索引服务器提供的功能。

评论

# re: 在SpringSide 2.0中使用CXF提供Web Service服务  回复  更多评论   

2008-03-09 11:57 by TonySoft
其实使用XFire比使用CXF要简单一些,但是CXF提供了更多的高级特性,如果项目允许,切换到CXF是一个不错的选择。

# re: 在SpringSide 2.0中使用CXF提供Web Service服务  回复  更多评论   

2008-03-18 10:23 by web
我和楼主的配置一样为什么通不过。
org.apache.cxf.binding.soap.SoapFault: Error reading XMLStreamReader.
org.apache.cxf.binding.soap.interceptor.Soap11FaultInInterceptor.handleMessage(Soap11FaultInInterceptor.java:70)
org.apache.cxf.binding.soap.interceptor.Soap11FaultInInterceptor.handleMessage(Soap11FaultInInterceptor.java:35)
org.apache.cxf.phase.PhaseInterceptorChain.doIntercept(PhaseInterceptorChain.java:208)
org.apache.cxf.interceptor.AbstractFaultChainInitiatorObserver.onMessage(AbstractFaultChainInitiatorObserver.java:96)
org.apache.cxf.binding.soap.interceptor.ReadHeadersInterceptor.handleMessage(ReadHeadersInterceptor.java:183)
org.apache.cxf.binding.soap.interceptor.ReadHeadersInterceptor.handleMessage(ReadHeadersInterceptor.java:56)
org.apache.cxf.phase.PhaseInterceptorChain.doIntercept(PhaseInterceptorChain.java:208)
org.apache.cxf.endpoint.ClientImpl.onMessage(ClientImpl.java:429)
org.apache.cxf.transport.http.HTTPConduit$WrappedOutputStream.handleResponse(HTTPConduit.java:1955)
org.apache.cxf.transport.http.HTTPConduit$WrappedOutputStream.close(HTTPConduit.java:1791)
org.apache.cxf.transport.AbstractConduit.close(AbstractConduit.java:66)
org.apache.cxf.transport.http.HTTPConduit.close(HTTPConduit.java:575)
org.apache.cxf.interceptor.MessageSenderInterceptor$MessageSenderEndingInterceptor.handleMessage(MessageSenderInterceptor.java:62)
org.apache.cxf.phase.PhaseInterceptorChain.doIntercept(PhaseInterceptorChain.java:208)
org.apache.cxf.endpoint.ClientImpl.invoke(ClientImpl.java:276)
org.apache.cxf.endpoint.ClientImpl.invoke(ClientImpl.java:222)
org.apache.cxf.frontend.ClientProxy.invokeSync(ClientProxy.java:73)
org.apache.cxf.jaxws.JaxWsClientProxy.invoke(JaxWsClientProxy.java:135)
$Proxy15.getCounter(Unknown Source)
com.hbby.installation.web.action.LoginAction.login(LoginAction.java:83)
sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
java.lang.reflect.Method.invoke(Method.java:585)
org.apache.struts.actions.ActionDispatcher.dispatchMethod(ActionDispatcher.java:335)
org.apache.struts.actions.ActionDispatcher.dispatchMethod(ActionDispatcher.java:318)
org.apache.struts.actions.ActionDispatcher.execute(ActionDispatcher.java:220)
com.hbby.installation.web.action.LoginAction.execute(LoginAction.java:44)
org.apache.struts.action.RequestProcessor.processActionPerform(RequestProcessor.java:431)
org.apache.struts.action.RequestProcessor.process(RequestProcessor.java:236)
org.apache.struts.action.ActionServlet.process(ActionServlet.java:1196)
org.apache.struts.action.ActionServlet.doPost(ActionServlet.java:432)
javax.servlet.http.HttpServlet.service(HttpServlet.java:710)
javax.servlet.http.HttpServlet.service(HttpServlet.java:803)
com.hbby.system.EncodingFilter.doFilter(EncodingFilter.java:36)

# re: 在SpringSide 2.0中使用CXF提供Web Service服务  回复  更多评论   

2008-03-18 20:09 by youxia
你还是把项目里面的库文件整理一下,把名称相同但版本较低的jar包删除。你出的错可能是因为XML解析错误引起的。

# re: 在SpringSide 2.0中使用CXF提供Web Service服务[未登录]  回复  更多评论   

2008-05-05 09:34 by 阿乐
上面的朋友是不是安装了卡吧杀毒软件,把它暂停一下试试.

# re: 在SpringSide 2.0中使用CXF提供Web Service服务  回复  更多评论   

2008-06-16 13:30 by hejianhuacn
@youxia
应该是卡巴的问题,我也碰到了,把它的Web防护关掉就好了

# re: 在SpringSide 2.0中使用CXF提供Web Service服务  回复  更多评论   

2008-09-02 14:53 by Eclipse_lijp
按照楼主步骤,CXF最后部署失败,访问http://localhost:8080/cxfServer/service/WebServiceSample?wsdl

页面报错:
java.lang.NoSuchMethodError: org.w3c.dom.Document.setXmlStandalone(Z)V
org.apache.cxf.transport.http.WSDLQueryHandler.updateDoc(WSDLQueryHandler.java:253)
org.apache.cxf.transport.http.WSDLQueryHandler.writeResponse(WSDLQueryHandler.java:201)
org.apache.cxf.transport.servlet.ServletController.invoke(ServletController.java:152)
org.apache.cxf.transport.servlet.AbstractCXFServlet.invoke(AbstractCXFServlet.java:174)
org.apache.cxf.transport.servlet.AbstractCXFServlet.doGet(AbstractCXFServlet.java:156)
javax.servlet.http.HttpServlet.service(HttpServlet.java:689)
javax.servlet.http.HttpServlet.service(HttpServlet.java:802)

望赐教,谢谢!

# re: 在SpringSide 2.0中使用CXF提供Web Service服务  回复  更多评论   

2008-09-04 14:55 by zhaoyutong
楼主,你好,我已经百度了cxf 官网的User guide 所有文章,但是有一些地方还没明白,我心情很沉重。我觉得我还是不会cxf

但是当我看到了这段话。
我的网站使用SpringSide 2.0开发,在SpringSide 2.0中,默认使用的是XFire来提供WebService,但是我按照文档进行操作,结果却失败了。于是我向江南白衣请教,白衣推荐我使用CXF的最新版本,于是我到官方网站下载了CXF的最新版,按照示例来了一遍,很快就成功了。由此可见,使用CXF不仅简单,而且成功率高。因此,我在这里把我的经验和大家分享。

以及文章的下边的内容。我觉得我是个高手了。如果我有你对待事物的态度就好了

这里www.frcircle.com有我收集的一些资料。 我觉得webservice是个庞大的体系

# re: 在SpringSide 2.0中使用CXF提供Web Service服务  回复  更多评论   

2010-09-30 15:09 by 刷刷刷
楼上是sb

只有注册用户登录后才能发表评论。


网站导航: