当前位置: 首页 > 工具软件 > Apache CXF > 使用案例 >

Apache CXF interceptor拦截器的使用

唐威
2023-12-01

现在一般很少会用到Webservice了,但有时候和第三方传统机构对接,他们用的可能是WebService。这里写下CXF 拦截器的使用。

拦截器分为服务端拦截器和客户端拦截器,又分为入拦截器(in)和出拦截器(out)

先讲述一个Webservice请求过程如下。

1、首先是客户端发起请求,在请求到达服务端之前,我们可以用客户端出拦截器(client  out  interceptor)进行拦截,比如可以修改下请求报文。

2、客户端发出请求后,接下来应该是服务端接收请求了。服务端接收请求之前可以通过服务端入拦截器(server  in  interceptor)先进行报文的拦截。

3、服务端接收到请求之后,自身需要处理,处理完请求后,就会进行响应了。在响应抵达客户端之前,我们可以通过服务端出拦截器(server  out  interceptor)进行相应报文的拦截。

4、接下来是客户端接收响应消息了,在客户端接收响应消息之前,我们可以通过客户端入拦截器(client  in  interceptor)进行拦截。

借助拦截器我们通常可以用来对报文XML消息体进行修改,比如我们可以根据实际需要修改其命名空间或者甚至XML消息内容。

一般我们要么是在消息发出之前(分为客户端消息发给服务端之前(client out interceptor),或者服务端发消息给客户端响应之前(server out interceptor)进行修改(此时是出拦截器,对应的生命周期阶段是Phase.PRE_STREAM);

或者是消息接收之前(分为服务端接收客户端的消息(server in interceptor),或者是客户端接收服务端响应消息之前(client in interceptor)进行修改(此时是入拦截器,对应生命周期阶段是Phase.RECEIVE))。

上面提到的生命周期阶段要注意,因为消息在不同时间点,所存在的形式是不一样的。我上面提到的生命周期是基于大部分拦截器仅仅是需要对XML报文进行一定的修改。如果需要对消息进行其他处理,请选择合适的阶段。

可以根据实际需要,选择对应的入拦截器或者出拦截器。

首先加入Apache Cxf 相关依赖包,我这里使用的是cxf 3.1.10版本

<!-- cxf Web Service -->
		<dependency> 
			<groupId>org.apache.cxf</groupId> 
			<artifactId>cxf-rt-frontend-jaxws</artifactId> 
			<version>3.1.10</version> 
		</dependency> 
		<dependency> 
			<groupId>org.apache.cxf</groupId> 
			<artifactId>cxf-rt-transports-http</artifactId> 
			<version>3.1.10</version> 
		</dependency>

下面首先提供入拦截器(in interceptor)例子

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.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * WebService入拦截器
 * @author lichuang
 *
 */
public class CxfInInterceptor extends AbstractPhaseInterceptor<SoapMessage>{
	
	private static final Logger logger = LoggerFactory.getLogger(CxfInInterceptor.class);


	public CxfInInterceptor() {
		super(Phase.RECEIVE);
	}

	@Override
	public void handleMessage(SoapMessage message) {
		InputStream is = message.getContent(InputStream.class);
		if (is != null) {
            try {
                String str = IOUtils.toString(is);
                str=str.replace("str1", "str2");
                InputStream ism = new ByteArrayInputStream(str.getBytes());
                message.setContent(InputStream.class, ism);
            }
            catch(IOException e){
            	logger.error("WebService消息拦截器处理异常!",e);
            }
		}
	}
}

再提供一个出拦截器(out interceptor)的例子

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

import org.apache.cxf.binding.soap.SoapMessage;
import org.apache.cxf.helpers.IOUtils;
import org.apache.cxf.io.CachedOutputStream;
import org.apache.cxf.phase.AbstractPhaseInterceptor;
import org.apache.cxf.phase.Phase;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class CxfOutInterceptor extends AbstractPhaseInterceptor<SoapMessage> {

	private static final Logger logger = LoggerFactory.getLogger(CxfOutInterceptor.class);
	
	public CxfOutInterceptor() {
		super(Phase.PRE_STREAM);
	}

	@Override
	public void handleMessage(SoapMessage message) {
		OutputStream os = message.getContent(OutputStream.class);
		if (os != null) {
			try {
				/*
				 * 网上提到当消息体很大时,拦截器获取得到的xml输出报文可能是空的,
				 * 可以试着将下面的CachedStream换成字节数组流ByteArrayOutputStream
				 */
				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=xml.replace("str1", "str2");
				// 这里对xml做处理,处理完后同理,写回流中
				IOUtils.copy(new ByteArrayInputStream(xml.getBytes()), os);
				cs.close();
				os.flush();
				message.setContent(OutputStream.class, os);
			} catch (IOException e) {
				logger.error("WebService消息命名空间拦截器处理异常!", 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 {
		}

	}
}

 

 类似资料: