我有一个用于捕获异常并发送此例外电子邮件的拦截器。
我的所有struts动作都扩展了实现SerlvetRequestAware的CoreController。
在邮件服务类中,我有:
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()
答案 0 :(得分:3)
如果您收到InputStream
,或许您应该尝试使用请求的Reader
而不是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();
答案 1 :(得分:1)
如果其他人已经阅读了请求正文,或者其他类型的阅读器(在您的情况下是InputStream)已被某人打开,您将获得该异常。
我的猜测是,这会发生在解析请求的代码中。因此,在此阶段,您无法再阅读请求正文。相反,您应该检查包含异常的字段。你的struts配置必须包含这个代码:
<exception
key="exception"
path="/UserExists.jsp"
type="java.lang.Exception"/>
这意味着您可以在请求属性exception
中找到例外。
答案 2 :(得分:0)
如果您想多次读取请求主体,可以添加一个Filter,它将原始HttpServletRequest包装在支持多次读取的自定义实现中(例如,通过将请求主体存储到字节数组中并为其创建新的ByteArrayInputStream每次电话会议。)
注意:包装HttpServletRequest和HttpServletResponse并不罕见(例如参见Jetty's GzipFilter,尤其是其GZIPResponseWrapper类)。尽管请求对象的更改(行为)可能影响其他过滤器或servlet,但您应该小心这样做。