1. 程式人生 > 其它 >5.如何斷點springboot(springmvc)如何解析引數

5.如何斷點springboot(springmvc)如何解析引數

我這邊用一個get請求來示例。這東西知道在哪斷點檢視,以後遇到問題可以快速定位。

我這裡的介面是 http://localhost:8082/pathVariable2/2

程式碼是

  @GetMapping("/pathVariable2/{id}")
  public String pathVariable2(@PathVariable(value = "id")
      String id){
    return id;
  }

1.入口是httpservlet,然後到org.springframework.web.servlet.DispatcherServlet#doDispatch打斷點

2.這裡2個關鍵方法

第一是獲取介面卡

第二個真正用介面卡解析引數

2.1介面卡一共4個,一般的請求用第一個就好

2.2執行引數解析

1)org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter#handleInternal 一路走下去

2)org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter#invokeHandlerMethod一路走下去

520:這裡是拿到所有的引數解析器:最終是遍歷所有的引數解析器去解析引數的

0 = {RequestParamMethodArgumentResolver@6898}
1 = {RequestParamMapMethodArgumentResolver@6899}
2 = {PathVariableMethodArgumentResolver@6900}
3 = {PathVariableMapMethodArgumentResolver@6901}
4 = {MatrixVariableMethodArgumentResolver@6902}
5 = {MatrixVariableMapMethodArgumentResolver@6903}
6 = {ServletModelAttributeMethodProcessor@6904}
7 = {RequestResponseBodyMethodProcessor@6905}
8 = {RequestPartMethodArgumentResolver@6906}
9 = {RequestHeaderMethodArgumentResolver@6907}
10 = {RequestHeaderMapMethodArgumentResolver@6908}
11 = {ServletCookieValueMethodArgumentResolver@6909}
12 = {ExpressionValueMethodArgumentResolver@6910}
13 = {SessionAttributeMethodArgumentResolver@6911}
14 = {RequestAttributeMethodArgumentResolver@6912}
15 = {ServletRequestMethodArgumentResolver@6913}
16 = {ServletResponseMethodArgumentResolver@6914}
17 = {HttpEntityMethodProcessor@6915}
18 = {RedirectAttributesMethodArgumentResolver@6916}
19 = {ModelMethodProcessor@6917}
20 = {MapMethodProcessor@6918}
21 = {ErrorsMethodArgumentResolver@6919}
22 = {SessionStatusMethodArgumentResolver@6920}
23 = {UriComponentsBuilderMethodArgumentResolver@6921}
24 = {PrincipalMethodArgumentResolver@6922}
25 = {RequestParamMethodArgumentResolver@6923}
26 = {ServletModelAttributeMethodProcessor@6924}

所以可以分析的出,我這個介面用PathVariableMethodArgumentResolver來解析,這是後話,肯定是哪所有解析器一個個去解析的。

524:拿到所有的返回值處理器

0 = {ModelAndViewMethodReturnValueHandler@6340}
1 = {ModelMethodProcessor@6341}
2 = {ViewMethodReturnValueHandler@6342}
3 = {ResponseBodyEmitterReturnValueHandler@6343}
4 = {StreamingResponseBodyReturnValueHandler@6344}
5 = {HttpEntityMethodProcessor@6345}
6 = {HttpHeadersReturnValueHandler@6346}
7 = {CallableMethodReturnValueHandler@6347}
8 = {DeferredResultMethodReturnValueHandler@6348}
9 = {AsyncTaskMethodReturnValueHandler@6349}
10 = {ServletModelAttributeMethodProcessor@6350}
11 = {RequestResponseBodyMethodProcessor@6351}
12 = {ViewNameMethodReturnValueHandler@6352}
13 = {MapMethodProcessor@6353}
14 = {ServletModelAttributeMethodProcessor@6354}

3)繼續斷點,核心執行解析是553行

4)org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod#invokeAndHandle

52行真正執行目標方法,我們進去

5)繼續斷點org.springframework.web.method.support.InvocableHandlerMethod#invokeForRequest

56行獲取引數 61行反射執行方法。所以我們得進入56行

6)org.springframework.web.method.support.InvocableHandlerMethod#getMethodArgumentValues方法

protected Object[] getMethodArgumentValues(NativeWebRequest request, @Nullable ModelAndViewContainer mavContainer, Object... providedArgs) throws Exception {
//這裡拿的是這個方法(到這步已經確認呼叫哪個方法了)所有引數,遍歷去給它們設定值 MethodParameter[] parameters
= this.getMethodParameters(); if (ObjectUtils.isEmpty(parameters)) { return EMPTY_ARGS; } else { Object[] args = new Object[parameters.length]; for(int i = 0; i < parameters.length; ++i) { MethodParameter parameter = parameters[i]; parameter.initParameterNameDiscovery(this.parameterNameDiscoverer); args[i] = findProvidedArgument(parameter, providedArgs); if (args[i] == null) {
//判斷引數解析器是否支援這種引數解析
if (!this.resolvers.supportsParameter(parameter)) { throw new IllegalStateException(formatArgumentError(parameter, "No suitable resolver")); } try {
//真正去給引數設定值 args[i]
= this.resolvers.resolveArgument(parameter, mavContainer, request, this.dataBinderFactory); } catch (Exception var10) { if (logger.isDebugEnabled()) { String exMsg = var10.getMessage(); if (exMsg != null && !exMsg.contains(parameter.getExecutable().toGenericString())) { logger.debug(formatArgumentError(parameter, exMsg)); } } throw var10; } } } return args; } }

6-1)判斷引數解析器是否支援這種引數解析

遍歷27個引數解析器,看看哪個支援。