欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

淺談SpringMVC HandlerInterceptor詭異問題排查

 更新時間:2019年05月22日 14:39:19   作者:戒嗔  
這篇文章主要介紹了淺談SpringMVC HandlerInterceptor詭異問題排查,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧

發(fā)現(xiàn)問題

最近在進(jìn)行壓測發(fā)現(xiàn),有一些接口時好時壞,通過sentry日志平臺及sky walking平臺跟蹤發(fā)現(xiàn),用戶張三獲取到的用戶上下文確是李四。

代碼走讀

用戶登錄下上文

/**
 * 用戶登錄下上文
 *
 * @author : jamesfu
 * @date : 22/5/2019
 * @time : 9:18 AM
 */
@Data
public class UserContext {
  private final static ThreadLocal<UserContext> threadLocal = new ThreadLocal<>();

  private Long id;

  private String loginName;

  public static UserContext get() {
    UserContext context = threadLocal.get();
    if (context == null) {
      // TODO(james.h.fu):根據(jù)請求上下文獲取token, 然后恢復(fù)用戶登錄下上文
      context = new UserContext() {{
        setId(1L);
        setLoginName("james.h.fu1");
      }};
      threadLocal.set(context);
    }

    return context;
  }

  public static void clear() {
    threadLocal.remove();
  }

  public static void set(UserContext context) {
    if (context != null) {
      threadLocal.set(context);
    }
  }
}

在攔截器中有調(diào)用UserContext.set恢復(fù)用戶登錄上下文,并在請求結(jié)束時調(diào)用UserContext.clear清理用戶登錄上下文。

攔截器注冊配置

/**
 * 攔截器注冊配置
 *
 * @author : jamesfu
 * @date : 22/5/2019
 * @time : 9:15 AM
 */
@Configuration
public class FilterConfig implements WebMvcConfigurer {
  @Autowired
  private JsonRpcInterceptor jsonRpcInterceptor;

  @Override
  public void addInterceptors(InterceptorRegistry registry) {
    registry.addInterceptor(jsonRpcInterceptor)
        .addPathPatterns("/json.rpc");
  }
}

 

 

通過debug可以發(fā)現(xiàn)UserContext中的ThreadLocal的清理工作沒有得到執(zhí)行。導(dǎo)致請求進(jìn)來時,有可能ThreadLocal已存在了,就不會再根據(jù)請求上下文恢復(fù)了。

springmvc 源碼走讀

tomcat 在收到http請求后,最終會交由spring mvc的 DispatcherServlet 處理。 這里可以從doDispatch按圖索驥,順藤摸瓜地往下看起走。

源碼走讀:DispatcherServlet

/**
	 * Process the actual dispatching to the handler.
	 * <p>The handler will be obtained by applying the servlet's HandlerMappings in order.
	 * The HandlerAdapter will be obtained by querying the servlet's installed HandlerAdapters
	 * to find the first that supports the handler class.
	 * <p>All HTTP methods are handled by this method. It's up to HandlerAdapters or handlers
	 * themselves to decide which methods are acceptable.
	 * @param request current HTTP request
	 * @param response current HTTP response
	 * @throws Exception in case of any kind of processing failure
	 */
	protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception

請求會得到分發(fā),然后執(zhí)行各個已注冊Handler的preHandle-->postHandle-->afterCompletion。

源碼走讀:HandlerExecutionChain applyPreHandle

/**
	 * Apply preHandle methods of registered interceptors.
	 * @return {@code true} if the execution chain should proceed with the
	 * next interceptor or the handler itself. Else, DispatcherServlet assumes
	 * that this interceptor has already dealt with the response itself.
	 */
	boolean applyPreHandle(HttpServletRequest request, HttpServletResponse response) throws Exception {
		HandlerInterceptor[] interceptors = getInterceptors();
		if (!ObjectUtils.isEmpty(interceptors)) {
			for (int i = 0; i < interceptors.length; i++) {
				HandlerInterceptor interceptor = interceptors[i];
				if (!interceptor.preHandle(request, response, this.handler)) {
					triggerAfterCompletion(request, response, null);
					return false;
				}
				this.interceptorIndex = i;
			}
		}
		return true;
	}

當(dāng)執(zhí)行到preHandle返回false時,它就會從上一個返回true的handler依次往前執(zhí)行afterCompletion,它自己的afterCompletion得不到執(zhí)行。

triggerAfterCompletion

/**
	 * Trigger afterCompletion callbacks on the mapped HandlerInterceptors.
	 * Will just invoke afterCompletion for all interceptors whose preHandle invocation
	 * has successfully completed and returned true.
	 */
	void triggerAfterCompletion(HttpServletRequest request, HttpServletResponse response, @Nullable Exception ex)
			throws Exception {

		HandlerInterceptor[] interceptors = getInterceptors();
		if (!ObjectUtils.isEmpty(interceptors)) {
			for (int i = this.interceptorIndex; i >= 0; i--) {
				HandlerInterceptor interceptor = interceptors[i];
				try {
					interceptor.afterCompletion(request, response, this.handler, ex);
				}
				catch (Throwable ex2) {
					logger.error("HandlerInterceptor.afterCompletion threw exception", ex2);
				}
			}
		}
	}

triggerAfterCompletion只會在(1)出現(xiàn)異常,(2)preHandle返回false 或(3)正常執(zhí)行結(jié)束才會從索引interceptorIndex依次往前執(zhí)行。

所以基于以上源碼可以得知,在寫攔截器時preHandle返回false時,afterCompletion是不會執(zhí)行的。所以一些必要的清理工作得不到執(zhí)行,會出現(xiàn)類似我們遇到的帳號串的問題。

以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

  • Java深度復(fù)制功能與用法實例分析

    Java深度復(fù)制功能與用法實例分析

    這篇文章主要介紹了Java深度復(fù)制功能與用法,簡單講述了深度復(fù)制的概念、功能并結(jié)合實例形式分析了java實現(xiàn)深度復(fù)制的具體操作技巧,需要的朋友可以參考下
    2018-01-01
  • SpringCloud項目集成Feign、Hystrix過程解析

    SpringCloud項目集成Feign、Hystrix過程解析

    這篇文章主要介紹了SpringCloud項目集成Feign、Hystrix過程解析,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2019-11-11
  • 詳解Spring Boot 屬性配置和使用

    詳解Spring Boot 屬性配置和使用

    本篇文章主要介紹了詳解Spring Boot 屬性配置和使用,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-06-06
  • SpringMvc web.xml配置實現(xiàn)原理過程解析

    SpringMvc web.xml配置實現(xiàn)原理過程解析

    這篇文章主要介紹了SpringMvc web.xml配置實現(xiàn)原理過程解析,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2020-08-08
  • Deep Module深模塊之軟件設(shè)計

    Deep Module深模塊之軟件設(shè)計

    這篇文章主要介紹了軟件設(shè)計之Deep Module深模塊詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-07-07
  • Spring Boot 實現(xiàn)圖片上傳并回顯功能

    Spring Boot 實現(xiàn)圖片上傳并回顯功能

    本篇文章給大家分享Spring Boot 實現(xiàn)圖片上傳并回顯功能,文中通過實例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友參考下吧
    2021-07-07
  • java 多態(tài)性詳解及常見面試題

    java 多態(tài)性詳解及常見面試題

    這篇文章主要介紹了java 多態(tài)性詳解及常見面試題的相關(guān)資料,這里對java 的多態(tài)性做了資料整理,并列舉常見的關(guān)于多態(tài)性的面試題,需要的朋友可以參考下
    2016-11-11
  • Spring事務(wù)失效場景的詳細(xì)整理

    Spring事務(wù)失效場景的詳細(xì)整理

    Spring 事務(wù)的傳播特性說的是,當(dāng)多個事務(wù)同時存在的時候,Spring 如何處理這些事務(wù)的特性,下面這篇文章主要給大家介紹了關(guān)于Spring事務(wù)失效場景的相關(guān)資料,需要的朋友可以參考下
    2022-02-02
  • SpringBoot+Vue.js實現(xiàn)前后端分離的文件上傳功能

    SpringBoot+Vue.js實現(xiàn)前后端分離的文件上傳功能

    這篇文章主要介紹了SpringBoot+Vue.js實現(xiàn)前后端分離的文件上傳功能,需要的朋友可以參考下
    2018-06-06
  • Java并發(fā)編程之Condition源碼分析(推薦)

    Java并發(fā)編程之Condition源碼分析(推薦)

    這篇文章主要介紹了Java并發(fā)編程之Condition源碼分析,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-03-03

最新評論