携手创造,共同成长!这是我参与「日新计划 8 月更文挑战」的第28天,点击检查活动概况
1.写在前面
在java的开发过程中,涉及到java web的开发,基本上都是走spring这一套了。
咱们之前一般来说,都会说mvc:Model(模型事务)、View(视图界面)、Controller(操控器)。这个学习java开发的,应该都懂吧,这儿就不多说了。
这儿,咱们先侧重解析下Controller:
Controller操控器是指操控器接受用户的输入并调用模型和视图去完成用户的需求,操控器本身不输出任何东西和做任何处理。它仅仅接纳恳求并决定调用哪个模型构件去处理恳求,然后再确认用哪个视图来显示回来的数据。
那作为操控层的结构,一般有springmvc、struts2,struts2一些老的结构或许会用到,新的一些结构,基本就很少见了,都走springmvc这套了。
springmvc,咱们就用得多了,但是关于SpringMvc日志打印被疏忽输出的问题,有无人研讨过呢?
嘿嘿,巧了,这个问题,哥们研讨过了,那咱们今日就来剖析下这个问题喽!!!
2.问题引出
DEBUG org.springframework.web.servlet.mvc.method.annotation.RequestResponseBodyMethodProcessor Read “application/json;charset=UTF-8” to [QueryData(pageNo=1, pageSize=10, sortField=, sortOrder=asc, params={Q_XM_S_EQ=llsydn, Q_SJH_S_EQ=135 (truncated)…]
能够看到操控台打印的日志,呈现了 (truncated)...
这儿对应的前端页面的功用是这样的:
很明显,springmvc接纳到前端传进来的参数,然后会在操控台打印相关的日志。但是这儿的参数,日志打印是不完整的。呈现了 (truncated)...
截取的问题。
看到这,有好奇心的小伙伴,估计都想探个究竟了吧?(别说你不想)
好嘛好嘛,是我自己想探个究竟啦!!!(低微)
那这儿咱们先从源码中,找到被截取的地方喽。
3.截取源码剖析
首要这儿,要怎么进行源码检查呢?这儿咱们能够从打印的日志下手……
- RequestResponseBodyMethodProcessor
进入到RequestResponseBodyMethodProcessor类中,检查log打印日志的地方,并没有发现打印日志的代码。
那咱们就将该类一切的办法都打上断点(主要是该类不算很大),再发一个恳求,断点调试一下:
- 进入到readWithMessageConverters,办法里面来了
经过一步步履行,履行到
Object arg = readWithMessageConverters(inputMessage, parameter, paramType);
能够看到操控台,就打印了咱们方才的日志
那这儿,咱们就能够继续往
readWithMessageConverters
,里面进行检查(再发一个恳求)
经过一步步履行,履行到
LogFormatUtils.traceDebug
能够看到操控台,就打印了咱们方才的日志
那这儿,将其他的断点去掉,再这儿点一个,然后再发一个恳求进来。
嘿嘿,看到这,估计大家都知道了吧。
当参数字符超越100,这儿就会截取。
看到这儿,咱们是经过源码,一步步的找到终究的原因,那这儿仅仅提供一个办法,思路。
大家伙能够自己着手去调试一波,究竟也不难,哈哈!
这儿贴一下,终究的事务逻辑代码,如下:
(limitLength && str.length() > 100 ? str.substring(0, 100) + " (truncated)..." : str);
能够看到,当limitLength为true时,str长度大于100,就会截取前100个字符,后边再拼接
(truncated)...
那咱们不禁会想,嘿,哥们想办法把limitLength
的值,改为false,不就永久都不会截取输出日志了吗?
嗯嗯,是这么一回事,那这个limitLength
的值,怎么改?怎么来的?
只能经过源码剖析一波了,好啦,这个使命就交给各位了,着手去干活吧!
4.截取问题处理
public boolean isTraceEnabled(Marker marker) {
final FilterReply decision = callTurboFilters(marker, Level.TRACE);
if (decision == FilterReply.NEUTRAL) {
return effectiveLevelInt <= Level.TRACE_INT;
} else if (decision == FilterReply.DENY) {
return false;
} else if (decision == FilterReply.ACCEPT) {
return true;
} else {
throw new IllegalStateException("Unknown FilterReply value: " + decision);
}
}
经过检查这儿的代码,便是这儿回来上面limitLength
的值。
能够看到这儿,咱们的改动decision
的值,让它变成FilterReply.ACCEPT
,这样这儿就能回来true
了。
callTurboFilters,怎么改呢?这儿我百度找到了一个方法:
Logback 使用TurboFilter实现日志级别等内容的动态修改操作。
- 定义TurboFilter
public class SpringMvcFilter extends TurboFilter {
@Override
public FilterReply decide(Marker marker, Logger logger, Level level, String format, Object[] params, Throwable throwable) {
if (logger.getName().equals("org.springframework.web.servlet.mvc.method.annotation.RequestResponseBodyMethodProcessor")) {
return FilterReply.ACCEPT; //回来accept
}
return FilterReply.NEUTRAL;
}
}
- logback的装备xml
<configuration>
<turboFilter class="com.llsydn.log.filter.SpringMvcFilter" />
......
</configuration>
看看终究作用:
DEBUG org.springframework.web.servlet.mvc.method.annotation.RequestResponseBodyMethodProcessor Read “application/json;charset=UTF-8” to [QueryData(pageNo=1, pageSize=10, sortField=, sortOrder=asc, params={Q_XM_S_EQ=llsydn, Q_SJH_S_EQ=135****4606]
能够看到,springmvc打印的日志,正常了,不再截取了。
好了,以上便是 SpringMvc日志打印被疏忽输出问题剖析(源码剖析) 的分享了。
个人实操或许也不行全面,布鼓雷门了。
如果觉得有收获的,帮助点赞、谈论、收藏
一下呗!!!