Java 读取http请求而不丢失其中的数据

Java 读取http请求而不丢失其中的数据,java,servlets,servlet-3.0,Java,Servlets,Servlet 3.0,有没有办法读取请求的inputStream而不丢失其中的数据。 在处理请求之前,我试图将请求的原始副本转换为字符串。但是,一旦我从请求中读取了inputstream,inputstream就会变为null,所以我以后无法从请求中获取参数。我尝试使用CustomHttpServletRequestWrapper,但没有成功。下面是我的代码片段 InboundHandler是我的处理程序类,它具有从我的servlet类调用的processRequest(HttpServletRequest请求,H

有没有办法读取请求的inputStream而不丢失其中的数据。


在处理请求之前,我试图将请求的原始副本转换为字符串。但是,一旦我从请求中读取了inputstream,inputstream就会变为null,所以我以后无法从请求中获取参数。我尝试使用
CustomHttpServletRequestWrapper
,但没有成功。下面是我的代码片段

InboundHandler
是我的处理程序类,它具有从我的servlet类调用的
processRequest(HttpServletRequest请求,HttpServletResponse响应)
方法

public class InboundHandler {

 protected void processRequest(HttpServletRequest request, HttpServletResponse response)
 throws ServletException, IOException {
  try {
   CustomHttpServletRequestWrapper requestWrapper = new CustomHttpServletRequestWrapper(request);
   String body = getRequestBody(requestWrapper.getInputStream());

   String from = request.getParameter("from"); //which I'm getting null here
   // I also tried using 
   // String from = requestWrapper.getParameter("from"); // Even this did not work
  } catch (Exception e) {
   e.printStackTrace();
  }
 }

 private String getRequestBody(InputStream inputStream) {

  StringBuilder stringBuilder = new StringBuilder();
  BufferedReader bufferedReader = null;
  try {
   if (inputStream != null) {
    bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
    char[] charBuffer = new char[128];
    int bytesRead = -1;
    while ((bytesRead = bufferedReader.read(charBuffer)) != -1) {
     stringBuilder.append(charBuffer, 0, bytesRead);
    }
   }
  } catch (IOException ex) {
   ex.printStackTrace();
   //throw new AuthenticationException("Error reading the request payload", ex);
  } finally {
   if (bufferedReader != null) {
    try {
     bufferedReader.close();
    } catch (IOException iox) {
     // ignore
    }
   }
  }

  return stringBuilder.toString();
 }

 public class CustomHttpServletRequestWrapper extends HttpServletRequestWrapper {

  private final String body;

  public CustomHttpServletRequestWrapper(HttpServletRequest request) {
   super(request);
   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) {
    ex.printStackTrace();
    //log.error("Error reading the request body...");  
   } finally {
    if (bufferedReader != null) {
     try {
      bufferedReader.close();
     } catch (IOException ex) {
      ex.printStackTrace();
      //log("Error closing bufferedReader...");  
     }
    }
   }

   body = stringBuilder.toString();
  }

  @Override
  public ServletInputStream getInputStream() throws IOException {

   final ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(body.getBytes());

   ServletInputStream inputStream = new ServletInputStream() {
    public int read() throws IOException {
     return byteArrayInputStream.read();
    }
   };

   return inputStream;
  }
 }
}

问:有没有办法读取请求的inputStream而不丢失其中的数据

答:是的,只需“保存”你“阅读”的内容

正如佩多莫夫正确地说的,“请求并不意味着被重用”。一旦你给花园浇水,你就不能把水放回水管里:)

您可以保存数据。Perdomoff建议使用会话变量

另一种选择可能是使用。以下是一个很好的教程:


javadoc for ServletRequest警告不要先读取正文,然后再使用getParameter方法:“如果参数数据是在请求正文中发送的,例如HTTP POST请求,那么直接通过getInputStream()或getReader()读取正文可能会干扰此方法的执行。”输入流可以重置,但这可能不是你想要的。也许您可以从主体中填充一次域对象,然后将其传递到代码的其余部分?是的,我阅读了javadoc for ServletRequest,它说通过getInputStream()直接读取主体会干扰此getParameter()方法的执行。我想知道是否有任何可能的方法可以在不从字符串体填充域对象的情况下获得所需的参数,这看起来不是一种复杂的方法。我更喜欢使用getParameter,而不是从字符串体中提取域对象。@Keefe RoedersheimerNo我仍在尝试这个@perdomoff,只要你相信这些都是参数(所以你没有发布JSON),那么我认为总是使用getParameter调用就可以了——多部分文件上传的工作更复杂;只使用getParameter而不解析正文是否有效?您是否尝试将inputstream复制到字节数组?是的,请求一旦被使用就无法重用,我也同意perdomoff提出了一个很好的解决方案,但它不适合我的要求,我试图找出是否有任何方法可以在我从客户端收到原始请求inputstream后立即备份它,然后我需要这个请求对象来处理其他进程,我试图通过使用HttpServletRequestWrapper将请求的inputstream包装来读取servlet Filter。在执行此操作后,我在servlet中接收到一个带有空inputstream的请求对象,因此我无法处理带有空请求的其他进程。如果您正确地使用了筛选器,您应该不会有任何问题。也许你必须放弃使用HttpServletRequestWrapper——我不知道。但是1)按照教程进行操作,2)创建一个带有过滤器的简单测试用例,3)看看是否可以对实际应用程序执行相同的操作。我想我需要在包装器中覆盖getParameter和其他我需要的方法,这样我可以多次使用request,第一次打印请求inputstream,然后使用getParameter在requestDude上获取所需的参数——同样,就像去年1月正确地说的:“请求并不意味着被重用”。忘记愚蠢的包装器想法,学习如何使用过滤器汉克斯,我真的很感谢你在这个问题上的帮助,我只会使用过滤器。然后发回我的解决方案来解决我的问题