使用cxf时拦截器的使用

本文介绍如何在使用CXF时利用拦截器进行API响应的统一处理,重点探讨了gatewayOutInterceptor在拦截返回内容上的作用。
1.在使用cxf时,我们想对客户端发送的请求字符串做一些处理,这个时候可以使用gatewayInInterceptor来处理,代码和配置如下:
import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

import javax.xml.soap.SOAPException;

import org.apache.cxf.interceptor.Fault;
import org.apache.cxf.message.Message;
import org.apache.cxf.phase.AbstractPhaseInterceptor;
import org.apache.cxf.phase.Phase;
import org.apache.log4j.Logger;
import org.springframework.stereotype.Service;
@Service("gatewayInInterceptor")
public class GatewayInInterceptor extends AbstractPhaseInterceptor<Message> {
    private Logger logger = Logger.getLogger(GatewayInInterceptor.class);

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

    public GatewayInInterceptor(String phase) {
        super(phase);
    }

    @SuppressWarnings("static-access")
    @Override
    public void handleMessage(Message message) throws Fault {
        String reqParams = null;
        if (message.get(message.HTTP_REQUEST_METHOD).equals("GET")) {// 采用GET方式请求
            reqParams = (String) message.get(message.QUERY_STRING);
            try {
                if (!CompareSignatureUtil.compareSignature(this
                        .getParamsMap(reqParams))) {
                    // 如果签名不一样,
                    SOAPException soapEx = new SOAPException("签名错误");
                    throw new Fault(soapEx);
                }
            } catch (UnsupportedEncodingException e) {
                throw new Fault(e);
            }
            message.remove(message.QUERY_STRING);
            reqParams = this.getParams(this.getParamsMap(reqParams));
            message.put(message.QUERY_STRING, reqParams);
            logger.info("QUERY_STRING:" + reqParams);
        } else if (message.get(message.HTTP_REQUEST_METHOD).equals("POST")) {// 采用POST方式请求
            try {
                //
                reqParams = (String) message.get(message.QUERY_STRING);
                try {
                    if (!CompareSignatureUtil.compareSignature(this
                            .getParamsMap(reqParams))) {
                        // 如果签名不一样,
                        SOAPException soapEx = new SOAPException("签名错误");
                        throw new Fault(soapEx);
                    }
                } catch (UnsupportedEncodingException e) {
                    throw new Fault(e);
                }
                message.remove(message.QUERY_STRING);
                reqParams = this.getParams(this.getParamsMap(reqParams));
                message.put(message.QUERY_STRING, reqParams);
                logger.info("》》》》》》》》》QUERY_STRING:" + reqParams);
                //
                InputStream is = message.getContent(InputStream.class);
                reqParams = this.getParams(this.getParamsMap(is.toString()));
                if (is != null && reqParams != null) {
                    message.setContent(InputStream.class,
                            new ByteArrayInputStream(reqParams.getBytes()));
                    logger.info("》》》》》》》》》Content:" + reqParams);
                }
            } catch (Exception e) {
                logger.error("GatewayInInterceptor异常", e);
            }
        }
        
        // only test

        // SOAPException soapEx=new SOAPException("自定义SOAPException错误");
        // throw new Fault(soapEx);

        // /RuntimeException ex=new RuntimeException("自定义RuntimeException错误");
        //throw new Fault(ex);

        // throw new RuntimeException("自定义SOAPException错误");

    }

    private Map<String, String> getParamsMap(String strParams) {
        if (strParams == null || strParams.trim().length() <= 0) {
            return null;
        }
        Map<String, String> map = new HashMap<String, String>();
        String[] params = strParams.split("&");
        for (int i = 0; i < params.length; i++) {
            String[] arr = params[i].split("=");
            if (arr.length > 1) {
                map.put(arr[0], arr[1]);
            }
        }
        return map;
    }

    private String getParams(Map<String, String> map) {
        if (map == null || map.size() == 0) {
            return null;
        }
        StringBuffer sb = new StringBuffer();
        Iterator<String> it = map.keySet().iterator();
        while (it.hasNext()) {
            String key = it.next();
            String value = map.get(key);

            /*
             * 这里可以对客户端上送过来的输入参数进行特殊处理。如密文解密;对数据进行验证等等。。。
             * if(key.equals("content")){ value.replace("%3D", "="); value =
             * DesEncrypt.convertPwd(value, "DES"); }
             */
            if (sb.length() <= 0) {
                if (key.toUpperCase().equals("FORMAT"))
                    sb.append("_type" + "=" + value);
                else
                    sb.append(key + "=" + value);
            } else {
                if (key.toUpperCase().equals("FORMAT"))
                    sb.append("&_type" + "=" + value);
                else
                    sb.append("&" + key + "=" + value);
            }
        }
        return sb.toString();
    }

}



<bean id="gatewayInInterceptor"
		class="com.mingdong.b01.test.cxf.restful.intercepter.GatewayInInterceptor" />

	<jaxrs:server id="restServiceContainer" address="/rest">
		<!-- 参数处理的拦截器 -->
		<jaxrs:inInterceptors>
			<ref bean="inMessageInterceptor" />
			<ref bean="gatewayInInterceptor" />
		</jaxrs:inInterceptors>

2.当你想对返回的响应内容做统一的处理的时候,可以使用gatewayOutInterceptor,

import org.apache.commons.io.IOUtils;
import org.apache.cxf.phase.AbstractPhaseInterceptor;

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

import org.apache.cxf.interceptor.Fault;
import org.apache.cxf.io.CachedOutputStream;
import org.apache.cxf.message.Message;
import org.apache.cxf.phase.Phase;
import org.apache.log4j.Logger;
import org.springframework.stereotype.Service;

@Service("gatewayOutInterceptor")
public class GatewayOutInterceptor extends AbstractPhaseInterceptor<Message> {

	private Logger logger = Logger.getLogger(GatewayOutInterceptor.class);

	public GatewayOutInterceptor() {
		super(Phase.PRE_STREAM); // 触发点在流关闭之前
	}

	@Override
	public void handleMessage(Message message) throws Fault {
		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 result = IOUtils.toString(in, "UTF-8");
			logger.info("返回给客户端值:" + result);
			System.out.println("返回给客户端值:" + result);
			/**
			 * 这里可以对result做处理,如可以对result进行加密,把密文返回给客户端 处理完后同理,写回流中
			 */
			//result=result+"3222";
			IOUtils.copy(new ByteArrayInputStream(result.getBytes("UTF-8")), os);
			System.out.println("返回给客户端值222222222222:" + result);
			cs.close();
			os.flush();
			message.setContent(OutputStream.class, os);
		} catch (Exception e) {
			logger.error("GatewayOutInterceptor异常", e);
		}
	}

i	@Override
	public void handleFault(Message message) {
		// TODO Auto-generated method stub
		super.handleFault(message);
	}

}

<bean id="gatewayOutInterceptor"
		class="com.mingdong.b01.test.cxf.restful.intercepter.GatewayOutInterceptor" />

<jaxrs:outInterceptors>
			<ref bean="outMessageInterceptor" />
			<ref bean="gatewayOutInterceptor" />
		</jaxrs:outInterceptors>

3.后来我们考虑到异常的处理,是否能把所有的异常都统一的做处理,在出现异常的时候,返回给客户端的响应是比较友好的,格式化的,当然cxf是有这个功能的,刚开始参考了一篇文章 点击打开链接,照着写了,可是没有成功,后来又在网上搜索了其他解决方式,比如写了一个<!-- <jaxrs:outFaultInterceptors> <ref bean="invokeFaultExceptionMapper"  /> </jaxrs:outFaultInterceptors> -->,可后来发现这个拦截器只能拦截除了拦截器之外其他类里面抛出的异常,有没有一中方式,一个拦截器可以拦截业务代码里面的异常,又可以拦截拦截器里面的异常呢?后来看到老外的一些文章,得到解决,在cxf3.0以上版本中,我们可以通过ExceptionMapper来一次性处理所有异常!这不就完美的解决了问题么。那么这个ExceptionMappery要怎么做呢,代码和配置如下:

import java.util.Locale;

import javax.ws.rs.core.Response;
import javax.ws.rs.core.Response.ResponseBuilder;
import javax.ws.rs.ext.ExceptionMapper;
import javax.ws.rs.ext.Provider;

/**
 * 异常的统一处理类
 * 
 * @author songyf
 *
 */

@Provider
public class XxInvokeFaultExceptionMapper implements
		ExceptionMapper<Throwable> {

	public XxInvokeFaultExceptionMapper per() {
		super();
	}

	public Response toResponse(Throwable ex) {
		StackTraceElement[] trace = new StackTraceElement[1];
		trace[0] = ex.getStackTrace()[0];
		ex.setStackTrace(trace);
		ResponseBuilder rb = Response
				.status(Response.Status.INTERNAL_SERVER_ERROR);
		// rb.type("application/json;charset=UTF-8");//返回json格式
		rb.type("application/xml;charset=UTF-8");//返回xml格式

		if (ex instanceof MingdongException) {// 自定义的异常类,
			XxException e = (XxException) ex;
			ExceptionEntity entity = new ExceptionEntity(e.getErrCode(),//这里可以根据你想返回的内容去定义自己的异常实体类
					e.getErrSubCode(), e.getMessage());
			rb.entity(entity);
		} else {
			rb.entity(ex);
		}
		rb.language(Locale.SIMPLIFIED_CHINESE);
		Response r = rb.build();
		return r;
	}

}
配置:

<jaxrs:providers>
			<bean class="org.codehaus.jackson.jaxrs.JacksonJsonProvider" />//转换json
			<bean
				class="org.apache.cxf.jaxrs.provider.xmlbeans.XMLBeansElementProvider" />//转换xml
			<bean
				class="com.xx.b01.test.cxf.restful.intercepter.XxInvokeFaultExceptionMapper" />
		</jaxrs:providers>
请注意,这里的cxf版本最好是3.0以上,我的版本是3.1.0





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值