陳本士,付立平
摘要: PDF形式的輸出格式愈來愈多地被商業(yè)客戶所接受.由于PDF文件具有格式整潔,所占空間小等特點,很多電子商務應用系統(tǒng)用PDF文件做為在線表格的打印與存儲.在基于JEE技術設計的系統(tǒng)中,利用iText( JAVA開源代碼庫), Java reflection特性來生成PDF文件是一種有效的方法。
關鍵詞:JEE應用;PDF表格
中圖分類號:TP311文獻標識碼:A文章編號:1009-3044(2012)02-0318-04
1定義
1) WEB表格:用戶從電子商務網(wǎng)站的網(wǎng)頁定義的表格輸入UI界面。
2) PDF表格(文件):由系統(tǒng)后端處理并在網(wǎng)頁UI界面顯示的PDF表格。
3) PDF模板:定義PDF表格的外觀,及表格數(shù)據(jù)所要填寫的field(域名)。
2商務案例(Use Case)
學生從學校網(wǎng)頁上輸入注冊信息:姓名,生日,性別,入學時間,專業(yè),院/系,聯(lián)系方式,住址,父母聯(lián)系方式等項目名。
學生點擊”提交”按鈕,將所填寫的表格存入系統(tǒng)。
學生點擊”打印”或”保存”按鈕, WEB登記表格會以PDF文件格式顯示在當前窗口中。
我們所討論的方案要求有以下幾個條件:
1)預先設計好的PDF表格模版所定義的field和WEB表格所定義的field必須確保以下所定義的關系:
{PDF Form: fieldA_1, fieldA_2, fieldA_3,…, fieldA_n}?{Web Form: fieldB_1, fieldB_2, fieldB_3…fieldB_n }
fieldA_i 1 : 1 fieldB_j
注: PDF field不必和WEB表格的field名字同名, PDF表格不一定包含所有的WEB表格field
2)WEB表格數(shù)據(jù)已輸入并提交或已經(jīng)存入系統(tǒng)數(shù)據(jù)庫中。
3)iText JAVA庫itext-1.4.4.jar文件已從http://itextpdf.com/網(wǎng)站下載, itext-1.4.4.jar文件的PATH加在系統(tǒng)環(huán)境變量CLASS_ PATH定義中。
3方案設計
3.1系統(tǒng)處理流程
如圖1所示。
3.2 JEE Design Pattern
本系統(tǒng)設計采用了以下JEE design pattern:
MVC
Session Fa?ade
Wrapper
Transfer Object
DAO
3.3 Class Diagram
如圖2所示。
圖1
圖2
3.4 Sequence Diagram
如圖3所示。
圖3
3.5編程細節(jié)
3.5.1 iText類庫
我們的設計將使用到以下iText所定義的類:
com.lowagie.text.Document
com.lowagie.text.DocumentException
com.lowagie.text.PageSize
com.lowagie.text.pdf.AcroFields
com.lowagie.text.pdf.PdfContentByte
com.lowagie.text.pdf.PdfImportedPage
com.lowagie.text.pdf.PdfReader
com.lowagie.text.pdf.PdfStamper
com.lowagie.text.pdf.PdfWriter
3.5.2 Value Object
·StudentFormVO class,此CLASS用于存取WEB表格主要學生數(shù)據(jù)
Private String studentID;
Private String FirstName;
Private String LastName;
Private String Birthdate;
Private String Gender;
Private String major;
Private ContactVO studentContact;//embedded class
Private ContactVO parentContact; embedded class
…
//定義每個類成員變量的getters, setters…
·ContactVO class此CLASS用于存取WEB表格學生聯(lián)系信息數(shù)據(jù)
·Private String phoneNumber;
·Private String cellPhoneNumber;
·Private String email;
//定義每個類成員變量的getters, setters…
StudentPdfFormVO
此CLASS繼承StudentFormVO class,用于存取最后生成的PDF表格數(shù)據(jù). StudentPdfFormVO
可能要定義更多的類成員變量.讓我們以RADIO按鈕field為例,如RADIO field有3項選擇,那么在StudentFormVO只需一個類成員變量即可,而其對應的StudentPdfFormVO則要定義3個類成員變量。
3.5.3 ViewStudentPDFFormAction class
·viewStudentForm method
功能:根據(jù)caller所傳遞的學生ID,從數(shù)據(jù)庫中讀取該學生的登記表,再把所得到的表格數(shù)據(jù)轉(zhuǎn)換成PDF格式,并寫到HTTPServeletResponse輸出流中.參數(shù): String studentId,返回數(shù)據(jù)類型:無
主要編程邏輯如下:
//step1: call StudentServiceSessionBean:: StudentServiceSessionBean()
method to retrieve student submitted form data and fill data in PDF template
//Step2: get filled pdf formbyte array variable pdf
//step3: write pdf byte array into http servlet response stream, see code below:
response.setContentType("application/pdf");
if(pdf != null && pdf.length > 0)
{
response.setContentLength(pdf.length);}
response.setHeader("Cache-Control", "cache, must-revalidate");
response.setHeader("Pragma", "public");
response.setHeader("content-transfer-encoding", "binary");
response.setHeader("content-disposition", "inline + ; filename=" + "STUDENT_REGISTRATION_FORM.pdf");
response.flushBuffer();
ByteArrayInputStream fileStream =
new ByteArrayInputStream(pdf);
//copy fileStream to response outputStream
3.5.4 StudentFormWrapper class
此class主要封裝StdentPdfFormVO,及將所接收的WEB表格數(shù)據(jù)(StudentFormVO參數(shù))轉(zhuǎn)換成PDF表格在JAVA程序中對應的StudentPdfFormVO. StudentFormWrapper還定義了很關鍵的子程序。
getFieldValue.pdfFieldsMap class variable
此變量用于定義PDF模板表格field name與web表格field name的對應關系。
HushMap key: PDF模板中所定義的filed名, value: StudentPdfFormVO對應的filed名.
private static Map
PdfFieldsMap的初始化:
Static
{
pdfFieldsMap.put(“first_name”,“firstName”);
pdfFieldsMap.put(“l(fā)ast_name”,“l(fā)astName”);
pdfFieldsMap.put(“student_id”,“studentID”);
...
pdfFieldsMap.put(“student_tel”,“studentContact.phoneNumber”);
pdfFieldsMap.put(“studentt_cell”,“studentContact.cellPhoneNumber”);
pdfFieldsMap.put(“student_email”,“studentContact.email”);
...
}
getFieldValue() method
此method主要用JAVA Reflection特性以獲得PdfFormVO的某一property值
注: StudentPdfFormVO file必須和PDF表格模板保持1:1的對應關系.
此外對JAVA嵌套定義的value object對象,我們必須用”.”來定義層次關系,
請參看ContactVO property : studentContact.cellPhoneNumber
功能:返回所接受的PDF表格的field(pdfFieldName)的值
參數(shù): String pdfFieldName, StudentPdfFormVO pdfForm
返回數(shù)據(jù)類型: String
主要編程邏輯如下:
String fieldName = pdfFieldsMap.get(pdfFieldName);
String fieldVal = "";
...
try
{fieldVal = BeanUtils.getProperty(pdfForm, fieldName); }
...
return fieldVal;
3.6 PDFFormServiceSessionBean class
·populatePdfFields() method
功能:將所接受的StudentFormWrapper中所含的StudentPdfFormVO數(shù)據(jù),填寫到PDF表格模板中
參數(shù): StudentFormWrapper wrapper, String templatePdf,返回數(shù)據(jù)類型: PdfReader,主要編程邏輯如下:
ByteArrayOutputStream tempOut = new ByteArrayOutputStream();
try
{
FileInputStream fin = new FileInputStream(new File(templatePdf));
PdfStamper stamp = new PdfStamper(new PdfReader(fin), tempOut);
AcroFields afields = stamp.getAcroFields();
for(Iterator iter = afields.getFields().keySet().iterator();
iter.hasNext();)
{ String fieldName = (String)iter.next();
String fieldValue = wrapper.getFieldValue(fieldName);
if(fieldName != null && fieldValue != null)
{afields.setField(fieldName, fieldValue); } }
stamp.setFormFlattening(true);
stamp.close();}
// catch block…
// finally block…
final PdfReader filledForm = new PdfReader(
new ByteArrayInputStream(tempOut.toByteArray()));
tempOut.reset();
return filledForm;
4總結
本文所討論的方法是利用iText和JAVA reflection的特性來解決電子商務中一個普遍的功能需求.它具有代碼優(yōu)化,易于維護和移植等優(yōu)點.我們只需修改和value object : StudentFormWrapper類中的pdfFieldsMap類成員變量即可.
參考文獻:
[1]王勇.Java編程基礎、實例與進級[M].北京.清華大學出版社,2011.
[2]王知強.管理信息系統(tǒng)[M].北京.哈爾濱工業(yè)大學出版社,2011.