java - Jasper Reports servlet 在调用 response.getOutputStream() 后停止工作

标签 java servlets jasper-reports

我有如下代码。程序在 servletOutputStream = response.getOutputStream(); 行停止工作。我不知道如何解决这个问题?有人可以帮我解决这个问题吗?

protected void processRequest(HttpServletRequest request, HttpServletResponse response)
        throws ServletException, IOException, SQLException, JRException, ParserConfigurationException, SAXException {
    response.setContentType("text/html;charset=UTF-8");
    PrintWriter out = response.getWriter();
    try {

        out.println ("<html>");
        out.println ("    <head>");
        out.println ("        <meta http-equiv='Content-Type' content='text/html; charset=UTF-8'>");
        out.println ("        <title>JSP Page</title>");
        out.println ("    </head>");
        out.println ("    <body>");
        out.println ("        <h1>Hello iReport!</h1>");

        String resourceName = "D:/classic.jrxml";         
        response.setContentType("application/pdf");
        ServletOutputStream servletOutputStream = null;
        servletOutputStream = response.getOutputStream(); // <--
        InputStream reportStream = getServletConfig().getServletContext().getResourceAsStream(resourceName);
        try {
                Driver driver = new org.gjt.mm.mysql.Driver();
                DriverManager.registerDriver(driver);
                String conString = "jdbc:mysql://localhost:3306/quanlynhasach";
                Properties info = new Properties(); 
                info.setProperty("characterEncoding", "utf8");
                info.setProperty("user", "root"); 
                info.setProperty("password", ""); 
                Connection con =  DriverManager.getConnection(conString, info);               
                JasperRunManager.runReportToPdfStream(reportStream, servletOutputStream,new HashMap<Object, Object>(), con);
                con.close();

        }catch(Exception e){
            StringWriter stringWriter = new StringWriter();
            PrintWriter printWriter = new PrintWriter(stringWriter);
             e.printStackTrace(printWriter);
            response.setContentType("text/plain");
            response.getOutputStream().print(stringWriter.toString());
        }
        out.println ("    </body>");
        out.println ("</html>");

    } finally {     

        out.close();
    }
}  // <editor-fold defaultstate="collapsed" desc="HttpServlet methods. Click on the + sign on the left to edit the code.">
/** 
 * Handles the HTTP <code>GET</code> method.
 * @param request servlet request
 * @param response servlet response
 * @throws ServletException if a servlet-specific error occurs
 * @throws IOException if an I/O error occurs
 */
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
        throws ServletException, IOException {
    try {
        try {
            processRequest(request, response);
        } catch (ParserConfigurationException ex) {
            Logger.getLogger(iReport.class.getName()).log(Level.SEVERE, null, ex);
        } catch (SAXException ex) {
            Logger.getLogger(iReport.class.getName()).log(Level.SEVERE, null, ex);
        }
    } catch (SQLException ex) {
        Logger.getLogger(iReport.class.getName()).log(Level.SEVERE, null, ex);
    } catch (JRException ex) {
        Logger.getLogger(iReport.class.getName()).log(Level.SEVERE, null, ex);
    }
}

/** 
 * Handles the HTTP <code>POST</code> method.
 * @param request servlet request
 * @param response servlet response
 * @throws ServletException if a servlet-specific error occurs
 * @throws IOException if an I/O error occurs
 */
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response)
        throws ServletException, IOException {
    try {
        try {
            processRequest(request, response);
        } catch (ParserConfigurationException ex) {
            Logger.getLogger(iReport.class.getName()).log(Level.SEVERE, null, ex);
        } catch (SAXException ex) {
            Logger.getLogger(iReport.class.getName()).log(Level.SEVERE, null, ex);
        }
    } catch (SQLException ex) {
        Logger.getLogger(iReport.class.getName()).log(Level.SEVERE, null, ex);
    } catch (JRException ex) {
        Logger.getLogger(iReport.class.getName()).log(Level.SEVERE, null, ex);
    }
}

/** 
 * Returns a short description of the servlet.
 * @return a String containing servlet description
 */
@Override
public String getServletInfo() {
    return "Short description";
}// </editor-fold>

最佳答案

看这里:

PrintWriter out = response.getWriter();
// *snip*
servletOutputStream = response.getOutputStream();

您将两者 WriterOutputStream从响应中。这是不允许的。阅读他们的 javadoc:

getOutputStream()

ServletOutputStream getOutputStream() throws java.io.IOException

Returns a ServletOutputStream suitable for writing binary data in the response. The servlet container does not encode the binary data.

Calling flush() on the ServletOutputStream commits the response. Either this method or getWriter() may be called to write the body, not both.

getWriter()

java.io.PrintWriter getWriter() throws java.io.IOException

Returns a PrintWriter object that can send character text to the client. The PrintWriter uses the character encoding returned by getCharacterEncoding(). If the response's character encoding has not been specified as described in getCharacterEncoding (i.e., the method just returns the default value ISO-8859-1), getWriter updates it to ISO-8859-1.

Calling flush() on the PrintWriter commits the response.

Either this method or getOutputStream() may be called to write the body, not both.

(强调我的)

问题是在你的具体情况下,但要大得多。您正在尝试将 Jasper Report 的 PDF 结果内联到 HTML 响应中的这些 HTML 标记之间。我不确定你在编写代码时的想法或想法,但这绝对行不通。您需要以这种方式重写 servlet,以便它返回 PDF,而不是一堆 HTML 噪音。您应该将所有 HTML 从 servlet 移出到某个 JSP 文件中。然后,您可以通过 JSP 中的简单下载链接来调用该 servlet

<a href="yourServletUrl">Download PDF</a>

或在 <iframe> 内(是的,在 JSP 中)

<iframe src="yourServletUrl" style="width: 500px; height: 300px;"></iframe>

或在<object>中(也在这里,只是在 JSP 中)

<object data="yourServletUrl" type="application/pdf" width="500" height="300" />

只需将该 HTML 放入 JSP 页面中,在浏览器中打开 JSP,Web 浏览器就会负责调用 servlet,并且 PDF 将按照您想要的方式表示。

你的另一个问题是异常处理不是很好。由于响应缓冲区未重置,因此您将完全看不到任何内容。你应该做的是

} catch (Exception e) {
    throw new ServletException("descriptive message here", e);
}

因为容器完全知道如何处理异常。

您的doGet()doPost()正在做完全相同的事情,顺便说一下,还有一种设计的味道。您在那里使用的 JDBC 驱动程序已完全过时且已弃用。您注册驱动程序的方式很笨拙。 finally中数据库连接未关闭很容易出现资源泄漏。好吧,我就停下来了……

关于java - Jasper Reports servlet 在调用 response.getOutputStream() 后停止工作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7225367/

相关文章:

java - 如何在 JPQL 中按 SUM() 排序

java - 当我们可以使用 Set 来添加唯一值时,为什么还要使用 ArrayList?

java - 为什么会发生这种字符转换?

java - Ajax 调用不起作用

grails - 如何在为 grails 2.4.4 版本添加 jasper :1. 11.0 插件时解决 Itext 问题

ms-word - 我可以使用 Microsoft Word 文件作为 JasperReports 的报告模板吗?

java - 如何在方法声明中使用类型参数而不是类

Java Regular Expression ReplaceAll with Regex 结果修剪定界符前后的空白

java - @WebServlet 注释和 GWT RPC

charts - 如何使用 JavaBeans 集合数据集填充图表数据?