使用 Java 日志过滤器解析 HTTP 请求
javax.servlet.Filter它实现了一个便捷的工具,可以解析 HTTP 请求的内容并输出日志。筛选让我来介绍一下这门课。
此日志过滤器使用“java.util.logging.Logger”进行日志输出,您可以通过更改日志级别来更改输出的信息。
什么是 javax.servlet.Filter?
在构建 Web 应用程序时,除了主要业务流程之外,还需要执行在这些流程之前和之后常见的辅助流程。
例如,客户端身份验证、权限检查、日志记录等。
在每个资源中编写此类辅助进程是软件可维护性的一个主要障碍,会导致应用程序难以维护。
通过实现 javax.servlet.Filter,可以在将请求传递给 servlet 类之前执行此辅助处理。
此外,由于过滤器设置可以在 web.xml 中配置,因此您可以灵活地添加或删除过滤器,而无需更改源代码。
我们来试试使用日志过滤器。
让我们使用日志过滤器来分析 HTTP 请求,方法是对其进行过滤。
这次汤姆猫我们将使用默认包含的示例应用程序。
完成以下设置后,即可立即运行此过滤器。
日志过滤器日志过滤器日志级别美好的日志过滤器/*
*使用 Struts 框架时的 URL 模式如下:
*。做
请在运行“会话示例”屏幕时检查日志输出结果。

日志信息输出和日志级别
●日志输出内容
| 日志信息 | 日志级别 |
|---|---|
| Cookie 信息 | 美好的 |
| HTTP 标头信息 | 美好的 |
| HTTP 和其他信息 | 美好的 |
| HTTP 请求参数 | 配置 |
| 请求作用域对象 | 配置 |
| 会话作用域对象 | 配置 |
| 请求前后的内存使用情况 | 配置 |
| 屏幕过渡信息 | 信息 |
您应该使用以下日志级别来区分它们。
- 精细设置……输出最详细的日志。当您想要详细分析 HTTP 请求时,请启用此选项。
- CONFIG... 输出更详细的日志。在开发过程中,最好保持此级别。
- 信息……仅输出屏幕过渡信息。
● 如何更改日志级别
您可以通过设置初始化参数 logging.Level 来更改日志输出级别。
例子:
日志级别信息
源代码
导入 javax.servlet.Filter;
导入 javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
导入 javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
/**
* 实现 javax.servlet.Filter 来解析 HTTP 请求的内容并输出日志。
* 过滤器类。
*/
public class LogFilter implements Filter {
私有静态日志记录器 logger =
Logger.getLogger(LogFilter.class.getName());
private static final String LINE_SEPA =
System.getProperty(“line.separator”);
private static final String NEXT_PAGE = “LogFilter.NEXT_PAGE”;
/**
* 初始化此日志过滤器。
* @param 映射
*/
public void init(FilterConfig mapping) {
String str = mapping.getInitParameter(“logging.Level”);
System.out.println("将日志级别设置为 " + str + "。");
级别 level = null;
尝试 {
level = Level.parse(str);
} catch (Exception e) {
e.printStackTrace();
level = Level.INFO;
}
LogManager.getLogManager().reset();
Handler handler = new CustomConsoleHandler();
handler.setFormatter(new CustomFormatter());
handler.setLevel(level);
日志记录器.setLevel(level);
logger.getParent().addHandler(处理程序);
}
/**
这是一个输出日志的过滤器。
* @param request 正在处理的 HTTP 请求
* @param response 正在生成的 HTTP 响应
* @param 链
*/
public void doFilter(ServletRequest _request, ServletResponse _response,
FilterChain 链) 抛出 IOException、ServletException {
// —————————————————————『预处理』
HttpServletRequest request = (HttpServletRequest) _request;
HttpServletResponse response = (HttpServletResponse) _response;
如果 (logger.isLoggable(Level.CONFIG)) {
logger.Config(
“============ 请求开始!!”
+”线程 ID:”
+ Thread.currentThread().hashCode()
+ ” =============================================================” 版权所有;
}
// 内存使用情况
String actionMemory = null;
如果 (logger.isLoggable(Level.CONFIG)) {
actionMemory = getMemoryInfo(” ”
+ new Time(System.currentTimeMillis()) + " 请求 [上一次]");
}
如果 (logger.isLoggable(Level.FINE)) {
logger.fine("Cookie 信息" + getCookieInfo(request));
}
如果 (logger.isLoggable(Level.FINE)) {
logger.fine("HTTP 标头信息" + getHeadersInfo(request));
}
如果 (logger.isLoggable(Level.FINE)) {
日志记录器
.fine("HTTP 其他信息" + getRequestOtherInfo(request));
}
如果 (logger.isLoggable(Level.CONFIG)) {
String reqlog = getRequestParametersInfo(request);
logger.config("HTTP 请求参数" + reqlog);
}
如果 (logger.isLoggable(Level.CONFIG)) {
logger.config("请求作用域对象")“
+ getRequestAttributeInfo(request));
}
如果 (logger.isLoggable(Level.CONFIG)) {
String sessionlog = getSessionInfo(request,true);
logger.config("会话作用域对象(请求处理之前)")“
+ 会话日志);;
}
// 调用以下过滤器
chain.doFilter(请求, 响应);
// ———————————————————-『后期处理』
如果 (logger.isLoggable(Level.CONFIG)) {
String sessionlog = getSessionInfo(request,false);
logger.config("会话作用域对象(请求处理后)")“
+ 会话日志);;
}
// 内存使用情况
如果 (logger.isLoggable(Level.CONFIG)) {
actionMemory = "请求前后的内存使用情况" + LINE_SEPA
+ actionMemory + LINE_SEPA
+ getMemoryInfo(” ” + new Time(System.currentTimeMillis())
+”请求[之后]”);
logger.config(actionMemory+LINE_SEPA);
}
// 屏幕过渡信息
如果 (logger.isLoggable(Level.INFO)) {
String nextPage = (String) request.getAttribute(NEXT_PAGE);
if (nextPage == null || nextPage.length() == 0) {
nextPage = request.getRequestURI();
}
logger.info(“NEXT_PAGE=[” + nextPage + “], ”
+ “IP_ADDRESS=[” + request.getRemoteAddr() + “], ”
+ “SESSION_ID=[” + request.getSession().getId() + “], ”
+ “USER-AGENT=[” + request.getHeader(“user-agent”) + “]”);
}
如果 (logger.isLoggable(Level.CONFIG)) {
logger.Config(
“============ 请求结束!!”
+”线程 ID:”+ Thread.currentThread().hashCode()
+ ” =============================================================”
+LINE_SEPA+LINE_SEPA);
}
}
/**
*
*/
public void destroy() {
}
// ------- 以下为私有方法 -------
private static String getMemoryInfo(String message) {
DecimalFormat dFromat = new DecimalFormat(“#,###KB”);
long free = Runtime.getRuntime().freeMemory() / 1024;
长总计 = Runtime.getRuntime().totalMemory() / 1024;
长最大值 = Runtime.getRuntime().maxMemory() / 1024;
长期使用 = 总计 – 免费;;
String msg = message + ": " + "Total=" + dFromat.format(total) + ", "”
+ “使用量=" + dFromat.format(used) + ” (” + (used * 100 / total)
+ “%”,最大可用值为” + dFromat.format(max);
返回消息;;
}
/**
* 记录所有请求头。
*/
private static String getHeadersInfo(HttpServletRequest request) {
StringBuffer buff = new StringBuffer(LINE_SEPA);
枚举 headerNames = request.getHeaderNames();
while (headerNames.hasMoreElements()) {
String headerName = (String) headerNames.nextElement();
buff.append("");
buff.append(headerName);
buff.append("=");
buff.append(request.getHeader(headerName));
buff.append(LINE_SEPA);
}
return buff.toString();
}
private static String getCookieInfo(HttpServletRequest request) {
StringBuffer buff = new StringBuffer();
Cookie[] cookies = request.getCookies();
如果 (cookies == null) {
返回 “”;
}
for (int i = 0; i < cookies.length; i++) {
buff.append(“\n — Cookie[” + i + “] —\n”);
buff.append("");
buff.append(cookies[i].getName());
buff.append("=");
buff.append(cookies[i].getValue());
buff.append(LINE_SEPA);
buff.append("");
buff.append(“getVersion()”);
buff.append("=");
buff.append(cookies[i].getVersion());
buff.append(LINE_SEPA);
buff.append("");
buff.append(“getComment()”);
buff.append("=");
buff.append(cookies[i].getComment());
buff.append(LINE_SEPA);
buff.append("");
buff.append(“getDomain()”);
buff.append("=");
buff.append(cookies[i].getDomain());
buff.append(LINE_SEPA);
buff.append("");
buff.append(“getMaxAge()”);
buff.append("=");
buff.append(cookies[i].getMaxAge());
buff.append(LINE_SEPA);
buff.append("");
buff.append("getPath()");
buff.append("=");
buff.append(cookies[i].getPath());
buff.append(LINE_SEPA);
buff.append("");
buff.append(“getSecure()”);
buff.append("=");
buff.append(cookies[i].getSecure());
buff.append(LINE_SEPA);
}
return buff.toString();
}
private static String getRequestParametersInfo(HttpServletRequest request) {
StringBuffer buff = new StringBuffer(LINE_SEPA);
Map map = convertRequest(request);
TreeMap trr = new TreeMap(map);
Iterator itr = trr.keySet().iterator();
while (itr.hasNext()) {
String key = (String) itr.next();
buff.append("");
buff.append(key);
buff.append("=");
对象值 = map.get(key);
String[] values = (String[]) value;
if (values.length == 1) {
buff.append(values[0]);
别的 {
// 字符串数组将被转换。
String strValue = stratum(values);
buff.append(strValue);
}
buff.append(LINE_SEPA);
}
return buff.toString();
}
private static String getRequestAttributeInfo(HttpServletRequest request) {
StringBuffer buff = new StringBuffer(LINE_SEPA);
枚举 e = request.getAttributeNames();
while (e.hasMoreElements()) {
String name = (String) e.nextElement();
buff.append(” name=” + name + “, attributeClass= ”
+ request.getAttribute(name).getClass().getName()
+ “, toString() = ” + request.getAttribute(name)
+ LINE_SEPA);
}
return buff.toString();
}
private static String getRequestOtherInfo(HttpServletRequest request) {
StringBuffer buff = new StringBuffer();
buff.append(LINE_SEPA);
buff.append("getCharacterEncoding()=");
buff.append(request.getCharacterEncoding());
buff.append(LINE_SEPA);
buff.append("getContentLength()=");
buff.append(request.getContentLength());
buff.append(LINE_SEPA);
buff.append("getContentType()=");
buff.append(request.getContentType());
buff.append(LINE_SEPA);
buff.append("getLocale()=");
buff.append(request.getLocale());
buff.append(LINE_SEPA);
buff.append("getProtocol()=");
buff.append(request.getProtocol());
buff.append(LINE_SEPA);
buff.append("getRemoteAddr()=");
buff.append(request.getRemoteAddr());
buff.append(LINE_SEPA);
buff.append("getRemoteHost()=");
buff.append(request.getRemoteHost());
buff.append(LINE_SEPA);
buff.append(”getScheme()=”);
buff.append(request.getScheme());
buff.append(LINE_SEPA);
buff.append("getServerName()=");
buff.append(request.getServerName());
buff.append(LINE_SEPA);
buff.append(”getServerPort()=”);
buff.append(request.getServerPort());
buff.append(LINE_SEPA);
buff.append("isSecure()=");
buff.append(request.isSecure());
buff.append(LINE_SEPA);
buff.append("getAuthType()=");
buff.append(request.getAuthType());
buff.append(LINE_SEPA);
buff.append("getContextPath()=");
buff.append(request.getContextPath());
buff.append(LINE_SEPA);
buff.append("getMethod()=");
buff.append(request.getMethod());
buff.append(LINE_SEPA);
buff.append("getPathInfo()=");
buff.append(request.getPathInfo());
buff.append(LINE_SEPA);
buff.append("getPathTranslated()=");
buff.append(request.getPathTranslated());
buff.append(LINE_SEPA);
buff.append("getQueryString()=");
buff.append(request.getQueryString());
buff.append(LINE_SEPA);
buff.append("getRemoteUser()=");
buff.append(request.getRemoteUser());
buff.append(LINE_SEPA);
buff.append("getRequestedSessionId()=");
buff.append(request.getRequestedSessionId());
buff.append(LINE_SEPA);
buff.append("getRequestURI()=");
buff.append(request.getRequestURI());
buff.append(LINE_SEPA);
buff.append("getServletPath()=");
buff.append(request.getServletPath());
buff.append(LINE_SEPA);
buff.append("getUserPrincipal()=");
buff.append(request.getUserPrincipal());
buff.append(LINE_SEPA);
buff.append("isRequestedSessionIdFromCookie()=");
buff.append(request.isRequestedSessionIdFromCookie());
buff.append(LINE_SEPA);
buff.append("isRequestedSessionIdFromURL()=");
buff.append(request.isRequestedSessionIdFromURL());
buff.append(LINE_SEPA);
buff.append("isRequestedSessionIdValid()=");
buff.append(request.isRequestedSessionIdValid());
buff.append(LINE_SEPA);
return buff.toString();
}
private static String getSessionInfo(HttpServletRequest request,boolean before) {
HttpSession session = request.getSession();
StringBuffer buff = new StringBuffer();
buff.append(LINE_SEPA);
如果(之前){
buff.append(” session.isNew() = ” + session.isNew());
buff.append(LINE_SEPA);
buff.append(” session.getId() = ” + session.getId());
buff.append(LINE_SEPA);
}
枚举 e = session.getAttributeNames();
while (e.hasMoreElements()) {
String sessionName = (String) e.nextElement();
String sessionClassName = session.getAttribute(sessionName)
.getClass().getName();
buff.append(” name =” + sessionName + “, value =”
+ session.getAttribute(sessionName) + “, attributeClass = ”
+ sessionClassName+LINE_SEPA);
}
return buff.toString();
}
private static Hashtable convertRequest(HttpServletRequest request) {
Hashtable tempHash = new Hashtable();
枚举 e = request.getParameterNames();
while (e.hasMoreElements()) {
String key = (String) e.nextElement();
String[] values = request.getParameterValues(key);
String[] parameterValues = new String[values.length];
for (int i = 0; i < values.length; i++) {
parameterValues[i] = convUnicode(values[i]);
}
tempHash.put(key, parameterValues);
}
返回临时哈希;;
}
private static String stratum(Object value) {
如果 (value == null) {
返回“null”;;
} else if (value instanceof String[]) {
返回 convString((String[]) 值);
别的 {
return value.toString();
}
}
/**
* 将字符串数组 [strArray] 的内容作为字符串返回,如下所示。
* “[temp1,temp2,temp3]”
* @param strArray 要计算的字符串数组。
* @return 转换后的字符串
*/
private static String convString(String[] strArray) {
如果 (strArray == null)
返回空值;;
StringBuffer buff = new StringBuffer(“[“);
for (int i = 0; i < strArray.length; i++) {
buff.append(strArray[i] + ", ");
}
buff.delete(buff.length() – 2, buff.length());
buff.append("]");
return buff.toString();
}
/**
* 将 [str] 转换为 Unicode。
* @param str
* @返回
*/
private static String convUnicode(String str) {
如果 (str == null)
返回空值;;
尝试 {
return new String(str.getBytes(“8859_1”), “JISAutoDetect”);
} catch (UnsupportedEncodingException e) {
抛出新的 RuntimeException(e);;
}
}
// —————————————————————————–
静态类 CustomFormatter 继承自 Formatter {
static final String pattern = “yyyy/MM/dd HH:mm:ss”;
public synchronized String format(LogRecord record) {
StringBuffer buf = new StringBuffer();
// 设置日期和时间
Date date = new Date();
date.setTime(record.getMillis());
SimpleDateFormat formatter = new SimpleDateFormat(pattern);
buf.append(formatter.format(date));
buf.append(":");
// 设置级别
buf.append(“[” + record.getLevel().getName() + “]”);
buf.append(":");
buf.append(record.getMessage());
buf.append(LINE_SEPA);
return buf.toString();
}
}
static class CustomConsoleHandler extends StreamHandler {
public CustomConsoleHandler() {
极好的();
设置输出流(System.out);
}
/**
* 将发出一个日志记录。
* 在初始状态下,日志记录请求会定向到 Logger 对象。
这是响应操作,此对象初始化 LogRecord。
* 此内容已转发至此。
*
* @param record 日志事件的描述。空记录将被忽略。
* 不会发送任何通知。
*/
public void publish(LogRecord record) {
super.publish(record);
刷新();
}
/**
即使你重写了 StreamHandler.close 来刷新,
输出流不会被关闭。换句话说,System.err 不会被关闭。
*/
public void close() {
刷新();
}
}
}
