paulwong

          #

          分布式事務(wù)

          一、 事務(wù)概述

          1、 事務(wù)協(xié)議

          WCF相關(guān)的事務(wù)協(xié)議有三個(gè)。

          1.1. Lightweight protocol

          這是個(gè)輕量級(jí)的本地事務(wù)協(xié)議,限制管理在一個(gè)AppDomain中的事務(wù)。不能跨AppDomain邊界傳播事務(wù),也不能跨服務(wù)邊界傳播事務(wù)。跟其他協(xié)議比,Lightweight protocol是最有效率的協(xié)議。

          1.2. OleTx protocol

          這個(gè)協(xié)議可用于跨AppDomain,進(jìn)程和機(jī)器邊界,管理兩階段提交的事務(wù)協(xié)議。這個(gè)跨邊界的事務(wù)協(xié)議使用RPC,是二進(jìn)制的,windows專有的協(xié)議,不能穿越防火墻,也不能用于與非windows系統(tǒng)的互操作。在windows環(huán)境下的局域網(wǎng),OleTx協(xié)議是很好的分布式事務(wù)的管理協(xié)議。

          1.3. WS-Atomic Transaction (WSAT) protocol

          WSATOleTx協(xié)議類似,也可以跨AppDomain,進(jìn)程和機(jī)器邊界,管理兩階段提交的事務(wù)協(xié)議。但WSAT不是微軟的專有協(xié)議,此協(xié)議是微軟、IBMBEA等公司共同提出的工業(yè)標(biāo)準(zhǔn)。此協(xié)議也可用于Intranet中,但是更多的是用于在Internet環(huán)境下,或者跟非windows系統(tǒng)進(jìn)行互操作的分布式事務(wù)。

          說到WSAT協(xié)議這里有必要一下分布式事務(wù)的發(fā)展。

          分布式事務(wù):

          分布式事務(wù)在企業(yè)應(yīng)用中是很重要的一個(gè)方面,微軟使用MSDTC作為分布式事務(wù)管理器,使用OleTx事務(wù)協(xié)議進(jìn)行分布式事務(wù)管理,但是OleTx事務(wù)協(xié)議是微軟的專有協(xié)議,不是公認(rèn)標(biāo)準(zhǔn)。在分布式環(huán)境中異構(gòu)系統(tǒng)的交互一定要有個(gè)公認(rèn)同意的分布式事務(wù)標(biāo)準(zhǔn)才能在異構(gòu)的系統(tǒng)中實(shí)現(xiàn)分布式事務(wù)的協(xié)調(diào)。

          l OGMXA事務(wù)規(guī)范

          1994年,開放組織(Open Group)的 X/Open 分布式事務(wù)流程(DTP)模型,它定義了 應(yīng)用程序如何使用 事務(wù)管理程序跨多個(gè) 資源管理程序來協(xié)調(diào)分布式事務(wù)。如果事務(wù)是通過遵循 XA 的事務(wù)管理程序來進(jìn)行協(xié)調(diào)的,則任何遵循 XA 規(guī)范的資源管理程序都可以參與該事務(wù),因此就可以讓不同廠商的事務(wù)產(chǎn)品可以共同工作。所有遵循 XA 的事務(wù)都是分布式事務(wù)。XA 既支持一步提交,也支持兩階段提交。

          對(duì)象管理組(Object Management Group)的通用對(duì)象請(qǐng)求代理體系結(jié)構(gòu)對(duì)象事務(wù)服務(wù)(Common Object Request Broker Architecture Object Transaction Service -- 定義遵循規(guī)范的流程如何跨多個(gè)流程線程將事務(wù)上下文從一個(gè)流程傳播到另一個(gè)流程。這種傳播使得即使分布式對(duì)象運(yùn)行于來自不同廠商的容器中,也可以在單個(gè)事務(wù)中合作。CORBA OTS 規(guī)范建立在 XA 規(guī)范的基礎(chǔ)之上。

          l OASISBusiness Transaction ProtocolBTP)標(biāo)準(zhǔn)

          2001 年, 一個(gè)由各大公司(包括惠普公司(Hewlett-Packard,HP)、甲骨文公司(Oracle)及BEA公司)組成的聯(lián)盟開始著手創(chuàng)建 Organization for Advance Structured Information Systems (OASIS) Business Transaction ProtocolBTP)標(biāo)準(zhǔn)。

          BTP 不是專門用于 Web 服務(wù)的事務(wù)處理協(xié)議,它的目的是它也能用于其他的環(huán)境中。因而,BTP 定義了事務(wù)性的 XML 協(xié)議,并且必須在規(guī)范中指定所有的服務(wù)依賴性。

          BTP協(xié)議相對(duì)比較復(fù)雜,并且它把原子性事務(wù)和長(zhǎng)時(shí)間運(yùn)行的商業(yè)事務(wù)放在一起進(jìn)行管理,這樣它必須解決各種各樣不同的問題。它是通過放松限制來這樣做的,這表面上給人感覺靈活度很高,但是很多東西就留給實(shí)現(xiàn)者去實(shí)現(xiàn)了,導(dǎo)致使用比較復(fù)雜。

          l OASISWS-Transactions

          BTP出現(xiàn)后,其他一些行業(yè)大公司,包括 IBMMicrosoft BEA,又發(fā)布了它們自己的規(guī)范: Web 服務(wù)事務(wù)處理(WS-Transactions),由三部分組成WS-Coordination(事務(wù)協(xié)調(diào)器)、WS-AtomicTransaction(實(shí)現(xiàn)原子事務(wù))、WS-BusinessActivity(實(shí)現(xiàn)長(zhǎng)時(shí)間運(yùn)行的商業(yè)事務(wù))。WS-TransactionsBTP好的方面是它將事務(wù)協(xié)調(diào)器獨(dú)立出來,另外用兩個(gè)標(biāo)準(zhǔn)在WS-Transactions基礎(chǔ)上分別實(shí)現(xiàn)原子事務(wù)和長(zhǎng)時(shí)間運(yùn)行的事務(wù),這樣簡(jiǎn)化了復(fù)雜性。

          WS-Transactions是專門用于web services的事務(wù)規(guī)范。

          2005年,WS-Transactions發(fā)布了第一個(gè)版本,Version 1.0。

          2007年,WS-Transactions發(fā)布了Version 1.1,并被OASIS組織接受為標(biāo)準(zhǔn),成為WS-*標(biāo)準(zhǔn)的一部分。

          WCF支持的可互操作的分布式事務(wù)協(xié)議只有WS-Transactions,并且只實(shí)現(xiàn)了WS-Coordination、WS-AtomicTransaction,WS-BusinessActivity沒被實(shí)現(xiàn)。

          1.3.1. WS-Coordination

          WS-Coordination它描述了一個(gè)可擴(kuò)展的交流協(xié)議框架,該框架對(duì)分布式的請(qǐng)求進(jìn)行其請(qǐng)求協(xié)議的判斷與處理,處理后再將請(qǐng)求向下方的業(yè)務(wù)處理模塊進(jìn)行分發(fā)。

          該 框架最大特點(diǎn)是其能夠以系統(tǒng)流程代理的身份來處理請(qǐng)求。當(dāng)不同的請(qǐng)求,無論是內(nèi)部的同系統(tǒng)的請(qǐng)求或外部的異構(gòu)系統(tǒng)的請(qǐng)求,經(jīng)過該框架處理后,再其原有的特 殊的傳輸代理層上添加了符合本系統(tǒng)信息流規(guī)則的本地協(xié)議。也就是本系統(tǒng)允許已經(jīng)存在的事務(wù)、工作流或其他服務(wù)的請(qǐng)求隱藏其自身獨(dú)特的傳輸協(xié)議,并可順利運(yùn) 行于異構(gòu)式的系統(tǒng)環(huán)境中。

          當(dāng)前WS-Coordination穩(wěn)定的版本是1.1,同樣是OASIS2007年發(fā)布的國(guó)際標(biāo)準(zhǔn)?,F(xiàn)在1.2版本也在起草過程之中。WS-Coordination規(guī)范的具體實(shí)現(xiàn)需要開發(fā)中在基于XML的配置文件中引入WS-Coordination規(guī)范的命名空間,如指定<xsschema>字段的值為ws-addr.xsd。由于是基于XML文件來實(shí)現(xiàn),WS-Coordination規(guī)范易于實(shí)現(xiàn),且對(duì)日后的擴(kuò)展支持度高。

          通過WS-Coordination的使用,一方面通過附加統(tǒng)一的本地協(xié)議,在使用不同通信協(xié)議的請(qǐng)求到來時(shí),進(jìn)行統(tǒng)一的協(xié)議處理,加快了請(qǐng)求的處理速度,提高了系統(tǒng)的松耦合性;另一方面WS-Coordination規(guī)范所定義的框架加強(qiáng)了系統(tǒng)的異構(gòu)性,使系統(tǒng)不因請(qǐng)求所使用的協(xié)議不同而無法處理,這提升了系統(tǒng)整體的兼容性,加強(qiáng)了系統(tǒng)的綜合服務(wù)能力。

          1.3.2. WS-AtomicTransaction

          WS-AtomicTransaction 定義了一組特定的協(xié)議,這組協(xié)議可以插入 WS-Coordination 模型,以實(shí)現(xiàn)傳統(tǒng)的兩階段原子事務(wù)處理協(xié)議。注意到原子的兩階段模型只是就涉及的服務(wù)而言的非常重要。提供服務(wù)的站點(diǎn)或基礎(chǔ)體系結(jié)構(gòu)可能大肆宣傳兩階段提交,但是卻使用一些其他的企業(yè)內(nèi)部模型,比如補(bǔ)償模型或版本模型。這種自由使簡(jiǎn)單的兩階段提交模型對(duì)于長(zhǎng)期運(yùn)行的 Internet 計(jì)算更有用。

          WCF實(shí)現(xiàn)了WS-AtomicTransaction協(xié)議,事務(wù)管理器是由MSDTC實(shí)現(xiàn),也就是說在WCF中可以使用WS-AtomicTransaction協(xié)議進(jìn)行分布式事務(wù)的管理,并跟其他實(shí)現(xiàn)了WS-AtomicTransaction的異構(gòu)分布式事務(wù)互操作。

          1.3.3. WS-BusinessActivity

          WS-BusinessActivity 定義了一組特定的協(xié)議,這組協(xié)議可以插入 WS-Coordination 模型,以實(shí)現(xiàn)長(zhǎng)期運(yùn)行的、基于補(bǔ)償?shù)氖聞?wù)處理協(xié)議。

          WS-BusinessActivity定義的是long-running事務(wù),所謂long-running事務(wù)是指那些企業(yè)業(yè)務(wù)流程,需要跨應(yīng)用、跨企業(yè)來完成某個(gè)事務(wù),甚至在事務(wù)流程中還需要有手工操作的參與,這類事務(wù)的完成時(shí)間可能以分計(jì),以小時(shí)計(jì),甚至可能以天計(jì),這類事務(wù)也被稱為SAGA。

          這類事務(wù)如果按照事務(wù)的ACID的要求去設(shè)計(jì),勢(shì)必造成系統(tǒng)的可用性大大的降低。試想一個(gè)由兩臺(tái)服務(wù)器一起參與的事務(wù),服務(wù)器A發(fā)起事務(wù),服務(wù)器B參與事務(wù),B的事務(wù)需要人工參與,所以處理時(shí)間可能很長(zhǎng)。如果按照ACID的原則,要保持事務(wù)的隔離性、一致性,服務(wù)器A中發(fā)起的事務(wù)中使用到的事務(wù)資源將會(huì)被鎖定,不允許其他應(yīng)用訪問到事務(wù)過程中的中間結(jié)果,直到整個(gè)事務(wù)被提交或者回滾。這就造成事務(wù)A中的資源被長(zhǎng)時(shí)間鎖定,系統(tǒng)的可用性將不可接受。

          WS-BusinessActivity提供了一種基于補(bǔ)償?shù)?/span>long-running的事務(wù)處理模型。還是上面的例子,服務(wù)器A的事務(wù)如果執(zhí)行順利,那么事務(wù)A就先行提交,如果事務(wù)B也執(zhí)行順利,則事務(wù)B也提交,整個(gè)事務(wù)就算完成。但是如果事務(wù)B執(zhí)行失敗,事務(wù)B本身回滾,這時(shí)事務(wù)A已經(jīng)被提交,所以需要執(zhí)行一個(gè)補(bǔ)償操作,將已經(jīng)提交的事務(wù)A執(zhí)行的操作作反操作,恢復(fù)到未執(zhí)行前事務(wù)A的狀態(tài)。這樣的SAGA事務(wù)模型,是犧牲了一定的隔離性和一致性的,但是提高了long-running事務(wù)的可用性。

          目前的WCF中未實(shí)現(xiàn)WS-BusinessActivity,在WCF 4.0 beta2中也為實(shí)現(xiàn),估計(jì)在WCF 4.0正式版中也不會(huì)實(shí)現(xiàn)WS-BusinessActivity協(xié)議。

          2、 事務(wù)管理器

          管理事務(wù)必須有相應(yīng)的協(xié)議外,還必須有個(gè)事務(wù)管理器,事務(wù)管理器通過相應(yīng)的事務(wù)協(xié)議對(duì)本機(jī)的事務(wù)進(jìn)行管理。如果同一個(gè)事務(wù)需要跨機(jī)器,則每臺(tái)參與事務(wù)的機(jī)器的事務(wù)管理器之間進(jìn)行相互協(xié)調(diào)共同完成一個(gè)分布式事務(wù)。

          2.1. LTM

          輕型事務(wù)管理器Lightweight Transaction Manager,只能管理本地事務(wù),事務(wù)在一個(gè)AppDomain內(nèi)。LTM使用Lightweight protocol管理兩階段提交的事務(wù)。LTM只能管理單一的可持久化的資源,如果有兩個(gè)以上的可持久化資源登記到事務(wù)中,LTM將被升級(jí)到DTC管理器。

          2.2. KTM

          Vistawindows2008引入了內(nèi)核事務(wù)管理器Kernel Transaction Manager (KTM)

          Windows Vista中還引入了兩個(gè)主要的事務(wù)資源,事務(wù)NTFS和事務(wù)注冊(cè)表,稱作核心資源kernel resource managers (KRM),KTM可以管理這兩類資源。

          事務(wù)性 NTFS,也稱為 TxF,使用TxF可以將文件操作納入到事務(wù)管理中,在事務(wù)中的的文件操作將同事務(wù)中的其他事務(wù)資源一樣在事務(wù)前后保持一致性。

          同樣事務(wù)性注冊(cè)表,也稱作TxR,注冊(cè)表的操作也可以納入到事務(wù)管理中。

          KTMLTM一樣,使用Lightweight protocol管理兩階段提交的事務(wù),只能管理本地事務(wù),事務(wù)在一個(gè)AppDomain內(nèi),只能管理單一的可持久化的資源。

          2.3. DTC

          DTC可以管理任何跨越執(zhí)行邊界的事務(wù),跨AppDomain,跨進(jìn)程,跨機(jī)器,跨服務(wù)。DTC可以使用OleTx 或者WSAT事務(wù)協(xié)議。

          DTC既可以管理本地事務(wù),更重要的是它能夠管理跨邊界的服務(wù)。

          在使用WCF的場(chǎng)景下,每臺(tái)運(yùn)行WCF服務(wù)的機(jī)器都默認(rèn)使用DTC。DTC建立一個(gè)新事務(wù),并跨機(jī)器把事務(wù)傳播到其他機(jī)器,發(fā)起事務(wù)的機(jī)器上的事務(wù)為根事務(wù),這個(gè)機(jī)器上的DTC就要負(fù)責(zé)這個(gè)分布式事務(wù)的協(xié)調(diào)任務(wù),負(fù)責(zé)啟動(dòng)事務(wù),提交事務(wù),和回滾事務(wù)。

          事務(wù)管理器可使用的事務(wù)協(xié)議:

          Protocal

          LTM

          KTM

          DTC

          Lightweight protocol

          Yes

          Yes

          No

          OleTx protocol

          No

          No

          Yes

          WS-Atomic Transaction

          No

          No

          Yes

          3、 事務(wù)資源

          在事務(wù)范圍內(nèi),可納入事務(wù)管理的資源,即可以在事務(wù)正常執(zhí)行后提交生效,在事務(wù)失敗可以回滾恢復(fù)到事務(wù)啟動(dòng)前狀態(tài)的資源成為事務(wù)資源。最常見的事務(wù)資源就是常用的數(shù)據(jù)庫操作。但是在vista開始引入了兩個(gè)核心事務(wù)資源:TxF事務(wù)文件和TxR事務(wù)注冊(cè)表。

          可用的事務(wù)資源:

          3.1. sql server事務(wù)資源

          Sql 2005sql 2008的事務(wù)資源是新sql serverLTM事務(wù)管理器可以管理這類事務(wù)。

          3.2. 核心事務(wù)資源

          Vista開始引入的TxF事務(wù)文件和TxR事務(wù)注冊(cè)表??梢詫?duì)文件和注冊(cè)表進(jìn)行事務(wù)性操作。KTM可以管理這類資源。

          3.3. 傳統(tǒng)事務(wù)資源

          SQL Server 2000, Oracle, DB2, MSMQ這類資源是傳統(tǒng)的事務(wù)資源,這些資源只能由DTC事務(wù)管理器進(jìn)行管理。

          事務(wù)管理器可管理的事務(wù)資源:

          Resource

          LTM

          KTM

          DTC

          Sql Server事務(wù)資源

          Yes

          No

          Yes

          核心事務(wù)資源

          No

          Yes

          Yes

          傳統(tǒng)事務(wù)資源

          No

          No

          Yes

          4、 事務(wù)管理器的升級(jí)

          每個(gè)WCF中啟動(dòng)的事務(wù)都是先由LTM事務(wù)管理器管理,一旦事務(wù)中出現(xiàn)現(xiàn)有事務(wù)管理器無法管理的資源或情況,WCF會(huì)提升事務(wù)管理器的級(jí)別。分別從LTM升級(jí)到KTM,最高級(jí)別升級(jí)到DTC。事務(wù)管理器可以多次升級(jí),事務(wù)管理器一旦升級(jí)后不能降級(jí)。

          事務(wù)管理器的升級(jí)規(guī)則:

          image

          posted @ 2012-03-30 00:20 paulwong 閱讀(1562) | 評(píng)論 (0)編輯 收藏

          開始Spring MVC

          建立一個(gè)web project,并導(dǎo)入spring 3.x的jar包配置web.xml根據(jù)上面的spring mvc流程圖,我們知道DispatcherServlet是spring mvc 的一個(gè)前端控制器,所以我們當(dāng)然要去配置它,以便于將請(qǐng)求轉(zhuǎn)給DispatcherServlet處理

            <servlet>
              
          <servlet-name>dispatcher</servlet-name>
              
          <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
              
          <init-param>
                  
          <param-name>contextConfigLocation</param-name>
          <!-- 如果配置文件位于classpath下,可以這么寫: classpath:dispatcher.xml -->
                  
          <param-value>/WEB-INF/dispatcher.xml</param-value>
              
          </init-param>
              
          <load-on-startup>1</load-on-startup>
            
          </servlet>

            
          <servlet-mapping>
              
          <servlet-name>dispatcher</servlet-name>
              
          <url-pattern>/</url-pattern>
            
          </servlet-mapping>

          注:由于DispatcherServlet在初始化的過程中需要一個(gè)配置文件來生產(chǎn)文件中的各種bean,并生成WebApplicationContext對(duì)象,保存到ServletContext中(如果DispatcherServlet有多個(gè),那么每一個(gè)DispatcherServlet都對(duì)應(yīng)一個(gè)WebApplicationContext),我們可以在Servlet的init-param中配置配置文件的路徑,當(dāng)然如果我們沒有配置Init-Param,它會(huì)默認(rèn)到WEB-INF的文件夾中找[servletname]-servlet.xml文件,例如上面如果我們沒有配置,則會(huì)去尋找dispatcher-servlet.xml這個(gè)配置文件。(在init-param中我們可以指定多個(gè)配置文件,用逗號(hào)分隔也可以使用通配符*)
          配置上文中我們指定的所需的dispatcher.xml文件

          <?xml version="1.0" encoding="UTF-8"?>
          <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
          xmlns:context
          ="http://www.springframework.org/schema/context"
          xmlns:mvc
          ="http://www.springframework.org/schema/mvc"
          xsi:schemaLocation
          ="
          http://www.springframework.org/schema/beans
          http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
          http://www.springframework.org/schema/context
          http://www.springframework.org/schema/context/spring-context-3.0.xsd
          http://www.springframework.org/schema/mvc
          http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd"
          >

              
          <context:component-scan base-package="com.controls" />
              
          <mvc:annotation-driven />
              
          <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
                 
          <property name="prefix" value="/WEB-INF/views/"></property>
                 
          <property name="suffix" value=".jsp"></property>
                 
          <property name="viewClass" value="org.springframework.web.servlet.view.JstlView"></property>
              
          </bean>
          </beans>



          配置文件說明:
          <context:component-scan base-package="com.controls" />
          由于我們使用了基于注解的Controller,所以這里指定了需要被掃描的包路徑,如果有多個(gè)可以使用逗號(hào)分隔
          <mvc:annotation-driven />

          上面的spring mvc流程圖中我們知道DispatcherServlet接管請(qǐng)求后,會(huì)由HandlerMapping來執(zhí)行映射,所以我們需要注冊(cè)HanlderMapping,比如上面的標(biāo)簽會(huì)自動(dòng)注冊(cè)比如DefaultAnnotationHandlerMapping(執(zhí)行請(qǐng)求到Controller的映射)和AnnotationMethodHandlerAdapter(調(diào)用controller中的方法)這樣的bean,當(dāng)然這個(gè)標(biāo)簽還提供了其他的一些支持(更多介紹請(qǐng)參照spring官方文檔第455頁)。

          <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">

                 
          <property name="prefix" value="/WEB-INF/views/"></property>

                 
          <property name="suffix" value=".jsp"></property>

                 
          <property name="viewClass" value="org.springframework.web.servlet.view.JstlView"></property>

          </bean>

          上面spring mvc流程圖的最后controller處理完畢后會(huì)交給一個(gè)ViewResolver進(jìn)行處理,大體上是解析視圖邏輯名并經(jīng)過一定的處理獲取一個(gè)視圖,這里的意思是設(shè)置視圖用jsp來處理(比如我們?cè)O(shè)置viewClass為JstlView)來進(jìn)行處理,就是以forward的形式轉(zhuǎn)發(fā)給jsp,這個(gè)地址是:/WEB-INF/views/[controller返回值].jsp ,當(dāng)然視圖解析器可以定義多個(gè),(視圖解析器不會(huì)處理ModelAndView中已經(jīng)設(shè)置了View的請(qǐng)求,因?yàn)橐呀?jīng)有View來處理了,那當(dāng)然就不需要它來解析到真正的視圖View啦)
          編寫Controller控制器這里我們使用例子的形式來說明

          實(shí)現(xiàn)一個(gè)控制器類@Controller
          @Controller
          @RequestMapping(
          "/user")
          public class UserControl {

          }

          只要給類加上Controller的注解,并放在被掃描的包中,那么這個(gè)類就是一個(gè)控制器了,RequestMapping表明匹配的路徑,可以寫在類或者類的方法上,如果類上面有RequestMapping注解,那么其下面的方法就是相對(duì)于類上面注解地址的一個(gè)相對(duì)路徑


          定義一個(gè)接管請(qǐng)求的方法方法名:無任何要求
          --------------------------------------------------------------
          參數(shù):(順序以及個(gè)數(shù)無任何要求)
          HttpServletRequest
          HttpServletResponse
          PrintWriter 相當(dāng)于HttpResponse.getWriter()獲得的對(duì)象
          Map 其實(shí)是獲得了ModelAndView中的Model
          BindingResult 綁定數(shù)據(jù)的處理結(jié)果
          HttpSession 如果使用此參數(shù),需要注意如果是第一次訪問還沒有session的話會(huì)報(bào)錯(cuò)
          @PathVariable 用于接收路徑變量
          @RequestParam 相當(dāng)于調(diào)用request.getParameter(“name”)方法
          @CookieValue 獲取cookie的值
          @RequestHeader 獲取header中的值
          實(shí)體對(duì)象 會(huì)根據(jù)請(qǐng)求的參數(shù)名,注入到這個(gè)對(duì)象對(duì)于得屬性中,必須提供set方法
          等等等等等
          --------------------------------------------------------------
          返回值:
          void
          返回值是void,如果接收了PrintWriter 或者 HttpServletResponse 參數(shù),那么返回的ModelAndView就是null,也就是直接將輸出流輸出到客戶端,如果方法沒有接收輸出參數(shù),后面會(huì)默認(rèn)生成一個(gè)視圖名

          String 視圖邏輯名

          ModelAndView 是一個(gè)視圖邏輯名+Map的封裝類
          其他任意類型 存入ModelAndView中的Model
          --------------------------------------------------------------

          不管我們的返回類型是什么,返回值會(huì)通過處理,最終返回一個(gè)ModelAndView或者null
          例1:給方法定義一個(gè)請(qǐng)求映射并使用路徑變量 @RequestMapping("/id/{userid}/name/{username}")

          @RequestMapping("/id/{userid}/name/{username}")
          public String queryUser(@PathVariable("userid"long userID, @PathVariable("username") String userName, Map<String, User> model) {
                 User user 
          = new User();
                 user.setUserID(userID);
                 user.setUserName(userName);
                 model.put(
          "userInfo", user);
                 
          return "Home";
              }


          @RequestMapping定義路由映射,其中{userid} {username} 是PathVariable(路徑變量)
          這樣我們只需訪問 http://localhost:8080/SpringMVC/user/id/10001/name/liudehua 就能進(jìn)入上面的方法
          RequestMapping還可以使用通配符,如: /test/*/name/{name}

          例2:接受請(qǐng)求參數(shù)@RequestMapping("/save")
          @RequestMapping("/save")
          public String save(@RequestParam("userName") String userName,@RequestParam("Age"int age) {
                 System.out.println(userName);
                 System.out.println(age);
                 
          return "Home";
          }


          例3:請(qǐng)求參數(shù)直接注入到Model@RequestMapping("/save")
          @RequestMapping("/save")
          public String save(User user) {
                 System.out.println(user.getUserID());
                 System.out.println(user.getUserName());
                 
          return "Home";
          }

          例4:轉(zhuǎn)發(fā)與重定向轉(zhuǎn)發(fā): (相當(dāng)于 request.getRequestDispatcher(“”).forward(request, response))
          return “forward:/user/test”;

          重定向: (相當(dāng)于response.redirect(“”))
          return “redirect:/user/test”
          return “redirect:http://www.google.com.hk”;

          例5:根據(jù)HttpMethod來過濾請(qǐng)求
          @RequestMapping(params="hello=world", method={RequestMethod.GET, RequestMethod.POST}
          public String helloworld() {
          }
           


          例6:根據(jù)參數(shù)來進(jìn)行過濾
          @RequestMapping(params="hello=world", method={RequestMethod.GET, RequestMethod.POST})  
          public String helloworld() {
          }
            

          必須有個(gè)hello的參數(shù)并且名稱為world,而且只能是get或post請(qǐng)求才會(huì)進(jìn)入此方法

          http://www.cnblogs.com/zhaoyang/archive/2012/01/07/2315425.html

          posted @ 2012-03-29 19:06 paulwong 閱讀(1164) | 評(píng)論 (0)編輯 收藏

          Joda-Time 簡(jiǎn)介

          假設(shè)我希望輸出這樣一個(gè)日期:距離 Y2K 45 天之后的某天在下一個(gè)月的當(dāng)前周的最后一天的日期。坦白地說,我甚至不想使用 Calendar 處理這個(gè)問題。使用 JDK 實(shí)在太痛苦了,即使是簡(jiǎn)單的日期計(jì)算,比如上面這個(gè)計(jì)算。正是多年前的這樣一個(gè)時(shí)刻,我第一次領(lǐng)略到 Joda-Time 的強(qiáng)大。使用 Joda,用于計(jì)算的代碼如清單 3 所示:

          DateTime dateTime = new DateTime(2000, 1, 1, 0, 0, 0, 0);
          System.out.println(dateTime.plusDays(
          45).plusMonths(1).dayOfWeek() .withMaximumValue().toString("E MM/dd/yyyy HH:mm:ss.SSS");

          詳見:
          http://www.oschina.net/question/12_7643

          posted @ 2012-03-27 17:09 paulwong 閱讀(298) | 評(píng)論 (0)編輯 收藏

          業(yè)務(wù)建模一般步驟和方法

          轉(zhuǎn)載自:http://hi.baidu.com/parryblog/blog/item/2d1ae59a72b043bcc9eaf4a0.html

          本篇開始之前先扯點(diǎn)閑話,商業(yè)應(yīng)用系統(tǒng)開發(fā)經(jīng)歷了三個(gè)階段:
            第一個(gè)階段以計(jì)算為中心,分析設(shè)計(jì)圍繞程序的運(yùn)行效率,算法優(yōu)劣,存貯優(yōu)化來進(jìn)行。90年代的大學(xué)課程講的都是這些。

            第二階段以數(shù)據(jù)為中心,分析設(shè)計(jì)圍繞數(shù)據(jù)流進(jìn)行,以數(shù)據(jù)流程來模擬業(yè)務(wù)流程。這也就是所謂的面向過程的分析模式。

            第三階段以人為中心,分析設(shè)計(jì)圍繞人的業(yè)務(wù)需求,使用要求,感受要求進(jìn)行。這也就是現(xiàn)在的面象對(duì)象分析模式。

            使用OO方法建立商業(yè)模型必須先定義涉眾。商業(yè)系統(tǒng)無論多復(fù)雜,無論什么行業(yè),其本質(zhì)無非是人,事,物,規(guī)則。人是一切的中心,人做事,做事產(chǎn)生物,規(guī)則限制人事物。人驅(qū)動(dòng)系統(tǒng),事體現(xiàn)過程,物記錄結(jié)果,規(guī)則則是控制。無論OO也好,UML也好,復(fù)雜的表面下其實(shí)只是一個(gè)簡(jiǎn)單的規(guī)則,系統(tǒng)分析員弄明白有什么人,什么人做什么事,什么事產(chǎn)生什么物,中間有什么規(guī)則,再把人,事,物之間的關(guān)系定義出來,商業(yè)建模也就基本完成了。這時(shí)候可以說,系統(tǒng)分析員已經(jīng)完全了解了用戶需求,可以進(jìn)入系統(tǒng)建模階段了。

            書歸正傳,上篇筆者歸納了一些典型的涉眾類型及他們的普遍期望。接下來,就是要將他們這些期望定義出來。這個(gè)過程,就是業(yè)務(wù)用例獲取的過程。筆者可以跟大家分享的經(jīng)驗(yàn)是通過以下步驟進(jìn)行,這些步驟并非唯一正確,對(duì)于經(jīng)驗(yàn)不多的系統(tǒng)分析員來說,這些步驟很有指導(dǎo)意義。

            筆者做了一個(gè)建模實(shí)例,有需要有讀者請(qǐng)到筆者的BLOG資源中心下載,實(shí)例以上一篇所述網(wǎng)上圖書館需求為藍(lán)本建立了業(yè)務(wù)用例模型,之后的概念模型、系統(tǒng)模型則抽取了其中的借閱過程作為例子。不記得了可以后頭找找。

            建模第一步,從涉眾中找出用戶。并定義這些用戶之間的關(guān)系。在ROSE中,應(yīng)該使用business actor 類型。參考上一篇的需求描述,下載實(shí)例

            第二步,找出每個(gè)用戶要做的事,即業(yè)務(wù)用例,在ROSE中應(yīng)使用Business use case類型。請(qǐng)參考《用例的類型與粒度》一文以幫助確定用例的粒度。筆者強(qiáng)烈建議為每一個(gè)business actor繪制一個(gè)業(yè)務(wù)用例圖,這能很好的體現(xiàn)以人為中心的分析模式,并且不容易漏掉business actor需要做的事。至于以參與者為中心的視圖容易漏掉某個(gè)業(yè)務(wù)用例的參與者的擔(dān)心,可以在第四步中得到消除。下載實(shí)例

            第三步,利用業(yè)務(wù)場(chǎng)景圖幫助分析業(yè)務(wù)流程,在ROSE中,這個(gè)階段最好使用活動(dòng)圖Activity diagram。在這個(gè)階段,業(yè)務(wù)場(chǎng)景圖非常重要,在繪制過程中,系統(tǒng)分析員必須采用第一步中定義的用戶名字作為泳道名,使用第二步中定義的業(yè)務(wù)用例名作為活動(dòng)名來繪制。必須這么做的原因是,如果你無法把利用已經(jīng)定義出來的 business actor 和 business use case完備的描繪業(yè)務(wù)流程,那么一定是前面的定義出問題了,你需要回頭審視是否 business actor 和 business use case定義不完善或錯(cuò)誤。如果不是所有的business actor 和 business use case 都被用到,要么應(yīng)該檢查業(yè)務(wù)流程調(diào)研時(shí)漏了什么,要么應(yīng)該檢查是否定義了一些無用的business actor 和 business use case 。同時(shí),繪制業(yè)務(wù)場(chǎng)景圖也非常有助于選擇合適的用例粒度并保持所有的用例都是同一粒度。下載實(shí)例

            第四步,繪制用例場(chǎng)景圖。與業(yè)務(wù)場(chǎng)景圖不同的是,用例場(chǎng)景圖只針對(duì)一個(gè)用例繪制該用例的執(zhí)行過程。筆者仍然強(qiáng)烈推薦使用activity diagram。在用例場(chǎng)景圖的繪制中,必須使用第一步中定義的業(yè)務(wù)用戶作為泳道。必須這么做的原因是,它能幫助你發(fā)現(xiàn)在定義業(yè)務(wù)用例圖時(shí)的錯(cuò)誤,比如是否漏掉了某個(gè)業(yè)務(wù)用例的潛在使用者。不是每個(gè)業(yè)務(wù)用例都需要繪制場(chǎng)景圖,只有兩三個(gè)步驟的業(yè)務(wù)用例是不必一定繪制業(yè)務(wù)用例圖的,但仍然需要在業(yè)務(wù)用例規(guī)約文檔中寫明。下載實(shí)例

          第五步,從第三步或第四步中繪制的活動(dòng)圖中找到每一步活動(dòng)將使用到的或產(chǎn)生的結(jié)果。這是找到物的過程。找到后,應(yīng)當(dāng)建立這些物之間的關(guān)系。在ROSE中,這稱為業(yè)務(wù)實(shí)體模型。應(yīng)該使用business entity 類型。下載實(shí)例

            第六步,在上述過程中,隨時(shí)補(bǔ)充詞匯表Glossary。將此過程中的所有業(yè)務(wù)詞匯,專業(yè)詞匯等一切在建模過程中使用到的需要解釋的名詞。這份文檔將成為模型建立人與讀者就模型達(dá)成一致理解的重要保證。

            第七步,根據(jù)上一篇中提到的業(yè)主,老板等涉眾的期望審視建立好的模型,確定業(yè)務(wù)范圍,決定哪些業(yè)務(wù)用例在系統(tǒng)建設(shè)范圍內(nèi)。那些不打算納入建設(shè)范圍內(nèi)的業(yè)務(wù)用例有兩種情況,一種是該業(yè)務(wù)用例是被調(diào)用一方,那么應(yīng)該把它改為 boundary 類型,意味著將來它是一個(gè)外部接口。另一種是該業(yè)務(wù)用例主動(dòng)調(diào)用系統(tǒng)內(nèi)業(yè)務(wù)用例,那么應(yīng)該將它改為business actor類型。與普通business actor不同的是,由業(yè)務(wù)用例轉(zhuǎn)換而成的business actor不是人,而通常是一個(gè)外部系統(tǒng)進(jìn)程,因此應(yīng)該在被調(diào)用的系統(tǒng)內(nèi)業(yè)務(wù)用例與它之間增加一個(gè)boundary元素,意味著我們的系統(tǒng)將為這樣一個(gè)外部進(jìn)程提供一個(gè)接口。嚴(yán)格來說,那些需要納入建設(shè)范圍的business use case 應(yīng)當(dāng)對(duì)應(yīng)的生成一個(gè) business use case realization, 以后的設(shè)計(jì)工作將歸納到這些實(shí)現(xiàn)用例中。但筆者覺得這一步并非很關(guān)鍵的,實(shí)際中本人也經(jīng)常省略這一步,而將協(xié)作圖,象活動(dòng)圖,類交互圖等直接在business usecase下說明。不過本實(shí)例中筆者還是按照正規(guī)方法來建模的。下載實(shí)例

            需要說明的是,上述的步驟并非一次性完成的,在每一個(gè)步驟中都可能導(dǎo)致對(duì)以前步驟的調(diào)整。即使建模已經(jīng)完成,當(dāng)遇到變化或發(fā)現(xiàn)新問題時(shí),上述步驟應(yīng)當(dāng)從頭到尾再執(zhí)行一次。這也是RUP倡導(dǎo)的迭代開發(fā)模式。

          經(jīng)過以上的步驟,我們已經(jīng)建立了一個(gè)完整的業(yè)務(wù)模型。但這決不是建模工作的全部,以上過程只說明了建立一個(gè)完整業(yè)務(wù)模型的過程,不能說這樣就建立了一個(gè)很好的業(yè)務(wù)模型。因?yàn)樯鲜龅倪^程中并沒有提及業(yè)務(wù)分析過程。分析過程全憑系統(tǒng)分析員的經(jīng)驗(yàn),對(duì)OO的理解和對(duì)行業(yè)業(yè)務(wù)的把握能力,對(duì)原始業(yè)務(wù)模型進(jìn)行歸納,整理,抽象,重構(gòu),以建立一個(gè)更高效,合理,擴(kuò)展性更強(qiáng)的模型。這個(gè)過程無法以步驟說明?;蛟S以后筆者會(huì)專門針對(duì)模型分析寫點(diǎn)東西。另外除了模型,還至少需要寫業(yè)務(wù)架構(gòu)文檔、用例規(guī)約和補(bǔ)充用例規(guī)約三種文檔。因?yàn)槟P碗m然可以較好的體現(xiàn)業(yè)務(wù)架構(gòu),但很不好表達(dá)業(yè)務(wù)規(guī)則和非業(yè)務(wù)需求,這些需要在文檔中說明。例如用例的前置條件和后置條件就是一種業(yè)務(wù)規(guī)則。讀者可以在RUP文檔中找到這些文檔的模板。
           
          http://hi.baidu.com/parryblog/blog/category/%CF%B5%CD%B3%B7%D6%CE%F6
          http://hi.baidu.com/parryblog/blog/category/%D0%E8%C7%F3%B7%D6%CE%F6


          posted @ 2012-03-26 00:26 paulwong 閱讀(675) | 評(píng)論 (0)編輯 收藏

          Spring MVC 的請(qǐng)求參數(shù)獲取的幾種方法

          通過@PathVariabl注解獲取路徑中傳遞參數(shù)

          JAVA
           @RequestMapping(value = "/{id}/{str}")
           
          public ModelAndView helloWorld(@PathVariable String id, @PathVariable String str) {
           System.out.println(id);
           System.out.println(str);
           
          return new ModelAndView("/helloWorld");
          }


          用@ModelAttribute注解獲取POST請(qǐng)求的FORM表單數(shù)據(jù)
          JSP
          <form method="post" action="hao.do">
           a: 
          <input id="a" type="text" name="a"/>
           b: 
          <input id="b" type="text" name="b"/>
           
          <input type="submit" value="Submit" />
          </form>


          JAVA pojo
           public class Pojo{
           
          private String a;
           
          private int b;
          }


          JAVA controller
          @RequestMapping(method = RequestMethod.POST)
          public String processSubmit(@ModelAttribute("pojo") Pojo pojo) {
           
          return "helloWorld";
           }


          直接用HttpServletRequest獲取
          JAVA
          @RequestMapping(method = RequestMethod.GET)
          public String get(HttpServletRequest request, HttpServletResponse response) {
           System.out.println(request.getParameter(
          "a"));
           
          return "helloWorld";
          }


          用注解@RequestParam綁定請(qǐng)求參數(shù)a到變量a
          當(dāng)請(qǐng)求參數(shù)a不存在時(shí)會(huì)有異常發(fā)生,可以通過設(shè)置屬性required=false解決,
          例如: @RequestParam(value="a", required=false)
          JAVA
          @RequestMapping(value = "/requestParam", method = RequestMethod.GET)
          public String setupForm(@RequestParam("a") String a, ModelMap model) {
           System.out.println(a);
          return "helloWorld";}

          posted @ 2012-03-23 17:36 paulwong 閱讀(51170) | 評(píng)論 (2)編輯 收藏

          HOST文件安裝器

          http://sourceforge.net/projects/huhamhirehosts/files/

          posted @ 2012-03-21 00:48 paulwong 閱讀(207) | 評(píng)論 (0)編輯 收藏

          Java容器類Collection、List、ArrayList、Vector及map、HashTable、HashMap區(qū)別

          Collection是List和Set兩個(gè)接口的基接口
          List在Collection之上增加了"有序"
          Set在Collection之上增加了"唯一"

          而ArrayList是實(shí)現(xiàn)List的類...所以他是有序的.
          它里邊存放的元素在排列上存在一定的先后順序

          而且ArrayList是采用數(shù)組存放元素
          另一種List LinkedList采用的則是鏈表。

          Collection和Map接口之間的主要區(qū)別在于:Collection中存儲(chǔ)了一組對(duì)象,而Map存儲(chǔ)關(guān)鍵字/值對(duì)。
          在Map對(duì)象中,每一個(gè)關(guān)鍵字最多有一個(gè)關(guān)聯(lián)的值。
          Map:不能包括兩個(gè)相同的鍵,一個(gè)鍵最多能綁定一個(gè)值。null可以作為鍵,這樣的鍵只有一個(gè);可以有一個(gè)或多個(gè)鍵所對(duì)應(yīng)的
          值為null。當(dāng)get()方法返回null值時(shí),即可以表示Map中沒有該鍵,也可以表示該鍵所對(duì)應(yīng)的值為null。因此,在Map中不能由get()方法來判斷Map中是否存在某個(gè)鍵,而應(yīng)該用containsKey()方法來判斷。
          繼承Map的類有:HashMap,HashTable
          HashMap:Map的實(shí)現(xiàn)類,缺省情況下是非同步的,可以通過Map Collections.synchronizedMap(Map m)來達(dá)到線程同步
          HashTable:Dictionary的子類,缺省是線程同步的。不允許關(guān)鍵字或值為null

          當(dāng)元素的順序很重要時(shí)選用TreeMap,當(dāng)元素不必以特定的順序進(jìn)行存儲(chǔ)時(shí),使用HashMap。Hashtable的使用不被推薦,因?yàn)镠ashMap提供了所有類似的功能,并且速度更快。當(dāng)你需要在多線程環(huán)境下使用時(shí),HashMap也可以轉(zhuǎn)換為同步的。

          為什么要使用集合類
          當(dāng)你事先不知道要存放數(shù)據(jù)的個(gè)數(shù),或者你需要一種比數(shù)組下標(biāo)存取機(jī)制更靈活的方法時(shí),你就需要用到集合類。

          理解集合類
          集合類存放于java.util包中。
          集合類存放的都是對(duì)象的引用,而非對(duì)象本身,出于表達(dá)上的便利,我們稱集合中的對(duì)象就是指集合中對(duì)象的引用(reference)。
          集合類型主要有3種:set(集)、list(列表)和map(映射)。

          (1)集 (Set):口袋
          集(set)是最簡(jiǎn)單的一種集合,它的對(duì)象不按特定方式排序,只是簡(jiǎn)單的把對(duì)象加入集合中,就像往口袋里放東西。
          對(duì)集中成員的訪問和操作是通過集中對(duì)象的引用進(jìn)行的,所以集中不能有重復(fù)對(duì)象。
          集也有多種變體,可以實(shí)現(xiàn)排序等功能,如TreeSet,它把對(duì)象添加到集中的操作將變?yōu)榘凑漳撤N比較規(guī)則將其插入到有序的對(duì)象序列中。它實(shí)現(xiàn)的是SortedSet接口,也就是加入了對(duì)象比較的方法。通過對(duì)集中的對(duì)象迭代,我們可以得到一個(gè)升序的對(duì)象集合。

          (2)列表 (List):列表
          列表的主要特征是其對(duì)象以線性方式存儲(chǔ),沒有特定順序,只有一個(gè)開頭和一個(gè)結(jié)尾,當(dāng)然,它與根本沒有順序的集是不同的。
          列表在數(shù)據(jù)結(jié)構(gòu)中分別表現(xiàn)為:數(shù)組和向量、鏈表、堆棧、隊(duì)列。
          關(guān)于實(shí)現(xiàn)列表的集合類,是我們?nèi)粘9ぷ髦薪?jīng)常用到的,將在后邊的筆記詳細(xì)介紹。

          (3)映射 (Map):鍵值對(duì)
          映射與集或列表有明顯區(qū)別,映射中每個(gè)項(xiàng)都是成對(duì)的。映射中存儲(chǔ)的每個(gè)對(duì)象都有一個(gè)相關(guān)的關(guān)鍵字(Key)對(duì)象,關(guān)鍵字決定了對(duì)象在映射中的存儲(chǔ)位置,檢索對(duì)象時(shí)必須提供相應(yīng)的關(guān)鍵字,就像在字典中查單詞一樣。關(guān)鍵字應(yīng)該是唯一的。
          關(guān)鍵字本身并不能決定對(duì)象的存儲(chǔ)位置,它需要對(duì)過一種散列(hashing)技術(shù)來處理,產(chǎn)生一個(gè)被稱作散列碼(hash code)的整數(shù)值,散列碼通常用作一個(gè)偏置量,該偏置量是相對(duì)于分配給映射的內(nèi)存區(qū)域起始位置的,由此確定關(guān)鍵字/對(duì)象對(duì)的存儲(chǔ)位置。理想情況下,散列處理應(yīng)該產(chǎn)生給定范圍內(nèi)均勻分布的值,而且每個(gè)關(guān)鍵字應(yīng)得到不同的散列碼。

          集合類簡(jiǎn)介
          java.util中共有13個(gè)類可用于管理集合對(duì)象,它們支持集、列表或映射等集合,以下是這些類的簡(jiǎn)單介紹

          集:
          HashSet: 使用HashMap的一個(gè)集的實(shí)現(xiàn)。雖然集定義成無序,但必須存在某種方法能相當(dāng)高效地找到一個(gè)對(duì)象。使用一個(gè)HashMap對(duì)象實(shí)現(xiàn)集的存儲(chǔ)和檢索操作是在固定時(shí)間內(nèi)實(shí)現(xiàn)的.
          TreeSet: 在集中以升序?qū)?duì)象排序的集的實(shí)現(xiàn)。這意味著從一個(gè)TreeSet對(duì)象獲得第一個(gè)迭代器將按升序提供對(duì)象。TreeSet類使用了一個(gè)TreeMap.
          列表:
          Vector: 實(shí)現(xiàn)一個(gè)類似數(shù)組一樣的表,自動(dòng)增加容量來容納你所需的元素。使用下標(biāo)存儲(chǔ)和檢索對(duì)象就象在一個(gè)標(biāo)準(zhǔn)的數(shù)組中一樣。你也可以用一個(gè)迭代器從一個(gè)Vector中檢索對(duì)象。Vector是唯一的同步容器類??當(dāng)兩個(gè)或多個(gè)線程同時(shí)訪問時(shí)也是性能良好的。(同步的含義:即同時(shí)只能一個(gè)進(jìn)程訪問,其他等待)
          Stack: 這個(gè)類從Vector派生而來,并且增加了方法實(shí)現(xiàn)棧??一種后進(jìn)先出的存儲(chǔ)結(jié)構(gòu)。
          LinkedList: 實(shí)現(xiàn)一個(gè)鏈表。由這個(gè)類定義的鏈表也可以像棧或隊(duì)列一樣被使用。
          ArrayList: 實(shí)現(xiàn)一個(gè)數(shù)組,它的規(guī)??勺儾⑶夷芟矜湵硪粯颖辉L問。它提供的功能類似Vector類但不同步。
          映射:
          HashTable: 實(shí)現(xiàn)一個(gè)映象,所有的鍵必須非空。為了能高效的工作,定義鍵的類必須實(shí)現(xiàn)hashcode()方法和equal()方法。這個(gè)類是前面java實(shí)現(xiàn)的一個(gè)繼承,并且通常能在實(shí)現(xiàn)映象的其他類中更好的使用。
          HashMap: 實(shí)現(xiàn)一個(gè)映象,允許存儲(chǔ)空對(duì)象,而且允許鍵是空(由于鍵必須是唯一的,當(dāng)然只能有一個(gè))。
          WeakHashMap: 實(shí)現(xiàn)這樣一個(gè)映象:通常如果一個(gè)鍵對(duì)一個(gè)對(duì)象而言不再被引用,鍵/對(duì)象對(duì)將被舍棄。這與HashMap形成對(duì)照,映象中的鍵維持鍵/對(duì)象對(duì)的生命周期,盡管使用映象的程序不再有對(duì)鍵的引用,并且因此不能檢索對(duì)象。
          TreeMap: 實(shí)現(xiàn)這樣一個(gè)映象,對(duì)象是按鍵升序排列的。

          下圖是集合類所實(shí)現(xiàn)的接口之間的關(guān)系:
          Set和List都是由公共接口Collection擴(kuò)展而來,所以它們都可以使用一個(gè)類型為Collection的變量來引用。這就意味著任何列表或集構(gòu)成的集合都可以用這種方式引用,只有映射類除外(但也不是完全排除在外,因?yàn)榭梢詮挠成浍@得一個(gè)列表。)所以說,把一個(gè)列表或集傳遞給方法的標(biāo)準(zhǔn)途徑是使用Collection類型的參數(shù)。

          List接口
          List是有序的Collection,使用此接口能夠精確的控制每個(gè)元素插入的位置。用戶能夠使用索引(元素在List中的位置,類似于數(shù)組下標(biāo))來訪問List中的元素,這類似于Java的數(shù)組。
          和下面要提到的Set不同,List允許有相同的元素。
          除了具有Collection接口必備的iterator()方法外,List還提供一個(gè)listIterator()方法,返回一個(gè)ListIterator接口,和標(biāo)準(zhǔn)的Iterator接口相比,ListIterator多了一些add()之類的方法,允許添加,刪除,設(shè)定元素,還能向前或向后遍歷。
          實(shí)現(xiàn)List接口的常用類有LinkedList,ArrayList,Vector和Stack。
          ArrayList類
          ArrayList實(shí)現(xiàn)了可變大小的數(shù)組。它允許所有元素,包括null。ArrayList沒有同步。
          size,isEmpty,get,set方法運(yùn)行時(shí)間為常數(shù)。但是add方法開銷為分?jǐn)偟某?shù),添加n個(gè)元素需要O(n)的時(shí)間。其他的方法運(yùn)行時(shí)間為線性。
          每個(gè)ArrayList實(shí)例都有一個(gè)容量(Capacity),即用于存儲(chǔ)元素的數(shù)組的大小。這個(gè)容量可隨著不斷添加新元素而自動(dòng)增加,但是增長(zhǎng)算法并沒有定義。ArrayList當(dāng)需要插入大量元素時(shí),在插入前可以調(diào)用ensureCapacity方法來增加ArrayList的容量以提高插入效率。
          和LinkedList一樣,ArrayList也是非同步的(unsynchronized)。
          Map接口
          請(qǐng)注意,Map沒有繼承Collection接口,Map提供key到value的映射。一個(gè)Map中不能包含相同的key,每個(gè)key只能映射一個(gè)value。Map接口提供3種集合的視圖,Map的內(nèi)容可以被當(dāng)作一組key集合,一組value集合,或者一組key-value映射。
          HashMap類
          HashMap和Hashtable類似,不同之處在于HashMap是非同步的,并且允許null,即null value和null key。,但是將HashMap視為Collection時(shí)(values()方法可返回Collection),其迭代子操作時(shí)間開銷和HashMap的容量成比例。因此,如果迭代操作的性能相當(dāng)重要的話,不要將HashMap的初始化容量設(shè)得過高,或者load factor過低。
          ----------------------------------------------------------------------------
          1.-------------------->
          List是接口,List特性就是有序,會(huì)確保以一定的順序保存元素.
          ArrayList是它的實(shí)現(xiàn)類,是一個(gè)用數(shù)組實(shí)現(xiàn)的List.
          Map是接口,Map特性就是根據(jù)一個(gè)對(duì)象查找對(duì)象.
          HashMap是它的實(shí)現(xiàn)類,HashMap用hash表實(shí)現(xiàn)的Map,就是利用對(duì)象的hashcode(hashcode()是Object的方法)進(jìn)行快速(Hash)散列查找.(關(guān)于散列查找,可以參看<<數(shù)據(jù)結(jié)構(gòu)>>)
          2.-------------------->
          一般情況下,如果沒有必要,推薦代碼只同List,Map接口打交道.
          比如:List list = new ArrayList();
          這樣做的原因是list就相當(dāng)于是一個(gè)泛型的實(shí)現(xiàn),如果想改變list的類型,只需要:
          List list = new LinkedList();//LinkedList也是List的實(shí)現(xiàn)類,也是ArrayList的兄弟類
          這樣,就不需要修改其它代碼,這就是接口編程的優(yōu)雅之處.
          另外的例子就是,在類的方法中,如下聲明:
          private void doMyAction(List list){}
          這樣這個(gè)方法能處理所有實(shí)現(xiàn)了List接口的類,一定程度上實(shí)現(xiàn)了泛型函數(shù).
          3.--------------------->
          如果開發(fā)的時(shí)候覺得ArrayList,HashMap的性能不能滿足你的需要,可以通過實(shí)現(xiàn)List,Map(或者Collection)來定制你的自定義類

          posted @ 2012-03-20 21:40 paulwong 閱讀(1442) | 評(píng)論 (0)編輯 收藏

          業(yè)務(wù)系統(tǒng)與工作流系統(tǒng)

          通常工作流系統(tǒng)是獨(dú)立的一個(gè)系統(tǒng),必須以業(yè)務(wù)系統(tǒng)和工作流系統(tǒng)的觀點(diǎn)才能比較好的理解業(yè)務(wù)系統(tǒng)。工作流系統(tǒng)負(fù)責(zé)節(jié)點(diǎn)的流轉(zhuǎn),即狀態(tài)的改變。

          1. 業(yè)務(wù)系統(tǒng)如果增加一個(gè)業(yè)務(wù)對(duì)象,須增加一堆的服務(wù)方法,工作流系統(tǒng)面向的是流程,增加流程無需增加代碼,因此啟動(dòng)流程的第一步,就要業(yè)務(wù)系統(tǒng)告訴工作流系統(tǒng)要管理哪個(gè)流程,即流程ID,然后工作流系統(tǒng)就記錄下此流程實(shí)例
          2. 工作流系統(tǒng)面向的是流程配置文件,即bpmn20.xml,用TASK表示業(yè)務(wù)系統(tǒng)中的步驟,如果這一節(jié)點(diǎn)為USER TASK,則表示工作流系統(tǒng)會(huì)等待業(yè)務(wù)系統(tǒng)的觸發(fā)而改變狀態(tài),業(yè)務(wù)系統(tǒng)會(huì)向客戶端展示頁面,收集信息并驗(yàn)證通過后才讓工作流系統(tǒng)改變流程實(shí)例的狀態(tài);如果是自動(dòng)任務(wù),則工作流系統(tǒng)會(huì)自行改變狀態(tài),流轉(zhuǎn)到下一節(jié)點(diǎn)。
          3. 由于處理USER TASK時(shí),需業(yè)務(wù)系統(tǒng)自行判斷,因此新增業(yè)務(wù)對(duì)象(表單)時(shí),需新增業(yè)務(wù)代碼,有別于OA系統(tǒng),新增表單時(shí),不用新增代碼。
          4. USER TASK中允許配有頁面展示的鏈接,業(yè)務(wù)系統(tǒng)可以從這里取得鏈接而返回給客戶端。靜態(tài)網(wǎng)頁處理時(shí),只需向客戶端傳實(shí)體HTML文件,由客戶端解釋成文本內(nèi)容,動(dòng)態(tài)網(wǎng)頁實(shí)際上由服務(wù)器端生成文本內(nèi)容再發(fā)給客戶端。

          posted @ 2012-03-20 10:26 paulwong 閱讀(454) | 評(píng)論 (0)編輯 收藏

          基于注解的SpringMVC+freemarker環(huán)境搭建

          1. 首先用IDE建一個(gè)web工程。(這個(gè)就不詳細(xì)介紹了)
          2. 引入響應(yīng)的jar包
          3. web.xml
            <?xml version="1.0" ?>
            <web-app xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                xsi:schemaLocation
            ="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
                version
            ="3.0">
                
            <!--  Spring 服務(wù)層的配置文件 -->
                
            <context-param>
                    
            <param-name>contextConfigLocation</param-name>
                    
            <param-value>classpath:applicationContext.xml</param-value>
                
            </context-param>
                
                
            <!--  Spring 容器啟動(dòng)監(jiān)聽器 -->
                
            <listener>
                    
            <listener-class>org.springframework.web.context.ContextLoaderListener
                    
            </listener-class>
                
            </listener>

                
            <servlet>
                    
            <servlet-name>springmvc</servlet-name>
                    
            <servlet-class>org.springframework.web.servlet.DispatcherServlet
                    
            </servlet-class>
                    
            <load-on-startup>1</load-on-startup>
                
            </servlet>
                
            <!--為DispatcherServlet建立映射 -->
                
            <servlet-mapping>
                    
            <servlet-name>springmvc</servlet-name>
                    
            <url-pattern>/</url-pattern>
                
            </servlet-mapping>
            </web-app>

          4. SpringMVC另外一個(gè)重要的配置文件。
            DispatcherServlet會(huì)根絕web.xml中配置的<servlet-name>去找<servlet-name>-servlet.xml的文件來加載spring的一些配置信息。我這里就應(yīng)該取名叫springmvc-servlet.xml
            <?xml version="1.0" encoding="UTF-8"?>
            <beans 
                
            xmlns="http://www.springframework.org/schema/beans" 
                xmlns:xsi
            ="http://www.w3.org/2001/XMLSchema-instance"
                xmlns:p
            ="http://www.springframework.org/schema/p" 
                xmlns:context
            ="http://www.springframework.org/schema/context"
                xsi:schemaLocation
            ="http://www.springframework.org/schema/beans 
                http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
                http://www.springframework.org/schema/context 
                http://www.springframework.org/schema/context/spring-context-2.5.xsd"
            >
                
                
            <!--對(duì)web包中的所有類進(jìn)行掃描,以完成Bean創(chuàng)建和自動(dòng)依賴注入的功能 -->
                
            <context:component-scan base-package="com.liba.spring.mvc"/>
                
                
            <!-- 啟動(dòng)Spring MVC的注解功能,完成請(qǐng)求和注解POJO的映射   請(qǐng)求映射-->
                
            <bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter" />
                
                    
            <!--以下三種視圖配置根據(jù)需要任選一種即可 -->

                
            <!--  一般的視圖配置 -->
                
            <!--<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" 
                    p:prefix="/WEB-INF/view/" p:suffix=".jsp"/>
            -->
                
                
            <!-- 針對(duì)freemarker的視圖配置 -->
                
            <bean id="viewResolver"
                    class
            ="org.springframework.web.servlet.view.freemarker.FreeMarkerViewResolver">
                    
            <property name="cache" value="true" />
                    
            <property name="prefix" value="" />
                    
            <property name="suffix" value=".ftl" />
                    
            <property name="contentType" value="text/html;charset=UTF-8"></property>
                    
            <property name="requestContextAttribute" value="request" />
                    
            <property name="exposeSpringMacroHelpers" value="true" />
                    
            <property name="exposeRequestAttributes" value="true" />
                    
            <property name="exposeSessionAttributes" value="true" />
                
            </bean>
                    
                    
                
            <!-- View resolvers can also be configured with ResourceBundles or XML files. 
                    If you need different view resolving based on Locale, you have to use the 
                    resource bundle resolver. 
            -->
                
            <!-- 這個(gè)是針對(duì)返回視圖還是json值的視圖配置   來分別處理同步和異步請(qǐng)求 -->
                
            <!--<bean
                        class="org.springframework.web.servlet.view.ContentNegotiatingViewResolver">
                        <property name="mediaTypes">
                            <map>
                                <entry key="html" value="text/html" />
                                <entry key="json" value="application/json" />
                            </map>
                        </property>
                        <property name="favorParameter" value="true" />
                        <property name="viewResolvers">
                            <list>
                                <bean class="org.springframework.web.servlet.view.BeanNameViewResolver" />
                                <bean id="viewResolver"
                                    class="org.springframework.web.servlet.view.freemarker.FreeMarkerViewResolver">
                                    <property name="cache" value="true" />
                                    <property name="prefix" value="" />
                                    <property name="suffix" value=".ftl" />
                                    <property name="contentType" value="text/html;charset=UTF-8"></property>
                                    <property name="requestContextAttribute" value="request" />
                                    <property name="exposeSpringMacroHelpers" value="true" />
                                    <property name="exposeRequestAttributes" value="true" />
                                    <property name="exposeSessionAttributes" value="true" />
                                </bean>
                            </list>
                        </property>
                        <property name="defaultContentType" value="text/html" />
                    </bean>
                    
            -->
            </beans>

          5. 如果是使用freemarker最為視圖模板需要再spring的配置文件applicationContext.xml中加入以下配置
            <bean id="freemarkerConfig"
                    class
            ="org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer">
                    
            <property name="templateLoaderPath" value="/WEB-INF/view/" />
                    
            <property name="freemarkerSettings">
                        
            <props>
                            
            <prop key="template_update_delay">0</prop>
                            
            <prop key="default_encoding">UTF-8</prop>
                            
            <prop key="number_format">0.##########</prop>
                            
            <prop key="datetime_format">yyyy-MM-dd HH:mm:ss</prop>
                            
            <prop key="classic_compatible">true</prop>
                            
            <prop key="template_exception_handler">ignore</prop>
                        
            </props>
                    
            </property>
                
            </bean>

          6. Controller建立
            import javax.servlet.http.HttpServletRequest;

            import org.springframework.stereotype.Controller;
            import org.springframework.web.bind.annotation.RequestMapping;
            import org.springframework.web.bind.annotation.RequestMethod;
            import org.springframework.web.servlet.ModelAndView;

            @Controller
            public class SpringMvcController {

                @RequestMapping(value
            ="/welcome",method={RequestMethod.GET}
                
            public ModelAndView getFirstPage(HttpServletRequest request) {
                            
            //welcom就是視圖的名稱(welcom.ftl)
                    ModelAndView mv = new ModelAndView("welcom");
                    mv.addObject(
            "name""My First Spring Mvc");
                    
            return mv;
                }

            }
            在url上敲http://localhost:8080/welcome就會(huì)到WEB-INF/view/welcom.ftl頁面渲染數(shù)據(jù)
          7. welcom.ftl頁面
            <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
            <html>
            <head>
            <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
            <title>Insert title here</title>
            </head>
            <body>
            Hello ${name}
            </body>
            </html>

            頁面出來的效果:

            Hello My First Spring Mvc








          posted @ 2012-03-19 21:32 paulwong 閱讀(25894) | 評(píng)論 (3)編輯 收藏

          架構(gòu)師的素質(zhì)

          架構(gòu)師最基本的素質(zhì),總結(jié)出兩點(diǎn),1是技術(shù)知識(shí)廣度,2是業(yè)務(wù)行業(yè)深度。


          1 架構(gòu)師是技術(shù)領(lǐng)導(dǎo)。
          架構(gòu)師必須要有技術(shù),而且還是領(lǐng)導(dǎo)。架構(gòu)師要帶領(lǐng)自己團(tuán)隊(duì)完成自己的任務(wù),完全憑借自己的能力做事情,完全是匹夫之勇,根本不提倡。

          2 架構(gòu)師理解軟件流程。
          架構(gòu)師必須了解軟件流程,否則無法驅(qū)動(dòng)整個(gè)團(tuán)隊(duì)前進(jìn),如果一個(gè)架構(gòu)師不熟悉開發(fā)流程,無法協(xié)調(diào)產(chǎn)品線相關(guān)人員進(jìn)行高效工作,也無法指導(dǎo)團(tuán)隊(duì)成員完成自己的工作。所以來說架構(gòu)師一般不是空降兵(除非是全新的部門),因?yàn)榭战当话悴粫?huì)熟悉新公司的開發(fā)流程,即使是同一個(gè)行業(yè)的,各個(gè)公司的差別還是很大。所以說聽說某某去某某公司做首席架構(gòu)師或者首席科學(xué)家,一般是高風(fēng)險(xiǎn)的事情,即使他對(duì)這個(gè)行業(yè)很了解。

          3 架構(gòu)師必須熟悉業(yè)務(wù)領(lǐng)域。
          如果一個(gè)架構(gòu)師不熟悉自己的行業(yè),做的架構(gòu)就是紙上談兵,熟悉業(yè)務(wù)領(lǐng)域的架構(gòu)師,才能很好的理解需求,做出合適的方案?;ヂ?lián)網(wǎng)和網(wǎng)絡(luò)安全是完全不同的兩個(gè)方向,即使你熟悉里面的各種具體技術(shù),但是以互聯(lián)網(wǎng)的架構(gòu)來做網(wǎng)絡(luò)安全產(chǎn)品,肯定是100%的失敗。
          我做PKI的時(shí)候,項(xiàng)目最初的使用.net,使用微軟的crytoAPI,開發(fā)的很順利。后來來了一位新的架構(gòu)師,覺得.net不能跨平臺(tái),決定?用java,做出產(chǎn)品后,發(fā)現(xiàn)找不到arm cpu的jdk,使用平臺(tái)有限。再次決定使用openssl做,最后這個(gè)項(xiàng)目以失敗而告終。后來我想過arm cpu都是嵌入式設(shè)備用的,根本沒有任何嵌入式設(shè)備提供CA服務(wù)。

          4 架構(gòu)師必須要有廣度的知識(shí)。
          架構(gòu)師考慮的問題必須全面,必須了解的要廣,具體的細(xì)節(jié)可以不關(guān)注,因?yàn)榧?xì)節(jié)變化很快。很多具體技術(shù)人員出身的架構(gòu)師,只關(guān)注于具體的細(xì)節(jié),某些方面做的很好,整體的性能很差。
          下面這個(gè)項(xiàng)目的成功可以理解為一個(gè)笑話。某公司的兩個(gè)部門都做c程序的,A部門做的平臺(tái)使用的x86和mips,B部門使用平臺(tái)是x86和 arm,后來A部門的一個(gè)模塊要給B部門用,最后發(fā)現(xiàn)根本不能運(yùn)行。最后A部門發(fā)現(xiàn)arm平臺(tái)使用big endian模式,這樣A部門的20多名員工,檢查代碼中所有非零整數(shù),經(jīng)過數(shù)個(gè)月苦戰(zhàn),才修改完畢。其實(shí)解決方法很簡(jiǎn)單,因B部門的代碼也是首先在 x86做的,做的時(shí)候他們考慮了cpu的endian模式。這并不能說B部門架構(gòu)師很牛,從另一個(gè)方面說他的無知。因?yàn)榘遄佑刑€,專門切換cpu的是 big endian還是little endian,這樣兩個(gè)部門都可以不修改程序。

          5 架構(gòu)師必須是寫程序的高手。
          架構(gòu)師一般都是?發(fā)人員出身,一般都是團(tuán)隊(duì)的核心。優(yōu)秀的架構(gòu)師應(yīng)該了解團(tuán)隊(duì)使用各種技術(shù),有了這些知識(shí),才能和開發(fā)人軟進(jìn)行有效溝通。
          有一個(gè)項(xiàng)目架構(gòu)使用xml做配置,因?yàn)椴《編旌荦嫶?,最后?dǎo)致xml 達(dá)30多兆,服務(wù)端的java程序使用dom 進(jìn)行過濾的時(shí)候,30兆xml加載很慢,頻繁出現(xiàn)out of memory。這個(gè)項(xiàng)目后來擱淺。根據(jù)以前的經(jīng)驗(yàn)發(fā)現(xiàn) msxml加載30多M的xml 不過幾秒,而且msxml的xpath速度很快,后來專門為此寫了JNI處理xml的。

          6架構(gòu)師是優(yōu)秀的溝通人員。
          架構(gòu)師一定要會(huì)忽悠,至少要扯淡。架構(gòu)師不但要指導(dǎo)本部門員工的工作,也要協(xié)調(diào)其他部門的資源,還要向用戶收集需求,制定規(guī)格說明書,重要的把用戶的不合理要求砍掉,合理需求遵循自己的思路

          posted @ 2012-03-19 02:21 paulwong 閱讀(296) | 評(píng)論 (0)編輯 收藏

          僅列出標(biāo)題
          共115頁: First 上一頁 85 86 87 88 89 90 91 92 93 下一頁 Last 
          主站蜘蛛池模板: 儋州市| 霍林郭勒市| 乌海市| 高安市| 青川县| 翼城县| 洮南市| 阳春市| 石景山区| 双峰县| 喀什市| 襄垣县| 庆云县| 普格县| 若羌县| 皋兰县| 涿州市| 阳高县| 绥化市| 岱山县| 镇沅| 姜堰市| 寻乌县| 上饶县| 定兴县| 长沙县| 乌海市| 宁明县| 宾阳县| 保德县| 常宁市| 屏东县| 安义县| 梧州市| 桃园市| 榆社县| 衡阳县| 东平县| 丹棱县| 阳朔县| 平阴县|