第一次用 Zoundry 客戶端工具來發布博客,WordPress 還是不錯的博客了,提供了 XML-RPC 方式的遠程提交接口,我們可以比較容易的把我們的博客發布到 WordPress 上。
老外對這方面的支持工作還是做的不錯的,國內的同類系統往往只考慮到功能,好一點的考慮到性能,而在這些新技術帶來的擴展性的增強上似乎沒有太多的理解,雖然 WordPress 在功能上和國內的很多博客有一定的差距,但是人家支持插件,這樣就可以讓地球人都上來擴展一把。Eclipse 的插件風風火火的做了幾年,現在人似乎沒有不用插件開發的了。
老外在 Web 2.0 中又很多好的思想,技術,拿到國內來就有點變味了,雖說國人在 Web 2.0 技術上跟進的速度還是相當的快,不過思想還是又相當的差距的。
要好好學學人家做東西的思想,而不僅僅是技術。
posted @
2008-01-04 16:42 steady 閱讀(997) |
評論 (0) |
編輯 收藏
該文章被發布在我的新博客中:http://4think.cn/blog/index.php/archives/25
市面上這么多的IM工具,每次打開的時候就要開上一堆,還不時的有個新的IM工具出來,加上一兩個及其有吸引力的功能,然后又不得不裝上,搞的每次開機以后總是要開上一大堆的IM,比如QQ啦,MSN啦,還有Yahoo,Google Talk,飛信,Skype,真的挺麻煩的。
一年前的時候,突然聽說 Yahoo 可以和 MSN 互通了,于是從此就沒用過 MSN 了,也是對 Microsoft 歧視國內用戶的一種不滿吧,這么多IM工具,最不穩定的也最為常用的要屬 MSN 了,雖然飛信這樣“國”字號的軟件似乎更加的不爭氣,就原諒他吧,誰叫他是咱最有錢的移動運營商呢。可以說,MSN 的掉線率是相當的高,登錄速度也是驚人的,在公司內部傳文字的效率呢更加不用說了,反正沒有人走的快。不過據我們去過美國的一些同事說,MSN 在美國速度是非常快的,包括其下屬的 hotmail,MSN Space,怪不得這么被推崇了,不過沒辦法,畢竟是在國內,屬于不被重視的使用群體,大不了就不用了,于是機子里再也沒有出現過 MSN,所有重要的好友都加到 Yahoo 里了。
其實說來 Yahoo 也是個比較不爭氣的東西,功能嘛,沒啥強的,不過吃內存的能力還挺強,印象中也就 Skype 可以和他有的一拼,不過好歹人家 Yahoo 還是比較重視中文用戶的,起碼光纜斷的時候還是能用的,而且相關的本地化服務也還是有一定的可用性的,Yahoo的郵件提示是最為迅速的,基本上是新郵件來到5秒之內就得讓你知道,這個功能還是挺體貼用戶的,其實我的一些 IM 的一個重要作用就是 check email,比如說 Google Talk。Yahoo 的客戶端程序其實是比較不穩定的,群聊功能是個殺手,一次領導通知事情,讓大家開個會,結果一位老兄圖方便,Yahoo 把大家全部加進來了,大家的機器全部死翹翹,只好 reset 重啟,自此以后,這個功能再也不敢使用了,Yahoo 工具箱里有個看股市行情的插件,不過這個曲線也太不本地化了,中午休息的時間也畫在上面,一條長長的直線,怎看都別扭。沒辦法啊,公司里唯一允許的 IM 工具,不得不裝,也就不得不去忍受這些了。
Google Talk 其實是我用的最多的,極為簡潔,擁有我需要的主要功能,email 通知,語音,文本聊天,傳文件(大家都喜歡裝中文版的,沒這個功能,所以也基本找不到人傳文件),其實還有一點重要的就是所有聊天記錄都會保存在 Gmail 里,在哪都不會丟失,也很連貫,這對于我們經常討論需求的人就不會有上句沒下句的了。也不用擔心聊天記錄留在本地泄密。另外還有一點,傳代碼的時候絕對不會變成一堆笑臉什么的。Google Talk 其實功能上是相當有限的,但是我卻非常喜歡,簡潔就是美了。
下面隆重出場的是唯利是圖、忘恩負義外加極端不安全的 QQ 了,如果不是這么多好友在里面,我是不會開 QQ 的,當然 QQ 作為國內用的最多的 IM 工具(其實叫他聊天工具更確切),QQ 還是有相當多的優勢的,首先網絡穩定性好,傳文件速度快,有遠程協助功能,語音質量也不錯,可以看 IP(還不都是珊瑚蟲的功勞,被忘恩負義的騰訊扼殺了),有群聊功能,也是最適合某些夜晚不甘寂寞的人尋找刺激的工具了,其他的功能我是不大能想到的了,更不用說去用了,所以嘛,QQ 對我來說,太大了,太花哨了,對公司來說也是的,基本上正規的公司,沒有哪個不封 QQ 的,所以嘛,QQ 只能被遠遠的拒之于企業應用的門外,騰訊的 RTX 也就不是那么容易進入企業市場的,誰讓你這么花哨,看了就不想好好工作了。
Skype 這個東西嘛,對我用處不大,自從充值卡被封事件以后就不再常開了,開會的時候才會去用,畢竟多人語音聊天功能還是挺不錯的。
國外的大部分 IM 工具都開放互通了,包括 MSN 和 Yahoo,Google Talk 也在和 MS 談互通的問題,國內的 IM 互通嘛,似乎完全不可能,國外那幾家都不是靠 IM 吃飯的,騰訊就不一樣了,如果不保持其 QQ 的占有率,瘋狂的扼殺非“官方”的客戶端,LumaQQ 這么優秀的跨平臺解決方案也就被騰訊自己和諧掉了,最近對珊瑚蟲下狠手也表示其在此方面的決心,呵呵,我的 QQ 從此不升級了。
posted @
2008-01-02 11:27 steady 閱讀(2030) |
評論 (4) |
編輯 收藏
每個人在開發的時候,都會根據自己的喜好選擇一些好用的工具,當然,通過一些年頭的積累,我自己也有了這么一些順手的工具,就把這些還不錯的東西拿出來和大家分享吧。
CyberArticle (網文快捕)
我們在查看資料,或者遇到問題上網搜索的時候,經常會想把自己看到的一些好東西保存下來,以后需要用的時候可以找到,有人把東西復制下來保存成文本,有人用 Word 文檔,也有人直接保存頁面,這些方法固然是可以,不過以后找起來可就比較麻煩了。我們需要一個帶分類的文檔管理工具。
在對一堆工具的篩選之后,我選中了 CyberArticle,也就是網文快捕,安裝以后,在瀏覽頁面時,IE 和 FF 的右鍵會出現保存全文,保存選中部分這樣的選項,我最喜歡的是保存選中部分這個功能,畢竟我們并不需要一個網頁中一些不相關的文字和圖片。CyberArticle 可以完整的把文章內容或選中部分的內容保存下來,無論是圖片或者其他什么的,都能較好的支持。在保存下自己喜歡的內容后,我們可以手工把這些內容分類,以后會比較容易的找到自己需要的東西。
另外 CyberArticle 中比較有用的功能是生成電子書。我們在網上搜集到一堆某一類別的文章,為了與他人分享或者便于攜帶,我們可以把這一個獨立的類別的內容導出成 CHM 或 EXE 版本的電子書。
CyberArticle 可以到 http://www.wizissoft.com/cn/index.aspx 下載,強烈建議使用最新的 5.0 版(只要25塊錢),舊的版本會有相當一部分的文章保存不下來。
posted @
2007-11-29 10:59 steady 閱讀(2088) |
評論 (11) |
編輯 收藏
昨天看到新聞,IBM 在其網站上放出了 Lotus Symphony 的 beta 版,看上去有點 Office2007 的一套辦公產品,最重要的是它是基于 Eclipse-RCP 平臺的,如果說 IBM 讓 Lotus 去做一個標準的 Windows 應用像 Office2007 到沒有什么奇怪的,關鍵在于它是 Eclipse 平臺的,IBM 在一個強大的 Eclipse 平臺上,構建出了一個向 Microsoft 最核心產品叫板的應用,這大大的壯大了 Java 愛好者的威風。
過去我們 Swing / SWT 做的東西似乎很難有直接面向普通用戶的優秀的應用,這次 IBM 是代 Java 出了重重的一拳,Eclipse 平臺不但是與 Microsoft 的 Visual Studio 叫板,甚至可以和 Office 叫板了。
從另一方面來說,從 Lotus Symphony 的推出,IBM 進一步亮相了 Eclipse RCP 的高級 UI 組件,傳統的 Eclipse 開發出的東西,千篇一律,沒有太大的界面差別,但是 Lotus Symphony 上卻不太容易讓人聯想到 Eclipse,除了看到啟動畫面上 build on eclipse 的只有,還有一些熟悉的菜單項,和 PlugIn 相關的內容才會發現,哇,這個酷酷的應用原來是 Eclipse 平臺上的產品。
當然 Lotus Symphony 并沒有說是開源的,這些新的,酷酷的 UI 組件也并沒有向開源社區開放,按照 IBM 最近幾年的慣例,遲早是要捐出來的,但前提是先做幾套東西,賣點錢再說,Eclipse WTP 的很多東西來源于 WSAD,很多 Eclipse 的插件也是來源于 Rational 的產品,只是 IBM 覺得沒有什么商業價值了,才捐出來。
其實我是非常希望 IBM 能盡快和大家分享 Lotus Symphony 的成功經驗,也希望更多的 Eclipse 愛好者能夠開發出更多強大的應用,特別是桌面級應用,讓更多的人看到,Java 在成長,在進取。
---------------------------------------------------
順便做個小廣告 鏈客中國 www.linkedcast.cn 上線運行,歡迎廣大 Blogger 使用
posted @
2007-09-23 08:40 steady 閱讀(1139) |
評論 (8) |
編輯 收藏
Java Web 應用似乎總有這樣的情況,有事沒事總是要在 URL 后面加上個 jsessionid,而且似乎不能使用配置的方式直接禁用 URL 傳遞 sessionid,這樣,就比較容易造成安全性的問題,或者在瀏覽器地址欄里留下一堆很不好看的地址,在 Struts2 中,使用了 url 標簽的所有鏈接,甚至 CSS, JS 這樣的東西,都會加上 jsessionid,如何去禁用呢,搜索國內的相關文章,無功而返,詢問我們過去的架構師,也沒有做過,只好想辦法去找國外的網站,找到了這樣的一篇文章。
http://randomcoder.com/articles/jsessionid-considered-harmful
通過加入 Filter 的方式過濾掉 URL 中包含的 jsessionid,再重新包裝 Response 返回給瀏覽器。
因為沒有太多東西,就不多解釋了,大家拿了用就可以了。
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpServletResponseWrapper;
import javax.servlet.http.HttpSession;
import java.io.IOException;
/**
* Servlet filter which disables URL-encoded session identifiers.
* <p/>
* <pre>
* Copyright (c) 2006, Craig Condit. All rights reserved.
* <p/>
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* <p/>
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* <p/>
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
* </pre>
*/
@SuppressWarnings("deprecation")
public class DisableUrlSessionFilter implements Filter {
/**
* Filters requests to disable URL-based session identifiers.
*/
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
// skip non-http requests
if (!(request instanceof HttpServletRequest)) {
chain.doFilter(request, response);
return;
}
HttpServletRequest httpRequest = (HttpServletRequest) request;
HttpServletResponse httpResponse = (HttpServletResponse) response;
// clear session if session id in URL
if (httpRequest.isRequestedSessionIdFromURL()) {
HttpSession session = httpRequest.getSession();
if (session != null) session.invalidate();
}
// wrap response to remove URL encoding
HttpServletResponseWrapper wrappedResponse = new HttpServletResponseWrapper(httpResponse) {
@Override
public String encodeRedirectUrl(String url) {
return url;
}
@Override
public String encodeRedirectURL(String url) {
return url;
}
@Override
public String encodeUrl(String url) {
return url;
}
@Override
public String encodeURL(String url) {
return url;
}
};
// process next request in chain
chain.doFilter(request, wrappedResponse);
}
/**
* Unused.
*/
public void init(FilterConfig config) throws ServletException {
}
/**
* Unused.
*/
public void destroy() {
}
-------------------------------------------------------------------------------------------------
順便做個小廣告 鏈客中國 www.linkedcast.cn 上線運行,歡迎廣大 Blogger 使用
posted @
2007-09-08 20:13 steady 閱讀(5682) |
評論 (4) |
編輯 收藏
在過去使用 Spring 整合 Hibernate 的時候,都是用這樣的配置方式。
<bean id="sessionFactory" lazy-init="true"
class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
<property name="mappingResources">
<list>
<value>resources/icustomer/Contact.hbm.xml</value>
<value>resources/icustomer/Customer.hbm.xml</value>
</list>
</property>
.
</bean>
每當需要加入一個新的 VO 時,我需要過來修改配置文件,來引入對新的 VO 的支持。現在我使用的時候,是這么配的:
<bean id="sessionFactory" lazy-init="true"
class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
<property name="mappingLocations">
<list>
<value>classpath:resources/**/*.hbm.xml</value>
</list>
</property>
.
</bean>
做項目開發的時候,就再也沒有改過配置。
posted @
2007-08-17 13:58 steady 閱讀(1932) |
評論 (5) |
編輯 收藏
因為有一個 Struts2 網站發布,需要整合一個論壇來使用,公司的一個項目過去曾經整合過一個英文論壇,但似乎不能滿足我們的需求,需要找一個成熟穩定的中文論壇,與我們的系統結合。
最終選擇了 Discuz 作為我們的論壇系統,主要是因為它提供了一套可用的 Passport API,來直接與我們現有系統進行整合。
下面摘錄 Discuz 文檔中的內容來說明整合原理,隨后的幾篇中,將詳細描述具體的整合過程。
假設已設置如下變量或參數
- 掛接 Discuz! Passport 的應用程序假設為一套 PHP 語言編寫的 CMS 系統
- Discuz! 的 URL 為 http://www.myforums.com
- 應用程序的 URL 為 http://www.mywebsite.com
- 應用程序的注冊頁面為 http://www.mywebsite.com/register.php
- 應用程序的登錄頁面為 http://www.mywebsite.com/login.php?action=login
- 應用程序的退出頁面為 http://www.mywebsite.com/login.php?action=logout
開啟通行證后的用戶登錄流程
- 如果用戶在論壇點擊“登錄”,則轉向到事先設置好的應用程序登錄頁面(http://www.mywebsite.com/login.php?action=login),并在登錄頁面的 URL 中加入參數 forward(加入 forward 后的鏈接例如 http://www.mywebsite.com/login.php?action=login&forward=http://www.myforums.com/index.php),用于在登錄后將用戶導向到指定的 URL。
- 應用程序收到此請求后,按照慣例生成表單,并增加一個表單變量,將 GET 方式傳遞過來的 forward 參數通過表單進行傳遞。
- 用戶在應用程序的表單中填寫登錄信息,并提交到應用程序的登錄驗證程序。應用程序驗證用戶提交的用戶名和密碼的合法性:
- 如果不通過:提示用戶名密碼錯誤,要求其返回上一頁重新填寫。
- 如果通過,需要進行如下操作:
- 設置自身 Cookie 或 Session,使得應用程序自身處于登錄狀態。
- 檢查表單中是否提交了 forward 變量,如有,則意味著登錄請求可能是由論壇而來,將此變量傳遞到后面的請求中。如沒有,自行生成 forward 變量,使得論壇登錄后能夠跳轉回到應用程序中。
- 通過 header('Location: http://www.myforums.com/api/passport.php?action=login&auth=xxx&forward=http://yyy&verify=zzz') 的方式,將登錄請求傳遞到論壇進行處理。其中 auth 用來將用戶信息與資料以特定的格式,加密傳遞給論壇,forward 用于告知論壇 Passport API 完成自身操作后轉向到的 URL 地址,verify 用于驗證前面兩個變量的有效性。auth、forward、verify 格式與結構將在后面進行說明。
- Discuz! Passport API 在接收到由應用程序通過 header() 提交過來的請求后,進行如下操作:
- 根據 verify 判斷 auth 和 forward 變量是否合法,如合法則繼續,否則終止。
- 將 auth 根據既定算法解密,并還原成數組,數組的內容與格式將在后面進行說明。根據數組中的內容,檢查此用戶是否存在。如存在,則根據上述數組中的內容 UPDATE 論壇中相應的用戶資料。如不存在,則使用數組中的信息 INSERT 到論壇用戶資料表中。
- 論壇設置 Cookie 或 Session,使得論壇自身處于登錄狀態。
- 根據應用程序反饋的 forward 值,通過 header('Location: http://xxx') 的形式將頁面跳轉到 forward 變量指定的 URL。
- 至此,登錄流程結束
開啟通行證后的用戶退出流程
- 如果用戶在論壇點擊“退出”,則轉向到事先設置好的應用程序退出頁面(http://www.mywebsite.com/login.php?action=logout),并在登錄頁面的 URL 中加入參數 forward(例如 http://www.mywebsite.com/login.php?action=login&forward=http://www.myforums.com/index.php),用于在退出后將用戶導向到指定的 URL。
- 應用程序收到此請求后,清除自身 Cookie 或 Session,使得應用程序自身處于非登錄狀態。
- 檢查是否提交了 forward 變量,如有,則意味著登錄請求可能是由論壇而來,將此變量傳遞到后面的請求中。如沒有,自行生成 forward 變量,使得論壇登錄后能夠跳轉回到應用程序中。
- 通過 header('Location: http://www.myforums.com/api/passport.php?action=logout&forward=http://yyy&verify=zzz') 的方式,將退出請求傳遞到論壇進行處理。其中 forward 用于告知論壇 Passport API 完成自身操作后轉向到的 URL 地址,verify 用于驗證 forward 變量的有效性。forward、verify 格式與結構將在后面進行說明。
- Discuz! Passport API 在接收到由應用程序通過 header() 提交過來的請求后,進行如下操作:
- 根據 verify 判斷 forward 變量是否合法,如合法則繼續,否則終止。
- 清楚論壇的 Cookie 或 Session,使得論壇自身處于非登錄狀態。
- 根據應用程序反饋的 forward 值,通過 header('Location: http://xxx') 的形式將頁面跳轉到 forward 變量指定的 URL。
- 至此,退出流程結束。
開啟通行證后的用戶注冊流程
posted @
2007-08-11 17:30 steady 閱讀(3288) |
評論 (3) |
編輯 收藏
Reschedule
rescheduleJob(String triggerName, String groupName, Trigger newTrigger)
在進行 reschedule 操作的時候,我們通常只需要修改 Trigger 的時間,這時候我們只需要重新 new 一個含有新的 Schedule 時間的 Trigger 對象,reschedule 一下就可以了。
Unschedule
unscheduleJob(String triggerName, String groupName)
進行 unschedule 的時候,我們只需要知道名字和 group 就可以了。
進行 Schedule 操作前后,Database 中的相關數據都會被更改,在執行 unschedule 或者該 schedule 已經執行過,數據庫中的 trigger 信息都會被刪除。
posted @
2007-08-03 09:00 steady 閱讀(1672) |
評論 (4) |
編輯 收藏
Quartz 是一個強大的企業級 Schedule 工具,也是目前最好的開源 Schedule 工具,最近因為項目的需要,簡單的用到了 Quartz 的一些功能,對項目中使用 Quartz 的一些問題做簡單的記錄。
在 Quartz 的應用中,我們用到了以下的一些東西,ScheduleFactory, Scheduler, Job, JobDetail, Trigger,簡單說明一下他們的用途。
SchedulerFactory 是 Scheduler 的工廠,我們可以從中獲得受工廠管理的 Scheduler 對象。
SchedulerFactory scheduleFactory = new StdSchedulerFactory();
Scheduler scheduler = scheduleFactory.getScheduler();
Scheduler 是一個計劃集,其中可以包含多個 JobDetail 和 Trigger 組成的計劃任務。
我們可以從 SchedulerFactory 中取得 Scheduler。
接口Job是每個業務上需要執行的任務需要實現的接口,該接口只有一個方法:
public interface Job {
public void execute(JobExecutionContext context)
throws JobExecutionException;
}
我們可以在里面定義我們的 Job 執行邏輯,比如清除過期數據,更新緩存等。
JobDetail描述了一個任務具體的信息,比如名稱,組名等等。
JobDetail jobDetail = new JobDetail("SayHelloWorldJob", Scheduler.DEFAULT_GROUP, SayHelloWorldJob.class);
在上面的構造方法中,第一個是任務的名稱,第二個是組名,第三個就是實際當任務需要執行的回調類。
Trigger顧名思義就是觸發器,Quartz有個很好的想法就是分離了任務和任務執行的條件。Trigger就是控制任務執行條件的類,當Trigger認為執行條件滿足的時刻,Trigger會通知相關的Job去執行。分離的好處是:
1.你可以為某個Job關聯多個Trigger,其中任何一個條件滿足都可以觸發job執行,這樣可以完成一些組合的高級觸發條件
2.當Trigger失效后(比如:一個永遠都不能滿足的條件),你不必去聲明一個新的job,代替的是你可以為job關聯一個新的Trigger讓job可以繼續執行。
目前的Quartz實現中,存在兩種Trigger,SimpleTrigger和CronTrigger,SimpleTrigger用來完成一些比如固定時間執行的任務,比如:從現在開始1分鐘后等等;而CronTrigger(沒錯,和unix的cron進程的含意一樣)用來執行calendar-like的任務,比如:每周五下午3:00,每月最后一天等等。
在我們項目中,都是一些固定時間的 Job,所以只用到了 SimpleTrigger。
Trigger trigger = new SimpleTrigger("SayHelloWorldJobTrigger",Scheduler.DEFAULT_GROUP,new Date(),null,0,0L);
這個構造方法中,第一個是Trigger的名稱,第二個是Trigger的組名,第三個是任務開始時間,第四個是結束時間,第五個是重復次數(使用SimpleTrigger.REPEAT_INDEFINITELY常量表示無限次),最后一個是重復周期(單位是毫秒),那么這樣就創建了一個立刻并只執行一次的任務。
但我們定義好了 JobDetail,Job,和 Trigger 后,就可以開始 Schedule 一個 Job 了。
scheduler.scheduleJob(jobDetail, trigger);
這條語句就是把job和Trigger關聯,這樣當Trigger認為應該觸發的時候就會調用(實際上是Scheduler調用)job.execute方法了。
scheduler.start();
千萬別忘了加上上面的語句,這條語句通知Quartz使安排的計劃生效。
關于execute方法的參數JobExecutionContext
JobExecutionContext就和很多Context結尾的類功能一樣,提供的運行時刻的上下文環境,JobExecutionContext中有Scheduler,JobDetail,Trigger等很多對象的引用,從而當你在execute方法內部須需要這些對象的時刻提供的便利。
在項目中,我們把需要執行的 Job 相對應的一些信息放在 JobExecutionContext 中,在 Job 執行的時候可以調用。
jobDetail.getJobDataMap().put(userid, id);
在 Job 中,我們可以拿到相關的 Context 信息:
jobExecutionContext.getJobDetail().getJobDataMap().getInt(userid);
JobDetail和Trigger的name和group
Scheduler實例對應了很多job和trigger的實例,為了方便的區分,Quartz使用name和group這兩個特性,正如你想向的一樣,同一個group下不能有兩個相同name的JobDetail,Trigger同理,同一個Scheduler下不能有兩個相同group的JobDetail,Trigger同理,JobDetail和Trigger的完全限定名為:group + name
為了讓服務器重啟以后,我們的 Scheduler 信息仍然不丟失,我們通常采用數據庫持久化 Scheduler 的信息。
DBScript 在 Quartz 的下載包中的:quartz-1.6.0\docs\dbTables 下,選擇自己使用的 DB 相應的 Script 導入數據庫就可以了。
在應用中,我們需要配置一個 quartz.properties 才能正常使用 DB。我們可以在 quartz-1.6.0\examples\example10 中找到該文件的樣例,稍作一些修改,就可以放到自己項目源碼的根目錄下使用了。
設置 org.quartz.jobStore.class = org.quartz.impl.jdbcjobstore.JobStoreTX 即可啟用基于 JDBC 的 Quartz 信息持久化。
根據項目情況設置以下配置信息:
org.quartz.jobStore.class = org.quartz.impl.jdbcjobstore.JobStoreTX
org.quartz.jobStore.driverDelegateClass = org.quartz.impl.jdbcjobstore.StdJDBCDelegate
org.quartz.jobStore.useProperties = false
org.quartz.jobStore.dataSource = myDS
org.quartz.jobStore.tablePrefix = QRTZ_
org.quartz.jobStore.isClustered = false
org.quartz.dataSource.myDS.driver = com.mysql.jdbc.Driver
org.quartz.dataSource.myDS.URL = jdbc:mysql://localhost:3306/myapplication
org.quartz.dataSource.myDS.user = root
org.quartz.dataSource.myDS.password =
org.quartz.dataSource.myDS.maxConnections = 5
但是光設置了 Database 不夠,我們還需要在 Application 啟動的時候自動啟動 Scheduler 才行,我們只需要簡單的寫一個 Servlet 的 Listener 并在 web.xml 中聲明該 Listener ,在 Servlet 容易啟動的時候,Scheduler 就開始自動執行。
public class ScheduleStartListener implements ServletContextListener {
public void contextInitialized(ServletContextEvent servletContextEvent) {
try {
scheduleFactory.getScheduler().start();
} catch (SchedulerException e) {
// write log
}
}
public void contextDestroyed(ServletContextEvent servletContextEvent) {
try {
scheduleFactory.getScheduler().shutdown();
} catch (SchedulerException e) {
// write log
}
}
}
在 web.xml 里面加入以下配置:
<listener>
<listener-class>org.agilejava.scheduler.ScheduleStartListener</listener-class>
</listener>
以上簡單的記錄了在項目中關于 Quartz 的一些應用,如果有什么新的使用心得,會在后面繼續加入的。
posted @
2007-08-02 16:28 steady 閱讀(3559) |
評論 (4) |
編輯 收藏
上一篇中我們說到了,如何使用 HttpClient 抓取所需要的數據,接下來介紹一下如何對這些數據進行處理。基本的處理原理是使用正則表達式進行內容的匹配。
為了便于處理,我們首先把使用 HttpClient 抓取到的數據做一些簡單的處理。
第一步要做的就是刪除回車符,當然我不會寫含有回車符的正則表達式才會這么寫的,當然如果您有更好的方法也可以不用這么做。
代碼很簡單:
1
protected String removeEnter(String response)
{
2
response = StringUtils.replace(response, "\r\n", "");
3
response = StringUtils.replace(response, "\n", "");
4
return response;
5
}
接下來就可以使用正則表達式來對所抓取的內容進行匹配了:
正則表達式是一種可以用于模式匹配和替換的強有力的工具,一個正則表達式就是由普通的字符(例如字符 a 到 z)以及特殊字符(稱為元字符)組成的文字模式,它描述在查找文字主體時待匹配的一個或多個字符串。正則表達式作為一個模板,將某個字符模式與所搜索的字符串進行匹配。正則表達式在字符數據處理中起著非常重要的作用,我們可以用正則表達式完成大部分的數據分析處理工作,如:判斷一個串是否是數字、是否是有效的Email地址,從海量的文字資料中提取有價值的數據等等,如果不使用正則表達式,那么實現的程序可能會很長,并且容易出錯。對這點本人深有體會,面對大量工具書電子檔資料的整理工作,如果不懂得應用正則表達式來處理,那么將是很痛苦的一件事情,反之則將可以輕松地完成,獲得事半功倍的效果。
在這里,我使用了 Jakarta-ORO 作為正則表達式工具來進行匹配。
Jakarta-ORO是最全面以及優化得最好的正則表達式API之一,Jakarta-ORO庫以前叫做OROMatcher,是由Daniel F. Savarese編寫,后來他將其贈與Jakarta Project,讀者可在jakarta.apache.org的網站下載該API包。
因為在這里我們不需要用到太多正則表達式的知識,僅僅是簡單的用用而已,所以幾行簡單的代碼就可以解決問題:

protected String match(String response, String template, int index)
{
Perl5Util engine = new Perl5Util();
String name = null;

if (response != null)
{

if (engine.match(template, response))
{
name = engine.group(index);
}
}
return name;
}
第一個參數 response 表示抓取到的頁面源碼,第二個參數 template 表示我們預先設定的模板,第三個表示第幾個匹配。返回的結果是匹配成功的 group 中的內容。
于是我們可以這樣的調用它:
String template = "/(滬綜指)</font></b></a> <span id=\"STK1\">(\\d{4,5}\\.\\d{1,4})</span>";
String name = match(response, template, 1);
String index = match(response, template, 2);
注意一下,我們正則表達式前后都有 "/"。
另外,我們用() 括起來的部分表示我們要匹配的內容,所以這里 name 可以匹配到 滬綜指,index 可以匹配到大盤的點數。
該匹配對應于: http://web7.jrj.com/homev1/StockIndex.htm
為了防止頁面以后打不開了大家找不到,我把其中相關的匹配部分的頁面源碼也發出來:
<a href=javascript:ShowImg('000001',2) target=_self><b><font color=#000000>滬綜指</font></b></a> <span id="STK1">3914.20</span> <span id="STK2" class="c1"><img src=/HomeV1/images/down.gif width=8 height=8>164.40</span> <a href=javascript:ShowImg('399001',1) target=_self><b><font color=#000000>深成指</font></b></a> <span id="STK3">12882.17</span> <span id="STK4" class="c1"><img src=/HomeV1/images/down.gif width=8 height=8>701.53</span> <a href=javascript:ShowImg('399300',1) target=_self><b><font color=#000000>滬深300</font></b></a> <span id="STK5">3858.52</span> <span id="STK6" class="c1"><img src=/HomeV1/images/down.gif width=8 height=8>181.96</span> <b>香港恒生</b> <span id="STK7">21938.22</span> <span id="STK8" class="c3"><img src=/HomeV1/images/up.gif width=8 height=8>232.66</span> <b>道瓊斯</b> <span id="STK9">13414.48</span> <span id="STK10" class="c1"><img src=/HomeV1/images/down.gif width=8 height=8>13.25</span> <b>納斯達克</b> <span id="STK11">2612.02</span> <span id="STK12" class="c3"><img src=/HomeV1/images/up.gif width=8 height=8>6.67</span>
<div id="indexdata"><object id="STKData" width="0" height="0" classid="CLSID:333C7BC4-460F-11D0-BC04-0080C7055A83" viewastext><param name="FieldDelim" value="F"><param name="DataURL" value="/HomeV1/text/StockIndex.htm"><param name="UseHeader" value="true"></object><input type="hidden" id="STKValue" datasrc="#STKData" datafld="a" name="STKValue"></div>
因為我不是為了介紹正則表達式而寫這篇文章的,所以對正則表達式不會做太多的介紹,如果大家對正則表達式有興趣或想進一步了解的話可以參考:
JAVA中正則表達式的應用
http://www.ibm.com/developerworks/cn/java/l-regp/part1/index.html
http://www.ibm.com/developerworks/cn/java/l-regp/part2/index.html 另外因為為了抓取其他東西,代碼已經被我改的面目全非了,暫時就不方便貼出來了,請大家諒解,如果大家有什么疑問的話可以和我聯系,我會盡量說明清楚的。
posted @
2007-06-28 22:58 steady 閱讀(1784) |
評論 (2) |
編輯 收藏
最近股市大牛,相信這里的不少朋友都在炒股,當然上班時間老是開著網頁看股市或是盯著紅紅綠綠的專業股票軟件是總是擔心被周圍同事看到的,但又不時的想著大盤是漲了還是跌了,自己的股票又是如何呢。
于是用 Java 寫了一套簡單的股市信息跟蹤的小程序,Console 的,用于抓取相應的股市信息并顯示到 console 中,誰也不會想到這個東西會是用來看股市的吧。
這套小小的程序用到了幾個非常簡單的技術,HttpClient 和 正則表達式。程序功能非常簡單,找到含有股市數據的頁面,使用 HttpClient 抓取下來,通過正則表達式匹配自己需要的內容,在 Console 上打印出來。
準備花兩篇文章簡單的介紹這個小系統中的實現細節,當然這只是簡單的介紹,其實我們再稍微用點其他的技術,可以做出更多更實用的小工具。比如我就寫了個小爬蟲,把某個基金網站上的基金凈值數據爬來了,足足有10W條,供我做基金形勢分析之用,拿到這些原始數據,再動用一下自己的頭腦,再配合一些方便的工具,比如 Excel,我們便可以用實際數據去輔助投資理財。
首先我們來簡單的介紹我們用到的第一個工具,HttpClient。
HttpClient 是 Apache Jakarta Common 下的子項目,可以用來提供高效的、最新的、功能豐富的支持 HTTP 協議的客戶端編程工具包,并且它支持 HTTP 協議最新的版本和建議。
以下列出的是 HttpClient 提供的主要的功能,要知道更多詳細的功能可以參見 HttpClient 的主頁。
實現了所有 HTTP 的方法(GET,POST,PUT,HEAD 等)
支持自動轉向
支持 HTTPS 協議
支持代理服務器等
HttpClient 可以在http://jakarta.apache.org/commons/httpclient/downloads.html下載
HttpClient 基本功能的使用
GET 方法
使用 HttpClient 需要以下 6 個步驟:
1. 創建 HttpClient 的實例
2. 創建某種連接方法的實例,在這里是 GetMethod。在 GetMethod 的構造函數中傳入待連接的地址
3. 調用第一步中創建好的實例的 execute 方法來執行第二步中創建好的 method 實例
4. 讀 response
5. 釋放連接。無論執行方法是否成功,都必須釋放連接
6. 對得到后的內容進行處理
根據以上步驟,我們來編寫用GET方法來取得某網頁內容的代碼。
根據這樣的過程,我們便可以寫出一個簡單的抓取頁面的方法,該方法返回抓到的頁面數據。傳入的參數是頁面的 URL。
protected String getURLResponse(String url) {
try {
HttpClient client = new HttpClient();
GetMethod method = new GetMethod(url);
int returnCode = client.executeMethod(method);
String response = null;
if (returnCode == 200) {
response = EncodingUtil.getString(method.getResponseBody(), "gb2312");
}
method.releaseConnection();
return decode(response);
} catch (Exception e) {
return null;
}
}
HttpClient 是一個很實用的工具,用它,我們可以做很多和 Http 有關的事情。
大家可以參考: http://www.ibm.com/developerworks/cn/opensource/os-httpclient/ 來初步了解 HttpClient 的功能。
或是去找找 Jakarta.Commons.Cookbook 或者 Jakarta.Commons.Online.Bookshelf,上面介紹了包括 HttpClient 在內的很多 Apache Jakarta Commons 項目,相信合理使用,會讓你事半功倍的。
下一篇我們將介紹一下如何用正則表達式處理我們抓取到的數據。
posted @
2007-06-21 22:11 steady 閱讀(1918) |
評論 (5) |
編輯 收藏
摘要: Java Platform Debugger Architecture(JPDA:Java平臺調試架構) 由Java虛擬機后端和調試平臺前端組成
1.Java虛擬機提供了Java調試的功能
2.調試平臺通過調試交互協議向Java虛擬機請求服務以對在虛擬機中運行的程序進行調試
閱讀全文
posted @
2007-06-18 16:20 steady 閱讀(818) |
評論 (0) |
編輯 收藏
最近在把在 tomcat 5.5 上開發的項目 deploy 到 JBoss 4.2 上時,在操作一段時間就會出現 java.lang.OutOfMemoryError: PermGen space,開始以為是代碼中存在死循環的地方造成這樣的問題,但是后來發現,出問題的地方都是隨機的,并不是某一處造成這樣的問題出現,懷疑是內存泄露,通過增大 heap 內存的方法來嘗試,依然不行,但是同樣的問題卻并沒有在 tomcat 中出現過,難道是 JBoss 的問題?
在網上做了一番搜索得到一些相關的內容。
PermGen space的全稱是Permanent Generation space,是指內存的永久保存區域OutOfMemoryError: PermGen space從表面上看就是內存益出,解決方法也一定是加大內存。說說為什么會內存益出:這一部分用于存放Class和Meta的信息,Class在被 Load的時候被放入PermGen space區域,它和和存放Instance的Heap區域不同,GC(Garbage Collection)不會在主程序運行期對PermGen space進行清理,所以如果你的APP會LOAD很多CLASS的話,就很可能出現PermGen space錯誤。這種錯誤常見在web服務器對JSP進行pre compile的時候。
改正方法,在 run.bat 中加入:-Xms256m -Xmx512m -XX:MaxNewSize=256m -XX:MaxPermSize=256m
因為項目中引用了很多的 jar 包,而這些 jar 包中的 class 信息會被 JBoss 的 class loader 加載到 PermGen space 區域,在 JVM 默認的情況下,該部分空間的大小只有 4M,在 jar 包非常多的情況下,顯然是不夠用的,所以通過 -XX:MaxPermSize=256m 指定最大值后即可解決問題。
另外,如果 heap 內存不足出現 java.lang.OutOfMemoryError: Java heap space 時,可以通過 -Xmx512m 指定最大 heap 內存來解決這樣的問題。
posted @
2007-06-17 20:13 steady 閱讀(16778) |
評論 (7) |
編輯 收藏
JBoss 4.2 GA 已經發布有一段時間了,主要還是一些 bug fix 已經一些新的包的加入。感覺比較爽的是解決了過去不太好用的一些地方。
過去在用 JBoss 4.0.5 的時候一直被 Log 的問題困擾,如果在自己的項目里加入 log4j 和 common logging 的話,必然會出錯,所以我們不得以,必須通過一些調整手段來處理這樣的問題,也就是每次在 tomcat 下調試的應用,需要改點東西才能 deploy 到 JBoss 上去,但使用了 4.2 以后就沒有這樣的問題了,在 tomcat 下用的包直接放過去,沒有做任何的修改就可以正常使用了。
因為我項目用的是 commons-lang 2.3 而 JBoss 4.0.5 用的是 2.1 每次使用 commons-lang 2.1 里面沒有的方法時,就會出現 NoSuchMethodException,最后只好把 JBoss 下所有的 commons-lang 的包用 2.3 的替換掉,而 4.2 已經沒有這個問題了,2.3 已經可以正常使用了。
默認的 JBoss 4.2 我只能用 localhost 訪問,不能用 IP 地址訪問,后來發現,需要修改 jboss-4.2.0.GA\server\default\deploy\jboss-web.deployer\server.xml 把 Connector 下面的 address 改成對應的 IP 或者 0.0.0.0 就可以用 IP 訪問了。
后面附上了 Release Note 中的一些內容。
This is the final release of JBoss Application Server v4.2.0. JBoss AS 4.2 is a stepping stone from JBoss 4.0 to JBoss 5.0. It combines a lot (but not all) of the exciting new features of JBoss 5, but based on the stable 4.x MicroKernel architecture.
Highlights
* JDK5 is *required* to run JBossAS 4.2.x. The decision was based on the fact that JDK1.4 is phased out and the reality that a lot of people like Java Annotations support and want to combine EJB3 and JBoss Seam components with JBossAS. JDK6 is not formally supported yet, although you may be able to start the server with it. JDK6 support will come with JBossAS 5.x.
* JBoss EJB3 is now deployed *by default* in JBossAS 4.2.x The fact that we base on JDK5 makes our life easier in this regard, meaning we don't have to maintain jdk5 code retro-weaved for jdk1.4 runtimes, and we can include by default components that require jdk5 to run.
* JBoss Web v2.x is the web container in JBossAS 4.2, an implementation based on Apache Tomcat that includes the Apache Portable Runtime (APR) and Tomcat native technologies to achieve scalability and performance characteristics that match and exceed the Apache Http server. In the absence of the native libraries in the JBoss classpath, JBoss Web falls back to the standard non-native connector mode. The native libraries need to be downloaded and installed separately.
* JBoss Transactions v4.2 is the default transaction manager for JBossAS 4.2. JBoss Transactions is founded on industry proven technology and 18 year history as a leader in distributed transactions, and is one of the most interoperable implementations available. The JTA version of JBoss Transactions included with the server provides for fully recoverable transactions. For distributed transaction support the JTS version of JBoss Transactions will need to be used. Furthermore, it is always possible to fall back to the legacy JBossTM fast in-memory transaction manager implementation, if necessary.
* JBossWS is the web services stack for JBoss 4.2 providing Java EE compatible web services. It has been upgraded to v1.2.1.GA
* JGroups/JBossCache were upgraded to the latest releases. The server is already configured to support channel multiplexing, when it becomes available.
* JBoss Remoting was upgraded to the latest stable 2.2.x version. This was done in order to align dependencies with the thirdparty libraries required by the new JBoss Messaging, which means that, if you want, you can replace the default JBossMQ messaging provider with JBoss Messaging, without having to revert to a scoped deployment.
posted @
2007-06-07 10:09 steady 閱讀(2741) |
評論 (1) |
編輯 收藏
新的一年開始,按理說要對去年的什么東西做一番總結了,當然總結很多了,這次先總結一下 JSF 了,畢竟這對我來說是今年最主要的技術方向,對它也算是比較熟悉了,雖然沒有非常深入的去研究它,但從一年多的使用和理解來說,還是有不少自己的心得的,在新的一年到來之際,把這些東西記錄下來,重新記起這個讓我歡喜讓我憂的 JSF。靜觀這一年 JSF 的發展,沒有太多的興奮,也沒有太多的歡喜,更多的是平靜,與同一時間大紅大紫的 Ajax 和 RoR 相比,JSF 帶給我們的更多是平靜,靜的讓人心里發慌,上半年可以說還是稍有一些波濤了,而隨著月份的數字越來越大,波濤是越來越小了。
可以說各大廠商在互相妥協讓步的基礎之上,把 JSF 實用化的實現版本的重任交到了 Apache Myfaces 項目上,而 Oracle 也將其 ADF Faces 的實現捐給了 Apache,而現在我們可以見到的 JSF 實現也主要就是 Myfaces 了,當然 Sun 自己也有一套實現,當然這只是一種不夠健壯,并且功能有限的實現版本,一般不會拿來做正式的項目的。剛過完年 Myfaces 1.1.2 和 Tomahawk 1.1.2 正式發布,這是過去 Myfaces 1.1.1 的一個 bug 修復版本,離上一個版本已經有半年左右的時間了,而項目組的同事們也在與 Myfaces 1.1.1 的 bug 斗爭了半年才用到這個新的版本。隨后的 Myfaces Core 1.1.3 / 1.1.4 則在幾乎一個月內發布,而 1.1.5 和 Tomahawk 1.1.4 則至今沒有動靜,雖然由 Myfaces 每次發布帶給我們的 new feature 已經不是那么的多了,但是還是期盼新的版本能夠給我們帶來新的驚喜。
五月份的時候 JavaEE 5 最終標準發布了,JSF 1.2 終于被正式提上了日程,這是一個對過去標準的一個修復版本,修正了上一個標準中的諸多問題,比如 JSTL 兼容性問題,還有一些細節性的改動,都是過去在 JSF 1.1 標準中非常折磨人的問題,但新的 1.2 標準依賴于 JDK 1.5,依賴于一系列新的 JavaEE 5 的 API,比如 Servlet 2.5, JSTL 1.2 而這些新的 API 也是在緊鑼密鼓的開發中,所以 Myfaces 1.2 的開發進程也一直很慢,因為其中出現的問題不光是 Myfaces 自己的問題,或許還有 Tomcat 6 的問題,或是其他的問題。而另一方面 Sun 也發布了一個 JSF 1.2 的實現版本,是由 JSF 1.2 的標準的主筆領導開發的,按照我對于 Sun JSF 上個版本的表現,我對于這個新的實現也不抱有太多的希望,或許它更多的只是一種象征了,象征著 JSF 1.2 的正式推出。
開源領域的 JSF 相關的項目發展緩慢。Myfaces 在一年內沒有給我們帶來太多的驚喜。曾經做為黑馬出現的 JSF 擴展框架 Shale 至今還沒有給大家帶來一個滿意的答復,一直以 develop 版本發布出來給大家嘗鮮用,雖然慢慢的在前進,但是卻很難帶給大家什么驚喜,或許會被人逐漸的淡忘。而去年年底由 Oracle 捐給 Apache 的 ADF Faces 也是至今沒有太大的動靜,同樣作為兄弟項目的 Struts 2 從提出到現在也有一年了,還沒有能提供一個正式的版本給我們用,作為 Apache 的項目,這樣的發布速度,確實很讓人不能滿意,而作為另一個大型的開源組織 Eclipse,則在一個個 Milestone 下有條不紊的向前推進,不斷蠶食著別人所占據的地盤。
作為 JSF 整體應用平臺一個重要的部分,第三方組件庫的發展有不小的突破,但是真正的應用度似乎不是很高,這一年內出現了很多優秀的商業,開源的組件庫,除去上面我們提到的 Myfaces Tomahawk, Oracle ADF 之外,還出現了 ICEFaces, BackBase,WebGalileo Faces,另外在 .Net 領域的組件提供商 Infragistics 也通過收購發布了 NetAdvantage for JSF 2006 這樣的組件庫。另外一直在 JSF IDE 上有所作為的 Exadel 公司也在 JSF 組件上插上一手,一方面發布了其開源的 JSF 框架 Ajax4JSF 另一方面在其基礎上提供了一個商業的 JSF 組件庫 VCP,這樣的方式確實有一套,可以同時抓住兩方面的市場。另一方面國內也出現了像金碟這樣基于自己 Apusic Application Server 的開源 JSF 組件庫,是一件值得我們國人驕傲的事情,不過由于其只能夠運行于 Apusic 上,使其應用面受到了不小的限制。
讓我們再來看看這一年 JSF 相關 IDE 在今年的作為了,在 06 年春節期間,一些支持 JSF 的 IDE 像趕集一樣不斷的推出來,先后有 MyEclipse 4.1 GA,Sun Java Studio Creator 2, Oracle JDeveloper, BEA Workshop Studio 3.0,在這一段時間推出。MyEclipse 和 BEA Workshop 是 Eclipse 的插件,而 JDeveloper 和 Creator 是基于 Swing 的,不過隨著時間的推移,大家真正在用的 JSF 開發工具也主要就是 MyEclipse 和 Workshop,不過 MyEclipse 在 JSF 上想和 Workshop 拼,還需要一些時日了,另外在九月份正式發布的 IntelliJ IDEA 6.0 也開始支持 JSF 了,當然是用其獨特的方式去支持,雖然不提供圖形化的所見即所得的開發方式,但由于其 IDE 內部各個部分間完美的組合,使得其在寫代碼的感覺上要遠遠超過的其他競爭者,這也正是獨立 IDE 和插件 IDE 一個重要的功能區別。
縱觀 06 年的 JSF 的發展歷程,我還是對 07 年的 JSF 的發展很期待,希望 Myfaces 基于 JSF 1.2 的實現能夠盡快的推出,也能夠有更多更好的開源組件庫的出現。
posted @
2007-01-05 09:22 steady 閱讀(2220) |
評論 (6) |
編輯 收藏