简体   繁体   English

java.lang.IllegalStateException:此请求已调用getInputStream()

[英]java.lang.IllegalStateException: getInputStream() has already been called for this request

I have a Jersey Web-Service that I need to parse some json data that was send along with a request. 我有一个Jersey Web服务,我需要解析一些与请求一起发送的json数据。

@POST
@Path ("/authenticate")
@Produces (MediaType.APPLICATION_JSON)
public Response authenticate (@Context HttpServletRequest request)
{

    try {
        StringBuffer json = new StringBuffer ();
        BufferedReader reader = request.getReader();
        int line;
        while ((line = reader.readLine()) != null)
        {
            json.append(line);
        }
            System.out.prinln (json);
    } catch (IOException e1) {
        // TODO Auto-generated catch block
        e1.printStackTrace();
    }

    return Response.ok().entity(json).build();
}//end authenticate method

This service generates the following Exception: 该服务生成以下异常:

java.lang.IllegalStateException: getInputStream() has already been called for this request

I did some research that suggests a getReader and getInputStream cannot be called on the same request. 我做了一些研究,建议不能在同一请求上调用getReadergetInputStream Therefore, it seemed like a getInputStream instance is already called. 因此,似乎已经调用了getInputStream实例。 How is this possible if I haven't made a explicit call to it? 如果我没有明确调用它怎么办? To solve this problem, I used the getInputStream method instead 为了解决此问题,我改用了getInputStream方法

    try {
        ServletInputStream reader = request.getInputStream();
        int line;
        while ((line = reader.read()) != -1)
        {

        }

    } catch (IOException e1) {
        // TODO Auto-generated catch block
        e1.printStackTrace();
    }

    return Response.ok().entity().build();

With this approach, how can I use the int of bytes to get the json? 通过这种方法,如何使用字节的int来获取json?

Seems like you're missing a @Consumes annotation. 好像您缺少@Consumes批注。 You realise you can just have a method; 您意识到自己可以拥有一种方法;

@POST
@Path ("/authenticate")
@Consumes (MediaType.APPLICATION_JSON)
@Produces (MediaType.APPLICATION_JSON)
public Response authenticate (String entity) {

  //entity contains the posted content

}

Without having to read the stream yourself? 无需自己阅读流? If you have a bean representing your consumed JSON , then you can just add it as a method param and jersey will automatically parse it for you; 如果您有一个表示使用的JSON的bean,则可以将其添加为param方法,并且jersey将自动为您解析它。

@POST
@Path ("/authenticate")
@Consumes (MediaType.APPLICATION_JSON)
@Produces (MediaType.APPLICATION_JSON)
public Response authenticate (AuthBean auth) {

  //auth bean contains the parsed JSON

}


class AuthBean {

   private String username;
   private String password;

   // getters/setters

}

Example post; 示例帖子;

{
 "username" : "joe@example.com",
 "password" : "super s3cret"
}

we can read from the HttpServletRequest only once, so we have to be using HttpServletRequestWrapper inside a filter before reading the request and use the wrapper for subsequent calls for multiple times.. 我们只能从HttpServletRequest中读取一次,因此在读取请求之前,必须在过滤器内部使用HttpServletRequestWrapper ,并将包装器多次用于后续调用。

import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import com.dbs.bds.ingestion.util.MultiReadRequestWrapper;
import lombok.extern.slf4j.Slf4j;
@Slf4j
public class SessionValidationFilter implements Filter {
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain)
        throws IOException, ServletException {
    try {
        log.debug("inside filter");
        HttpServletRequest httpServletRequest = new MultiReadRequestWrapper((HttpServletRequest) servletRequest);
        filterChain.doFilter(httpServletRequest, servletResponse);
    } catch (Exception ex) {
        log.error("error inside filter:{}", ex.getMessage());
    }
 }
}

The below is the code for Wrapper which we used in above Filter. 以下是我们在上面的过滤器中使用的包装器代码。

import org.apache.commons.io.input.BoundedInputStream;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.servlet.ReadListener;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import java.io.*;

public class MultiReadRequestWrapper extends HttpServletRequestWrapper {
private static final Logger LOG = LoggerFactory.getLogger(MultiReadRequestWrapper.class);
// We include a max byte size to protect against malicious requests, 
//since this all has to be read into memory
public static final Integer MAX_BYTE_SIZE = 1_048_576; // 1 MB 
private StringBuilder body;
public MultiReadRequestWrapper(HttpServletRequest request) throws IOException {
    super(request);
    body = new StringBuilder("");
    try (
        InputStream bounded = new BoundedInputStream(request.getInputStream(), MAX_BYTE_SIZE);
        BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(bounded));){
        String line;
        while ((line = bufferedReader.readLine()) != null) {
            body.append(line);
        }
    } catch(Exception e) {
        LOG.error(e.getMessage());
    }
}
@Override
public ServletInputStream getInputStream() throws IOException {
    final ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(body.toString().getBytes());
    return new ServletInputStream() {
        public int read() throws IOException {
            return byteArrayInputStream.read();
        }
        @Override
        public boolean isFinished() {
            return byteArrayInputStream.available() == 0;
        }
        @Override
        public boolean isReady() {
            return true;
        }
        @Override
        public void setReadListener(ReadListener readListener) {
            //do nothing
        }
    };
}
@Override
public BufferedReader getReader() throws IOException {
    return new BufferedReader(new InputStreamReader(this.getInputStream()));
 }
}

Now expose the above filter as bean 现在将上述过滤器公开为bean

 @Bean(name = "sessionValidationFilter")
public Filter getSessionValidationFilter() {
    return new SessionValidationFilter();
}

@SuppressWarnings({"rawtypes", "unchecked"})
@Bean
public FilterRegistrationBean sessionValidationFilterRegistration() {
    FilterRegistrationBean registration = new FilterRegistrationBean();
    registration.setFilter(getSessionValidationFilter());
    registration.addUrlPatterns("/v1/create/record");
    registration.setName("sessionValidationFilter");
    return registration;
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 java.lang.IllegalStateException:在为当前请求调用 getReader() 后无法调用 getInputStream() - java.lang.IllegalStateException: Cannot call getInputStream() after getReader() has already been called for the current request java.lang.IllegalStateException: 已经为此请求调用了getReader() - java.lang.IllegalStateException: getReader() has already been called for this request java.lang.IllegalStateException:已为此响应调用getWriter() - java.lang.IllegalStateException: getWriter() has already been called for this response java.lang.IllegalStateException:已经为此响应调用了 getOutputStream() - java.lang.IllegalStateException: getOutputStream() has already been called for this response java.lang.IllegalStateException:已为此响应调用了getOutputStream() - java.lang.IllegalStateException: getOutputStream() has already been called for this response Spring:java.lang.IllegalStateException:已经为此响应调用了getOutputStream() - Spring: java.lang.IllegalStateException: getOutputStream() has already been called for this response java.lang.IllegalStateException:此响应已经被调用getOutputStream()-SpringBoot - java.lang.IllegalStateException: getOutputStream() has already been called for this response - SpringBoot 我得到一个异常:java.lang.IllegalStateException:已经为此响应调用了getOutputStream() - I am getting an exception: java.lang.IllegalStateException: getOutputStream() has already been called for this response 我正在获取java.lang.IllegalStateException:此响应已调用getOutputStream()异常 - I m getting java.lang.IllegalStateException: getOutputStream() has already been called for this response Exception Servlet - java.lang.IllegalStateException:已为此响应调用了getWriter() - Servlet - java.lang.IllegalStateException: getWriter() has already been called for this response
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM