|
2006年12月6日
 至此,準備工作就可以了。 看看頁面怎么寫的  運行,就可以了。
在struts2中,獲取表單元素有三種方式: 1.在action類中,為屬性提供get/set方法。 2.使用javabean的引用,提供get/set方法。但是表單中名字必須是javabean引用的名字.屬性名。 3.實現Modeldriven接口。
摘要: 說實話,eclipse我受夠了.自從用了Intellijidea ,我的腰不酸了,腿不疼了,一口氣能上一層樓.先上代碼結構數據庫表結構
Code highlighting produced by Actipro CodeHighlighter (freeware)http://www.CodeHighlighter.com/--> 1 CREATE DATABASE... 閱讀全文
Map接口: | + -- WeakHashMap: 以弱鍵 實現的基于哈希表的 Map。在 WeakHashMap 中,當某個鍵不再正常使用時,將自動移除其條 | 目。更精確地說,對于一個給定的鍵,其映射的存在并不阻止垃圾回收器對該鍵的丟棄,這就使該鍵成為可終止的,被終 | 止,然后被回收。丟棄某個鍵時,其條目從映射中有效地移除,因此,該類的行為與其他的 Map 實現有所不同。此實現 | 不是同步的。 | + -- TreeMap:該映射根據其鍵的自然順序進行排序,或者根據創建映射時提供的 Comparator 進行排序,具體取決于使用的 | 構造方法。此實現不是同步的。 | + -- HashMap:基于哈希表的 Map 接口的實現。此實現提供所有可選的映射操作,并允許使用 null 值和 null 鍵。(除了 | 非同步和允許使用 null 之外,HashMap 類與 Hashtable 大致相同。)此類不保證映射的順序,特別是它不保證該順 | 序恒久不變。此實現不是同步的。 | +-- SortedMap: 進一步提供關于鍵的總體排序 的 Map。該映射是根據其鍵的自然順序進行排序的,或者根據通常在創建有 序映射時提供的 Comparator 進行排序。對有序映射的 collection 視圖(由 entrySet、keySet 和 values 方法返回 )進行迭代時,此順序就會反映出來。要采用此排序方式,還需要提供一些其他操作(此接口是 SortedSet 的對應映 射)。
Collection接口: | + -- Set接口:一個不包含重復元素的 collection。更正式地說,set 不包含滿足 e1.equals(e2) 的元素對 e1 和 e2,并 | | 且最多包含一個 null 元素。正如其名稱所暗示的,此接口模仿了數學上的 set 抽象。 | | | + -- HashSet:此類實現 Set 接口,由哈希表(實際上是一個 HashMap 實例)支持。它不保證 set 的迭代順序; | | 特別是它不保證該順序恒久不變。此類允許使用 null 元素。此類為基本操作提供了穩定性能,此實現不是同 | | 步的。 | | | + -- LinkedHashSet:具有可預知迭代順序的 Set 接口的哈希表和鏈接列表實現。此實現與 HashSet 的不同之外在 | | 于,后者維護著一個運行于所有條目的雙重鏈接列表。此鏈接列表定義了迭代順序,即按照將元素插入到 set | | 中 的順序(插入順序)進行迭代。注意,插入順序不 受在 set 中重新插入的 元素的影響。此實現不是同步 | | 的。 | | | + -- TreeSet:基于 TreeMap 的 NavigableSet 實現。使用元素的自然順序對元素進行排序,或者根據創建 set 時 | 提供的 Comparator 進行排序,具體取決于使用的構造方法。此實現為基本操作(add、remove 和 contains) | 提供受保證的 log(n) 時間開銷。此實現不是同步的。 | + -- List接口:有序的 collection(也稱為序列)。此接口的用戶可以對列表中每個元素的插入位置進行精確地控制。用戶 | 可以根據元素的整數索引(在列表中的位置)訪問元素,并搜索列表中的元素。 | + -- ArrayList:List 接口的大小可變數組的實現。實現了所有可選列表操作,并允許包括 null 在內的所有元素。 | 除了實現 List 接口外,此類還提供一些方法來操作內部用來存儲列表的數組的大小。(此類大致上等同于 | Vector 類,除了此類是不同步的。)每個 ArrayList 實例都有一個容量。該容量是指用來存儲列表元素的數 | 組的大小。它總是至少等于列表的大小。隨著向 ArrayList 中不斷添加元素,其容量也自動增長。并未指定增 | 長策略的細節,因為這不只是添加元素會帶來分攤固定時間開銷那樣簡單。此實現不是同步的。 | + -- LinkedList:List 接口的鏈接列表實現。實現所有可選的列表操作,并且允許所有元素(包括 null)。除了實 | 現 List 接口外,LinkedList 類還為在列表的開頭及結尾 get、remove 和 insert 元素提供了統一的命名方 | 法。這些操作允許將鏈接列表用作堆棧、隊列或雙端隊列。提供先進先出隊列操作(FIFO)。此實現不是同步的。 | + -- Vector:Vector 類可以實現可增長的對象數組。與數組一樣,它包含可以使用整數索引進行訪問的組件。但是 ,Vector 的大小可以根據需要增大或縮小,以適應創建 Vector 后進行添加或移除項的操作。此實現是同步的 。 |
自從用上了tomcat5.5,發現日志信息沒了,出錯了也找不著有用的信息,上apache找答案,果然
Tomcat 5.5 uses Commons Logging throughout its internal code allowing the developer to choose a logging configuration that suits their needs, e.g java.util.logging or Log4J. Commons Logging provides Tomcat the ability to log hierarchially across various log levels without needing to rely on a particular logging implementation.
An important consequence for Tomcat 5.5 is that the <Logger> element found in previous versions to create a localhost_log is no longer a valid nested element of <Context>. Instead, the default Tomcat configuration will use java.util.logging. If the developer wishes to collect detailed internal Tomcat logging (i.e what is happening within the Tomcat engine), then they should configure a logging system such as java.util.logging or log4j as detailed next
習慣用log4j來配置log信息的輸出。
新建log4j.properties,內容為
log4j.rootLogger=info,Console,R
log4j.appender.Console=org.apache.log4j.ConsoleAppender log4j.appender.Console.layout=org.apache.log4j.PatternLayout #log4j.appender.Console.layout.ConversionPattern=%d [%t] %-5p %c - %m%n log4j.appender.Console.layout.ConversionPattern=%d{yy-MM-dd HH:mm:ss} %5p %c{1}:%L - %m%n
log4j.appender.R=org.apache.log4j.DailyRollingFileAppender log4j.appender.R.File=${catalina.home}/logs/tomcat.log log4j.appender.R.layout=org.apache.log4j.PatternLayout log4j.appender.R.layout.ConversionPattern=%d{yyyy.MM.dd HH:mm:ss} %5p %c{1}(%L):? %m%n
log4j.logger.org.apache=info, R log4j.logger.org.apache.catalina.core.ContainerBase.[Catalina].[localhost]=DEBUG, R log4j.logger.org.apache.catalina.core=info, R log4j.logger.org.apache.catalina.session=info, R
最后四行是tomcat的信息,如果改為debug日志文件將十分龐大。
將這個文件放入${catalina.home}/common/classes下,再將log4j.jar和commons-logging.jar放入${catalina.home}/common/lib下,就可以在${catalina.home}/logs/下見到日志了。
?Servlet 和filter是J2EE開發中常用的技術,使用方便,配置簡單,老少皆宜。估計大多數朋友都是直接配置用,也沒有關心過具體的細節,今天遇到一個問題,上網查了servlet的規范才發現,servlet和filter中的url-pattern還是有一些文章在里面的,總結了一些東西,放出來供大家參考,以免遇到問題又要浪費時間。??? 一,servlet容器對url的匹配過程:????? 當一個請求發送到servlet容器的時候,容器先會將請求的url減去當前應用上下文的路徑作為servlet的映射url,比如我訪問的是http://localhost/test/aaa.html,我的應用上下文是test,容器會將http://localhost/test去掉,剩下的/aaa.html部分拿來做servlet的映射匹配。這個映射匹配過程是有順序的,而且當有一個servlet匹配成功以后,就不會去理會剩下的servlet了(filter不同,后文會提到)。其匹配規則和順序如下: 1.???? 精確路徑匹配。例子:比如servletA 的url-pattern為 /test,servletB的url-pattern為/* ,這個時候,如果我訪問的url為http://localhost/test,這個時候容器就會先進行精確路徑匹配,發現/test正好被servletA精確匹配,那么就去調用servletA,也不會去理會其他的servlet了。 2.???? 最長路徑匹配。例子:servletA的url-pattern為/test/*,而servletB的url-pattern為/test/a/*,此時訪問http://localhost/test/a時,容器會選擇路徑最長的servlet來匹配,也就是這里的servletB。 3.???? 擴展匹配,如果url最后一段包含擴展,容器將會根據擴展選擇合適的servlet。例子:servletA的url-pattern:*.action 4.???? 如果前面三條規則都沒有找到一個servlet,容器會根據url選擇對應的請求資源。如果應用定義了一個default servlet,則容器會將請求丟給default servlet(什么是default servlet?后面會講)。 |
???? 根據這個規則表,就能很清楚的知道servlet的匹配過程,所以定義servlet的時候也要考慮url-pattern的寫法,以免出錯。 ????? 對于filter,不會像servlet那樣只匹配一個servlet,因為filter的集合是一個鏈,所以只會有處理的順序不同,而不會出現只選擇一個filter。Filter的處理順序和filter-mapping在web.xml中定義的順序相同。 ??? 二,url-pattern詳解???????? 在web.xml文件中,以下語法用于定義映射: l? 以”/’開頭和以”/*”結尾的是用來做路徑映射的。 l? 以前綴”*.”開頭的是用來做擴展映射的。 l? “/” 是用來定義default servlet映射的。 l? 剩下的都是用來定義詳細映射的。比如: /aa/bb/cc.action 所以,為什么定義”/*.action”這樣一個看起來很正常的匹配會錯?因為這個匹配即屬于路徑映射,也屬于擴展映射,導致容器無法判斷。
使用servlet來下載文件,其原理非常簡單,只要得到文件的輸入流(或相應字節),然后寫輸出流即可。現就其中的幾個細節問題展開: 1. MIME類型的設置: Web 瀏覽器使用 MIME 類型來識別非 HTML 文檔,并決定如何顯示該文檔內的數據。 例如EXCEL文件的 MIME 類型是 "application/vnd.ms-excel "。要用servlet 來打開一個 EXCEL 文檔,需要將 response 對象中 header 的 contentType 設置成“application/vnd.ms-excel ”。 response.setContentType(contentType); 2. Content disposition HTTP response header中的content-disposition 允許 servlet 指定文檔表示的信息。使用這種header ,你就可以將文檔指定成單獨打開(而不是在瀏覽器中打開),還可以根據用戶的操作來顯示。 如果用戶要保存文檔,你還可以為該文檔建議一個文件名。這個建議名稱會出現在 Save As 對話框的“文件名”欄中。如果沒有指定,則對話框中就會出現 servlet 的名字。 servlet 中,將 header 設置成下面這樣: response.setHeader("Content-disposition","attachment;filename="+ "Example.xls" );
response.setHeader("Content-Disposition", "inline; filename="fliename) 點擊打開會在ie中打開。
需要說明的有三點: ? 中文文件名需要進行iso8859-1轉碼方可正確顯示: fileName = new String(fileName.getBytes("GBK"),"iso8859-1"); ? 傳遞的文件名,需要包含后綴名(如果此文件有后綴名),否則丟失文件的屬性,而不能自行選擇相關程序打開。 ? 有下載前詢問(是打開文件還是保存到計算機)和通過IE瀏覽器直接選擇相關應用程序插件打開兩種方式,前者如上代碼所示,后者如下: response.setHeader("Content-disposition","filename="+ "Example.xls" ); 3. 在研究文件的上傳及下載過程中,有幾點體會 程序的I/O操作往往是性能的瓶頸所在,java io定義了兩個基本的抽象類:InputStream和OutputStream,對于不同的數據類型比如磁盤,網絡又提供了不同的實現,java.io也提供了一些緩沖流(BufferedStream),使硬盤可以很快的讀寫一大塊的數據, 而Java基本的I/O類一次只能讀寫一個字節,但緩沖流(BufferedStream)可以一次讀寫一批數據,,緩沖流(Buffered Stream)大大提高了I/O的性能。所以: ?小塊小塊的讀寫數據會非常慢,因此,盡量大塊的讀寫數據 ?使用BufferedInputStream和BufferedOutputStream來批處理數據以提高性能 ?對象的序列化(serialization)非常影響I/O的性能,盡量少用
希望對剛開始學Hibernate的同學有所幫助。
一、saveorUpdate與unsaved-value
到底是sava還是update Hibernate需要判斷被操作的對象究竟是一個已經持久化過的持久對象還是臨時對象。 1).主鍵Hibernate的id generator產生 <id name="id" type="java.lang.Long"> <column name="ID" precision="22" scale="0" /> <generator class="increment" /> </id>
Project project = new Project(); project.setId(XXX); this.projectDao.saveOrUpdate(project);
1、默認unsaved-value="null" 主鍵是對象類型,hebernate判斷project的主鍵是否位null,來判斷project是否已被持久化 是的話,對project對象發送save(project), 若自己設置了主鍵則直接生成update的sql,發送update(project),即便數據庫里沒有那條記錄。 主鍵是基本類型如int/long/double/ 自己設置unsaved-null="0"。 所以這樣的話save和update操作肯定不會報錯。
2、unsaved-value="none", 由于不論主鍵屬性為任何值,都不可能為none,因此Hibernate總是對project對象發送update(project)
3、unsaved-value="any" 由于不論主鍵屬性為任何值,都肯定為any,因此Hibernate總是對project對象發送save(project),hibernate生成主鍵。
Hibernate文檔中寫到 saveOrUpdate()完成了如下工作: 如果對象已經在這個session中持久化過了,什么都不用做 如果對象沒有標識值,調用save()來保存它 如果對象的標識值與unsaved-value中的條件匹配,調用save()來保存它 如果對象使用了版本(version或timestamp),那么除非設置unsaved-value="undefined",版本檢查會發生在標識符檢查之前. 如果這個session中有另外一個對象具有同樣的標識符,拋出一個異常
2).主鍵由自己來賦值
<id name="id" type="java.lang.Long"> <column name="ID" precision="22" scale="0" /> <generator class="assigned" /> </id>
Project project = new Project(); project.setId(XXX); this.projectDao.saveOrUpdate(project);
1、默認unsaved-value="null" 這時有所不同,hibernate會根據主鍵產生一個select,來判斷此對象是否已被持久化 已被持久化則update,未被持久化則save。 2、unsaved-value="none",update對象,同上
3、unsaved-value="any" ,save對象, 如果自己自己設置的ID在數據庫中已存在,則報錯。
二、save與update操作
顯式的使用session.save()或者session.update()操作一個對象的時候,實際上是用不到unsaved-value的 在同一Session,save沒什么可說得 update對象時, 最直接的更改一個對象的方法就是load()它,保持Session打開,然后直接修改即可: Session s =… Project p = (Project) sess.load(Project.class, id) ); p.setName(“test”); s.flush(); 不用調用s.update(p);hibernate能察覺到它的變化,會自動更新。當然顯示調用的話也不會錯
Hibernate文檔中寫到 update()方法在下列情形下使用: 程序在前面的session中裝載了對象 對象被傳遞到UI(界面)層 對該對象進行了一些修改 對象被傳遞回業務層 應用程序在第二個session中調用update()保存修改
三、delete操作
刪除時直接自己構造一個project即可刪除 this.projectDao.delete(preojct);
以前刪除我是這樣寫的 public void deleteProject(String id) { Project project = (Project) this.projectDao.get(Project.class, id); if (project != null) { this.projectDao.delete(project); } 即這樣也是可以的 Project project = new Project(); project.setId(id); this.projectDao.delete(project).
如果有級聯關系,需要把級聯的子類也構造出來add進去,同樣可以刪除。
好了,羅嗦的夠多了。
1、遍歷workbook
代碼
-
??
-
POIFSFileSystem?fs?=?
new
?POIFSFileSystem(
new
?FileInputStream(filePath)); ??
-
HSSFWorkbook?wb?=?
new
?HSSFWorkbook(fs); ??
-
for
?(
int
?i?=?
0
;?i?<?wb.getNumberOfSheets();?i++)?{ ??
-
????HSSFSheet?sheet?=?wb.getSheetAt(i); ??
-
????
for
?(
int
?i?=?sheet.getFirstRowNum();?i?<?sheet.getLastRowNum();?i?++)?{ ??
-
????HSSFRow?row?=?sheet.getRow(i); ??
-
????????????
if
?(row?!=?
null
)?{ ??
-
????????。。。操作} ??
-
???????} ??
-
?????} ??
-
??
-
FileOutputStream?fos?=?
new
?FileOutputStream(objectPath); ??
-
??
-
swb.write(fos); ??
-
fos.close();??
2、得到列和單元格
代碼
-
HSSFRow?row?=?sheet.getRow(i); ??
-
HSSFCell?cell?=?row.getCell((
short
)?j);??
3、設置sheet名稱和單元格內容為中文
代碼
-
wb.setSheetName(n,?
"中文"
,HSSFCell.ENCODING_UTF_16);???? ??
-
cell.setEncoding((
short
)?
1
); ??
-
cell.setCellValue(
"中文"
);??
4、單元格內容未公式或數值,可以這樣讀寫
代碼
-
cell.setCellType(HSSFCell.CELL_TYPE_NUMERIC); ??
-
cell.getNumericCellValue()??
5、設置列寬、行高
代碼
-
sheet.setColumnWidth((
short
)column,(
short
)width); ??
-
row.setHeight((
short
)height);??
6、添加區域,合并單元格
代碼
-
Region?region?=?
new
?Region((
short
)rowFrom,(
short
)columnFrom,(
short
)rowTo,(
short
)columnTo); ??
-
sheet.addMergedRegion(region); ??
-
??
-
sheet.getNumMergedRegions()??
7、常用方法
根據單元格不同屬性返回字符串數值
代碼
-
public
?String?getCellStringValue(HSSFCell?cell)?{ ??
-
????????String?cellValue?=?
""
; ??
-
????????
switch
?(cell.getCellType())?{ ??
-
????????
case
?HSSFCell.CELL_TYPE_STRING: ??
-
????????????cellValue?=?cell.getStringCellValue(); ??
-
????????????
if
(cellValue.trim().equals(
""
)||cellValue.trim().length()<=
0
) ??
-
????????????????cellValue=
"?"
; ??
-
????????????
break
; ??
-
????????
case
?HSSFCell.CELL_TYPE_NUMERIC: ??
-
????????????cellValue?=?String.valueOf(cell.getNumericCellValue()); ??
-
????????????
break
; ??
-
????????
case
?HSSFCell.CELL_TYPE_FORMULA: ??
-
????????????cell.setCellType(HSSFCell.CELL_TYPE_NUMERIC); ??
-
????????????cellValue?=?String.valueOf(cell.getNumericCellValue()); ??
-
????????????
break
; ??
-
????????
case
?HSSFCell.CELL_TYPE_BLANK: ??
-
????????????cellValue=
"?"
; ??
-
????????????
break
; ??
-
????????
case
?HSSFCell.CELL_TYPE_BOOLEAN: ??
-
????????????
break
; ??
-
????????
case
?HSSFCell.CELL_TYPE_ERROR: ??
-
????????????
break
; ??
-
????????
default
: ??
-
????????????
break
; ??
-
????????} ??
-
????????
return
?cellValue; ??
-
????}??
8、常用單元格邊框格式
虛線HSSFCellStyle.BORDER_DOTTED 實線HSSFCellStyle.BORDER_THIN
代碼
-
public
?
static
?HSSFCellStyle?getCellStyle(
short
?type) ??
-
????{??? ??
-
???????HSSFWorkbook?wb?=?
new
?HSSFWorkbook(); ??
-
???????HSSFCellStyle?style?=?wb.createCellStyle(); ??
-
???????style.setBorderBottom(type);
??
-
????????style.setBorderLeft(type);
??
-
????????style.setBorderRight(type);
??
-
????????style.setBorderTop(type);
??
-
???????
return
?style; ??
-
????}??
9、設置字體和內容位置
代碼
-
HSSFFont?f??=?wb.createFont(); ??
-
f.setFontHeightInPoints((
short
)?
11
);
??
-
f.setBoldweight(HSSFFont.BOLDWEIGHT_NORMAL);
??
-
style.setFont(f); ??
-
style.setAlignment(HSSFCellStyle.ALIGN_CENTER);
??
-
style.setVerticalAlignment(HSSFCellStyle.VERTICAL_CENTER);
??
-
style.setRotation(
short
?rotation);
??
-
HSSFDataFormat?df?=?wb.createDataFormat(); ??
-
style1.setDataFormat(df.getFormat(
"0.00%"
));
??
-
cell.setCellFormula(string);
??
-
style.setRotation(
short
?rotation);
??
-
cell.setCellStyle(style); ??
10、插入圖片
論壇里看到的
代碼 - ??
- ??????ByteArrayOutputStream?byteArrayOut?=?new?ByteArrayOutputStream(); ??
- ??????BufferedImage?bufferImg?=?ImageIO.read(new?File("ok.jpg")); ??
- ??????ImageIO.write(bufferImg,"jpg",byteArrayOut); ??
- ??
- FileInputStream?fos?=?new?FileInputStream(filePathName+"/stencil.xlt");? ??
- fs?=?new?POIFSFileSystem(fos); ??
- ??
- HSSFWorkbook?wb?=?new?HSSFWorkbook(fs); ??
- HSSFSheet?sheet?=?wb.getSheetAt(0); ??
- HSSFPatriarch?patriarch?=?sheet.createDrawingPatriarch(); ??
- HSSFClientAnchor?anchor?=?new?HSSFClientAnchor(0,0,1023,255,(short)?0,0,(short)10,10);????? ??
- patriarch.createPicture(anchor?,?wb.addPicture(byteArrayOut.toByteArray(),HSSFWorkbook.PICTURE_TYPE_JPEG));??
|
最后更新:2006-10-30 20:12
一.POI簡介
Jakarta POI 是apache的子項目,目標是處理ole2對象。它提供了一組操縱Windows文檔的Java API
目前比較成熟的是HSSF接口,處理MS Excel(97-2002)對象。它不象我們僅僅是用csv生成的沒有格式的可以由Excel轉換的東西,而是真正的Excel對象,你可以控制一些屬性如sheet,cell等等。
二.HSSF概況
HSSF 是Horrible SpreadSheet Format的縮寫,也即“討厭的電子表格格式”。也許HSSF的名字有點滑稽,就本質而言它是一個非常嚴肅、正規的API。通過HSSF,你可以用純Java代碼來讀取、寫入、修改Excel文件。
HSSF 為讀取操作提供了兩類API:usermodel和eventusermodel,即“用戶模型”和“事件-用戶模型”。前者很好理解,后者比較抽象,但操作效率要高得多。
三.開始編碼
1 . 準備工作
要求:JDK 1.4+POI開發包
可以到
http://www.apache.org/dyn/closer.cgi/jakarta/poi/
最新的POI工具包
2 . EXCEL 結構
HSSFWorkbook excell 文檔對象介紹 HSSFSheet excell的表單 HSSFRow excell的行 HSSFCell excell的格子單元 HSSFFont excell字體 HSSFName 名稱 HSSFDataFormat 日期格式 在poi1.7中才有以下2項: HSSFHeader sheet頭 HSSFFooter sheet尾 和這個樣式 HSSFCellStyle cell樣式 輔助操作包括 HSSFDateUtil 日期 HSSFPrintSetup 打印 HSSFErrorConstants 錯誤信息表
3 .具體用法實例 (采用 usermodel )
如何讀Excel
讀取Excel文件時,首先生成一個POIFSFileSystem對象,由POIFSFileSystem對象構造一個HSSFWorkbook,該HSSFWorkbook對象就代表了Excel文檔。下面代碼讀取上面生成的Excel文件寫入的消息字串: try{ ?? POIFSFileSystem fs=new POIFSFileSystem(new FileInputStream("d:/workbook.xls")); ?? HSSFWorkbook wb = new HSSFWorkbook(fs); ?? HSSFSheet sheet = wb.getSheetAt(0); ?? HSSFRow row = sheet.getRow(0); ?? HSSFCell cell = row.getCell((short) 0); ?? String msg = cell.getStringCellValue(); ?? System.out.println(msg); ? }catch(Exception e){ ?? e.printStackTrace(); ? }
如何寫excel,
將excel的第一個表單第一行的第一個單元格的值寫成“a test”。
POIFSFileSystem fs =new POIFSFileSystem(new FileInputStream("workbook.xls"));
??? HSSFWorkbook wb = new HSSFWorkbook(fs);
??? HSSFSheet sheet = wb.getSheetAt(0);
??? HSSFRow row = sheet.getRow(0);
??? HSSFCell cell = row.getCell((short)0);
??? cell.setCellValue("a test");
??? // Write the output to a file
??? FileOutputStream fileOut = new FileOutputStream("workbook.xls");
??? wb.write(fileOut);
fileOut.close();
4 . 可參考文檔
POI 主頁:
http://jakarta.apache.org/poi/
,
初學者如何快速上手使用POI HSSF
http://jakarta.apache.org/poi/hssf/quick-guide.html
。
里面有很多例子代碼,可以很方便上手。
四.使用心得
POI HSSF 的usermodel包把Excel文件映射成我們熟悉的結構,諸如Workbook、Sheet、Row、Cell等,它把整個結構以一組對象的形式保存在內存之中,便于理解,操作方便,基本上能夠滿足我們的要求,所以說這個一個不錯的選擇。
------------------------------- 前面已經講過利用POI讀寫Excel,下面是一個用POI向Excel中插入圖片的例子。
官方文檔: Images are part of the drawing support. To add an image just call createPicture() on the drawing patriarch. At the time of writing the following types are supported: PNG JPG DIB It is not currently possible to read existing images and it should be noted that any existing drawings may be erased once you add a image to a sheet.
// Create the drawing patriarch. This is the top level container for // all shapes. This will clear out any existing shapes for that sheet.
通過HSSFPatriarch類createPicture方法的在指定的wb中的sheet創建圖片,它接受二個參數,第一個是HSSFClientAnchor,設定圖片的大小。
?1
package
?com.poi.hssf.test;
?2
?3
import
?java.io.FileOutputStream;
?4
import
?java.io.File;
?5
import
?java.io.ByteArrayOutputStream;
?6
import
?java.io.IOException;
?7
?8
import
?java.awt.image.BufferedImage;
?9
import
?javax.imageio.
*
;
10
11
import
?org.apache.poi.hssf.usermodel.HSSFWorkbook;
12
import
?org.apache.poi.hssf.usermodel.HSSFSheet;
13
import
?org.apache.poi.hssf.usermodel.HSSFPatriarch;
14
import
?org.apache.poi.hssf.usermodel.HSSFClientAnchor;;
15
16
public
?
class
?TestPOI?
{
17
18
????
public
?
static
?
void
?main(String[]?args)?
{
19
????????????FileOutputStream?fileOut?
=
?
null
;
20
????????????BufferedImage?bufferImg?
=
null
;
21
????????????BufferedImage?bufferImg1?
=
?
null
;
22
????????????
try
{
23
????????????????
24
??????????
//
先把讀進來的圖片放到一個ByteArrayOutputStream中,以便產生ByteArray
25
??????????ByteArrayOutputStream?byteArrayOut?
=
?
new
?ByteArrayOutputStream();
26
??????????ByteArrayOutputStream?byteArrayOut1?
=
?
new
?ByteArrayOutputStream();
27
??????????bufferImg?
=
?ImageIO.read(
new
?File(
"
d:/PieChart.jpg
"
));
28
??????????bufferImg1?
=
?ImageIO.read(
new
?File(
"
d:/fruitBarChart.jpg
"
));
29
??????????ImageIO.write(bufferImg,
"
jpg
"
,byteArrayOut);
30
??????????ImageIO.write(bufferImg1,
"
jpg
"
,byteArrayOut1);
31
??????????
32
????????
//
創建一個工作薄
33
????????HSSFWorkbook?wb?
=
?
new
?HSSFWorkbook();
34
????????HSSFSheet?sheet1?
=
?wb.createSheet(
"
new?sheet
"
);
35
????????
//
HSSFRow?row?=?sheet1.createRow(2);
36
????????HSSFPatriarch?patriarch?
=
?sheet1.createDrawingPatriarch();
37
????????HSSFClientAnchor?anchor?
=
?
new
?HSSFClientAnchor(
0
,
0
,
512
,
255
,(
short
)?
1
,
1
,(
short
)
10
,
20
);
38
????????HSSFClientAnchor?anchor1?
=
?
new
?HSSFClientAnchor(
0
,
0
,
512
,
255
,(
short
)?
2
,
30
,(
short
)
10
,
60
);
39
????????anchor1.setAnchorType(
2
);
40
????????
//
插入圖片
41
????????patriarch.createPicture(anchor?,?wb.addPicture(byteArrayOut.toByteArray(),HSSFWorkbook.PICTURE_TYPE_JPEG));
42
????????patriarch.createPicture(anchor1?,?wb.addPicture(byteArrayOut1.toByteArray(),HSSFWorkbook.PICTURE_TYPE_JPEG));
43
????????
44
????????????fileOut?
=
?
new
?FileOutputStream(
"
d:/workbook.xls
"
);
45
????????????
//
寫入excel文件
46
????????????wb.write(fileOut);
47
????????????fileOut.close();
48
????????
49
????????????}
catch
(IOException?io)
{
50
????????????????????io.printStackTrace();
51
????????????????????System.out.println(
"
io?erorr?:??
"
+
?io.getMessage());
52
????????????}
?
finally
53
????????????
{
54
????????????????
if
?(fileOut?
!=
?
null
)
55
????????????????
{
56
???????????????????????????
57
????????????????????
try
?
{
58
??????????????????????????????fileOut.close();
59
?????????????????????????}
60
????????????????????
catch
?(IOException?e)
61
????????????????????
{
62
????????????????????????????
//
?TODO?Auto-generated?catch?block
63
????????????????????????????e.printStackTrace();
64
?????????????????????}
65
????????????????}
66
????????????}
67
????}
68
}
目前整個開發社區對AOP(Aspect Oriented Programing)推崇備至,也涌現出大量支持AOP的優秀Framework,--Spring, JAC, Jboss AOP 等等。AOP似乎一時之間成了潮流。Java初學者不禁要發出感慨,OOP還沒有學通呢,又來AOP。本文不是要在理論上具體闡述何為AOP, 為何要進行AOP . 要詳細了解學習AOP可以到它老家http://aosd.net去瞧瞧。這里只是意圖通過一個簡單的例子向初學者展示一下如何來進行AOP.
為了簡單起見,例子沒有沒有使用任何第三方的AOP Framework, 而是利用Java語言本身自帶的動態代理功能來實現AOP.
讓我們先回到AOP本身,AOP主要應用于日志記錄,性能統計,安全控制,事務處理等方面。它的主要意圖就要將日志記錄,性能統計,安全控制等等代碼從商業邏輯代碼中清楚的劃分出來,我們可以把這些行為一個一個單獨看作系統所要解決的問題,就是所謂的面向問題的編程(不知將AOP譯作面向問題的編程是否欠妥)。通過對這些行為的分離,我們希望可以將它們獨立地配置到商業方法中,而要改變這些行為也不需要影響到商業方法代碼。
假設系統由一系列的BusinessObject所完成業務邏輯功能,系統要求在每一次業務邏輯處理時要做日志記錄。這里我們略去具體的業務邏輯代碼。
public interface BusinessInterface { public void processBusiness(); }
public class BusinessObject implements BusinessInterface { private Logger logger = Logger.getLogger(this.getClass().getName()); public void processBusiness(){ try { logger.info("start to processing..."); //business logic here. System.out.println(“here is business logic”); logger.info("end processing..."); } catch (Exception e){ logger.info("exception happends..."); //exception handling } } } 這里處理商業邏輯的代碼和日志記錄代碼混合在一起,這給日后的維護帶來一定的困難,并且也會造成大量的代碼重復。完全相同的log代碼將出現在系統的每一個BusinessObject中。
按照AOP的思想,我們應該把日志記錄代碼分離出來。要將這些代碼分離就涉及到一個問題,我們必須知道商業邏輯代碼何時被調用,這樣我們好插入日志記錄代碼。一般來說要截獲一個方法,我們可以采用回調方法或者動態代理。動態代理一般要更加靈活一些,目前多數的AOP Framework也大都采用了動態代理來實現。這里我們也采用動態代理作為例子。
JDK1.2以后提供了動態代理的支持,程序員通過實現java.lang.reflect.InvocationHandler接口提供一個執行處理器,然后通過java.lang.reflect.Proxy得到一個代理對象,通過這個代理對象來執行商業方法,在商業方法被調用的同時,執行處理器會被自動調用。
有了JDK的這種支持,我們所要做的僅僅是提供一個日志處理器。
public class LogHandler implements InvocationHandler {
private Logger logger = Logger.getLogger(this.getClass().getName()); private Object delegate; public LogHandler(Object delegate){ this.delegate = delegate; }
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { Object o = null; try { logger.info("method stats..." + method); o = method.invoke(delegate,args); logger.info("method ends..." + method); } catch (Exception e){ logger.info("Exception happends..."); //excetpion handling. } return o; } } 現在我們可以把BusinessObject里面的所有日志處理代碼全部去掉了。
public class BusinessObject implements BusinessInterface {
private Logger logger = Logger.getLogger(this.getClass().getName()); public void processBusiness(){ //business processing System.out.println(“here is business logic”); } } 客戶端調用商業方法的代碼如下:
BusinessInterface businessImp = new BusinessObject();
InvocationHandler handler = new LogHandler(businessImp);
BusinessInterface proxy = (BusinessInterface) Proxy.newProxyInstance( businessImp.getClass().getClassLoader(), businessImp.getClass().getInterfaces(), handler);
proxy.processBusiness(); 程序輸出如下:
INFO: method stats... here is business logic INFO: method ends... 至此我們的第一次小嘗試算是完成了。可以看到,采用AOP之后,日志記錄和業務邏輯代碼完全分開了,以后要改變日志記錄的話只需要修改日志記錄處理器就行了,而業務對象本身(BusinessObject)無需做任何修改。并且這個日志記錄不會造成重復代碼了,所有的商業處理對象都可以重用這個日志處理器。
當然在實際應用中,這個例子就顯得太粗糙了。由于JDK的動態代理并沒有直接支持一次注冊多個InvocationHandler,那么我們對業務處理方法既要日志記錄又要性能統計時,就需要自己做一些變通了。一般我們可以自己定義一個Handler接口,然后維護一個隊列存放所有Handler, 當InvocationHandler被觸發的時候我們依次調用自己的Handler。所幸的是目前幾乎所有的AOP Framework都對這方面提供了很好的支持.這里推薦大家使用Spring。
?1?<script> ?2??var?start=0; ?3?var?n; ?4??function?init(){ ?5???start++; ?6???} ?7??function?process(i){ ?8???n=setTimeout("init()",1000); ?9???if(start>i){ 10????clearTimeout(n); 11?????start=0; 12?//這里寫你需要執行的代碼 13???} 14?} 15?</script> 其中process(i) i為你要設置延遲的時間 秒為單位 關于timeout: 它其實就是一個循環而已,在循環里調用它的第一個參數,第2個參數是Thread.sleep的時間間隔,當然如果你不在合適的時候clearTimeout的話,它將成為一個死循環
|