參考: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); } }