国产日韩欧美一区二区三区三州_亚洲少妇熟女av_久久久久亚洲av国产精品_波多野结衣网站一区二区_亚洲欧美色片在线91_国产亚洲精品精品国产优播av_日本一区二区三区波多野结衣 _久久国产av不卡

?

基于Java反射機(jī)制的POI實(shí)現(xiàn)Excel數(shù)據(jù)導(dǎo)入/導(dǎo)出

2015-04-29 00:44:03朱文君黃國(guó)權(quán)
計(jì)算機(jī)時(shí)代 2015年1期

朱文君 黃國(guó)權(quán)

摘 ?要: 隨著Java語(yǔ)言越來(lái)越多地被選擇用于B/S結(jié)構(gòu)系統(tǒng)的開(kāi)發(fā)語(yǔ)言,利用POI解析技術(shù)操作Excel文件越來(lái)越廣泛。在POI組件下,采用Java反射機(jī)制及自定義注解原理,設(shè)計(jì)實(shí)現(xiàn)了數(shù)據(jù)庫(kù)與Excel文件的數(shù)據(jù)交互。此方法不僅能保證數(shù)據(jù)導(dǎo)入的完整性,而且能免去數(shù)據(jù)導(dǎo)出后重新編輯的復(fù)雜性,從而提高POI實(shí)現(xiàn)Excel數(shù)據(jù)導(dǎo)入/導(dǎo)出的靈活性、重用性和易擴(kuò)展性。

關(guān)鍵詞: POI; Excel; 反射機(jī)制; 自定義注解; 數(shù)據(jù)導(dǎo)入導(dǎo)出

中圖分類(lèi)號(hào):TP312 ? ? ? ? ?文獻(xiàn)標(biāo)志碼:A ? ? 文章編號(hào):1006-8228(2015)01-38-02

Realization of import and export of data in Excel files by POI based on Java reflection

Zhu Wenjun, Huang Guoquan

(College of Medical Information Engineering, Guangdong Pharmaceutical University, Guangzhou, Guangdong 510006, China)

Abstract: With more and more systems on B/S structure being developed by Java, operating Excel by POI is used more widely. Under POI component, applying Java reflection and custom annotation, data interaction between database and Excel files is designed and realized. This method can not only ensure the integrity of data import, but also avoid the complexity of the data export. Flexibility, re-usability and ductility of using POI in importing and exporting Excel files are improved.

Key words: POI; Excel; reflection; custom annotation; data import and export

0 引言

在Web應(yīng)用系統(tǒng)中,用戶(hù)常會(huì)要求將數(shù)據(jù)庫(kù)中的數(shù)據(jù)導(dǎo)出到Excel表格中,或?qū)xcel表格中的數(shù)據(jù)導(dǎo)入到數(shù)據(jù)庫(kù)中[1]。然而,傳統(tǒng)的Excel數(shù)據(jù)導(dǎo)入導(dǎo)出技術(shù),對(duì)于不同的對(duì)象,都需要重新配置固定的表頭并且頻繁更改關(guān)鍵代碼算法,導(dǎo)致程序員操作過(guò)于繁瑣。本文介紹一種基于Java反射機(jī)制原理,只需要配置自定義注解,而無(wú)需更改關(guān)鍵代碼算法的Excel導(dǎo)入導(dǎo)出技術(shù)。

1 Java反射機(jī)制簡(jiǎn)介

Java反射機(jī)制是指Java語(yǔ)言在運(yùn)行時(shí)擁有的一項(xiàng)自審的能力,對(duì)自身進(jìn)行檢查,并能直接操作程序的內(nèi)部屬性[2]。即在運(yùn)行狀態(tài)中,對(duì)于任意一個(gè)類(lèi),都能夠知道這個(gè)類(lèi)的所有屬性和方法;對(duì)于任意一個(gè)對(duì)象,都能夠調(diào)用它的任意一個(gè)方法和屬性。通過(guò)采用該機(jī)制來(lái)實(shí)現(xiàn)對(duì)自己行為的描述和檢測(cè),并能根據(jù)自身行為的狀態(tài)和結(jié)果,為下一步的動(dòng)作做準(zhǔn)備[3]。

也就是說(shuō),Java反射機(jī)制提供了一種在運(yùn)行中獲得類(lèi)信息并構(gòu)建類(lèi)的Class對(duì)象和生成類(lèi)的實(shí)例的機(jī)制。同時(shí),使程序代碼能夠訪問(wèn)裝載到JVM中的類(lèi)的內(nèi)部信息,主要包括:已裝載類(lèi)的字段、方法和構(gòu)造函數(shù)的信息,并允許編寫(xiě)處理類(lèi)的代碼[4]。

2 輔助類(lèi)

2.1 ExcelAnnotation.java

@Retention(RetentionPolicy.RUNTIME)

public @interface ExcelAnnotation {

String title();

int order();

}

ExcelAnnotation注釋采用自定義注解技術(shù),可在實(shí)體model類(lèi)上的字段get()方法上注釋?zhuān)瑫r(shí)設(shè)定屬性所對(duì)應(yīng)的title(標(biāo)題)、order(順序)。通過(guò)設(shè)定@Retention(RetentionPolicy.RUNTIME),該注釋會(huì)在Class字節(jié)碼文件中存在,在運(yùn)行時(shí)可通過(guò)反射機(jī)制獲取該注釋的屬性。沒(méi)有注釋的實(shí)體model類(lèi)的字段將不受影響,有注釋的實(shí)體model類(lèi)的字段將會(huì)根據(jù)title的值輸出標(biāo)題,并且根據(jù)order的值進(jìn)行排序。從而在不需要預(yù)定義模板的情況下,實(shí)現(xiàn)Excel表格的表頭的動(dòng)態(tài)輸出,提高了功能模塊的靈活性。

2.2 ExcelHeader.java

public class ExcelHeader implements Comparable

{

private String title;

private int order;

private String methodName;

……

public int compareTo(ExcelHeader eh) {

return order>eh.order?1:(order

public ExcelHeader(String title, int order,

String methodName) {

super();

this.title = title;

……

}

}

ExcelHeader類(lèi)用來(lái)存儲(chǔ)Excel標(biāo)題的對(duì)象,通過(guò)該類(lèi)在反射機(jī)制中可以動(dòng)態(tài)獲取標(biāo)題和方法的對(duì)應(yīng)關(guān)系。同時(shí),該類(lèi)實(shí)現(xiàn)Comparable接口,重寫(xiě)了public int compareTo()方法。通過(guò)調(diào)用Collections.sort()方法,可根據(jù)order的值進(jìn)行標(biāo)題的排序,從而實(shí)現(xiàn)Excel表格的表頭的靈活配置。

3 主類(lèi)

3.1 Excel數(shù)據(jù)導(dǎo)出

傳統(tǒng)的Excel數(shù)據(jù)導(dǎo)出技術(shù),只能根據(jù)數(shù)據(jù)持久層或業(yè)務(wù)邏輯層中已經(jīng)由程序員寫(xiě)好的sql查詢(xún)語(yǔ)句導(dǎo)出規(guī)定的數(shù)據(jù),不能滿(mǎn)足用戶(hù)的自定義需求。引用Java反射機(jī)制后,通過(guò)BeanUtils.getProperty()方法,根據(jù)加載類(lèi)對(duì)象和字段名便可以動(dòng)態(tài)獲得對(duì)應(yīng)的屬性值,因此,不需要更改關(guān)鍵代碼的算法,減少了程序員的操作,同時(shí)也提高了功能模塊的重用性。

以下為Excel數(shù)據(jù)導(dǎo)出的關(guān)鍵代碼:

private List getHeaderList(Class model) {

List headers=new ArrayList();

//通過(guò)反射機(jī)制,能訪問(wèn)model對(duì)象表示的類(lèi)的所有方法

Method[] methods=model.getDeclaredMethods();

for (Method m:methods) {

String mn=m.getName();

if (mn.startsWith("get") ) {

//通過(guò)反射機(jī)制,判斷注釋存在于方法上,篩選出指定的數(shù)據(jù)集

if (m.isAnnotationPresent(ExcelAnnotation.class)) {

ExcelAnnotation ea=m.getAnnotation(ExcelAnnotation.class);

headers.add(new ExcelHeader(ea.title(),ea.order(), mn));

}

}

}

return headers;

}

getHeaderList()方法首先通過(guò)反射機(jī)制,獲取實(shí)體model類(lèi)的所有方法,然后通過(guò)自定義注解技術(shù)獲取存在于方法上的注釋?zhuān)⑶野炎⑨尩膬?nèi)容添加到headers對(duì)象中,從而動(dòng)態(tài)的綁定標(biāo)題和方法的對(duì)應(yīng)關(guān)系。

private Workbook exportExcel(List objs, Class model) {

……

List headers=getHeaderList(model);

Collections.sort(headers);

//輸出表頭

for (int i=0; i

cell1.setCellValue(headers.get(i).getTitle()); }

//輸出對(duì)象信息

for (int i=0; i

……

obj=objs.get(i);

for (int j=0; j

Cell cell2=r.createCell(j);

setDefaultCellStyle(cell2, cellStyle);

//通過(guò)反射機(jī)制,調(diào)用加載類(lèi)對(duì)象和字段名獲取對(duì)應(yīng)的屬性值

cell2.setCellValue(BeanUtils.getProperty(obj,

getMethodName(headers.get(j))));

……

}

exportExcel()方法通過(guò)調(diào)用getHeaderList()取得headers對(duì)象中標(biāo)題和方法的對(duì)應(yīng)關(guān)系。通過(guò)反射機(jī)制,調(diào)用加載類(lèi)對(duì)象和字段名獲取對(duì)應(yīng)的屬性值,從而動(dòng)態(tài)的綁定表頭和屬性值的映射關(guān)系。最后,通過(guò)Workbook對(duì)象傳值調(diào)用POI生成Excel表格方法,便實(shí)現(xiàn)將數(shù)據(jù)庫(kù)中的數(shù)據(jù)導(dǎo)出到Excel表格中。

3.2 Excel數(shù)據(jù)導(dǎo)入

傳統(tǒng)的Excel數(shù)據(jù)導(dǎo)入技術(shù),需要程序員在數(shù)據(jù)持久層或業(yè)務(wù)邏輯層中手動(dòng)組合sql插入語(yǔ)句。數(shù)據(jù)處理效率過(guò)低,并且容易導(dǎo)致數(shù)據(jù)處理出錯(cuò)。引用Java反射機(jī)制后,通過(guò)BeanUtils.copyProperty()方法,把字段名和對(duì)應(yīng)的屬性值復(fù)制到加載類(lèi)對(duì)象中,調(diào)用數(shù)據(jù)持久層的存儲(chǔ)操作即可。同樣,不需要更改關(guān)鍵代碼的算法,體現(xiàn)了功能模塊的重用性。

以下為Excel數(shù)據(jù)導(dǎo)入的關(guān)鍵代碼:

private Map getHeaderMap(Row titleRow,

Class model) { List headers=getHeaderList

(model);

for (Cell c:titleRow) {

String title=c.getStringCellValue();

for (ExcelHeader eh : headers) {

if (eh.getTitle().equals(title.trim())) {

maps.put(c.getColumnIndex(), eh.getMethodName()

.replace("get", "set"));

……

return maps; }

getHeaderMap()方法首先獲取Excel表格中的表頭,然后通過(guò)與實(shí)體model類(lèi)中注釋的標(biāo)題作對(duì)比,若一致,則把標(biāo)題的順序和對(duì)應(yīng)的方法名添加到maps對(duì)象中。

public List readExcel(Workbook wb, Class model,

int read, int tail) { ……

List objs=null;

objs=new ArrayList();

Map maps=getHeaderMap(row, model);

if (maps==null || maps.size()<=0) throw new

RuntimeException("要讀取的Excel表格的格式不正確,

請(qǐng)檢查標(biāo)題欄順序!");

for (int i=read+1; i<=sheet.getLastRowNum()-tail; i++) {

row=sheet.getRow(i);

//通過(guò)反射機(jī)制,只能調(diào)用無(wú)參數(shù)的構(gòu)造方法,篩選出指定的數(shù)據(jù)集

Object obj=model.newInstance();

for (Cell c:row) {

int ci=c.getColumnIndex();

//對(duì)方法名進(jìn)行改造,形成字段名

String mn=maps.get(ci).substring(3);

mn=mn.substring(0, 1).toLowerCase()+mn.substring(1);

Map params=new HashMap

Object>(); //通過(guò)反射機(jī)制,把字段名和對(duì)應(yīng)的屬性值復(fù)制到加載類(lèi)對(duì)象中

BeanUtils.copyProperty(obj, mn, this.getCellValue(c)); }

…… }

readExcel()方法通過(guò)調(diào)用getHeaderMap()取得Excel表格中的標(biāo)題和對(duì)應(yīng)實(shí)體model的方法名的對(duì)應(yīng)關(guān)系。通過(guò)反射機(jī)制,把字段名和Excel表格中對(duì)應(yīng)的屬性值復(fù)制到obj對(duì)象中,形成實(shí)體model類(lèi)的復(fù)制類(lèi)。最后,通過(guò)objs集合傳值調(diào)用數(shù)據(jù)持久層的存儲(chǔ)操作,實(shí)現(xiàn)將Excel表格中的數(shù)據(jù)導(dǎo)入到數(shù)據(jù)庫(kù)中。

4 結(jié)束語(yǔ)

反射是Java語(yǔ)言中一個(gè)非常突出的動(dòng)態(tài)相關(guān)機(jī)制。在使用Java語(yǔ)言開(kāi)發(fā)出靈活、高重用及易于擴(kuò)展的系統(tǒng)的過(guò)程中,反射機(jī)制起到越來(lái)越關(guān)鍵的作用[5]。本文通過(guò)對(duì)基于Java反射機(jī)制的POI實(shí)現(xiàn)Excel數(shù)據(jù)導(dǎo)入導(dǎo)出的研究,減少了程序員的手工操作,帶來(lái)了極大的方便。該方法在實(shí)際中得到應(yīng)用,取得了較好的效果。

本文創(chuàng)新點(diǎn):第一,在Web應(yīng)用系統(tǒng)中,只需要本文中所提及的三個(gè)封裝類(lèi),即ExcelAnnotation注釋、ExcelHeader類(lèi)及ExcelUtil類(lèi)便可以實(shí)現(xiàn)其功能,體現(xiàn)了功能模塊的松耦合性;第二,只需為實(shí)體類(lèi)配置ExcelAnnotation注釋?zhuān)诓恍枰A(yù)定義模板的情況下,實(shí)現(xiàn)Excel表格的表頭的動(dòng)態(tài)輸出,體現(xiàn)了功能模塊的靈活性;第三,在實(shí)體類(lèi)沒(méi)有外鍵關(guān)聯(lián)的情況下,不需要更改關(guān)鍵代碼的算法,體現(xiàn)了功能模塊的重用性。當(dāng)實(shí)體類(lèi)存在外鍵關(guān)聯(lián)時(shí),只需調(diào)用數(shù)據(jù)持久層的查詢(xún)操作修改屬性值即可,體現(xiàn)了功能模塊的易擴(kuò)展性。

參考文獻(xiàn):

[1] 戴維.POI實(shí)現(xiàn)Excel的數(shù)據(jù)導(dǎo)入導(dǎo)出的研究[J].科技信息,2013.1:

107

[2] Bruce Eckel.Thinking in Java[M].4.American:Prentice Hall PTR,

2006.

[3] 王善發(fā),吳道榮.Java語(yǔ)言的反射機(jī)制[J].保山學(xué)院學(xué)報(bào),2011.5:32

[4] 王開(kāi),譚翼,周蘭江.Java中反射機(jī)制淺析及應(yīng)用[J].計(jì)算機(jī)教育,

2007.1:255

[5] 尹松強(qiáng),傅鸝.Java反射機(jī)制探究[J].軟件導(dǎo)刊,2008.7(11):85

芜湖市| 舟曲县| 西乌珠穆沁旗| 山丹县| 微博| 宜阳县| 曲阳县| 平果县| 阳高县| 万年县| 南充市| 二连浩特市| 德格县| 清水县| 怀柔区| 上高县| 蓬溪县| 博野县| 和林格尔县| 儋州市| 杂多县| 肃北| 长治县| 抚宁县| 互助| 阿瓦提县| 馆陶县| 离岛区| 天全县| 穆棱市| 拉萨市| 温州市| 洛扎县| 襄垣县| 昌都县| 宣化县| 内黄县| 大姚县| 社会| 凌海市| 高清|