最近项目需要与外部项目进行数据交换,需要开发webservice接口,项目的webservice基于CXF开发的,返回报文格式不符合接口调用方的规范:
例如:
CXF自动返回的报文格式如下:
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<ns2:doRequestResponse xmlns:ns2="http://aaa.bbb.ccc.ddd/">
<return>返回的数据。。。。</return>
</ns2:doRequestResponse >
</soap:Body>
</soap:Envelope>
然而,接口调用方要求格式如下:
<?xml version="1.0" ?>
<S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/">
<S:Body>
<ns2:doRequestResponse xmlns:ns2="http://aaa.bbb.ccc.ddd/">
<return>返回的数据。。。。</return>
</ns2:doRequestResponse>
</S:Body>
</S:Envelope>
怎么办?开发一个基于CXF的拦截器,数据返回前进行拦截,改写报文,再返回。
具体步骤如下:
1. 准备好CXF的有关的jar包,可以到官网下载。
2. 新建java工程,构建路径中引入上面的jar包。
3. 新建一个类MyInterceptor,继承AbstractPhaseInterceptor<SoapMessage>
public class MyInterceptor extends AbstractPhaseInterceptor<SoapMessage> {
public MyInterceptor () {
super(Phase.PRE_STREAM);
// TODO Auto-generated constructor stub
}
@Override
public void handleMessage(SoapMessage message) throws Fault {
// TODO Auto-generated method stub
String ms = "";
try {
// 从输出流中获取内容
OutputStream os = (OutputStream)message.getContent(OutputStream.class);
CachedOutputStream cs = new CachedOutputStream();
message.setContent(OutputStream.class, cs);
message.getInterceptorChain().doIntercept(message);
CachedOutputStream csnew = (CachedOutputStream)message.getContent(OutputStream.class);
InputStream in = csnew.getInputStream();
// 将流转换为字符串
ms = IOUtils.toString(in, "UTF-8");
ms = ms.replace("soap:", "S:");
ms = ms.replace(":soap", ":S");
ms = "<?xml version=\"1.0\" ?>" + ms;
IOUtils.copy(new ByteArrayInputStream(ms.getBytes("UTF-8")), os);
cs.close();
os.flush();
message.setContent(OutputStream.class, os);
} catch (IOException var7) {
System.out.println(var7.getMessage() + var7);
}
}
}
4. 在CXF的的配置文件cxf-servlet.xml中配置:
<cxf:bus>
<cxf:outInterceptors>
<bean class="你的包名.MyZInterceptor"></bean>
</cxf:outInterceptors>
</cxf:bus>
5. 重启CXF服务,大功告成:
6. 如果要对指定的服务做拦截,其它服务不拦截,加入下列代码:
boolean isMyService = false;
Exchange ec = message.getExchange();
if (ec != null)
for (String key : ec.keySet()) {
// System.out.println(key + ":" + ec.get(key));
if ("javax.xml.ws.wsdl.description".equals(key)) {
Object o = ec.get(key);
if (o != null && "/你的service的完整路径?wsdl".equals(o.toString())) {
isGonganService = true;
break;
}
}
}
在第三步的拦截代码上加判断:
if (MyService) {
//是我的服务,进行拦截
}
原创不易,转载请注明出处。