Post blojsom blogs with Windows Live Writer

最近在 survey 新網銀廠商時,部落格剛好是新網銀功能上的一個需求項目,看到其中一家廠商使用 Windows Live Writer 來作部落格文章發佈的工具,看起來還蠻不錯的,於是便想來試試看。

安裝了 Windows Live Writer 後,依照安裝精靈的指示,發現 blojsom 這套 blog 套件並不在預設支援的清單中,不過幸好 blojsom 支援 MetaWeblog API (XML-RPC) 的介面,只要修改一下 properties,就可以將 XML-RPC 的遠端發佈功能啟動。

研讀了一下 blojsom 的相關說明,blojsom XML-RPC 的發佈網址為 http://your.blog.com/blojsom/xmlrpc/blog-id/,不過測試了一下,卻發生 404 Not Found。再檢查了一下,才發現原來我的 Apache 設定原先只有將 /blojsom/blog/* 才交給 Application Server 去處理,當然 /blojsom/xmlrpc 就會發生 Not Found的問題了。

修正問題後,果然 Windows Live Writer 就能正確的找到 隨想意誌,這篇文章就是用 Windows Live Writer 所編輯發佈的。

推薦大家試試 Windows Live Writer !!

Apache Digest Authentication – IE Workaround.

昨天設定好 Digest Realm Authentication 之後,測試過 IE7 / Firefox 2,看起來都沒什麼問題。結果今天到公司用 IE6 看的時候,竟然發現怎麼會有 400 Bad Request 錯誤..

Bad Request

查了一下子,才發現原來這是 IE 的 bug,原定身份檢核完畢後,任何連線 IE 都應該會自動帶上 Authorization 的 Header.

Authorization: Digest username=”cychien”, realm=”AWSTATS”, qop=”auth”, algorithm=”MD5″, uri=”/awstats/awstats.pl/”, nonce=”UBoBaJM3BAA=192135920c05c0d0ce0b89e69fbef6144b46ccad”, nc=00000002, cnonce=”a592556fde6ae1e828f360be6081d636″, response=”53580f5e52dd07e62ffa594865aeb1e2″

但碰到有 query string 的 URL 時,IE 就突槌了,摘錄 HTTP Header 資料如下就一切明瞭了

GET /awstats/awstats.pl/awstats.pl?framename=mainleft HTTP/1.1
….
….省略
Cookie: __utma=200320509.1007104159.1151628725.1187006067.1187006101.242; __utmz=200320509.1182908533.228.4.utmccn=(organic)|utmcsr=google|utmctr=%e9%9a%a8%e6%83%b3%e6%84%8f%e8%aa%8c|utmcmd=organic; phpbb2mysql_data=a%3A2%3A%7Bs%3A11%3A%22autologinid%22%3Bs%3A0%3A%22%22%3Bs%3A6%3A%22userid%22%3Bi%3A-1%3B%7D; control-commentControl=false; control-pluginControl=false; control-miscControl=false; control-mediaCastControl=false; rfolder-root=true; rfolder-??????=true; rfolder-??L???=true; __utmb=200320509; __utmc=200320509; JSESSIONID=GQGGcQPrYCQhzvCpyVKxJBGwmfNpy1cs2wXfy1bv1sgST9vSYyL1!-857858892

Authorization: Digest username=”cychien”, realm=”AWSTATS”, qop=”auth”, algorithm=”MD5″, uri=”/awstats/awstats.pl/awstats.pl?framename=mainleft“, nonce=”UBoBaJM3BAA=192135920c05c0d0ce0b89e69fbef6144b46ccad”, nc=00000003, cnonce=”8b98b9b1072e4c812443386f8363c07c”, response=”6d5c775889d9e631aed40cfafd19ce9a”

問題就出在 Authorization 的 uri 參數中,IE 的 bug 註定不會將 query string 附上,所以Apache 會認為與先前的 uri 不同,所以回覆 Bad Request.

針對微軟的老大心態,死就是不改他的 bug,所幸 Apache 從 2.0.51 之後也推出一組解決方案,藉以解決 IE query string 問題.

只要在 httpd.conf 中加上

BrowserMatch “MSIE” AuthDigestEnableQueryStringHack=On

只有針對 IE 瀏覽器,才會忽略 Authorization uri 參數的錯誤。經過測試果然有效。特別記錄一下..

Apache Basic / Digest Realm Authentication

最近想針對 Broso 特定系統統計功能做身份檢核的動作,於是稍微研究了一下針對 HTTP 協定中有關於身份驗證的機制。
HTTP 協定針對身份驗證分兩種模式,Basic Realm / Digest Realm。Basic Realm 僅將帳號密碼用標準 BASE64 來做編碼後,上送給 Web Server 來驗證,所以有心人其實可以透過 Sniffer 之類的軟體來進行側錄,再用 BASE64 解碼即可得知帳號密碼。

Digest Realm 則是為了解決上述 Basic Realm 的缺點,採用一般 Unix 儲存/驗證密碼的方式,每次瀏覽器要求連線,Web Server 會回覆一組隨機產生的 nonce value。瀏覽器則將帳號/密碼/nonce/GET(or POST)以及 URI 等參數,依指定的 hash function 做成訊息摘要( Digest),再將 Digest 上傳到 WebServer 驗證,如此一來上送的 Digest 每次皆會不同,藉以避免被有心人士所側錄。

以上可參考 RFC 2617 – HTTP Authentication: Basic and Digest Access Authentication

Apache 已經實作上述兩種機制,mod_auth 模組僅支援 Basic Realm。而 mod_auth_digest 則是支援 Digest Realm。不過如果 Apache 是抓預先編譯好的的 binary,或是編譯時未特別指定,那麼預設是不包含 mod_auth_digest 模組。

步驟一:重新編譯 APACHE.

由於我先前的 Apache 2.0.55 並未特別指明要啟用 mod_auth_digest,於是我重新下載 Apache 2.0.59 回來重新編譯。
執行 configure 指令如下

./configure –enable-auth-digest –prefix=<APACHE_INSTALL_DIR>

如此編譯時就會自動將 mod_auth_digest 加入。接著作 make, make install 就完成了。

步驟二:產生 Digest 帳號密碼檔

接下來先產生一組帳號密碼設定檔,每組帳號密碼都需針對特定的 realm 獨立設定。需使用 <APACHE_INSTALL_DIR>/bin/htdigest 指令來產生密碼檔。
指令格式

<APACHE_INSTALL_DIR>/bin/htdigest -c <path>/<digest_password_file_name> <realm name> <user id>

-c 代表要產生一個新的密碼檔,如果檔名已經存在,就會被覆蓋。所以如果想繼續增加新的帳號密碼,就無須加上 -c 即可
後面接上密碼檔的路徑與檔名,以及要檢核密碼的 “領域(realm)” (意指瀏覽器 popup 視窗,提示輸入帳號密碼時,上面顯示的名稱),最後是帳號名稱
之後 htdigest 會詢問兩次密碼後就完成建立密碼檔。

例如:我要針對 /mymrtg 與 /awstats 兩個目錄進行身份檢核,就需針對這兩個領域來建立帳號密碼

htdigest -c <somewhere>/digestpasswd “MYMRTG” <user_id>
htdigest <somewhere>/digestpasswd “AWSTATS” <user_id>

屆時瀏覽器提示帳號密碼輸入時,就會顯示目前要您輸入的領域是 MYMRTG 或是 AWSTATS

步驟三:調整 httpd.conf

針對每個要作身份檢核的的領域作設定

<Directory “<somewhere>/mymrtg”>
   AuthType Digest → 指定使用 Digest Realm Authentication
   AuthName “MYMRTG” → 指定領域名稱
   AuthDigestFile <somewhere>/<digest_password_file_name> → 指定帳號密碼檔路徑與檔名
   Require user <allowed user id> → 這裡指定允許使用的 user id

   …
   …
</Directory>

設定完畢重起 Apache 即可

圖片盜連進階版

續上篇 防賊妙招!如何防止圖片被小偷盜連?

後來發現部分圖片是我自己發佈在一些我常去的討論區,或者是從股溝大神搜尋結果中連結過來的,以及直接在網址列打入網址時,Referer 會是空白。所以特別把上面這些情形給開放了。

設定調整如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

# 防止人家盜連圖片, 擋 gif, jpg,png
SetEnvIfNoCase Referer "^http://broso\.twbbs\.org/" local_ref=1
SetEnvIfNoCase Referer "^http://www\.mobile01\.com/" external_ref=1
SetEnvIfNoCase Referer "^http://www\.play01\.com/" external_ref=1
SetEnvIfNoCase Referer "^http://www\.google\.com/" external_ref=1
SetEnvIfNoCase Referer ^$ blank_ref=1

<FilesMatch "\.([Gg][Ii][Ff]|[Jj][Pp][Gg]|[Pp][Nn][Gg] )$">
  Order deny,allow
  Deny from all
  Allow from env=local_ref
  Allow from env=external_ref
  Allow from env=blank_ref
  ErrorDocument 403 /thief.giff
</FilesMatch>

另外,還加了一個小圖,如果盜連圖片的人網頁上就會出現小偷的圖示 😛
小偷

嘿嘿..再繼續盜連沒關係])
圖片盜連

防賊妙招!如何防止圖片被小偷盜連?

這兩天把 AWSTATS 給裝起來了,順道把 Apache Access Log 格式改成 Combined 格式,一併將 Referer 與瀏覽器/OS的類型一併記錄在Access Log 中。
開始紀錄了以後才發現,原來有人盜連我文章上的圖片。

220.132.143.85 – – [30/Jul/2007:00:02:46 +0800] “GET /blojsom/resources/default/20050911_azureus/step3.JPG HTTP/1.1” 403 357 “http://www.btpig.com/html/200702/649999.html” “Mozilla/5.0 (Windows; U; Windows NT 5.1; zh-TW; rv:1.8.1.5) Gecko/20070713 Firefox/2.0.0.5”

按照 Referer 的網址連過去,果然又是大陸的網站。難怪先前沒事在看 Access Log 時,常常看到怎麼會只有圖片而沒有文章的的點擊紀錄。這下子得來想想怎麼防這些小偷。

股溝大神真是我的好朋友,有什麼問題問他,包準給你一個滿意的答覆。查了一下怎麼擋盜連圖片,大抵上都是說要透過 HTTP Header 上的 Referer 來達到阻擋的效果。

所謂 Referer 是指,瀏覽器在進行 HTTP Request 時,會自動將上一個 URL 放在 Referer 中。於是乎,如果是正常連結過來圖片,Referer 必然是從 broso.twbbs.org 所連結過來的。所以只要 Referer 不是 broso.twbbs.org,那就不用客氣了,殺無赦!!

於是調整了一下我的 Apache httpd.conf,增加參數如下:

1
2
3
4
5
6
7

# 防止人家盜連圖片, 擋 gif, jpg,png
SetEnvIfNoCase Referer "^http://broso\.twbbs\.org/" local_ref=1
<FilesMatch "\.([Gg][Ii][Ff]|[Jj][Pp][Gg]|[Pp][Nn][Gg] )$">
  Order deny,allow
  Deny from all
  Allow from env=local_ref
</FilesMatch>

稍微解釋一下

SetEnvIfNoCase 這一行,指的是任何 Referer 開頭是 http://broso.twbbs.org/ 都設定環境變數 local_ref 為 1
接著用 FilesMatch Tag,針對任何 gif/jpg/png 結尾的檔案進行檢查,有設定環境變數 local_ref 的要求才允許讀取

改完後,重起以後就可以了…

秋郊海報

從來沒想過自己也會需要學 PhotoShop。敗今年被選為部門福委之賜,公司的秋郊海報被交辦由我來製作。
以前 PhotoShop 對我來說是個超大型的繪圖處理軟體,我平常使用的不外乎圖檔 resize,調調顏色飽和度。殺雞焉用牛刀,這種技巧實在是用不著這套軟體,所以我也從來沒認真學過怎麼使用 PhotoShop。
這下子可糟了,硬著頭皮被逼著開始找資料學著使用。幸好有先前的秋郊海報圖檔可以參考,所以也不用一切重頭開始。大約搞了一個禮拜,才終於弄了三張出來,也許技巧熟練的人兩天就弄出來了說。:p

貼在這裡紀錄一下。

海報 1
海報 1

海報 2
海報 2

海報 3
海報 3

參考網址:
PhotoShop 之巧妙製作繩子及其應用

EXIFTool

過去拍完 raw 檔,回來後製轉檔為 jpeg 時,常用的軟體是 BreezeBrowser Pro,這套軟體好處是批次處理方便,出去旅遊回來動輒上百張的照片,如果一張張用 Canon 附贈的 DPP 來轉檔,那不知道要轉到什麼時候,這時候用 BreezeBrowser Pro 就很好用。然而,我覺得 BreezeBrowser Pro 轉出來的 jpeg 檔畫質總是沒有 DPP 來得細緻,但是為了節省時間似乎也只能暫時妥協。

DPP 從 2.0 以後就加入了批次處理的功能,同時還加上了 Canon 特有的 Picture Style 參數調整,於是批次處理照片不再是夢靨。最近 DPP 更新推出 3.0 版本,還加上了雜訊抑制的功能,讓原本雜訊純淨度有極佳表現的 Canon CMOS,這下子更是如虎添翼。

於是最近幾次的後製,就開始轉為使用 DPP 來批次轉檔。不過發現了另一個問題,DPP 似乎轉檔時,並不會將所有的 EXIF tag 完整複製到轉出的 jpeg 檔中,只保留少許重要的資訊,例如:曝光模式、白平衡、閃燈等資訊就付之闕如。真是有一好沒兩好。

於是又求助股溝大神,看看別人是如何解決這個問題,找了很久只有人提到這個問題,但也沒人說該怎麼解。最後找到有人提到 EXIFTool 這套小工具,可完整從 raw 檔複製所有的 EXIF tags 到指定的檔案中,於是就解決我的問題,只要將 DPP 轉出來的 jpeg 再用這個小工具從 raw 檔將 EXIF 複製過來即可,而且這個工具是用 perl 寫的,所以在 Linux 上寫個 shell script 去做批次複製更是沒問題。

寫了下面的 script 來做批次轉檔

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34


#!/bin/sh

if [ $# = 0 ]; then
    echo "Usage : copy_exif.sh <RAW_SOURCE_FOLDER>"
    exit
fi

RAW_SOURCE_FOLDER=$1

for file in `ls *`
do
    if [ -f $file ]; then
        PREV_FILENAME=`echo $file|awk -F"." '{print $1}'`
        EXT_FILENAME=`echo $file|awk -F"." '{print $2}'`

        RAW_FILE_LOWER=$RAW_SOURCE_FOLDER/$PREV_FILENAME.cr2
        RAW_FILE_UPPER=$RAW_SOURCE_FOLDER/$PREV_FILENAME.CR2
        EXIFTOOL_BACKUP_FILE=`echo "$file"_original`

        if [ -f $RAW_FILE_LOWER ]; then
            echo Copying EXIF tags from $RAW_FILE_LOWER to $file
            exiftool -TagsFromFile $RAW_FILE_LOWER $file
            rm $EXIFTOOL_BACKUP_FILE
        else
            if [ -f $RAW_FILE_UPPER ]; then
                echo Copying EXIF tags from $RAW_FILE_UPPER to $file
                exiftool -TagsFromFile $RAW_FILE_UPPER $file
                rm $EXIFTOOL_BACKUP_FILE
            fi
        fi
    fi
done

用法為在轉檔完畢的 jpeg 目錄下面執行,給定一個 raw 檔的來源目錄即可

copy_exif.sh <RAW_SOURCE_FOLDER>

Using Ramdisk on Windows Vista

過年時閒來無聊,便在我的 VAIO S56 上面裝 Vista Ultimate 試用版,裝完後效能評估得到的分數如下:

Vista 效能評估

Aero 特效雖然跑起來只有 2.3 分,但是實際上 Aero 特效啟動後也並不會感覺很慢,相反的我似乎覺得比 XP 還來得快了一點點??
也許是 VAIO 原版的 XP 內建一大堆有的沒的軟體。其實 S56 買來一年了,那些內建的軟體也只有剛買來時點開來玩玩,所以沒裝也沒什麼差。
試用了近一個月,常用的除了一些特定軟體因相容性的問題無法使用之外,整體來說還不錯,於是也想正式升級為正版軟體。

為了讓整體效能跑起來更順一些,我也將系統記憶體一次升級到 2G 滿檔,雖然使用起來沒什麼特別感覺,但是心理層級的爽度卻是大大的加分。
上禮拜在 Yahoo 買下了 Vista 的 Home Premium 版,拿到貨之後便迫不及待裝上去並且啟用成功,使用正版軟體跟之前裝好 XP 後還要到處找破解的那種心情真是差太多了,雖然正版軟體還真是不便宜。

不過今天這篇主要不是來聊安裝 Vista 後的爽度,主要是要來記錄一下怎麼在 Vista 上面安裝 Ramdisk 的軟體。
Ramdisk 的類似軟體很多,以前用 XP 時,常使用 Gavotte Ramdisk 這套軟體,主要是因為這套免費,沒有使用容量上的限制,用起來又很穩定,所以拿來當 IE / Firefox 的暫存目錄碟是最佳不過。

不過在 Vista 上面安裝時直接按下 Install Ramdisk,卻會發生 Fail 的訊息。

Install Failed!

研讀了一下 Gavotte Ramdisk 的 Readme 後才發現,原來其實 Gavotte 在撰寫這套軟體時,並沒有撰寫 ramdisk.exe 這個安裝的 GUI 介面,而是必須靠手動方式在 Registry 中設定相關的參數,Registry 的路徑如下

[HKEY_LOCAL_MACHINE\SYSYEM\CurrentControlSet\Services\RRamdisk\Parameters]

稍微看了一下裡面的參數設定,其中

Regidtry Parameters

DiskSizeM 是指定 Ramdisk 的磁碟大小,以 MB 計算,也可以使用 DiskSizeK 來以 KB 為計算單位,其中 DiskSizeK 設定為優先。
DriveLetter 是指定 Ramdisk 使用的磁碟機代號。
MediaType 則是指定磁碟機的類型,預設為 2 (Fixed Media)。

於是便開始手動安裝 Gavotte Ramdisk 了

Step 1. 安裝 Gavotte Ramdisk Driver.

開啟裝置管理員,選擇 執行–>新增傳統硬體,再選擇 安裝我從清單中手動選取硬體(進階選項) –> 顯示所有裝置 –> 從磁片安裝,然後瀏覽至 Gavotte Ramdisk 解開目錄中的 RRAMDISK.INF


最後按下開啟舊檔 –> 確定,接下來便看到硬碟一陣狂轉,然後在裝置管理員便多了一項裝置

Step 2. 修改 Registry 參數

打開 Regedit,並瀏覽至 [HKEY_LOCAL_MACHINE\SYSYEM\CurrentControlSet\Services\RRamdisk\Parameters]

雙擊 DiskSizeM 參數,修改磁碟大小為 512M
如果要改磁碟機代號,就必須一道修改 DriveLetter 參數
改完後重新開機

Step 3. 修改 IE 或 Firefox 的暫存目錄路徑

IE 修改方式很簡單,從 網際網路選項 中按照下圖修改後重新登入即可

Firefox 修改路徑比較麻煩,從網址列打入 about:config,然後在篩選器中輸入 browser.cache.disk.parent_directory
如果沒找到,就自行新增一個字串設定,內容就是完整的目錄路徑即可,設定完畢後重新開啟 Firefox 即可生效

Nikon S7 曲線機 開箱測試

Reyna 過年前想買台傻瓜數位相機給家裡用,研究很久決定目標為 Nikon S7,710 萬畫素/3″ LCD/數位防手振/臉部辨識功能。於是趁同學會後,帶她到
全台最大水貨商億華去敗家。到了現場真是人山人海,億華從先前在芝山站前的小小店面,擴展到目前雙拼店面的規模,我想服務及後續保固處理應該是他最大的賣點吧。

好不容易擠到了櫃臺前,請小姐拿 S7 出來把玩測試,3″ LCD 果然是明亮動人,情境模式超多,真的挺適合初學者,名符其實的傻瓜數位相機。最後測完以後,付了錢後就趕緊回家來開箱拍照。

未開封 Nikon S7 盒裝

打開上蓋後 S7 靜靜的躺在盒中,安全的包裹在塑膠保護袋中

鏘鏘鏘鏘…S7 的初見靚影

側面是亮銀握把,閃閃動人,不過也很容易留下指紋

正背面,寬大的 3″ LCD 螢幕及操作介面

S7號稱曲線機,正上方的操作介面,由左至右分別為
啟動/關閉 臉部辨識功能、錄影收音麥克風、電源開關、電源指示燈、Zoon In/Out

多買了記憶卡/電池套件,另外還附了清潔組及桌上型小腳架

套件也另外附贈一個皮套,挺有質感的

S7 裝進皮套後,質感加倍

S7 的屁屁下方還有傳輸接點,另附底座以便與電腦連接或做充電使用

多來幾張 S7 各個角度的照片




這次去億華順道買了兩片濾鏡,一片是要給 24-105mmF4L 用的,原先是拿 17-40mmF4L 的濾鏡先頂著用,兩者剛好都是 77mm 口徑,所以可以共用
另一片是 Suzuki 請我幫他的 17-85mm 買的,聽說原來濾鏡的在日本摔破了。

銷魂的 B+W 字樣

下面是 S7 實際拍出來的測試照,試拍結果覺得 S7 的近拍能力真是強,不過高 ISO 的雜訊還是嚴重的有點無法接受
也許是已經習慣 Canon 高 ISO 的可用性了吧






DBUtils 如何處理 oracle.sql.TIMESTAMP

接續上篇 java.sql.Date v.s. java.sql.Timestamp in Oracle 9i

Oracle JDBC 的 FAQ 中提到,在 Oracle 9i 中如果要取得時間部分的資料,最好也最標準的方法是將資料型態由 DATE 改為 TIMESTAMP。經過實際測試將資料型態改為 TIMESTAMP 之後,Oracle 9i JDBC Driver 並非如預期地將 TIMESTAMP 轉為 java.sql.Timestamp,而是轉型為 oracle.sql.TIMESTAMP,應用程式必須再呼叫一次 oracle.sql.TIMESTAMP.timestampValue(),才能正確轉回 java.sql.Timestamp,這對我原先已經撰寫完成的許多程式來說,必須一一修改,相當麻煩。

所幸原先程式係透過一個共用元件來使用 DBUtils,經過檢視 Jakarta Commons DBUtils 的原始碼後,問題出在 org.apache.commons.dbutils.BasicRowProcessor 的 toMap() 函式

1
2
3
4
5
6
7
8
9
10
11
12
13


    public Map toMap(ResultSet rs) throws SQLException {
        Map result = new CaseInsensitiveHashMap();
        ResultSetMetaData rsmd = rs.getMetaData();
        int cols = rsmd.getColumnCount();

        for (int i = 1; i <= cols; i++) {
            result.put(rsmd.getColumnName(i), rs.getObject(i));
        }

        return result;
    }

裡面使用 ResultSet.getObject() 來直接取得 JDBC Driver 回傳的型態,而 Oracle 9i JDBC Driver 遇到資料型態為 DATE,則回傳 java.sql.Date,資料型態為 TIMESTAMP,則回傳 oracle.sql.TIMESTAMP。真不知道是 Oracle 的 bug 還是故意這麼搞的,所以 DBUtils 得到的就絕對不會是 java.sql.Timestamp

思考之後,最好的方式應該是寫一個 Wrapper 去繼承 org.apache.commons.dbutils.BasicRowProcessor,然後只改寫 toMap()函式如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32


public class BasicRowProcessorWrapper extends BasicRowProcessor {
    /**
     * 繼承自 org.apache.commons.dbutils.BasicRowProcessor
     * 由於 Oracle 9i JDBC Driver 遇到資料型態為 DATE 會轉為 java.sql.Date
     * 導致僅留下日期而遺失時間的部分,遇到資料型態為 TIMESTAMP 會轉為 oracle.sql.TIMESTAMP
     * 必須自行再轉為 java.sql.Timestamp,因此改寫 toMap() 函式
     * @param rs ResultSet
     * @return Map
     * @throws SQLException
     */
    public Map toMap(ResultSet rs) throws SQLException {
        Map result = new CaseInsensitiveHashMap();
        ResultSetMetaData rsmd = rs.getMetaData();
        int cols = rsmd.getColumnCount();

        for (int i = 1; i <= cols; i++) {
            Object obj = rs.getObject(i);
            if ("oracle.sql.TIMESTAMP".equals(obj.getClass().getName())) {
                result.put(rsmd.getColumnName(i), rs.getTimestamp(i));
            } else if (obj instanceof java.sql.Date) {
                result.put(rsmd.getColumnName(i), rs.getTimestamp(i));
            } else  {
                result.put(rsmd.getColumnName(i), obj);
            }
        }

        return result;
    }
}

遇到 JDBC Driver 型態為 oracle.sql.TIMESTAMP 或是 java.sql.Date,則強迫使用 getTimestamp() 函式來轉型為 java.sql.Timestamp,如此一來,即使未來 DBUtils 改版更新,也無須更動舊有程式

下載相關原始碼