我的Java应用程序试图从Web服务获取信息。XML请求需要在XML根元素(类名)中指定命名空间,但标记(类字段)的命名空间必须为空(null),否则Web服务将拒绝该请求。
我必须将Spring 3.0和Spring WS 2.0与CastorMarshaller一起使用(目前使用的是Castor 1.3.1版本),才能将我的Java对象编组到XML中/从XML中取消编组。
请注意以下代码段中的__PREFIX__
和__NAMESPACE__
位置。
所需整理输出(即所需生成的SOAP请求)
<?xml version="1.0" encoding="UTF-8"?>
<soap-env:Envelope xmlns:soap-env="http://schemas.xmlsoap.org/soap/envelope/">
<soap-env:Header xmlns:soap-env="http://schemas.xmlsoap.org/soap/envelope/" />
<soap-env:Body xmlns:soap-env="http://schemas.xmlsoap.org/soap/envelope/">
<__PREFIX__:className xmlns:__PREFIX__="__NAMESPACE__">
<fieldName>fieldValue</fieldName>
</__PREFIX__:className>
</soap-env:Body>
</soap-env:Envelope>
当前整理的输出(即生成的SOAP请求)
未添加命名空间
<?xml version="1.0" encoding="UTF-8"?>
<soap-env:Envelope xmlns:soap-env="http://schemas.xmlsoap.org/soap/envelope/">
<soap-env:Header xmlns:soap-env="http://schemas.xmlsoap.org/soap/envelope/" />
<soap-env:Body xmlns:soap-env="http://schemas.xmlsoap.org/soap/envelope/">
<className>
<fieldName>fieldValue</fieldName>
</className>
</soap-env:Body>
</soap-env:Envelope>
或者将名称空间添加到所有元素
<?xml version="1.0" encoding="UTF-8"?>
<soap-env:Envelope xmlns:soap-env="http://schemas.xmlsoap.org/soap/envelope/">
<soap-env:Header xmlns:soap-env="http://schemas.xmlsoap.org/soap/envelope/" />
<soap-env:Body xmlns:soap-env="http://schemas.xmlsoap.org/soap/envelope/">
<__PREFIX__:className xmlns:__PREFIX__="__NAMESPACE__">
<__PREFIX__:fieldName xmlns:__PREFIX__="__NAMESPACE__">fieldValue</__PREFIX__:fieldName>
</__PREFIX__:className>
</soap-env:Body>
</soap-env:Envelope>
两者都被网络服务拒绝。
我的配置
applicationContext.xml
中的CastorMarshaller bean
<bean id="castorMarshaller" class="org.springframework.oxm.castor.CastorMarshaller">
<property name="mappingLocation" value="classpath:castor-mapping.xml" />
<property name="ignoreExtraAttributes" value="true" />
<property name="ignoreExtraElements" value="true" />
<property name="namespaceMappings">
<map>
<entry key="__PREFIX__" value="__NAMESPACE__" />
</map>
</property>
</bean>
Castor映射文件castor-mapping.xml
不添加命名空间(应将castorMarshaller
bean中通过namespaceMappings
指定的命名空间添加到根中)
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapping PUBLIC "-//EXOLAB/Castor Mapping DTD Version 1.0//EN"
"http://castor.org/mapping.dtd">
<mapping>
<class name="some.package.ClassName">
<map-to xml="className">
<field name="fieldName" type="string">
<bind-xml name="fieldName" node="element" />
</field>
</class>
</mapping>
或者将名称空间添加到所有元素
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapping PUBLIC "-//EXOLAB/Castor Mapping DTD Version 1.0//EN"
"http://castor.org/mapping.dtd">
<mapping>
<class name="some.package.ClassName">
<map-to xml="className" ns-uri="__NAMESPACE__" ns-prefix="__PREFIX__">
<field name="fieldName" type="string">
<bind-xml name="fieldName" node="element" />
</field>
</class>
</mapping>
由于我面临同样的问题,我正在考虑的解决方案如下:
- 创建一个扩展EndpointInterceptorAdapter的拦截器
- 重写handleResponse方法
- 通过直接访问或使用转换器修改为soap消息
公共类MyEndpointInterceptorAdapter扩展EndpointInterceptorAdapter{
@Override public boolean handleResponse(MessageContext msgContext, Object endpoint) throws IOException { WebServiceMessage responseMsg = msgContext.getResponse(); SoapMessage soapMsg = (SoapMessage) responseMsg; if(soapMsg!=null){ SoapEnvelope soapEnvelope=soapMsg.getEnvelope(); if(soapEnvelope!=null){ SoapBody soapbody=soapEnvelope.getBody(); if(soapbody!=null){ Source bodySource=soapbody.getSource(); if(bodySource instanceof DOMSource){ DOMSource bodyDomSource=(DOMSource)bodySource; Node bodyNode=bodyDomSource.getNode(); if(bodyNode!=null){ NodeList bodyNodeList=bodyNode.getChildNodes(); if(bodyNodeList.getLength()!=0){ Element root=(Element)bodyNodeList.item(0); root.setAttribute("xmlns:ns", "YourURI"); root.setPrefix("ns"); } } } } } } return true; } }