环境
Spring Boot:2.2.6
Spring Boot 启动不打印Mapped信息
- Spring Boot正常启动之后是控制台不输入Mapped信息,也就是使用@RequestMapping配置的信息
- 先搜索一下spring boot does not output mapped info
- stackoverflow
- Spring 更新日志 What's New in Version 5.1
Logging revision:
Spring's JCL bridge can be detected by standard Commons Logging.
Less noise on info, readable debug logs, details at trace level.
验证效果
- 修改application.properties
logging.level.web=TRACE
调查代码
-
寻找入手点,既然请求会被转发到用@GetMapping注解标注的方法上,程序启动时Spring MVC应该扫描了所有被标注的方法
-
在方法中打断点调查调用流程
@GetMapping(value = "/hello")
public String home(String name,String key){
System.out.println("test");
return null;
}
- 调用栈
- 一直向上找到只接收request和response作为入参的方法。对request的解析、找相应的handler的逻辑肯定在这个之后。于是找到了DispatcherServlet中的doDispatch方法
protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
//...
// Determine handler for the current request.
mappedHandler = getHandler(processedRequest);
// Actually invoke the handler.
mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
//...
}
- 根据mappedHandler = getHandler(processedRequest)查找handler是如何取得的,直到AbstractHandlerMethodMapping的getMappingsByUrl方法
@Nullable
public List<T> getMappingsByUrl(String urlPath) {
return this.urlLookup.get(urlPath);
}
- 查看this.urlLookup在何处被赋值,找到AbstractHandlerMethodMapping中的register方法
public void register(T mapping, Object handler, Method method) {
for (String url : directUrls) {
this.urlLookup.add(url, mapping);
}
}
- 在this.urlLookup.add(url, mapping)处打断点,重启项目。Spring完成handler注册后并没有打log,往register的调用方找,找到detectHandlerMethods方法
protected void detectHandlerMethods(Object handler) {
//...
if (logger.isTraceEnabled()) {
logger.trace(formatMappings(userType, methods));
}
methods.forEach((method, mapping) -> {
Method invocableMethod = AopUtils.selectInvocableMethod(method, userType);
registerHandlerMethod(handler, invocableMethod, mapping);
});
}
总结
- Spring MVC从5.1之后,Spring Boot从2.1之后修改了打印日志的逻辑,开发过程中可以使用logging.level.web=TRACE
- 本文展示了在完全不知道实现逻辑的情况如何去找切入点来调查代码
- Spring MVC在启动时先扫描所偶配置的@Mapping的类,将路径和生成的对应handler存储起来,当请求到达容器时,根据路径匹找到相应的handler来处理请求。
- Spring MVC在真正注册handler之前就打印了log,后期调查为什么要这样做