1. 程式人生 > >Java post請求傳送json資料在filter中解析方法

Java post請求傳送json資料在filter中解析方法

大家都知道Java的servlet分get和post請求方式,在servlet或者在集成了springMVC、Struts2的框架的情況下獲取請求的引數。那麼有時候我們需要在攔截其中獲取ServletRequest的引數就不那麼容易了。因為在ServletRequst中,如果是get請求我們可以通過request.getParameter(“”)來獲取get的引數或者是form提交的post引數,但是如果是ajax提交的post請求的application/json請求,那麼在get的時候就無法獲取到值了,有人會想我通過request的請求流來解析json文字,這樣做是可以的,但 是有個問題就是如果在攔截其中呼叫了ServletRequest的getInputStream方法,那麼在後面的servlet中或者你整合的框架中的control層就無法呼叫getInputStream方法來解析獲取引數了。
有了上面的疑問,我們就有了分析,解決辦法的途徑。通過對HttpServletRequest的分析結合資料,最後得出結論就是改寫ServletRequst的getInputStream方法便可以解決問題。我們可以分析一下HttpServletRequest的中的stream只能被read一次,那麼我們可以在filter中呼叫getInputSteam獲取json字串,然後通過獲取的json文字去生成新的stream來給ServletRequest,後面的control就可以繼續獲取stream(我們自己用json文字生成)。有了這個思路我們就來看看程式碼。
第一部分,改寫ServletRequest:

public classPostServletRequestextendsHttpServletRequestWrapper{
    private String body=null;

    /**
     * Constructs a request object wrapping the given request.
     * @param request
     * @throws IllegalArgumentException if the request is null
     */
    public PostServletRequest(HttpServletRequest request,String body) {
        super
(request); this.body=body; } @Override public ServletInputStream getInputStream() throws IOException { ServletInputStream inputStream = null; if(StringUtil.isNotEmpty(body)){ inputStream = new PostServletInputStream(body); } return inputStream; } @Override
public BufferedReader getReader() throws IOException { String enc = getCharacterEncoding(); if(enc == null) enc = "UTF-8"; return new BufferedReader(new InputStreamReader(getInputStream(), enc)); } }

第二本分,ServletInputStream的改寫:

public classPostServletInputStreamextendsServletInputStream {
    private InputStream inputStream;
    private String body ;//解析json之後的文字

    public PostServletInputStream(String body) throws IOException {
        this.body=body;
        inputStream = null;
    }


    private InputStream acquireInputStream() throws IOException {
        if(inputStream == null) {
            inputStream = new ByteArrayInputStream(body.getBytes());//通過解析之後傳入的文字生成inputStream以便後面control呼叫
        }

        return inputStream;
    }


    public void close() throws IOException {
        try {
            if(inputStream != null) {
                inputStream.close();
            }
        }
        catch(IOException e) {
            throw e;
        }
        finally {
            inputStream = null;
        }
    }


    public int read() throws IOException {
        return acquireInputStream().read();
    }


    public boolean markSupported() {
        return false;
    }


    public synchronized void mark(int i) {
        throw new UnsupportedOperationException("mark not supported");
    }


    public synchronized void reset() throws IOException {
        throw new IOException(new UnsupportedOperationException("reset not supported"));
    }
}

第三部分:在filter中的呼叫

//解析post的json引數
String body = getBody((HttpServletRequest)request);
Map paramMap = JsonUtil.json2Map(body);
if(null != paramMap){
    wpcCd = (String)paramMap.get("wpcCd");
}
//使用解析資料重新生成ServletRequest,供doChain呼叫
request =getRequest(request,body);

getBody方法:
private String getBody(HttpServletRequest request) throws IOException {
        String body = null;
        StringBuilder stringBuilder = new StringBuilder();
        BufferedReader bufferedReader = null;
        try {
            InputStream inputStream = request.getInputStream();
            if (inputStream != null) {
                bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
                char[] charBuffer = new char[128];
                int bytesRead = -1;
                while ((bytesRead = bufferedReader.read(charBuffer)) > 0) {
                    stringBuilder.append(charBuffer, 0, bytesRead);
                }
            } else {
                stringBuilder.append("");
            }
        } catch (IOException ex) {
            throw ex;
        }finally {
            if(null != bufferedReader){
                bufferedReader.close();
            }
        }
        body = stringBuilder.toString();
        return body;
    }

    /**
     * 將post解析過後的request進行封裝改寫
     * @param request
     * @param body
     * @return
     */
    private ServletRequest getRequest(ServletRequest request ,String body){
        String enctype = request.getContentType();
        if (StringUtils.isNotEmpty(enctype) && enctype.contains("application/json")){
            return new PostServletRequest((HttpServletRequest) request,body);
        }
        return request;
    }

如果在其他地方也有用到類似,可根據實際應用自己封裝改寫getInputStream即可。到此結束。謝謝!