Arthas是阿里巴巴开源的Java诊断利器,深受开发者喜好。html
以前分享了Arthas怎样排查 404/401 的问题: http://hengyunabc.github.io/arthas-spring-boot-404-401/java
咱们能够快速定位一个请求是被哪些Filter
拦截的,或者请求最终是由哪些Servlet
处理的。git
但有时,咱们想知道一个请求是被哪一个Spring MVC Controller处理的。若是翻代码的话,会比较难找,而且不必定准确。github
经过Arthas能够精肯定位是哪一个Controller
处理请求。web
仍是以这个demo为例: https://github.com/hengyunabc/spring-boot-inside/tree/master/demo-404-401spring
启动以后,访问: http://localhost:8080/user/1 ,会返回一个user对象。那么这个请求是被哪一个Controller
处理的呢?apache
咱们先试下跟踪Servlet
:bash
trace javax.servlet.Servlet *
从trace的结果能够看出来,请求最终是被DispatcherServlet#doDispatch()
处理了,可是没有办法知道是哪一个Controller
处理。app
`---[27.453122ms] org.springframework.web.servlet.DispatcherServlet:doDispatch() +---[0.005822ms] org.springframework.web.context.request.async.WebAsyncUtils:getAsyncManager() #929 +---[0.107365ms] org.springframework.web.servlet.DispatcherServlet:checkMultipart() #936 | `---[0.062451ms] org.springframework.web.servlet.DispatcherServlet:checkMultipart() | `---[0.016924ms] org.springframework.web.multipart.MultipartResolver:isMultipart() #1093 +---[2.103935ms] org.springframework.web.servlet.DispatcherServlet:getHandler() #940 | `---[2.036042ms] org.springframework.web.servlet.DispatcherServlet:getHandler()
trace结果里把调用的行号打印出来了,咱们能够直接在IDE里查看代码(也能够用jad命令反编译):async
// org.springframework.web.servlet.DispatcherServlet protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception { HttpServletRequest processedRequest = request; HandlerExecutionChain mappedHandler = null; boolean multipartRequestParsed = false; WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request); try { ModelAndView mv = null; Exception dispatchException = null; try { processedRequest = checkMultipart(request); multipartRequestParsed = (processedRequest != request); // Determine handler for the current request. mappedHandler = getHandler(processedRequest); if (mappedHandler == null || mappedHandler.getHandler() == null) { noHandlerFound(processedRequest, response); return; }
mappedHandler = getHandler(processedRequest);
获得了处理请求的handler下面用watch
命令来获取getHandler
函数的返回结果。
watch
以后,再次访问 http://localhost:8080/user/1
$ watch org.springframework.web.servlet.DispatcherServlet getHandler returnObj Press Q or Ctrl+C to abort. Affect(class-cnt:1 , method-cnt:1) cost in 332 ms. ts=2019-06-04 11:38:06; [cost=2.75218ms] result=@HandlerExecutionChain[ logger=@SLF4JLocationAwareLog[org.apache.commons.logging.impl.SLF4JLocationAwareLog@665c08a], handler=@HandlerMethod[public com.example.demo.arthas.user.User com.example.demo.arthas.user.UserController.findUserById(java.lang.Integer)], interceptors=null, interceptorList=@ArrayList[isEmpty=false;size=2], interceptorIndex=@Integer[-1], ]
能够看处处理请求的handler是 om.example.demo.arthas.user.UserController.findUserById
。
DispatcherServlet
分发,查找到对应的mappedHandler
来处理欢迎关注横云断岭的专栏,专一Java,Spring Boot,Arthas,Dubbo。