iReport 筆記(三) 使用JavaBean集合作爲數據源

 

使用JDBC作爲報表數據源其實是有很多缺陷的,例如,它要求使用SQL查詢作爲數據來源,但有時報表的內容並不能由一條SQL語句完成。因此,使用JavaBean集合作爲數據源纔是終極的解決之道,用戶只需要將數據整理到一個JavaBean集合之中就可以了,無論用什麼方法,數據源爲何物。

3.1 定義Bean

定義一個最簡單的Bean,只包含一個屬性,如下所示:

 

package lld.test.ireport;

public class ProductBean
{
    
private String productName;

    
public String getProductName()
    
{
        
return productName;
    }


    
public void setProductName(String productName)
    
{
        
this.productName = productName;
    }

}

3.2 在iReport中設定數據源及創建報表

要在iReport中使用JavaBean作爲數據源,首先要定義好Classpath,以使iReport能夠找到我們定義的Bean,使用菜單“Options”-“Classpath”定義Classpath,定義的路徑爲編譯後的.class文件所在路徑,例如,我定義的Classpath爲“D:/Work/Java/ireport_test/WebContent/WEB-INF/classes”。

在菜單“Data”-“Connections/Datasources”菜單中,添加數據源,將數據源類型設爲“JavaBeans set data source”,設定的數據源屬性如下圖所示:

按道理而言,上圖中的“Factory class”和 “The static method to call to retrieve the array or the collection of javaBeans”中,應該填寫相應的工廠類及方法,然後,我們就能夠在iReport集成環境中測試輸出結果,但就我測試結果而言,發現在我賦上實際的工廠類後,按下Test按鈕後,總是提示“The method doen't return a valid array or java.util.Collection”。所以,我們就只把iReport作爲一個報表編輯器好了,不要對它報太大奢望,畢竟不花錢,有點bug(或者是我豬頭沒找對方法)也就原諒一下了。

將其設爲當前數據源,然後到菜單“Data”-“Report Query”中定義需要用到的 Bean屬性,在“Class name”中輸入自定義Bean的名稱,本例中爲“lld.test.ireport.ProductBean”,然後點擊“Read attributes”按鈕,獲取Bean屬性,點擊“Add Selected Field(s)”添加要用的屬性,如下圖所示:

秉承本人所作筆記的一貫風格,只作最主要的功能描述,用最簡單的代碼描述最核心的功能,因此定義的報表非常之簡單,各位如果有興趣的話,可以加上邊框線之類的美化元素,如下圖所示:

該文件名爲report_2.jrxml,編譯即可獲取report_2.jasper

3.3 編程導出PDF

對於Web應用,以PDF格式導出報表是最常見的應用,另外如果是使用C/S模式的話,還可以導出來JRViewer格式。至於其它格式,例如Excel、HTML、Java2D圖形等,基本上是自找麻煩,因爲導出來的格式很難看,用戶會有意見,不如自己去手工生成的好。

對於JavaBean集合,最終仍然要轉化成爲JRDataSource以供JasperReport使用,不過這個轉換很簡單,一行代碼即足夠,示例代碼如下所示:

List<?> data = new ArrayList<?>();

...(填充數據)

//生成JRDataSource
JRDataSource dataSource = new JRBeanCollectionDataSource(data);

下面的代碼是一個生成PDF的完整示例(Servlet):

package lld.test.ireport;

import java.io.IOException;
import java.io.OutputStream;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.List;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import net.sf.jasperreports.engine.JRDataSource;
import net.sf.jasperreports.engine.JRExporterParameter;
import net.sf.jasperreports.engine.JasperFillManager;
import net.sf.jasperreports.engine.JasperPrint;
import net.sf.jasperreports.engine.JasperReport;
import net.sf.jasperreports.engine.data.JRBeanCollectionDataSource;
import net.sf.jasperreports.engine.export.JRPdfExporter;
import net.sf.jasperreports.engine.util.JRLoader;
import net.sf.jasperreports.j2ee.servlets.BaseHttpServlet;

public class BeanReportServlet extends HttpServlet
{
    
private static final long serialVersionUID = 348226870594216833L;

    @Override
    
protected void doGet(HttpServletRequest req, HttpServletResponse resp)
            
throws ServletException, IOException
    
{
        
this.doPost(req, resp);
    }


    @Override
    
protected void doPost(HttpServletRequest req, HttpServletResponse resp)
            
throws ServletException, IOException
    
{
        
try
        
{
            
//生成測試數據
            ArrayList<ProductBean> data = new ArrayList<ProductBean>();
            
for(int i = 1; i <= 100; i++)
            
{
                ProductBean bean 
= new ProductBean();
                bean.setProductName(
"Product " + i);
                data.add(bean);
            }

            JRDataSource dataSource 
= new JRBeanCollectionDataSource(data);
            
            
//獲取報表模板文件
            String root_path = this.getServletContext().getRealPath("/");
            root_path 
= root_path.replace('/''/');
            String reportFilePath 
= root_path + "WEB-INF/classes/lld/test/ireport/report_2.jasper";
            System.out.println(
"jasper file is " + reportFilePath);
            
            
//生成JasperPrint
            JasperReport report = (JasperReport)JRLoader.loadObject(reportFilePath);
            JasperPrint jasperPrint 
= JasperFillManager.fillReport(report, null, dataSource);

            
//設定輸出格式
            OutputStream ouputStream = resp.getOutputStream();  
            resp.setContentType(
"application/pdf");
            resp.setCharacterEncoding(
"UTF-8");  
            resp.setHeader(
"Content-Disposition""attachment; filename=""  
                    
+ URLEncoder.encode("PDF報表""UTF-8"+ ".pdf"");  
                    
            
// 使用JRPdfExproter導出器導出pdf  
            JRPdfExporter exporter = new JRPdfExporter();  
            
// 設置JasperPrintList  
            exporter.setParameter(JRExporterParameter.JASPER_PRINT, jasperPrint);  
            exporter.setParameter(JRExporterParameter.OUTPUT_STREAM, ouputStream);  
            exporter.exportReport();
            
            ouputStream.close();  
        }
 catch (Exception e)
        
{
            e.printStackTrace();
        }
    
    }


}

在上例中,我生成數據源的方式很簡單,只是順序成生了100個ProductBean對象。

JasperReport生成報表時使用的參數傳遞方式比較奇怪,它不是使用常規的函數參數傳遞方式,而是需要調用相應Exporter對象的setParameter方法,設定各個參數值,怎一個BT了得,莫非是爲了配合它的文檔收費計劃?

實話實說,上例中的好多代碼也是從網上copy來的,在些感謝各位在網上無私奉獻的同仁。

3.4 報表生成方式

目前我知道兩種報表的生成方式,一種是使用JRPdfExporter對象,上面的例子即是使用的該方法,還有一種方法是使用JasperRunManager對象,示例代碼如下所示:

byte[] bytes = JasperRunManager.runReportToPdf(reportFilePath, null, dataSource);
outputStream.write(bytes, 
0, bytes.length);
outputStream.close();  
發佈了54 篇原創文章 · 獲贊 1 · 訪問量 8萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章