Java post请求发送json数据在filter中解析方法

版权声明:本文为博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/Kyunchen/article/details/55652160

大家都知道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 class PostServletRequest extends HttpServletRequestWrapper{
    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 class PostServletInputStream  extends ServletInputStream {
    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即可。到此结束。谢谢!

展开阅读全文

没有更多推荐了,返回首页