UReport2 報表存儲與數(shù)據(jù)源配置

2022-12-30 13:38 更新
UReport2教學(xué)視頻
http://pan.baidu.com/s/1boWTxF5,密碼:98hj

UReport商業(yè)版BaskReport已推出,采出全新算法,全新設(shè)計器,實現(xiàn)百萬條數(shù)據(jù)秒級加載, 價格低至1000/年,詳見:https://www.basksoft.com  


報表存儲目錄配置

       在第二小節(jié)中,我們介紹如何搭建一個包含UReport2的項目,在運行項目后,我們發(fā)現(xiàn)在項目的WEB-INF目錄有會自動生成了一個名為“ureportfiles”目錄,這個目錄是UReport2提供的默認的報表文件存儲目錄,也就是說默認情況下,UReport將在項目的WEB-INF/ureportfiles目錄下存儲設(shè)計好的報表文件。

默認報表存儲目錄
如果您的項目在Eclipse的開發(fā)環(huán)境運行時,采用的是jetty(比如run-jetty-run插件),那么就可以在項目的WEB-INF目錄下發(fā)現(xiàn)一個名為“ureportfiles”目錄。
但如果你采用tomcat運行項目,那么在WEB-INF目錄下就沒有一個名為“ureportfiles”目錄,原因是在Eclipse中運行tomcat,tomcat需要創(chuàng)建一個臨時的工作目錄(該目錄一般位于workspace\.metadata\.plugins\org.eclipse.wst.server.core\tmp0\wtpwebapps\下),所以采用tomcat運行項目,則需要到這個臨時的工作目錄下找到對應(yīng)的項目,再到這個項目的WEB-INF目錄下找到對應(yīng)的“ureportfiles”目錄。

運行我們搭建好的項目,打開報表設(shè)計器,點擊工具欄上的保存按鈕(),選擇“保存”,可以看到如下圖所示的彈出窗口:

save-dialog\

  在這個窗口,我們只要輸入報表名稱,同時再選擇報表的存儲目的地就,可以保存當(dāng)前報表文件??梢钥吹?,UReport2默認給我們提供的存儲目的地是“服務(wù)器文件系統(tǒng) ”,實際上就是我們項目中WEB-INF目錄下的“ureportfiles”目錄,這個目錄是系統(tǒng)默認自動生成的,如果需要我們可以添加一個屬性來更改這個目錄位置。

       在我們項目的WEB-INF目錄下創(chuàng)建一個名為config.properties,打開位于WEB-INF下名為context.xml的spring配置文件,在其中添加如下Bean以加載這個config.properties文件(如果我們的項目中已有自己的Properties文件,那么直接在這個Properties文件中配置即可)。


<bean id="propertyConfigurer" parent="ureport.props">
    <property name="location">
        <value>/WEB-INF/config.properties</value>
    </property>
</bean>
說明
上面的Bean配置,實際上就是一個標(biāo)準的org.springframework.beans.factory.config.PropertyPlaceholderConfigurer類配置,我們知道通過配置PropertyPlaceholderConfigurer,可以實現(xiàn)加載Spring外部properties的作用,所以如果您的項目中已配置了PropertyPlaceholderConfigurer類,那么直接在這個類對應(yīng)的properties文件中添加對應(yīng)的UReport2屬性即可,而不需要額外配置config.properties文件。

       打開config.properties文件,在其中添加名為“ureport.fileStoreDir”的屬性,該屬性的值用于定義UReport2中提供的默認基于文件系統(tǒng)的報表存儲目錄,比如定義該屬性為下面樣式:

屬性值定義示例
ureport.fileStoreDir=D:/ureportfiles

       表示在D盤根下名為ureportfiles的目錄中存儲報表文件,需要注意的是,這里指定特定目錄時,一定要保存這個目錄已存在,否則將不會被采用,比如上面的D盤下名為ureportfiles的目錄,就需要我們預(yù)先創(chuàng)建好。

自定義報表存儲器

       UReport2默認提供的名為“服務(wù)器文件系統(tǒng)”的報表存儲機制,實際上是實現(xiàn)了UReport2提供的com.bstek.ureport.provider.report.ReportProvider接口,該接口源碼如下:

package com.bstek.ureport.provider.report;
import java.io.InputStream;
import java.util.List;
/**
 * @author Jacky.gao
 * @since 2016年12月4日
 */
public interface ReportProvider {
    /**
     * 根據(jù)報表名加載報表文件
     * @param file 報表名稱
     * @return 返回的InputStream
     */
    InputStream loadReport(String file);
    /**
     * 根據(jù)報表名,刪除指定的報表文件
     * @param file 報表名稱
     */
    void deleteReport(String file);
    /**
     * 獲取所有的報表文件
     * @return 返回報表文件列表
     */
    List<ReportFile> getReportFiles();
    /**
     * 保存報表文件
     * @param file 報表名稱
     * @param content 報表的XML內(nèi)容
     */
    void saveReport(String file,String content);
    /**
     * @return 返回存儲器名稱
     */
    String getName();
    /**
     * @return 返回是否禁用
     */
    boolean disabled();
    /**
     * @return 返回報表文件名前綴
     */
    String getPrefix();
}

       實現(xiàn)了ReportProvider接口后,只需要將實現(xiàn)類配置到Spring中,讓其成為一個標(biāo)準的Spring Bean,這樣UReport2就會檢測到它而將其加載。下面是UReport2默認提供的名為“服務(wù)器文件系統(tǒng)”的報表存儲器源碼:


package com.bstek.ureport.provider.report.file;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import javax.servlet.ServletContext;
import org.apache.commons.io.IOUtils;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.web.context.WebApplicationContext;
import com.bstek.ureport.exception.ReportException;
import com.bstek.ureport.provider.report.ReportFile;
import com.bstek.ureport.provider.report.ReportProvider;
/**
 * @author Jacky.gao
 * @since 2017年2月11日
 */
public class FileReportProvider implements ReportProvider,ApplicationContextAware{
    private String prefix="file:";
    private String fileStoreDir;
    private boolean disabled;
    @Override
    public InputStream loadReport(String file) {
        if(file.startsWith(prefix)){
            file=file.substring(prefix.length(),file.length());
        }
        String fullPath=fileStoreDir+"/"+file;
        try {
            return new FileInputStream(fullPath);
        } catch (FileNotFoundException e) {
            throw new ReportException(e);
        }
    }
     
    @Override
    public void deleteReport(String file) {
        if(file.startsWith(prefix)){
            file=file.substring(prefix.length(),file.length());
        }
        String fullPath=fileStoreDir+"/"+file;
        File f=new File(fullPath);
        if(f.exists()){
            f.delete();
        }
    }
    @Override
    public List<ReportFile> getReportFiles() {
        File file=new File(fileStoreDir);
        List<ReportFile> list=new ArrayList<ReportFile>();
        for(File f:file.listFiles()){
            Calendar calendar=Calendar.getInstance();
            calendar.setTimeInMillis(f.lastModified());
            list.add(new ReportFile(f.getName(),calendar.getTime()));
        }
        Collections.sort(list, new Comparator<ReportFile>(){
            @Override
            public int compare(ReportFile f1, ReportFile f2) {
                return f2.getUpdateDate().compareTo(f1.getUpdateDate());
            }
        });
        return list;
    }
    @Override
    public String getName() {
        return "服務(wù)器文件系統(tǒng)";
    }
     
    @Override
    public void saveReport(String file,String content) {
        if(file.startsWith(prefix)){
            file=file.substring(prefix.length(),file.length());
        }
        String fullPath=fileStoreDir+"/"+file;
        FileOutputStream outStream=null;
        try{
            outStream=new FileOutputStream(new File(fullPath));
            IOUtils.write(content, outStream,"utf-8");
        }catch(Exception ex){
            throw new ReportException(ex);
        }finally{
            if(outStream!=null){
                try {
                    outStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
         
    }
    @Override
    public boolean disabled() {
        return disabled;
    }
     
    public void setDisabled(boolean disabled) {
        this.disabled = disabled;
    }
     
    public void setFileStoreDir(String fileStoreDir) {
        this.fileStoreDir = fileStoreDir;
    }
     
    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        File file=new File(fileStoreDir);
        if(file.exists()){
            return;
        }
        if(applicationContext instanceof WebApplicationContext){
            WebApplicationContext context=(WebApplicationContext)applicationContext;
            ServletContext servletContext=context.getServletContext();
            String basePath=servletContext.getRealPath("/");
            fileStoreDir=basePath+fileStoreDir;
            file=new File(fileStoreDir);
            if(!file.exists()){
                file.mkdirs();
            }
        }
    }
    @Override
    public String getPrefix() {
        return prefix;
    }
}
禁用系統(tǒng)提供的默認報表存儲器
 如果我們定義了自己的報表存儲器,同時又不想再使用系統(tǒng)默認提供的”服務(wù)器文件系統(tǒng)“的報表存儲器,那么我們只需要在之前介紹的config.properties文件中添加一個名為ureport.disableFileProvider屬性,將其值設(shè)置成true即可。

       通過上面的介紹,可以看到,通過實現(xiàn)ReportProvider接口,我們可以很容易的開發(fā)出其它類型的報表存儲器,比如開發(fā)一個新的報表存儲器將報表文件存儲到數(shù)據(jù)庫、FTP等。

配置報表數(shù)據(jù)源

       打開UReport2的報表設(shè)計器,可以看到UReport2提供了三種類型的報表數(shù)據(jù)源,如下圖所示:

datasource

       三種類型的數(shù)據(jù)源分別是直接連接數(shù)據(jù)庫,Spring Bean以及通過實現(xiàn)com.bstek.ureport.definition.datasource.BuildinDatasource接口提供的內(nèi)置數(shù)據(jù)源。

       直接連接數(shù)據(jù)庫比較簡單,就是在項目的classpath中添加好相應(yīng)數(shù)據(jù)庫的驅(qū)動Jar包后,在彈出的窗口中配置數(shù)據(jù)源連接信息即可,如下圖所示:

config-ds

       Spring Bean類型的數(shù)據(jù)源可以選擇Spring上下文中定義好的一個Bean來作為數(shù)據(jù)源,點擊圖標(biāo),在彈出的窗口中輸入數(shù)據(jù)源名稱及要采用的Bean的ID,如下圖所示:

bean-ds

       保存后,就可以在這個數(shù)據(jù)源下添加具體的數(shù)據(jù)集,添加方法就是在這個數(shù)據(jù)源下右鍵,在彈出的菜單中選擇添加數(shù)據(jù)集,在彈出的窗口中定義數(shù)據(jù)集名稱、對應(yīng)的方法名以及返回對象類型,如下圖所示:

bean-dataset

       在Spring bean數(shù)據(jù)集配置中,方法名我們可以點擊右側(cè)的“選擇方法”按鈕來選擇當(dāng)前Bean對應(yīng)的類中定義的方法,但這里對方法的要求是:方法必須要有三個參數(shù),依次是String,String,Map,比如我們上面定義的testBean里就包含兩個合法的方法,如下所示:


package com.ureport.test;
import java.util.List;
import java.util.Map;
/**
 * @author Jacky.gao
 * @since 2017年2月7日
 */
public class TestBean {
    public List<Map<String,Object>> loadReportData(String dsName,String datasetName,Map<String,Object> parameters){
        return null;
    }
    public List<Map<String,Object>> buildReport(String dsName,String datasetName,Map<String,Object> parameters){
        return null;
    }
}

       所以對于一個合法的Bean數(shù)據(jù)集方法要有三個參數(shù),分別是String,String,Map,依次對應(yīng)數(shù)據(jù)源名稱、數(shù)據(jù)集名稱以及外部傳入的參數(shù)Map,Bean的方法只有是這種結(jié)構(gòu)才可以選擇。對于數(shù)據(jù)集方法的返回值,目前來說可以支持兩種類型,一種是我們TestBean中返回的Map<String,Object>類型的List集合;另一種就是返回一個POJO類型的List集合,比如像下面的方法:


public List<User> loadData(String dsName,String datasetName,Map<String,Object> parameters){
    return null;
}

       在上面的示例方法中,返回的就是User對象集合,這里的User對象,就是一個普通的POJO對象。

內(nèi)置數(shù)據(jù)源

       這種類型的數(shù)據(jù)源,要示我們實現(xiàn)BuildinDatasource接口,同時將BuildinDatasource接口實現(xiàn)類配置到Spring即可,BuildinDatasource接口源碼如下:


package com.bstek.ureport.definition.datasource;
import java.sql.Connection;
/**
 * @author Jacky.gao
 * @since 2017年2月9日
 */
public interface BuildinDatasource {
    /**
     * @return 返回數(shù)據(jù)源名稱
     */
    String name();
    /**
     * @return 返回當(dāng)前采用數(shù)據(jù)源的一個連接
     */
    Connection getConnection();
}

       BuildinDatasource接口實現(xiàn)類配置到Spring中后,UReport2會自動檢測到,這樣在報表設(shè)計器中,點擊數(shù)據(jù)源頁簽中的按鈕,在彈出的窗口中就可以選擇定義好的內(nèi)置數(shù)據(jù)源,如下圖所示:

built-list

        對于UReport2提供的三種類型的數(shù)據(jù)源,各有其特點及適用場景,對于使用者來說,要根據(jù)它們的特點靈活選擇。


以上內(nèi)容是否對您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號