




已閱讀5頁(yè),還剩47頁(yè)未讀, 繼續(xù)免費(fèi)閱讀
版權(quán)說(shuō)明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡(jiǎn)介
JasperReport和IReport報(bào)表開(kāi)發(fā)的功能介紹目錄1 簡(jiǎn)介42 JasperReport和IReport的安裝與配置42.1 JDK的下載、安裝和配置42.2 ANT的下載、安裝和配置52.3 Jasperreport的下載、安裝和配置62.4 iReport的安裝和配置73 主要功能和實(shí)現(xiàn)過(guò)程73.1 XML解析83.2編譯報(bào)表設(shè)計(jì)83.3 Report Design 預(yù)覽93.4報(bào)表填充103.5查看報(bào)表113.6打印報(bào)表113.7導(dǎo)出報(bào)表113.8對(duì)象的載入和保存114 iReport的使用指南124.1一個(gè)簡(jiǎn)單的報(bào)表124.2報(bào)表預(yù)覽134.3使用數(shù)據(jù)庫(kù)的數(shù)據(jù)生成報(bào)表155 報(bào)表設(shè)計(jì)185.1DTD Reference185.2XML編碼195.3報(bào)表屬性196 報(bào)表數(shù)據(jù)216.1表達(dá)式216.2參數(shù)226.3數(shù)據(jù)源246.4查詢報(bào)表256.5字段266.6變量287 Report Sections317.1 Main Report Sections317.2 數(shù)據(jù)分組368 腳本程序389 報(bào)表元素389.1文本元素409.2圖像元素459.3超鏈接489.4元素組4810 子報(bào)表4910.1子報(bào)表參數(shù)5010.2子報(bào)表數(shù)據(jù)源5011高級(jí)JasperReports應(yīng)用5011.1 XML報(bào)表的導(dǎo)入和設(shè)計(jì)5011.2實(shí)例化數(shù)據(jù)源接口5011.3自定義查看器5011.4導(dǎo)出新的格式511 簡(jiǎn)介Jasperreport是一款報(bào)表打印組件,是開(kāi)放源代碼組織中的一個(gè)java報(bào)表打印工程,是一款功能強(qiáng)大的報(bào)表生成工具。它既可以將報(bào)表內(nèi)容在顯示器上輸出,也可以通過(guò)打印機(jī)打印出來(lái),同時(shí)它還支持使用PDF、HTML和XML等多種文件格式進(jìn)行存儲(chǔ)。在不久的將來(lái),諸如CSV、XLS、RTF等格式也將會(huì)被兼容。iReport也是開(kāi)源組織中的一款免費(fèi)軟件,其主要作用是用來(lái)以可視化的方式設(shè)計(jì)生成JasperReport所使用的報(bào)表格式文件,因?yàn)镴asperReport本身并未提供很好的可視化報(bào)表設(shè)計(jì)工具,iReport的出現(xiàn)正好彌補(bǔ)了這個(gè)缺陷。2 JasperReport和IReport的安裝與配置 2.1 JDK的下載、安裝和配置下載JDK的最新版本可以從SUN 公的官方網(wǎng)站上下載得到,網(wǎng)址為 ,JDK共分為3 個(gè)版本,J2ME,J2SE,J2EE,因?yàn)槭窃谟?jì)算機(jī)上使用,我們需要下載使用 J2SE SDK,如果您的計(jì)算機(jī)是用來(lái)做軟件開(kāi)發(fā),需要下載J2SE SDK,如果是用來(lái)運(yùn)行已經(jīng)編譯好的JAVA 程序的,可以只下載J2SE JRE 即可。下載JDK 時(shí)SUN 公司會(huì)要求你同意一個(gè)JDK 的使用許可協(xié)議,選接受協(xié)議后,會(huì)出現(xiàn)選擇適合不同的操作系統(tǒng)平臺(tái)使用的JDK 版本選擇的界面,您可以根據(jù)自己使用的操作系統(tǒng)平臺(tái)選擇適合的JDK 版本。安裝以Windows 平臺(tái)的安裝為例,在安裝的過(guò)程中一路Next 即可,同時(shí)請(qǐng)注意記錄下JDK安裝后的目錄,稍后進(jìn)行配置時(shí)要用到。配置以在Windows xp平臺(tái)配置J2SE SDK 為例,鼠標(biāo)右鍵點(diǎn)擊桌面上的“我的電腦”圖標(biāo),在彈出的菜單中選擇屬性,選擇“高級(jí)”選項(xiàng),選擇“環(huán)境變量”。點(diǎn)擊“系統(tǒng)變量”下的新增按鈕,在對(duì)話框中的變量名處輸入大寫(xiě)的JAVA_HOME,在變量值處輸入的JDK 安裝目錄。點(diǎn)擊“確定”完成第一步的配置,接下來(lái)以同樣的方法配置系統(tǒng)環(huán)境變量CLASSPATH,在CLASSPATH的變量值處輸入%JAVA_HOME%libtools.jar; %JAVA_HOME%libdt.jar,當(dāng)然,也可以直接輸入絕對(duì)路徑,但建議使用%JAVA_HOME%的方式。再接下來(lái)還要修改系統(tǒng)環(huán)境變量PATH,增加%JAVA_HOME%bin 目錄。至此JDK 的配置也完成.打開(kāi)一個(gè)命令行窗口,鍵入set classpath 與set java_home 應(yīng)該可以看到正確的配置信息,同時(shí),輸入javac -version 看系統(tǒng)能否找到JAVA 的編譯器。 2.2 ANT的下載、安裝和配置ant 是個(gè)很好用的工具,雖然對(duì)于JasperReport 和iReport 來(lái)說(shuō)ant 并不是必須的,但還是建議以使用ant 的方式來(lái)應(yīng)用。ANT的下載和安裝ant 是apache 組織的一個(gè)子項(xiàng)目,可以從 下載得到,Windows 平臺(tái)的可以下載ZIP 格式的安裝文件,下載完成以后解壓縮到某個(gè)目錄,建議使用根目錄下的直接子目錄作為ant 解壓縮以后目錄,ant 無(wú)需安裝,解壓縮文件以后就算安裝完成。Ant的配置與設(shè)置JDK相同的操作過(guò)程打開(kāi)系統(tǒng)環(huán)境變量設(shè)置窗口,增加ANT_HOME環(huán)境變量,變量值為解壓縮以后的ant 所在目錄在系統(tǒng)的環(huán)境變量Path 中增加%ANT_HOME%bin 目錄新開(kāi)一個(gè)命令行窗口,輸入ant 后如果出現(xiàn)如下圖所示內(nèi)容即算正確完成ant 的配置。 2.3 Jasperreport的下載、安裝和配置Jasperreport的下載和安裝因?yàn)镴asperReport 是 的開(kāi)源項(xiàng)目,最新的JasperReport 版本可以在 中找到,同時(shí),為了方便世界各國(guó)程序員下載, 還設(shè)有許多的鏡像站點(diǎn)供你選擇。強(qiáng)烈建議下載jasperreport 的source.zip,因?yàn)檫@里面包含了很多的示例程序,對(duì)于想深入研究jasperreport 的人來(lái)說(shuō)會(huì)有很大的幫助。如果不想對(duì)JasperReport 有太多的深入了解,只需要下載.jar 文件就能正常開(kāi)發(fā)應(yīng)用了。沒(méi)有必要單獨(dú)為JasperReport.jar 文件設(shè)置目錄,建議放在系統(tǒng)中%JAVA_HOME%lib目錄中。Jasperreport的配置將JasperReport-x.x.x.jar 文件添加到操作系統(tǒng)的環(huán)境變量ClASSPATH 中即可完成JasperReport 的配置。 2.4 iReport的安裝和配置iReport的安裝iReport 在Windows 平臺(tái)也是以.zip 形式的文件提供的,直接解壓縮后就算完成了安裝如果是2.x版的,且您決定以ant 的方式運(yùn)行iReport 程序,需要修改一下iReport 目錄中的ireport.bat 文件中的內(nèi)容,第一次運(yùn)行ireport.bat 會(huì)生成javadoc,在確定已正確生成javadoc 文件后可以將生成doc 的那一段注釋掉以便以后可以快速的啟動(dòng)iReport 程序。3.0 版無(wú)需修改ireport.bat 文件。iReport 的使用在有ant 環(huán)境的下運(yùn)行iReport,直接運(yùn)行iReport 目錄中的ireport.exe 即可。在沒(méi)有ant 的環(huán)境下運(yùn)行iReport,2.X 版本使用iReport 目錄中的noant 目錄中的startup.bat 運(yùn)行,3.0 版本使用bin 目錄中的startup.bat 運(yùn)行。3 主要功能和實(shí)現(xiàn)過(guò)程 現(xiàn)在我們將對(duì)XML報(bào)表設(shè)計(jì)進(jìn)行分析,編譯,裝填數(shù)據(jù),預(yù)覽結(jié)果和導(dǎo)出到其他格式的過(guò)程。Jasperreport的實(shí)例下面是Jasperreport工具,將XML報(bào)表轉(zhuǎn)變成的各種類型報(bào)表的流程圖: 3.1 XML解析 JasperReport使用SAX2.0 API對(duì)XML文件進(jìn)行解析。然而,這并不是必須的,用于可以在執(zhí)行其自行決定使用哪一種XML解析器。JasperReport使用org.xml.sax.helpers.XMLReaderFactory類的createXMLReader()來(lái)獲得解析器實(shí)例。在這種情況下,就像在SAX2.0文檔中說(shuō)的那樣,在運(yùn)行期,把Java系統(tǒng)屬性org.xml.sax.driver的值設(shè)定為SAX driver類的全限定名是必要的。設(shè)置系統(tǒng)屬性有兩種方法:第一種方法是在你啟動(dòng)Java虛擬機(jī)的時(shí)候,在命令行窗口使用-D開(kāi)關(guān):java -Dorg.xml.sax.driver=org.apache.xerces.parsers.SAXParser MySAXApp sample.xml在JasperReport提供的所有例子中,都采用ANT構(gòu)建工具來(lái)執(zhí)行不同的任務(wù)。我們通過(guò)使用內(nèi)置的 task中的元素來(lái)提供這一系統(tǒng)屬性;第二種設(shè)置系統(tǒng)屬性的方法是使用java.lang.System.setProperty(String key, String value)System.setProperty(“org.xml.sax.driver”,“ org.apache.xerces.parsers.SAXParser”);Jsp/compile.jsp和web-inf/class/servlets/CompileServlet.java文件提供了這方面的例子。 3.2 編譯報(bào)表設(shè)計(jì) 為了生成一個(gè)報(bào)表,用戶首先需要完成報(bào)表的設(shè)計(jì),生成方法或采用直接編輯XML文件,或通過(guò)程序生成一個(gè)net.sf.jasper.engine.design.JasperDesign對(duì)象。在此,主要采用編輯XML文件的方法,因?yàn)檫@種方法在目前是使用JasperReport類庫(kù)的最好的方法。 XML報(bào)表設(shè)計(jì)是JasperReport用來(lái)生成報(bào)表的初級(jí)材料。這是因?yàn)閄ML中的內(nèi)容需要被編譯并載入到JasperDesign對(duì)象中,這些對(duì)象將在報(bào)表引擎向其中填入數(shù)據(jù)之前,必須經(jīng)過(guò)編譯過(guò)程。 報(bào)表編譯過(guò)程的主要目的是生成并裝載含有所有報(bào)表表達(dá)式的類的字節(jié)碼。這個(gè)動(dòng)態(tài)生成的類將會(huì)被用來(lái)在裝填數(shù)據(jù),并在給所有報(bào)表表達(dá)式求值的時(shí)候使用。具體例子是,如果你用iReport生成一個(gè)報(bào)表名字叫SimpleSheetTest,它的XML設(shè)計(jì)文件名叫SimpleSheetTest.jrxml,同時(shí)和它在同一目錄下iReport會(huì)自動(dòng)生成一個(gè)文件名為SimpleSheetTest.java,里面主要是一些報(bào)表元素,如Field,Parameters,Variables的定義,以及一些求值表達(dá)式。當(dāng)然,像上面提到的,這個(gè)文件在你直接使用JasperReport API的時(shí)候是看不到的,因?yàn)樗窃趫?zhí)行期生成的一個(gè)Class。要想看到它的辦法是:在IDE(JBuilder,Eclipse)中單步執(zhí)行程序,在報(bào)表打印的階段,你將能跟蹤到這個(gè)類,它的名字就是“你的報(bào)表名.java”,按上面的例子就是SimpleSheetTest.java,這和iReport是一致的。當(dāng)然也可以像下面說(shuō)的那樣,到生成這個(gè)類的臨時(shí)目錄里找到它。在這個(gè)類生成過(guò)程之前,JasperReport引擎需要驗(yàn)證報(bào)表設(shè)計(jì)的一致性,哪怕存在一處驗(yàn)證檢查失敗都不會(huì)繼續(xù)運(yùn)行下面的工作。對(duì)于這個(gè)包含了所有報(bào)表表達(dá)式的類的字節(jié)碼,我們至少需要關(guān)心三個(gè)方面的內(nèi)容:臨時(shí)工作目錄、Java 編譯器的使用、Classpath 為了能夠編譯Java源文件,這個(gè)文件必須被創(chuàng)建并且被保存到磁盤上。Java編譯過(guò)程的輸出是一個(gè).class文件,這個(gè)包含所有報(bào)表表達(dá)式的類在這個(gè)工作目錄里被創(chuàng)建并編譯,這也是為什么JasperReport需要訪問(wèn)這個(gè)臨時(shí)目錄的原因。當(dāng)報(bào)表的編譯過(guò)程結(jié)束之后,這些臨時(shí)的類文件將被自動(dòng)刪除,而生成的字節(jié)碼將保存在net.sf.jasper.engine.JasperReport對(duì)象中。如果需要的話,這個(gè)類可以將自己序列化并保存到磁盤上。這就是iReport的做法。 缺省情況下,這個(gè)臨時(shí)工作目錄就是啟動(dòng)JVM時(shí)的當(dāng)前目錄,這卻取決于JVM的系統(tǒng)屬性u(píng)ser.dir。通過(guò)更改系統(tǒng)屬性pile.temp,用戶可以很容易更改這個(gè)工作目錄。在Web環(huán)境下,特別是當(dāng)你不想讓含有啟動(dòng)Web Server的批處理文件的目錄和報(bào)表編譯過(guò)程的臨時(shí)工作目錄混在一起的時(shí)候,修改這個(gè)屬性就可以了。上面提到的第二個(gè)方面涉及用來(lái)編譯報(bào)表表達(dá)式類的Java編譯器。首先,報(bào)表引擎將試圖使用sun.tools.javac.Main類來(lái)編譯Java源文件。這個(gè)類包含在tools.jar中,當(dāng)且僅當(dāng)這個(gè)jar文件在JDK安裝目錄下的bin/目錄中,或在classpath中時(shí),sun.tools.javac.Main才能正常使用。如果JasperReport不能成功裝載sun.tools.javac.Main文件,程序?qū)?dòng)態(tài)執(zhí)行java編譯過(guò)程,就像我們通常用命令行那樣,使用JDK安裝目錄下的bin/目錄下的javac.exe。這就是為什么將JDK安裝目錄/lib/下的tools.jar文件copy到JasperReport工程的lib/目錄下是一個(gè)可選的操作(optional operation)。如果tools.jar不在classpath中,JasperReport將顯示錯(cuò)誤信息并繼續(xù)上面提到的操作。 當(dāng)編譯Java源文件的時(shí)候,最重要的事情莫過(guò)于classpath。如果Java編譯器不能在指定的classpath中找到它試圖編譯的所有相關(guān)類的源文件,則整個(gè)過(guò)程將失敗并停止,錯(cuò)誤信息將在控制臺(tái)顯示出來(lái)。同樣的事情也將發(fā)生在JasperReport試圖編譯報(bào)表表達(dá)式類的時(shí)候。所以,在runtime為編譯過(guò)程提供正確的classpath是非常重要的。例如,我們我們需要確認(rèn)在classpath中,我們提供了在報(bào)表表達(dá)式中可能用到的類(custom class)。 在這個(gè)方面也有一個(gè)缺省的行為。如果沒(méi)有為編譯report class特殊指定classpath,引擎將會(huì)使用系統(tǒng)屬性java.class.path的值來(lái)確定當(dāng)前的JVM classpath。如果你指定了系統(tǒng)屬性pile.class.path的值,你可以用你定義的classpath來(lái)覆蓋缺省行為。 大多數(shù)情況下,編譯一個(gè)report只需要簡(jiǎn)單的調(diào)用JasperReport類庫(kù)中的JasperCompileMpileReport(myXmlFileName);即可。調(diào)用之后將生成編譯好的report design并存儲(chǔ)在.jasper文件中,這個(gè)文件將會(huì)保存在和提供XML report design文件相同的目錄中。 3.3 Report Design 預(yù)覽 JasperReport類庫(kù)并沒(méi)有提供高級(jí)的GUI工具來(lái)輔助進(jìn)行設(shè)計(jì)工作。但是目前已經(jīng)有至少4個(gè)project試圖提供這樣的工具。然而,JasperReport本身提供了一個(gè)很有用的可視化組件來(lái)幫助報(bào)表設(shè)計(jì)者在編譯的時(shí)候預(yù)覽報(bào)表設(shè)計(jì)(其實(shí)不如直接用IReport方便)。net.sf.jasper.view.JasperDesigner是一個(gè)基于Swing的Java應(yīng)用程序,它可以載入并顯示XML形式或編譯后的報(bào)表設(shè)計(jì)。盡管它不是一個(gè)復(fù)雜的GUI應(yīng)用程序,缺乏像拖拽可視化報(bào)表元素這樣的高級(jí)功能,但是它仍然是一個(gè)有用的工具。所有JasperReport工程提供的例子都利用了這個(gè)報(bào)表查看器。 如果你已經(jīng)安裝了ANT,想要查看一個(gè)簡(jiǎn)單的報(bào)表設(shè)計(jì),你只需要到相應(yīng)的文件夾下輸入如下命令:ant viewDesignXML 或者 ant viewDesign 如果你沒(méi)安裝ANT,要達(dá)到上面的效果就不是很容易,因?yàn)镴asperReport本身需要一些其他輔助的jar包(在JasperReport安裝目錄/lib下),在運(yùn)行的時(shí)候,你需要把這些jar包都包含到你的classpath里面,并且正確設(shè)計(jì)系統(tǒng)屬性,如上面提到的org.xml.sax.driver。我可以展示一下在windows下的例子:java -classpath ./;./././lib/commons-digester.jar;./././lib/commons-beanutils.jar;./././lib/commons-collections.jar;./././lib/xerces.jar;./././lib/jasperreports.jar-Dorg.xml.sax.driver=org.apache.xerces.parsers.SAXParserdori.jasper.view.JasperDesignViewer -XML -FFirstJasper.xml 3.4報(bào)表填充 報(bào)表填充過(guò)程是JasperReport library最重要的功能。它體現(xiàn)了這個(gè)軟件最主要的目的,因?yàn)檫@一過(guò)程可以自由的操作數(shù)據(jù)集,以便可以產(chǎn)生高質(zhì)量的文檔。有3種材料需要裝填過(guò)程中作為輸入提供給JasperReport:report design、參數(shù)、數(shù)據(jù)源 這一過(guò)程的輸出通常是一個(gè)單一的最終要被查看,打印或?qū)С龅狡渌袷降奈臋n。要進(jìn)行這一過(guò)程,我們需要采用net.sf.jasper.engine.JasperFillManager類。這個(gè)類提供了一些方法來(lái)讓我們填充報(bào)表設(shè)計(jì),report design的來(lái)源可以是本地磁盤,輸入流,或者直接就是一個(gè)已存在于內(nèi)存中的net.sf.jasper.engine.JasperReport類。輸出的產(chǎn)生是于輸入類型相對(duì)應(yīng)的,也就是說(shuō),如果JasperFillManager接到一個(gè)report design的文件名,填充結(jié)束后生成的report將會(huì)是一個(gè)放在磁盤上的文件;如果JasperFillManager收到的是一個(gè)輸入流,則生成的report將會(huì)被寫(xiě)到一個(gè)輸出流中。有些時(shí)候,這些JasperFillManager提供的方法不能滿足某些特定的應(yīng)用的要求,例如可能有人希望他的report design被作為從classpath中得到的資源,并且輸出的報(bào)表作為一個(gè)文件存放在一個(gè)指定的磁盤目錄下。遇到這種情況時(shí),開(kāi)發(fā)人員需要考慮在將報(bào)表設(shè)計(jì)傳遞給報(bào)表裝填過(guò)程之前,用net.sf.jasper.engine.util.JRLoader類來(lái)裝載report design對(duì)象。這樣,他們就能獲得像報(bào)表名這樣的report design屬性,于是開(kāi)發(fā)者就能生成最終文檔的名字,并將它存放到所需的位置上。 在現(xiàn)實(shí)中,有許多報(bào)表裝填的情境,而裝填管理器僅試圖覆蓋其中最常被使用到的部分。然而對(duì)于想要自己定制裝填過(guò)程的人來(lái)說(shuō),只要采用上面所說(shuō)的方法,任何開(kāi)發(fā)者都可以達(dá)到滿意的結(jié)果。報(bào)表參數(shù)通常作為java.util.Map的value提供給裝填管理器,參數(shù)名為其鍵值。作為裝填過(guò)程所需的第三種數(shù)據(jù)源,有如下兩種情況:通常,引擎需要處理net.sf.jasper.engine.JRDataSource接口的一個(gè)實(shí)例,通過(guò)這個(gè)實(shí)例,引擎可以在裝填過(guò)程中獲取所需數(shù)據(jù)。JasperFillManager提供的方法支持所有的JRDataSource對(duì)象。 然而,這個(gè)管理器還提供一些接受java.sql.Connection對(duì)象作為參數(shù)的方法集,來(lái)取代所需的數(shù)據(jù)源對(duì)象。這是因?yàn)樵诤芏嗲闆r下,報(bào)表生成所需的數(shù)據(jù)都來(lái)源于某個(gè)關(guān)系型數(shù)據(jù)庫(kù)中的表。在報(bào)表中,用戶可以提供SQL查詢語(yǔ)句來(lái)從數(shù)據(jù)庫(kù)中取回報(bào)表數(shù)據(jù)。在執(zhí)行期,engine唯一需要做的是獲得JDBC connection對(duì)象,并使用它來(lái)連接想要連接的數(shù)據(jù)庫(kù),執(zhí)行SQL查詢并取回報(bào)表數(shù)據(jù)。在后臺(tái),引擎將使用一個(gè)特殊的JRDataSource對(duì)象,但是它對(duì)于調(diào)用它的程序來(lái)說(shuō)是透明的。JasperReport工程提供了相關(guān)的例子,它們采用HSQL數(shù)據(jù)庫(kù)服務(wù)器(在工程文件中,有一個(gè)相應(yīng)的文件夾),要運(yùn)行這些例子你需要首先啟動(dòng)該服務(wù)器,方法是:在/demo/hsqldb目錄下輸入如下命令:ant 或者 ant runServer 沒(méi)裝ANT就麻煩點(diǎn):java -classpath ./;././lib/hsqldb.jar org.hsqldb.Server一下代碼片斷顯示了query例子是如何裝填數(shù)據(jù)的:/Preparing parametersMap parameters = new HashMap();parameters.put(ReportTitle, Address Report);parameters.put(FilterClause, Boston, Chicago, Oslo);parameters.put(OrderClause, City);/Invoking the filling processJasperFillManager.fillReportToFile(fileName, parameters, getConnection(); 3.5 查看報(bào)表 報(bào)表填充階段的輸出通常是一個(gè)JasperPrint對(duì)象,如果把它保存在磁盤上,通常以一個(gè).jrprint文件的形式存在。JasperReport擁有一個(gè)內(nèi)置的查看器,用來(lái)查看用內(nèi)置的XML導(dǎo)出器獲得的XML格式的報(bào)表文件。這個(gè)查看器就是以前提到過(guò)的net.sf.jasper.niew.JRViewer,用戶可以通過(guò)繼承這個(gè)類來(lái)定制自己所需的查看器。JasperReport工程中自帶的例子webapp中,你可以閱讀JRViewerPlus類的代碼來(lái)獲取進(jìn)一步內(nèi)容。 3.6 打印報(bào)表 JasperReport類庫(kù)的主要目標(biāo),就是生成可打印的文檔。而且多數(shù)應(yīng)用程序生成的報(bào)表都是需要打印到紙張上。我們可以用net.sf.jasper.engine.JasperPrintManager來(lái)打印JasperReport生成的文檔。當(dāng)然,報(bào)表也同樣可以在被導(dǎo)出到其他格式如PDF,HTML之后再被打印。通過(guò)JasperPrintManager提供的方法,我們可以打印整個(gè)文檔,打印單個(gè)文檔或打印某一范圍內(nèi)的文檔,可以顯示打印對(duì)話框也可以不顯示。下面的例子演示了不顯示對(duì)話框,打印整個(gè)文檔的方法:JasperPrintManager.printReport(myReport,false); 3.7 導(dǎo)出報(bào)表 在一些應(yīng)用程序環(huán)境下,將JasperReport生成的文檔從其特有的格式導(dǎo)出到其他更為流行的格式如PDF,HTML是非常有用的。這樣一來(lái),其他人就可以在沒(méi)有安裝JasperReport的情況下查看這些報(bào)表,特別是當(dāng)這些文檔要通過(guò)網(wǎng)絡(luò)發(fā)送出去的時(shí)候。JasperReport提供了JasperExportManager類來(lái)支持此項(xiàng)功能。這項(xiàng)功能將會(huì)在以后不斷加入對(duì)新的格式的支持。目前,JasperReport主要支持導(dǎo)出PDF,HTML和XML類型的文檔,下面是導(dǎo)出的代碼片斷:JasperExportManager.exortReportToHtmlFile(myReport); 注意:想要將自己的報(bào)表導(dǎo)出到其他格式的用戶,需要實(shí)現(xiàn)JRExporter的接口,或繼承相應(yīng)的JRAbstractExporter類。 3.8 對(duì)象的載入和保存 當(dāng)使用JasperReport的時(shí)候,你經(jīng)常會(huì)與序列化的對(duì)象,如以編譯的報(bào)表設(shè)計(jì),或已生成的報(bào)表打交道。有時(shí),你需要手動(dòng)載入從不同的source如input stream或你用類庫(kù)核心功能產(chǎn)生的序列化類。JasperReport提供了兩個(gè)特殊的工具類來(lái)提供上述操作的能力,這些類通常供報(bào)表引擎自己使用:net.sf.jasper.engine.util.JRLoadernet.sf.jasper.engine.util.JRSaver 第一個(gè)類提供了一些方法讓我們能夠從不同類型的數(shù)據(jù)源如文件,URL,input stream和classpath里面獲取序列化對(duì)象。最令人感興趣的方法是loadObjectFormLocation(String)。它已經(jīng)在上一章中介紹過(guò)了,這里不再贅述。 與上面的對(duì)象載入工具相反的部分是JRSaver類,它可以幫助程序員將自己的類序列化之后存放到本地磁盤或通過(guò)Output Stream發(fā)送到網(wǎng)絡(luò)上去。 有時(shí),開(kāi)發(fā)人員可能想要載入已經(jīng)生成好的report,或最終的已經(jīng)被導(dǎo)出到XML格式的JasperReport文檔,這與上面所說(shuō)的直接load序列化對(duì)象有所不同。這時(shí),我們需要載入的是將載入的XML內(nèi)容進(jìn)行編譯,并生成JasperPrint對(duì)象,而并非僅僅是載入序列化對(duì)象。這時(shí),我們可以通過(guò)net.sf.jasper.engine.xml.JRPrintXmlLoader類的一些靜態(tài)方法,通過(guò)編譯從XML文件中讀取的內(nèi)容構(gòu)建出一個(gè)位于內(nèi)存中的文檔對(duì)象。4 iReport的使用指南4.1一個(gè)簡(jiǎn)單的報(bào)表 如上面左圖所示新建一個(gè)文檔,如右圖設(shè)置報(bào)表的名稱、大小等屬性。依照上圖的標(biāo)識(shí),分別設(shè)計(jì)報(bào)表的各部分,可以通過(guò)以下快捷方式來(lái)插入圖形、靜態(tài)文字、動(dòng)態(tài)文字圖片等元素,設(shè)計(jì)如下圖報(bào)表設(shè)計(jì)完畢,選擇菜單欄中的“建立”下拉菜單,選擇其中“編譯”,對(duì)報(bào)表盡進(jìn)行編譯,如有錯(cuò)誤,會(huì)在底端提示,若無(wú)錯(cuò)誤,則生成.Jrxml文件。編譯成功之后,選擇“執(zhí)行報(bào)表”,進(jìn)行預(yù)覽。4.2 報(bào)表預(yù)覽Ireport默認(rèn)是用其自帶的iReport JasperViewer進(jìn)行預(yù)覽。我們可以選擇其他的預(yù)覽方式,通過(guò)選擇菜單欄中的“Option”下拉菜單,選擇其中的“選項(xiàng)”,選擇External Programs選項(xiàng)卡,如下圖所示,對(duì)各個(gè)預(yù)覽工具進(jìn)行配置配置之后,可以通過(guò)選擇菜單欄中的“建立”下拉菜單,選擇以配置好的預(yù)覽方式,之后選擇“執(zhí)行報(bào)表”,就可以用相應(yīng)的應(yīng)用程序?qū)ζ溥M(jìn)行預(yù)覽。4.3 使用數(shù)據(jù)庫(kù)的數(shù)據(jù)生成報(bào)表4.3.1連接數(shù)據(jù)庫(kù)選擇菜單欄中的“data”下拉菜單,選擇“連結(jié)/資料來(lái)源”, 選擇“New”新建一個(gè)連接,配置如下圖,其中experiment是已建立的數(shù)據(jù)庫(kù)名稱單擊“Test”,測(cè)試數(shù)據(jù)庫(kù)連接是否成功,若成功,有以下對(duì)話框若不成功,有類似于下圖的相應(yīng)的對(duì)話框測(cè)試成功,單擊“save”保存新建連接。4.3.2設(shè)置SQL查詢語(yǔ)句選擇菜單欄中的“data”下拉菜單,選擇“報(bào)表查詢”,之后在相應(yīng)地方編寫(xiě)SQL語(yǔ)句。編寫(xiě)完畢,單擊“OK”保存并退出編寫(xiě)。4.3.3字段在報(bào)表設(shè)計(jì)器中的使用點(diǎn)擊工具欄中的在報(bào)表中的“Details”段中用鼠標(biāo)拖拽到適合的大小,右擊該字段框,選擇屬性,在選擇Text Fiel選項(xiàng)卡,如下圖: 選中Text Field 項(xiàng),如果沒(méi)有設(shè)置正確的字段名稱,則Textfield expression 中的內(nèi)容將顯示藍(lán)色,手工修改Textfield expression 中的內(nèi)容為正確的字段名稱,格式為$F字段名稱,正確修改后將變?yōu)榫G色顯示。4.3.4編譯與預(yù)覽帶有字段的報(bào)表對(duì)下面報(bào)表進(jìn)行編譯,其中數(shù)據(jù)已經(jīng)在數(shù)據(jù)庫(kù)中預(yù)先設(shè)好編譯報(bào)表可以選擇菜單欄中“建立”下拉菜單中的“編譯”,也可以直接點(diǎn)擊工具欄中的圖標(biāo),如果編譯過(guò)程正確完成,iReport 設(shè)計(jì)器的下面會(huì)顯示如下內(nèi)容:帶有字段的報(bào)表進(jìn)行預(yù)覽有兩種方式,一種是不使用數(shù)據(jù)庫(kù)中的數(shù)據(jù),默認(rèn)所有字段值為null 的方式,預(yù)覽方法為選擇“建立”菜單中的“執(zhí)行報(bào)表”,也可以直接點(diǎn)擊工具欄中的圖標(biāo);第二種方式為使用數(shù)據(jù)庫(kù)中的數(shù)據(jù)的方式,預(yù)覽方法為選擇“建立”菜單中的“執(zhí)行報(bào)表(使用動(dòng)態(tài)連接)”,也可以直接點(diǎn)擊工具欄中的圖標(biāo)。下圖進(jìn)行預(yù)覽:5 報(bào)表設(shè)計(jì)報(bào)表設(shè)計(jì)體現(xiàn)了一個(gè)模板,JasperReport引擎利用這個(gè)模板將同臺(tái)生成的內(nèi)容傳遞給打印機(jī),屏幕或Web。存儲(chǔ)在數(shù)據(jù)庫(kù)中的數(shù)據(jù)在報(bào)表裝填的過(guò)程中被組織起來(lái),根據(jù)已有的報(bào)表設(shè)計(jì)來(lái)獲得可以進(jìn)行打印的,面向頁(yè)面的(page oriented)文檔。總而言之,一個(gè)報(bào)表設(shè)計(jì)包含了所有的結(jié)構(gòu)相關(guān)信息和將數(shù)據(jù)提供給報(bào)表所涉及的各個(gè)方面。這些信息涉及將在文檔中顯示出來(lái)的各種text或圖像元素的位置和內(nèi)容,自定義計(jì)算(custom calculation),數(shù)據(jù)組織,報(bào)表生成時(shí)的數(shù)據(jù)操作,等等。報(bào)表設(shè)計(jì)通常都定義在一個(gè)擁有特殊格式的XML文檔中,并且在被填充數(shù)據(jù)之前要經(jīng)歷JasperReport的編譯過(guò)程。然而JasperReport也允許用戶通過(guò)JasperReport提供的API構(gòu)造in-memory報(bào)表對(duì)象,例如noxmldesign就是很好的例子。 5.1 DTD Reference 當(dāng)使用XML文件進(jìn)行報(bào)表設(shè)計(jì)的時(shí)候,JasperReport將使用內(nèi)置的DTD文件來(lái)驗(yàn)證其受到的XML內(nèi)容的有效性。如果XML驗(yàn)證通過(guò),則說(shuō)明所提供的報(bào)表設(shè)計(jì)符合JasperReport所需要的XML結(jié)構(gòu)和語(yǔ)法規(guī)則,其引擎能夠生成經(jīng)過(guò)編譯的report design。 有效的XML文檔總是在驗(yàn)證時(shí)指向JasperReport的內(nèi)部DTD文件。如果沒(méi)有提供DTD文檔的引用,報(bào)表的編譯過(guò)程將會(huì)突然結(jié)束。這對(duì)所有人來(lái)說(shuō)都是一個(gè)負(fù)擔(dān),因?yàn)镈TD引用通常是相同的,并且這些引用可能會(huì)簡(jiǎn)單的被從以前的報(bào)表設(shè)計(jì)中copy過(guò)來(lái)。在一開(kāi)始,你需要將這個(gè)引用從給定的例子中copy過(guò)來(lái)。 正如以前說(shuō)的一樣,報(bào)表引擎僅能識(shí)別指向其內(nèi)部DTD文件的的引用。你不能隨便從類庫(kù)的源文件中將那些DTD文件copy到別的地方,再在你的報(bào)表設(shè)計(jì)文件中指向你copy的那些DTD文件。如果你想那樣做的話,你將需要調(diào)整類庫(kù)中某些類,包括dori.jasper.engine.xml.JRXmlDigester類的某些代碼。如果你遇到像引擎無(wú)法找到其內(nèi)部的DTD文件而導(dǎo)致的無(wú)法載入資源的問(wèn)題,請(qǐng)確定你已經(jīng)在使用外部DTD文件之前排除了所有可能發(fā)生的情況。遇到這樣的問(wèn)題是不太可能的,因?yàn)橘Y源載入機(jī)制會(huì)隨著時(shí)間不斷改進(jìn)。JasperReport只有兩種合法的XML報(bào)表設(shè)計(jì)的DTD引用,他們是:或者: XML報(bào)表設(shè)計(jì)的根元素是,下面是一個(gè)普通的JasperReports XML報(bào)表設(shè)計(jì)文件的樣子: . 前三點(diǎn)描述了該報(bào)表設(shè)計(jì)的屬性和設(shè)置,下面省略的部分則描述了各種報(bào)表設(shè)計(jì)要素如報(bào)表參數(shù)、字段、變量、組和報(bào)表欄等。 5.2 XML 編碼 當(dāng)要生成不同語(yǔ)言的XML報(bào)表設(shè)計(jì)的時(shí)候,在XMl文件的首部的編碼屬性需要特別關(guān)注一下。缺省情況下,如果這個(gè)屬性的值沒(méi)被訂制,則XML解析器將會(huì)使用“UTF-8”作為XML文件的編碼格式。這一點(diǎn)是非常重要的,因?yàn)閳?bào)表設(shè)計(jì)通常包含了靜態(tài)的本地化文本。對(duì)于大多數(shù)西歐語(yǔ)言來(lái)說(shuō),ISO-8859-1編碼,也就是我們常說(shuō)的LATIN1將會(huì)很好的處理如法語(yǔ)中重音符號(hào)的顯示問(wèn)題。 在編輯XML文件的時(shí)候,要找到某種特殊語(yǔ)言的編碼類型,你可以查看XML document.FIXME。 5.3 報(bào)表屬性 我們上面已經(jīng)看到,XML報(bào)表設(shè)計(jì)的根元素。這一節(jié)我們將介紹報(bào)表設(shè)計(jì)對(duì)象的Property的細(xì)節(jié)以及這些屬性所對(duì)應(yīng)的XML attributes報(bào)表名稱 每一個(gè)報(bào)表都必須有一個(gè)名稱。這個(gè)名稱是相當(dāng)重要的,因?yàn)轭悗?kù)需要它來(lái)生成文件,尤其是當(dāng)編譯,裝填,導(dǎo)出報(bào)表的默認(rèn)行為被使用的時(shí)候,這個(gè)名的作用更為重要。這個(gè)名稱是以元素的name attribute的形式提供的,并且是強(qiáng)制必須填寫(xiě)。列數(shù) JasperReport允許生成每頁(yè)的列數(shù)超過(guò)一列的報(bào)表,正如下面的圖片,展示了擁有兩列的報(bào)表:默認(rèn)情況下,報(bào)表引擎生成每頁(yè)一列的報(bào)表。打印順序 對(duì)于擁有超過(guò)一列的報(bào)表,為其提供列將被以什么順序填充是很重要的。你可以使用元素的printOrder attribute來(lái)進(jìn)行設(shè)置。有如下兩種情況:l Verticaln Filling:這個(gè)選項(xiàng)將導(dǎo)致列是自頂向下被填充(printOrder=”Vertical”)l Horizontal filling:列將自左向右被填充(printOrder=”Horizontal”)缺省設(shè)置將是printOrder=Vertical頁(yè)面大小 有兩個(gè)attribute是用來(lái)提供要生成的文檔大小的:pageWith,pageHeight。像所有其他顯示元素位置和尺寸的attribute一樣,這兩個(gè)attribute是以像素為單位的。JasperReport采用Java默認(rèn)的每英寸72點(diǎn)的設(shè)置。這意味著pageWith=”595”將大約是8.26英寸,這大概是A4紙的尺寸。默認(rèn)的紙張大小是A4紙:pageWith=”595” pageHeight=”842” Page Orientation(默認(rèn)設(shè)置為Portrait) orientation屬性用來(lái)設(shè)置文檔打印格式是“Portrait”還是“Landscape”。JasperReport允許用戶在從“Portrait”切換到“Landscape”的時(shí)候調(diào)整液面的寬度和高度。我們先看一個(gè)例子:我們假定要生成一個(gè)A4紙的報(bào)表,采用“Protrait”格式: pageWidth=”595” pageHeight=”842” orientation=”Portrait” 如果我們決定用A4紙的“Landscape”布局,首先要調(diào)整相應(yīng)的頁(yè)面寬度和高度: pageWidth=”842” pageHeight=”595” orientation=”Landscape” 這是因?yàn)镴asperReport需要確切知道它所要繪制的報(bào)表頁(yè)的寬度和高度,而不只看我們提供的orientation屬性,至少在報(bào)表裝填的時(shí)候是這樣。orientation屬性僅在報(bào)表打印時(shí)有用,來(lái)通知打印機(jī)或某些exporters頁(yè)面的orientation設(shè)置。頁(yè)邊距 一旦頁(yè)面大小確定下來(lái),用戶就可以在生成報(bào)表的時(shí)候設(shè)定報(bào)表的邊距。有四個(gè)屬性來(lái)完成這項(xiàng)工作:topMargin,LeftMargin,bottomMargin和rightMargin。缺省的設(shè)置是上下邊距20像素,左右邊距30像素。列寬和列間距(Column Size and Spacing) 一個(gè)報(bào)表可能含有多列,我們可以通過(guò)上面提到的columnCount屬性得到報(bào)表列數(shù)。JasperReport需要知道列的寬度和列間距的大小。有兩個(gè)屬性用于這項(xiàng)工作:columnWidth和columnSpacing。當(dāng)我們對(duì)報(bào)表設(shè)計(jì)進(jìn)行編譯的時(shí)候,編譯器會(huì)對(duì)這項(xiàng)設(shè)置進(jìn)行有效性檢查(validation check)-看列的寬度和列間距是否符合給定的頁(yè)面寬度和頁(yè)邊距。因?yàn)槿笔〉牧袛?shù)為一,所以缺省的列間距為0像素,并且缺省的列寬等于頁(yè)面寬度減去左右邊距所得的值。在上面A4的例子中,列寬即為555像素??諗?shù)據(jù)源時(shí)的行為 有時(shí)我們提供給我們的報(bào)表的數(shù)據(jù)源可能會(huì)沒(méi)有任何記錄。whenNoDataType屬性可以讓你選擇當(dāng)所提供的數(shù)據(jù)源中沒(méi)有數(shù)據(jù)的時(shí)候入和察看生成的報(bào)表。如下有三種不同的可能性,你可以任選其一:l Empty Document:生成的報(bào)表不含有頁(yè)面(no page in it)。當(dāng)你試圖裝載這樣的文檔(whenNoDataType=”NoPages”)的時(shí)候,Viewer 可能會(huì)拋出一個(gè)錯(cuò)誤。l Blank page:表示生成的報(bào)表將僅含有一個(gè)空白頁(yè)(whenNoDataType=”BlankPage”)l All sections displayed:除了detail部分的其他部分將在生成的文檔中顯示出來(lái)(whenNoDataType=”AllSectionNoDetail”)。缺省的設(shè)置是whenNoDataType=”NoPages”。 標(biāo)題和摘要的放置(Title and Summary Sections Placement) 如果你想讓title部分和summary部分在單獨(dú)的一頁(yè)里顯示,你所需要做的事情就是讓下面的一個(gè)或兩個(gè)屬性的值為“true”:isTitleNewPage,isSummaryNewPage。這兩個(gè)屬性缺省情況下為false。注意:即使你選擇了在最后一頁(yè)的剩余部分顯示summary,如果列數(shù)超過(guò)一列,并且第二列已經(jīng)在最后一頁(yè)出現(xiàn)的時(shí)候(沒(méi)試過(guò),等有機(jī)會(huì)試驗(yàn)一下),新的一頁(yè)將會(huì)被自動(dòng)生成。腳本類(Scriptlet Class) scirptletClass屬性用于設(shè)置用于當(dāng)前報(bào)表的scriptlet類的名字。在后面會(huì)對(duì)Scriptlet進(jìn)行詳細(xì)討論。如果你沒(méi)為這個(gè)屬性提供任何值,報(bào)表引擎將會(huì)使用dori.jasper.engine.JRDefaultScriptlet的實(shí)例。6 報(bào)表數(shù)據(jù) 當(dāng)談到報(bào)表裝填過(guò)程的時(shí)候,有三樣?xùn)|西需要作為輸入提供給報(bào)表引擎:報(bào)表設(shè)計(jì)(report design),參數(shù)值(parameter values)和報(bào)表的數(shù)據(jù)源(data source)。在先前的介紹,我們已經(jīng)看到了有關(guān)報(bào)表設(shè)計(jì)的某些方面,現(xiàn)在我們要更加詳細(xì)的關(guān)注其他兩方面的內(nèi)容:參數(shù)(parameter)和報(bào)表數(shù)據(jù)源。他們描繪了報(bào)表引擎在裝填報(bào)表過(guò)程中所用到的僅有的數(shù)據(jù)來(lái)源。像你用其他報(bào)表工具所希望的一樣,這些數(shù)據(jù)將會(huì)根據(jù)報(bào)表設(shè)計(jì)中的定義的模板(template)被組織起來(lái),并被用來(lái)生成準(zhǔn)備打印的、面向頁(yè)面的文檔。 6.1 表達(dá)式(expressions) 表達(dá)式是JasperReports的一個(gè)非常有用的特性。他們可以用來(lái)聲明執(zhí)行各種執(zhí)行各種計(jì)算(calculations)的報(bào)表變量(report variables),進(jìn)行報(bào)表的數(shù)據(jù)組織,定制報(bào)表文本字段(text field)的內(nèi)容或者進(jìn)一步定制報(bào)表對(duì)象的appearance。所有報(bào)表表達(dá)式基本上都是Java表達(dá)式,他們可以以特殊的語(yǔ)法引用報(bào)表參數(shù)(parameter),報(bào)表字段(field)和報(bào)表變量(variable)。在XML報(bào)表設(shè)計(jì)中,有一些用于定義表達(dá)式的元素:, , 等。因?yàn)樗械腏asperReport表達(dá)式都是真正(real)的Java表達(dá)式,只要你用完整的類名(包括包名)來(lái)引用這些表達(dá)式,你就可以在任何class中使用他們。當(dāng)你編譯報(bào)表和裝填數(shù)據(jù)的時(shí)候,你應(yīng)該確定你在報(bào)表表達(dá)式中使用的類已經(jīng)寫(xiě)入了classpath。報(bào)表參數(shù)引用是通過(guò)$P序列引入的,例如: $PReportTitle 這個(gè)例子假定我們?cè)趫?bào)表設(shè)計(jì)中有一個(gè)名為ReportTitle的報(bào)表參數(shù),這個(gè)參數(shù)是一個(gè)java.lang.String類。當(dāng)報(bào)表進(jìn)行裝填的時(shí)候,文本字段將會(huì)顯示這個(gè)參數(shù)的值。為了在一個(gè)表達(dá)式中使用報(bào)表字段,字段名必須放在$F的括號(hào)中。例如,如果我們想要在一個(gè)文本字段中顯示兩個(gè)數(shù)據(jù)源字段的連接值(concatenated values),我們可以定義如下表達(dá)式: $FFirstName + + $F
溫馨提示
- 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 強(qiáng)化子公司管理制度
- 形成痕跡化管理制度
- 征地拆遷辦管理制度
- 德云社名片管理制度
- 志愿團(tuán)成員管理制度
- 快遞店運(yùn)營(yíng)管理制度
- 總經(jīng)理怎樣管理制度
- 想投訴學(xué)校管理制度
- 戒毒局歸誰(shuí)管理制度
- 《重癥醫(yī)學(xué)科建設(shè)與管理指南(試行)》
- 醫(yī)用耗材一次性使用申請(qǐng)表
- GB/T 42068-2022農(nóng)村產(chǎn)權(quán)流轉(zhuǎn)交易市場(chǎng)建設(shè)和管理規(guī)范
- 第五課古典芭蕾(芭蕾舞鼎盛時(shí)期)
- 中小學(xué)生肥胖調(diào)查表
- 胃癌HER2判讀及評(píng)分課件
- 學(xué)校機(jī)房網(wǎng)絡(luò)規(guī)劃與設(shè)計(jì)
- 中儲(chǔ)糧警示教育心得體會(huì)三篇
- 船用空調(diào)電氣控制系統(tǒng)簡(jiǎn)介課件
- 2009-2022歷年河北省公安廳高速交警總隊(duì)招聘考試真題含答案帶詳解2022-2023上岸資料匯編3
- 遙控器檢驗(yàn)作業(yè)指導(dǎo)書(shū)
評(píng)論
0/150
提交評(píng)論