隨筆 - 11, 文章 - 1, 評(píng)論 - 20, 引用 - 0
          數(shù)據(jù)加載中……

          小經(jīng)驗(yàn)兩則

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

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

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

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

          回復(fù) 亂彈權(quán)限系統(tǒng)續(xù)一

          亂彈權(quán)限系統(tǒng)續(xù)一
          原文在這:http://www.aygfsteel.com/RongHao/archive/2006/07/03/56258.html

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


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

          另外,作為架構(gòu)設(shè)計(jì)者,非常非常不贊成動(dòng)輒就把很底層的概念扯進(jìn)高層設(shè)計(jì)中(例如行級(jí),數(shù)據(jù)庫(kù)什么的),很容易把自己和別人搞胡涂。
          可以最近狀態(tài)不好,要不好好blog一篇,8過(guò),有句話怎么說(shuō)來(lái)著:“都素那浮云而已。。。”

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

          不完美的世界-看到了IOC工具的又一個(gè)發(fā)展方向

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

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

          結(jié)合WebWork實(shí)現(xiàn)高復(fù)用度系統(tǒng)的探索(上)

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

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

          分析: 回到我們的需求,從功能上看,維護(hù)一個(gè)組織機(jī)構(gòu)的需求,已經(jīng)涵蓋了每一個(gè)子結(jié)構(gòu)的維護(hù)需求,以部門的建立為例,在新建一個(gè)部門時(shí),同時(shí)也必須建立機(jī)構(gòu)樹上的節(jié)點(diǎn),
          ?這樣,如果需要直接使用原有的創(chuàng)建部門的所有代碼,需要在其上加上創(chuàng)建組織機(jī)構(gòu)所需要的父節(jié)點(diǎn),以及當(dāng)前節(jié)點(diǎn)名稱信息(在這里department的增加界 面JSP是需要修改的,不過(guò)實(shí)際上我沒(méi)有修改該文件,而是利用DHTML來(lái)動(dòng)態(tài)加入需要新增加的信息),然后提交給原創(chuàng)建部門的URI (departmentSave.action)和組織機(jī)構(gòu)創(chuàng)建URI(orgCreate.action),在這里我們利用ww提供的action chain功能來(lái)完成這兩個(gè)操作。
          ?這里需要修改department.action的配置,攔截save方法使其執(zhí)行完后跳過(guò)原來(lái)的relist結(jié)果頁(yè)面轉(zhuǎn)向組織結(jié)構(gòu)的創(chuàng)建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>
          可能有同學(xué)看到這里會(huì)問(wèn):創(chuàng)建組織節(jié)點(diǎn)時(shí)應(yīng)該還需要關(guān)聯(lián)前面創(chuàng)建的部門對(duì)象啊,這個(gè)操作是如何實(shí)現(xiàn)的?信息是如何傳遞的?
          在這里,由于整個(gè)架構(gòu)體系并沒(méi)有支持這種信息傳遞的功能,所以只好以一種比較”臟“的方式實(shí)現(xiàn):
          ??????? 在department.action類里增加了一個(gè)方法getModel()返回剛剛創(chuàng)建的部門對(duì)象,然后在org.action類中增加一個(gè)接收的方法setModel(object o)這樣在整action chain執(zhí)行的時(shí)候,ww會(huì)自動(dòng)將getModel后的數(shù)據(jù)填入setModel中,這樣做的后果是以后增加新的機(jī)構(gòu)類型的功能時(shí),action必須也照這樣的語(yǔ)意設(shè)置getModel方法。(如果要解決這個(gè)問(wèn)題,這能需要使用一個(gè)特定的Context,然后攔截指定Service的創(chuàng)建方法,把創(chuàng)建結(jié)果放入Context,不過(guò)這又帶來(lái)如何清除Context的問(wèn)題,于是又要求助與ww的interspector,專門寫一個(gè)攔截器來(lái)擦屁股,夠麻煩。。。)

          ??????? 就這樣,我們完成了新增,修改組織機(jī)構(gòu)的功能合成,雖然有點(diǎn)拖沓,但是還是達(dá)到了復(fù)用,少修改原有代碼,而且擴(kuò)展性也很好的目標(biāo)。這上篇說(shuō)的是兩個(gè)簡(jiǎn)單業(yè)務(wù)的功能揉合問(wèn)題,下篇我們來(lái)看看稍微復(fù)雜點(diǎn)的情況,看看還能不能繼續(xù)依葫蘆畫瓢來(lái)完成功能合的成
          ??
          (未完待續(xù))??

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

          log4j配置簡(jiǎn)要說(shuō)明

          雖然以前一直在用log4j,但是對(duì)其配置不甚了了,突然間因?yàn)樾杞鉀Q某些問(wèn)題,要理解log4j的配置,
          然而用google搜了一下,卻發(fā)現(xiàn)網(wǎng)上沒(méi)有一個(gè)簡(jiǎn)單直觀的說(shuō)明,于是只好看log4j的官方介紹,終于
          理解了log4j的配置用法,以下是我對(duì)log4j配置的一點(diǎn)認(rèn)識(shí),如有謬誤還請(qǐng)不吝賜教.

          首先我們搞清楚log4j能干什么,簡(jiǎn)單來(lái)說(shuō)就是提供一個(gè)記錄不同級(jí)別信息內(nèi)容的日志工具,
          可以把不同級(jí)別,不同包路徑的信息,以指定格式輸出到多種設(shè)備(控制臺(tái),文件等)
          在程序中,可以以以下方式來(lái)使用
          ?? 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,先讓我們先看看一個(gè)典型的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
          ===================================

          這個(gè)文件可以劃為三小塊

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

          log4j.appender.stdout=org.apache.log4j.ConsoleAppender
          定義stdout的實(shí)際輸出實(shí)現(xiàn)類,從這個(gè)appender實(shí)現(xiàn)類名可以猜到,這個(gè)類是負(fù)責(zé)控制臺(tái)輸出的。
          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
          裝飾器參數(shù)配置


          ============第二塊定義了一個(gè)名為 fileout 的appender和layout:
          log4j.appender.fileout=org.apache.log4j.RollingFileAppender
          同理可猜這個(gè)實(shí)現(xiàn)類是輸出到文件的
          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的兩個(gè)logger
          log4j.rootCategory=INFO, stdout, fileout
          log4j.logger.com.wolfsquare.log2=DEBUG,stdout

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

          輸出信息的分類級(jí)別是DEBUG > INFO > WARN > ERROR,信息細(xì)節(jié)由細(xì)到粗,指定輸出某一級(jí)別的信息時(shí),
          過(guò)細(xì)的信息輸出將會(huì)被忽略

          如果一個(gè)配置中有多個(gè)logger,他們之間會(huì)有什么關(guān)系呢?答案是,在輸出上,他們沒(méi)有任何關(guān)系,都是獨(dú)立運(yùn)作的,
          不相關(guān)的,但是在配置上,父包的配置會(huì)傳給子包,如果子包沒(méi)有另外定義配置的話。
          例如上面配置文件中的兩個(gè)logger:
          log4j.logger.com.wolfsquare
          log4j.logger.com.wolfsquare.log2

          這里認(rèn)為 log4j.logger.com.wolfsquare.log2 繼承自 log4j.logger.com.wolfsquare,他們的配置聲明如下:
          log4j.rootCategory=INFO, stdout, fileout
          log4j.logger.com.wolfsquare.log2=,stdout
          注意第二句沒(méi)有指定輸出級(jí)別,那么根據(jù)配置繼承規(guī)則會(huì)繼承父logger的配置,在這里就是INFO。

          同時(shí)需要強(qiáng)調(diào)的是,如果兩個(gè)logger有繼承關(guān)系,且輸出到同一個(gè)appender,根據(jù)輸出獨(dú)立原則,那么將會(huì)出現(xiàn)兩行一樣的信息,
          例如上面的兩個(gè)logger定義會(huì)導(dǎo)致這樣的情況。
          最后以一幅圖來(lái)概括:

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

          spring配置中bean的循環(huán)引用問(wèn)題及解決方法

          問(wèn)題:Spring+Hibernate的應(yīng)用中,定義了兩個(gè)業(yè)務(wù)Service,這里分別稱它們?yōu)閟erivceA,ServiceB。
          它們的關(guān)系簡(jiǎn)單點(diǎn)來(lái)說(shuō)是這樣的:
          serviceA需要引用serviceB,在serviceB中定義了一個(gè)接口列表,serverA必須在serviceB初始化時(shí)設(shè)置進(jìn)列表。
          在純bean的情況下,也就是這兩個(gè)類不需要設(shè)置其他bean的情況下,循環(huán)引用是正常的,可以通過(guò)的。例如下面配置所表示:

              <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>
          但是作為一個(gè)業(yè)務(wù)接口,它應(yīng)該是不需要關(guān)心事務(wù),回滾這些無(wú)關(guān)的東西,
          但現(xiàn)實(shí)又有這樣的需求,所以我們必須保證透明的實(shí)現(xiàn)這個(gè)功能,于是引
          入了AOP方式解決該問(wèn)題,利用的是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>
          于是問(wèn)題就出現(xiàn)了,Spring報(bào)了FactoryBeanCircularReferenceException,無(wú)法繼續(xù)完成設(shè)置工作。
          查看TransactionProxyFactoryBean源碼,其實(shí)現(xiàn)了FactoryBean和InitializingBean接口,應(yīng)該是
          做了代理之后,兩個(gè)代理Bean需要等待所有Bean設(shè)置完成后才會(huì)標(biāo)識(shí)狀態(tài)為初始化完畢,于是造成了
          沖突。

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

           

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

          Spring+Hibernate+Websphere5.0經(jīng)驗(yàn)一則

          環(huán)境Spring1.1.3,Hibernate 2.1.8, Websphere5.01

          hbm文件采用通配符獲取:


            
            
             classpath:/**/*.hbm.xml
            

            
           

          問(wèn)題癥狀:

          應(yīng)用啟動(dòng)報(bào)錯(cuò)說(shuō)不能重復(fù)定義某類,去掉該類后仍然報(bào)下一個(gè)類重復(fù)定義。

          仔細(xì)查看Log輸出發(fā)現(xiàn),所有的hbm文件均找到了兩份 -_-!!!

          項(xiàng)目組認(rèn)為應(yīng)該是websphere不太厚道,在classpath中使用了多處目錄(web-inf & classes),并以這些目錄為根進(jìn)行遞歸搜索匹配文件,可是如果這些目錄有包含關(guān)系,WebSphere就沒(méi)有處理重復(fù)查找的文件了。

          于是在以上配置中改為:


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

            
           

          問(wèn)題雖然解決了,可是tomcat中卻又無(wú)效了。 :(

          什么時(shí)候,企業(yè)應(yīng)用才能一次拷貝,到處運(yùn)行啊~~

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

          修改Tds驅(qū)動(dòng)Url聲明解決兩個(gè)Sql Server問(wèn)題

          問(wèn)題1:JDBC Sql Server varchar的取出最大長(zhǎng)度限制

          環(huán)境: JDBC驅(qū)動(dòng)inet tds驅(qū)動(dòng)(版本不明),SQLServer2K

          問(wèn)題癥狀:對(duì)于數(shù)據(jù)庫(kù)聲明為varchar的長(zhǎng)度大于256的字段,可以正常保存,但是無(wú)法取出多于256字符以后的內(nèi)容

          問(wèn)題2:使用Hibernate映射時(shí)0長(zhǎng)度字符串保存后,取出多加了一個(gè)空格

          環(huán)境:inet tds驅(qū)動(dòng)Hibernate2.1.8,SQL Server2K

          問(wèn)題癥狀:保存0長(zhǎng)度字符串后,取出增加了多余的空格。

          以上兩個(gè)問(wèn)題都是因?yàn)闆](méi)有使用最新的通訊協(xié)議引起的,修改URL聲明方式如下:

          jdbc:inetdae7:127.0.0.1:1433?database=xxx

          問(wèn)題解決,收工。

          ps:發(fā)現(xiàn)協(xié)議inetdae時(shí),數(shù)據(jù)庫(kù)字段為Null時(shí),Hibernate取出聲明為基本類型(例如boolean)的對(duì)象屬性并不會(huì)報(bào)錯(cuò),實(shí)際上在其他數(shù)據(jù)庫(kù)如Oracle和新協(xié)議上是會(huì)報(bào)錯(cuò)的。為了避免此類問(wèn)題出現(xiàn),最好還是嚴(yán)格遵守:Hibernate聲明對(duì)象的基本類型屬性,一定不能在數(shù)據(jù)庫(kù)端置為空值。

          ps2:在解決以上問(wèn)題中發(fā)現(xiàn),Oracle居然對(duì)傳人0長(zhǎng)度字符串,會(huì)轉(zhuǎn)為空值,不知道是為了節(jié)省空間還是別的什么理由。-_-!!!

          全文完

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

          Java高精度打印

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

              以上做法形象的說(shuō)應(yīng)該是這樣:把需要產(chǎn)生的圖形對(duì)象先放大,畫在一張“紙上”,然后整體縮小,這樣精度就提高了。

              tips 1:在一般企業(yè)報(bào)表表格打印中,使用144DPI得到的表格線的寬度看起來(lái)最舒服。
              tips 2:現(xiàn)在號(hào)稱600DPI的打印機(jī)其實(shí)是576DPI,如果想使用這個(gè)分辨率的精度,需要用好一點(diǎn)的紙張,因?yàn)橐呀?jīng)到極限了,紙張稍差點(diǎn),打印墨粉就沾不上,導(dǎo)致線體殘缺。

          附源碼(修改分辨率就改動(dòng)變量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 閱讀(1717) | 評(píng)論 (2)編輯 收藏

          基于攔截器的企業(yè)應(yīng)用構(gòu)造

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

             // 訂單服務(wù)只負(fù)責(zé)做好自己的事
            

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

           

            而為了攔截任何的方法調(diào)用,則實(shí)現(xiàn)了攔截器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();// 執(zhí)行被攔截的方法完成業(yè)務(wù)操作
                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配置里將這些組件全部連接起來(lái):

           1.OrderService實(shí)現(xiàn):
           <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.具體的財(cái)務(wù)子系統(tǒng)的偵聽器實(shí)現(xiàn)與財(cái)務(wù)系統(tǒng)的通訊:
            <bean id="orderEventListener" class="OrderEventListener" autowire="byName">
             <propety name="financialService"><ref bean="financialService"/></property>
           </bean>

              這樣,我們與具體實(shí)現(xiàn)無(wú)關(guān)的事件廣播就做到了,聰明的朋友看到這里,肯定想到了攔截器方式不僅僅適用與事件廣播,還可以實(shí)現(xiàn)事務(wù)的統(tǒng)一管理,事實(shí)上Spring的事務(wù)管理就是這樣完成的,還可以實(shí)現(xiàn)權(quán)限的控制例如Acegi,簡(jiǎn)直有點(diǎn)象萬(wàn)能的膠水,呵呵。

              從兩篇文章的逐步探討下,同一個(gè)機(jī)器,同一個(gè)虛擬機(jī)之內(nèi)的數(shù)據(jù)通訊都可以實(shí)現(xiàn)了,那么異構(gòu)系統(tǒng)和多虛擬機(jī)間的通訊又如何處理呢,于是ESB(企業(yè)服務(wù)總線)的概念就慢慢浮現(xiàn)出來(lái)了,不過(guò)這個(gè)不在本文探討的范疇了,也許在不久的將來(lái),我會(huì)補(bǔ)上這一篇。

          (全文完)

           

           

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

          僅列出標(biāo)題
          共2頁(yè): 1 2 下一頁(yè) 
          主站蜘蛛池模板: 延长县| 渭南市| 汪清县| 普兰店市| 柳江县| 庆阳市| 精河县| 全州县| 青田县| 平定县| 县级市| 榆树市| 额敏县| 驻马店市| 霍山县| 丁青县| 曲沃县| 聂拉木县| 南澳县| 伊吾县| 阿荣旗| 建始县| 宁强县| 扎兰屯市| 溆浦县| 洪湖市| 榆林市| 丁青县| 江安县| 保山市| 遵义县| 沙坪坝区| 安多县| 东源县| 仁化县| 原阳县| 南丰县| 长子县| 乐至县| 根河市| 海原县|