Spring-web源码解析之Filter-AbstractRequestLoggingFilter
基于4.1.7.RELEASE
Filter处理request log的基类,提供了在filterChain.doFilter调用前后的回调函数,其实现类有CommonsRequestLoggingFilter,Log4jNestedDiagnosticContextFilter,ServletContextRequestLoggingFilter。
其核心代码为doFilterInternal方法:
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)throws ServletException, IOException {boolean isFirstRequest = !isAsyncDispatch(request);HttpServletRequest requestToUse = request;if (isIncludePayload() && isFirstRequest && !(request instanceof ContentCachingRequestWrapper)) {requestToUse = new ContentCachingRequestWrapper(request);}boolean shouldLog = shouldLog(requestToUse);if (shouldLog && isFirstRequest) {beforeRequest(requestToUse, getBeforeMessage(requestToUse));}try {filterChain.doFilter(requestToUse, response);}finally {if (shouldLog && !isAsyncStarted(requestToUse)) {afterRequest(requestToUse, getAfterMessage(requestToUse));}}
}
在调用filterChain.doFilter方法前后分别调用beforeRequest和afterRequest,而这两个方法具体实现由子类决定,根据功能不同来决定记录日志的方法,
在beforeRequest中和afterRequest中分别调用了 getBeforeMessage,getAfterMessage,这两个方法代码如下
private String getBeforeMessage(HttpServletRequest request) {return createMessage(request, this.beforeMessagePrefix, this.beforeMessageSuffix);
}private String getAfterMessage(HttpServletRequest request) {return createMessage(request, this.afterMessagePrefix, this.afterMessageSuffix);
}
最终都会进入到createMessage中去,只是前缀后缀不同,
before的Msg格式是: Before request [ Msg ]
after的Msg格式是 : After request [ Msg ]
这里的Msg具体内容则由createMessage决定
protected String createMessage(HttpServletRequest request, String prefix, String suffix) {StringBuilder msg = new StringBuilder();msg.append(prefix);msg.append("uri=").append(request.getRequestURI());if (isIncludeQueryString()) {msg.append('?').append(request.getQueryString());}if (isIncludeClientInfo()) {String client = request.getRemoteAddr();if (StringUtils.hasLength(client)) {msg.append(";client=").append(client);}HttpSession session = request.getSession(false);if (session != null) {msg.append(";session=").append(session.getId());}String user = request.getRemoteUser();if (user != null) {msg.append(";user=").append(user);}}if (isIncludePayload() && request instanceof ContentCachingRequestWrapper) {ContentCachingRequestWrapper wrapper = (ContentCachingRequestWrapper) request;byte[] buf = wrapper.getContentAsByteArray();if (buf.length > 0) {int length = Math.min(buf.length, getMaxPayloadLength());String payload;try {payload = new String(buf, 0, length, wrapper.getCharacterEncoding());}catch (UnsupportedEncodingException e) {payload = "[unknown]";}msg.append(";payload=").append(payload);}}msg.append(suffix);return msg.toString();
}
根据具体的参数设置的不同,其表现出不同的形式,msg的最基本格式为
Before/After request [ uri=xxx ]
设置includeQueryString=true:
Before/After request [ uri=xxx?a=xx&b=xxx ]
设置includeClientInfo=true:
Before/After request [ uri=xxx?a=xxx&b=xxx;client=xxx;session=sessionId;user=xxx ]
设置includePayload=true:
先判断request的content的长度,如果超过设置maxPayload的长度,则按照maxPayload进行截取,如果出现异常,则payload=[unknown]
Before/After request [ uri=xxx?a=xxx&b=xxx;client=xxx;session=sessionId;user=xxx;payload=xxx/[unknown] ]
下面来看其子类对应的不同的实现
CommonsRequestLoggingFilter:
@Override
protected boolean shouldLog(HttpServletRequest request) {return logger.isDebugEnabled();
}@Override
protected void beforeRequest(HttpServletRequest request, String message) {logger.debug(message);
}@Override
protected void afterRequest(HttpServletRequest request, String message) {logger.debug(message);
}
其主要是调用初始化时候设置的GenericFilterBean中的logger进行记录。
Log4jNestedDiagnosticContextFilter:
其采用了Log4j来进行日志记录。自定义变量
protected final Logger log4jLogger = Logger.getLogger(getClass());
ServletContextRequestLoggingFilter:
使用ServletContext来记录日志
Spring-web源码解析之Filter-AbstractRequestLoggingFilter相关推荐
- spring boot 源码解析23-actuate使用及EndPoint解析
前言 spring boot 中有个很诱人的组件–actuator,可以对spring boot应用做监控,只需在pom文件中加入如下配置即可: <dependency><group ...
- 深入剖析Spring Web源码(十九) - 整理的文档和日志的索引(第一版)
整理的文档 把所有的<深入剖析Spring Web>系列日志整理成为文档,供大家下载阅读,希望对大家有所帮助.里面有些章节尚未完成,所以称为第一版.希望不久的将来,能把没有完成的章节在第二 ...
- spring事务源码解析
前言 在spring jdbcTemplate 事务,各种诡异,包你醍醐灌顶!最后遗留了一个问题:spring是怎么样保证事务一致性的? 当然,spring事务内容挺多的,如果都要讲的话要花很长时间, ...
- Spring AOP源码解析-拦截器链的执行过程
一.简介 在前面的两篇文章中,分别介绍了 Spring AOP 是如何为目标 bean 筛选合适的通知器,以及如何创建代理对象的过程.现在得到了 bean 的代理对象,且通知也以合适的方式插在了目标方 ...
- Spring Session源码解析
AbstractHttpSessionApplicationInitializer,很明显它是一个初始化的类,它是一个抽象类,可以理解为一个公用的基类,然后看一下onStartup这个方法,最主要的方 ...
- Spring MVC源码解析——HandlerMapping(处理器映射器)
Sping MVC 源码解析--HandlerMapping处理器映射器 1. 什么是HandlerMapping 2. HandlerMapping 2.1 HandlerMapping初始化 2. ...
- Spring IOC源码解析笔记
小伙伴们,你们好,我是老寇 Spring最重要的概念就算IOC和AOP,本篇主要记录Spring IOC容器的相关知识,本文适合有spring相关基础并且想了解spring ioc的相关原理的人看 本 ...
- Spring AOP源码解析(一)——核心概念
目录 Pointcut ClassFilter MethodMatcher Advisor IntroductionAdvisor PointcutAdvisor AbstractPointcutAd ...
- Spring @Import源码解析
在Spring boot中常用到@Import,允许通过它引入 @Configuration 注解的类 (java config), 引入ImportSelector接口(这个比较重要, 因为要通过它 ...
- Spring AOP源码解析——AOP动态代理原理和实现方式
2019独角兽企业重金招聘Python工程师标准>>> Spring介绍 Spring(http://spring.io/)是一个轻量级的Java 开发框架,同时也是轻量级的IoC和 ...
最新文章
- 475. Heaters
- mysql数据库主从配置
- 边工作边考研的计算机经验,边工作边考研的经验
- Servlet的认识
- spark性能优化 -- spark工作原理
- JVM运行时数据区分析
- PAT甲级 -- 1090 Highest Price in Supply Chain (25 分)
- 计算机操作系统 内存_计算机内存的类型| 操作系统
- 寻路的几种算法_Godot游戏开发实践之二:AI之寻路新方式
- NBIA Data Retriever(NBIA数据下载工具)使用
- Oracle根据月份获取其是哪个季度
- centos7 pe系统安装_U盘PE启动安装Win7系统教程(微PE版)
- php fpm过多,Linux下php-fpm进程过多导致内存耗尽问题解决
- 个人博客系统(附源码)
- 最通俗易懂的JavaScript入门教程
- treetable怎么带参数_jquery treeTable插件使用细则
- 使用 SetProcessWorkingSetSize 降低程序内存
- c#winform——Gobang五子棋简易版双人对战制作(基本结构+代码)
- linux表示一序列ip,linux 下查看硬件信息(mac,IP地址,硬盘型号,序列号等)
- 字节跳动智力题-推理题