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

过滤器实现用户访问记录日志记录相关推荐

  1. 2012文件服务器 读写日志,管理用户访问日志记录记录

    管理用户访问日志记录记录 10/16/2017 本文内容 适用范围:Windows Server 2022.Windows Server 2019.Windows Server 2016.Window ...

  2. 50.Spark大型电商项目-用户访问session分析-top10热门品类之本地测试

    本篇文章记录用户访问session分析-top10热门品类之本地测试. 在测试的过程中,到很多问题. 问题一:二次排序需要序列化,否则会在程序运行的时候报错. public class Categor ...

  3. 如何记录网内用户访问了哪些网站

    导言 网络安全的"管"与"控"一直以来备受企业网管.中小办公用户和家庭用户的关注. 如何能让一台设备通过"简单"的操作对网络进行有效地管控呢 ...

  4. js记录用户访问页面和停留时间

    1.setInterval setInterval() 方法可按照指定的周期(以毫秒计)来调用函数或计算表达式. setInterval(code,millisec[,"lang" ...

  5. 程序员修仙之路--把用户访问记录优化到极致

    点击上方蓝色字体,关注我们 菜菜呀,前几天做的用户空间,用户反映有时候比较慢呀 CEO,CTO,CFO于一身的CXO 是吗? 菜菜 我把你拉进用户反馈群,你解决一下呀 CEO,CTO,CFO于一身的C ...

  6. springboot记录用户访问次数_SpringBoot中自定义注解实现控制器访问次数限制示例...

    今天给大伙介绍一下SpringBoot中如何自定义注解实现控制器访问次数限制. 在Web中最经常发生的就是利用恶性URL访问刷爆服务器之类的攻击,今天我就给大伙介绍一下如何利用自定义注解实现这类攻击的 ...

  7. 利用监听器(Listener)实现用户访问记录

    自定义监听器(Listener) 1. 当用户访问网站时,先判断用户的session是否为new: 2. 如果该session为new,获取用户的真实IP,查询数据库对应的今天访问信息是否有该IP: ...

  8. java记录访问次数_Java 利用监听器来实现记录用户访问网站次数(示例代码)

    假如有这么一个需求,要记录所有用户访问某一页面的次数. 最先想到的可能是在该Controller定义一个静态成员,然后在相应Action里自增.但这样有一个问题,就是Tomcat或者其他服务器重启的话 ...

  9. 华硕路由器信息发现服务器,研究人员发现华硕路由器收集用户访问记录等隐私数据...

    基于网络发展和使用需求已经越来越多的用户开始选择智能路由器, 但智能归智能安全性倒是非常值得关注. 日前就有安全研究人员发现了华硕路由器使用的 ASUSWRT 存在收集用户的网页访问记录并与趋势科技共 ...

最新文章

  1. Linux ssh/scp/docker学习
  2. 微型计算机原理实验报告总结,微机原理实验报告-两个多位十进制数相加的实验等.doc...
  3. 超有用的,从此vi变得友好了
  4. MFC中GetDlgItemInt()方法的疑惑与使用总结
  5. ubuntu 安装星际译王词典
  6. 【30分钟学完】canvas动画|游戏基础(1):理论先行
  7. make modules 和 make modules_install
  8. 数据库的嵌套查询和统计查询
  9. linuxoracle查看用户权限_权限管理系统设计过程
  10. 回归的误差服从正态分布吗_盘点10大回归类型:总有一款深得你心
  11. 好消息,MaxtoCode 1.10 已经封包,待2005.5.5日发布(如果有Bug将在1.20改正)
  12. Golang入门~搭建Beego
  13. 2013-2017蓝桥杯省赛C++A组真题总结(题型及解法)
  14. java怎么让main方法不退出_JAVA线程池原理源码解析—为什么启动一个线程池,提交一个任务后,Main方法不会退出?...
  15. 12.2.4 TCP网络调试助手实例
  16. matlab 平滑曲线连接_科研画图-率失真曲线图改进:散点连接成曲线并画出原散点的标记点(基于Matlab)...
  17. UVA 11478 Halum(用bellman-ford解差分约束)
  18. Oracle项目管理系统之任务督办及收发文
  19. McObject新版eXtremeDB v.8.0在E8存储上运行STAC基准测试创造了多个记录
  20. 虎扑体育客户端zen源码学习笔记

热门文章

  1. 山东大学计算机考研压分,很坑!考研院校:这些骚操作,你不得不防
  2. 企业微信SCRM软件打造私域营销闭环?以保险行业为例
  3. Crontab定时执行任务
  4. 拍摄独特人像的技巧(下)
  5. 一度智信:拼多多商家开直通车大忌
  6. 治疗抑郁症,这款聊天机器人是认真的
  7. 洲际酒店集团发布全新奢华精选品牌;凯悦27亿美元收购奢华酒店运营集团ALG | 美通社头条...
  8. 中大近代物理实验实验报告(LaTeX实现)
  9. linux文件权限 705,Linux 文件权限 - osc_86eb7mly的个人空间 - OSCHINA - 中文开源技术交流社区...
  10. android studio编译app,Android Studio编译项目报错