一、 第一种实现
  把一个JasperReports生成的PDF报告发送到用户浏览器的技巧在于,调用 net.sf.jasperreports.engine.JasperRunManager.runReportToPdf()方法。这个方法具有多个 重载版本,我们在本文中使用的这个版本具有三个参数:一个字符串—描述了编译的报告(jasper文件)的绝对路径;一个实现了 java.util.Map接口的类的实例;一个实现了net.sf.jasperreports.engine.JRDataSource接口的类的实 例。JasperRunManager.runReportToPdf()方法返回一个字节数组—它被作为一个参数传递给 javax.servlet.ServletOutputStream类的write()方法。我们可以从 javax.servlet.http.HttpServletResponse类的getOutputStream()方法中获得一个 ServletOutputStream的实例。事实胜于雄辩,下列代码片断展示了这一技术:

   
package net.ensode.jasperreportsbrowserdemo;
import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.HashMap;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import net.sf.jasperreports.engine.JREmptyDataSource;
import net.sf.jasperreports.engine.JRException;
import net.sf.jasperreports.engine.JasperRunManager;
public class JasperReportsBrowserDemoServlet extends HttpServlet
{
protected
void doGet(HttpServletRequest request,HttpServletResponse response)
throws ServletException,IOException
{
ServletOutputStream servletOutputStream
= response.getOutputStream();
File reportFile
= new File(getServletConfig().getServletContext()
.getRealPath(
" /reports/Simple_Report.jasper " ));
byte [] bytes = null ;
try {
bytes
= JasperRunManager.runReportToPdf(reportFile.getPath(),
new HashMap(), new JREmptyDataSource());
response.setContentType(
" application/pdf " );
response.setContentLength(bytes.length);
servletOutputStream.write(bytes,
0 ,bytes.length);
servletOutputStream.flush();
servletOutputStream.close();
}
catch (JRException e)
{
// 在浏览器中显示栈跟踪消息 StringWriter stringWriter = new StringWriter();
PrintWriter printWriter
= new PrintWriter(stringWriter);
e.printStackTrace(printWriter);
response.setContentType(
" text/plain " );
response.getOutputStream().print(stringWriter.toString());
}
}
}

    从前面的例子中可以看出,获得jasper文件绝对路径的最容易的方法是调用一个实现javax.servlet.ServletContext接口的类 实例的getRealPath()方法。对于本文中的简单示例来说,我们把一个java.util.HashMap空实例和一个 net.sf.jasperreports.engine.JREmptyDataSource实例作为另外两个参数传递给 JasperRunManager.runReportToPdf()方法。注意,对于更复杂的应用程序情况,一般在这些两个参数中传递一些数据。
二、 改进的方法
    尽管前一个示例能够按要求进行工作,但是,我们还可以进一步改进之。不是创建一个字节数组并把它传递给ServletOutputStream类的 write()方法,我们可以把PDF直接“流向”浏览器。为此,我们必须首先通过调用ServletContext中的 getResourceAsStream()方法以流形式得到编译的资源。这个方法返回一个java.io.InputStream的实例—我们可以把它 作为一个参数传递给JasperRunManager类的runReportToPdfStream()方法。下面示例展示了这一技术的使用:

   
package net.ensode.jasperreportsbrowserdemo;
// ……导入语句(省略)
public class JasperReportsBrowserDemoServlet2 extends HttpServlet
{
protected
void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException
{
ServletOutputStream servletOutputStream
= response.getOutputStream();
InputStream reportStream
= getServletConfig().getServletContext()
.getResourceAsStream(
" /reports/Simple_Report.jasper " );
try
{
JasperRunManager.runReportToPdfStream(reportStream, servletOutputStream,
new HashMap(), new JREmptyDataSource());
response.setContentType(
" application/pdf " );
servletOutputStream.flush();
servletOutputStream.close();
}
catch (JRException e)
{
// 处理异常
}
}
}


    与前一个示例相比,这里的两处主要改动都以加粗显示。当生成PDF报告时,JasperRunManager的runReportToPdfStream ()方法能够把PDF报告“流向”浏览器。通过这种方式,我们不必象前一个示例一样把一个字节数组存储在内存中。注意,当使用这种技术时,不能设置内容的 长度;因此,客户端不能与服务器保持一种持续性连接,但是这通常对于PDF来说并不重要,因为整个PDF本身是自包含的,而客户端一般不要求更多的信息。

三、 小结
  从本文提供的示例程序可知,把一个JasperReports生成的PDF报告发送到一个浏览器并不是一件困难的事情。类似技术还可以用于导出HTML,RTF,XLS或任何其它由JasperReports所支持的输出格式。