过滤器实现用户访问记录日志记录
2019独角兽企业重金招聘Python工程师标准>>>
需求:
1.记录用户请求记录,需要记录请求的参数,在异常情况下可以复现异常。
2.记录每个请求的响应记录。
实现:
记录请求日志
1.使用log4j输出记录到单独日志文件中,配置log4j
#配置logger和日志输出等级
log4j.logger.com.jsz.peini.interceptor.AccessLogFilter= INFO,accessLog
#配置不继承父类appender 它是 子Logger 是否继承 父Logger 的 输出源(appender) 的标志位。具体说,默认情况下子#Logger会继承父Logger的appender,也就是说子Logger会在父Logger的appender里输出。若是additivity设为false,则子#Logger只会在自己的appender里输出,而不会在父Logger的appender里输出。
log4j.additivity.com.jsz.peini.interceptor.AccessLogFilter=false
#配置按天滚动日志文件
log4j.appender.accessLog=org.apache.log4j.DailyRollingFileAppender
#日志文件位置
log4j.appender.accessLog.File=d:/peinilog/peini20access.log
#文件名
log4j.appender.accessLog.DatePattern=yyyy-MM-dd'.log'
log4j.appender.accessLog.layout=org.apache.log4j.PatternLayout
log4j.appender.accessLog.layout.ConversionPattern=%-d{yyyy-MM-dd HH\:mm\:ss} - %m%n
log4j.additivity.accessLog=false
2.请求参数分两种类型,一种存放在url中一种放在requestBody中。
在url中的参数使用request.getParameterMap();即可获取,不会对以后的使用造成影响,而requestBody中的数据,如果在过滤器中getInputStream后就会被消耗掉,后面的程序就无法再次获取。所以需要将request对象包装一下,缓存住inputstream中的内容。
实现HttpServletRequestWrapper类 将数据缓存到byte数组中,重写getInputStream和getReader方法。
package com.jsz.peini.interceptor;import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.HashMap;
import java.util.Map;import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;public class PnRequestWrapper extends HttpServletRequestWrapper {private final byte[] body; // 报文 final static int BUFFER_SIZE = 4096; public PnRequestWrapper(HttpServletRequest request) throws IOException { super(request);body = InputStreamTOByte(request.getInputStream()); } @Override public BufferedReader getReader() throws IOException { return new BufferedReader(new InputStreamReader(getInputStream())); } @Override public ServletInputStream getInputStream() throws IOException { final ByteArrayInputStream bais = new ByteArrayInputStream(body); return new ServletInputStream() { @Override public int read() throws IOException { return bais.read(); } }; }// 将InputStream转换成byte数组 public static byte[] InputStreamTOByte(InputStream in) throws IOException { ByteArrayOutputStream outStream = new ByteArrayOutputStream(); byte[] data = new byte[BUFFER_SIZE]; int count = -1; while ((count = in.read(data, 0, BUFFER_SIZE)) != -1) outStream.write(data, 0, count); data = null; return outStream.toByteArray(); } }
3.解决了前面的问题后实现filter
package com.jsz.peini.interceptor;import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.Map;import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;import com.alibaba.fastjson.JSONObject;
import com.jsz.peini.common.util.PeiniUtils;
import com.jsz.peini.common.util.ThreadUtil;public class AccessLogFilter implements Filter {private static final Logger logger = LoggerFactory.getLogger(AccessLogFilter.class);@Overridepublic void init(FilterConfig filterConfig) throws ServletException {}@Overridepublic void doFilter(ServletRequest request, ServletResponse response,FilterChain chain) throws IOException, ServletException {/*** 判断请求* get请求不用多余处理,获取请求参数后放行。* post请求判断* content-type:keyvalue获取requestmap记录* json 包装request获取inputstream 记录* 放行* * 记录参数:访问时间-响应时间-请求的接口-请求的类型-请求的userid-请求的token-请求的ip-请求useragent-请求的parameter-请求的inputstream*/HttpServletRequest httpServletRequest = (HttpServletRequest) request;long startTime = System.currentTimeMillis(); String method = httpServletRequest.getMethod();String accessIp = getIpAddr(httpServletRequest);String accessUrl = httpServletRequest.getRequestURI();//从header获取token 如果token未获取到,从parameter获取token(userId)String token = httpServletRequest.getHeader("token");String userId = "";if(StringUtils.isBlank(token)){token = request.getParameter("userId");if(StringUtils.isNotBlank(token)){JSONObject obj = PeiniUtils.validToken(token);if (obj.getInteger("resultCode") != 1) {} else {userId = obj.getString("userId");}}else{userId = token;}}else{userId = ThreadUtil.getThreadInfo().getUserId();}String userAgent = httpServletRequest.getHeader("User-Agent");String requestParameter = "";String requestBodyJson = "";ServletRequest requestWrapper = null; if("GET".equals(method)){requestParameter = getRequestParameter(httpServletRequest);}else if("POST".equals(method)){if(request instanceof HttpServletRequest&&"application/json".equals(((HttpServletRequest) request).getHeader("Content-Type"))) { requestWrapper = new PnRequestWrapper((HttpServletRequest) request); } if(requestWrapper == null) { requestParameter = getRequestParameter(httpServletRequest);}else{InputStream is = requestWrapper.getInputStream();StringBuilder requsetBodyBuilder = new StringBuilder (); BufferedReader streamReader = new BufferedReader (new InputStreamReader (is,"UTF-8")); String inputStr; while ((inputStr = streamReader.readLine ()) != null){requsetBodyBuilder.append (inputStr); }requestBodyJson = requsetBodyBuilder.toString();}}if(requestWrapper == null) { chain.doFilter(request, response); }else{chain.doFilter(requestWrapper, response);}long endTime = System.currentTimeMillis(); long execteTime = endTime - startTime;logger.info("{} {} {} {} {} {} {} {} {}",execteTime,accessUrl,method,userId,token,accessIp,userAgent,requestParameter,requestBodyJson);}@Overridepublic void destroy() {}/** * 获取当前网络ip * @param request * @return */ public String getIpAddr(HttpServletRequest request){ String ipAddress = request.getHeader("x-forwarded-for"); if(ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) { ipAddress = request.getHeader("Proxy-Client-IP"); } if(ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) { ipAddress = request.getHeader("WL-Proxy-Client-IP"); } if(ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) { ipAddress = request.getRemoteAddr(); if(ipAddress.equals("127.0.0.1") || ipAddress.equals("0:0:0:0:0:0:0:1")){ //根据网卡取本机配置的IP InetAddress inet=null; try { inet = InetAddress.getLocalHost(); } catch (UnknownHostException e) { e.printStackTrace(); } ipAddress= inet.getHostAddress(); } } //对于通过多个代理的情况,第一个IP为客户端真实IP,多个IP按照','分割 if(ipAddress!=null && ipAddress.length()>15){ //"***.***.***.***".length() = 15 if(ipAddress.indexOf(",")>0){ ipAddress = ipAddress.substring(0,ipAddress.indexOf(",")); } } return ipAddress; }public String getRequestParameter(HttpServletRequest request){StringBuilder requestParameter = new StringBuilder();Map<String, String[]> pa = request.getParameterMap();for (Map.Entry<String, String[]> entry : pa.entrySet()) {requestParameter.append(entry.getKey()+":"+entry.getValue()[0]);}return requestParameter.toString();}}
记录响应日志
记录响应内容,已开始困扰了我很久找不到合适的解决方案,拿不到response的输出流中的数据。
平时开发时除了mybatis sql有异常时日志等级设置为debug等级一般都是info等级,有次设置问debug等级后发现spring mvc会输出响应内容,追踪后是RequestResponseBodyMethodProcessor输出的。
在log4j的配置文件中为这个类配置为debug的日志等级,使用accessLog这个logger,additivity设置问false,既可以实现在日志文件中记录响应内容
log4j.logger.org.springframework.web.servlet.mvc.method.annotation.RequestResponseBodyMethodProcessor=DEBUG,accessLog
log4j.additivity.org.springframework.web.servlet.mvc.method.annotation.RequestResponseBodyMethodProcessor=false
转载于:https://my.oschina.net/u/3714931/blog/1595572
过滤器实现用户访问记录日志记录相关推荐
- 2012文件服务器 读写日志,管理用户访问日志记录记录
管理用户访问日志记录记录 10/16/2017 本文内容 适用范围:Windows Server 2022.Windows Server 2019.Windows Server 2016.Window ...
- 50.Spark大型电商项目-用户访问session分析-top10热门品类之本地测试
本篇文章记录用户访问session分析-top10热门品类之本地测试. 在测试的过程中,到很多问题. 问题一:二次排序需要序列化,否则会在程序运行的时候报错. public class Categor ...
- 如何记录网内用户访问了哪些网站
导言 网络安全的"管"与"控"一直以来备受企业网管.中小办公用户和家庭用户的关注. 如何能让一台设备通过"简单"的操作对网络进行有效地管控呢 ...
- js记录用户访问页面和停留时间
1.setInterval setInterval() 方法可按照指定的周期(以毫秒计)来调用函数或计算表达式. setInterval(code,millisec[,"lang" ...
- 程序员修仙之路--把用户访问记录优化到极致
点击上方蓝色字体,关注我们 菜菜呀,前几天做的用户空间,用户反映有时候比较慢呀 CEO,CTO,CFO于一身的CXO 是吗? 菜菜 我把你拉进用户反馈群,你解决一下呀 CEO,CTO,CFO于一身的C ...
- springboot记录用户访问次数_SpringBoot中自定义注解实现控制器访问次数限制示例...
今天给大伙介绍一下SpringBoot中如何自定义注解实现控制器访问次数限制. 在Web中最经常发生的就是利用恶性URL访问刷爆服务器之类的攻击,今天我就给大伙介绍一下如何利用自定义注解实现这类攻击的 ...
- 利用监听器(Listener)实现用户访问记录
自定义监听器(Listener) 1. 当用户访问网站时,先判断用户的session是否为new: 2. 如果该session为new,获取用户的真实IP,查询数据库对应的今天访问信息是否有该IP: ...
- java记录访问次数_Java 利用监听器来实现记录用户访问网站次数(示例代码)
假如有这么一个需求,要记录所有用户访问某一页面的次数. 最先想到的可能是在该Controller定义一个静态成员,然后在相应Action里自增.但这样有一个问题,就是Tomcat或者其他服务器重启的话 ...
- 华硕路由器信息发现服务器,研究人员发现华硕路由器收集用户访问记录等隐私数据...
基于网络发展和使用需求已经越来越多的用户开始选择智能路由器, 但智能归智能安全性倒是非常值得关注. 日前就有安全研究人员发现了华硕路由器使用的 ASUSWRT 存在收集用户的网页访问记录并与趋势科技共 ...
最新文章
- Linux ssh/scp/docker学习
- 微型计算机原理实验报告总结,微机原理实验报告-两个多位十进制数相加的实验等.doc...
- 超有用的,从此vi变得友好了
- MFC中GetDlgItemInt()方法的疑惑与使用总结
- ubuntu 安装星际译王词典
- 【30分钟学完】canvas动画|游戏基础(1):理论先行
- make modules 和 make modules_install
- 数据库的嵌套查询和统计查询
- linuxoracle查看用户权限_权限管理系统设计过程
- 回归的误差服从正态分布吗_盘点10大回归类型:总有一款深得你心
- 好消息,MaxtoCode 1.10 已经封包,待2005.5.5日发布(如果有Bug将在1.20改正)
- Golang入门~搭建Beego
- 2013-2017蓝桥杯省赛C++A组真题总结(题型及解法)
- java怎么让main方法不退出_JAVA线程池原理源码解析—为什么启动一个线程池,提交一个任务后,Main方法不会退出?...
- 12.2.4 TCP网络调试助手实例
- matlab 平滑曲线连接_科研画图-率失真曲线图改进:散点连接成曲线并画出原散点的标记点(基于Matlab)...
- UVA 11478 Halum(用bellman-ford解差分约束)
- Oracle项目管理系统之任务督办及收发文
- McObject新版eXtremeDB v.8.0在E8存储上运行STAC基准测试创造了多个记录
- 虎扑体育客户端zen源码学习笔记
热门文章
- 山东大学计算机考研压分,很坑!考研院校:这些骚操作,你不得不防
- 企业微信SCRM软件打造私域营销闭环?以保险行业为例
- Crontab定时执行任务
- 拍摄独特人像的技巧(下)
- 一度智信:拼多多商家开直通车大忌
- 治疗抑郁症,这款聊天机器人是认真的
- 洲际酒店集团发布全新奢华精选品牌;凯悦27亿美元收购奢华酒店运营集团ALG | 美通社头条...
- 中大近代物理实验实验报告(LaTeX实现)
- linux文件权限 705,Linux 文件权限 - osc_86eb7mly的个人空间 - OSCHINA - 中文开源技术交流社区...
- android studio编译app,Android Studio编译项目报错