Сервлет Jasper Reports перестал работать после вызова response.getOutputStream () - PullRequest
2 голосов
/ 29 августа 2011

У меня есть код, такой как ниже.Программа перестала работать на линии 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>

Ответы [ 2 ]

5 голосов
/ 29 августа 2011

Смотрите здесь:

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

Вы получаете оба Writer и OutputStream из ответа. Это не разрешено Прочитайте их Javadocs:

getOutputStream ()

ServletOutputStream getOutputStream() throws java.io.IOException

Возвращает ServletOutputStream, подходящий для записи двоичных данных в ответе. Контейнер сервлета не кодирует двоичные данные.

Вызов flush() на ServletOutputStream фиксирует ответ. Либо этот метод, либо getWriter() может быть вызван для написания тела, но не обоих.

и

getWriter ()

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

Возвращает объект PrintWriter, который может отправлять текстовый символ клиенту. PrintWriter использует кодировку символов, возвращаемую getCharacterEncoding(). Если кодировка символа ответа не была указана, как описано в getCharacterEncoding (т.е. метод просто возвращает значение по умолчанию ISO-8859-1), getWriter обновляет его до ISO-8859-1.

Вызов flush() на PrintWriter фиксирует ответ.

Либо этот метод, либо getOutputStream() может быть вызван для записи тела, но не обоих.

(акцент мой)

Проблема в вашем конкретном случае гораздо больше. Вы пытаетесь встроить PDF-результат отчета Jasper между этими HTML-тегами в HTML-ответе. Я не уверен, что вы думали или курили, когда писали код, но это определенно не сработает. Вам нужно переписать сервлет таким образом, чтобы он only возвращал PDF, а не эту кучу HTML-шума. Вы должны переместить весь этот HTML из сервлета в какой-нибудь файл JSP. Затем вы можете вызвать этот сервлет по простой ссылке для скачивания в JSP

<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 в браузере, и веб-браузер позаботится о том, чтобы сервлет вызывался и чтобы PDF-файл отображался так, как вы хотели.

Ваша другая проблема в том, что обработка исключений не очень хороша. Таким образом, вы ничего не увидите, поскольку буфер ответов не был сброшен. Вместо этого вы должны делать

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

, поскольку контейнер прекрасно знает, как обрабатывать исключения.

То, что и ваши doGet() и doPost() делают точно так же, это, кстати, и запах дизайна. Драйвер JDBC, который вы там использовали, полностью устарел и устарел. То, как вы зарегистрировали драйвер, неуклюже. То, что соединение с БД не закрыто в finally, подвержено утечке ресурсов. Хорошо, я остановлюсь ...

0 голосов
/ 29 августа 2011

Я предполагаю, что вы получаете IllegalStateException, потому что вы звоните getWriter() и getOutputStream() по одному и тому же ответу.Что вы не можете делать.

...