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

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

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

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

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

先来看一个InInterceptor
  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.     } 
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的时候,始终从流里边读不到数据,官网上没有例子,网上也搜了好多好多,最后在一个国外的论坛上搜到了,使用方式如下:

  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.  
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()方法来指定自己的拦截器放到什么位置。

  • 2
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值