当前位置: 首页 > 知识库问答 >
问题:

JAVAlang.IllegalStateException:已为此请求调用getInputStream()

师曦
2023-03-14

我有一个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

此服务生成以下异常:

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

我做了一些研究,表明不能在同一个请求上调用getReadergetInputStream。因此,似乎已经调用了一个getInputStream实例。如果我没有给它打个明确的电话,这怎么可能呢?为了解决这个问题,我使用了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();

使用这种方法,我如何使用字节的int来获取json?

共有2个答案

万俟沛
2023-03-14

我们只能从HttpServletRequest读取一次,所以在读取请求之前,我们必须在过滤器中使用HttpServletRequest estWrapper,并多次使用包装器进行后续调用。

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());
    }
 }
}

下面是我们在上面的过滤器中使用的包装器代码。

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()));
 }
}

现在将上述过滤器公开为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;
}
宇文温文
2023-03-14

似乎您缺少一个@消费注释。你意识到你可以有一个方法;

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

  //entity contains the posted content

}

不必自己读这条流?如果您有一个bean代表您使用的JSON,那么您可以将其添加为方法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

}

示例职位;

{
 "username" : "joe@example.com",
 "password" : "super s3cret"
}
 类似资料:
  • 我得到了以下错误:java。lang.IllegalStateException:在使用Struts2实现JSON时,已为此请求调用getInputStream()。例外情况: 请帮助我解决这个错误,因为我一直在解决这个问题。我没有什么问题:我已经实现了ServletRequestAware,并使用它来获取userLocale。它是否与JSONWriter对象冲突。

  • 问题内容: 我想将日志记录添加到Servlet中,因此我创建了Filter,该过滤器应显示请求并转到Servlet。但不幸的是,我遇到了例外: 因此,要解决此问题,我发现了Wrapper的解决方案,但它不起作用。我还能在代码中使用/更改什么?有任何想法吗? [MyHttpServletRequestWrapper] [MyFilter] 问题答案: 看起来restlet框架已经调用了Request

  • 我正在用Spring做一个项目,我有这个问题,我谷歌了错误信息,我找到了解决方案,甚至所有关于这个问题的帖子 有人能帮忙吗?

  • 问题内容: 我谷歌的错误消息 ,很多人说,这是因为后面的空格或换行,但在我的代码,没有一个空格或一个换行符。我在Linux上使用tomcat6。 根本原因 问题答案: 好的,你应该使用servlet而不是JSP,但是如果你确实需要…在页面顶部添加以下指令: 或者在jsp-config部分中,你的web.xml 此外flush/ close中OutputStream和返回完成时。

  • 我正在尝试使用以下代码段在浏览器中打开pdf文件: 我收到以下错误: 我还尝试使用以下方式关闭: 有人能帮我吗?

  • 我有一个包含表的JSP页面。加载页面时,将填充表。我还有一个每隔X秒的ajax调用,它必须刷新表内容。 加载时,按预期填充内容。但在ajax调用期间,它会失败,并出现以下错误: 我检查了这个问题上存在的问题,但没有什么好结果。我没有在代码中使用scriplets。 JSP代码: 控制器代码: