Spring Boot中使用拦截器和过滤器拦截请求并且使用包装类

2019-02-25  本文已影响17人  我的小熊不见了

拦截器

在Spring Boot中使用拦截器和过滤器可以帮助我们解决很多通用性的问题。使用拦截器只需要重写preHandle方法。

    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws IOException {

问题

在进行拦截时我们一般都需要解析HttpServletRequest中的流信息,但是HttpServletRequest 只能被读取一次,如果在拦截器中被读取了那么在后续的程序中就无法使用request了。因此我们需要使用包装类包装request

包装类

以下是包装类的代码:

public class BodyReaderHttpServletRequestWrapper extends HttpServletRequestWrapper {

    private final byte[] body;

    public BodyReaderHttpServletRequestWrapper(HttpServletRequest request) throws IOException {
        super(request);
        body = IOUtil.readByteArray(request.getInputStream());
    }

    @Override
    public BufferedReader getReader() {
        return new BufferedReader(new InputStreamReader(getInputStream()));
    }

    @Override
    public ServletInputStream getInputStream() {

        final ByteArrayInputStream bais = new ByteArrayInputStream(body);

        return new ServletInputStream() {

            @Override
            public int read() {
                return bais.read();
            }

            @Override
            public boolean isFinished() {
                return false;
            }

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

            @Override
            public void setReadListener(ReadListener readListener) {
            }
        };
    }
}

代码中用到了一个工具方法:

public static byte[] readByteArray(InputStream in) throws IOException {
        BufferedInputStream bufin = new BufferedInputStream(in);
        int buffSize = 1024;
        ByteArrayOutputStream out = new ByteArrayOutputStream(buffSize);
        byte[] temp = new byte[buffSize];
        boolean var5 = false;

        int size;
        while((size = bufin.read(temp)) != -1) {
            out.write(temp, 0, size);
        }

        bufin.close();
        return out.toByteArray();
    }

上面的代码中,将原始的HttpServletRequest通过构造方法传进去保存起来,读取的时候直接读取包装类中保存的流。

if (request instanceof BodyReaderHttpServletRequestWrapper) {
            String body = IOUtil.readStream(request.getInputStream(), "UTF-8");
}

问题是在什么地方去把HttpServletRequest转换成我们自己的BodyReaderHttpServletRequestWrapper

过滤器

在Java中实现Filter,对所有请求进行过滤。

@Component
@WebFilter(value = "/*")
public class WrapRequestFilter implements Filter {
    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        HttpServletRequest request = (HttpServletRequest) servletRequest;
        if (servletRequest.getContentType() != null && servletRequest.getContentType().contains("application/json")) {
             //包装request
            filterChain.doFilter(new BodyReaderHttpServletRequestWrapper(request), servletResponse);
        } else {//不进行包装
            filterChain.doFilter(servletRequest, servletResponse);
        }
    }

    @Override
    public void init(FilterConfig filterConfig) {
    }

    @Override
    public void destroy() {

    }
}

如果符合条件就使用包装类。这样就把所有的接口都包装成我们自己的包装类了。然后就可以随心所欲的使用request做你想做的事情了。

上一篇下一篇

猜你喜欢

热点阅读