Java 从请求读取时防止IllegalStateException

Java 从请求读取时防止IllegalStateException,java,rest,struts2,request,Java,Rest,Struts2,Request,我有一个拦截器,用于捕获异常并发送此异常的电子邮件 我所有的struts操作都扩展了CoreController,它实现了SerlvetRequestAware 在邮件服务类中,我有: CoreController cc = (CoreController)invocation.getAction(); HttpServletRequest request = cc.getRequest(); 我想在电子邮件中插入请求正文(如果存在)。像这样: StringWriter msg = new S

我有一个拦截器,用于捕获异常并发送此异常的电子邮件

我所有的struts操作都扩展了CoreController,它实现了SerlvetRequestAware

在邮件服务类中,我有:

CoreController cc = (CoreController)invocation.getAction();
HttpServletRequest request = cc.getRequest();
我想在电子邮件中插入请求正文(如果存在)。像这样:

StringWriter msg = new StringWriter();
msg.write("Requested URI: " + request.getRequestURI()+NEW_LINE);
msg.write("Requested Query String: " + request.getQueryString()+NEW_LINE);
msg.write("Request method: "+request.getMethod()+NEW_LINE);
try {
 if (request.getReader() != null) {
  msg.write("Request body: "+ request.getReader().readLine()+NEW_LINE);
  request.getReader().close();
 }
} catch (IOException e) {
    e.printStrackTrace();
} catch(IllegalStateException e) {
    e.printStrackTrace();
}
现在,当reader不为null时,它总是抛出一个非法状态异常。如何“还原”读卡器,或者如何以其他方式读取请求正文

编辑
异常:已为此请求调用getInputStream()

如果收到
非法状态异常
,您可能应该尝试使用请求的
输入流
,而不是其
读取器

BufferedReader bufferedReader;
try {
    bufferedReader = request.getReader();
} catch (IllegalStateException e) {
    InputStream inputStream = request.getInputStream();

    // As per BalusC's comment:
    String charsetName = request.getCharacterEncoding();
    if (charsetName == null) {
        charsetName = "UTF-8";
    }

    InputStreamReader inputStreamReader = new InputStreamReader(inputStream, charsetName);
    bufferedReader = new BufferedReader(inputStreamReader);
}

bufferedReader.readLine();

如果其他人已经读取了请求正文,或者其他类型的读取器(在您的例子中是InputStream)已经被其他人打开,您将得到该异常

我猜这是在解析请求的代码中发生的。所以在这个阶段,您不能再读取请求主体了。相反,您应该检查包含异常的字段。struts配置必须包含以下代码:

<exception
  key="exception"
  path="/UserExists.jsp"
  type="java.lang.Exception"/>


这意味着您可以在请求属性
exception

中找到异常。如果您想多次读取请求正文,可以添加一个过滤器,将原始HttpServletRequest封装在支持多次读取的自定义实现中(例如,将请求正文存储到字节数组中,并为每个调用创建一个新的ByteArrayInputStream)


注意:包装HttpServletRequest和HttpServletResponse并不少见(例如,请参阅,尤其是其GZIPResponseWrapper类)请求对象可能会影响其他筛选器或servlet。

请发布异常消息并进行跟踪。除了简单的猜测之外,只有异常类型没有太多工作要做。如果IllegalArgumentException确实是由调用读取器而不是InputStream引起的,并且topicstarter会选择此解决方案,请保留c记住字符编码。最好使用从request.getCharacterEncoding()获得的字符集构造InputStreamReader,否则您将在使用“unicode”时遇到麻烦。我尝试了此操作,但值为null(但我在请求正文中发送它)@Trick:如果为空,请使用UTF-8。感谢您的帮助,我在第一次尝试时尝试了此方法,但它仍然为空…还有其他想法吗?)@Trick:由
getCharacterEncoding()
返回的值应该在
内容类型
HTTP头中指定。例如:
内容类型:text/plain;charset=UTF-8
我不明白这一点。我只做REST调用,所以我没有任何jsp文件将其转发到那里。我通过拦截器获取异常。