CXF 拦截器预处理request、response消息

在接受soap消息的时候,可能需要对消息做预处理!可以使用拦截器实现这一目的! 

cxf有2种拦截器,InInterceptor、OutInterceptor,顾名思义,InInterceptor可以处理soap请求消息,OutInterceptor可以处理soap响应消息。

所有的拦截器都继承自AbstractPhaseInterceptor<?>,此抽象拦截器实现了Interceptor接口! 

可以通过注解和配置文件2种方式来启用自定义的拦截器。 

先来看一个InInterceptor 

 

package XXX.web.webservice.interceptor; 
 
import java.io.ByteArrayInputStream; 
import java.io.InputStream; 
 
import org.apache.cxf.message.Message; 
import org.apache.cxf.phase.AbstractPhaseInterceptor; 
import org.apache.cxf.phase.Phase; 
import org.apache.log4j.Logger; 
 
public class ArtifactInInterceptor extends AbstractPhaseInterceptor<Message> { 
    private static final Logger log = Logger.getLogger(ArtifactInInterceptor.class); 
     
    public ArtifactInInterceptor() { 
        //这儿使用receive,接收的意思 
        super(Phase.RECEIVE); 
    } 
 
    public void handleMessage(Message message){ 
         
        try { 
            InputStream is = message.getContent(InputStream.class); 
            //这里可以对流做处理,从流中读取数据,然后修改为自己想要的数据 
             
            //处理完毕,写回到message中 
            //在这里需要注意一点的是,如果修改后的soap消息格式不符合webservice框架格式,比如:框架封装后的格式为 
            //<soap:Envelope xmlns:soap="http://www.w3.org/2001/12/soap-envelope" <soap:Body> 
            //<这里是调用服务端方法的命名空间><这是参数名称>  
            //这里才是真正的消息 
            //</这里是调用服务端方法的命名空间></这是参数名称> 
            //</soap:Body> 
            //</soap:Envelope> 
            //如果是以上这种格式,在暴露的接口方法里才会真正接收到消息,而如果请求中在body里边,没有加方法命名空间和参数名称,直接就是消息体 
            //那接口方法里是接收不到消息的,因为cxf是按照上面的这种格式去解析的,所以如果不符合上面的格式,就应该在这里做处理 
            //……………………处理代码…………………… 
             
            if(is != null) 
                message.setContent(InputStream.class, is); 
        } catch (Exception e) { 
            log.error("Error when split original inputStream. CausedBy : "+"\n"+e); 
        } 
    } 
} 

 

package XXX.web.webservice.interceptor;  
  
import java.io.ByteArrayInputStream;  
import java.io.InputStream;  
  
import org.apache.cxf.message.Message;  
import org.apache.cxf.phase.AbstractPhaseInterceptor;  
import org.apache.cxf.phase.Phase;  
import org.apache.log4j.Logger;  
  
public class ArtifactInInterceptor extends AbstractPhaseInterceptor<Message> {  
    private static final Logger log = Logger.getLogger(ArtifactInInterceptor.class);  
      
    public ArtifactInInterceptor() {  
        //这儿使用receive,接收的意思  
        super(Phase.RECEIVE);  
    }  
  
    public void handleMessage(Message message){  
          
        try {  
            InputStream is = message.getContent(InputStream.class);  
            //这里可以对流做处理,从流中读取数据,然后修改为自己想要的数据  
              
            //处理完毕,写回到message中  
            //在这里需要注意一点的是,如果修改后的soap消息格式不符合webservice框架格式,比如:框架封装后的格式为  
            //<soap:Envelope xmlns:soap="http://www.w3.org/2001/12/soap-envelope" <soap:Body>  
            //<这里是调用服务端方法的命名空间><这是参数名称>   
            //这里才是真正的消息  
            //</这里是调用服务端方法的命名空间></这是参数名称>  
            //</soap:Body>  
            //</soap:Envelope>  
            //如果是以上这种格式,在暴露的接口方法里才会真正接收到消息,而如果请求中在body里边,没有加方法命名空间和参数名称,直接就是消息体  
            //那接口方法里是接收不到消息的,因为cxf是按照上面的这种格式去解析的,所以如果不符合上面的格式,就应该在这里做处理  
            //……………………处理代码……………………  
              
            if(is != null)  
                message.setContent(InputStream.class, is);  
        } catch (Exception e) {  
            log.error("Error when split original inputStream. CausedBy : "+"\n"+e);  
        }  
    }  
}  

然后使用注解@InInterceptors(interceptors="XXX.ArtifactInInterceptor")加到实现类上。 
InInterceptor相比OutInterceptor来说简单多了,我在使用OutInterceptor的时候,始终从流里边读不到数据,官网上没有例子,网上也搜了好多好多,最后在一个国外的论坛上搜到了,使用方式如下:

package XXX.web.webservice.interceptor; 
 
import java.io.ByteArrayInputStream; 
import java.io.IOException; 
import java.io.InputStream; 
import java.io.OutputStream; 
 
import org.apache.commons.io.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.log4j.Logger; 
 
public class ArtifactOutInterceptor extends AbstractPhaseInterceptor<Message>{ 
    private static final Logger log = Logger.getLogger(ArtifactOutInterceptor.class); 
 
    public ArtifactOutInterceptor() { 
        //这儿使用pre_stream,意思为在流关闭之前 
        super(Phase.PRE_STREAM); 
    } 
 
    public void handleMessage(Message message) { 
 
        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); 
             
            //这里对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 { 
 
        } 
 
    } 
 
} 
package XXX.web.webservice.interceptor;  
  
import java.io.ByteArrayInputStream;  
import java.io.IOException;  
import java.io.InputStream;  
import java.io.OutputStream;  
  
import org.apache.commons.io.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.log4j.Logger;  
  
public class ArtifactOutInterceptor extends AbstractPhaseInterceptor<Message>{  
    private static final Logger log = Logger.getLogger(ArtifactOutInterceptor.class);  
  
    public ArtifactOutInterceptor() {  
        //这儿使用pre_stream,意思为在流关闭之前  
        super(Phase.PRE_STREAM);  
    }  
  
    public void handleMessage(Message message) {  
  
        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);  
              
            //这里对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 {  
  
        }  
  
    }  
  
}  

然后使用注解@OutInterceptors(interceptors="XXX.ArtifactOutInterceptor")加到实现类上。 

cxf框架中,有默认的拦截器链,可以使用addAfter()和addBefore()方法来指定自己的拦截器放到什么位置。

 

posted @ 2014-12-01 15:23  贝壳风铃  阅读(1289)  评论(0)    收藏  举报