• 配置RepeatableFilter


    在项目中经常出现多次读取HTTP请求体的情况,这时候可能就会报错,原因是读取HTTP请求体的操作,最终都要调用HttpServletRequest的getInputStream()方法和getReader()方法,而这两个方法总共只能被调用一次,第二次调用就会报错,那如何解决这个问题呢?以若依框架中的RepeatableFilter为例进行说明。

    将HttpServletRequest的字节流的数据,保存到一个变量中,重写getInputStream()方法和getReader()方法,从变量中读取数据,返回给调用者。

    RepeatableFilter 
    package com.ruoyi.common.filter;
    
    import java.io.IOException;
    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.springframework.http.MediaType;
    import com.ruoyi.common.utils.StringUtils;
    
    
    public class RepeatableFilter implements Filter
    {
        @Override
        public void init(FilterConfig filterConfig) throws ServletException
        {
    
        }
    
        @Override
        public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
                throws IOException, ServletException
        {
            ServletRequest requestWrapper = null;
            if (request instanceof HttpServletRequest && StringUtils.equalsAnyIgnoreCase(request.getContentType(),
                    MediaType.APPLICATION_JSON_VALUE, MediaType.APPLICATION_JSON_UTF8_VALUE))
            {
                requestWrapper = new RepeatedlyRequestWrapper((HttpServletRequest) request, response);
            }
            if (null == requestWrapper)
            {
                chain.doFilter(request, response);
            }
            else
            {
                chain.doFilter(requestWrapper, response);
            }
        }
    
        @Override
        public void destroy()
        {
    
        }
    }
    RepeatedlyRequestWrapper
    package com.ruoyi.common.filter;
    
    import java.io.BufferedReader;
    import java.io.ByteArrayInputStream;
    import java.io.IOException;
    import java.io.InputStreamReader;
    import javax.servlet.ReadListener;
    import javax.servlet.ServletInputStream;
    import javax.servlet.ServletResponse;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletRequestWrapper;
    import com.ruoyi.common.utils.http.HttpHelper;
    
    /**
     * 构建可重复读取inputStream的request
     * 
     * @author ruoyi
     */
    public class RepeatedlyRequestWrapper extends HttpServletRequestWrapper
    {
        private final byte[] body;
    
        public RepeatedlyRequestWrapper(HttpServletRequest request, ServletResponse response) throws IOException
        {
            super(request);
            request.setCharacterEncoding("UTF-8");
            response.setCharacterEncoding("UTF-8");
    
            body = HttpHelper.getBodyString(request).getBytes("UTF-8");
        }
    
        @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();
                }
    
                @Override
                public boolean isFinished()
                {
                    return false;
                }
    
                @Override
                public boolean isReady()
                {
                    return false;
                }
    
                @Override
                public void setReadListener(ReadListener readListener)
                {
    
                }
            };
        }
    }

    然后再将filter注册进spring即可:

    package com.ruoyi.framework.config;
    
    import java.util.HashMap;
    import java.util.Map;
    import javax.servlet.DispatcherType;
    import org.springframework.beans.factory.annotation.Value;
    import org.springframework.boot.web.servlet.FilterRegistrationBean;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import com.ruoyi.common.filter.RepeatableFilter;
    import com.ruoyi.common.filter.XssFilter;
    import com.ruoyi.common.utils.StringUtils;
    
    /**
     * Filter配置
     *
     * @author ruoyi
     */
    @Configuration
    public class FilterConfig
    {
        @Value("${xss.enabled}")
        private String enabled;
    
        @Value("${xss.excludes}")
        private String excludes;
    
        @Value("${xss.urlPatterns}")
        private String urlPatterns;
    
        @SuppressWarnings({ "rawtypes", "unchecked" })
        @Bean
        public FilterRegistrationBean xssFilterRegistration()
        {
            FilterRegistrationBean registration = new FilterRegistrationBean();
            registration.setDispatcherTypes(DispatcherType.REQUEST);
            registration.setFilter(new XssFilter());
            registration.addUrlPatterns(StringUtils.split(urlPatterns, ","));
            registration.setName("xssFilter");
            registration.setOrder(FilterRegistrationBean.HIGHEST_PRECEDENCE);
            Map<String, String> initParameters = new HashMap<String, String>();
            initParameters.put("excludes", excludes);
            initParameters.put("enabled", enabled);
            registration.setInitParameters(initParameters);
            return registration;
        }
    
        @SuppressWarnings({ "rawtypes", "unchecked" })
        @Bean
        public FilterRegistrationBean someFilterRegistration()
        {
            FilterRegistrationBean registration = new FilterRegistrationBean();
            registration.setFilter(new RepeatableFilter());
            registration.addUrlPatterns("/*");
            registration.setName("repeatableFilter");
            registration.setOrder(FilterRegistrationBean.LOWEST_PRECEDENCE);
            return registration;
        }
    
    }
     
  • 相关阅读:
    linux 压缩当前文件夹下所有文件
    redis从入门到精通
    焦点小组测试和可用性测试
    面包屑的故事
    VSCode导入两个工程示例
    数据库规格化
    mergeCI一点小波澜
    Java中List与Set相互转化
    MyBatis中in的使用
    长寿时代的养老风险管理
  • 原文地址:https://www.cnblogs.com/silenceshining/p/14328104.html
Copyright © 2020-2023  润新知