zoukankan      html  css  js  c++  java
  • CXF通过拦截器修改请求报文

    最近一位做Siebel的同事需要通过Web Service接口调用另外一个系统,对方的Web Service使用的是CXF框架,并提供了WSDL文件。

    Siebel通过WSDL生成请求报文时报错,而直接通过SoapUI导入WSDL测试是OK的。通过抓取报文发现,两者生成的报文namespace有所不同,Siebel生成的namespace放在节点上,SoapUI生成的namespace放在头上,具体如下:

    Siebel生成的报文: 

    <SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
       <SOAP-ENV:Body>
          <handleCallCenterWarningInfo xmlns="http://service.webservice.kora.com/">
             <arg0>
                <handleDepartment/>
                <handleResult/>
                <handleStatus>1</handleStatus>
                <handleTime/>
                <realWarningCaseId/>
                <rescueOrderNumber>121212121</rescueOrderNumber>
             </arg0>
          </handleCallCenterWarningInfo>
       </SOAP-ENV:Body>
    </SOAP-ENV:Envelope>

    Siebel调用时报错信息如下:

    Unmarshalling Error: unexpected element (uri:"http://service.webservice.kora.com/", local:"arg0"). Expected elements are &lt;{}arg0>

    SoapUI生成的报文:

    <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ser="http://server.webservice.mycompany.com/">
       <soapenv:Header/>
       <soapenv:Body>
          <ser:haha>
             <arg0>
                <handleDepartment>1</handleDepartment>
                <handleResult>2</handleResult>
                <handleStatus>3</handleStatus>
                <handleTime>4</handleTime>
                <realWarningCaseId>5</realWarningCaseId>
                <rescueOrderNumber>6</rescueOrderNumber>
             </arg0>
          </ser:haha>
       </soapenv:Body>
    </soapenv:Envelope>

    针对报文格式问题,准备两种尝试方式:

    1、拦截请求报文,把报文修改成符合WS命名空间的结构。

    2、通过CXF框架的设置,设成不校验命名空间。(此方式没有技术参考,凭空想象的。后经测试验证也没有发现该配置选项,具体的WS规范以及CXF实现后续需要更深一步的查阅文档以及源码)

    后经测试验证,最终选择了方式1解决,具体调整步骤如下:

    1、在WS配置文件中增加红色区域内容。
    <jaxws:endpoint implementor="com.kora.webservice.service.CallCenterServiceImplPortImpl" address="/callCenterService" >
       <jaxws:inInterceptors>
           <bean class="com.info.CAbstractPhaseInterceptor">
               <constructor-arg><value>receive</value></constructor-arg>
           </bean>
       </jaxws:inInterceptors>
    </jaxws:endpoint>
     
    2、增加一个拦截类CallCenterServiceImplPortImpl修改报文:
    /**
     * CAbstractPhaseInterceptor.java
     * Created at 2017-4-13
     * Created by hff
     * Copyright (C) 2017 SHANGHAI XXX, All rights reserved.
     */
    package com.info;
    
    import java.io.ByteArrayInputStream;
    import java.io.IOException;
    import java.io.InputStream;
    
    import org.apache.cxf.binding.soap.Soap11;
    import org.apache.cxf.binding.soap.SoapVersion;
    import org.apache.cxf.helpers.IOUtils;
    import org.apache.cxf.interceptor.Fault;
    import org.apache.cxf.message.Message;
    import org.apache.cxf.phase.AbstractPhaseInterceptor;
    
    /**
     * <p>ClassName: CAbstractPhaseInterceptor</p>
     * <p>Description: cxf拦截器</p>
     * <p>Author: hff</p>
     * <p>Date: 2017-4-13</p>
     */
    public class CAbstractPhaseInterceptor extends AbstractPhaseInterceptor<Message> {
    
        /**
         * <p>Description: TODO</p>
         * @param phase
         */
        public CAbstractPhaseInterceptor(String phase) {
            super(phase);
        }
    
        /* (non-Javadoc)
         * <p>Title: handleMessage</p>
         * <p>Description: </p>
         * @param message
         * @throws Fault
         * @see org.apache.cxf.interceptor.Interceptor#handleMessage(org.apache.cxf.message.Message)
         */
        @Override
        public void handleMessage(Message message) throws Fault {
            InputStream is = message.getContent(InputStream.class);
            if (is != null) {
                try {
                    String str = IOUtils.toString(is);
                    // 原请求报文
                    System.out.println("====> request xml=
    " + str);
                    
                    // 把siebel格式的报文替换成符合cxf带前缀的命名空间
                    str = str.replace("<handleCallCenterWarningInfo xmlns="http://service.webservice.kora.com/">", 
                            "<ser:handleCallCenterWarningInfo xmlns:ser="http://service.webservice.kora.com/">").replace(
                                    "</handleCallCenterWarningInfo>", "</ser:handleCallCenterWarningInfo>").replace(
                                            "xmlns="http://service.webservice.kora.com/"", "");
                    // 替换后的报文
                    System.out.println("====> replace xml=
    " + str);
                    
                    InputStream ism = new ByteArrayInputStream(str.getBytes());
                    message.setContent(InputStream.class, ism);
                    
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    
    }
  • 相关阅读:
    连接查询
    使用聚合函数查询
    mysql 查询数据
    Mysql的基本操作
    MySQL的数据类型
    Mysql简介及安装教程
    客户端-服务端
    configparser模块
    反射
    class_method和static_method
  • 原文地址:https://www.cnblogs.com/feong/p/6722256.html
Copyright © 2011-2022 走看看