隨筆 - 170  文章 - 536  trackbacks - 0
          <2025年8月>
          272829303112
          3456789
          10111213141516
          17181920212223
          24252627282930
          31123456

          常用鏈接

          我參與的團(tuán)隊(duì)

          隨筆分類(103)

          搜索

          •  

          積分與排名

          • 積分 - 415488
          • 排名 - 135

          最新評(píng)論

          閱讀排行榜

            第一次用 Zoundry 客戶端工具來發(fā)布博客,WordPress 還是不錯(cuò)的博客了,提供了 XML-RPC 方式的遠(yuǎn)程提交接口,我們可以比較容易的把我們的博客發(fā)布到 WordPress 上。

            老外對(duì)這方面的支持工作還是做的不錯(cuò)的,國內(nèi)的同類系統(tǒng)往往只考慮到功能,好一點(diǎn)的考慮到性能,而在這些新技術(shù)帶來的擴(kuò)展性的增強(qiáng)上似乎沒有太多的理解,雖然 WordPress 在功能上和國內(nèi)的很多博客有一定的差距,但是人家支持插件,這樣就可以讓地球人都上來擴(kuò)展一把。Eclipse 的插件風(fēng)風(fēng)火火的做了幾年,現(xiàn)在人似乎沒有不用插件開發(fā)的了。

            老外在 Web 2.0 中又很多好的思想,技術(shù),拿到國內(nèi)來就有點(diǎn)變味了,雖說國人在 Web 2.0 技術(shù)上跟進(jìn)的速度還是相當(dāng)?shù)目欤贿^思想還是又相當(dāng)?shù)牟罹嗟摹?/p>

            要好好學(xué)學(xué)人家做東西的思想,而不僅僅是技術(shù)。

          posted @ 2008-01-04 16:42 steady 閱讀(1005) | 評(píng)論 (0)編輯 收藏

          該文章被發(fā)布在我的新博客中:http://4think.cn/blog/index.php/archives/25

            市面上這么多的IM工具,每次打開的時(shí)候就要開上一堆,還不時(shí)的有個(gè)新的IM工具出來,加上一兩個(gè)及其有吸引力的功能,然后又不得不裝上,搞的每次開機(jī)以后總是要開上一大堆的IM,比如QQ啦,MSN啦,還有Yahoo,Google Talk,飛信,Skype,真的挺麻煩的。

            一年前的時(shí)候,突然聽說 Yahoo 可以和 MSN 互通了,于是從此就沒用過 MSN 了,也是對(duì) Microsoft 歧視國內(nèi)用戶的一種不滿吧,這么多IM工具,最不穩(wěn)定的也最為常用的要屬 MSN 了,雖然飛信這樣“國”字號(hào)的軟件似乎更加的不爭氣,就原諒他吧,誰叫他是咱最有錢的移動(dòng)運(yùn)營商呢。可以說,MSN 的掉線率是相當(dāng)?shù)母撸卿浰俣纫彩求@人的,在公司內(nèi)部傳文字的效率呢更加不用說了,反正沒有人走的快。不過據(jù)我們?nèi)ミ^美國的一些同事說,MSN 在美國速度是非常快的,包括其下屬的 hotmail,MSN Space,怪不得這么被推崇了,不過沒辦法,畢竟是在國內(nèi),屬于不被重視的使用群體,大不了就不用了,于是機(jī)子里再也沒有出現(xiàn)過 MSN,所有重要的好友都加到 Yahoo 里了。

            其實(shí)說來 Yahoo 也是個(gè)比較不爭氣的東西,功能嘛,沒啥強(qiáng)的,不過吃內(nèi)存的能力還挺強(qiáng),印象中也就 Skype 可以和他有的一拼,不過好歹人家 Yahoo 還是比較重視中文用戶的,起碼光纜斷的時(shí)候還是能用的,而且相關(guān)的本地化服務(wù)也還是有一定的可用性的,Yahoo的郵件提示是最為迅速的,基本上是新郵件來到5秒之內(nèi)就得讓你知道,這個(gè)功能還是挺體貼用戶的,其實(shí)我的一些 IM 的一個(gè)重要作用就是 check email,比如說 Google Talk。Yahoo 的客戶端程序其實(shí)是比較不穩(wěn)定的,群聊功能是個(gè)殺手,一次領(lǐng)導(dǎo)通知事情,讓大家開個(gè)會(huì),結(jié)果一位老兄圖方便,Yahoo 把大家全部加進(jìn)來了,大家的機(jī)器全部死翹翹,只好 reset 重啟,自此以后,這個(gè)功能再也不敢使用了,Yahoo 工具箱里有個(gè)看股市行情的插件,不過這個(gè)曲線也太不本地化了,中午休息的時(shí)間也畫在上面,一條長長的直線,怎看都別扭。沒辦法啊,公司里唯一允許的 IM 工具,不得不裝,也就不得不去忍受這些了。

            Google Talk 其實(shí)是我用的最多的,極為簡潔,擁有我需要的主要功能,email 通知,語音,文本聊天,傳文件(大家都喜歡裝中文版的,沒這個(gè)功能,所以也基本找不到人傳文件),其實(shí)還有一點(diǎn)重要的就是所有聊天記錄都會(huì)保存在 Gmail 里,在哪都不會(huì)丟失,也很連貫,這對(duì)于我們經(jīng)常討論需求的人就不會(huì)有上句沒下句的了。也不用擔(dān)心聊天記錄留在本地泄密。另外還有一點(diǎn),傳代碼的時(shí)候絕對(duì)不會(huì)變成一堆笑臉什么的。Google Talk 其實(shí)功能上是相當(dāng)有限的,但是我卻非常喜歡,簡潔就是美了。

            下面隆重出場的是唯利是圖、忘恩負(fù)義外加極端不安全的 QQ 了,如果不是這么多好友在里面,我是不會(huì)開 QQ 的,當(dāng)然 QQ 作為國內(nèi)用的最多的 IM 工具(其實(shí)叫他聊天工具更確切),QQ 還是有相當(dāng)多的優(yōu)勢的,首先網(wǎng)絡(luò)穩(wěn)定性好,傳文件速度快,有遠(yuǎn)程協(xié)助功能,語音質(zhì)量也不錯(cuò),可以看 IP(還不都是珊瑚蟲的功勞,被忘恩負(fù)義的騰訊扼殺了),有群聊功能,也是最適合某些夜晚不甘寂寞的人尋找刺激的工具了,其他的功能我是不大能想到的了,更不用說去用了,所以嘛,QQ 對(duì)我來說,太大了,太花哨了,對(duì)公司來說也是的,基本上正規(guī)的公司,沒有哪個(gè)不封 QQ 的,所以嘛,QQ 只能被遠(yuǎn)遠(yuǎn)的拒之于企業(yè)應(yīng)用的門外,騰訊的 RTX 也就不是那么容易進(jìn)入企業(yè)市場的,誰讓你這么花哨,看了就不想好好工作了。

            Skype 這個(gè)東西嘛,對(duì)我用處不大,自從充值卡被封事件以后就不再常開了,開會(huì)的時(shí)候才會(huì)去用,畢竟多人語音聊天功能還是挺不錯(cuò)的。

            國外的大部分 IM 工具都開放互通了,包括 MSN 和 Yahoo,Google Talk 也在和 MS 談互通的問題,國內(nèi)的 IM 互通嘛,似乎完全不可能,國外那幾家都不是靠 IM 吃飯的,騰訊就不一樣了,如果不保持其 QQ 的占有率,瘋狂的扼殺非“官方”的客戶端,LumaQQ 這么優(yōu)秀的跨平臺(tái)解決方案也就被騰訊自己和諧掉了,最近對(duì)珊瑚蟲下狠手也表示其在此方面的決心,呵呵,我的 QQ 從此不升級(jí)了。

          posted @ 2008-01-02 11:27 steady 閱讀(2048) | 評(píng)論 (4)編輯 收藏

          每個(gè)人在開發(fā)的時(shí)候,都會(huì)根據(jù)自己的喜好選擇一些好用的工具,當(dāng)然,通過一些年頭的積累,我自己也有了這么一些順手的工具,就把這些還不錯(cuò)的東西拿出來和大家分享吧。

          CyberArticle (網(wǎng)文快捕)

            我們在查看資料,或者遇到問題上網(wǎng)搜索的時(shí)候,經(jīng)常會(huì)想把自己看到的一些好東西保存下來,以后需要用的時(shí)候可以找到,有人把東西復(fù)制下來保存成文本,有人用 Word 文檔,也有人直接保存頁面,這些方法固然是可以,不過以后找起來可就比較麻煩了。我們需要一個(gè)帶分類的文檔管理工具。

            在對(duì)一堆工具的篩選之后,我選中了 CyberArticle,也就是網(wǎng)文快捕,安裝以后,在瀏覽頁面時(shí),IE 和 FF 的右鍵會(huì)出現(xiàn)保存全文,保存選中部分這樣的選項(xiàng),我最喜歡的是保存選中部分這個(gè)功能,畢竟我們并不需要一個(gè)網(wǎng)頁中一些不相關(guān)的文字和圖片。CyberArticle 可以完整的把文章內(nèi)容或選中部分的內(nèi)容保存下來,無論是圖片或者其他什么的,都能較好的支持。在保存下自己喜歡的內(nèi)容后,我們可以手工把這些內(nèi)容分類,以后會(huì)比較容易的找到自己需要的東西。

            另外 CyberArticle 中比較有用的功能是生成電子書。我們在網(wǎng)上搜集到一堆某一類別的文章,為了與他人分享或者便于攜帶,我們可以把這一個(gè)獨(dú)立的類別的內(nèi)容導(dǎo)出成 CHM 或 EXE 版本的電子書。

            CyberArticle 可以到 http://www.wizissoft.com/cn/index.aspx 下載,強(qiáng)烈建議使用最新的 5.0 版(只要25塊錢),舊的版本會(huì)有相當(dāng)一部分的文章保存不下來。


          鏈客中國,寫文章也可以賺錢哦
          posted @ 2007-11-29 10:59 steady 閱讀(2101) | 評(píng)論 (11)編輯 收藏
              昨天看到新聞,IBM 在其網(wǎng)站上放出了 Lotus Symphony 的 beta 版,看上去有點(diǎn) Office2007 的一套辦公產(chǎn)品,最重要的是它是基于 Eclipse-RCP 平臺(tái)的,如果說 IBM 讓 Lotus 去做一個(gè)標(biāo)準(zhǔn)的 Windows 應(yīng)用像 Office2007 到?jīng)]有什么奇怪的,關(guān)鍵在于它是 Eclipse 平臺(tái)的,IBM 在一個(gè)強(qiáng)大的 Eclipse 平臺(tái)上,構(gòu)建出了一個(gè)向 Microsoft 最核心產(chǎn)品叫板的應(yīng)用,這大大的壯大了 Java 愛好者的威風(fēng)。

              過去我們 Swing / SWT 做的東西似乎很難有直接面向普通用戶的優(yōu)秀的應(yīng)用,這次 IBM 是代 Java 出了重重的一拳,Eclipse 平臺(tái)不但是與 Microsoft 的 Visual Studio 叫板,甚至可以和 Office 叫板了。

              從另一方面來說,從 Lotus Symphony 的推出,IBM 進(jìn)一步亮相了 Eclipse RCP 的高級(jí) UI 組件,傳統(tǒng)的 Eclipse 開發(fā)出的東西,千篇一律,沒有太大的界面差別,但是 Lotus Symphony 上卻不太容易讓人聯(lián)想到 Eclipse,除了看到啟動(dòng)畫面上 build on eclipse 的只有,還有一些熟悉的菜單項(xiàng),和 PlugIn 相關(guān)的內(nèi)容才會(huì)發(fā)現(xiàn),哇,這個(gè)酷酷的應(yīng)用原來是 Eclipse 平臺(tái)上的產(chǎn)品。

              當(dāng)然 Lotus Symphony 并沒有說是開源的,這些新的,酷酷的 UI 組件也并沒有向開源社區(qū)開放,按照 IBM 最近幾年的慣例,遲早是要捐出來的,但前提是先做幾套東西,賣點(diǎn)錢再說,Eclipse WTP 的很多東西來源于 WSAD,很多 Eclipse 的插件也是來源于 Rational 的產(chǎn)品,只是 IBM 覺得沒有什么商業(yè)價(jià)值了,才捐出來。

              其實(shí)我是非常希望 IBM 能盡快和大家分享 Lotus Symphony 的成功經(jīng)驗(yàn),也希望更多的 Eclipse 愛好者能夠開發(fā)出更多強(qiáng)大的應(yīng)用,特別是桌面級(jí)應(yīng)用,讓更多的人看到,Java 在成長,在進(jìn)取。


          ---------------------------------------------------
          順便做個(gè)小廣告 鏈客中國 www.linkedcast.cn 上線運(yùn)行,歡迎廣大 Blogger 使用

          鏈客中國,寫文章也可以賺錢哦
          posted @ 2007-09-23 08:40 steady 閱讀(1145) | 評(píng)論 (8)編輯 收藏
          Java Web 應(yīng)用似乎總有這樣的情況,有事沒事總是要在 URL 后面加上個(gè) jsessionid,而且似乎不能使用配置的方式直接禁用 URL 傳遞 sessionid,這樣,就比較容易造成安全性的問題,或者在瀏覽器地址欄里留下一堆很不好看的地址,在 Struts2 中,使用了 url 標(biāo)簽的所有鏈接,甚至 CSS, JS 這樣的東西,都會(huì)加上 jsessionid,如何去禁用呢,搜索國內(nèi)的相關(guān)文章,無功而返,詢問我們過去的架構(gòu)師,也沒有做過,只好想辦法去找國外的網(wǎng)站,找到了這樣的一篇文章。

          http://randomcoder.com/articles/jsessionid-considered-harmful

          通過加入 Filter 的方式過濾掉 URL 中包含的 jsessionid,再重新包裝 Response 返回給瀏覽器。

          因?yàn)闆]有太多東西,就不多解釋了,大家拿了用就可以了。

          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() {
              }

          -------------------------------------------------------------------------------------------------
          順便做個(gè)小廣告 鏈客中國 www.linkedcast.cn 上線運(yùn)行,歡迎廣大 Blogger 使用

          鏈客中國,寫文章也可以賺錢哦
          posted @ 2007-09-08 20:13 steady 閱讀(5691) | 評(píng)論 (4)編輯 收藏
          在過去使用 Spring 整合 Hibernate 的時(shí)候,都是用這樣的配置方式。

          <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>

          每當(dāng)需要加入一個(gè)新的 VO 時(shí),我需要過來修改配置文件,來引入對(duì)新的 VO 的支持。

          現(xiàn)在我使用的時(shí)候,是這么配的:
          <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>

          做項(xiàng)目開發(fā)的時(shí)候,就再也沒有改過配置。
          posted @ 2007-08-17 13:58 steady 閱讀(1944) | 評(píng)論 (5)編輯 收藏
          因?yàn)橛幸粋€(gè) Struts2 網(wǎng)站發(fā)布,需要整合一個(gè)論壇來使用,公司的一個(gè)項(xiàng)目過去曾經(jīng)整合過一個(gè)英文論壇,但似乎不能滿足我們的需求,需要找一個(gè)成熟穩(wěn)定的中文論壇,與我們的系統(tǒng)結(jié)合。

          最終選擇了 Discuz 作為我們的論壇系統(tǒng),主要是因?yàn)樗峁┝艘惶卓捎玫?Passport API,來直接與我們現(xiàn)有系統(tǒng)進(jìn)行整合。

          下面摘錄 Discuz 文檔中的內(nèi)容來說明整合原理,隨后的幾篇中,將詳細(xì)描述具體的整合過程。

          假設(shè)已設(shè)置如下變量或參數(shù)

          • 掛接 Discuz! Passport 的應(yīng)用程序假設(shè)為一套 PHP 語言編寫的 CMS 系統(tǒng)
          • Discuz! 的 URL 為 http://www.myforums.com
          • 應(yīng)用程序的 URL 為 http://www.mywebsite.com
          • 應(yīng)用程序的注冊頁面為 http://www.mywebsite.com/register.php
          • 應(yīng)用程序的登錄頁面為 http://www.mywebsite.com/login.php?action=login
          • 應(yīng)用程序的退出頁面為 http://www.mywebsite.com/login.php?action=logout

          開啟通行證后的用戶登錄流程

          • 如果用戶在論壇點(diǎn)擊“登錄”,則轉(zhuǎn)向到事先設(shè)置好的應(yīng)用程序登錄頁面(http://www.mywebsite.com/login.php?action=login),并在登錄頁面的 URL 中加入?yún)?shù) forward(加入 forward 后的鏈接例如 http://www.mywebsite.com/login.php?action=login&forward=http://www.myforums.com/index.php),用于在登錄后將用戶導(dǎo)向到指定的 URL。

          • 應(yīng)用程序收到此請求后,按照慣例生成表單,并增加一個(gè)表單變量,將 GET 方式傳遞過來的 forward 參數(shù)通過表單進(jìn)行傳遞。

          • 用戶在應(yīng)用程序的表單中填寫登錄信息,并提交到應(yīng)用程序的登錄驗(yàn)證程序。應(yīng)用程序驗(yàn)證用戶提交的用戶名和密碼的合法性:

            • 如果不通過:提示用戶名密碼錯(cuò)誤,要求其返回上一頁重新填寫。

            • 如果通過,需要進(jìn)行如下操作:

              • 設(shè)置自身 Cookie 或 Session,使得應(yīng)用程序自身處于登錄狀態(tài)。

              • 檢查表單中是否提交了 forward 變量,如有,則意味著登錄請求可能是由論壇而來,將此變量傳遞到后面的請求中。如沒有,自行生成 forward 變量,使得論壇登錄后能夠跳轉(zhuǎn)回到應(yīng)用程序中。

              • 通過 header('Location: http://www.myforums.com/api/passport.php?action=login&auth=xxx&forward=http://yyy&verify=zzz') 的方式,將登錄請求傳遞到論壇進(jìn)行處理。其中 auth 用來將用戶信息與資料以特定的格式,加密傳遞給論壇,forward 用于告知論壇 Passport API 完成自身操作后轉(zhuǎn)向到的 URL 地址,verify 用于驗(yàn)證前面兩個(gè)變量的有效性。auth、forward、verify 格式與結(jié)構(gòu)將在后面進(jìn)行說明。


          • Discuz! Passport API 在接收到由應(yīng)用程序通過 header() 提交過來的請求后,進(jìn)行如下操作:

            • 根據(jù) verify 判斷 auth 和 forward 變量是否合法,如合法則繼續(xù),否則終止。

            • 將 auth 根據(jù)既定算法解密,并還原成數(shù)組,數(shù)組的內(nèi)容與格式將在后面進(jìn)行說明。根據(jù)數(shù)組中的內(nèi)容,檢查此用戶是否存在。如存在,則根據(jù)上述數(shù)組中的內(nèi)容 UPDATE 論壇中相應(yīng)的用戶資料。如不存在,則使用數(shù)組中的信息 INSERT 到論壇用戶資料表中。

            • 論壇設(shè)置 Cookie 或 Session,使得論壇自身處于登錄狀態(tài)。

            • 根據(jù)應(yīng)用程序反饋的 forward 值,通過 header('Location: http://xxx') 的形式將頁面跳轉(zhuǎn)到 forward 變量指定的 URL。


          • 至此,登錄流程結(jié)束

          開啟通行證后的用戶退出流程

          • 如果用戶在論壇點(diǎn)擊“退出”,則轉(zhuǎn)向到事先設(shè)置好的應(yīng)用程序退出頁面(http://www.mywebsite.com/login.php?action=logout),并在登錄頁面的 URL 中加入?yún)?shù) forward(例如 http://www.mywebsite.com/login.php?action=login&forward=http://www.myforums.com/index.php),用于在退出后將用戶導(dǎo)向到指定的 URL。

          • 應(yīng)用程序收到此請求后,清除自身 Cookie 或 Session,使得應(yīng)用程序自身處于非登錄狀態(tài)。

          • 檢查是否提交了 forward 變量,如有,則意味著登錄請求可能是由論壇而來,將此變量傳遞到后面的請求中。如沒有,自行生成 forward 變量,使得論壇登錄后能夠跳轉(zhuǎn)回到應(yīng)用程序中

          • 通過 header('Location: http://www.myforums.com/api/passport.php?action=logout&forward=http://yyy&verify=zzz') 的方式,將退出請求傳遞到論壇進(jìn)行處理。其中 forward 用于告知論壇 Passport API 完成自身操作后轉(zhuǎn)向到的 URL 地址,verify 用于驗(yàn)證 forward 變量的有效性。forward、verify 格式與結(jié)構(gòu)將在后面進(jìn)行說明

          • Discuz! Passport API 在接收到由應(yīng)用程序通過 header() 提交過來的請求后,進(jìn)行如下操作:

            • 根據(jù) verify 判斷 forward 變量是否合法,如合法則繼續(xù),否則終止。

            • 清楚論壇的 Cookie 或 Session,使得論壇自身處于非登錄狀態(tài)。

            • 根據(jù)應(yīng)用程序反饋的 forward 值,通過 header('Location: http://xxx') 的形式將頁面跳轉(zhuǎn)到 forward 變量指定的 URL。


          • 至此,退出流程結(jié)束。

          開啟通行證后的用戶注冊流程

          • 如果用戶在論壇點(diǎn)擊“注冊”,則轉(zhuǎn)向到事先設(shè)置好的應(yīng)用程序注冊頁面(http://www.mywebsite.com/register.php),并在注冊頁面的 URL 中加入?yún)?shù) forward(例如 http://www.mywebsite.com/register.php?forward=http://www.myforums.com/index.php),用于在注冊后將用戶導(dǎo)向到指定的 URL

          • 應(yīng)用程序收到此請求后,按照慣例生成表單,并增加一個(gè)表單變量,將 GET 方式傳遞過來的 forward 參數(shù)通過表單進(jìn)行傳遞

          • 用戶在應(yīng)用程序的表單中填寫注冊信息,并提交到應(yīng)用程序的注冊驗(yàn)證程序。應(yīng)用程序驗(yàn)證用戶提交信息的完整性和合法性:

            • 如果不通過:提示其問題所在,要求其返回上一頁重新填寫

            • 如果通過,需要進(jìn)行如下操作:

              • 將用戶資料插入到應(yīng)用程序自身用戶數(shù)據(jù)庫中

              • 設(shè)置自身 Cookie 或 Session,使得應(yīng)用程序自身處于登錄狀態(tài)

              • 檢查表單中是否提交了 forward 變量,如有,則意味著注冊請求可能是由論壇而來,將此變量傳遞到后面的請求中。如沒有,自行生成 forward 變量,使得論壇注冊后能夠跳轉(zhuǎn)回到應(yīng)用程序中

              • 通過 header('Location: http://www.myforums.com/api/passport.php?action=login&auth=xxx&forward=http://yyy&verify=zzz') 的方式,將注冊請求傳遞到論壇進(jìn)行處理。其中 auth 用來將用戶信息與資料以特定的格式,加密傳遞給論壇,forward 用于告知論壇 Passport API 完成自身操作后轉(zhuǎn)向到的 URL 地址,verify 用于驗(yàn)證前面兩個(gè)變量的有效性。auth、forward、verify 格式與結(jié)構(gòu)將在后面進(jìn)行說明


          • Discuz! Passport API 在接收到由應(yīng)用程序通過 header() 提交過來的請求后,進(jìn)行如下操作:

            • 根據(jù) verify 判斷 auth 和 forward 變量是否合法,如合法則繼續(xù),否則終止

            • 將 auth 根據(jù)既定算法解密,并還原成數(shù)組,數(shù)組的內(nèi)容與格式將在后面進(jìn)行說明。根據(jù)數(shù)組中的內(nèi)容,檢查此用戶是否存在。如存在,則根據(jù)上述數(shù)組中的內(nèi)容 UPDATE 論壇中相應(yīng)的用戶資料。如不存在,則使用數(shù)組中的信息 INSERT 到論壇用戶資料表中

            • 論壇設(shè)置 Cookie 或 Session,使得論壇自身處于登錄狀態(tài)

            • 根據(jù)應(yīng)用程序反饋的 forward 值,通過 header('Location: http://xxx') 的形式將頁面跳轉(zhuǎn)到 forward 變量指定的 URL


          • 至此,注冊流程結(jié)束

            本部分中,加下劃線顯示的部分,是需要對(duì)您的應(yīng)用程序進(jìn)行更改的部分,事實(shí)上,這部分更改會(huì)非常容易和方便。

          posted @ 2007-08-11 17:30 steady 閱讀(3300) | 評(píng)論 (3)編輯 收藏

          Reschedule
          rescheduleJob(String triggerName, String groupName, Trigger newTrigger)

          在進(jìn)行 reschedule 操作的時(shí)候,我們通常只需要修改 Trigger 的時(shí)間,這時(shí)候我們只需要重新 new 一個(gè)含有新的 Schedule 時(shí)間的 Trigger 對(duì)象,reschedule 一下就可以了。

          Unschedule
          unscheduleJob(String triggerName, String groupName)

          進(jìn)行 unschedule 的時(shí)候,我們只需要知道名字和 group 就可以了。

          進(jìn)行 Schedule 操作前后,Database 中的相關(guān)數(shù)據(jù)都會(huì)被更改,在執(zhí)行 unschedule 或者該 schedule 已經(jīng)執(zhí)行過,數(shù)據(jù)庫中的 trigger 信息都會(huì)被刪除。

          posted @ 2007-08-03 09:00 steady 閱讀(1684) | 評(píng)論 (4)編輯 收藏

          Quartz 是一個(gè)強(qiáng)大的企業(yè)級(jí) Schedule 工具,也是目前最好的開源 Schedule 工具,最近因?yàn)轫?xiàng)目的需要,簡單的用到了 Quartz 的一些功能,對(duì)項(xiàng)目中使用 Quartz 的一些問題做簡單的記錄。

          在 Quartz 的應(yīng)用中,我們用到了以下的一些東西,ScheduleFactory, Scheduler, Job, JobDetail, Trigger,簡單說明一下他們的用途。

          SchedulerFactory 是 Scheduler 的工廠,我們可以從中獲得受工廠管理的 Scheduler 對(duì)象。

          SchedulerFactory scheduleFactory = new StdSchedulerFactory();
          Scheduler scheduler = scheduleFactory.getScheduler();

          Scheduler 是一個(gè)計(jì)劃集,其中可以包含多個(gè) JobDetail 和 Trigger 組成的計(jì)劃任務(wù)。
          我們可以從 SchedulerFactory 中取得 Scheduler。

          接口Job是每個(gè)業(yè)務(wù)上需要執(zhí)行的任務(wù)需要實(shí)現(xiàn)的接口,該接口只有一個(gè)方法:

          public interface Job {
              public void execute(JobExecutionContext context)
                  throws JobExecutionException;
          }

          我們可以在里面定義我們的 Job 執(zhí)行邏輯,比如清除過期數(shù)據(jù),更新緩存等。

          JobDetail描述了一個(gè)任務(wù)具體的信息,比如名稱,組名等等。
          JobDetail jobDetail = new JobDetail("SayHelloWorldJob", Scheduler.DEFAULT_GROUP, SayHelloWorldJob.class);
          在上面的構(gòu)造方法中,第一個(gè)是任務(wù)的名稱,第二個(gè)是組名,第三個(gè)就是實(shí)際當(dāng)任務(wù)需要執(zhí)行的回調(diào)類。

          Trigger顧名思義就是觸發(fā)器,Quartz有個(gè)很好的想法就是分離了任務(wù)和任務(wù)執(zhí)行的條件。Trigger就是控制任務(wù)執(zhí)行條件的類,當(dāng)Trigger認(rèn)為執(zhí)行條件滿足的時(shí)刻,Trigger會(huì)通知相關(guān)的Job去執(zhí)行。分離的好處是:
          1.你可以為某個(gè)Job關(guān)聯(lián)多個(gè)Trigger,其中任何一個(gè)條件滿足都可以觸發(fā)job執(zhí)行,這樣可以完成一些組合的高級(jí)觸發(fā)條件
          2.當(dāng)Trigger失效后(比如:一個(gè)永遠(yuǎn)都不能滿足的條件),你不必去聲明一個(gè)新的job,代替的是你可以為job關(guān)聯(lián)一個(gè)新的Trigger讓job可以繼續(xù)執(zhí)行。

          目前的Quartz實(shí)現(xiàn)中,存在兩種Trigger,SimpleTrigger和CronTrigger,SimpleTrigger用來完成一些比如固定時(shí)間執(zhí)行的任務(wù),比如:從現(xiàn)在開始1分鐘后等等;而CronTrigger(沒錯(cuò),和unix的cron進(jìn)程的含意一樣)用來執(zhí)行calendar-like的任務(wù),比如:每周五下午3:00,每月最后一天等等。

          在我們項(xiàng)目中,都是一些固定時(shí)間的 Job,所以只用到了 SimpleTrigger。
          Trigger trigger = new SimpleTrigger("SayHelloWorldJobTrigger",Scheduler.DEFAULT_GROUP,new Date(),null,0,0L);
          這個(gè)構(gòu)造方法中,第一個(gè)是Trigger的名稱,第二個(gè)是Trigger的組名,第三個(gè)是任務(wù)開始時(shí)間,第四個(gè)是結(jié)束時(shí)間,第五個(gè)是重復(fù)次數(shù)(使用SimpleTrigger.REPEAT_INDEFINITELY常量表示無限次),最后一個(gè)是重復(fù)周期(單位是毫秒),那么這樣就創(chuàng)建了一個(gè)立刻并只執(zhí)行一次的任務(wù)。

          但我們定義好了 JobDetail,Job,和 Trigger 后,就可以開始 Schedule 一個(gè) Job 了。

          scheduler.scheduleJob(jobDetail, trigger);

          這條語句就是把job和Trigger關(guān)聯(lián),這樣當(dāng)Trigger認(rèn)為應(yīng)該觸發(fā)的時(shí)候就會(huì)調(diào)用(實(shí)際上是Scheduler調(diào)用)job.execute方法了。

          scheduler.start();
          千萬別忘了加上上面的語句,這條語句通知Quartz使安排的計(jì)劃生效。

          關(guān)于execute方法的參數(shù)JobExecutionContext
          JobExecutionContext就和很多Context結(jié)尾的類功能一樣,提供的運(yùn)行時(shí)刻的上下文環(huán)境,JobExecutionContext中有Scheduler,JobDetail,Trigger等很多對(duì)象的引用,從而當(dāng)你在execute方法內(nèi)部須需要這些對(duì)象的時(shí)刻提供的便利。

          在項(xiàng)目中,我們把需要執(zhí)行的 Job 相對(duì)應(yīng)的一些信息放在 JobExecutionContext 中,在 Job 執(zhí)行的時(shí)候可以調(diào)用。

          jobDetail.getJobDataMap().put(userid, id);

          在 Job 中,我們可以拿到相關(guān)的 Context 信息:

          jobExecutionContext.getJobDetail().getJobDataMap().getInt(userid);

          JobDetail和Trigger的name和group
          Scheduler實(shí)例對(duì)應(yīng)了很多job和trigger的實(shí)例,為了方便的區(qū)分,Quartz使用name和group這兩個(gè)特性,正如你想向的一樣,同一個(gè)group下不能有兩個(gè)相同name的JobDetail,Trigger同理,同一個(gè)Scheduler下不能有兩個(gè)相同group的JobDetail,Trigger同理,JobDetail和Trigger的完全限定名為:group + name

          為了讓服務(wù)器重啟以后,我們的 Scheduler 信息仍然不丟失,我們通常采用數(shù)據(jù)庫持久化 Scheduler 的信息。
          DBScript 在 Quartz 的下載包中的:quartz-1.6.0\docs\dbTables 下,選擇自己使用的 DB 相應(yīng)的 Script 導(dǎo)入數(shù)據(jù)庫就可以了。
          在應(yīng)用中,我們需要配置一個(gè) quartz.properties 才能正常使用 DB。我們可以在 quartz-1.6.0\examples\example10 中找到該文件的樣例,稍作一些修改,就可以放到自己項(xiàng)目源碼的根目錄下使用了。

          設(shè)置 org.quartz.jobStore.class = org.quartz.impl.jdbcjobstore.JobStoreTX 即可啟用基于 JDBC 的 Quartz 信息持久化。

          根據(jù)項(xiàng)目情況設(shè)置以下配置信息:
          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

          但是光設(shè)置了 Database 不夠,我們還需要在 Application 啟動(dòng)的時(shí)候自動(dòng)啟動(dòng) Scheduler 才行,我們只需要簡單的寫一個(gè) Servlet 的 Listener 并在 web.xml 中聲明該 Listener ,在 Servlet 容易啟動(dòng)的時(shí)候,Scheduler 就開始自動(dòng)執(zhí)行。

          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>

          以上簡單的記錄了在項(xiàng)目中關(guān)于 Quartz 的一些應(yīng)用,如果有什么新的使用心得,會(huì)在后面繼續(xù)加入的。

          posted @ 2007-08-02 16:28 steady 閱讀(3575) | 評(píng)論 (4)編輯 收藏

          上一篇中我們說到了,如何使用 HttpClient 抓取所需要的數(shù)據(jù),接下來介紹一下如何對(duì)這些數(shù)據(jù)進(jìn)行處理。基本的處理原理是使用正則表達(dá)式進(jìn)行內(nèi)容的匹配。

          為了便于處理,我們首先把使用 HttpClient 抓取到的數(shù)據(jù)做一些簡單的處理。

          第一步要做的就是刪除回車符,當(dāng)然我不會(huì)寫含有回車符的正則表達(dá)式才會(huì)這么寫的,當(dāng)然如果您有更好的方法也可以不用這么做。

          代碼很簡單:

          1protected String removeEnter(String response) {
          2    response = StringUtils.replace(response, "\r\n""");
          3    response = StringUtils.replace(response, "\n""");
          4    return response;
          5}

          接下來就可以使用正則表達(dá)式來對(duì)所抓取的內(nèi)容進(jìn)行匹配了:

          正則表達(dá)式是一種可以用于模式匹配和替換的強(qiáng)有力的工具,一個(gè)正則表達(dá)式就是由普通的字符(例如字符 a 到 z)以及特殊字符(稱為元字符)組成的文字模式,它描述在查找文字主體時(shí)待匹配的一個(gè)或多個(gè)字符串。正則表達(dá)式作為一個(gè)模板,將某個(gè)字符模式與所搜索的字符串進(jìn)行匹配。正則表達(dá)式在字符數(shù)據(jù)處理中起著非常重要的作用,我們可以用正則表達(dá)式完成大部分的數(shù)據(jù)分析處理工作,如:判斷一個(gè)串是否是數(shù)字、是否是有效的Email地址,從海量的文字資料中提取有價(jià)值的數(shù)據(jù)等等,如果不使用正則表達(dá)式,那么實(shí)現(xiàn)的程序可能會(huì)很長,并且容易出錯(cuò)。對(duì)這點(diǎn)本人深有體會(huì),面對(duì)大量工具書電子檔資料的整理工作,如果不懂得應(yīng)用正則表達(dá)式來處理,那么將是很痛苦的一件事情,反之則將可以輕松地完成,獲得事半功倍的效果。

          在這里,我使用了 Jakarta-ORO 作為正則表達(dá)式工具來進(jìn)行匹配。

          Jakarta-ORO是最全面以及優(yōu)化得最好的正則表達(dá)式API之一,Jakarta-ORO庫以前叫做OROMatcher,是由Daniel F. Savarese編寫,后來他將其贈(zèng)與Jakarta Project,讀者可在jakarta.apache.org的網(wǎng)站下載該API包。
          因?yàn)樵谶@里我們不需要用到太多正則表達(dá)式的知識(shí),僅僅是簡單的用用而已,所以幾行簡單的代碼就可以解決問題:
          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;
          }

          第一個(gè)參數(shù) response 表示抓取到的頁面源碼,第二個(gè)參數(shù) template 表示我們預(yù)先設(shè)定的模板,第三個(gè)表示第幾個(gè)匹配。返回的結(jié)果是匹配成功的 group 中的內(nèi)容。

          于是我們可以這樣的調(diào)用它:

          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);

          注意一下,我們正則表達(dá)式前后都有 "/"。
          另外,我們用() 括起來的部分表示我們要匹配的內(nèi)容,所以這里 name 可以匹配到 滬綜指,index 可以匹配到大盤的點(diǎn)數(shù)。 

          該匹配對(duì)應(yīng)于: http://web7.jrj.com/homev1/StockIndex.htm
          為了防止頁面以后打不開了大家找不到,我把其中相關(guān)的匹配部分的頁面源碼也發(fā)出來:

          <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> <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> <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>納斯達(dá)克</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>

          因?yàn)槲也皇菫榱私榻B正則表達(dá)式而寫這篇文章的,所以對(duì)正則表達(dá)式不會(huì)做太多的介紹,如果大家對(duì)正則表達(dá)式有興趣或想進(jìn)一步了解的話可以參考:

          JAVA中正則表達(dá)式的應(yīng)用
          http://www.ibm.com/developerworks/cn/java/l-regp/part1/index.html
          http://www.ibm.com/developerworks/cn/java/l-regp/part2/index.html


          另外因?yàn)闉榱俗ト∑渌麞|西,代碼已經(jīng)被我改的面目全非了,暫時(shí)就不方便貼出來了,請大家諒解,如果大家有什么疑問的話可以和我聯(lián)系,我會(huì)盡量說明清楚的。
          posted @ 2007-06-28 22:58 steady 閱讀(1800) | 評(píng)論 (2)編輯 收藏

              最近股市大牛,相信這里的不少朋友都在炒股,當(dāng)然上班時(shí)間老是開著網(wǎng)頁看股市或是盯著紅紅綠綠的專業(yè)股票軟件是總是擔(dān)心被周圍同事看到的,但又不時(shí)的想著大盤是漲了還是跌了,自己的股票又是如何呢。

              于是用 Java 寫了一套簡單的股市信息跟蹤的小程序,Console 的,用于抓取相應(yīng)的股市信息并顯示到 console 中,誰也不會(huì)想到這個(gè)東西會(huì)是用來看股市的吧。

              這套小小的程序用到了幾個(gè)非常簡單的技術(shù),HttpClient 和 正則表達(dá)式。程序功能非常簡單,找到含有股市數(shù)據(jù)的頁面,使用 HttpClient 抓取下來,通過正則表達(dá)式匹配自己需要的內(nèi)容,在 Console 上打印出來。

              準(zhǔn)備花兩篇文章簡單的介紹這個(gè)小系統(tǒng)中的實(shí)現(xiàn)細(xì)節(jié),當(dāng)然這只是簡單的介紹,其實(shí)我們再稍微用點(diǎn)其他的技術(shù),可以做出更多更實(shí)用的小工具。比如我就寫了個(gè)小爬蟲,把某個(gè)基金網(wǎng)站上的基金凈值數(shù)據(jù)爬來了,足足有10W條,供我做基金形勢分析之用,拿到這些原始數(shù)據(jù),再動(dòng)用一下自己的頭腦,再配合一些方便的工具,比如 Excel,我們便可以用實(shí)際數(shù)據(jù)去輔助投資理財(cái)。

                  首先我們來簡單的介紹我們用到的第一個(gè)工具,HttpClient。

              HttpClient 是 Apache Jakarta Common 下的子項(xiàng)目,可以用來提供高效的、最新的、功能豐富的支持 HTTP 協(xié)議的客戶端編程工具包,并且它支持 HTTP 協(xié)議最新的版本和建議。
              以下列出的是 HttpClient 提供的主要的功能,要知道更多詳細(xì)的功能可以參見 HttpClient 的主頁。
          實(shí)現(xiàn)了所有 HTTP 的方法(GET,POST,PUT,HEAD 等)
          支持自動(dòng)轉(zhuǎn)向
          支持 HTTPS 協(xié)議
          支持代理服務(wù)器等

          HttpClient 可以在http://jakarta.apache.org/commons/httpclient/downloads.html下載

          HttpClient 基本功能的使用
          GET 方法
          使用 HttpClient 需要以下 6 個(gè)步驟:
          1. 創(chuàng)建 HttpClient 的實(shí)例
          2. 創(chuàng)建某種連接方法的實(shí)例,在這里是 GetMethod。在 GetMethod 的構(gòu)造函數(shù)中傳入待連接的地址
          3. 調(diào)用第一步中創(chuàng)建好的實(shí)例的 execute 方法來執(zhí)行第二步中創(chuàng)建好的 method 實(shí)例
          4. 讀 response
          5. 釋放連接。無論執(zhí)行方法是否成功,都必須釋放連接
          6. 對(duì)得到后的內(nèi)容進(jìn)行處理

          根據(jù)以上步驟,我們來編寫用GET方法來取得某網(wǎng)頁內(nèi)容的代碼。

          根據(jù)這樣的過程,我們便可以寫出一個(gè)簡單的抓取頁面的方法,該方法返回抓到的頁面數(shù)據(jù)。傳入的參數(shù)是頁面的 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 是一個(gè)很實(shí)用的工具,用它,我們可以做很多和 Http 有關(guān)的事情。
          大家可以參考: http://www.ibm.com/developerworks/cn/opensource/os-httpclient/ 來初步了解 HttpClient 的功能。
          或是去找找 Jakarta.Commons.Cookbook 或者 Jakarta.Commons.Online.Bookshelf,上面介紹了包括 HttpClient 在內(nèi)的很多 Apache Jakarta Commons 項(xiàng)目,相信合理使用,會(huì)讓你事半功倍的。

          下一篇我們將介紹一下如何用正則表達(dá)式處理我們抓取到的數(shù)據(jù)。

          posted @ 2007-06-21 22:11 steady 閱讀(1931) | 評(píng)論 (5)編輯 收藏
               摘要: Java Platform Debugger Architecture(JPDA:Java平臺(tái)調(diào)試架構(gòu)) 由Java虛擬機(jī)后端和調(diào)試平臺(tái)前端組成
          1.Java虛擬機(jī)提供了Java調(diào)試的功能
          2.調(diào)試平臺(tái)通過調(diào)試交互協(xié)議向Java虛擬機(jī)請求服務(wù)以對(duì)在虛擬機(jī)中運(yùn)行的程序進(jìn)行調(diào)試  閱讀全文
          posted @ 2007-06-18 16:20 steady 閱讀(825) | 評(píng)論 (0)編輯 收藏

          最近在把在 tomcat 5.5 上開發(fā)的項(xiàng)目 deploy 到 JBoss 4.2 上時(shí),在操作一段時(shí)間就會(huì)出現(xiàn) java.lang.OutOfMemoryError: PermGen space,開始以為是代碼中存在死循環(huán)的地方造成這樣的問題,但是后來發(fā)現(xiàn),出問題的地方都是隨機(jī)的,并不是某一處造成這樣的問題出現(xiàn),懷疑是內(nèi)存泄露,通過增大 heap 內(nèi)存的方法來嘗試,依然不行,但是同樣的問題卻并沒有在 tomcat 中出現(xiàn)過,難道是 JBoss 的問題?

          在網(wǎng)上做了一番搜索得到一些相關(guān)的內(nèi)容。

          PermGen space的全稱是Permanent Generation space,是指內(nèi)存的永久保存區(qū)域OutOfMemoryError: PermGen space從表面上看就是內(nèi)存益出,解決方法也一定是加大內(nèi)存。說說為什么會(huì)內(nèi)存益出:這一部分用于存放Class和Meta的信息,Class在被 Load的時(shí)候被放入PermGen space區(qū)域,它和和存放Instance的Heap區(qū)域不同,GC(Garbage Collection)不會(huì)在主程序運(yùn)行期對(duì)PermGen space進(jìn)行清理,所以如果你的APP會(huì)LOAD很多CLASS的話,就很可能出現(xiàn)PermGen space錯(cuò)誤。這種錯(cuò)誤常見在web服務(wù)器對(duì)JSP進(jìn)行pre compile的時(shí)候。

          改正方法,在 run.bat 中加入:-Xms256m -Xmx512m -XX:MaxNewSize=256m -XX:MaxPermSize=256m

          因?yàn)轫?xiàng)目中引用了很多的 jar 包,而這些 jar 包中的 class 信息會(huì)被 JBoss 的 class loader 加載到 PermGen space 區(qū)域,在 JVM 默認(rèn)的情況下,該部分空間的大小只有 4M,在 jar 包非常多的情況下,顯然是不夠用的,所以通過 -XX:MaxPermSize=256m 指定最大值后即可解決問題。

          另外,如果 heap 內(nèi)存不足出現(xiàn) java.lang.OutOfMemoryError: Java heap space 時(shí),可以通過 -Xmx512m 指定最大 heap 內(nèi)存來解決這樣的問題。

          posted @ 2007-06-17 20:13 steady 閱讀(16809) | 評(píng)論 (7)編輯 收藏

          JBoss 4.2 GA 已經(jīng)發(fā)布有一段時(shí)間了,主要還是一些 bug fix 已經(jīng)一些新的包的加入。感覺比較爽的是解決了過去不太好用的一些地方。

          過去在用 JBoss 4.0.5 的時(shí)候一直被 Log 的問題困擾,如果在自己的項(xiàng)目里加入 log4j 和 common logging 的話,必然會(huì)出錯(cuò),所以我們不得以,必須通過一些調(diào)整手段來處理這樣的問題,也就是每次在 tomcat 下調(diào)試的應(yīng)用,需要改點(diǎn)東西才能 deploy 到 JBoss 上去,但使用了 4.2 以后就沒有這樣的問題了,在 tomcat  下用的包直接放過去,沒有做任何的修改就可以正常使用了。

          因?yàn)槲翼?xiàng)目用的是 commons-lang 2.3 而 JBoss 4.0.5 用的是 2.1 每次使用 commons-lang 2.1 里面沒有的方法時(shí),就會(huì)出現(xiàn) NoSuchMethodException,最后只好把 JBoss 下所有的 commons-lang 的包用 2.3 的替換掉,而 4.2 已經(jīng)沒有這個(gè)問題了,2.3 已經(jīng)可以正常使用了。

          默認(rèn)的 JBoss 4.2 我只能用 localhost 訪問,不能用 IP 地址訪問,后來發(fā)現(xiàn),需要修改 jboss-4.2.0.GA\server\default\deploy\jboss-web.deployer\server.xml 把 Connector 下面的 address 改成對(duì)應(yīng)的 IP 或者 0.0.0.0 就可以用 IP 訪問了。 

          后面附上了 Release Note 中的一些內(nèi)容。

          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 閱讀(2757) | 評(píng)論 (1)編輯 收藏

              新的一年開始,按理說要對(duì)去年的什么東西做一番總結(jié)了,當(dāng)然總結(jié)很多了,這次先總結(jié)一下 JSF 了,畢竟這對(duì)我來說是今年最主要的技術(shù)方向,對(duì)它也算是比較熟悉了,雖然沒有非常深入的去研究它,但從一年多的使用和理解來說,還是有不少自己的心得的,在新的一年到來之際,把這些東西記錄下來,重新記起這個(gè)讓我歡喜讓我憂的 JSF。靜觀這一年 JSF 的發(fā)展,沒有太多的興奮,也沒有太多的歡喜,更多的是平靜,與同一時(shí)間大紅大紫的 Ajax 和 RoR 相比,JSF 帶給我們的更多是平靜,靜的讓人心里發(fā)慌,上半年可以說還是稍有一些波濤了,而隨著月份的數(shù)字越來越大,波濤是越來越小了。   

              可以說各大廠商在互相妥協(xié)讓步的基礎(chǔ)之上,把 JSF 實(shí)用化的實(shí)現(xiàn)版本的重任交到了 Apache Myfaces 項(xiàng)目上,而 Oracle 也將其 ADF Faces 的實(shí)現(xiàn)捐給了 Apache,而現(xiàn)在我們可以見到的 JSF 實(shí)現(xiàn)也主要就是 Myfaces 了,當(dāng)然 Sun 自己也有一套實(shí)現(xiàn),當(dāng)然這只是一種不夠健壯,并且功能有限的實(shí)現(xiàn)版本,一般不會(huì)拿來做正式的項(xiàng)目的。剛過完年 Myfaces 1.1.2 和 Tomahawk 1.1.2 正式發(fā)布,這是過去 Myfaces 1.1.1 的一個(gè) bug 修復(fù)版本,離上一個(gè)版本已經(jīng)有半年左右的時(shí)間了,而項(xiàng)目組的同事們也在與 Myfaces 1.1.1 的 bug 斗爭了半年才用到這個(gè)新的版本。隨后的 Myfaces Core 1.1.3 / 1.1.4 則在幾乎一個(gè)月內(nèi)發(fā)布,而 1.1.5 和 Tomahawk 1.1.4 則至今沒有動(dòng)靜,雖然由 Myfaces 每次發(fā)布帶給我們的 new feature 已經(jīng)不是那么的多了,但是還是期盼新的版本能夠給我們帶來新的驚喜。

              五月份的時(shí)候 JavaEE 5 最終標(biāo)準(zhǔn)發(fā)布了,JSF 1.2 終于被正式提上了日程,這是一個(gè)對(duì)過去標(biāo)準(zhǔn)的一個(gè)修復(fù)版本,修正了上一個(gè)標(biāo)準(zhǔn)中的諸多問題,比如 JSTL 兼容性問題,還有一些細(xì)節(jié)性的改動(dòng),都是過去在 JSF 1.1 標(biāo)準(zhǔn)中非常折磨人的問題,但新的 1.2 標(biāo)準(zhǔn)依賴于 JDK 1.5,依賴于一系列新的 JavaEE 5 的 API,比如 Servlet 2.5, JSTL 1.2 而這些新的 API 也是在緊鑼密鼓的開發(fā)中,所以 Myfaces 1.2 的開發(fā)進(jìn)程也一直很慢,因?yàn)槠渲谐霈F(xiàn)的問題不光是 Myfaces 自己的問題,或許還有 Tomcat 6 的問題,或是其他的問題。而另一方面 Sun 也發(fā)布了一個(gè) JSF 1.2 的實(shí)現(xiàn)版本,是由 JSF 1.2 的標(biāo)準(zhǔn)的主筆領(lǐng)導(dǎo)開發(fā)的,按照我對(duì)于 Sun JSF 上個(gè)版本的表現(xiàn),我對(duì)于這個(gè)新的實(shí)現(xiàn)也不抱有太多的希望,或許它更多的只是一種象征了,象征著 JSF 1.2 的正式推出。

              開源領(lǐng)域的 JSF 相關(guān)的項(xiàng)目發(fā)展緩慢。Myfaces 在一年內(nèi)沒有給我們帶來太多的驚喜。曾經(jīng)做為黑馬出現(xiàn)的 JSF 擴(kuò)展框架 Shale 至今還沒有給大家?guī)硪粋€(gè)滿意的答復(fù),一直以 develop 版本發(fā)布出來給大家嘗鮮用,雖然慢慢的在前進(jìn),但是卻很難帶給大家什么驚喜,或許會(huì)被人逐漸的淡忘。而去年年底由 Oracle 捐給 Apache 的 ADF Faces 也是至今沒有太大的動(dòng)靜,同樣作為兄弟項(xiàng)目的 Struts 2 從提出到現(xiàn)在也有一年了,還沒有能提供一個(gè)正式的版本給我們用,作為 Apache 的項(xiàng)目,這樣的發(fā)布速度,確實(shí)很讓人不能滿意,而作為另一個(gè)大型的開源組織 Eclipse,則在一個(gè)個(gè) Milestone 下有條不紊的向前推進(jìn),不斷蠶食著別人所占據(jù)的地盤。

              作為 JSF 整體應(yīng)用平臺(tái)一個(gè)重要的部分,第三方組件庫的發(fā)展有不小的突破,但是真正的應(yīng)用度似乎不是很高,這一年內(nèi)出現(xiàn)了很多優(yōu)秀的商業(yè),開源的組件庫,除去上面我們提到的 Myfaces Tomahawk, Oracle ADF 之外,還出現(xiàn)了 ICEFaces, BackBase,WebGalileo Faces,另外在 .Net 領(lǐng)域的組件提供商 Infragistics 也通過收購發(fā)布了 NetAdvantage for JSF 2006 這樣的組件庫。另外一直在 JSF IDE 上有所作為的 Exadel 公司也在 JSF 組件上插上一手,一方面發(fā)布了其開源的 JSF 框架 Ajax4JSF 另一方面在其基礎(chǔ)上提供了一個(gè)商業(yè)的 JSF 組件庫 VCP,這樣的方式確實(shí)有一套,可以同時(shí)抓住兩方面的市場。另一方面國內(nèi)也出現(xiàn)了像金碟這樣基于自己 Apusic Application Server 的開源 JSF 組件庫,是一件值得我們國人驕傲的事情,不過由于其只能夠運(yùn)行于 Apusic 上,使其應(yīng)用面受到了不小的限制。

              讓我們再來看看這一年 JSF 相關(guān) IDE 在今年的作為了,在 06 年春節(jié)期間,一些支持 JSF 的 IDE 像趕集一樣不斷的推出來,先后有 MyEclipse 4.1 GA,Sun Java Studio Creator 2, Oracle JDeveloper, BEA Workshop Studio 3.0,在這一段時(shí)間推出。MyEclipse 和 BEA Workshop 是 Eclipse 的插件,而 JDeveloper 和 Creator 是基于 Swing 的,不過隨著時(shí)間的推移,大家真正在用的 JSF 開發(fā)工具也主要就是 MyEclipse 和 Workshop,不過 MyEclipse 在 JSF 上想和 Workshop 拼,還需要一些時(shí)日了,另外在九月份正式發(fā)布的 IntelliJ IDEA 6.0 也開始支持 JSF 了,當(dāng)然是用其獨(dú)特的方式去支持,雖然不提供圖形化的所見即所得的開發(fā)方式,但由于其 IDE 內(nèi)部各個(gè)部分間完美的組合,使得其在寫代碼的感覺上要遠(yuǎn)遠(yuǎn)超過的其他競爭者,這也正是獨(dú)立 IDE 和插件 IDE 一個(gè)重要的功能區(qū)別。

              縱觀 06 年的 JSF 的發(fā)展歷程,我還是對(duì) 07 年的 JSF 的發(fā)展很期待,希望 Myfaces 基于 JSF 1.2 的實(shí)現(xiàn)能夠盡快的推出,也能夠有更多更好的開源組件庫的出現(xiàn)。

          posted @ 2007-01-05 09:22 steady 閱讀(2227) | 評(píng)論 (6)編輯 收藏
          僅列出標(biāo)題
          共7頁: 上一頁 1 2 3 4 5 6 7 下一頁 
          主站蜘蛛池模板: 开平市| 盖州市| 阿拉善左旗| 张家川| 洪湖市| 新绛县| 合水县| 昌邑市| 永和县| 平乐县| 丹东市| 临泉县| 乡城县| 青川县| 鄂尔多斯市| 彩票| 泽州县| 河间市| 石狮市| 建昌县| 台东市| 扎赉特旗| 五原县| 定结县| 永平县| 江陵县| 大洼县| 金堂县| 通城县| 旅游| 扶沟县| 江城| 白玉县| 锦州市| 崇仁县| 田阳县| 卢龙县| 高青县| 昭平县| 财经| 邮箱|