CXF 拦截器 拦截请求和发送时的报文
参考:https://blog.csdn.net/yczz/article/details/16809859#commentBox
http://cxf.apache.org/docs/interceptors.html
https://elim.iteye.com/blog/2248620#_Toc431737707
cxf 可以对请求和发送时的报文进行拦截,然后对其进行加工成我们想要的格式,然后再放到回去!!!!!
我实现的是自定义拦截器
1.在需要拦截的方法上面加上这个注解,注解里面是我们的自定义拦截器
@OutInterceptors(interceptors = { "com.deloitte.tms.vat.webservice.result1.CDATAOutInterceptor" })
@InInterceptors(interceptors="com.deloitte.tms.vat.webservice.result1.ArtifactOutInterceptor")
2.对返回时的格式进行拦截实例,如果
public CDATAOutInterceptor() {
//这里代表流关闭之前的阶段,这很重要!可以到官网去看,拦截的阶段分为很多种
super(Phase.PRE_STREAM);
}
Phase.PRE_STREAM写的阶段不对可能会对想要的结果有影响,我开始写的Send和Write都是不生效的,网上也有好多博文写的是这种!!!踩到坑了!
import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import org.apache.cxf.helpers.IOUtils; 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.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; public class CDATAOutInterceptor extends AbstractPhaseInterceptor<Message> { private static final Logger log = LogManager.getLogger(ArtifactOutInterceptor.class); public CDATAOutInterceptor() {
//这里代表流关闭之前的阶段,这很重要!可以到官网去看,拦截的阶段分为很多种 super(Phase.PRE_STREAM); } @Override public void handleMessage(Message message) { /*这里是通过注解的方式来加<!CDATA[[]]>的格式 * message.put("disable.outputstream.optimization", Boolean.TRUE); * XMLStreamWriter writer = * StaxUtils.createXMLStreamWriter(message.getContent(OutputStream.class * )); message.setContent(XMLStreamWriter.class, new * CDATAXMLStreamWriter(writer)); */ 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); System.out.println("replaceBegin" + xml); //转换的方式 xml = xml.replace("<body>", "<![CDATA[<?xml version=\"1.0\" encoding=\"UTF-8\"?><body>") .replace("<returnMessage>", "<returnMessage><![CDATA[") .replace("</returnMessage>", "]]></returnMessage>").replace("<returnCode>", "<returnCode><![CDATA[") .replace("</returnCode>", "]]></returnCode>"); // 这里对xml做处理,处理完后同理,写回流中 System.out.println("replaceAfter" + xml); IOUtils.copy(new ByteArrayInputStream(xml.getBytes()), os); cs.close(); os.flush(); message.setContent(OutputStream.class, os); } catch (Exception e) { log.error("Error when split original inputStream. CausedBy : " + "\n" + e); } } private class CachedStream extends CachedOutputStream { public CachedStream() { super(); } protected void doFlush() throws IOException { currentStream.flush(); } protected void doClose() throws IOException { } protected void onWrite() throws IOException { } } }
如果上请求的数据量过大的话:会出现传输的xml获取不到数据的情况。需要将CachedStream换成ByteArrayOutputStream,
如下的方式:
1 @Override 2 public void handleMessage(Message message) { 3 try { 4 5 OutputStream os = message.getContent(OutputStream.class); 6 ByteArrayOutputStream cs=new ByteArrayOutputStream(); 7 8 message.setContent(OutputStream.class, cs); 9 10 message.getInterceptorChain().doIntercept(message); 11 12 //ByteArrayOutputStream csnew = (ByteArrayOutputStream) message.getContent(ByteArrayOutputStream.class); 13 //InputStream in = csnew.toString(charsetName); 14 //String xml = IOUtils.toString(in); 15 String xml=new String(cs.toByteArray(), "utf-8"); 16 log.info("replaceBegin"+xml); 17 xml = xml.replace(""0; 18 // 这里对xml做处理,处理完后同理,写回流中 19 log.info("replaceAfter"+xml); 20 IOUtils.copy(new ByteArrayInputStream(xml.getBytes()), os); 21 cs.close(); 22 os.flush(); 23 log.info("将参数设置会cxf框架中------------"); 24 message.setContent(OutputStream.class, os); 25 26 } catch (Exception e) { 27 log.error("Error when split original inputStream. CausedBy : " + "\n" + e); 28 } 29 }
3.对请求进行拦截
import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; import org.apache.cxf.binding.soap.SoapMessage; import org.apache.cxf.helpers.IOUtils; import org.apache.cxf.phase.AbstractPhaseInterceptor; import org.apache.cxf.phase.Phase; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; public class ArtifactOutInterceptor extends AbstractPhaseInterceptor<SoapMessage>{ private static final Logger log = LogManager.getLogger(ArtifactOutInterceptor.class); public ArtifactOutInterceptor() { //这儿使用pre_stream,意思为在流关闭之前 super(Phase.PRE_STREAM); } @Override public void handleMessage(SoapMessage message) { InputStream is = message.getContent(InputStream.class); if (is != null) { try { String str = IOUtils.toString(is); log.info("原格式--传入的xml格式为:"+str); str=str.replace("<", "<"); str=str.replace(">", ">"); str=str.replace("<?xml version=\"1.0\" encoding=\"UTF-8\"?>",""); InputStream ism = new ByteArrayInputStream(str.getBytes()); message.setContent(InputStream.class, ism); log.info("解析后的格式--传入的xml格式为:"+str); } catch(IOException e){ log.error("WebService消息拦截器处理异常!",e); } } } }
4.1.对输出加<CADATA[[]]>的另外一种方法
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import javax.xml.stream.XMLStreamWriter;
import org.apache.cxf.helpers.IOUtils;
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.apache.cxf.staxutils.StaxUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
public class CDATAOutInterceptor extends AbstractPhaseInterceptor<Message> {
private static final Logger log = LogManager.getLogger(ArtifactOutInterceptor.class);
public CDATAOutInterceptor() {
super(Phase.PRE_STREAM);
}
@Override
public void handleMessage(Message message) {
message.put("disable.outputstream.optimization", Boolean.TRUE);
XMLStreamWriter writer =
StaxUtils.createXMLStreamWriter(message.getContent(OutputStream.class
)); message.setContent(XMLStreamWriter.class, new
CDATAXMLStreamWriter(writer));
}
}
import java.util.Arrays; import javax.xml.stream.XMLStreamException; import javax.xml.stream.XMLStreamWriter; import org.apache.cxf.staxutils.DelegatingXMLStreamWriter; public class CDATAXMLStreamWriter extends DelegatingXMLStreamWriter{ private String currentElementName; private static String[] CDATA_ELEMENTS = { "returnCode", "returnMessage", "fpdm", "fphm","code", "smrq","kpfsh","kprq","fpje","fpse", "sl","spfsh", "spfmc","fply","fplx", "xgrq","zfbz" , "rzrq","rzzt","body","start_time","end_time"}; public CDATAXMLStreamWriter(XMLStreamWriter writer) { super(writer); } @Override public void writeCharacters(String text) throws XMLStreamException { boolean useCData = isNeedCData(); if (useCData) { super.writeCData(text); } else { super.writeCharacters(text); } } private boolean isNeedCData() { if(currentElementName.equals("body")||currentElementName.equals("data")){ System.out.println("-------"); } if (Arrays.asList(CDATA_ELEMENTS).contains(currentElementName)) { return true; } else { return false; } } public void writeStartElement(String prefix, String local, String uri) throws XMLStreamException { currentElementName = local; super.writeStartElement(prefix, local, uri); } }