解决post请求无法多次获取inputstream的问题

解决post请求无法多次获取inputstream的问题

问题
post请求在controller中通过request的getinputstream方法获取不到输入流
原因:
post的request当获取流或者获取参数之后,无法再次获取,可能是请求进来时在其他地方进行了数据读取,但是我在项目中没找到。
解决:
可以通过实现httpservletrequestwrapper 对request请求进行封装


package net.referee.config;

import javax.servlet.ReadListener;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import java.io.*;

public class MyRequestWrapper extends HttpServletRequestWrapper {
    private final String body;
    public MyRequestWrapper(HttpServletRequest request) throws IOException {
        super(request);
        ServletInputStream inputStream = request.getInputStream();
        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
        try {
            byte[] b = new byte[10240];
            int n;
            while ((n = inputStream.read(b)) != -1) {
                outputStream.write(b, 0, n);
            }
        } catch (Exception e) {
            try {
                inputStream.close();
                outputStream.close();
            } catch (Exception e1) {
            }
        }
        body = outputStream.toString();
        request.setAttribute("body",body); //将post的body数据放入缓存,这样子在后面就能够随时取用
    }

    @Override
    public ServletInputStream getInputStream() throws IOException {
        final ByteArrayInputStream bais = new ByteArrayInputStream(body.getBytes());
        return new ServletInputStream() {
            @Override
            public int read() throws IOException {
                return bais.read();
            }

            @Override
            public boolean isFinished() {
                return false;
            }

            @Override
            public boolean isReady() {
                return false;
            }

            @Override
            public void setReadListener(ReadListener readListener) {

            }
        };
    }

    @Override
    public BufferedReader getReader() throws IOException {
        return new BufferedReader(new InputStreamReader(this.getInputStream()));
    }
}

包装之后在调用getinputstream时就会调用包装类的 方法。
这时候还有问题,因为包装之后并没有应用,因为我们找不到具体什么地方读取了post请求的内容,所以设置了过滤器让请求经过过滤器,并且将request替换成包装类这样就可以重复获取了。

package net.referee.config;

import org.springframework.core.annotation.Order;

import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;

/*
此过滤器用于解决post请求无法重复获取参数的问题
 */
public class MyFilter  implements Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {

    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        MyRequestWrapper req = new MyRequestWrapper((HttpServletRequest)servletRequest);
        filterChain.doFilter(req,servletResponse);
    }

    @Override
    public void destroy() {

    }
}

这时候又有问题,这个过滤器怎么应用到项目中呢 ,我通过配置类将此过滤器注册,并且将其放到了最前方,请求一进来就会经过。

//将自定义的过滤器置于最前
@Bean
public FilterRegistrationBean myFilter() {
    FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean();

    MyFilter myFilter1 = new MyFilter();

    filterRegistrationBean.setFilter(myFilter1);
    filterRegistrationBean.addUrlPatterns("/*");//配置过滤规则
    filterRegistrationBean.setName("myFilter");//设置过滤器名称
    filterRegistrationBean.setOrder(Ordered.HIGHEST_PRECEDENCE);//执行次序

    return filterRegistrationBean;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值