cxf与Spring结合发布服务端与客户端以及拦截器配置与使用

一、前言

其实网上有很多文章均说过CXF如何与Spring结合发布服务,以及如何构建测试客户端的话题。但纸上得来终觉浅,既然本次项目遇到了,且自己动手实践了,就做个记录。记录是最好的成长。且其中遇到了一些啼笑皆非的异常事件。

 

二、思路

实现正常的java接口以及实现类。业务实现逻辑暂且不表,这不是该文章的内容。

如下:

com.***.fax.facade.tomi.CallBackNotifyFacade

com.***.fax.facade.tomi.CallBackNotifyFacadeImpl

CallBackNotifyFacade上加入如下注解:@WebService

CallBackNotifyFacadeImpl上加入如下注解:

@WebService(endpointInterface = "com.qunar.fax.facade.tomi.CallBackNotifyFacade")

@Service("callBackNotifyFacadeImpl")

 

xml配置如下:

 

  <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"/>

    <!-- http://localhost:8081/callBackNotifyFacade/callBackNotifyFacade?wsdl -->
    <jaxws:endpoint
            id="callBackNotifyFacade"
            implementor="com.***.fax.facade.tomi.CallBackNotifyFacadeImpl"
            address="/callBackNotifyFacade" >
      <jaxws:inInterceptors>
         <bean class="com.***.fax.facade.interceptor.CxfLoggingInInterceptor"/>
      </jaxws:inInterceptors>
      <jaxws:outInterceptors>
         <bean class="com.***.fax.facade.interceptor.CxfLoggingOutInterceptor" />
       </jaxws:outInterceptors>
    </jaxws:endpoint>

 其中CxfLoggingInInterceptor与CxfLoggingOutInterceptor分别为入口和出口拦截器。代码如下:

 

 

 

public class CxfLoggingInInterceptor extends AbstractLoggingInterceptor {

    private static final Logger LOG = LogUtils.getLogger(LoggingInInterceptor.class);

    public CxfLoggingInInterceptor() {
        super(Phase.RECEIVE);
    }

    @Override
    protected Logger getLogger() {
        return LOG;
    }

    @Override
    public void handleMessage(Message message) throws Fault {
        // 日志增加唯一标识
        long startTime = SystemTimer.currentTimeMillis();
        NDC.push(startTime + "_" + Thread.currentThread().getId());
    }
}

 

 

   

public class CxfLoggingOutInterceptor extends AbstractLoggingInterceptor {

    private static final Logger LOG = LogUtils.getLogger(CxfLoggingOutInterceptor.class);

    public CxfLoggingOutInterceptor() {
        super(Phase.PRE_STREAM);
    }

    @Override
    protected Logger getLogger() {
        return LOG;
    }

    @Override
    public void handleMessage(Message message) throws Fault {
        // 释放内存,清除标记
        NDC.pop();
        NDC.remove();
        NDC.clear();
    }
}

 

    pom.xml配置信息

   

<!-- cxf -->
        <dependency>
            <groupId>org.apache.cxf</groupId>
            <artifactId>cxf</artifactId>
            <version>${cxf.version}</version>
            <type>pom</type>
        </dependency>
        <dependency>
            <groupId>org.apache.cxf</groupId>
            <artifactId>cxf-rt-frontend-jaxws</artifactId>
            <version>${cxf.version}</version>
            <exclusions>
                <exclusion>
                    <artifactId>geronimo-javamail_1.4_spec</artifactId>
                    <groupId>org.apache.geronimo.specs</groupId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>org.apache.cxf</groupId>
            <artifactId>cxf-rt-transports-http</artifactId>
            <version>${cxf.version}</version>
        </dependency>

  cxf.version 为  2.7.0

 

 

 

    服务端的代码就这些了。

 

三、客户端测试代码

 

 /**
     * 测试发送状态通知接口
     */
    @Test
    public void testSendFaxCallBack(){

        try{
            //生成动态客户端
            String wsdlUrl="fax/test/callback.wsdl";
            JaxWsDynamicClientFactory dynamicClient = JaxWsDynamicClientFactory.newInstance();
            Client client = dynamicClient.createClient(wsdlUrl);

            //设置超时时间
            HTTPConduit http = (HTTPConduit) client.getConduit();
            HTTPClientPolicy httpClientPolicy =  new  HTTPClientPolicy();
            httpClientPolicy.setConnectionTimeout( 36000 );
            httpClientPolicy.setAllowChunking( false );
            httpClientPolicy.setReceiveTimeout( 32000 );
            http.setClient(httpClientPolicy);

            //调用参数
            String xml="。。。。。";

            //调用,并返回结果
            Object[] res = client.invoke("sendCallBack", xml);
            System.out.println("response: " + res[0]);
        }catch (Exception e){
            logger.warn("",e);
        }
    }

 

 

四、开发过程出现的异常

1、异常信息如下:

 

HTTP

 Status 500 - Servlet.init() for servlet CXFServlet threw exception

type Exception report
message Servlet.init() for servlet CXFServlet threw exception
description The server encountered an internal error that prevented it from fulfilling this request.
exception
javax.servlet.ServletException: Servlet.init() for servlet CXFServlet threw exception
	org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:103)
	org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:293)
	org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:861)
	org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:606)
	org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:489)
	java.lang.Thread.run(Thread.java:662)
root cause
org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'cxf' is defined
	org.springframework.beans.factory.support.DefaultListableBeanFactory.getBeanDefinition(DefaultListableBeanFactory.java:568)
	org.springframework.beans.factory.support.AbstractBeanFactory.getMergedLocalBeanDefinition(AbstractBeanFactory.java:1099)
	org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:278)
	org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:198)
	org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1121)
	org.apache.cxf.transport.servlet.CXFServlet.loadBus(CXFServlet.java:77)
	org.apache.cxf.transport.servlet.CXFNonSpringServlet.init(CXFNonSpringServlet.java:71)
	org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:103)
	org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:293)
	org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:861)
	org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:606)
	org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:489)

 

 

   原因,以下配置信息未引入生效:   

   

    <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"/>

 

 

2、异常信息如下:

Caused by: org.apache.cxf.binding.soap.SoapFault: Error reading XMLStreamReader.
at org.apache.cxf.binding.soap.interceptor.Soap11FaultInInterceptor.handleMessage(Soap11FaultInInterceptor.java:70)
at org.apache.cxf.binding.soap.interceptor.Soap11FaultInInterceptor.handleMessage(Soap11FaultInInterceptor.java:35)
at org.apache.cxf.phase.PhaseInterceptorChain.doIntercept(PhaseInterceptorChain.java:221)
at org.apache.cxf.interceptor.AbstractFaultChainInitiatorObserver.onMessage(AbstractFaultChainInitiatorObserver.java:96)
at org.apache.cxf.binding.soap.interceptor.CheckFaultInterceptor.handleMessage(CheckFaultInterceptor.java:65)
at org.apache.cxf.binding.soap.interceptor.CheckFaultInterceptor.handleMessage(CheckFaultInterceptor.java:34)
at org.apache.cxf.phase.PhaseInterceptorChain.doIntercept(PhaseInterceptorChain.java:221)
at org.apache.cxf.endpoint.ClientImpl.onMessage(ClientImpl.java:429)

    原因:这个错误是最让我没有头绪的,因为一切配置正常,在本地测试也很正常,但是一上服务器就报错。

    查了很多的原因,更换了很多的版本,均无效,最后偶然发现在发布的脚本job里面,有一个checkurl,用来检查最终发布是否成功,被我写成了wsdl发布的url,结果造成ws服务未完全起来的时候,该url就会被不断重试。导致异常。

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值