/* * Copyright 2002-2007 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.web.filter; import java.io.IOException; import javax.servlet.FilterChain; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; import org.springframework.util.StringUtils; /** * Base class for <code>Filter</code>s that perform logging operations before and after a * request is processed. * * <p>Subclasses should override the <code>beforeRequest(HttpServletRequest, String)</code> * and <code>afterRequest(HttpServletRequest, String)</code> methods to perform the actual * logging around the request. * * <p>Subclasses are passed the message to write to the log in the <code>beforeRequest</code> * and <code>afterRequest</code> methods. By default, only the URI of the request is logged. * However, setting the <code>includeQueryString</code> property to <code>true</code> will * cause the query string of the request to be included also. * * <p>Prefixes and suffixes for the before and after messages can be configured * using the <code>beforeMessagePrefix</code>, <code>afterMessagePrefix</code>, * <code>beforeMessageSuffix</code> and <code>afterMessageSuffix</code> properties, * * @author Rob Harrop * @author Juergen Hoeller * @since 1.2.5 * @see #beforeRequest * @see #afterRequest */ public abstract class AbstractRequestLoggingFilter extends OncePerRequestFilter { public static final String DEFAULT_BEFORE_MESSAGE_PREFIX = "Before request ["; public static final String DEFAULT_BEFORE_MESSAGE_SUFFIX = "]"; public static final String DEFAULT_AFTER_MESSAGE_PREFIX = "After request ["; public static final String DEFAULT_AFTER_MESSAGE_SUFFIX = "]"; private boolean includeQueryString = false; private boolean includeClientInfo = false; private String beforeMessagePrefix = DEFAULT_BEFORE_MESSAGE_PREFIX; private String beforeMessageSuffix = DEFAULT_BEFORE_MESSAGE_SUFFIX; private String afterMessagePrefix = DEFAULT_AFTER_MESSAGE_PREFIX; private String afterMessageSuffix = DEFAULT_AFTER_MESSAGE_SUFFIX; /** * Set whether or not the query string should be included in the log message. * <p>Should be configured using an <code><init-param></code> for parameter * name "includeQueryString" in the filter definition in <code>web.xml</code>. */ public void setIncludeQueryString(boolean includeQueryString) { this.includeQueryString = includeQueryString; } /** * Return whether or not the query string should be included in the log message. */ protected boolean isIncludeQueryString() { return this.includeQueryString; } /** * Set whether or not the client address and session id should be included * in the log message. * <p>Should be configured using an <code><init-param></code> for parameter * name "includeClientInfo" in the filter definition in <code>web.xml</code>. */ public void setIncludeClientInfo(boolean includeClientInfo) { this.includeClientInfo = includeClientInfo; } /** * Return whether or not the client address and session id should be included * in the log message. */ protected boolean isIncludeClientInfo() { return this.includeClientInfo; } /** * Set the value that should be prepended to the log message written * <i>before</i> a request is processed. */ public void setBeforeMessagePrefix(String beforeMessagePrefix) { this.beforeMessagePrefix = beforeMessagePrefix; } /** * Set the value that should be apppended to the log message written * <i>before</i> a request is processed. */ public void setBeforeMessageSuffix(String beforeMessageSuffix) { this.beforeMessageSuffix = beforeMessageSuffix; } /** * Set the value that should be prepended to the log message written * <i>after</i> a request is processed. */ public void setAfterMessagePrefix(String afterMessagePrefix) { this.afterMessagePrefix = afterMessagePrefix; } /** * Set the value that should be appended to the log message written * <i>after</i> a request is processed. */ public void setAfterMessageSuffix(String afterMessageSuffix) { this.afterMessageSuffix = afterMessageSuffix; } /** * Forwards the request to the next filter in the chain and delegates * down to the subclasses to perform the actual request logging both * before and after the request is processed. * @see #beforeRequest * @see #afterRequest */ protected void doFilterInternal( HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException { beforeRequest(request, getBeforeMessage(request)); try { filterChain.doFilter(request, response); } finally { afterRequest(request, getAfterMessage(request)); } } /** * Get the message to write to the log before the request. * @see #createMessage */ private String getBeforeMessage(HttpServletRequest request) { return createMessage(request, this.beforeMessagePrefix, this.beforeMessageSuffix); } /** * Get the message to write to the log after the request. * @see #createMessage */ private String getAfterMessage(HttpServletRequest request) { return createMessage(request, this.afterMessagePrefix, this.afterMessageSuffix); } /** * Create a log message for the given request, prefix and suffix. * <p>If <code>includeQueryString</code> is <code>true</code> then * the inner part of the log message will take the form * <code>request_uri?query_string</code> otherwise the message will * simply be of the form <code>request_uri</code>. * <p>The final message is composed of the inner part as described * and the supplied prefix and suffix. */ protected String createMessage(HttpServletRequest request, String prefix, String suffix) { StringBuffer buffer = new StringBuffer(); buffer.append(prefix); buffer.append("uri=").append(request.getRequestURI()); if (isIncludeQueryString()) { buffer.append('?').append(request.getQueryString()); } if (isIncludeClientInfo()) { String client = request.getRemoteAddr(); if (StringUtils.hasLength(client)) { buffer.append(";client=").append(client); } HttpSession session = request.getSession(false); if (session != null) { buffer.append(";session=").append(session.getId()); } String user = request.getRemoteUser(); if (user != null) { buffer.append(";user=").append(user); } } buffer.append(suffix); return buffer.toString(); } /** * Concrete subclasses should implement this method to write a log message * <i>before</i> the request is processed. * @param request current HTTP request * @param message the message to log */ protected abstract void beforeRequest(HttpServletRequest request, String message); /** * Concrete subclasses should implement this method to write a log message * <i>after</i> the request is processed. * @param request current HTTP request * @param message the message to log */ protected abstract void afterRequest(HttpServletRequest request, String message); }