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

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

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

    隨筆 - 11, 文章 - 1, 評論 - 20, 引用 - 0
    數據加載中……

    小經驗兩則

    1.Oracle 8i 下使用最新的oracle thin driver時用DatabaseMetaData獲取主鍵等信息時,需要將
    connection.getMetaData().getPrimaryKeys(connection.getCatalog(),null,tableName);
    中的tableName轉為大寫,否則無法得到數據。

    2.正則表達式中,需要以","分割字符串,但是要分割的字串中含有","號,為了避免沖突,引入前置轉義字符"\",這樣的正則怎么寫呢?
    例如:
    String txt = "STATE_COUNTY=kj\\\\,,ADDR_LINE1=l=j,ADDR_LINE2=mj\n\n,ADDR_LINE3=n\\,o,\n\nADDR_LINE4=\np";
    需要把鍵值對切分出來:
    ?Pattern.compile("[^\\\\],)");
    這個是不行的,會將","號前一個字符消耗掉。

    ?Pattern.compile("(?![\\\\]),)");
    也不行
    Pattern?p?=?Pattern.compile,",(?![\\\\])");
    倒是可以,但是把轉義字符放后面似乎有點詭異。
    找了一個折衷辦法,不切割使用正則獲取"鍵=值"子串:
    Pattern?p?=?Pattern.compile("\\w+\\s*=.*?[,]*.*?(?=,|$)",Pattern.DOTALL);
    但是還是帶來了子串中不能含有"="的問題。
    最后查了一個JDK1.4 DOC,發現了一個反向的非匹配串寫法:
    Pattern?p?=?Pattern.compile("(?<!\\\\),\\s*");
    這樣一來就解決了以上問題。

    posted @ 2006-08-03 09:54 wolfsquare 閱讀(555) | 評論 (0)編輯 收藏

    回復 亂彈權限系統續一

    亂彈權限系統續一
    原文在這:http://www.tkk7.com/RongHao/archive/2006/07/03/56258.html

    仔細分析一,二,三,四權限背后的實質可以發現:
    一系統權限的概念有一些冗余,很難想象這樣一種情況:你已經有了子系統下的很多權限,結果因為沒有模塊權限而使得無法使用該模塊進行任何操作,分配權限的人要非常小心才行.這個世界已經夠復雜了,不要再給開發,部署人員增加復雜度了.很明白的,這個權限是不需要資源的權限
    二數據庫操作權限的概念,有一點疑惑,不知道為什么要建立這樣的一個概念,和行級權限有什么區別呢? 從你的上下文理解來看,似乎是這樣子的:有操作X表的業務,如果用戶有增加權限,則可以任意增加數據,如果用戶有編輯權限,則可以編輯任意數據.實際上對應標準權限模型為:不需要限定資源的操作,即不需要資源標識的權限.
    三行級數據權限,這個概念很直白,對應標準權限模型就是: 資源(行數據)+操作
    四列級數據權限,由于不是針對某特定行數據,所以它也是無資源型權限
    就這樣,所有的權限最終可劃為需要資源標識和不需要資源標識,換句話說,所有權限可劃分為控制某些集合的權限和控制單體的權限兩種,在某些時候,也稱之為 功能權限和數據權限


    談到把權限分給別人,很自然的就是如何控制權限的權限的問題了,很拗口,是吧?仔細想想,這樣很直觀,也沒有什么后遺癥,權限自遞歸控制和自解釋,真是一個完美的循環.
    有愛思考的同學想深了,會覺得非常麻煩,難實現.當然,概念上一回事,具體實現上可以是另一回事,可以做很多的變通來達到目的.只要保持概念上的簡單性,就足以使得非常多的人得以解脫了。

    另外,作為架構設計者,非常非常不贊成動輒就把很底層的概念扯進高層設計中(例如行級,數據庫什么的),很容易把自己和別人搞胡涂。
    可以最近狀態不好,要不好好blog一篇,8過,有句話怎么說來著:“都素那浮云而已。。。”

    posted @ 2006-07-04 22:45 wolfsquare 閱讀(1940) | 評論 (1)編輯 收藏

    不完美的世界-看到了IOC工具的又一個發展方向

         摘要: 在本篇文章中,作者在一個系統的構建中深度地被各種配置邏輯所困擾,由此發現了IOC工具(如Spring,Nuts等)的又一個發展方向。  閱讀全文

    posted @ 2006-06-08 00:30 wolfsquare 閱讀(1944) | 評論 (7)編輯 收藏

    結合WebWork實現高復用度系統的探索(上)

    需求: 某機構體系下,機構類型分為子公司,部門,人員等,以后可能在某機構或者其子孫機構下可能會再分出其他子機構類型,希望在增加新類型過程中,盡可能的避免修改已有代碼。

    情況:子公司,部分,人員等已完成所有編碼(界面,商業邏輯,數據邏輯)
    變化:需要把這個機構體系組成為一顆樹狀結構
    策略:鑒于除了樹結構外的其他部分代碼已經完成,那么應該首先保持這些代碼不予改動。復用修改的優先級從高到低的順序如下:
    ? 界面×JSP,Action層
    ? 商業邏輯 Service層
    ? 數據邏輯層
    ? 數據物理層
    有經驗的人知道,大部分情況下,越是下層的改動,越是影響越廣泛(注意不是修改難度),所以我們只有在無計可施的情況下,才進行低層的修改。

    分析: 回到我們的需求,從功能上看,維護一個組織機構的需求,已經涵蓋了每一個子結構的維護需求,以部門的建立為例,在新建一個部門時,同時也必須建立機構樹上的節點,
    ?這樣,如果需要直接使用原有的創建部門的所有代碼,需要在其上加上創建組織機構所需要的父節點,以及當前節點名稱信息(在這里department的增加界 面JSP是需要修改的,不過實際上我沒有修改該文件,而是利用DHTML來動態加入需要新增加的信息),然后提交給原創建部門的URI (departmentSave.action)和組織機構創建URI(orgCreate.action),在這里我們利用ww提供的action chain功能來完成這兩個操作。
    ?這里需要修改department.action的配置,攔截save方法使其執行完后跳過原來的relist結果頁面轉向組織結構的創建orgCreate.action:
    ?<action name="unitSave" class="com.wolfsquare.ibase.org.action.UnitAction" method="save">
    ?? <result name="input">/org/unit/input.jsp</result>
    ?? <result name="relist" type="chain">
    ?????? <param name="actionName">orgCreate</param>
    ??????????????? <param name="namespace">/org</param>??
    ??????????? </result>
    ?? <result name="xxx" type="redirect">/org/unit.action?start=${start}</result>
    ?? <interceptor-ref name="validationStack"/>
    ? </action>
    可能有同學看到這里會問:創建組織節點時應該還需要關聯前面創建的部門對象啊,這個操作是如何實現的?信息是如何傳遞的?
    在這里,由于整個架構體系并沒有支持這種信息傳遞的功能,所以只好以一種比較”臟“的方式實現:
    ??????? 在department.action類里增加了一個方法getModel()返回剛剛創建的部門對象,然后在org.action類中增加一個接收的方法setModel(object o)這樣在整action chain執行的時候,ww會自動將getModel后的數據填入setModel中,這樣做的后果是以后增加新的機構類型的功能時,action必須也照這樣的語意設置getModel方法。(如果要解決這個問題,這能需要使用一個特定的Context,然后攔截指定Service的創建方法,把創建結果放入Context,不過這又帶來如何清除Context的問題,于是又要求助與ww的interspector,專門寫一個攔截器來擦屁股,夠麻煩。。。)

    ??????? 就這樣,我們完成了新增,修改組織機構的功能合成,雖然有點拖沓,但是還是達到了復用,少修改原有代碼,而且擴展性也很好的目標。這上篇說的是兩個簡單業務的功能揉合問題,下篇我們來看看稍微復雜點的情況,看看還能不能繼續依葫蘆畫瓢來完成功能合的成
    ??
    (未完待續)??

    posted @ 2006-05-17 23:40 wolfsquare 閱讀(1223) | 評論 (0)編輯 收藏

    log4j配置簡要說明

    雖然以前一直在用log4j,但是對其配置不甚了了,突然間因為需解決某些問題,要理解log4j的配置,
    然而用google搜了一下,卻發現網上沒有一個簡單直觀的說明,于是只好看log4j的官方介紹,終于
    理解了log4j的配置用法,以下是我對log4j配置的一點認識,如有謬誤還請不吝賜教.

    首先我們搞清楚log4j能干什么,簡單來說就是提供一個記錄不同級別信息內容的日志工具,
    可以把不同級別,不同包路徑的信息,以指定格式輸出到多種設備(控制臺,文件等)
    在程序中,可以以以下方式來使用
    ?? Log log = org.apache.commons.logging.LogFactory.LogFactory.getLog(yourClassName.class);
    ??log.debug("debug message -------------------");
    ??log.info("info message ******************");
    ??log.warn("warn message +++++++++++++++");
    ??log.error("error msg=================");
    ??
    本文主要講的是如何配置log4j,先讓我們先看看一個典型的log4j配置:??

    ==========log4j.properties==================

    log4j.appender.stdout=org.apache.log4j.ConsoleAppender
    log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
    log4j.appender.stdout.layout.ConversionPattern=%d{MM-dd HH\:mm\:ss.SSS} %-5p [%F\:%L]%x %m%n

    log4j.appender.fileout=org.apache.log4j.RollingFileAppender
    log4j.appender.fileout.File=D:/workspace/log4jtest/log/application.log
    log4j.appender.fileout.MaxFileSize=10000KB
    log4j.appender.fileout.MaxBackupIndex=10
    log4j.appender.fileout.layout=org.apache.log4j.PatternLayout
    log4j.appender.fileout.layout.ConversionPattern=%d{MM-dd HH:mm:ss.SSS}[%24F:%-3L:%-5p]%x %m%n

    log4j.rootCategory=INFO, stdout, fileout
    log4j.logger.com.wolfsquare.log2=DEBUG,stdout
    ===================================

    這個文件可以劃為三小塊

    ===========第一塊定義了一個名為 stdout 的appender和layout (appender,layout的概念后面再解釋,目前先記著有這樣兩個名詞):

    log4j.appender.stdout=org.apache.log4j.ConsoleAppender
    定義stdout的實際輸出實現類,從這個appender實現類名可以猜到,這個類是負責控制臺輸出的。
    log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
    定義stdout的輸出裝飾器
    log4j.appender.stdout.layout.ConversionPattern=%d{MM-dd HH\:mm\:ss.SSS} %-5p [%F\:%L]%x %m%n
    裝飾器參數配置


    ============第二塊定義了一個名為 fileout 的appender和layout:
    log4j.appender.fileout=org.apache.log4j.RollingFileAppender
    同理可猜這個實現類是輸出到文件的
    log4j.appender.fileout.File=D:/workspace/log4jtest/log/application.log
    log4j.appender.fileout.MaxFileSize=10000KB
    log4j.appender.fileout.MaxBackupIndex=10
    log4j.appender.fileout.layout=org.apache.log4j.PatternLayout
    log4j.appender.fileout.layout.ConversionPattern=%d{MM-dd HH:mm:ss.SSS}[%24F:%-3L:%-5p]%x %m%n

    ============第三塊定義了名字分別為rootCategory,log4j.logger.com.wolfsquare.log2的兩個logger
    log4j.rootCategory=INFO, stdout, fileout
    log4j.logger.com.wolfsquare.log2=DEBUG,stdout

    rootCategory logger是缺省的logger,記錄所有的包的信息輸出。
    第二個logger是只輸出指定包com.wolfsquare.log2下的日志信息。
    那么INFO,DEBUG又是什么意思呢,他們是信息的分級標識,通過繼承實現這個實現自定義級別的分級。
    第三塊配置兩句的意思是這樣的:
    rootCategory 把所有類的INFO級別以上的信息輸出到stdout和fileout兩個appender中,
    logger.com.wolfsquare.log2,把com.wolfsquare.log2包中的所有類(包括子包)DEBUG級別(含)以上的信息輸出到stdout 中
    一個logger可以輸出到很多個設備中(appender),如果需要增加輸出設備則用分號分隔開appender名稱即可。

    輸出信息的分類級別是DEBUG > INFO > WARN > ERROR,信息細節由細到粗,指定輸出某一級別的信息時,
    過細的信息輸出將會被忽略

    如果一個配置中有多個logger,他們之間會有什么關系呢?答案是,在輸出上,他們沒有任何關系,都是獨立運作的,
    不相關的,但是在配置上,父包的配置會傳給子包,如果子包沒有另外定義配置的話。
    例如上面配置文件中的兩個logger:
    log4j.logger.com.wolfsquare
    log4j.logger.com.wolfsquare.log2

    這里認為 log4j.logger.com.wolfsquare.log2 繼承自 log4j.logger.com.wolfsquare,他們的配置聲明如下:
    log4j.rootCategory=INFO, stdout, fileout
    log4j.logger.com.wolfsquare.log2=,stdout
    注意第二句沒有指定輸出級別,那么根據配置繼承規則會繼承父logger的配置,在這里就是INFO。

    同時需要強調的是,如果兩個logger有繼承關系,且輸出到同一個appender,根據輸出獨立原則,那么將會出現兩行一樣的信息,
    例如上面的兩個logger定義會導致這樣的情況。
    最后以一幅圖來概括:

    posted @ 2006-04-20 23:21 wolfsquare 閱讀(982) | 評論 (0)編輯 收藏

    spring配置中bean的循環引用問題及解決方法

    問題:Spring+Hibernate的應用中,定義了兩個業務Service,這里分別稱它們為serivceA,ServiceB。
    它們的關系簡單點來說是這樣的:
    serviceA需要引用serviceB,在serviceB中定義了一個接口列表,serverA必須在serviceB初始化時設置進列表。
    在純bean的情況下,也就是這兩個類不需要設置其他bean的情況下,循環引用是正常的,可以通過的。例如下面配置所表示:

        <bean id="serviceA" class="A"  autowire="byName"  lazy-init="true">
         <property name="serviceB"><ref local="serviceB"/></property>
        </bean>
     <bean id="serviceB" class="B"  autowire="byName"  lazy-init="true">
         <property name="serviceA"><ref bean="serviceA"/></property>
     </bean>
    但是作為一個業務接口,它應該是不需要關心事務,回滾這些無關的東西,
    但現實又有這樣的需求,所以我們必須保證透明的實現這個功能,于是引
    入了AOP方式解決該問題,利用的是Spring自帶的org.springframework.t
    ransaction.interceptor.TransactionProxyFactoryBean.
    重新聲明文件如下:
       <bean id="baseTxProxy" lazy-init="true"
          class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
            <property name="proxyTargetClass"><value>true</value></property>
            <property name="transactionAttributes">
                <props>
      <prop key="*">PROPAGATION_REQUIRED</prop>
                </props>
            </property>
        </bean>
         
        <bean id="serviceA" parent="baseTxProxy">
         <property name="target"><ref local="serviceAImpl"/></property>
        </bean>
       
       <bean id="serviceAImpl" class="serviceA"  autowire="byName"  lazy-init="true">
         <property name="serviceB">
             <ref bean="serviceB"/>
         </property>
       </bean>
       
        <bean id="serviceB" parent="baseTxProxy" lazy-init="true">
         <property name="target"><ref local="serviceBImpl"/></property>
        </bean>
      
       <bean id="serviceBImpl" class="D" lazy-init="true">
         <property name="serviceA">
             <ref bean="serviceA"/>
         </property>
       </bean>
    于是問題就出現了,Spring報了FactoryBeanCircularReferenceException,無法繼續完成設置工作。
    查看TransactionProxyFactoryBean源碼,其實現了FactoryBean和InitializingBean接口,應該是
    做了代理之后,兩個代理Bean需要等待所有Bean設置完成后才會標識狀態為初始化完畢,于是造成了
    沖突。

        由于兩個業務服務互相調用的路徑是不相交的,所以采用了一種變通的方法,在聲明serviceA時,
    直接定義serviceB:
      <bean id="serviceAImpl" class="serviceA"  autowire="byName"  lazy-init="true">
         <property name="serviceB">
             <bean class="B"  autowire="byName"/>
         </property>
     </bean>
    相當于serviceB和serviceA中使用的serviceB不是同一個實例。
     
     但是如果確實調用重合時怎么辦?
     
     解決方法是這樣的:
     
     <bean id="serviceAImpl" class="serviceA"  autowire="byName"  lazy-init="true">
         <property name="serviceB">
             <ref bean="serviceBImpl"/>
         </property>
     </bean>
     
      非常簡單,serviceAImpl調用時,可能已經在事務環境中了,不需再使用serviceB代理的事務支持,
      于是直接引用serviceB實例。這個方法是我寫這篇文章時想到的,-_-!!!,看來知識果真還是好好
      整理呀。

     

    posted @ 2006-02-07 08:53 wolfsquare 閱讀(2572) | 評論 (0)編輯 收藏

    Spring+Hibernate+Websphere5.0經驗一則

    環境Spring1.1.3,Hibernate 2.1.8, Websphere5.01

    hbm文件采用通配符獲取:


      
      
       classpath:/**/*.hbm.xml
      

      
     

    問題癥狀:

    應用啟動報錯說不能重復定義某類,去掉該類后仍然報下一個類重復定義。

    仔細查看Log輸出發現,所有的hbm文件均找到了兩份 -_-!!!

    項目組認為應該是websphere不太厚道,在classpath中使用了多處目錄(web-inf & classes),并以這些目錄為根進行遞歸搜索匹配文件,可是如果這些目錄有包含關系,WebSphere就沒有處理重復查找的文件了。

    于是在以上配置中改為:


      
      
       classpath:/classes/**/*.hbm.xml
      

      
     

    問題雖然解決了,可是tomcat中卻又無效了。 :(

    什么時候,企業應用才能一次拷貝,到處運行啊~~

    posted @ 2006-02-07 08:50 wolfsquare 閱讀(651) | 評論 (0)編輯 收藏

    修改Tds驅動Url聲明解決兩個Sql Server問題

    問題1:JDBC Sql Server varchar的取出最大長度限制

    環境: JDBC驅動inet tds驅動(版本不明),SQLServer2K

    問題癥狀:對于數據庫聲明為varchar的長度大于256的字段,可以正常保存,但是無法取出多于256字符以后的內容

    問題2:使用Hibernate映射時0長度字符串保存后,取出多加了一個空格

    環境:inet tds驅動Hibernate2.1.8,SQL Server2K

    問題癥狀:保存0長度字符串后,取出增加了多余的空格。

    以上兩個問題都是因為沒有使用最新的通訊協議引起的,修改URL聲明方式如下:

    jdbc:inetdae7:127.0.0.1:1433?database=xxx

    問題解決,收工。

    ps:發現協議inetdae時,數據庫字段為Null時,Hibernate取出聲明為基本類型(例如boolean)的對象屬性并不會報錯,實際上在其他數據庫如Oracle和新協議上是會報錯的。為了避免此類問題出現,最好還是嚴格遵守:Hibernate聲明對象的基本類型屬性,一定不能在數據庫端置為空值。

    ps2:在解決以上問題中發現,Oracle居然對傳人0長度字符串,會轉為空值,不知道是為了節省空間還是別的什么理由。-_-!!!

    全文完

    posted @ 2006-02-07 08:49 wolfsquare 閱讀(552) | 評論 (0)編輯 收藏

    Java高精度打印

        在Java環境中,可以使用 java.awt.Toolkit.getScreenResolution()可以得到屏幕每英寸的象素數,但是好像沒有什么方法能知道某一臺打印機的分辨率,更別提去控制打印粒度了。于是可恥的使用著丑陋的缺省打印精度幾年后,終于找到了解決方法,不知道該高興還是悲傷,其原理說出來也是非常的簡單:
        提高打印精度,其實就是把本來是A3紙的內容往A4紙里畫,也就是說,打印區域(這里對應著Java里的Graphics對象)需要縮小,然后由于缺省情況下打印是照72DPI來打的,不做改變的話,打印內容也會跟著變小。這樣就不是我們想要的效果了,所以還得把打印內容成比例放大。一個縮小,一個放大,于是畫完后,在指定大小的紙張內,便容納了比以往更多象素的內容,這下世界總算完美了。

        以上做法形象的說應該是這樣:把需要產生的圖形對象先放大,畫在一張“紙上”,然后整體縮小,這樣精度就提高了。

        tips 1:在一般企業報表表格打印中,使用144DPI得到的表格線的寬度看起來最舒服。
        tips 2:現在號稱600DPI的打印機其實是576DPI,如果想使用這個分辨率的精度,需要用好一點的紙張,因為已經到極限了,紙張稍差點,打印墨粉就沾不上,導致線體殘缺。

    附源碼(修改分辨率就改動變量iResMul就好):

     

    import java.awt.*;
    import java.awt.print.*;

    public class MyPrintableObject implements Printable {
     
    public int iResMul = 1// 1 = 72 dpi; 4 = 288 dpi

     
    public int print(Graphics g, PageFormat pf, int iPage)
       
    throws PrinterException {
      
    final int FONTSIZE = 12;
      
    final double PNT_MM = 25.4 / 72.;
      
    if (0 != iPage)
       
    return NO_SUCH_PAGE;
      
    try {
       
    int iPosX = 1;
       
    int iPosY = 1;
       
    int iAddY = FONTSIZE * 3 / 2 * iResMul;
       
    int iWdth = (int) Math.round(pf.getImageableWidth() * iResMul) - 3;
       
    int iHght = (int) Math.round(pf.getImageableHeight() * iResMul) - 3;
       
    int iCrcl = Math.min(iWdth, iHght) - 4 * iResMul;
       Graphics2D g2 
    = (Graphics2D) g;
       PrinterJob prjob 
    = ((PrinterGraphics) g2).getPrinterJob();
       g2.translate(pf.getImageableX(), pf.getImageableY());
       g2.scale(
    1.0 / iResMul, 1.0 / iResMul);
       g2.setFont(
    new Font("SansSerif", Font.PLAIN, FONTSIZE * iResMul));
       g2.setColor(Color.black);
       g2.drawRect(iPosX, iPosY, iWdth, iHght);
       g2.drawLine(iPosX, iHght 
    / 2 + iWdth / 50, iPosX + iWdth, iHght / 2
         
    - iWdth / 50);
       g2.drawLine(iPosX, iHght 
    / 2 - iWdth / 50, iPosX + iWdth, iHght / 2
         
    + iWdth / 50);
       g2.drawOval(iPosX 
    + 2 * iResMul, iHght - iCrcl - 2 * iResMul,
         iCrcl, iCrcl);
       iPosX 
    += iAddY;
       iPosY 
    += iAddY / 2;
       g2.drawString(
    "PrinterJob-UserName: " + prjob.getUserName(), iPosX,
         iPosY 
    += iAddY);
       g2.drawString(
    "Betriebssystem: " + System.getProperty("os.name")
         
    + " " + System.getProperty("os.version"), iPosX,
         iPosY 
    += iAddY);
       g2
         .drawString(
    "Java-Version: JDK "
           
    + System.getProperty("java.version"), iPosX,
           iPosY 
    += iAddY);
       g2.drawString(
    "Width/Height: " + dbldgt(pf.getWidth()) + " / "
         
    + dbldgt(pf.getHeight()) + " points = "
         
    + dbldgt(pf.getWidth() * PNT_MM) + " / "
         
    + dbldgt(pf.getHeight() * PNT_MM) + " mm", iPosX,
         iPosY 
    += iAddY);
       g2.drawString(
    "Imageable Width/Height: "
         
    + dbldgt(pf.getImageableWidth()) + " / "
         
    + dbldgt(pf.getImageableHeight()) + " points = "
         
    + dbldgt(pf.getImageableWidth() * PNT_MM) + " / "
         
    + dbldgt(pf.getImageableHeight() * PNT_MM) + " mm", iPosX,
         iPosY 
    += iAddY);
       g2.drawString(
    "Imageable X/Y: " + dbldgt(pf.getImageableX())
         
    + " / " + dbldgt(pf.getImageableY()) + " points = "
         
    + dbldgt(pf.getImageableX() * PNT_MM) + " / "
         
    + dbldgt(pf.getImageableY() * PNT_MM) + " mm", iPosX,
         iPosY 
    += iAddY);
       g2.drawString(
    "versuchte Druckaufl sung: " + 72 * iResMul + " dpi",
         iPosX, iPosY 
    += iAddY);
      }
     catch (Exception ex) {
       
    throw new PrinterException(ex.getMessage());
      }

      
    return PAGE_EXISTS;
     }


     
    private static double dbldgt(double d) {
      
    return Math.round(d * 10.) / 10.; // show one digit after point
     }


     
    public static void main(String[] args) {
      PrinterJob pj 
    = PrinterJob.getPrinterJob();
      pj.setPrintable(
    new MyPrintableObject());
      
    if (pj.printDialog()) {
       
    try {
        pj.print();
       }
     catch (PrinterException e) {
        System.out.println(e);
       }

      }

     }

    }



    全文完)   

    posted @ 2006-02-06 21:44 wolfsquare 閱讀(1720) | 評論 (2)編輯 收藏

    基于攔截器的企業應用構造

        在上一篇文章里,我們使用了基于事件傳遞的機制來對企業應用的子系統進行解耦,但是由于需要強制地繼承或者實現一個廣播事件的接口EventBrocast,實際上,就職責分離和功能單一的角度來看,前篇文章中的例子中,這個機制對OrderService侵入太大了,我們必須尋找更為有效的方法,不需要程序實現某個接口或繼承某個超類來完成這個工作,這一切必須對具體程序完全透明,這個責任誰能承擔呢,毫無疑問,歷史的重擔就落在了AOP身上 ;) 。下面我們來看看具體的實現:
        OrderService已經實現,除了訂單的處理,沒有任何的職責,為了完成事件的廣播,必須要有一個途徑能夠攔截到OrderService的所有方法調用,然后分析調用的語義(參數),并根據這些內容給廣播出去。而恰好,AOP組織統一的接口MethodInterceptor可以完成這個功能。于是上篇文章的程序可以這樣修改:

       // 訂單服務只負責做好自己的事
      

     public class OrderService {
         
    public Order saveOrder(Order order){
         。。。。處理訂單
         。。。保存
         }
      }

     

      而為了攔截任何的方法調用,則實現了攔截器EventBrocaster:
     

    public class EventBrocaster extends LifeEventBrocast implements MethodInterceptor  {
        
    private List eventListeners;
        
    public void setEventListener(List list){
         
    this.eventListeners=list;
        }
        
    public List geteEventListeners(){
         
    return eventListeners;
        }
        
    public Object invoke(MethodInvocation invoke) {
          obj 
    = invoke.proceed();// 執行被攔截的方法完成業務操作
          Object[] params = invoke.getArguments();
         Object param 
    = params.length > 1 ? params : params[0];
         Event le 
    = new Event(param, eventType);
         brocast(le);
    // 廣播
        }
      }

     

      事件偵聽器:
     

     public OrderEventListener implements EventListener{
      
    private FinancialService  financialService;
       
    public void setFinancialService(FinancialService fs){
         
    this.financialService=fs;
       }
      
    public void performed(Event e){
       Order order 
    =(Order) e.getObject();
        financialService.createRequestOfMoney(order.getAmount());
      }
     }

     


      然后,在Spring配置里將這些組件全部連接起來:

     1.OrderService實現:
     <bean id="orderServiceImpl" class="OrderService" autowire="byName">
     </bean>

     2. 聲明OrderService代理:

     <bean id="orderService" class="org.springframework.aop.framework.ProxyFactoryBean">
      <property name="target">
       <ref local="orderServiceImpl"/>
      </property>
      <property name="interceptorNames"> <!--攔截器列表-->
       <list>
        <value>eventBrocaster</value>
       </list>
      </property>
      <property name="singleton">
       <value>true</value>
      </property>
     </bean>
      3.事件廣播攔截器
     <bean id="eventBrocaster" class="com.wolfsquare.core.service.EventBrocaster" singleton="true">
      <property name="lifecycleListeners">
          <list>
           <ref bean="orderEventListener"/>
          </list>
         </property>
     </bean>
      4.具體的財務子系統的偵聽器實現與財務系統的通訊:
      <bean id="orderEventListener" class="OrderEventListener" autowire="byName">
       <propety name="financialService"><ref bean="financialService"/></property>
     </bean>

        這樣,我們與具體實現無關的事件廣播就做到了,聰明的朋友看到這里,肯定想到了攔截器方式不僅僅適用與事件廣播,還可以實現事務的統一管理,事實上Spring的事務管理就是這樣完成的,還可以實現權限的控制例如Acegi,簡直有點象萬能的膠水,呵呵。

        從兩篇文章的逐步探討下,同一個機器,同一個虛擬機之內的數據通訊都可以實現了,那么異構系統和多虛擬機間的通訊又如何處理呢,于是ESB(企業服務總線)的概念就慢慢浮現出來了,不過這個不在本文探討的范疇了,也許在不久的將來,我會補上這一篇。

    (全文完)

     

     

    posted @ 2005-12-06 20:49 wolfsquare 閱讀(2821) | 評論 (6)編輯 收藏

    僅列出標題
    共2頁: 1 2 下一頁 
    主站蜘蛛池模板: 男女午夜24式免费视频| 一本一道dvd在线观看免费视频 | 亚洲国产精品无码专区| 日韩毛片免费一二三| 亚洲男人的天堂一区二区| 特级毛片全部免费播放| 亚洲精品岛国片在线观看| 国产伦精品一区二区免费| 亚洲一区二区三区免费| 成人免费av一区二区三区| 亚洲五月综合缴情在线观看| 二个人看的www免费视频| 亚洲国产精品无码久久一线 | 国产免费A∨在线播放| 综合亚洲伊人午夜网 | 亚洲人成色7777在线观看不卡| 一区二区三区AV高清免费波多| 久久久久亚洲AV成人网人人软件 | 精品免费久久久久国产一区| 亚洲国产精品一区二区久久hs| 免费无码成人AV在线播放不卡| 亚洲国产综合人成综合网站00| 大地资源二在线观看免费高清 | 亚洲av无码成h人动漫无遮挡| 免费国产黄网站在线观看可以下载| 亚洲无限乱码一二三四区| 天天摸夜夜摸成人免费视频| 国产成人亚洲精品无码AV大片| 久久亚洲AV无码精品色午夜麻| 一个人免费日韩不卡视频| 亚洲中文久久精品无码1| 日韩免费毛片视频| 51午夜精品免费视频| 亚洲无线电影官网| 在线观看免费大黄网站| A国产一区二区免费入口| 亚洲人成电影院在线观看| 国产精品免费看香蕉| 日本免费电影一区二区| 亚洲精品无码专区| 久久精品亚洲日本佐佐木明希|