<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    nighty

    折騰的年華
    posts - 37, comments - 143, trackbacks - 0, articles - 0

    2013年4月12日

    系統為ubuntu server,二臺機器A和B,IP為A 192.168.1.111,B 192.168.1.222
    A為rsync server,啟動為守護進程,B為備份機,做為rsync client,最后用crontab做一個簡單的作業,定時在B上執行同步文件的功能
    A的安裝和配置如下:
    1.  apt-get install rsync   可能提示系統已經安裝有了
    2. 配置文件/etc/rsyncd.conf
        默認安裝時是不會有這個配置文件的,但是可以 cp /usr/share/doc/rsync/examples/rsyncd.conf /etc  把它示例中的配置文件拷貝過來
        vi /etc/rsyncd.conf    這里參數有點多,但是有些可以先不管,關注重點的
        [ftp]  這里是模塊,可以配置多個,這個是系統默認給出的一個配置,下面給一個本機上的配置示例:
    --------------------------------------------------------------------------------------------------
    # so omit the "pid file" line completely in that case.
    pid file=/var/run/rsyncd.pid
    #syslog facility=daemon
    #socket options=
    # MODULE OPTIONS
    [share]
    comment = public archive
    path = /var/www/pub
    use chroot = no
    max connections=2
    # lock file = /var/lock/rsyncd
    # the default for read only is yes...
    read only = no
    list = yes
    uid = nobody
    gid = nogroup
    # exclude = 
    # exclude from = 
    # include =
    # include from =
    auth users = rsync
    secrets file = /etc/rsyncd.secrets
    strict modes = yes
    hosts allow = 192.168.1.222
    # hosts deny =
    ignore errors = yes
    ignore nonreadable = yes
    transfer logging = yes
    log format = %t: host %h (%a) %o %f (%l bytes). Total %b bytes.
    timeout = 600
    refuse options = checksum dry-run
    dont compress = *.gz *.tgz *.zip *.z *.rpm *.deb *.iso *.bz2 *.tbz
    ---------------------------------------------------------------------------------------------
    這里,最上面的是pid文件位置。然后配置了一個模塊名叫做share,最大連接數是2,read only = no,指定為非只讀(不然同步時會有權限問題)
    而后面的auth users = rsync 是指定一個同步的賬戶名叫做rsync,這個賬戶的認證文件是/etc/rsyncd.secrets,當然我們要創建這個文件

    3.  創建 /etc/rsyncd.secrets文件,內容為: rsync:123  表示rsync這個用戶的密碼是123 然后修改文件的權限 chmod 600 /etc/rsyncd.secrets

    4.  rsync server做為守護進程
         vi /etc/default/rsync
         可以看到開頭處這樣聲明:
    ------------------------------------
    # start rsync in daemon mode from init.d script?
    #  only allowed values are "true", "false", and "inetd"
    #  Use "inetd" if you want to start the rsyncd from inetd,
    #  all this does is prevent the init.d script from printing a message
    #  about not starting rsyncd (you still need to modify inetd's config yourself).
    RSYNC_ENABLE=inetd
    -------------------------------------------
       做為守護進程,可以設置為true或是xinetd方式來啟動。于是我們安裝inetd   sudo apt-get install xinetd
       安裝好后配置inetd的配置文件  vi /etc/xinetd.d/rsync ,輸入如下內容:
    ---------------------------------------------------
    service rsync
    {
        disable = no
        socket_type = stream
        wait = no
        user = root
        server = /usr/bin/rsync
        server_args = --daemon
        log_on_failure += USERID
    }
    -------------------------------------------------------
    然后啟動xinetd,/etc/init.d/xinetd restart,A服務器的rsyncd server就完成了!

    5.  B服務器由于是client,不需要配置,也不需要安裝xinetd,直接可以通過命令行執行
    rsync --delete -azvv rsync@192.168.1.111::share /var/www/pub/
    這個命令就可以直接連接到192.168.111的rsync賬戶,它會提示你輸入密碼,就是A中的secrets文件中的密碼,然后同步share模塊到本機的/var/www/pub目錄,你可以事前在A機器上創建一個文件如test.txt,隨便寫點內容,然后執行些命令,看是不是B上多了這樣一個文件?如果是,則表示已經連接成功。你接下來就可以做crontab了!

    posted @ 2013-04-12 12:23 寒武紀 閱讀(1345) | 評論 (0)編輯 收藏

    2013年4月9日

    二臺服務器,A的內網IP為192.168.1.111,B的內網IP為192.168.1.222,A做為master,B做為Slave
    1.  配置A的Mysql
         (1)  vim /etc/mysql/my.cnf
               去掉[mysqld]段中 server_id =1 和log_bin=/var/log/mysql/mysql-bin.log的#注釋
               加上  binlog-do-db = s3     s3就是要同步的數據庫的名稱,如果沒有這一行,表示同步所有的數據,另外 binlog_ignore_db = mysql。要表示忽略同步的數據庫名稱為mysql,如果有多個要指定同步或是忽略同步的數據,就配置多行,保存退出。
         (2) 創建一個復制用的賬戶(名稱為repl,允許從遠程連接,密碼為123456):
              GRANT REPLICATION SLAVE, RELOAD,SUPER, NO *.* TO repl@'%' IDENTIFIED BY '123456';
            FLUSH PRIVILEGES;
         (3) 重啟mysql服務,或是直接reboot機器也可以
         (4) 進入mysql,然后用 show master status\G  查看二進制日志的狀態,看到類似以下的結果:
              +------------------+----------+--------------+------------------+
              | File                      | Position  | Binlog_Do_DB | Binlog_Ignore_DB |
              +------------------+----------+--------------+------------------+
              | mysql-bin.000003 |     1376  | s3                  |                           |
              +------------------+----------+--------------+------------------+
    2.  配置B的Mysql
          (1) vim /etc/mysql/my.cnf
               去掉[mysqld]段中 server_id =1 和log_bin=/var/log/mysql/mysql-bin.log的#注釋,把server_id改為2,要和master機器的不一樣。并增加以下內容:
               binlog_do_db=s3
               log-slave-updates
              保存退出
         (2) 重啟mysql服務
         (3) 進入mysql,執行
              CHANGE MASTER TO MASTER_HOST='192.168.1.111', MASTER_USER='repl',Master_Port=3306,MASTER_PASSWORD='123456',MASTER_LOG_FILE='mysql-bin.000003',MASTER_LOG_POS=1376;
              SLAVE START;
              注意上面的CHANGE語句中,MASTER_LOG_FILE和MASTER_LOG_POS就是上面1.4中提到的show master status命令得到的結果,指定二進制文件的名稱和開始同步的位置。
         (4) 查看SLAVE狀態:    show slave status\G
    *************************** 1. row ***************************
                   Slave_IO_State: Waiting for master to send event
                      Master_Host: 192.168.1.111
                      Master_User: repl
                      Master_Port: 3306
                    Connect_Retry: 60
                  Master_Log_File: mysql-bin.000003
              Read_Master_Log_Pos: 1376
                   Relay_Log_File: mysqld-relay-bin.000002
                    Relay_Log_Pos: 1355
            Relay_Master_Log_File: mysql-bin.000003
                 Slave_IO_Running: Yes
                Slave_SQL_Running: Yes
                  Replicate_Do_DB: 
              Replicate_Ignore_DB: 
               Replicate_Do_Table: 
           Replicate_Ignore_Table: 
          Replicate_Wild_Do_Table: 
      Replicate_Wild_Ignore_Table: 
                       Last_Errno: 0
                       Last_Error: 
                     Skip_Counter: 0
              Exec_Master_Log_Pos: 1376
                  Relay_Log_Space: 1512
                  Until_Condition: None
                   Until_Log_File: 
                    Until_Log_Pos: 0
               Master_SSL_Allowed: No
               Master_SSL_CA_File: 
               Master_SSL_CA_Path: 
                  Master_SSL_Cert: 
                Master_SSL_Cipher: 
                   Master_SSL_Key: 
            Seconds_Behind_Master: 0
    Master_SSL_Verify_Server_Cert: No
                    Last_IO_Errno: 0
                    Last_IO_Error: 
                   Last_SQL_Errno: 0
                   Last_SQL_Error: 
      Replicate_Ignore_Server_Ids: 
                 Master_Server_Id: 1
        上面的紅色二行如果為YES則表示已經正常連接,可以進行復制了。

    posted @ 2013-04-09 20:33 寒武紀 閱讀(1735) | 評論 (0)編輯 收藏

    2013年3月27日

        許久沒用服務器上裝的那個postgresql,其實是用來做redmine的數據庫的,考慮到mysql可能經常升級,而rails的連接組件在安裝上有點麻煩,所以當初就裝成postgresql。
        今天準備備份一下,用的phppgadmin,剛開始是提示其中的pg_dump執行路徑沒有配置,重新配置好后,導出的結果卻是空的損壞文件。于是想算了,還是轉到pg的安裝目錄下執行pg_dump.
        服務器裝的是centos 6.2,忘了當初是建了一個用戶postgres.postgres進行安裝的,用其它用戶切換到pg的安裝目錄下bin/pg_dump是執行不了的,提示在指定目標下生成導出文件。故猜測應該是postgres這個用戶的權限不足!
        cat /etc/passwd查看一下當前有多少用戶,的確有postgres.postgres用戶,密碼多少?忘了!反正有root,直接passwd修改成新的密碼吧,于是就立馬修改了該用戶的密碼,可以正確切換到postgres用戶了,還需要root為postgres指定一個目錄有操作權限
        chown -R postgres.postgres /var/xxxx   
        然后再回到pg的bin目錄下,執行pg_dump redmine > /var/xxx/redmine.bak
        這下終于正常了,別忘了還得去redmine安裝目錄下,備份下files文件夾。
        
        僅以此為筆記,以后可以查閱使用

    posted @ 2013-03-27 22:39 寒武紀 閱讀(1400) | 評論 (0)編輯 收藏

    2012年4月28日

          用Flex做企業應用將近有一年時間了,這個過程很累,在國內這方面的積累不多,真正有參考意義的資料的確非常少。經過一段長時間的摸索后,多少也積累了一點經驗,就最近的關于單元測試的想法做一點總結,由于涉及的知識較多,這里也只是給出個人的一種思路。
         眾所周知,Flex的缺點是開發調試效率較低,而且它只是表現層的一種解決方案。在企業應用中最需要解決的是編譯生成的swf體積問題,我想任何客戶都很難接受一個企業應用全部打包在一個swf里,幾MB甚至幾十MB的初始化過程誰都無法接受,所以都必不可少地采用Module的加載方式,把不同的業務功能編譯成獨立的swf,需要用的時候再去加載。把核心功能、通信機制、公共組件設計成庫項目,編譯成swc做為RSL讓業務模塊共享調用,達到盡量減少業務模塊編譯體積的目的。在這方面如果用心優化的話,基本上可以控制到每個swf體積大概在200KB以內,這樣就算是互聯網方式部署,客戶訪問仍是可以接受的。
        

         該結構圖給出了一種整體的設計方案,Flex的啟動肯定得有Application,這個是用戶初登錄后第一個加載的swf(登錄就不要用flex了,用jsp或是模板實現吧)。所以它負責加載你設計的整個框架,包含模塊加載機制、通信代理方式、基礎庫初始化等等,而和Java端的通信目前比較有效的仍然是blazeds,這個技術需要的介紹內容不在本文的范圍之內。關于通信接口的實現有一種非常有用的方式就是借用Java的動態代理理念,Spring有一個flex的擴展子項目叫做springactionscript,而這個項目又引用了as3commons的庫(類似于apache commons的一些公共組件)。為什么提及這個,因為flex本身的反射功能api非常難用,所以as3commons就做了擴展,它大大簡化了反射的使用,而且提供了一個bytecode的工具用于操作字節碼,它是實現動態代理的關鍵。至于為什么要動態代理?目的就是達到在寫和Java對接的接口時,可以只聲明接口,不需要實現類(得減少多少重復代碼呀?),而和Java對接接口我們又可以開發一個工具讓java code 自動轉成 as code,如果懂得Eclipse插件開發的話還可以進一步做一個插件,達到Java只寫一次就可以自動生成對應的flex接口,提高開發效率。
         轉入正題,關于單元測試的概念,Flash Builder在4.5已經把flex unit作為內置庫了,這點和Eclipse把junit內置類似,而flex unit的使用網上有大量的資料介紹,這里也不多說。flex unit在測試as代碼還是不錯的,和junit測試一樣,提供了一些簡單的Assert斷言,但是你最痛苦的卻不是as的測試。企業開發的特點就是數據量不大,但是需求坑爹,經常變來變去,而且結構復雜,往往一張表很多字段,關聯子表,層級屬性多。而你如果選擇了Flex做了展示層的技術,那必定是看中它比HTML + CSS + JS更強的界面交互功能。的確,這點不容質疑,Flex Spark的皮膚機制的確提供了很多優秀的特點,不過如果你想純熟掌握它的整個機制,恐怕得花很多時間閱讀源代碼才行,而皮膚的制作整對別想讓美工獨自實現,它同樣是需要技術積累的,介紹它需要用幾個篇幅才足夠。任何技術方案都一樣,BS、CS、AIR在實現復雜界面時,對于開發人員來說,最痛苦的莫過于界面的單元測試。
         痛苦在哪里?回看上面那幅架構圖,業務功能界面實現在Flex,業務邏輯在后臺Java,那么當二個團隊同時進行工作的時候,溝通就是最大的成本。解決溝通的問題就必須在先前設計時約定好接口和數據結構,那是會影響雙方團隊協調的關鍵因素。當雙方同時進行開發的時候,勢必存在前臺依賴后臺的情況,因為它能到達界面的前提得在整個框架載入后(并且可以初始化一堆數據,發生了通信),Java后臺還好說,依賴于spring和junit可以做到很好的單元測試。而flex就痛苦了,我沒有通訊啥都做不了呀!
         如何設計單元測試?最大的出發點就是如何切掉和后臺通信連接,看下面的簡單結構圖

         實現思路介紹:
         1.  簡化Application加載過程   --   可以套用你主程序中的加載過程,但是不需要你的主界面其它多余的元素,達到減少到達測試界面的多余步驟(盡可能少地減少鼠標和鍵盤操作)
         2.  定義測試配置   --   測試哪個模塊?哪個工作流程?你得通過配置的方式來定義,而不是每次都手寫代碼,才能方便你的成員使用你這個工具
         3.  模擬后臺接口實現  --  記得上面說的動態代理嗎?其實是為接口動態生成一個實現類,然后注入真正通信的實現代碼,例如WebService、HTTP,既然可以注入這些通信渠道,當然就可以注入本地實現類啦
         4.  對象查看器    --   這個是神馬?因為你都不要Java后臺了,每次操作一個界面后得提交數據吧?沒有后臺了,提交到哪里?你得必須把你的提交對象用界面展示出來吧?好吧,這個可是個難點!

         我想這四個方面的原則無非就是:減少單元測試需要進行的步驟(最快到達測試界面),脫離后臺依賴(自己簡單模擬后臺實現,可惜flex沒有類似java的mock庫,悲劇!),如何查看提交到后臺的結果。 單元測試的目標:界面能正常加載、提交數據正常,如果二者都沒問題,那么聯調的時候就可以非常容易定位到是Flex的問題還是Java的問題!達到介分責任的目標,當然,如果你所在團隊是按模塊分的,也就是說flex和java都是同一個人做,那么就不存在責任問題。

         怎么實現上面的四個步驟呢?簡要地介紹一下吧。
         第1簡化application加載,其實你可以把第一張圖中的application加載機制拷貝過來,只是主界面可以做得非常簡單,比如不需要多余的控件(比如過長的菜單、當前登錄人、時間、一陀設置按鈕等),只留下最核心的能到達你測試界面的入口,至于怎么設計這個簡化版的application,那得發揮你本人的創造力,另外還得看具體的業務。

        第2定義測試配置。模塊如何加載?通信接口本地模擬實現類定義?通過配置顯示在appliation做為觸發控件,這些你都得自定義一套xml之類的文件來配置吧,這個就需要技巧了,不能設計得太復雜,因為你的開發人員需要沿用你定義的規范來定義它需要測試的模塊,關于這方面的知識,可以參考spring加載配置文件方式、struts2加載定義文件等理念,有一個概念我比較推薦,就是struts2中的include配置文件,允許配置文件分散,讓大家提供代碼和文件時減少沖突,又可以套用你正常的加載機制。

        第3模擬后臺接口實現。這個是比較煩的,模擬機制本身通過動態代理倒是不難實現,惡心的是你得自己動手用flex簡單實現一次后臺生成數據、處理數據的邏輯。這里我有個實踐的總結經驗分享,在前期你調試完的后臺接口證明是沒有問題的,那么可以混合使用,一部分調試過的接口可以直接用后臺,而新接口才本地模擬。一個原則就是后臺有的,已經證明穩定的就用后臺,沒有的或是后臺還沒有完成的你就自己模擬。

        第4對象查看器。想想flex不能操作數據庫、由于安全限制不允許直接操作文件、無法讀取本地文件目錄。而你的測試數據也許會有關聯(特別是在工作流方面),所以你得想一個方案來保存你的對象結果,而且得以一種人性化的方式查看對象內容。且拋開數據存儲的問題,這個對象查看器如何設計就夠你頭疼的了,首先是對象得定義成一種格式,一種人可以看得懂的格式,比如xml,可以支持序列化和反序列化,你得去掉多余的無用屬性和訪問器。又得回到反射機制上了,序列化其實不難,難的是反序列化時如何正確地轉成原來的對象。列一種本人設計的結構:
         <xxx   type="com.xx.oo.XXClass">
              <aa type="String">aaa</aa>
              <bb type="Boolean">true</bb>
              <list type="mx.collection.ArrayCollenction">
                  ....
              </list>
         </xxx>
         對象分簡單對象、復雜對象、動態對象等,如何表達這種結構和保證序列化時不丟失數據需要細心考慮。那么最后如何實現查看器呢?其實有一個參考的范例,就是Eclipse的“大綱”視圖,經過實踐的擴展,把樹視圖換成表格樹(這種控件原生沒有,有第三方的可以拿來修改),看個樣圖吧!
     
         因為你關注的對象內容無法就是這三個方面,屬性名、值、和類型,又支持以樹方式導航對象,已經足夠你人眼分辯內容了。至于如何有效的保存測試數據,并且組織好結構,這個方面我目前也仍在思考中,未有較好的思路。
         以上內容僅是出于本人的一種方案,也許有更好的實現方案,只是水平不足以超過這種認識,希望后續能進一步思考能實現更加完美的單元測試框架。
         ST測試更關注的界面的自動化測試,這方面涉及的知識更多,一般公司是很難有財力和技術去支持做自動化測試,屬于比較高端的范圍,實現是很多回歸都靠測試團隊人肉在實現。

    posted @ 2012-04-28 12:03 寒武紀 閱讀(1538) | 評論 (1)編輯 收藏

    2011年10月13日

          采用Spark進行Flex的Web應用開發的時候,往往會用一個固定欄,比如說類似Windows的任務欄,我們想把它固定在頂部或是底部,用于某些場景存放一些控件。<s:Application>組件中有一個<s:controlBarContent>屬性和<s:controlBarLayout>,用于設置Application的一個組件區域(我猜官方起的這個名稱大概用意在于此吧),下面這段話就是官方的中文注釋:
    Title包含在 Application 容器控件欄區域中的組件集。Application 容器控件欄區域的位置和外觀由 spark.skins.spark.ApplicationSkin 類確定。默認情況下,ApplicationSkin 類定義以灰色背景顯示在 Application 容器內容區域頂部的控件欄區域。創建自定義外觀以更改控件欄的默認外觀。
          于是可以簡單的給<s:controlBarContent>區域添加各種控件,以及設置它內在的布局(controlBarLayout)。但是,發現它只能顯示在Application的頂部!
          這是怎么回事,根據上面的注釋,感覺應該原因在它的皮膚,得跟進代碼,看一下究竟。
          首先找到<s:Application>控件的標準Skin,可以在Flash Builder中直接查看。
          
          雙擊打開ApplicationSkin,里面的代碼包含了各種SVG圖形學的實現api調用,flex管這些庫叫FVG,大意就是SVG的Flex實現版本,該庫實現得還算簡潔!
          Application標準皮膚的就是先畫一個矩形,然后用一個Group來包含不同的形狀,最后一段<s:Group id="contentGroup" width="100%" height="100%" minWidth="0" minHeight="0" />,代表Application的內容區域,Flex從設計上區分了控件樹和布局樹,有些復雜,可以參考官方的文檔。因為Application是屬于容器,所以必須在皮膚中包含這一句,不然程序運行時就看不到它包含的子控件。
         而前面長長一串<s:Group id="topGroup">中是畫了頂欄的外觀,它用FVG庫畫了四層:
         <!-- layer 0: control bar highlight -->     底部高亮線(用畫筆填充一個矩形)
         <!-- layer 1: control bar fill -->              背景填充線性漸變顏色
         <!-- layer 2: control bar divider line -->  分割線
         <!-- layer 3: control bar -->                  controlBar的具體內容容器
         當然這個controlBar不是自己會出現的,只有當你填充了內容控件的時候它才顯示,所以有includeIn="normalWithControlBar, disabledWithControlBar",表示在這二個State下才顯示,什么時候State才包含這二個呢?當然,就得去看Application.as的實現原理,具體篇幅就不描述。
         那么回到最初的問題:我想改變controlBar的位置在下方怎么處理?
         從上面的分析可知其實controlBar的擺放位置是在Skin中定義的,而它是什么布局,它顯示不顯示是通過Application.as本身的代碼控制的,那么我們就只要自定義Application.as的皮膚就可以,新建一個外觀mxml,直接復制官方的ApplicationSkin.mxml的代碼,然后,把<s:Group id="contentGroup" width="100%" height="100%" minWidth="0" minHeight="0" />代碼移到<s:Group id="topGroup">代碼的上面,在你的Application中強制指定skinClass為你自定義的ApplicationSkin,或是通過css設定即可。
         再擴展思維一下,其實我們完全可以把controlBar放到左邊或是右邊,甚至任何位置,都取決你在Skin的定義和Application.as的邏輯控制(你可以繼承Application擴展)。
         那么controlBar有什么作用?其實spark的Panel從及它的子類TitleWindow都有controlBar的概念,它能獨立于你容器外的區域,對于你容器本身包含的組件和布局不會產生干擾,以及你設置了width、height為100%時也不產生影響。如果你不要controlBar,直接在Application中用布局添加一個Group也是可以實現,但是它從根本上是屬于布局樹中contentGroup的內容,會受限于布局。
         Spark Skin的設計的確有高明的地方,對比Flex3的外觀,它提供給設計人員的空間實在大得多,你可以組合圖片和FVG庫的功能自定義各種外觀,當然,我就建議你多熟悉一下FVG庫的應用,畢竟從外加載圖片對flex來說是一個消耗,你的程序也會增肥。

    posted @ 2011-10-13 18:14 寒武紀 閱讀(2480) | 評論 (0)編輯 收藏

    2011年8月14日

          問題描述:
              服務器操作系統是Centos5.5,此前已經有多套系統跑在上面,且裝有PHP5.2.10。Centos5.X系統的穩定yum安裝源版本是5.1.6,并不符合最新版本的phpmyadmin(5.2以上版本),下載了最新版本phpmyadmin安裝后提示缺少mysql支持模塊。
    查看了一下發現的確是安裝php的時候沒有裝上php-mysql模塊。直接重新編譯php源碼安裝比較麻煩。
         一個比較方便的方法:
        為yum添加第三方的源,然后直接用yum -y install php-mysql進行安裝
        以下方法為從網絡搜索到的,做個記錄,方面須用之時查閱。
              導入地址:    rpm --import http://www.jasonlitka.com/media/RPM-GPG-KEY-jlitka
              編輯yum源: vi  /etc/yum.repos.d/CentOS-Base.repo
              在最下面添加如下信息:
                       [utterramblings]
                       name=Jason's Utter Ramblings Repo
                       baseurl=http://www.jasonlitka.com/media/EL$releasever/$basearch/
                       enabled=1
                       gpgcheck=1
                       gpgkey=http://www.jasonlitka.com/media/RPM-GPG-KEY-jlitka

          
        然后執行安裝命令: yum -y install php-mysql    系統就會自動從上面添加的源中讀取合適該版本的php-mysl模塊,安裝完成后重啟httpd服務,再訪問就OK了。
        該方法同樣適合于默認安裝的php5.1.6版本安裝成功后再進行升級到 5.2版本。

    posted @ 2011-08-14 15:53 寒武紀 閱讀(2100) | 評論 (2)編輯 收藏

    2011年5月22日

        freemarker幾天前才發布了2.3.17版本,5月21號又發布了2.3.18,距2.3.16已經一年多了。老的編輯器已經不能安裝在新版本的eclipse和myeclipse上面了,最新的官方編輯器仍在開發階段,有網友貌似知道最新的源代碼鏈接位置,不過肯定是不穩定的。
        另一個可選的編輯器就是JBoss Tools 3.2中的FreeMarker編輯器,值得安慰,啟動MyEclipse9.0后進入MyEclipse Configuration Center --> Software --> add site,輸入Name: freemarker,    
        URL:   http://download.jboss.org/jbosstools/updates/stable/helios/  然后在All JBoss Tools 3.2.0下選擇FreeMarker IDE,其它的大概你不需要都不用管,也不影響下載時間,然后一路確認安裝就OK!

    posted @ 2011-05-22 22:15 寒武紀 閱讀(2837) | 評論 (0)編輯 收藏

    2011年5月20日

           上周服務器的一個PHP軟件不能訪問,查看原因是CentOS的PCRE模塊未用utf-8編碼引起的,由是搜索了一些資料照著變更,沒有效果。
           當時和另一個朋友L共同嘗試刪除后重裝,由于對Linux系統不熟悉,只會使用常規的命令進行一些皮毛的操作,就直接用yum remove進行刪除,系統當時還提示是否remove掉相關聯的700多個組件或模塊。當時也沒有多想就直接回車!結果------悲劇了,屏幕狂刷,我意識到pcre是基礎模塊,所有關聯它的或是它關聯都刪除掉,系統將遭遇一個災難式的破壞。等刷完屏幕的字符,最終發現:所有的bin目錄下的命令全部不見了!!!天哪,連ls命令都沒有,唯獨剩下一個cd命令。幸運的是,當時運行在服務器的幾個應用還能訪問,比如說phpmyadmin。

            而后想了想,嘗試了各種方式去恢復,都沒有辦法,那么,唯一的辦法就是盡量備份原有的數據和文件,重裝系統進行環境的重新搭建。還好有其它方式,可以先把里面重要的文件都提取了出來。然后在幸存的phpmyadmin上趕緊進行mysql相關數據庫的備份。(注:因為是個人的服務器,所以并沒有像公司一樣做好運營和備份計劃)

            第二天決定重裝系統了,管理員用了3個小時才搭建起CentOS5.5和SSH遠程服務端。輪到我和L需要用SSH進行遠程的環境搭建。接下來的三天晚上,真是折騰又折騰。計劃安裝的幾個主要軟件是:Mysql、PHP、Apache、JDK、Tomcat、Ruby on Rails、Redmine、PHPMyAdmin等。

            第一個晚上,災難之前裝在上面的上述各種軟件版本都有點低,所以想干脆直接上最新的,而CentOS5.5的yum庫是取不到這些最新的軟件的。所以朋友 L 大量地采用了make install和rpm方式來安裝,而CentOS本身集成的就只有Apache的版本滿足。裝了MySQL5.5+phpMyAdmin3.4,運行起來了卻發現和MySQL5.5和redmine1.1.1有沖突,主要是RoR環境的Mysql驅動有問題,在網上能找到的都是從http://www.tmtm.org/en/ruby/mysql/ 下載的0.2.6版本,這個版本我只試在MySQL5.0情況下正常連接。現在換成5.5,就無法運行了,為此我還特地把Ruby環境從1.8.6提高到1.8.7,同樣裝了redmine官網要求的各種Ruby工具和Rails組件,折騰無果!最后,我還把異常信息拿出來,給ruby-mysql的日本作者發了一個email,第二天作者回復我,原來ruby-mysql已經掛到GitHub去了,而且現在已經是3.0alpha狀態了,但是他不確定能否工作在ruby1.8.6下。 最后感覺還是不行,切換回MySQL5.0,同樣高版本的ruby-mysql驅動也無法連接低版本的MySQL。第一天以失敗告終!

           第二天晚上繼續折騰,再不停地重新安裝,這時才想起一個問題:應該退回到系統宕機前的所有軟件版本狀態,這樣原先備份的數據才能正常恢復,不會帶來額外的版本沖突麻煩。于是折騰到接近晚上12:00時發覺方向錯了,無奈,和 L 打了個招呼,計劃明天讓管理員再重裝一次系統,現在目前的系統又被我們搞亂了!

           第三天。就著原來的思路,重裝恢復到以前的版本,又用yum的原來方式裝回原來的版本,這次進行順利。用了二個小時,就把常用的軟件恢復了,同時恢復了數據庫。最后只剩下一個問題,redmine的密鑰恢復后,仍然無法連接原來的用戶密碼,我想可能得去查閱redmine的用戶管理模塊,看看它究竟是怎么生成密碼和檢驗登錄的,有趣的事是發現網友找到另一個方法,就是直接在redmine下建ruby腳本,調用ActiveReord的User.save(),存一個自己的新密碼,不曉得可不可行,找個時間做個實驗看看。

          回頭一想。其實規劃、整理、理清服務器的管理工作,比精通Linux系統、各種軟解決技術更為重要!

    posted @ 2011-05-20 09:24 寒武紀 閱讀(7795) | 評論 (2)編輯 收藏

    2011年5月19日

        Phusion Passenger模塊使得Rails應用可以像PHP模塊一樣運行在Apache上,非常方便。
       準備條件:CentOS服務器已經裝好了Apache2.2和Redmine應用        

        1. 安裝Passenger模塊
                gem install passenger
                passenger-install-apache2-module
            
                第二個命令是安裝passenger的apache2模塊,它已經做得很智能,會提示你確認安裝以及最后怎么配置模塊到apache中。
                摘出配置段的內容如下:
                    Please edit your Apache configuration file, and add these lines:

                    LoadModule passenger_module /usr/lib/ruby/gems/1.8/gems/passenger-3.0.7/ext/apache2/mod_passenger.so
                    PassengerRoot /usr/lib/ruby/gems/1.8/gems/passenger-3.0.7
                    PassengerRuby /usr/bin/ruby

                把紅色字體部分拷貝到apache的配置文件,可以是主配置文件/etc/httpd/conf/httpd.conf,也可以是在/etc/httpd/conf.d/目錄下新建一個子文件命名為ruby.conf,推薦第二種方式,更為簡潔,不會影響主文件的配置。
          
        2. 先測試一下passenger是否安裝正常

                切換到redmine的安裝目錄下,passenger start  命令嘗試一下是否正常能以paasenger方式啟動,如果沒有異常,恭喜,已經安裝完成,剩下的工作就是配置一個虛擬主機和子給你的redmine,這樣可以轉到更為常用的80端口上。

        3. 配置rails應用做為sub URI模式
                 在passenger的官方文檔中其實有好幾種配置的方式,可以是域名、域名子URI等,很多時候你可能只有一個域名,那么利用sub URI來掛不同的應用就顯得比較
                首先配置一段虛擬主機如下:

            <VirtualHost *:80>
                ServerName www.phusion.nl
                DocumentRoot /websites/phusion
                <Directory /websites/phusion>
            Allow from all
                </Directory>
            </VirtualHost>

               解釋一下過程大致是先創建一個硬鏈接,如下:

            ln -s /webapps/mycook/public /websites/phusion/rails 
     
         /webapps/mycook/public是你的rails的應用目錄下面的public目錄,例如你的redmine安裝在/var/www/html,這個目錄就是
    /var/www/html/redmine/public,后面就是你Apache主目錄下的創建的一個鏈接地址rails,意思就是把/var/www/html/redmine/public
    鏈接到/var/www/html/rails,而/var/www/html/rails是實際上不存在的。
    然后再配置子目錄如下:

    <VirtualHost *:80> ServerName www.phusion.nl DocumentRoot /websites/phusion <Directory /websites/phusion> Allow from all </Directory>
    RailsBaseURI /rails # <-- These lines have <Directory /websites/phusion/rails> # <-- been added. Options -MultiViews # <-- </Directory> # <-- </VirtualHost>

     最后四句帶#注釋說明是重點,應用RailsBaseURI命令把rails子URI指定到rails的應用目錄,而rails目錄就是我們上面鏈接的目錄,而實際上會跳到我們的直接redmine目錄。

     

    posted @ 2011-05-19 15:10 寒武紀 閱讀(2543) | 評論 (1)編輯 收藏

    2011年4月26日

            引言:最近又用到dbutils,之前一直用Map映射的方式取出select的結果再手工做轉換。有寫過一篇文章說MapHandler方式的一個缺陷:關于commons dbutils組件的一個小缺陷分析 ,用這種方式,在項目不大的情況下,寫一些Map到JavaBean的轉換代碼工作量不大,但是在數據庫表過多并且表中的字段過多的情況下,這種重復的setter感覺有點煩。于是又重新思考了BeanHandler和BeanListHandler的情況,dbutils底層映射用的反射,性能上肯定有損失,不過在大多數項目規模不是很大的情況下,這點損失可以忽略,帶來的代碼減少卻是比較可觀。
            問題在哪里?先看一段官方的示例代碼:

    QueryRunner run = new QueryRunner(dataSource);

    // Use the BeanHandler implementation to convert the first
    // ResultSet row into a Person JavaBean.
    ResultSetHandler<Person> h = new BeanHandler<Person>(Person.class);

    // Execute the SQL statement with one replacement parameter and
    // return the results in a new Person object generated by the BeanHandler.
    Person p = run.query(
        
    "SELECT * FROM Person WHERE name=?", h, "John Doe");

            這里有個地方有約束,就是要求示例中的JavaBean類Person中的字段定義要和數據庫的字段定義一致。Java的命名習慣一般是駱峰寫法,例如userId,那么數據庫中就必須定義為userId,而問題在于:有時候我們需要數據庫中字段的定義格式與JavaBean的命名不一樣,比如數據庫定義為:user_id,而JavaBean則定義為userId
            看源代碼可能有點費時間,在官方的example頁面的最下面果然有一段關于自定義BeanProcessor的指引。摘錄出來:

          BasicRowProcessor uses a BeanProcessor to convert ResultSet columns into JavaBean properties. You can subclass and override processing steps to handle datatype mapping specific to your application. The provided implementation delegates datatype conversion to the JDBC driver.
          BeanProcessor maps columns to bean properties as documented in the BeanProcessor.toBean() javadoc. Column names must match the bean's property names case insensitively. For example, the firstname column would be stored in the bean by calling its setFirstName() method. However, many database column names include characters that either can't be used or are not typically used in Java method names. You can do one of the following to map these columns to bean properties:
          1. Alias the column names in the SQL so they match the Java names: select social_sec# as socialSecurityNumber from person
          2. Subclass BeanProcessor and override the mapColumnsToProperties() method to strip out the offending characters.


          大概意思就是提供二種方式:一種就是最直接的,用as關鍵字把colName重命名,另一種方式就是繼承BeanProcessor類,重寫mapColumnsToProperties()方法。
          那當然是第二種方式更加具有代表性。嘗試了一下。代碼如下:
        
     1public class CustomBeanProcessor extends BeanProcessor {
     2    
     3    @Override
     4    protected int[] mapColumnsToProperties(ResultSetMetaData rsmd,
     5            PropertyDescriptor[] props) throws SQLException {
     6        int cols = rsmd.getColumnCount();
     7        int columnToProperty[] = new int[cols + 1];
     8        Arrays.fill(columnToProperty, PROPERTY_NOT_FOUND);
     9
    10        for (int col = 1; col <= cols; col++{
    11            String columnName = rsmd.getColumnLabel(col); 
    12            if (null == columnName || 0 == columnName.length()) {
    13              columnName = rsmd.getColumnName(col);
    14            }

    15            columnName = colNameConvent(columnName); // 在這里進行數據庫表columnName的特殊處理
    16            for (int i = 0; i < props.length; i++{
    17
    18                if (columnName.equalsIgnoreCase(props[i].getName())) {
    19                    columnToProperty[col] = i;
    20                    break;
    21                }

    22            }

    23        }

    24        return columnToProperty;
    25    }

    26
    27    /**
    28     * 數據庫列名重新約定
    29     * @param columnName
    30     * @return
    31     */

    32    private String colNameConvent(String columnName) {
    33        String[] strs = columnName.split("_");
    34        String conventName = "";
    35        for (int i = 0; i < strs.length; i++{
    36            conventName += StringUtils.capitalize(strs[i]);
    37        }

    38        StringUtils.uncapitalize(conventName);
    39        return conventName;
    40    }

    41}

            注意mapColumnsToProperties方法的邏輯是從父類的方法中直接復制出來的,然后在第15行那里變了個戲法,這里的columnName就是從數據庫中讀出來的,自定義一個private方法用于轉換命名,這里你就可以添加自己的命名約束。例如上面就是把 user_id 轉化為Java的駱峰寫法:userId
           再深入一層思考,你可以在這里進行更多擴展,以便讓自己可以選擇不同的命名轉換方式。定義了這個Processor之后,下面看看如何調用:
    Connection conn = ConnectionManager.getInstance().getConnection();
    QueryRunner qr 
    = new QueryRunner();
    CustomBeanProcessor convert 
    = new CustomBeanProcessor();
    RowProcessor rp 
    = new BasicRowProcessor(convert);
    BeanHandler
    <User> bh = new BeanHandler<User>(User.class, rp);
    User u 
    = qr.query(conn, sql, bh, params);
    DbUtils.close(conn);
          是不是非常靈活?如果是想返回List結果的,就把BeanHandler替換成BeanListHander類,還可以再進一步封裝這些操作,抽象到公共模塊中去,讓外部直接傳入sql語句和Class就能直接返回想要的結果,當然你得增加泛型的定義。同樣舉一個封裝的例子:
     1protected <T> List<T> selectBeanList(Connection conn, String sql, Class<T> type,
     2            Object[] params) throws Exception {
     3        log.debug("select sql:[" + sql + "]");
     4        QueryRunner qr = new QueryRunner();
     5        CustomBeanProcessor convert = new CustomBeanProcessor();
     6        RowProcessor rp = new BasicRowProcessor(convert);
     7        ResultSetHandler<List<T>> bh = new BeanListHandler<T>(type, rp);
     8        List<T> list = qr.query(conn, sql, bh, params);
     9        return list;
    10    }

            至于為什么擴展這個方法就可以實現這個邏輯就得去跟源代碼看它的內部實現,用了一些JavaBean的處理和反映的技巧來做的。具體就不說。
            總結:commons組件都設計得非常好,可擴展性和實用性都非常高。雖然上面舉例實現了轉換邏輯的替換,但是仍然需要開發人員在設計數據庫的時候和寫JavaBean時都要嚴格做好規范,避免產生不必要的問題。這方面Ruby On Rails就直接內部實現,動態語言的優點特別能體現,同時強制你在設計時必須用這種方式,典型的約定優于配置原則。當然,在dbutils里你愿意二種字段名都一樣也無可厚非。
           缺點:BeanProcessor是不支持關聯查詢的,所以上面的方式也只能局限于單表的轉換,這點就不如myBatis和Hibernate,當然用這二個就引入了一些復雜性,如何權衡需要自己衡量,哪個用得好都一樣。本人就不喜歡myBatis那種把SQL寫到XML中的方式,見過太復雜的SQL最終在XML里面變得面目全非,如果是接手別人的代碼,是很痛苦的,而且你無法避免只修改XML而不改Java,既然二者都要改,那直接寫Java里又有什么區別?簡單就是美。格式和注釋寫好一點同樣很容易理解!

    posted @ 2011-04-26 16:41 寒武紀 閱讀(4266) | 評論 (0)編輯 收藏

    主站蜘蛛池模板: 成人精品视频99在线观看免费| 在线a人片天堂免费观看高清| 亚洲电影唐人社一区二区| 午夜影视日本亚洲欧洲精品一区| 午夜免费啪视频在线观看| 激情五月亚洲色图| 国产午夜亚洲不卡| 免费福利视频导航| 无码毛片一区二区三区视频免费播放 | 国产成人亚洲午夜电影| 亚洲码国产精品高潮在线| 1024免费福利永久观看网站| 老司机福利在线免费观看| 337p日本欧洲亚洲大胆艺术| 免费永久国产在线视频| 8888四色奇米在线观看免费看| 美女扒开屁股让男人桶爽免费| 亚洲大片在线观看| 伊在人亚洲香蕉精品区麻豆| 永久黄色免费网站| 亚洲国产精品久久人人爱| 又粗又硬免费毛片| 老司机在线免费视频| 老司机69精品成免费视频| 久久精品国产亚洲AV香蕉| 亚洲国产精品碰碰| 最新猫咪www免费人成| 亚洲国产成人AV网站| 亚洲精品国产啊女成拍色拍| 久久久久一级精品亚洲国产成人综合AV区 | 亚洲无线电影官网| 久久久久一级精品亚洲国产成人综合AV区 | 亚洲天然素人无码专区| 国产亚洲高清不卡在线观看| 免费真实播放国产乱子伦| 欧亚精品一区三区免费| 99视频在线精品免费| a级毛片免费完整视频| 免费激情网站国产高清第一页 | 99国产精品免费视频观看| 中文在线免费观看|