H2P在很多人看來是個令人激動的方案,而且javaei網(wǎng)站提供h2p文件資源又是相當(dāng)自然的一件事情,一想到h2p,我都很高興,因為這個方案是我提出來的,盡管實現(xiàn)h2p的技術(shù)很成熟。在這篇文章里,說一下實現(xiàn)h2p所涉及到的技術(shù)吧,既有核心的j2se應(yīng)用,又有開源框架的使用。
(1)dtd的應(yīng)用,為了規(guī)范使用者正確的編輯h2p文件,我定義了h2p文件的dtd,當(dāng)然我還有一個奢望,希望能成為一種規(guī)范。
(2)使用根據(jù)dtd校驗xml(h2p文件),h2p-tool需要解析xml(h2p文件)提取url生成pdf并合并,不合法的xml文件肯定不能正確的生成pdf,所以必須對xml文件進(jìn)行校驗。
(3)xml解析,編輯h2p,用JTree展示xml的樹形結(jié)構(gòu),這一部分用的是dom解析(具體的是JDom),獲取書簽的目錄結(jié)構(gòu)并構(gòu)建書簽的數(shù)據(jù)結(jié)構(gòu),這一部分用的是SAX解析,并借助于Stack。保存xml文件用的是dom。
(4)swing的應(yīng)用,h2p-tool編輯功能用的是swing,展示并編輯樹形結(jié)構(gòu)用的是JTree
(5)C#組件,根據(jù)url生成單個的pdf,用的是c#組件,并在vs.net開發(fā)平臺上進(jìn)行了簡單的開發(fā)。Javaei提供的h2p文件通常包含幾十條url,單就每條url生成pdf也需要一點時間,何況是幾十條,所以運用多線程是必須的方式,研究了一下c#的多線程(c#的多線程方式也很有意思,感覺比java的簡單),可是別人的組件在多線程下表現(xiàn)欠佳,無賴之下,只好還是采用單線程。本想用jni把c#的調(diào)用封裝起來,但經(jīng)過研究,據(jù)說比較麻煩,就放棄了,所以采用簡單的辦法,用批處理來調(diào)用。
(6)iText的應(yīng)用,生成單個pdf頁面以及合并pdf生成書簽用的是iText。在合并的時候,也研究過另一個框架就是pdfbox。IText確實強悍,理論上,應(yīng)用iText可以實現(xiàn)任意效果的輸出,應(yīng)該可以實現(xiàn)瀏覽器的效果,但比較麻煩。iText在生成書簽這一塊,做得相當(dāng)漂亮,書簽可以指向任意一個頁面的任意部分,還可以設(shè)置書簽對應(yīng)頁面的打開效果,對書簽的開發(fā)也很便利,直接構(gòu)造書簽的樹形數(shù)據(jù)結(jié)構(gòu)我認(rèn)為是最簡單的,iText還支持用xml描述書簽的結(jié)構(gòu)。
(7)Classloader的應(yīng)用,h2p-tool的運行依賴于很多的jar包,通常我們開發(fā)的時候,都是把jar包放在指定的目錄,應(yīng)用服務(wù)器會去加載依賴的jar包。在h2p-tool中,需要自己處理jar包。因為這是提供給用戶使用的工具,不應(yīng)要求使用者去配置除了jdk環(huán)境變量以外的變量。所以解決jar包加載的問題通常的辦法是在主類(帶有main方法的類)所在jar包里的Manifest.mf文件里寫上jar包的相對路徑。這種辦法不太靈活,所以在h2p-tool中,對類加載進(jìn)行了改寫,使其自動加載指定目錄下的jar包。
(8)jvm參數(shù)的應(yīng)用,因為要合并的pdf很多,再合并的時候會占用大量內(nèi)存,很容易out of memery,所以在批處理文件里,需要配置適當(dāng)?shù)?/span>jvm參數(shù),主要是兩個:-Xmx512m -Xms512m,這兩個參數(shù)的意義這里不再贅述,網(wǎng)上有很多的。
總結(jié)一下,實現(xiàn)h2p-tool的技術(shù)細(xì)節(jié)貌似很多,實則很少,除了JDOm和iText,再就是j2se核心的東西了,出列上面列到的,還包括流、字符集的處理等。H2p-tool及源代碼下載。