从请求读取时防止 IllegalStateException

发布于 2024-08-09 18:48:11 字数 957 浏览 5 评论 0原文

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

我所有的 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 时,它总是抛出 IllegalStateException。我如何“恢复”阅读器或如何以其他方式读取请求正文?

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

I have an interceptor for catching Exceptions and sending emails of this exceptions.

All my struts actions extend CoreController which implements SerlvetRequestAware.

In mail service class then I have:

CoreController cc = (CoreController)invocation.getAction();
HttpServletRequest request = cc.getRequest();

I want to insert request body to email, if exists. Like so:

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

Now it always throws an IllegalStateException, when reader is not null. How could I "revert" reader or how any other way to read the request body?

EDIT
Exception: getInputStream() has already been called for this request

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

dawn曙光 2024-08-16 18:48:11

如果您收到 IllegalStateException,也许您应该尝试使用请求的 InputStream 而不是其 Reader

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

Perhaps you should try using the request's InputStream rather than its Reader if you receive an IllegalStateException:

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();
夏九 2024-08-16 18:48:11

如果其他人已经读取了请求正文或者其他类型的读取器(在您的情况下为 InputStream)已被某人打开,您将收到该异常。

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

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

这意味着您可以在请求属性 exception 中找到异常。

You will get that exception if someone else has already read the request body or if the other kind of reader (in your case the InputStream) has been opened by someone.

My guess is that this happens in the code which parses the request. So at this stage, you can't read the request body anymore. Instead, you should check the field which contains the exception. Your struts config must contain this code somewhere:

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

This means you can find the exception in the request attribute exception.

酷到爆炸 2024-08-16 18:48:11

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

注意:包装 HttpServletRequest 和 HttpServletResponse 并不罕见(例如,请参见 Jetty 的 GzipFilter,特别是它的 GZIPResponseWrapper 类)。尽管更改请求对象(的行为)可能会影响其他过滤器或 servlet,但您应该小心地执行此操作。

If you want to read the request body more than once, you could add a Filter that wraps the original HttpServletRequest inside a custom implementation that supports multiple reads (e.g. by storing the request body into a byte array and creating a new ByteArrayInputStream for each call).

Note: Wrapping HttpServletRequest and HttpServletResponse isn't uncommon (see for instance Jetty's GzipFilter, especially its GZIPResponseWrapper class). You should do this carefully though as changing (the behavior of) the request object might affect other filters or servlets.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文