SpringMVC框架中利用Filter实现请求日志打印

SpringMVC框架中利用Filter实现请求日志打印


之前利用HttpServletRequest.getInputStream()和RequestWrapper实现了请求的requestBody获取,现在提出将一个请求的RequestBody和ResponseBody都提出来并打印日志&落入数据库,以便统计和查找问题。查找资料后确定两种技术方案:
1. 使用AOP对所有Controller的方法进行环绕通知处理;
2. 使用Filter拦截所有的Request和Response,并获取body。
最后选择了第二种方式,具体实现记录如下。


具体实现

  1. 日志记录过滤器

    public class RequestFilter implements Filter{
         
    private static final String LOG_FORMATTER_IN = "请求路径:{%s},请求方法:{%s},参数:{%s},来源IP:{%s},请求开始时间{%s},返回:{%s},请求结束时间{%s},用时:{%s}ms,操作类型:{%s},操作人:{%s}";
    public static final String USER_TOKEN_REDIS_PREFIX = "token_prefix";
    private static final Logger log = LoggerFactory.getLogger(RequestFilter.class);
    //request拦截的conten-type列表
    private List<String> contentTypes;
    
    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        HttpServletRequest httpServletRequest = (HttpServletRequest) request;
        HttpServletResponse httpServletResponse = (HttpServletResponse) response;
    
        //请求路径
        String path = httpServletRequest.getRequestURI();
        String method = httpServletRequest.getMethod();
        //所有请求参数的Map
        Map<String,String> paramMap = new HashMap<>();
        //请求的真实IP
        String requestedIP = RequestUtils.getRealIP(httpServletRequest);
        //是否拦截并包装请求,如果需要拦截则会获取RequestBody,一般为application/json才拦截
        boolean filterRequestFlag = checkFilter(request.getContentType());
        if (filterRequestFlag) {
            httpServletRequest = new MyRequestBodyReaderWrapper(httpServletRequest);
        }
        //获取所有queryString和requestBody
        Map<String, String> requestParamMap = RequestUtils.getRequestParamMap(httpServletRequest);
        if (requestParamMap != null && !requestParamMap.isEmpty()){
            paramMap.putAll(requestParamMap);
        }
        //获取header参数
        Map<String, String> headerMap = RequestUtils.getHeaders(httpServletRequest);
        if (headerMap != null && !headerMap.isEmpty()){
           paramMap.putAll(headerMap);
        }
        //获取路径参数
        Map<String,String> uriTemplateMap = RequestUtils.getUriTemplateVar(httpServletRequest);
        if (uriTemplateMap != null && !uriTemplateMap.isEmpty()){
            paramMap.putAll(uriTemplateMap);
        }
        //包装Response,重写getOutputStream()和getWriter()方法,并用自定义的OutputStream和Writer来拦截和保存ResponseBody
        MyResponseWrapper responseWrapper = new MyResponseWrapper(httpServletResponse);
        //请求开始时间
        Long dateStart = System.currentTimeMillis();
        //Spring通过DispatchServlet处理请求
        chain.doFilter(httpServletRequest, responseWrapper);
        //请求结束时间
        Long dateEnd = System.currentTimeMillis();
        String responseBody;
        if (responseWrapper.getMyOutputStream() == null){
                if (responseWrapper.getMyWriter() != null){
                    responseBody = responseWrapper.getMyWriter().getContent();
                    //一定要flush,responseBody会被复用
                    responseWrapper.getMyWriter().myFlush();
                }
            }else {
                responseBody = responseWrapper.getMyOutputStream().getBuffer();
                <
  • 1
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值