自定义httpservletrequestwrapper导致form表单提交数据丢失

话不多说,先上大概的demo代码

Wrapper

public class TestWrapper extends HttpServletRequestWrapper {


    private byte[] body;

    public TestWrapper(HttpServletRequest request) throws IOException {
        super(request);
        body  = StreamUtils.copyToByteArray(request.getInputStream());
    }
    ...

}

Filter

public class TestFilter implements Filter {
    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        TestWrapper testWrapper = new TestWrapper((HttpServletRequest) servletRequest);
        filterChain.doFilter(testWrapper,servletResponse);
    }
}

由于之前的请求一直是json content-type的,所以没发现任何问题

这次在实现一个form content-type的请求时,发现getParameter or getParameterMap数据都为空。

大概Debug过程:

DispatchServletRequest#doService debug发现参数已丢失,那么在Servlet之前只有filter

TestWrapper 断点发现参数还在,但是wrapper后就丢失了

最后分析发现问题所在与request.getParameter实现有关,下面直接贴代码

//org.apache.catalina.connector.RequeseFacade#getParameter

  public String getParameter(String name) {
        if (!this.parametersParsed) {
            this.parseParameters();
        }

        return this.coyoteRequest.getParameters().getParameter(name);
    }

// parseParameters()

protected void parseParameters() {
        this.parametersParsed = true;
        Parameters parameters = this.coyoteRequest.getParameters();
        boolean success = false;
        ...
        try {
            ...
           //如果input stream被用过,就直接return,不解析part
            if (this.usingInputStream || this.usingReader) {
                success = true;
                return;
            } 
        }
        ...
       //没被调用,所以导致参数为空的原因
        this.parseParts(false);
    }

private void parseParts(boolean explicit) {
        if (this.parts == null && this.partsParseException == null) {
      ...//重点在这里,parameters = this.coyoteRequest.getParameters(); 而getParameter最终是通过 return this.coyoteRequest.getParameters().getParameter(name); 获取参数
                            parameters.addParameter(name, value);
                        }
                    }

                    success = true;
                } catch (InvalidContentTypeException var29) {
                    parameters.setParseFailedReason(FailReason.INVALID_CONTENT_TYPE);
                    this.partsParseException = new ServletException(var29);
                } catch (SizeException var30) {
                    parameters.setParseFailedReason(FailReason.POST_TOO_LARGE);
                    this.checkSwallowInput();
                    this.partsParseException = new IllegalStateException(var30);
                } catch (IOException var31) {
                    parameters.setParseFailedReason(FailReason.IO_ERROR);
                    this.partsParseException = new IOException(var31);
                } catch (IllegalStateException var32) {
                    this.checkSwallowInput();
                    this.partsParseException = var32;
                }
            } finally {
                if (this.partsParseException != null || !success) {
                    parameters.setParseFailedReason(FailReason.UNKNOWN);
                }

            }

        }
    }


看上面源码就知道原因出在哪了。

所以解决办法:

1、wrapper之前 先 调用下 getParameterMap or getParameter

2、按需wrapper吧~

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值