精品欧美一区二区三区在线观看 _久久久久国色av免费观看性色_国产精品久久在线观看_亚洲第一综合网站_91精品又粗又猛又爽_小泽玛利亚一区二区免费_91亚洲精品国偷拍自产在线观看 _久久精品视频在线播放_美女精品久久久_欧美日韩国产成人在线

SpringMVC 異常處理體系深入分析

開發 架構
SpringMVC 中針對異常問題有一套完整的處理體系,這套體系非常好用,今天松哥就花點時間來和大家聊一聊 SpringMVC 中的異常處理體系,我們把 SpringMVC 中的異常體系從頭到尾梳理一下。

[[392859]]

SpringMVC 中針對異常問題有一套完整的處理體系,這套體系非常好用,今天松哥就花點時間來和大家聊一聊 SpringMVC 中的異常處理體系,我們把 SpringMVC 中的異常體系從頭到尾梳理一下。

1.異常解析器概覽

在 SpringMVC 的異常體系中,處于最頂層的大 Boss 是 HandlerExceptionResolver,這是一個接口,里邊只有一個方法:

  1. public interface HandlerExceptionResolver { 
  2.  @Nullable 
  3.  ModelAndView resolveException( 
  4.    HttpServletRequest request, HttpServletResponse response, @Nullable Object handler, Exception ex); 

resolveException 方法就用來解析請求處理過程中所產生的異常,并最終返回一個 ModelAndView。

我們來看下 HandlerExceptionResolver 的實現類:

直接實現 HandlerExceptionResolver 接口的類有三個:

  • HandlerExceptionResolverComposite:這個一看又是一個組合,在最近的源碼分析中我們已經多次見到 xxxComposite 了,這里就不再贅述。
  • DefaultErrorAttributes:這個用來保存異常屬性。
  • AbstractHandlerExceptionResolver:這個的子類比較多:
    • SimpleMappingExceptionResolver:通過提前配置好的異常類和 View 之間的對應關系來解析異常。
    • AbstractHandlerMethodExceptionResolver:處理使用 @ExceptionHandler 注解自定義的異常類型。
    • DefaultHandlerExceptionResolver:按照不同類型來處理異常。
    • ResponseStatusExceptionResolver:處理含有 @ResponseStatus 注解的異常。

在 SpringMVC 中,大致的異常解析器就是這些,接下來我們來逐個學習這些異常解析器。

2.AbstractHandlerExceptionResolver

AbstractHandlerExceptionResolver 是真正干活的異常解析器的父類,我們就先從他的 resolveException 方法開始看起。

  1. @Override 
  2. @Nullable 
  3. public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, @Nullable Object handler, Exception ex) { 
  4.  if (shouldApplyTo(request, handler)) { 
  5.   prepareResponse(ex, response); 
  6.   ModelAndView result = doResolveException(request, response, handler, ex); 
  7.   if (result != null) { 
  8.    logException(ex, request); 
  9.   } 
  10.   return result; 
  11.  } 
  12.  else { 
  13.   return null
  14.  } 
  1. 首先調用 shouldApplyTo 方法判斷當前解析器是否可以處理傳入的處理器所拋出的異常,如果不支持,則直接返回 null,這個異常將交給下一個 HandlerExceptionResolver 去處理。
  2. 調用 prepareResponse 方法處理 response。
  3. 調用 doResolveException 方法實際處理異常,這是一個模版方法,具體的實現在子類中。
  4. 調用 logException 方法記錄異常日志信息。

記錄異常日志沒啥好說的,doResolveException 則是一個空的模版方法,所以這里對我們來說主要就是兩個方法:shouldApplyTo 和 prepareResponse,我們分別來看。

shouldApplyTo

  1. protected boolean shouldApplyTo(HttpServletRequest request, @Nullable Object handler) { 
  2.  if (handler != null) { 
  3.   if (this.mappedHandlers != null && this.mappedHandlers.contains(handler)) { 
  4.    return true
  5.   } 
  6.   if (this.mappedHandlerClasses != null) { 
  7.    for (Class<?> handlerClass : this.mappedHandlerClasses) { 
  8.     if (handlerClass.isInstance(handler)) { 
  9.      return true
  10.     } 
  11.    } 
  12.   } 
  13.  } 
  14.  return !hasHandlerMappings(); 

這里涉及到了兩個對象:mappedHandlers 和 mappedHandlerClasses:

  • mappedHandlers:存儲的是處理器對象(Controller 或者 Controller 中的方法)
  • mappedHandlerClasses:存儲的是處理器的 Class。

我們在配置異常解析器的時候可以配置這兩個對象,進而實現該異常處理器只為某一個處理器服務,但是一般來說沒這種需求,所以大家僅做了解即可。

如果開發者一開始配置了 mappedHandlers 或者 mappedHandlerClasses,則用這兩個和處理器去比較,否則就直接返回 true,表示支持該異常處理。

prepareResponse

prepareResponse 方法比較簡單,主要是處理一下響應頭的緩存字段。

  1. protected void prepareResponse(Exception ex, HttpServletResponse response) { 
  2.  if (this.preventResponseCaching) { 
  3.   preventCaching(response); 
  4.  } 
  5. protected void preventCaching(HttpServletResponse response) { 
  6.  response.addHeader(HEADER_CACHE_CONTROL, "no-store"); 

這是 AbstractHandlerExceptionResolver 的大致內容,可以看到還是非常 easy 的,接下來我們來看它的實現類。

2.1 AbstractHandlerMethodExceptionResolver

AbstractHandlerMethodExceptionResolver 主要是重寫了 shouldApplyTo 方法和 doResolveException 方法,一個一個來看。

shouldApplyTo

  1. @Override 
  2. protected boolean shouldApplyTo(HttpServletRequest request, @Nullable Object handler) { 
  3.  if (handler == null) { 
  4.   return super.shouldApplyTo(request, null); 
  5.  } 
  6.  else if (handler instanceof HandlerMethod) { 
  7.   HandlerMethod handlerMethod = (HandlerMethod) handler; 
  8.   handler = handlerMethod.getBean(); 
  9.   return super.shouldApplyTo(request, handler); 
  10.  } 
  11.  else if (hasGlobalExceptionHandlers() && hasHandlerMappings()) { 
  12.   return super.shouldApplyTo(request, handler); 
  13.  } 
  14.  else { 
  15.   return false
  16.  } 

這塊感覺沒啥好說的,判斷邏輯基本上都還是調用父類的 shouldApplyTo 方法去處理。

doResolveException

  1. @Override 
  2. @Nullable 
  3. protected final ModelAndView doResolveException( 
  4.   HttpServletRequest request, HttpServletResponse response, @Nullable Object handler, Exception ex) { 
  5.  HandlerMethod handlerMethod = (handler instanceof HandlerMethod ? (HandlerMethod) handler : null); 
  6.  return doResolveHandlerMethodException(request, response, handlerMethod, ex); 
  7. @Nullable 
  8. protected abstract ModelAndView doResolveHandlerMethodException( 
  9.   HttpServletRequest request, HttpServletResponse response, @Nullable HandlerMethod handlerMethod, Exception ex); 

doResolveException 是具體的異常處理方法,但是它里邊卻沒有實質性操作,具體的事情交給 doResolveHandlerMethodException 方法去做了,而該方法是一個抽象方法,具體的實現在子類中。

2.1.1 ExceptionHandlerExceptionResolver

AbstractHandlerMethodExceptionResolver 只有一個子類就是 ExceptionHandlerExceptionResolver,來看下它的 doResolveHandlerMethodException 方法:

  1. @Override 
  2. @Nullable 
  3. protected ModelAndView doResolveHandlerMethodException(HttpServletRequest request, 
  4.   HttpServletResponse response, @Nullable HandlerMethod handlerMethod, Exception exception) { 
  5.  ServletInvocableHandlerMethod exceptionHandlerMethod = getExceptionHandlerMethod(handlerMethod, exception); 
  6.  if (exceptionHandlerMethod == null) { 
  7.   return null
  8.  } 
  9.  if (this.argumentResolvers != null) { 
  10.   exceptionHandlerMethod.setHandlerMethodArgumentResolvers(this.argumentResolvers); 
  11.  } 
  12.  if (this.returnValueHandlers != null) { 
  13.   exceptionHandlerMethod.setHandlerMethodReturnValueHandlers(this.returnValueHandlers); 
  14.  } 
  15.  ServletWebRequest webRequest = new ServletWebRequest(request, response); 
  16.  ModelAndViewContainer mavContainer = new ModelAndViewContainer(); 
  17.  ArrayList<Throwable> exceptions = new ArrayList<>(); 
  18.  try { 
  19.   if (logger.isDebugEnabled()) { 
  20.    logger.debug("Using @ExceptionHandler " + exceptionHandlerMethod); 
  21.   } 
  22.   // Expose causes as provided arguments as well 
  23.   Throwable exToExpose = exception; 
  24.   while (exToExpose != null) { 
  25.    exceptions.add(exToExpose); 
  26.    Throwable cause = exToExpose.getCause(); 
  27.    exToExpose = (cause != exToExpose ? cause : null); 
  28.   } 
  29.   Object[] arguments = new Object[exceptions.size() + 1]; 
  30.   exceptions.toArray(arguments);  // efficient arraycopy call in ArrayList 
  31.   arguments[arguments.length - 1] = handlerMethod; 
  32.   exceptionHandlerMethod.invokeAndHandle(webRequest, mavContainer, arguments); 
  33.  } 
  34.  catch (Throwable invocationEx) { 
  35.   // Any other than the original exception (or a cause) is unintended here, 
  36.   // probably an accident (e.g. failed assertion or the like). 
  37.   if (!exceptions.contains(invocationEx) && logger.isWarnEnabled()) { 
  38.    logger.warn("Failure in @ExceptionHandler " + exceptionHandlerMethod, invocationEx); 
  39.   } 
  40.   // Continue with default processing of the original exception... 
  41.   return null
  42.  } 
  43.  if (mavContainer.isRequestHandled()) { 
  44.   return new ModelAndView(); 
  45.  } 
  46.  else { 
  47.   ModelMap model = mavContainer.getModel(); 
  48.   HttpStatus status = mavContainer.getStatus(); 
  49.   ModelAndView mav = new ModelAndView(mavContainer.getViewName(), model, status); 
  50.   mav.setViewName(mavContainer.getViewName()); 
  51.   if (!mavContainer.isViewReference()) { 
  52.    mav.setView((View) mavContainer.getView()); 
  53.   } 
  54.   if (model instanceof RedirectAttributes) { 
  55.    Map<String, ?> flashAttributes = ((RedirectAttributes) model).getFlashAttributes(); 
  56.    RequestContextUtils.getOutputFlashMap(request).putAll(flashAttributes); 
  57.   } 
  58.   return mav; 
  59.  } 

這個方法雖然比較長,但是很好理解:

  1. 首先查找到帶有 @ExceptionHandler 注解的方法,封裝成一個 ServletInvocableHandlerMethod 對象(關于 ServletInvocableHandlerMethod 對象,松哥在之前的文章中已經介紹過了,具體參見:Spring Boot 定義接口的方法是否可以聲明為 private?)。
  2. 如果找到了對應的方法,則為 exceptionHandlerMethod 配置參數解析器、視圖解析器等,關于這些解析器,參考松哥之前的文章:SpringBoot 中如何自定義參數解析器?、深入分析 SpringMVC 參數解析器、Spring Boot 中如何統一 API 接口響應格式?。
  3. 接下來定義一個 exceptions 數組,如果發生的異常存在異常鏈,則將整個異常鏈存入 exceptions 數組中。
  4. exceptions 數組再加上 handlerMethod,共同組成方法參數,調用 exceptionHandlerMethod.invokeAndHandle 完成自定義異常方法的執行,執行結果被保存再 mavContainer 中。
  5. 如果請求到此結束,則直接構造一個 ModelAndView 返回。
  6. 否則從 mavContainer 中取出各項信息,構建新的 ModelAndView 返回。同時,如果存在重定向參數,也將之保存下來(關于重定向參數,參見:SpringMVC 中的參數還能這么傳遞?漲姿勢了!)。

這就是 ExceptionHandlerExceptionResolver 的大致工作流程,可以看到,還是非常 easy 的。

2.2 DefaultHandlerExceptionResolver

這個看名字就知道是一個默認的異常處理器,用來處理一些常見的異常類型,我們來看一下它的 doResolveException 方法:

  1. @Override 
  2. @Nullable 
  3. protected ModelAndView doResolveException( 
  4.   HttpServletRequest request, HttpServletResponse response, @Nullable Object handler, Exception ex) { 
  5.  try { 
  6.   if (ex instanceof HttpRequestMethodNotSupportedException) { 
  7.    return handleHttpRequestMethodNotSupported( 
  8.      (HttpRequestMethodNotSupportedException) ex, request, response, handler); 
  9.   } 
  10.   else if (ex instanceof HttpMediaTypeNotSupportedException) { 
  11.    return handleHttpMediaTypeNotSupported( 
  12.      (HttpMediaTypeNotSupportedException) ex, request, response, handler); 
  13.   } 
  14.   else if (ex instanceof HttpMediaTypeNotAcceptableException) { 
  15.    return handleHttpMediaTypeNotAcceptable( 
  16.      (HttpMediaTypeNotAcceptableException) ex, request, response, handler); 
  17.   } 
  18.   else if (ex instanceof MissingPathVariableException) { 
  19.    return handleMissingPathVariable( 
  20.      (MissingPathVariableException) ex, request, response, handler); 
  21.   } 
  22.   else if (ex instanceof MissingServletRequestParameterException) { 
  23.    return handleMissingServletRequestParameter( 
  24.      (MissingServletRequestParameterException) ex, request, response, handler); 
  25.   } 
  26.   else if (ex instanceof ServletRequestBindingException) { 
  27.    return handleServletRequestBindingException( 
  28.      (ServletRequestBindingException) ex, request, response, handler); 
  29.   } 
  30.   else if (ex instanceof ConversionNotSupportedException) { 
  31.    return handleConversionNotSupported( 
  32.      (ConversionNotSupportedException) ex, request, response, handler); 
  33.   } 
  34.   else if (ex instanceof TypeMismatchException) { 
  35.    return handleTypeMismatch( 
  36.      (TypeMismatchException) ex, request, response, handler); 
  37.   } 
  38.   else if (ex instanceof HttpMessageNotReadableException) { 
  39.    return handleHttpMessageNotReadable( 
  40.      (HttpMessageNotReadableException) ex, request, response, handler); 
  41.   } 
  42.   else if (ex instanceof HttpMessageNotWritableException) { 
  43.    return handleHttpMessageNotWritable( 
  44.      (HttpMessageNotWritableException) ex, request, response, handler); 
  45.   } 
  46.   else if (ex instanceof MethodArgumentNotValidException) { 
  47.    return handleMethodArgumentNotValidException( 
  48.      (MethodArgumentNotValidException) ex, request, response, handler); 
  49.   } 
  50.   else if (ex instanceof MissingServletRequestPartException) { 
  51.    return handleMissingServletRequestPartException( 
  52.      (MissingServletRequestPartException) ex, request, response, handler); 
  53.   } 
  54.   else if (ex instanceof BindException) { 
  55.    return handleBindException((BindException) ex, request, response, handler); 
  56.   } 
  57.   else if (ex instanceof NoHandlerFoundException) { 
  58.    return handleNoHandlerFoundException( 
  59.      (NoHandlerFoundException) ex, request, response, handler); 
  60.   } 
  61.   else if (ex instanceof AsyncRequestTimeoutException) { 
  62.    return handleAsyncRequestTimeoutException( 
  63.      (AsyncRequestTimeoutException) ex, request, response, handler); 
  64.   } 
  65.  } 
  66.  catch (Exception handlerEx) { 
  67.  } 
  68.  return null

可以看到,這里實際上就是根據不同的異常類型,然后調用不同的類去處理該異常。這里相關的處理都比較容易,以 HttpRequestMethodNotSupportedException 為例,異常處理就是對 response 對象做一些配置,如下:

  1. protected ModelAndView handleHttpRequestMethodNotSupported(HttpRequestMethodNotSupportedException ex, 
  2.   HttpServletRequest request, HttpServletResponse response, @Nullable Object handler) throws IOException { 
  3.  String[] supportedMethods = ex.getSupportedMethods(); 
  4.  if (supportedMethods != null) { 
  5.   response.setHeader("Allow", StringUtils.arrayToDelimitedString(supportedMethods, ", ")); 
  6.  } 
  7.  response.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED, ex.getMessage()); 
  8.  return new ModelAndView(); 

配置響應頭,然后 sendError,最后返回一個空的 ModelAndView 對象。

其實這里哥哥異常處理方法都大同小異,松哥就不再贅述啦。

2.3 ResponseStatusExceptionResolver

這個用來處理 ResponseStatusException 類型的異常,或者使用了 @ResponseStatus 注解標記的普通異常類。我們來看下它的 doResolveException 方法:

  1. @Override 
  2. @Nullable 
  3. protected ModelAndView doResolveException( 
  4.   HttpServletRequest request, HttpServletResponse response, @Nullable Object handler, Exception ex) { 
  5.  try { 
  6.   if (ex instanceof ResponseStatusException) { 
  7.    return resolveResponseStatusException((ResponseStatusException) ex, request, response, handler); 
  8.   } 
  9.   ResponseStatus status = AnnotatedElementUtils.findMergedAnnotation(ex.getClass(), ResponseStatus.class); 
  10.   if (status != null) { 
  11.    return resolveResponseStatus(status, request, response, handler, ex); 
  12.   } 
  13.   if (ex.getCause() instanceof Exception) { 
  14.    return doResolveException(request, response, handler, (Exception) ex.getCause()); 
  15.   } 
  16.  } 
  17.  catch (Exception resolveEx) { 
  18.  } 
  19.  return null

可以看到,首先判斷異常類型是不是 ResponseStatusException,如果是,則直接調用 resolveResponseStatusException 方法進行異常信息處理,如果不是,則去查找到異常類上的 @ResponseStatus 注解,并從中查找出相關的異常信息,然后調用 resolveResponseStatus 方法進行處理。

可以看到,ResponseStatusExceptionResolver 處理的異常類型有兩種:

  • 直接繼承自 ResponseStatusException 的異常類,這種異常類可以直接從里邊提取出來想要的信息。
  • 通過 @ResponseStatus 注解的普通異常類,這種情況下異常信息從 @ResponseStatus 注解中提取出來。

這個比較簡單,沒啥好說的。

2.4 SimpleMappingExceptionResolver

SimpleMappingExceptionResolver 則是根據不同的異常顯示不同的 error 頁面。可能有的小伙伴還沒用過 SimpleMappingExceptionResolver,所以松哥這里先簡單說一下用法。

SimpleMappingExceptionResolver 的配置非常簡單,直接提供一個 SimpleMappingExceptionResolver 的實例即可,如下:

  1. @Bean 
  2. SimpleMappingExceptionResolver simpleMappingExceptionResolver() { 
  3.     SimpleMappingExceptionResolver resolver = new SimpleMappingExceptionResolver(); 
  4.     Properties mappings = new Properties(); 
  5.     mappings.put("java.lang.ArithmeticException""11"); 
  6.     mappings.put("java.lang.NullPointerException""22"); 
  7.     resolver.setExceptionMappings(mappings); 
  8.     Properties statusCodes = new Properties(); 
  9.     statusCodes.put("11""500"); 
  10.     statusCodes.put("22""500"); 
  11.     resolver.setStatusCodes(statusCodes); 
  12.     return resolver; 

在 mappings 中配置異常和 view 之間的對應關系,要寫異常類的全路徑,后面的 11、22 則表示視圖名稱;statusCodes 中配置了視圖和響應狀態碼之間的映射關系。配置完成后,如果我們的項目在運行時拋出了 ArithmeticException 異常,則會展示出 11 視圖,如果我們的項目在運行時拋出了 NullPointerException 異常,則會展示出 22 視圖。

這是用法,了解了用法之后我們再來看源碼,就容易理解了,我們直接來看 doResolveException 方法:

  1. @Override 
  2. @Nullable 
  3. protected ModelAndView doResolveException( 
  4.   HttpServletRequest request, HttpServletResponse response, @Nullable Object handler, Exception ex) { 
  5.  String viewName = determineViewName(ex, request); 
  6.  if (viewName != null) { 
  7.   Integer statusCode = determineStatusCode(request, viewName); 
  8.   if (statusCode != null) { 
  9.    applyStatusCodeIfPossible(request, response, statusCode); 
  10.   } 
  11.   return getModelAndView(viewName, ex, request); 
  12.  } 
  13.  else { 
  14.   return null
  15.  } 
  1. 首先調用 determineViewName 方法確定視圖的名稱。
  2. 接下來調用 determineStatusCode 查看視圖是否有對應的 statusCode。
  3. 調用 applyStatusCodeIfPossible 方法將 statusCode 設置到 response 上,這個方法很簡單,不多說。
  4. 調用 getModelAndView 方法構造一個 ModelAndView 對象返回,在構造時,同時設置異常參數,異常的信息的 key 默認就是 exception。

在上面這個過程中,有兩個比較長的方法,松哥這里需要和大家額外多說兩句。

determineViewName

這個就是根據異常類型找到視圖名,我們來看下具體的查找方式:

  1. @Nullable 
  2. protected String determineViewName(Exception ex, HttpServletRequest request) { 
  3.  String viewName = null
  4.  if (this.excludedExceptions != null) { 
  5.   for (Class<?> excludedEx : this.excludedExceptions) { 
  6.    if (excludedEx.equals(ex.getClass())) { 
  7.     return null
  8.    } 
  9.   } 
  10.  } 
  11.  if (this.exceptionMappings != null) { 
  12.   viewName = findMatchingViewName(this.exceptionMappings, ex); 
  13.  } 
  14.  if (viewName == null && this.defaultErrorView != null) { 
  15.   viewName = this.defaultErrorView; 
  16.  } 
  17.  return viewName; 
  1. 如果當前異常包含在 excludedExceptions 中,則直接返回 null(意思是當前異常被忽略處理了,直接按照默認方式來)。
  2. 如果 exceptionMappings 不為 null,則直接調用 findMatchingViewName 方法查找異常對應的視圖名(exceptionMappings 變量就是前面我們配置的映射關系),具體的查找方式就是遍歷我們前面配置的映射表。
  3. 如果沒找到對應的 viewName,并且用戶配置了 defaultErrorView,則將 defaultErrorView 賦值給 viewName,并將 viewName 返回。

determineStatusCode

  1. @Nullable 
  2. protected Integer determineStatusCode(HttpServletRequest request, String viewName) { 
  3.  if (this.statusCodes.containsKey(viewName)) { 
  4.   return this.statusCodes.get(viewName); 
  5.  } 
  6.  return this.defaultStatusCode; 

這個就比較容易,直接去 statusCodes 中查看是否有視圖對應的狀態碼,如果有則直接返回,如果沒有,就返回一個默認的。

3.HandlerExceptionResolverComposite

最后,還有一個 HandlerExceptionResolverComposite 需要和大家介紹下,這是一個組合的異常處理器,用來代理哪些真正干活的異常處理器。

  1. @Override 
  2. @Nullable 
  3. public ModelAndView resolveException( 
  4.   HttpServletRequest request, HttpServletResponse response, @Nullable Object handler, Exception ex) { 
  5.  if (this.resolvers != null) { 
  6.   for (HandlerExceptionResolver handlerExceptionResolver : this.resolvers) { 
  7.    ModelAndView mav = handlerExceptionResolver.resolveException(request, response, handler, ex); 
  8.    if (mav != null) { 
  9.     return mav; 
  10.    } 
  11.   } 
  12.  } 
  13.  return null

它的 resolveException 方法就比較簡單了,這種寫法我們已經見到過很多次了,不再贅述。

4.小結

好啦,今天就和大家簡單聊一聊 SpringMVC 中的異常處理體系,整體來說并不難,小伙伴們可以仔細品一品。

本文轉載自微信公眾號「江南一點雨」,可以通過以下二維碼關注。轉載本文請聯系江南一點雨公眾號。

 

責任編輯:武曉燕 來源: 江南一點雨
相關推薦

2021-03-18 10:56:59

SpringMVC參數解析器

2021-03-26 11:00:50

SpringMVC組件接口

2010-10-14 12:44:02

無線LAN故障處理

2010-09-07 14:21:22

PPPoE協議

2022-04-12 08:30:45

TomcatWeb 應用Servlet

2011-03-23 11:01:55

LAMP 架構

2010-03-08 14:53:48

Linux分區

2023-02-01 08:13:30

Redis內存碎片

2011-09-01 13:51:52

JavaScript

2025-09-16 10:57:31

2009-12-14 14:50:46

Ruby傳參數

2009-12-16 16:39:01

Visual Stud

2022-08-30 07:00:18

執行引擎Hotspot虛擬機

2021-10-29 16:36:53

AMSAndroidActivityMan

2009-06-10 18:12:38

Equinox動態化OSGi動態化

2011-09-13 09:08:22

架構

2018-12-18 10:11:37

軟件復雜度軟件系統軟件開發

2013-11-14 17:02:41

Android多窗口

2018-10-25 15:24:10

ThreadLocal內存泄漏Java

2020-12-07 06:23:48

Java內存
點贊
收藏

51CTO技術棧公眾號

日本福利视频导航| 国产精品久久久久久久久男| 性感美女一区二区三区| sis001欧美| 一色桃子久久精品亚洲| 亚洲国产精品第一区二区| 日本韩国欧美国产| 婷婷视频在线播放| 亚洲色图21p| 激情综合色丁香一区二区| 久久99国产精品自在自在app| 特级西西人体wwwww| 伊人亚洲精品| 色婷婷综合激情| 人人妻人人做人人爽| 日本免费在线观看| 91啪九色porn原创视频在线观看| 国产日韩欧美黄色| 91精品国产综合久久久蜜臀九色| 日韩免费特黄一二三区| 亚洲精品720p| 性久久久久久久久久久久久久| 亚洲性受xxx喷奶水| 亚洲欧美日韩中文播放| 日韩av一区二区三区在线| 亚洲av无码国产综合专区| 免费视频最近日韩| 欧美亚洲成人免费| 五月天综合在线| 亚洲电影在线一区二区三区| 国产亚洲aⅴaaaaaa毛片| 亚洲欧美日韩偷拍| 日韩视频在线直播| 91精品国产高清一区二区三区| 妞干网在线免费视频| 国产蜜臀在线| 一区二区三区四区在线免费观看 | 亚洲91网站| 欧美精品高清视频| 国产一级做a爰片久久| 亚洲三级欧美| 欧美午夜精品伦理| 国产探花一区在线观看| 国产亚洲精品bv在线观看| 日韩网站免费观看| 久久精品中文字幕一区二区三区| 这里只有精品9| 久久久xxx| 青青草原一区二区| av资源免费观看| 亚洲麻豆视频| 91av在线精品| 国产成人免费看| 国产欧美亚洲一区| 欧美性视频精品| wwwxxx亚洲| 亚洲女同在线| 国产成人精品午夜| 欧美日韩在线视频播放| 人禽交欧美网站| 国产精品午夜视频| 一本色道久久综合无码人妻| 久久精品99久久久| 成人免费在线视频网址| 精品国产亚洲一区二区麻豆| 国产精品18久久久久久久久| 91网免费观看| 日韩一级在线播放| 26uuu另类欧美亚洲曰本| 欧美少妇一区| 色网站免费在线观看| 中文字幕字幕中文在线中不卡视频| 日本特级黄色大片| 秋霞在线午夜| 日韩欧美精品网站| 天天干天天爽天天射| av一级久久| 亚洲国产精品久久久久秋霞不卡| aa片在线观看视频在线播放| 精品日韩欧美一区| 久久中文字幕在线| 日韩av综合在线| 美女视频一区免费观看| 国产欧美一区二区三区在线看 | 69久久久久| 一区二区三区四区视频精品免费| 亚洲人精品午夜射精日韩 | 国产精品免费电影| 99久久精品日本一区二区免费| 国产成人aaa| 欧洲视频一区二区三区| 97caopor国产在线视频| 丰满岳妇乱一区二区三区| 中文字幕国产传媒| 亚洲一区 二区| 亚洲色图五月天| 国产这里有精品| 性色一区二区三区| 92国产精品视频| 日本韩国精品一区二区| 亚洲三级在线观看| 日本在线视频www| 欧美精品三级在线| 亚洲一二三在线| 久久久国产精品黄毛片| 日韩和的一区二区| 国产伦精品一区二区三区高清版| 最新电影电视剧在线观看免费观看| 亚洲一区二区精品久久av| 在线观看的毛片| 另类ts人妖一区二区三区| 日韩一区二区欧美| 中文字幕免费观看| www.欧美精品一二区| 中文字幕一区二区三区有限公司| 国产伦精品一区二区三区视频金莲| 欧美一区二区在线免费观看| 受虐m奴xxx在线观看| 欧美大片一区| 国产自摸综合网| 高清日韩av电影| 日韩欧美在线免费| 亚洲欧美日韩色| 综合激情在线| 成人xxxx视频| 97在线观看免费观看高清| 精品久久久久久国产| 在线播放国产视频| 国产一区二区区别| 97超级碰碰碰久久久| 丰满肉肉bbwwbbww| 一区二区在线观看视频| 日韩av卡一卡二| 欧美日韩中文字幕一区二区三区| 欧美黑人性猛交| 国产人妖一区二区| 亚洲欧美色综合| 波多野结衣在线免费观看| 99国产精品一区二区| 国产精品第3页| 狠狠v欧美ⅴ日韩v亚洲v大胸| 狠狠色噜噜狠狠狠狠97| 日韩www视频| 亚洲国产午夜| 九色综合婷婷综合| 小早川怜子影音先锋在线观看| 亚洲国产精品电影| 永久免费看片在线播放| 不卡视频在线看| 免费av观看网址| 香蕉久久夜色精品国产更新时间| 91高清视频免费观看| 无码精品人妻一区二区| 欧美色视频日本高清在线观看| 天堂久久久久久| 美女精品在线| 亚洲一区三区电影在线观看| 精品美女一区| 日韩视频第一页| www.日本在线观看| 亚洲成av人**亚洲成av**| 性猛交╳xxx乱大交| 日韩一区二区免费看| 免费不卡亚洲欧美| 欧美日韩在线精品一区二区三区激情综合| 中文字幕亚洲二区| av免费在线不卡| 亚洲成在线观看| 成人免费看aa片| 日本不卡的三区四区五区| 亚洲资源视频| 在这里有精品| 欧美中文在线观看| 91在线不卡| 日韩精品一区二区三区在线观看| 久久草视频在线| 国产日韩精品视频一区| 欧美xxxxxbbbbb| 国产日韩精品视频一区二区三区| 欧美午夜精品久久久久免费视| 国产黄色精品| 欧美激情图片区| 欧美孕妇性xxxⅹ精品hd| 欧美日韩一级片网站| 欧美日韩成人免费观看| 91蝌蚪国产九色| 欧美激情国内自拍| 亚洲在线成人| 2025韩国大尺度电影| 色婷婷综合久久久久久| 91精品久久久久久久| 136福利第一导航国产在线| 国产一区二区三区在线观看视频 | 精品久久五月天| 日本视频www色| 亚洲一区二区3| 国产又大又粗又爽的毛片| 国产一区二区三区黄视频| 日韩av高清在线看片| 日韩欧美高清| 久久久久久国产精品免费免费| 亚洲最大的免费视频网站| 青青草成人在线| 黄页网站在线| 精品久久久av| 国产露出视频在线观看| 精品电影一区二区| 91精品国产色综合久久不8| 激情亚洲一区二区三区四区| 九九精品视频免费| 国产欧美一区在线| 亚洲一区二区在线免费| 国产一区二区0| 日韩精品你懂的| 国产精品夜夜夜| 18禁裸男晨勃露j毛免费观看 | 国产激情片在线观看| 精品视频日韩| 麻豆av一区二区三区久久| 亚洲高清999| 91香蕉国产在线观看| 欧美日韩不卡| 琪琪第一精品导航| 都市激情国产精品| 欧美激情一级欧美精品| 中文字幕中文字幕在线十八区| 综合网中文字幕| 邻居大乳一区二区三区| 亚洲精品xxx| 黄色av中文字幕| 欧美成人一区二区三区片免费 | 中文字幕日韩免费| 精品福利在线观看| 日产精品久久久久久久| 亚洲一区二区三区四区不卡| 日韩黄色免费观看| 亚洲欧美日本韩国| 侵犯稚嫩小箩莉h文系列小说| 国产精品人妖ts系列视频| 亚洲av毛片基地| 国产精品天天看| sm捆绑调教视频| 亚洲欧美综合另类在线卡通| 亚洲人做受高潮| 亚洲欧美激情小说另类| 欧产日产国产v| 亚洲中国最大av网站| 久久久久久欧美精品se一二三四| 一区二区三区精品在线观看| 欧美精品一区二区蜜桃| 亚洲一区二区美女| 国产精品男女视频| 日本高清不卡在线观看| 中文字幕+乱码+中文| 欧美日韩在线不卡| 国产欧美一级片| 欧美成人在线直播| 亚洲色图另类小说| 一区国产精品视频| 草莓福利社区在线| 久久久视频免费观看| 在线黄色的网站| 国产精品普通话| 日本一区二区三区视频在线看 | 中文字幕1234区| 高清在线不卡av| 国产在线观看无码免费视频| 久久久99精品久久| 91久久久久久久久久久久久久 | 91免费看视频| 亚洲欧美va天堂人熟伦 | 一道本无吗dⅴd在线播放一区| av在线三区| 欧美成人黄色小视频| 阿v视频在线观看| 国产福利精品在线| 亚洲欧洲一二区| 国产精品自拍首页| 日本黄色精品| 草草视频在线免费观看| 久久精品亚洲| 香蕉视频色在线观看| 成人精品小蝌蚪| 色屁屁草草影院ccyy.com| 亚洲女厕所小便bbb| 成人午夜视频在线播放| 欧美猛男超大videosgay| 人人妻人人澡人人爽久久av | 欧美日韩aaaaaa| 熟妇人妻一区二区三区四区| 一区二区三区精品99久久 | 精品欧美aⅴ在线网站| 在线免费观看一区二区| 精品国产91乱码一区二区三区| 国产精品一区二区三区四区色| 久久99久国产精品黄毛片入口| 欧美大片免费| 丁香婷婷久久久综合精品国产| 精品日本12videosex| 国产精彩视频一区二区| 麻豆久久一区二区| 黄色录像a级片| 亚洲激情在线激情| 国产情侣免费视频| 亚洲精品电影网| 亚洲电影视频在线| 国产美女被下药99| 尤物tv在线精品| a级黄色小视频| 国产成人午夜电影网| 91视频免费看片| 欧美日韩中文字幕| 成人免费观看在线视频| www日韩中文字幕在线看| 美女100%一区| 国产一区在线免费观看| 亚洲国产一区二区三区在线播放| 欧洲熟妇精品视频| 99re亚洲国产精品| 日本三级免费看| 日韩欧美国产综合一区| 国内外激情在线| 91精品美女在线| 欧美国产美女| 香港日本韩国三级网站| 久久久精品影视| 国产无人区码熟妇毛片多| 欧美成人女星排名| 午夜影院免费在线| 99久久精品久久久久久ai换脸| 欧美电影一区| 亚洲欧美国产中文| 国产精品久久久久久久久晋中 | 亚洲精品久久视频| 91福利在线免费| 国产私拍一区| 最新亚洲激情| 国产毛片毛片毛片毛片毛片毛片| 亚洲资源中文字幕| 日韩在线观看视频网站| 国a精品视频大全| 免费萌白酱国产一区二区三区| 野外做受又硬又粗又大视频√| 国产91综合网| 国产成人精品亚洲男人的天堂| 亚洲第一色中文字幕| 51精品在线| 久久久久九九九| 久久久久欧美精品| 亚洲天堂最新地址| 欧美日韩国产高清一区二区三区| 日韩黄色影院| 不卡视频一区二区三区| 精品999日本| 国产亚洲无码精品| 在线亚洲免费视频| 日本精品在线| aa日韩免费精品视频一| 亚洲黄色精品| a级大片在线观看| 欧美日韩一级视频| 男女在线视频| 欧美国产一区二区在线| 免费一级片91| 久久久综合久久久| 日韩电视剧免费观看网站| 午夜影视一区二区三区| 亚洲一卡二卡| 国产成人精品免费在线| 亚洲高清毛片一区二区| 在线成人激情黄色| 日本99精品| 男女曰b免费视频| 亚洲你懂的在线视频| 天堂在线资源库| 国产精品欧美日韩一区二区| 欧美久久成人| 欧洲av一区二区三区| 6080国产精品一区二区| 爱看av在线入口| 亚洲成人18| 成人免费毛片高清视频| 国产主播第一页| 欧美国产第一页| 成人黄色小视频| 国产一级免费片| 欧美日韩国产大片| 啊啊啊久久久| 亚洲小说欧美另类激情| 久久久久久久电影| 精品乱子伦一区二区| 国产91精品不卡视频| 你懂的视频一区二区| 成人精品999| 日韩欧美aaaaaa| 欧美电影在线观看网站| 国产二区视频在线| 亚洲视频精选在线| 黄色的视频在线免费观看| 国产精成人品localhost|