玩轉aop之cxf配置攔截器

1、客戶端寫法

一、配置


<jaxrs:outInterceptors>
			<bean
				class="com.xxx.base.interceptor.CxfOutMessageInterceptor"></bean>
		</jaxrs:outInterceptors>

二、CxfOutMessageInterceptor

cxf客戶端將公共參數放在頭信息裏面傳遞到cxf的服務器端 java


import javax.ws.rs.core.MultivaluedMap;

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

import com.iflashbuy.base.common.CommonParams;
import com.iflashbuy.base.common.ContextThread;
import com.iflashbuy.base.util.ParamUtils;
import com.iflashbuy.base.util.StringUtil;
import com.iflashbuy.util.F2BUtil;

/**
 * cxf攔截器,在請求服務前生效<br>
 * 一、將公共參數經過header傳到服務器端cxf
 * 
 * @author 漂泊者及其影子
 * @date 2016年1月13日
 */
public class CxfOutMessageInterceptor extends AbstractPhaseInterceptor<Message> {
	private Logger logger = LoggerFactory.getLogger(getClass());

	public CxfOutMessageInterceptor() {
		super(Phase.WRITE);
	}

	@Override
	public void handleMessage(Message message) throws Fault {
		String sysid = "";
		String key = "";
		CommonParams params = ContextThread.getCurrentParams();
		if (params != null) {
			sysid = params.getSysid();
			key = params.getKey();
		} else {
			sysid = ParamUtils.get("sysid");
			key = ParamUtils.get("key");
		}

		@SuppressWarnings("unchecked")
		MultivaluedMap<String, Object> headers = (MultivaluedMap<String, Object>) message.get(Message.PROTOCOL_HEADERS);
		headers.putSingle("sysid", sysid);
		headers.putSingle("key", key);

	}
	


}



2、cxf服務器端寫法


一、配置

<jaxrs:inInterceptors>
			<bean class="com.xxx.base.util.CxfInMessageInterceptor"></bean>
		</jaxrs:inInterceptors>
       
       	<jaxrs:outInterceptors>
			<bean
				class="com.xxx.base.util.CxfOutMessageInterceptor"></bean>
		</jaxrs:outInterceptors>



二、CxfInMessageInterceptor

cxf服務器端在接受請求的時候從請求的頭信息中獲取公共參數 apache

import java.util.List;
import java.util.TreeMap;

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

import com.iflashbuy.base.common.ContextThread;
import com.iflashbuy.base.constant.BaseConstant;

/**
 * cxf攔截器,在接受服務時候生效<br>
 * 一、獲取從客戶端傳來的sysid<br>
 * 
 * @author 漂泊者及其影子
 * @date 2016年1月13日
 */
public class CxfInMessageInterceptor extends AbstractPhaseInterceptor<Message> {
	private Logger logger = LoggerFactory.getLogger(getClass());

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

	@Override
	public void handleMessage(Message message) throws Fault {
		@SuppressWarnings("unchecked")
		TreeMap<String, Object> headers = (TreeMap<String, Object>) message.get(Message.PROTOCOL_HEADERS);
		String sysid = "";
		@SuppressWarnings("unchecked")
		List<String> sysidList = (List<String>) headers.get("sysid");
		if (CollectionUtil.isNotEmpty(sysidList)) {
			logger.info("sysid:" + sysidList.get(0));
			sysid = sysidList.get(0);
		}
		ContextThread.setCurrentSysid(sysid);
		log(message);
	}

	private void log(Message message) {
		if(BaseConstant.DEBUG_ENABLED) {
			String requestUri = (String) message.get(Message.REQUEST_URI);
			logger.info("requestUri:" + requestUri);
		}

	}
}



三、CxfOutMessageInterceptor

出於保險考慮,在cxf服務器端的請求完成後將ThreadLocal裏面的對象銷燬 服務器

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 com.iflashbuy.base.common.ContextThread;

/**
 * cxf服務器端攔截器,在請求完成後生效<br>
 *
 * 
 * @author 漂泊者及其影子
 * @date 2016年1月13日
 */
public class CxfOutMessageInterceptor extends AbstractPhaseInterceptor<Message> {
	public CxfOutMessageInterceptor() {
		super(Phase.WRITE);
	}

	@Override
	public void handleMessage(Message message) throws Fault {
		// 在請求完成後銷燬contextThread裏面的內容
		ContextThread.setCurrentSysid(null);
	}

}



3、ContextThread

cxf服務器端將公共參數放在ThreadLocal裏面,以便cxf服務器端具體的業務方法可以拿到這些公共參數 session

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * 
 * @author limanman
 * @date 2015年11月24日
 */
public class ContextThread {
	/**
	 * ThreadLocal確保高併發下每一個請求的request,response都是獨立的
	 */
	private static ThreadLocal<HttpServletRequest> currentRequest = new ThreadLocal<HttpServletRequest>();
	private static ThreadLocal<HttpServletResponse> currentResponse = new ThreadLocal<HttpServletResponse>();
	private static ThreadLocal<CommonParams> currentParams = new ThreadLocal<CommonParams>();
	private static ThreadLocal<String> threadSessionKey = new ThreadLocal<String>();
	
	/**
	 * 用於sgint_service,進在cxf接受請求的時候將sysid設入
	 */
	private static ThreadLocal<String> currentSysid = new ThreadLocal<String>();
	
	
	public static String getCurrentSysid() {
		return currentSysid.get();
	}

	public static void setCurrentSysid(String sysid) {
		ContextThread.currentSysid.set(sysid);
	}

	public static CommonParams getCurrentParams() {
		return currentParams.get();
	}

	public static void setCurrentParams(CommonParams currentParams) {
		ContextThread.currentParams.set(currentParams);
	}

	public static HttpServletRequest getCurrentRequest() {
		return currentRequest.get();
	}

	public static void setCurrentRequest(HttpServletRequest currentRequest) {
		ContextThread.currentRequest.set(currentRequest);
	}

	public static HttpServletResponse getCurrentResponse() {
		return currentResponse.get();
	}

	public static void setCurrentResponse(HttpServletResponse currentResponse) {
		ContextThread.currentResponse.set(currentResponse);
	}

	public static String getThreadSessionKey() {
		return threadSessionKey.get();
	}

	public static void setThreadSessionKey(String sessionKey) {
		threadSessionKey.set(sessionKey);
	}
}


4、cxf配置了攔截器的好處總結


  1. 權限驗證,有些請求可能涉及到權限這一塊
  2. 公共參數傳遞,避免在每一個方法中都要在參數總加入一些公共參數,公共參數能夠在攔截器中經過頭部信息來傳遞
  3. 日誌打印,打印相關請求信息(測試階段)
相關文章
相關標籤/搜索