解决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
    评论
### 回答1: 可以使用以下Java代码从HttpServletRequest对象中获取POST请求体: ``` // 获取请求体长度 int contentLength = request.getContentLength(); // 创建字节数组来保存请求数据 byte[] requestBodyData = new byte[contentLength]; // 读取请求数据到字节数组 ServletInputStream inputStream = request.getInputStream(); int totalBytesRead = 0; while(totalBytesRead < contentLength) { int bytesRead = inputStream.read(requestBodyData, totalBytesRead, contentLength - totalBytesRead); if(bytesRead == -1) { break; } totalBytesRead += bytesRead; } // 将字节数组转换成字符串 String requestBody = new String(requestBodyData, "UTF-8"); ``` 在这个示例代码中,我们首先从HttpServletRequest对象中获取请求体长度,然后创建一个字节数组来保存请求数据。接着,我们使用ServletInputStream对象从请求中读取数据,并将其存储在字节数组中。最后,我们将字节数组转换成字符串,以便在后续代码中进行处理。请注意,在这个示例代码中,我们假设请求体使用UTF-8编码。如果请求使用其他编码,则需要相应地更改代码。 ### 回答2: 从HttpServletRequest对象获取POST请求体可以通过以下步骤完成: 1. 首先,确保添加了javax.servlet-api依赖包到项目中,以便使用HttpServletRequest类。 2. 在Servlet的doPost或doPut方法中,接收HttpServletRequest对象作为方法参数。 3. 使用HttpServletRequest对象的getInputStream方法,获取来自客户端的请求体输入流。代码示例如下: ``` InputStream inputStream = request.getInputStream(); ``` 4. 在获取请求体输入流后,我们可以使用IO流的方式来读取POST请求体的内容。例如,使用BufferedReader读取输入流内容。代码示例如下: ``` BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream)); String line; StringBuilder stringBuilder = new StringBuilder(); while ((line = reader.readLine()) != null) { stringBuilder.append(line); } String requestBody = stringBuilder.toString(); ``` 5. 最后,你可以通过requestBody变量来获取POST请求体的内容。你可以根据实际情况对请求体进行解析、处理或存储。 需要注意的是,如果请求体较大或需要多次读取请求体内容,可以使用缓冲流、字符流等方式进行读取和处理。 希望以上回答能够帮助到你,如果还有其他问题,请随时提问。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值