Arthas实践:是哪一个Controller处理了请求?

背景

Arthas是阿里巴巴开源的Java诊断利器,深受开发者喜好。html

以前分享了Arthas怎样排查 404/401 的问题: hengyunabc.github.io/arthas-spri…java

咱们能够快速定位一个请求是被哪些Filter拦截的,或者请求最终是由哪些Servlet处理的。git

但有时,咱们想知道一个请求是被哪一个Spring MVC Controller处理的。若是翻代码的话,会比较难找,而且不必定准确。github

经过Arthas能够精肯定位是哪一个Controller处理请求。web

Demo

仍是以这个demo为例: github.com/hengyunabc/…spring

启动以后,访问: http://localhost:8080/user/1 ,会返回一个user对象。那么这个请求是被哪一个Controller处理的呢?apache

trace定位DispatcherServlet

咱们先试下跟踪Servlet设计模式

trace javax.servlet.Servlet *
复制代码

从trace的结果能够看出来,请求最终是被DispatcherServlet#doDispatch()处理了,可是没有办法知道是哪一个Controller处理。bash

`---[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()
复制代码

watch定位handler

trace结果里把调用的行号打印出来了,咱们能够直接在IDE里查看代码(也能够用jad命令反编译):架构

// 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

总结

  • Spring MVC的请求是在DispatcherServlet分发,查找到对应的mappedHandler来处理
  • 使用Arthas时,灵活结合代码,能够快速精肯定位问题

连接

原文地址

mp.weixin.qq.com/s/oWUzgF4lR… 抽奖两本新书《微服务架构设计模式》

公众号

欢迎关注横云断岭的专栏,专一Java,Spring Boot,Arthas,Dubbo。

横云断岭的专栏
相关文章
相关标签/搜索