servlet讀取請求參數後流失效的問題

在用reset接口的時候,經常會使用request.getInputStream()方法,可是流只能讀取一次,一旦想要加上一個過濾器用來檢測用戶請求的數據時就會出現異常。html

在過濾器中經過流讀取出用戶post提交過來的數據,這是流已經讀取了一次,那麼該流就已經做廢了,因此在contorller再次讀取用戶請求的數據時就會拋出異常。
解決方法
 
方法一:
 
參見: http://www.cnblogs.com/jiangxinnju/p/5709378.html
簡單說一下原理,其實就是經過自定義的HttpServletRequestWrapper 備份一下流的數據,自定義HttpServletRequestWrapper 調用父類request.getInputStream()讀取所有數據出來保存在一個byte數組內,當再次獲取流數據的時候,自定義的HttpServletRequestWrapper 就會用byte數組從新生成一個新的流。備份的流數據仍然保留在byte數組中。
 
方法二:
request.getInputStream()方法只能使用一次,流就會做廢了,其實咱們還能夠經過另外一種方式獲取用戶傳輸的數據,那就是經過request.getReader()來獲取到一個BufferedReader。這裏要說一下BufferedReader是緩存流,而且BufferedReader的markSupported方法是返回true,說明BufferedReader是能夠標記和回退的流。
 
BufferedReader中有defaultCharBufferSize屬性
 
static { BufferedReader.defaultCharBufferSize = 8192; BufferedReader.defaultExpectedLineLength = 80; }
 
這裏能夠看出緩存大小爲8192,也就是8KB大小的緩存,因此咱們能夠用BufferedReader的標記和重置方法來進行重複讀取流。
 
方法二的性能會比方法一的性能較快,由於BufferedReader只存在一個實例,而不是每次調用都生成。要注意的是經過BufferedReader的標記和重置方法只能讀取8KB之內的內容。超過8KB進行重複讀取時,將會清空8KB前的緩存,致使標記失效,緩存內容將會丟失。好比:讀取了9KB的內容,那麼其中前面的1KB的內容將會在緩存中被清除掉,而只緩存了後面的8KB內容,前面的1KB內容被永久清除了,但後面的8KB內容仍是能經過標記重置來進行重複讀取。 (8KB內容至關於4000字)
 
方法一也是能夠作成緩存流的形式,代替每次生成一個新的實例,這裏就不一一介紹。
 
方法一也是有缺點的,就是遇到文件上傳時內存消耗會增長,由於上傳的文件也是在request流中的,一旦上傳較大的文件,服務器將會內存不足致使宕機。
 
建議最好使用原生自帶的緩存BufferedReader,會更加方便。

重寫request的inputstream方法。。而後在須要部署應用中加上過濾器,在過濾器中加上這個重寫的request的方法web

以下:編寫filter並在web.xml中配置filter數組

@WebFilter(filterName="accessFilter", urlPatterns={
             "*.do",
     //        "*.jsp",
     //        "/*",
     //        "/layout/*",
     //        "/apply/*",
     //        "/audit/*",
     //        "/authority/*",
     //        "/commonWare/*",
     //        "/contract/*",
     //        "/marketing/*",
     //        "/product/*",
     //        "/project/*",
     //        "/system/*",
     //        "/user/*"
             })
     public class MyFilter implements Filter {
         //     日誌對象
         private static Logger logger = Logger.getLogger(MyFilter.class);
     
         public void init(FilterConfig filterConfig) throws ServletException {
         }
         
         public void destroy() {
         }
     
         public void doFilter(ServletRequest req, ServletResponse res,FilterChain chain) throws IOException, ServletException {
             HttpServletRequest request = (HttpServletRequest) req;
             System.out.println("=====+" + req.hashCode());
             HttpServletResponse response = (HttpServletResponse) res;        
             if ("POST".equalsIgnoreCase(request.getMethod())) {
                 
                 ServletRequest requestWrapper = new BodyReaderHttpServletRequestWrapper(request);
                 System.out.println("===filter==+" + requestWrapper.hashCode());
     
                 String body = HttpUtil.getBodyString(requestWrapper);
                 System.out.println("AccessFilter="+body);
                 chain.doFilter(requestWrapper, response);
                 return ;
             }
             
             chain.doFilter(req, res);
         }
     }

 

public class MyHttpServletRequestWrapper extends HttpServletRequestWrapper {

        private final byte[] body;

        public MyHttpServletRequestWrapper(HttpServletRequest request) throws IOException {
            super(request);
            body = HttpUtil.getBodyString(request).getBytes(Charset.forName("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();
                }
            };
        }
    }

 

public static String getBodyString(ServletRequest request) {
        StringBuilder sb = new StringBuilder();
        InputStream inputStream = null;
        BufferedReader reader = null;
        try {
            inputStream = request.getInputStream();
            reader = new BufferedReader(new InputStreamReader(inputStream, Charset.forName("UTF-8")));
            String line = "";
            while ((line = reader.readLine()) != null) {
                sb.append(line);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (inputStream != null) {
                try {
                    inputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (reader != null) {
                try {
                    reader.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return sb.toString();
    }

參考:https://www.cnblogs.com/a393060727/p/6141295.html緩存

相關文章
相關標籤/搜索