webservice CXF拦截器处理response消息。SOAP协议不匹配

目录

第一个问题,接收报错

第二个问题,响应不到

响应前重写消息

总结


场景:需要对接客户服务,获取信息。客户采用webservice接口调用传输数据。我放需要开发webservice的服务端给客户调用。

经过一番折腾,采用CXFServlet结合springmvc  的web形式开发。

第一个问题,接收报错

org.apache.cxf.binding.soap.SoapFault: SOAP 1.2 message is not valid when sent to a SOAP 1.1 only endpoint.

原因是 协议不匹配,需要使用soap1.2协议才可以。

解决办法是:在接口或实现类上声明

@Component("receive")
@WebService(targetNamespace = "http://service.webservice.com")
@BindingType(value= SOAPBinding.SOAP12HTTP_BINDING)
public class XcfService {

}

第二个问题,响应不到

调好这个之后是能接收到客户的消息了。。

但是响应的消息那边没有办法获取到(或者解析不出来),对方研发给的回应是

异常回复的报文
HTTP/1.1 200 OK
Server: Apache-Coyote/1.1
Content-Type: application/soap+xml;charset=UTF-8
Content-Length: 441
Date: Mon, 18 Nov 2019 08:02:41 GMT
Connection: close

<soap:Envelope
    xmlns:soap="http://www.w3.org/2003/05/soap-envelope">
    <soap:Body>
        <ns2:initSystemResponse
            xmlns:ns2="http://service.webservice.com">
            <return>
                <?xml version='1.0' encoding='UTF-8'?>
                <root>
                    <code>0</code>
                    <message>成功</message>
                    <sessionId>17448931860480646017448931860481</sessionId>
                </root>
            </return>
        </ns2:initSystemResponse>
    </soap:Body>
</soap:Envelope>

正常上级回复的报文
HTTP/1.1 200 OK
Server: gSOAP/2.8
Content-Type: application/soap+xml; charset=utf-8; action="urn:initSystem"
Content-Length: 922
Connection: close

<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://www.w3.org/2003/05/soap-envelope" xmlns:SOAP-ENC="http://www.w3.org/2003/05/soap-encoding"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:xsd="http://www.w3.org/2001/XMLSchema"
    xmlns:ns2="http://service.webservice.com/ServiceSoap11Binding"
    xmlns:ns1="http://service.webservice.com"
    xmlns:ns3="http://service.webservice.com/ServiceSoap12Binding">
    <SOAP-ENV:Body>
        <ns1:initSystemResponse>
            <ns1:return>
                <?xml version="1.0" encoding="UTF-8"?>
                <root>
                    <code>0</code>
                    <message>init system success.</message>
                    <sessionId>1007723808</sessionId>
                </root>
            </ns1:return>
        </ns1:initSystemResponse>
    </SOAP-ENV:Body>
</SOAP-ENV:Envelope>

看到之后第一想法就是消息头不一样,是不是要改。查阅一番,不好改。

后面就直接手动封装消息体,按照对方的格式封装,只是把自己的sessionId做动态设置,试了一下,果然可以。

才用的方法是

响应前重写消息

public class MyOutterceptor extends AbstractPhaseInterceptor<SoapMessage> {

    private static final Logger log = LoggerFactory.getLogger(ThirdBayonetService.class);

    private static String INIT_SYSTEM_RESPONSE = "initSystemResponse";

    public MyOutterceptor() {
        //流关闭之前 处理
        super(Phase.PRE_STREAM);
    }

    public MyOutterceptor(String phase) {
        super(phase);
    }

    public void handleMessage(SoapMessage message) {
        try {
            OutputStream os = message.getContent(OutputStream.class);
            CachedStream cs = new CachedStream();
            message.setContent(OutputStream.class, cs);
            message.getInterceptorChain().doIntercept(message);
            CachedOutputStream csnew = (CachedOutputStream) message.getContent(OutputStream.class);
            InputStream in = csnew.getInputStream();
            String xml = IOUtils.toString(in);

            StringBuffer stringBuffer = new StringBuffer();
            stringBuffer.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>" +
                    "<SOAP-ENV:Envelope xmlns:SOAP-ENV=\"http://www.w3.org/2003/05/soap-envelope\"" +
                    " xmlns:SOAP-ENC=\"http://www.w3.org/2003/05/soap-encoding\"" +
                    " xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"" +
                    " xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\"" +
                    " xmlns:ns2=\"http://service.webservice.com/ServiceSoap11Binding\"" +
                    " xmlns:ns1=\"http://service.webservice.com\"" +
                    " xmlns:ns3=\"http://service.webservice.com/ServiceSoap12Binding\">");

            if (xml != null && xml.contains(INIT_SYSTEM_RESPONSE)) {
                // 初始化
                stringBuffer.append("<SOAP-ENV:Body><ns1:initSystemResponse><ns1:return>" +
                        "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" +
                        "<root>" +
                        "<code>0</code>" +
                        "<message>init system success.</message>" +
                        "<sessionId>");

                String sessionId = "随机生成";
                stringBuffer.append(sessionId);

                stringBuffer.append("</sessionId></root></ns1:return></ns1:initSystemResponse></SOAP-ENV:Body></SOAP-ENV:Envelope>");
                log.info("initSystem response sessionId:{}", sessionId);  
            } else{
                stringBuffer = new StringBuffer(IOUtils.toString(in));
            }


            //这里对xml做处理,处理完后同理,写回流中
            IOUtils.copy(new ByteArrayInputStream(stringBuffer.toString().getBytes()), os);

            cs.close();
            os.flush();

            message.setContent(OutputStream.class, os);

        } catch (Exception e) {
            log.error("Error when split original inputStream. CausedBy : " + "\n" + e);
        }
    }

 然后在applicationContext.xml里面把拦截器配上,用的是 jaxws:outInterceptors 表响应拦截

    <!-- 自动扫描webService -->
    <context:component-scan base-package="com."/>
    <jaxws:endpoint implementor="#XcfService" address="/ThirdBayonetService">
        <jaxws:outInterceptors>
            <bean class="com.interceptor.ReceiveInterceptor"/>
        </jaxws:outInterceptors>
    </jaxws:endpoint>

总结

采用springmvc的Xcf搭建的webservice,本篇涉及的点是接收协议和响应封装

最后感谢:

https://www.iteye.com/blog/empirel-1620128

https://blog.csdn.net/tigerl2008/article/details/84268698

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

cy谭

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值