CXF WebService SpringBoot 添加拦截器,处理响应报文格式
描述
XFIRE升级CXF框架,但是对接的系统不做调整,这时候就要保证参数报文和响应报文和以前是一致的。但是不同的框架有不同的规则,想要将报文调整的一致,就需要用到拦截器拦截报文,自定义解析处理。
CXF框架本身就是支持配置自定义拦截器的,以下是案例。
响应拦截器案例
package com.xinyuan.model.thirdparty.cxf.interceptor;
import org.apache.cxf.interceptor.AttachmentOutInterceptor;
import org.apache.cxf.io.CachedOutputStream;
import org.apache.cxf.message.Message;
import org.apache.cxf.phase.AbstractPhaseInterceptor;
import org.apache.cxf.phase.Phase;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import java.io.OutputStream;
import java.io.StringReader;
import java.io.StringWriter;
public class NamespacePrefixInterceptor extends AbstractPhaseInterceptor<Message> {
public NamespacePrefixInterceptor() {
// 在发送消息之前的阶段进行拦截
super(Phase.PRE_STREAM);
// 添加依赖的拦截器
addAfter(AttachmentOutInterceptor.class.getName());
}
@Override
public void handleMessage(Message message) {
try {
// 获取输出流
OutputStream outputStream = message.getContent(OutputStream.class);
if (outputStream == null) {
return;
}
// 使用 CachedOutputStream 缓存输出流,以便我们可以读取和修改它
CachedOutputStream cachedOutputStream = new CachedOutputStream();
message.setContent(OutputStream.class, cachedOutputStream);
// 在拦截器处理完毕后,将缓存的输出流写回到原始输出流中
message.getInterceptorChain().doIntercept(message);
// 读取缓存的输出流内容
try (CachedOutputStream cos = cachedOutputStream) {
String response = new String(cos.getBytes());
// 在这里对 response 进行处理
String modifiedResponse = processResponse(response);
// 将处理后的内容写回到输出流中
try (OutputStream finalOutputStream = outputStream) {
finalOutputStream.write(modifiedResponse.getBytes());
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
private String processResponse(String response) {
//在这里写处理报文的逻辑
return response;
}
}
- 在发布接口的代码处,添加拦截器
通过dom的方式解析xml,并为满足条件的元素添加属性
public static void main(String[] args){
String xml = "<soap:Envelope xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\">\n" +
" <soap:Body>\n" +
" <ns1:queryGysxxResponse xmlns:ns1=\"http://iface.xt.service.zzxy.com\" xmlns=\"http://entity.service.zzxy.com\">\n" +
" <ns1:out>\n" +
" <cz>111</cz>\n" +
" <dh xsi:nil=\"true\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"/>\n" +
" <dzyx xsi:nil=\"true\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"/>\n" +
" <frdbmc xsi:nil=\"true\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"/>\n" +
" <gsdz xsi:nil=\"true\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"/>\n" +
" <gysbh>gysbh</gysbh>\n" +
" <gysmc xsi:nil=\"true\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"/>\n" +
" <khhmc xsi:nil=\"true\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"/>\n" +
" <khhzh xsi:nil=\"true\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"/>\n" +
" <lxrmc xsi:nil=\"true\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"/>\n" +
" <sj xsi:nil=\"true\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"/>\n" +
" <xxdz xsi:nil=\"true\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"/>\n" +
" <yzbh xsi:nil=\"true\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"/>\n" +
" <zzjgdmh xsi:nil=\"true\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"/>\n" +
" </ns1:out>\n" +
" </ns1:queryGysxxResponse>\n" +
" </soap:Body>\n" +
"</soap:Envelope>";
try {
// 创建DocumentBuilderFactory对象
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
// 设置命名空间感知
factory.setNamespaceAware(true);
// 创建DocumentBuilder对象
DocumentBuilder builder = factory.newDocumentBuilder();
// 解析XML字符串
Document document = builder.parse(new InputSource(new StringReader(xml)));
// 获取<ns1:out>元素
NodeList outNodes = document.getElementsByTagNameNS("http://iface.xt.service.zzxy.com", "out");
if (outNodes.getLength() > 0) {
Element outElement = (Element) outNodes.item(0);
// 获取<ns1:out>元素下的所有子节点
NodeList childNodes = outElement.getChildNodes();
for (int i = 0; i < childNodes.getLength(); i++) {
Node childNode = childNodes.item(i);
if (childNode.getNodeType() == Node.ELEMENT_NODE) {
// 修改子节点的命名空间
//((Element) childNode).setNamespaceURI("http://entity.service.zzxy.com");
((Element) childNode).setAttribute("a","http://entity.service.zzxy.com");
}
}
}
// 输出修改后的XML
TransformerFactory transformerFactory = TransformerFactory.newInstance();
Transformer transformer = transformerFactory.newTransformer();
DOMSource source = new DOMSource(document);
StreamResult result = new StreamResult(System.out);
transformer.transform(source, result);
} catch (Exception e) {
e.printStackTrace();
}
}
dom4j的方式解析xml,对满足条件的元素添加命名空间
public static void main(String[] args) throws DocumentException {
String xml = "<soap:Envelope xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\">\n" +
" <soap:Body>\n" +
" <ns1:queryGysxxResponse xmlns:ns1=\"http://iface.xt.service.zzxy.com\" xmlns=\"http://entity.service.zzxy.com\">\n" +
" <ns1:out>\n" +
" <cz>111</cz>\n" +
" <dh xsi:nil=\"true\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"/>\n" +
" <dzyx xsi:nil=\"true\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"/>\n" +
" <frdbmc xsi:nil=\"true\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"/>\n" +
" <gsdz xsi:nil=\"true\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"/>\n" +
" <gysbh>gysbh</gysbh>\n" +
" <gysmc xsi:nil=\"true\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"/>\n" +
" <khhmc xsi:nil=\"true\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"/>\n" +
" <khhzh xsi:nil=\"true\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"/>\n" +
" <lxrmc xsi:nil=\"true\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"/>\n" +
" <sj xsi:nil=\"true\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"/>\n" +
" <xxdz xsi:nil=\"true\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"/>\n" +
" <yzbh xsi:nil=\"true\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"/>\n" +
" <zzjgdmh xsi:nil=\"true\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"/>\n" +
" </ns1:out>\n" +
" </ns1:queryGysxxResponse>\n" +
" </soap:Body>\n" +
"</soap:Envelope>";
try {
SAXReader reader = new SAXReader();
Document document = reader.read(new StringReader(xml));
Element root = document.getRootElement();
//printElementNames(root);
//查找 <ns1:out> 元素
Element ns1OutElement = root.element("Body").element("queryGysxxResponse").element("out");
// 打印所有的元素名称
printElementNames(ns1OutElement);
setNamespaceForChildElements(ns1OutElement);
} catch (DocumentException e) {
e.printStackTrace();
}
}
private static void setNamespaceForChildElements(Element element) {
// 创建目标命名空间
Namespace targetNamespace = new Namespace("", "http://entity.service.zzxy.com");
// 遍历当前元素的所有子元素
for (Object child : element.elements()) {
if (child instanceof Element) {
Element childElement = (Element) child;
// 将子元素的 QName 更新为目标命名空间
QName newQName = new QName(childElement.getName(), targetNamespace);
childElement.setQName(newQName);
}
}
}
private static void printElementNames(Element element) {
// 打印当前元素的名称
System.out.println(element.getName());
// 递归打印子元素的名称
for (Object child : element.elements()) {
if (child instanceof Element) {
printElementNames((Element) child);
}
}
}