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

来源:互联网 发布:电商项目面试题java 编辑:程序博客网 时间:2024/04/29 19:49
在接受soap消息的时候,可能需要对消息做预处理!可以使用拦截器实现这一目的! 

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

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

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

先来看一个InInterceptor 
Java代码  收藏代码
  1. package XXX.web.webservice.interceptor;  
  2.   
  3. import java.io.ByteArrayInputStream;  
  4. import java.io.InputStream;  
  5.   
  6. import org.apache.cxf.message.Message;  
  7. import org.apache.cxf.phase.AbstractPhaseInterceptor;  
  8. import org.apache.cxf.phase.Phase;  
  9. import org.apache.log4j.Logger;  
  10.   
  11. public class ArtifactInInterceptor extends AbstractPhaseInterceptor<Message> {  
  12.     private static final Logger log = Logger.getLogger(ArtifactInInterceptor.class);  
  13.       
  14.     public ArtifactInInterceptor() {  
  15.         //这儿使用receive,接收的意思  
  16.         super(Phase.RECEIVE);  
  17.     }  
  18.   
  19.     public void handleMessage(Message message){  
  20.           
  21.         try {  
  22.             InputStream is = message.getContent(InputStream.class);  
  23.             //这里可以对流做处理,从流中读取数据,然后修改为自己想要的数据  
  24.               
  25.             //处理完毕,写回到message中  
  26.             //在这里需要注意一点的是,如果修改后的soap消息格式不符合webservice框架格式,比如:框架封装后的格式为  
  27.             //<soap:Envelope xmlns:soap="http://www.w3.org/2001/12/soap-envelope" <soap:Body>  
  28.             //<这里是调用服务端方法的命名空间><这是参数名称>   
  29.             //这里才是真正的消息  
  30.             //</这里是调用服务端方法的命名空间></这是参数名称>  
  31.             //</soap:Body>  
  32.             //</soap:Envelope>  
  33.             //如果是以上这种格式,在暴露的接口方法里才会真正接收到消息,而如果请求中在body里边,没有加方法命名空间和参数名称,直接就是消息体  
  34.             //那接口方法里是接收不到消息的,因为cxf是按照上面的这种格式去解析的,所以如果不符合上面的格式,就应该在这里做处理  
  35.             //……………………处理代码……………………  
  36.               
  37.             if(is != null)  
  38.                 message.setContent(InputStream.class, is);  
  39.         } catch (Exception e) {  
  40.             log.error("Error when split original inputStream. CausedBy : "+"\n"+e);  
  41.         }  
  42.     }  
  43. }  

然后使用注解@InInterceptors(interceptors="XXX.ArtifactInInterceptor")加到实现类上。 
InInterceptor相比OutInterceptor来说简单多了,我在使用OutInterceptor的时候,始终从流里边读不到数据,官网上没有例子,网上也搜了好多好多,最后在一个国外的论坛上搜到了,使用方式如下:
Java代码  收藏代码
  1. package XXX.web.webservice.interceptor;  
  2.   
  3. import java.io.ByteArrayInputStream;  
  4. import java.io.IOException;  
  5. import java.io.InputStream;  
  6. import java.io.OutputStream;  
  7.   
  8. import org.apache.commons.io.IOUtils;  
  9. import org.apache.cxf.io.CachedOutputStream;  
  10. import org.apache.cxf.message.Message;  
  11. import org.apache.cxf.phase.AbstractPhaseInterceptor;  
  12. import org.apache.cxf.phase.Phase;  
  13. import org.apache.log4j.Logger;  
  14.   
  15. public class ArtifactOutInterceptor extends AbstractPhaseInterceptor<Message>{  
  16.     private static final Logger log = Logger.getLogger(ArtifactOutInterceptor.class);  
  17.   
  18.     public ArtifactOutInterceptor() {  
  19.         //这儿使用pre_stream,意思为在流关闭之前  
  20.         super(Phase.PRE_STREAM);  
  21.     }  
  22.   
  23.     public void handleMessage(Message message) {  
  24.   
  25.         try {  
  26.   
  27.             OutputStream os = message.getContent(OutputStream.class);  
  28.   
  29.             CachedStream cs = new CachedStream();  
  30.   
  31.             message.setContent(OutputStream.class, cs);  
  32.   
  33.             message.getInterceptorChain().doIntercept(message);  
  34.   
  35.             CachedOutputStream csnew = (CachedOutputStream) message.getContent(OutputStream.class);  
  36.             InputStream in = csnew.getInputStream();  
  37.               
  38.             String xml = IOUtils.toString(in);  
  39.               
  40.             //这里对xml做处理,处理完后同理,写回流中  
  41.             IOUtils.copy(new ByteArrayInputStream(xml.getBytes()), os);  
  42.               
  43.             cs.close();  
  44.             os.flush();  
  45.   
  46.             message.setContent(OutputStream.class, os);  
  47.   
  48.   
  49.         } catch (Exception e) {  
  50.             log.error("Error when split original inputStream. CausedBy : " + "\n" + e);  
  51.         }  
  52.     }  
  53.   
  54.     private class CachedStream extends CachedOutputStream {  
  55.   
  56.         public CachedStream() {  
  57.   
  58.             super();  
  59.   
  60.         }  
  61.   
  62.         protected void doFlush() throws IOException {  
  63.   
  64.             currentStream.flush();  
  65.   
  66.         }  
  67.   
  68.         protected void doClose() throws IOException {  
  69.   
  70.         }  
  71.   
  72.         protected void onWrite() throws IOException {  
  73.   
  74.         }  
  75.   
  76.     }  
  77.   
  78. }  

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

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


文章来自于:http://empirel.iteye.com/blog/1620128

0 0
原创粉丝点击