SpringBoot拦截器与过滤器 实现用户访问量/功能访问量的统计

前言

下一篇链接:实现用户访问量/功能访问量的统计信息的查询

真正在公司中的实践:NoSQL + RDBMS 一起使用才是最强的

技术没有高低之分,就看你如何去使用!(提升内功,思维的提高!多思考!)

云计算的长征之路:阿里云的这群疯子,阿里巴巴的架构演进!

1、过滤器 解决输入流不能重复读取问题

request的输入流只能读取一次不能重复读取
我们在过滤器或拦截器里读取了request的输入流之后
请求走到controller 层时就会报错。
文章最后会分析不能重复读取的原因


解决办法:HttpServletRequestWrapper + Filter(过滤器)
既然ServletInputStream不支持重新读写,那我们将ServletInputStream流读出来后,用容器存储起来起来,后面就可以多次读取了。

1.1定义RequestWrapper容器

关于HttpServletRequestWrapper类:
它并没有真正去实现HttpServletRequest的方法,而只是在方法内又去调用HttpServletRequest的方法
所以我们可以通过继承该类并实现想要重新定义的方法,就可以达到包装原生HttpServletRequest对象的目的。

RequestWrapper是我们定义的一个容器,将ServletInputStream输入流里面的数据存储到这个容器里
这个容器可以是数组或集合,然后我们重写里面的getInputStream方法
每次都从这个容器里读数据,这样我们的输入流就可以读取任意次了。

package com.hut.weekcp.server.utils;

import lombok.extern.slf4j.Slf4j;
import org.springframework.util.StreamUtils;

import javax.servlet.ReadListener;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import java.io.*;

/**
 * @author zxp
 * @program wrapper-demo
 * @description 包装HttpServletRequest,目的是让其输入流可重复读,解决了在过滤器或拦截器里读取了request的输入流之后,请求走到controller层时就会报错的问题
 * @create 2021-1-22
 **/
@Slf4j
public class RequestWrapper extends HttpServletRequestWrapper {
   
   
    /**
     * 缓存下来的HTTP body
     */
    private byte[] body;

    public RequestWrapper(HttpServletRequest request) throws IOException {
   
   
        super(request);
        body = StreamUtils.copyToByteArray(request.getInputStream());
    }

    /**
     * 重新包装输入流
     * @return
     * @throws IOException
     */
    @Override
    public ServletInputStream getInputStream() throws IOException {
   
   
        InputStream bodyStream = new ByteArrayInputStream(body);
        return new ServletInputStream() {
   
   

            @Override
            public int read() throws IOException {
   
   
                return bodyStream.read();
            }

            /**
             * 下面的方法一般情况下不会被使用,如果你引入了一些需要使用ServletInputStream的外部组件,可以重点关注一下。
             * @return
             */
            @Override
            public boolean isFinished() {
   
   
                return false;
            }

            @Override
            public boolean isReady() {
   
   
                return true;
            }

            @Override
            public void setReadListener(ReadListener readListener) {
   
   

            }
        };
    }

    @Override
    public BufferedReader getReader() throws IOException {
   
   
        InputStream bodyStream = new ByteArrayInputStream(body);
        return new BufferedReader(new InputStreamReader(getInputStream()));
    }
}

1.2 定义ReplaceStreamFilter 过滤规则

在过滤器doFilter()方法里将原生的HttpServletRequest对象替换成我们的RequestWrapper对象
然后每次接口请求的输入流,都会用RequestWrapper容器存储了

package com.hut.weekcp.server.filter;

import com.hut.weekcp.server.utils.RequestWrapper;
import lombok.extern.slf4j.Slf4j;

import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;

/**
 * @author zxp
 * @program wrapper-demo
 * @description 替换HttpServletRequest
 * @create 2021-1-22
 **/
@Slf4j
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值