request使用getReader()和getInputStream()擷取請求參數報400錯誤

來源:互聯網
上載者:User

標籤:java filter修改參數 報400錯誤

參考:http://liwx2000.iteye.com/blog/1542431 和http://stackoverflow.com/questions/7318632/java-lang-illegalstateexception-getreader-has-already-been-called-for-this-re


原因:ServletRequest中getReader()和getInputStream()只能調用一次的解決辦法

最近使用spring mvc做項目,資料格式是json,需要對請求參數中的密碼解密,而請求的參數是整個RequestBody,Controller裡是用過@RequestBody擷取的。實現方法是通過一個Filter讀取整個RequestBody並記錄。但是這時就遇到一個問題,ServletRequest的getReader()和getInputStream()兩個方法只能被調用一次,而且不能兩個都調用。那麼如果Filter中調用了一次,在Controller裡面就不能再調用了

解決辦法:

兩個方法都註明方法只能被調用一次,由於RequestBody是流的形式讀取,那麼流讀了一次就沒有了,所以只能被調用一次。既然是因為流只能讀一次的原因,那麼只要將流的內容儲存下來,就可以實現反覆讀取了。 

實現方法:先將RequestBody儲存為一個byte數組,然後通過Servlet內建的HttpServletRequestWrapper類覆蓋getReader()和getInputStream()方法,使流從儲存的byte數組讀取。然後再Filter中將ServletRequest替換為ServletRequestWrapper。代碼如下: 

public class DecodeFilter implements Filter {@Overridepublic void init(FilterConfig filterConfig) throws ServletException {// TODO Auto-generated method stub}@Overridepublic void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)throws IOException, ServletException {ServletRequest requestWrapper = null;          if(request instanceof HttpServletRequest) {              requestWrapper = new MyHttpServletRequest((HttpServletRequest) request);          }          if(null == requestWrapper) {              chain.doFilter(request, response);          } else {              chain.doFilter(requestWrapper, response);          }   }/** * getInputStream()和getReader() 都只能讀取一次,由於RequestBody是流的形式讀取,那麼流讀了一次就沒有了,所以只能被調用一次。 * 先將RequestBody儲存,然後通過Servlet內建的HttpServletRequestWrapper類覆蓋getReader()和getInputStream()方法, * 使流從儲存的body讀取。然後再Filter中將ServletRequest替換為ServletRequestWrapper * @description * @author yuhy * @date 2015年12月9日 */private class MyHttpServletRequest extends HttpServletRequestWrapper {private String _body;    private HttpServletRequest _request;    public MyHttpServletRequest(HttpServletRequest request) throws IOException    {        super(request);        _request = request;        StringBuffer jsonStr = new StringBuffer();        try (BufferedReader bufferedReader = request.getReader())        {            String line;            while ((line = bufferedReader.readLine()) != null)            jsonStr.append(line);        }        //擷取到提交測json,將密碼解密後重新複製給requestBody        JSONObject json = JSONObject.parseObject(jsonStr.toString());        json.put("trdPwd", DesUtil.decrypt(json.getString("trdPwd"),DesUtil.key));        _body = json.toJSONString();    }    @Override    public ServletInputStream getInputStream() throws IOException    {        final ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(_body.getBytes());        return new ServletInputStream()        {            public int read() throws IOException            {                return byteArrayInputStream.read();            }        };    }    @Override    public BufferedReader getReader() throws IOException    {        return new BufferedReader(new InputStreamReader(this.getInputStream()));    }}@Overridepublic void destroy() {// TODO Auto-generated method stub}}

request使用getReader()和getInputStream()擷取請求參數報400錯誤

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.