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 : " + " " + 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 : " + "
" + 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("&lt;", "<");
                str=str.replace("&gt;", ">");
                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);
    }
}
原文地址:https://www.cnblogs.com/fengxiaoyuan/p/10683806.html