javascript
Spring-web源码解析之Filter-AbstractRequestLoggingFilter
基于4.1.7.RELEASE
Filter處理request log的基類,提供了在filterChain.doFilter調(diào)用前后的回調(diào)函數(shù),其實現(xiàn)類有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));}} }在調(diào)用filterChain.doFilter方法前后分別調(diào)用beforeRequest和afterRequest,而這兩個方法具體實現(xiàn)由子類決定,根據(jù)功能不同來決定記錄日志的方法,
在beforeRequest中和afterRequest中分別調(diào)用了? 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); }最終都會進(jìn)入到createMessage中去,只是前綴后綴不同,
before的Msg格式是: Before request [? Msg? ]
after的Msg格式是 : After request [? Msg? ]
這里的Msg具體內(nèi)容則由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(); }根據(jù)具體的參數(shù)設(shè)置的不同,其表現(xiàn)出不同的形式,msg的最基本格式為
Before/After request [? uri=xxx? ]
設(shè)置includeQueryString=true:
Before/After request [? uri=xxx?a=xx&b=xxx? ]
設(shè)置includeClientInfo=true:
Before/After request [? uri=xxx?a=xxx&b=xxx;client=xxx;session=sessionId;user=xxx? ]
設(shè)置includePayload=true:
先判斷request的content的長度,如果超過設(shè)置maxPayload的長度,則按照maxPayload進(jìn)行截取,如果出現(xiàn)異常,則payload=[unknown]
Before/After request [? uri=xxx?a=xxx&b=xxx;client=xxx;session=sessionId;user=xxx;payload=xxx/[unknown]? ]
下面來看其子類對應(yīng)的不同的實現(xiàn)
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); }其主要是調(diào)用初始化時候設(shè)置的GenericFilterBean中的logger進(jìn)行記錄。
Log4jNestedDiagnosticContextFilter:
其采用了Log4j來進(jìn)行日志記錄。自定義變量
protected final Logger log4jLogger = Logger.getLogger(getClass());
ServletContextRequestLoggingFilter:
使用ServletContext來記錄日志
總結(jié)
以上是生活随笔為你收集整理的Spring-web源码解析之Filter-AbstractRequestLoggingFilter的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: bzoj 2631: tree
- 下一篇: memcache 缓存的批量删除方案(转