我正在 Tomcat 7 环境中使用 Java 访问 Oracle 9 数据库。
在context.xml中我有
<Resource type="javax.sql.DataSource" auth="Container"
name="jdbc/myDB"
factory="org.apache.tomcat.jdbc.pool.DataSourceFactory"
driverClassName="oracle.jdbc.OracleDriver"
url="jdbc:oracle:thin:@localhost:1521:db" maxwait="10000"
username="temp" password="temp" maxActive="20" maxIdle="10"/>
我的java代码大部分时间都可以工作,但有时我会随机得到Stream Closed异常。我怀疑这可能是因为用户按下应用程序中的按钮太快,从而在完成另一个查询之前启动一个查询。
此异常是由以下代码中的 doEndTag 函数引起的。
public class SQLIteratorTag extends BodyTagSupport
{
public SQLIteratorTag()
{
query = "";
rs = null;
stmt = null;
rsmd = null;
dbConn = null;
con = null;
}
public int doStartTag()
throws JspTagException
{
String fieldName = "";
try
{
DBConnection d=DBConnection.getInstance();
con = d.getConnection();
...
public int doAfterBody()
throws JspException
{
try
{
....
public int doEndTag()
throws JspException
{
try
{
if(bodyContent != null)
{
bodyContent.writeOut(bodyContent.getEnclosingWriter());
}
}
catch(IOException ex)
{
Log.getIns
我不想发布太多代码,但我可能发布的代码太少了。我不知道问题出在哪里,但如果有必要我会更新问题。
异常本身是:
SEVERE: Servlet.service() for servlet [jsp] in context with path [/charm] threw exception [javax.servlet.ServletException: javax.servlet.jsp.JspTagException: Stream closed] with root cause
javax.servlet.jsp.JspTagException: Stream closed
at c.tags.sql.SQLIteratorTag.doEndTag(SQLIteratorTag.java:218)
at org.apache.jsp.comp_005fpara_jsp._jspService(comp_005fpara_jsp.java:708)
at org.apache.jasper.runtime.HttpJspBase.service(HttpJspBase.java:70)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:722)
at org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:432)
at org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:390)
at org.apache.jasper.servlet.JspServlet.service(JspServlet.java:334)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:722)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:305)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
at com.jspbook.GZIPFilter.doFilter(Unknown Source)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:243)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:224)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:169)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:472)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:168)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:98)
at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:927)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:407)
at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:987)
at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:579)
at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:309)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1110)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:603)
at java.lang.Thread.run(Thread.java:722)
最佳答案
从堆栈跟踪来看,这似乎与数据库连接无关,但看起来确实与用户从后端提交两个请求有关。我已经更改了标签,但您可能需要稍微改一下问题的措辞并更改标题以获得更多关注。
本质上,您的应用程序接收两个请求,并处理它们。我已经有一段时间没有看到这个了,但据我记得第一个出现此错误是因为浏览器关闭了 TCP/IP 连接以便为第二个请求打开一个新连接。 (这对于 HTTP/1.1 来说可能有点简单,因为它重用了连接)。
我认为我们通过在页面生成时隐藏唯一标识符来解决这个问题,然后检测我们是否在同一 session 上收到具有该 UID 的第二个 POST 请求 - 表明他们已提交两次。不过那是不久前的事了,所以我对我们到底做了什么以及我们如何阻止它对用户可见感到相当模糊;我记得我们将第二个请求的 HttpServletRequest 包装在 HttpServletRequestWrapper 中,这似乎将请求从 POST 更改为 GET,但我必须进行一些挖掘才能弄清楚发生了什么。
编辑: This link已经很老了,但似乎有比我能拖起来的任何古老的东西更好的方法来处理它(这似乎本质上是该帖子中的选项2)。可能有几种常见的方法可以解决这个问题。
关于java - "Stream Closed"显然是由多次提交引起的错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9499535/