gpt4 book ai didi

servlets - 在 servlet 过滤器中创建错误页面会导致错误 "Writer already obtained"

转载 作者:行者123 更新时间:2023-12-04 12:02:05 24 4
gpt4 key购买 nike

我正在为大量 JSF 1.x 和 2.x 应用程序创建一个自定义框架(类似于门户)。为此,我创建了一个 servlet 过滤器,用框架菜单、面包屑、注销等“丰富”应用程序 HTML。在该过滤器中,我读取应用程序的 HTML,修改它并将其写入输出流。到目前为止,一切都很好,但现在我在创建自定义错误页面时遇到了问题。
我试图读取响应状态代码,并基于该代码,我正在创建输出 HTML:

public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
HttpServletRequest req = (HttpServletRequest) req;
HttpServletResponse res = (HttpServletResponse) resp;
StringServletResponseWrapper responseWrapper = new StringServletResponseWrapper(res);
// Invoke resource, accumulating output in the wrapper.
chain.doFilter(req, responseWrapper);
String contentType = res.getContentType();
byte[] data;
if (contentType.contains("text/html")) {
String html = null;
int statusCode = res.getStatus();
LOG.debug("status: {}, committed: {}", statusCode, res.isCommitted());

if (statusCode != 200) {
html = "<!DOCTYPE html>\r\n" +
"<html xmlns=\"http://www.w3.org/1999/xhtml\">\r\n" +
"<head>\r\n" +
"<script type=\"text/javascript\" src=\"/path/to/jquery/jquery-1.11.1.min.js\"></script>\r\n" +
"<title>Error</title>\r\n" +
"</head>\r\n" +
"<body>\r\n" +
"<h1>Error</h1>\r\n" +
"</body>\r\n" +
"</html>";
Collection<String> headerNames = res.getHeaderNames();
Map<String, String> headerMap = new HashMap<String, String>();
for (String header : headerNames) {
headerMap.put(header, res.getHeader(header));
}
res.reset();
for (Map.Entry<String,String> entry : headerMap.entrySet()) {
res.setHeader(entry.getKey(), entry.getValue());
}
res.setStatus(statusCode);
response.setContentType("text/html");
} else {
html = responseWrapper.getCaptureAsString();
}

if (ObjectUtils.isNotEmpty(html)) {
// do some modification
String modifiedResponse = doModification(html);
data = modifiedResponse.getBytes("UTF-8");
response.setContentLength(data.length);
response.getOutputStream().write(data); // this line causes error
}
} else {
data = responseWrapper.getCaptureAsBytes();
response.setContentLength(data.length);
response.getOutputStream().write(data);
}
}
如果状态代码等于 200(else 子句),此代码可以正常工作,但是当它不等于 200(我触发了 404 错误)时,会出现以下错误:
com.ibm.ws.webcontainer.webapp.WebApp logServletError SRVE0293E: [Servlet Error]-[Faces Servlet]: java.lang.IllegalStateException: SRVE0209E: Writer already obtained
我真的不明白为什么会出现这个错误。两种情况之间的唯一区别是在两种情况下都有效的 HTML 内容。有什么帮助吗?
使用 Websphere 应用程序服务器 8.5.5.18。
编辑:我试过打电话 reset()然后再次设置标题和状态代码,但是 reset()调用导致 IllegalStateException - 如 javadoc 中所述,显然响应已经提交。据我了解, flush() ServletOutputStream的方法可能会导致提交响应,但我不会在任何地方调用它。我还添加了一些日志来查看是否真的提交了响应。在这两种情况下(状态 200 和 404) response.isCommitted()返回真。这是否意味着在调用 doFilter 之前提交了响应?

最佳答案

选项 1 - 降级 JAX-RS to 1.1

Once JAX-RS version is changed back to 1.1 the errors in SystemOut.log will not be shown.


Do the following steps:


  1. Change the JAX-RS version to 1.1 using WAS 9 Admin console. See the detailed instructions athttps://www.ibm.com/support/knowledgecenter/SSEQTP_9.0.0/com.ibm.websphere.base.doc/ae/twbs_jaxrs_coexist_adminconsole.html

选项 2 - 移动 chain.doFilter到最后你的 doFilter method
   chain.doFilter(req, resp);
}

选项 3 - 删除 PrintWriter or OuputStream 的其他用法

Review application to determine if both PrintWriter and OuputStream were obtained. Modify the failing servlet/JSP to only obtain one or the other.

关于servlets - 在 servlet 过滤器中创建错误页面会导致错误 "Writer already obtained",我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66991601/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com