美文网首页
Spring Boot中使用拦截器和过滤器拦截请求并且使用包装类

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

作者: 我的小熊不见了 | 来源:发表于2019-02-25 19:06 被阅读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做你想做的事情了。

    相关文章

      网友评论

          本文标题:Spring Boot中使用拦截器和过滤器拦截请求并且使用包装类

          本文链接:https://www.haomeiwen.com/subject/jtypdqtx.html