《轻量级J2EE企业应用实战》一书的第2章有一个使用SerlvetResponse输出图像的例子,代码如下:
<%
BufferedImageimage=newBufferedImage(400,400,BufferedImage.TYPE_INT_RGB);
Graphicsg=image.getGraphics();
g.fillRect(0,0,400,400);
g.setColor(newColor(255,0,0));
g.fillArc(20,20,100,100,30,120);
g.setColor(newColor(0,255,0));
g.fillArc(20,20,100,100,150,20);
g.setColor(newColor(0,0,255));
g.fillArc(20,20,100,100,270,120);
g.setColor(newColor(0,0,0));
g.drawString("red:climb",300,80);
g.drawString("green:swim",300,120);
g.drawString("blue:jump",300,160);
ImageIO.write(image,"bmp",response.getOutputStream());
//out.clear();
//out=pageContext.pushBody();
%>
在Tomcat下运行时抛出如下异常:

atorg.apache.catalina.connector.Response.getWriter(Response.java:601)
atorg.apache.catalina.connector.ResponseFacade.getWriter(ResponseFacade.java:196)
atorg.apache.jasper.runtime.JspWriterImpl.initOut(JspWriterImpl.java:125)
atorg.apache.jasper.runtime.JspWriterImpl.flushBuffer(JspWriterImpl.java:118)
atorg.apache.jasper.runtime.PageContextImpl.release(PageContextImpl.java:185)
atorg.apache.jasper.runtime.JspFactoryImpl.internalReleasePageContext(JspFactoryImpl.java:116)
atorg.apache.jasper.runtime.JspFactoryImpl.releasePageContext(JspFactoryImpl.java:76)
atorg.apache.jsp.pages.drawImage_jsp._jspService(drawImage_jsp.java:84)
atorg.apache.jasper.runtime.HttpJspBase.service(HttpJspBase.java:98)
atjavax.servlet.http.HttpServlet.service(HttpServlet.java:803)
atorg.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:328)
atorg.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:315)
atorg.apache.jasper.servlet.JspServlet.service(JspServlet.java:265)
atjavax.servlet.http.HttpServlet.service(HttpServlet.java:803)
atorg.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:269)
atorg.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:188)
atorg.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:210)
atorg.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:174)
atorg.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:127)
atorg.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:117)
atorg.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:108)
atorg.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:151)
atorg.apache.coyote.http11.Http11Processor.process(Http11Processor.java:870)
atorg.apache.coyote.http11.Http11BaseProtocol$Http11ConnectionHandler.processConnection(Http11BaseProtocol.java:665)
atorg.apache.tomcat.util.net.PoolTcpEndpoint.processSocket(PoolTcpEndpoint.java:528)
atorg.apache.tomcat.util.net.LeaderFollowerWorkerThread.runIt(LeaderFollowerWorkerThread.java:81)
atorg.apache.tomcat.util.threads.ThreadPool$ControlRunnable.run(ThreadPool.java:685)
atjava.lang.Thread.run(Thread.java:595)
查看转换后的JSP代码,发现第84行如下(绿色高亮处):
publicvoid_jspService(HttpServletRequestrequest,HttpServletResponseresponse)
throwsjava.io.IOException,ServletException{

JspFactory_jspxFactory=null;
PageContextpageContext=null;
HttpSessionsession=null;
ServletContextapplication=null;
ServletConfigconfig=null;
JspWriterout=null;
Objectpage=this;
JspWriter_jspx_out=null;
PageContext_jspx_page_context=null;


try{
_jspxFactory=JspFactory.getDefaultFactory();
response.setContentType("text/html;charset=UTF-8");
pageContext=_jspxFactory.getPageContext(this,request,response,
null,true,8192,true);
_jspx_page_context=pageContext;
application=pageContext.getServletContext();
config=pageContext.getServletConfig();
session=pageContext.getSession();
out=pageContext.getOut();
_jspx_out=out;

out.write("\r\n");
out.write("\n");
out.write("<!DOCTYPEhtmlPUBLIC\"-//W3C//DTDHTML4.01Transitional//EN\"\"http://www.w3.org/TR/html4/loose.dtd\">\n");
out.write("<html>\n");
out.write("<head>\n");
out.write("<metahttp-equiv=\"Content-Type\"content=\"text/html;charset=UTF-8\">\n");
out.write("<title>DrawImage</title>\n");
out.write("</head>\n");
out.write("<body>\n");
out.write("\r\n");

BufferedImageimage=newBufferedImage(400,400,BufferedImage.TYPE_INT_RGB);
Graphicsg=image.getGraphics();
g.fillRect(0,0,400,400);
g.setColor(newColor(255,0,0));
g.fillArc(20,20,100,100,30,120);
g.setColor(newColor(0,255,0));
g.fillArc(20,20,100,100,150,20);
g.setColor(newColor(0,0,255));
g.fillArc(20,20,100,100,270,120);
g.setColor(newColor(0,0,0));
g.drawString("red:climb",300,80);
g.drawString("green:swim",300,120);
g.drawString("blue:jump",300,160);
ImageIO.write(image,"bmp",response.getOutputStream());
//out.clear();
//out=pageContext.pushBody();

out.write("\r\n");
out.write("</body>\n");
out.write("</html>");
}catch(Throwablet){
if(!(tinstanceofSkipPageException)){
out=_jspx_out;
if(out!=null&&out.getBufferSize()!=0)
out.clearBuffer();
if(_jspx_page_context!=null)_jspx_page_context.handlePageException(t);
}
}finally{
if(_jspxFactory!=null)_jspxFactory.releasePageContext(_jspx_page_context);
}
}
我们看到在JSP页面释放资源的时候,调用了ServetResponse.getWriter()方法,之后程序即抛出异常了,查看Servlet的API发现问题:
解决方法如下:
将JSP页面的最后两行代码的注释去掉,这两行代码的作用如下:
out.clear():清空缓存的内容。
pageContext.pushBody():参考API
publicBodyContentpushBody()
<%
BufferedImageimage=newBufferedImage(400,400,BufferedImage.TYPE_INT_RGB);
Graphicsg=image.getGraphics();
g.fillRect(0,0,400,400);
g.setColor(newColor(255,0,0));
g.fillArc(20,20,100,100,30,120);
g.setColor(newColor(0,255,0));
g.fillArc(20,20,100,100,150,20);
g.setColor(newColor(0,0,255));
g.fillArc(20,20,100,100,270,120);
g.setColor(newColor(0,0,0));
g.drawString("red:climb",300,80);
g.drawString("green:swim",300,120);
g.drawString("blue:jump",300,160);
ImageIO.write(image,"bmp",response.getOutputStream());
//out.clear();
//out=pageContext.pushBody();
%>
在Tomcat下运行时抛出如下异常:

atorg.apache.catalina.connector.Response.getWriter(Response.java:601)
atorg.apache.catalina.connector.ResponseFacade.getWriter(ResponseFacade.java:196)
atorg.apache.jasper.runtime.JspWriterImpl.initOut(JspWriterImpl.java:125)
atorg.apache.jasper.runtime.JspWriterImpl.flushBuffer(JspWriterImpl.java:118)
atorg.apache.jasper.runtime.PageContextImpl.release(PageContextImpl.java:185)
atorg.apache.jasper.runtime.JspFactoryImpl.internalReleasePageContext(JspFactoryImpl.java:116)
atorg.apache.jasper.runtime.JspFactoryImpl.releasePageContext(JspFactoryImpl.java:76)
atorg.apache.jsp.pages.drawImage_jsp._jspService(drawImage_jsp.java:84)
atorg.apache.jasper.runtime.HttpJspBase.service(HttpJspBase.java:98)
atjavax.servlet.http.HttpServlet.service(HttpServlet.java:803)
atorg.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:328)
atorg.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:315)
atorg.apache.jasper.servlet.JspServlet.service(JspServlet.java:265)
atjavax.servlet.http.HttpServlet.service(HttpServlet.java:803)
atorg.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:269)
atorg.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:188)
atorg.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:210)
atorg.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:174)
atorg.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:127)
atorg.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:117)
atorg.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:108)
atorg.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:151)
atorg.apache.coyote.http11.Http11Processor.process(Http11Processor.java:870)
atorg.apache.coyote.http11.Http11BaseProtocol$Http11ConnectionHandler.processConnection(Http11BaseProtocol.java:665)
atorg.apache.tomcat.util.net.PoolTcpEndpoint.processSocket(PoolTcpEndpoint.java:528)
atorg.apache.tomcat.util.net.LeaderFollowerWorkerThread.runIt(LeaderFollowerWorkerThread.java:81)
atorg.apache.tomcat.util.threads.ThreadPool$ControlRunnable.run(ThreadPool.java:685)
atjava.lang.Thread.run(Thread.java:595)
查看转换后的JSP代码,发现第84行如下(绿色高亮处):
publicvoid_jspService(HttpServletRequestrequest,HttpServletResponseresponse)
throwsjava.io.IOException,ServletException{
JspFactory_jspxFactory=null;
PageContextpageContext=null;
HttpSessionsession=null;
ServletContextapplication=null;
ServletConfigconfig=null;
JspWriterout=null;
Objectpage=this;
JspWriter_jspx_out=null;
PageContext_jspx_page_context=null;

try{
_jspxFactory=JspFactory.getDefaultFactory();
response.setContentType("text/html;charset=UTF-8");
pageContext=_jspxFactory.getPageContext(this,request,response,
null,true,8192,true);
_jspx_page_context=pageContext;
application=pageContext.getServletContext();
config=pageContext.getServletConfig();
session=pageContext.getSession();
out=pageContext.getOut();
_jspx_out=out;
out.write("\r\n");
out.write("\n");
out.write("<!DOCTYPEhtmlPUBLIC\"-//W3C//DTDHTML4.01Transitional//EN\"\"http://www.w3.org/TR/html4/loose.dtd\">\n");
out.write("<html>\n");
out.write("<head>\n");
out.write("<metahttp-equiv=\"Content-Type\"content=\"text/html;charset=UTF-8\">\n");
out.write("<title>DrawImage</title>\n");
out.write("</head>\n");
out.write("<body>\n");
out.write("\r\n");
BufferedImageimage=newBufferedImage(400,400,BufferedImage.TYPE_INT_RGB);
Graphicsg=image.getGraphics();
g.fillRect(0,0,400,400);
g.setColor(newColor(255,0,0));
g.fillArc(20,20,100,100,30,120);
g.setColor(newColor(0,255,0));
g.fillArc(20,20,100,100,150,20);
g.setColor(newColor(0,0,255));
g.fillArc(20,20,100,100,270,120);
g.setColor(newColor(0,0,0));
g.drawString("red:climb",300,80);
g.drawString("green:swim",300,120);
g.drawString("blue:jump",300,160);
ImageIO.write(image,"bmp",response.getOutputStream());
//out.clear();
//out=pageContext.pushBody();
out.write("\r\n");
out.write("</body>\n");
out.write("</html>");
}catch(Throwablet){
if(!(tinstanceofSkipPageException)){
out=_jspx_out;
if(out!=null&&out.getBufferSize()!=0)
out.clearBuffer();
if(_jspx_page_context!=null)_jspx_page_context.handlePageException(t);
}
}finally{
if(_jspxFactory!=null)_jspxFactory.releasePageContext(_jspx_page_context);
}
}
我们看到在JSP页面释放资源的时候,调用了ServetResponse.getWriter()方法,之后程序即抛出异常了,查看Servlet的API发现问题:
public java.io.PrintWriter getWriter() throws java.io.IOException
- Returns a
PrintWriterobject that can send character text to the client. ThePrintWriteruses the character encoding returned bygetCharacterEncoding(). If the response's character encoding has not been specified as described ingetCharacterEncoding(i.e., the method just returns the default valueISO-8859-1),getWriterupdates it toISO-8859-1.Calling flush() on the
PrintWritercommits the response.Either this method or
getOutputStream()may be called to write the body, not both. -
- Returns:
- a
PrintWriterobject that can return character data to the client
Throws:
-
UnsupportedEncodingException- if the character encoding returned bygetCharacterEncodingcannot be used java.lang.IllegalStateException-
java.io.IOException- if an input or output exception occurred
See Also:
-
getOutputStream(),setCharacterEncoding(java.lang.String)
- a
解决方法如下:
将JSP页面的最后两行代码的注释去掉,这两行代码的作用如下:
out.clear():清空缓存的内容。
pageContext.pushBody():参考API
publicBodyContentpushBody()
- Return a new BodyContent object, save the current "out" JspWriter, and update the value of the "out" attribute in the page scope attribute namespace of the PageContext.
- Returns:
- the new BodyContent
·返回一个新的BodyContent(代表一个HTML页面的BODY部分内容)
·保存JspWriter实例的对象out
·更新PageContext的out属性的内容
本文探讨了在使用JSP页面时,ServletResponse的getWriter()方法与PrintWriter方法同时调用引发异常的原因,并提供了相应的解决方案。通过分析API文档,解释了为何在释放资源时不应同时使用这两个方法来输出内容,以及如何正确地避免此异常。
1983

被折叠的 条评论
为什么被折叠?



