FTP (File Transfer Protocol) is a common way of moving files between computers. By default your RimuHosting server will not have FTP enabled.
Do you really need to run FTP? For example, if you are going to be the only person moving files to and from your server, then you may not need it. Try our scp howto instead.
To enable FTP, first edit the vsftpd.conf file (e.g. vi /etc/vsftpd/vsftpd.conf
). Then:
Then create a non-super user that vsftp will run as. Note: this is not the FTP username you'll use when logging into your FTP server.
# create an unpriviledged user that will run the vsftpd service
adduser -s /sbin/nologin ftpsecure
sed --in-place 's/^anonymous_enable=YES/anonymous_enable=NO/ig' /etc/vsftpd/vsftpd.conf
sed --in-place 's/^anon_upload_enable=YES/anon_upload_enable=NO/ig' /etc/vsftpd/vsftpd.conf
Then, most redhat distributions you can then run:
chkconfig --level 35 vsftpd on && /etc/init.d/vsftpd start
Or, on a RedHat 8 distribution:
vi /etc/xinetd.d/vsftpd
# ... and change the disable = yes to disable = no
# then restart xinetd
/etc/init.d/xinetd restart
The ftp daemon will not let you log in as root (?why?). Try a log in as a non-super user. To create such a user:
# add the user, use the -s (shell) option if you do not want the
# user to be able to ssh into the server (else skip it)
adduser -s /sbin/nologin yourusername
passwd yourusername
# you will be prompted for a password
# now, log in to your ftp server using this username and password
By default FTP users can read and write files any files on the server, provided they have access to read/write those files.
You can also set things up so that FTP users only see files under their home
directory. This can often be a more secure setup. To do this just
add chroot_local_user=YES
in vsftpd.conf (and restart vsftpd). e.g.
sed --in-place 's/^anonymous_enable=YES/anonymous_enable=NO/ig' /etc/vsftpd/vsftpd.conf
sed --in-place 's/^anon_upload_enable=YES/anon_upload_enable=NO/ig' /etc/vsftpd/vsftpd.conf
if ! test -e /etc/vsftpd/vsftpd.conf; then
echo /etc/vsftpd/vsftpd.conf not found
elif grep -qai chroot_local_user=YES /etc/vsftpd/vsftpd.conf; then
echo "chroot_local_user directive already existed"
else
echo "Adding the chroot_local_user directive"
echo "chroot_local_user=YES" >> /etc/vsftpd/vsftpd.conf
fi
/etc/init.d/vsftpd restart
When a user logs in, if there directory was /home/user/html, they would see /html. They're locked into /home/user, and /home/user becomes their root (/) directory.
讀者定位為具有 Java 和 Ant 使用經驗的開發人員。
讀者可以學習到如何使用 Ant 解決一些多用戶開發環境中,根據不同的目標環境編譯成不同部署包的問題。
現在有一個 web 項目,是多人進行開發的,通過 CVS 來管理。另外該項目還有一些測試人員,他們測試部署在測試服務器上的應用程序,發現 bug 后通過 bug 管理系統通知開發人員,在開發人員修復 bug 并經過本地測試后,由專門的人負責檢出(check out)代碼,編譯打包后部署到測試服務器上。
該項目的成員小A就是負責檢出代碼、編譯打包,并部署到服務器上的人。除了這個任務之外,他還是該項目的編程人員。在項目進入測試階段后,小A在得到組中別的成員修復了 bug 并且檢入(check in)了代碼的消息后(也有可能是小A自己檢入了代碼),小A首先更新本地的代碼,先在本地做測試,確認修復了 bug 后打成 WAR 包部署到測試服務器上,并通知測試人員已經修復了 bug,讓測試人員繼續進行測試。
在該項目中,有一些為測試方便開發而寫的代碼和頁面,比如跳過用戶認證,但是在部署到測試機環境的時候,需要刪除這些代碼和頁面;另外作為一個具有靈活性和擴展性的應用程序,又有一些配置文件,配置文件中的值會根據環境的改變而變動。例如,在項目中使用了 Log4j 記錄日志,需要給 Log4j 指定日志文件的保存路徑,本地程序員開發的時候用的是 Windows 系統,給 Log4j 指定的也是 Windows 的文件系統,在測試階段的時候,需要部署到 Linux 系統中,那么日志的保存路徑也需要做相應的改動。部署到測試服務器上的時候,除了 Log4j 需要改之外,還有很多別的配置項目也需要變動,并且分散在各個 package 中。小A的煩惱也隨之而來,每次他在做完本地測之后,就根據測試機的需要逐個找配置文件,更改相應的值,并刪除那些為測試方便寫的代碼和頁面,每天可能根據需要做好幾次這樣的事情,最煩的是他在快做完對測試機環境更改的時候,某開發人員突然通知小A說:“我又改了一點代碼,剛檢入,你再重打一個包吧。”,小A又不得不從頭開始做新一輪的檢出代碼、本地測試、更改配置文件、刪除不需要的文件、打包部署的工作。另外小A在測試階段的后期被通知要求除了每次生成一個測試環境的 WAR 包外還必須生成一個在產品環境下的 WAR 包,他做的事情就更多了。
從上面的場景可以看出,小A的工作效率低而且容易出錯,甚至有可能導致整個項目的工作效率低下。其實可以通過 Ant 來幫助小A快速而且有效地完成這個工作。在 Ant 中,根據目標環境的需要,可以把所有要更改的配置文件的項目集中寫到某個配置文件中。這樣根據不同的目標環境得到不同的配置文件,Ant 在編譯包時根據不同的目標環境切換不同的配置文件即可。比如小A現在碰到的有 3 中環境:開發環境、測試環境以及產品環境,根據這三種環境可以生成三個不同的配置文件:develop_deploy.property、test_deploy. property和product_deploy. property,當小A想生成不同的包時只需在這三個配置文件之間切換就可以了。
在正式開始編寫腳本之前,我們需要下載安裝相應的軟件。
![]() ![]() |
![]()
|
如果你使用 Eclipse 來編寫 Ant,建議使用 Eclipse 3.1 以后的版本。除了以前 Ant 編輯器提供的語法高亮,提示語法錯誤等功能外,Eclipse3.1 版本增加了許多新的功能。比如:腳本代碼的折疊;快速定位某屬性或者目標(target)段的定義;在同一 builder 文件中重構屬性名和目標名(快捷方式Alt + Shift +R);調試 Ant 腳本等。
下面我們就來看看 Eclipse 3.1 中對 Ant 的支持
打開“File”-“New”-“Project”-“Simple”-“Project”,點擊“Next”,輸入工程名“Ant”,然后點擊直到“Finish”
在新建的 Ant 工程中,新建 Test.xml,并且拷貝下面的腳本。該段腳本的內容就不做介紹了,我們主要看 Eclipse 提供了哪些功能。注意這時候打開的并不是 Ant 編輯器,將內容拷貝進去之后,關掉打開的“Test.xml”,然后再重新打開它,這樣 Eclipse 就會用 Ant 編輯器打開它,并且也語法高亮了。
|
自動提示和代碼折疊功能。如果是 Ant 內置的命令或者前面已經定義的變量,編輯器會自動提示;編輯器右邊的加/減號可以代碼折疊。如下所示:
快速定位目標(target)或者定義變量處。在上圖中,將鼠標移至 default=”init” 中的 init 上之后,按下 ctrl 鍵,鼠標變成手狀,單擊就可以定位到定義該目標的地方
快速重構目標名或者屬性名。選中目標/屬性名,按下 Alt + Shift + R,然后鍵入你要修改后的值,所有引用到的地方都會隨之改動。如下圖所示,選中 init 后,按下快捷鍵,改成 initial:
調試 Ant 腳本。在標簽“<target name=..”的左邊設置一斷點,然后在編輯器中右擊,出現的菜單中選“Debug As”-“Ant Build”,出現后的窗口與調試 Java 程序的界面差不多。
這是調試窗口,這里可以選擇單步跟進、跳出等:
下面是運行時變量窗口。可以看到 test 變量的值是“test”:
運行結果窗口:
由此可見,如果使用好 Eclipse Ant 編輯器所提供強大的功能的話能大大提高寫 Ant 腳本的效率。
![]() ![]() |
![]()
|
剛開始寫 Ant 的初學者可能會把所有的信息都放在 build.xml 中,下面就是這樣的一個例子。
|
在上面的例子中,所有的路徑信息都是寫在 build.xml 中。但是 Ant 腳本可能在不同的機器或者不同的系統上運行,也有可能一些值需要根據環境的不同而變化,在 Ant 中可以把所有這些可能變化的地方都放到一個配置文件中,然后在 Ant 腳本中引用這個配置文件就可以了,針對上面的例子,如下所示:
|
如果想在 Ant 腳本中引用值的話,只需用$符號開頭,在一對'{}'中寫入要引用的鍵值。如上例中,需要引用編譯的目標路徑用'${dest.dir}'。
![]() ![]() |
![]()
|
使用 Ant 任務從 CVS 中檢出(check out)源代碼,并編譯打包
Ant 中提供了 cvs 任務(Task)可以從 CVS 服務器中檢出資源(注意:在使用 Ant 的 cvs 任務之前,請先將 cvs.exe 下載到你的機器,并且將它添加到你本地的 PATH 環境變量中,然后重新啟動 Eclipse。否則在執行下面腳本的時候就會得到 error=2 的錯誤)。cvs 的可選用屬性很多,在這里介紹經常使用到的幾個屬性。從 CVS 中檢出資源一般需要指定:
在介紹使用 Ant 的 cvs 之前,先說一下本地的目錄結構。在 C 盤的 temp 目錄下,分別有四個目錄,如下所示:
在 Ant 中這樣寫就可以從中檢出資源:
|
這段腳本片斷的意思就是從叫'cvs.server'的服務器中,用用戶名是 username、密碼為 pwd 的用戶檢出在庫路徑是 /home/testPath 下的 TestProj 模塊(項目),檢出后的資源放入本地目錄 c:/temp/src/testProj 中。在上面這段腳本中,可以看到有很多值可能會根據不同的環境或者用戶隨之改變的,比如用戶名和密碼等;而且從腳本的重復可利用性來說,需要把有些值抽出來放到配置文件中,如服務器的地址和庫路徑等。因此把這些可能需要更改的地方放到 property 文件中,效果會更好。改完后的完整 Ant 腳本如下所示:
|
對應的 TestWeb.properties 文件內容如下所示:
|
在檢出了資源后,需要對其進行編譯打包。為了使 Ant 腳本更加具有可讀性和靈活性,我們需要對上面的 Ant 腳本進行一些改動。首先將 Ant 腳本中進行分段,如下所示:
|
上面的腳本中,總共分成了5個目標(target),腳本的入口點是'all',all 按順序調用 init,clean,checkout,build。其中:
詳細的 Ant 腳本可以參見隨本文所附的 TestWeb.xml 和 TestWeb.properties。
![]() ![]() |
![]()
|
在前面介紹的 Ant 腳本中,根據從 CVS 服務器中檢出的資源打成了一個默認的 war 包,并沒有考慮根據不同的目標環境來生成不同的包,從下一節開始介紹如何根據不同的環境來生成不同的部署包。
還有一個問題是:為什么需要把從 CVS 中檢出資源、編譯的過程跟根據目標環境打包的過程分開?
這是因為本身 CVS 檢出資源是需要花一定的時間,如果資源比較多這個過程就會花費挺長時間;另外,在多人開發的情況下必須保證在生成不同的部署包的時候是用的是同一套代碼生成的,否則會出現各個服務器上運行的版本不一致,如果檢出資源、編譯的過程跟生成包的腳本一起執行的話就會出現這個問題(比如小A在測試服務器測試通過的時候之后,再生成一個在產品環境下的部署包,如果分兩次從 CVS 服務器中檢出資源的話,在此期間可能會有開發人員往 CVS 服務器中檢入代碼,導致生成的版本不一致),因此,必須將這兩個過程分開執行。現在我們開始建立另外一個 Ant 腳本文件,叫 deploy.xml,專門用來生成包;另外與 deploy.xml 相對應的還有一個 deploy.properties 文件。在 deploy.xml 中會引用 deploy.properties 文件。另外根據在前面的場景中碰到的環境,創建三個不同的屬性文件, develop_deploy.property、test_deploy. property 和 product_deploy. Property,在打包的時候,根據不同的目標環境,將相應屬性文件中的內容拷貝至 deploy.properties 文件中(或者也可以直接在 deploy.xml 中直接切換不同的屬性文件),然后在 Eclipse 中直接執行 deploy.xml;如果在命令行中,可以用下面的命令來執行:
|
![]() ![]() |
![]()
|
我們首先得建立一個目錄(這里是 unpack)用來存放解壓后的文件。Ant 中提供了 unzip 命令用來解壓 ear/war/jar 包。除了這個目錄外,根據不同的目標環境,在運行目錄下建立一個與目標環境相對應的目錄,重新打好的 war 包就放在這個目錄下,比如針對場景中的情況,如果需要創建一個產品環境下的部署包,我們可以建立一個 TestWebProduct 目錄,目錄名寫在配置文件中(${pack.base.dir})。
|
在 init 段中首先刪除掉上次解壓的目錄和目標打包目錄,然后重新建立目錄;在 unpack 中,首先將編譯好的默認 war 包拷貝至 unpack 定義的目錄,解壓之后把 unpack 下的 war 包刪除。下面是這時候對應的屬性文件。
|
![]() ![]() |
![]()
|
現在根據不同環境的需要,對某些配置文件的值做一些替換。在 Ant 中,提供了 filter 任務,使得替換值很方便。當然也可以使用下面介紹的正則表達式來替換屬性值。filter 主要用來在同一行內容中的替換,而正則表達式一下子可以替換多行內容。filter 的使用例子:
|
這段腳本的意思就是在 src.dir 目錄下的所有文件中,如果有預先定義好的'@log4j.logger@'占位符的話,在拷貝到 dest.dir 目錄后,所有的占位符都被替換成了'INFO'。
你也可以將所有被替換的值放到某個屬性文件中,filter 任務將屬性文件中的每一個條目讀出來并且設置成一個 Filter。如下所示:
|
上面的腳本表示所有在 deploy_env 中出現的條目將被作為一個 filter,在拷貝到 dest.dir 目錄后,所有 src.dir 目錄中存在的占位符將被替換成 deploy_env 中的值。具體的例子可以參見隨本文附帶的 deploy.xml, deploy_env.properties 和 Test.properties。
其中 deploy.xml 是 ant 腳本,deploy_env.properties 中包含所有要替換的值,在 Test.properties 中是包含有占位符的資源文件。
![]() ![]() |
![]()
|
Ant 中支持多種正則表達式,在運行 Ant 的時候用哪種正則表達式可以通過設置 ant.regexp.regexpimpl 的值來切換,Ant 支持的的正則表達式有:
正則表達式的例子:
|
byline 屬性用來確認被替換的時候是一次替換一行還是多行;pattern 屬性用來指明正則表達式;substitution expression 中是替換的值,替換的值都定義在相對應的配置文件中;fileset 屬性中的 dir 用來指定被替換文件所在的目錄,includes 用來指定要替換哪個文件。需要注意的是,如果在正則表達式或者替換的值中出現'<'的話,需要用轉義符'<'。
在 Eclipse3.1 中已經內置了對正則表達式的支持;但是如果你在命令行中運行需要正則表達式支持的腳本的話,則需要自己將正則表達式的包下載下來加到 classpath 中。在隨文章的 deploy.xml 中提供了一個簡單的替換屬性文件的值的例子。正則表達式的例子可以在本文所帶的 deploy.xml 中找到。
![]() ![]() |
![]()
|
在生成部署包的時候,還有可能會根據目標環境的不同,刪除一些不同的文件。比如在產品環境中那些作為測試需要的代碼往往需要刪除,但是測試環境中并不需要。因此就需要條件表達式來做判斷。如下所示:
|
在上面的例子中,先讀出 ${deploy.isTestEnv} 的值(在配置文件 deloy.properties 中),根據讀出的值對屬性 isTestEnv 設值,如果 ${deploy.isTestEnv} 的值是 true,isTestEnv 的值也是 true;否則是 false。然后分別調用目標段 trueCondition 和 falseCondition。在這里,表達式值的判斷是用'istrue',在 Ant 中還提供了很多別的表達式,比如 not/and/or,equals 等等,具體關于條件表達式的信息可以參考:http://ant.apache.org/manual/CoreTasks/condition.html ,該頁也可以在隨下載下來的文檔中找到。
在段 trueCondition 中,判斷 isTestEnv,如果是真的話就運行,否則不運行;在段 falseCondition 中,也判斷 isTestEnv,如果是假就運行,否則不運行,在段中可以根據情況做相應的事情。條件判斷式的例子可以在本文的 deploy.xml 中找到。
![]() ![]() |
![]()
|
在上面的替換過程完成后,調用 war 將 unpack 目錄下的內容重新打包。
|
詳細的例子可以參見隨本文的附件 deploy.xml 和 deploy.properties。
![]() ![]() |
![]()
|
通過本文可以看出編寫好有效的 Ant 腳本能很好的解決在編譯部署包的時候出現的問題,將那些變化的內容放到配置文件中,在部署的時候切換不同的配置文件就可以實現生成不同的部署包。文中也介紹了如何使用 Eclipse 來提高你編寫/調試 Ant 腳本的效率。
|
|
|
|
|
|
|
|
|
|
客戶類型 | 樣例 | 如何聯接 |
商業合作伙伴 | 代理商,客戶群 | 基于XML的Web 服務技術 (SOAP, UDDI, WSDL, ebXML) |
瘦客戶端 | 瀏覽器,PDAs,無線設備 | HTTP 協議 |
胖客戶端 | 應用小程序,應用程序,已經存在的系統 | IIOP協議 |
<?xml version="1.0"?> POST /StockQuote HTTP/1.1 <SOAP-ENV:Envelope
<definitions name="StockQuote"
??????????????? targetNamespace="http://example.com/stockquote.wsdl"
??????????????? xmlns:tns="http://example.com/stockquote.wsdl"
??????????????? xmlns:xsd1="http://example.com/stockquote.xsd"
??????????????? xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
??????????????? xmlns="http://schemas.xmlsoap.org/wsdl/">
<types>
?? <schema targetNamespace=http://example.com/stockquote.xsd
???????????????? xmlns="http://www.w3.org/2000/10/XMLSchema">
????? <element name="TradePriceRequest">
??????? <complexType>
?????????? <all>
??????????????? <element name="tickerSymbol" type="string"/>
????????????? </all>
?????????? </complexType>
??????? </element>
??????? <element name="TradePrice">
??????????? <complexType>
??????????????? <all>
?????????????????? <element name="price" type="float"/>
???????????????? </all>
????????????? </complexType>
?????????? </element>
??????? </schema>
???? </types>
???? <message name="GetLastTradePriceInput">
???????? <part name="body" element="xsd1:TradePriceRequest"/>
???? </message>
???? <message name="GetLastTradePriceOutput">
???????? <part name="body" element="xsd1:TradePrice"/>
??? </message>
??? <portType name="StockQuotePortType">
??????? <operation name="GetLastTradePrice">
??????????? <input message="tns:GetLastTradePriceInput"/>
??????????? <output message="tns:GetLastTradePriceOutput"/>
???????? </operation>
????? </portType>
????? <binding name="StockQuoteSoapBinding"
??????????????????? type="tns:StockQuotePortType">
???????? <soap:binding style="document"
???????????????????????????????? transport="http://schemas.xmlsoap.org/soap/http"/>
??????? <operation name="GetLastTradePrice">
??????????? <soap:operation
?????????????????????????? soapAction="http://example.com/GetLastTradePrice"/>
??????????? <input>
?????????????? <soap:body use="literal"/>
??????????? </input>
??????????? <output>
??????????????? <soap:body use="literal"/>
??????????? </output>
???????? </operation>
????? </binding>
???? <service name="StockQuoteService">
??????? <documentation>My first service</documentation>
??????? <port name="StockQuotePort" binding="tns:StockQuoteBinding">
??????????? <soap:address location="http://example.com/stockquote"/>
??????? </port>
???? </service>
? </definitions>
它包含了以下的關鍵信息:
· 消息的描述和格式定義可以通過XML文檔中的
·
·
·
WSDL在UDDI中總是作為一個接口描述文檔。因為UDDI是一個通用的用來注冊WSDL規范的地方,UDDI的規范并不限制任何類型或者格式描述文檔。這些文檔可能是一個WSDL文檔,或者是一個正規的包含導向文檔的Web頁面,也可能只是一個包含聯系信息的電子郵件地址。
現在Java提供了一個 Java API for WSDL (JWSDL)規范。它提供了一套能快速處理WSDL文檔的方法,并且不用直接對XML文檔進行操作,它會比JAXP更方便,更快速。
圖 3 顯示了如何使用WSDL 和 UDDI。
圖 3
SOAP
當商業用戶通過UDDI找到你的WSDL描述文檔后,他通過可以Simple Object Access Protocol (SOAP) 調用你建立的Web服務中的一個或多個操作。
SOAP是XML文檔形式的調用商業方法的規范,它可以支持不同的底層接口,象HTTP(S)或者SMTP。之所以使用XML是因為它的獨立于編程語言,良好的可擴展性以及強大的工業支持。之所以使用HTTP是因為幾乎所有的網絡系統都可以用這種協議來通信,由于它是一種簡單協議,所以可以與任何系統結合,還有一個原因就是它可以利用80端口來穿越過防火墻。 SOAP的強大是因為它簡單。SOAP是一種輕量級的,非常容易理解的技術,并且很容易實現。它有工業支持,可以從各主要的電子商務平臺供應商那里獲得。
從技術角度來看,SOAP詳細指明了如何響應不同的請求以及如何對參數編碼。一個SOAP封裝了可選的頭信息和正文,并且通常使用HTTP POST方法來傳送到一個HTTP 服務器,當然其他方法也是可以的,例如SMTP。SOAP同時支持消息傳送和遠程過程調用。以下是一個SOAP請求。
Host: www.stockquoteserver.com
Content-Type: text/xml; charset="utf-8"
Content-Length: nnnn
SOAPAction: "Some-URI"
??? xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
??? SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
??? <SOAP-ENV:Header>
??????? <t:Transaction xmlns:t="some-URI" SOAP-ENV:mustUnderstand="1">
?????????? 5
??????? </t:Transaction>
??? </SOAP-ENV:Header>
??? <SOAP-ENV:Body>
??????? <m:GetLastTradePrice xmlns:m="Some-URI">
??????????? <symbol>SUNW</symbol>
??????? </m:GetLastTradePrice>
??? </SOAP-ENV:Body>
</SOAP-ENV:Envelope>
JAX/RPC
為了使開發人員專注于建立象SOAP那樣的基于XML的請求,JCP正在開發基于RPC (JAX/RPC) 的Java API。JAX/RPC是用來發送和接收方法調用請求的,它基于XML協議,象SOAP,或者其他的象XMLP (XML Protocol,要了解更多可以參考http://www.w3.org/2000/xp/)。JAX/RPC使你不用再關注這些協議的規范,使應用的開發更快速。不久,開發人員就不用直接以XML表示方法調用了。
目前有很多第三方實現了SOAP,開發人員可以在不同的層次上調用SOAP,并選擇使用哪一種。將來,JAX/RPC會取代這些APIs并提供一個統一的接口來構造以及處理SOAP RPC請求。
在接收一個從商業伙伴那里過來的SOAP請求的時候,一個Java servlet用JAX/RPC來接收這個基于XML的請求。一旦接收到請求后,servlet會調用商務方法,并且把結果回復給商業伙伴。
ebXML 對于具有高擴展性的商業交易來說,他們需要一種可信任的結構來實現商業事務,多請求的事務,計劃以及文檔流程,應用的需求經常超越了基于純SOAP的實現。因為SOAP只是提供了一個底層的結構,而你可能需要一個更高級的框架結構。
ebXML就是為了這個目的的,它是一套處理B2B應用間的合作與通信的XML規范。以下是ebXML中的關鍵組件:
Collaboration Protocol Profile (CPP)
CPP提供了一種標準并且簡單的方法描述了公司提供的產品。另外,它還描述了消息交換的能力以及公司支持的商務合作。它也描述了公司的商務處理方法,包括合伙人如何與公司合作。CPP定義了B2B交易中雙方的商務協作。例如,它同時定義了買賣雙方的商務處理方法。
Collaboration Protocol Agreement (CPA)
CPA描述了兩個公司之間進行交易時的詳細需求以及機制。它包含有由手工或者自動從經過買賣雙方認可的CPPs中的信息。這個CPA是雙方進行指定交易的合約。 CPP和CPA的樣例,以及關于規范的細節可以從以下網站獲得:
http://ebxml.org/project_teams/trade_partner/cpp-example.xml
http://ebxml.org/project_teams/trade_partner/cpa-example.xml
http://www.ebxml.org/specs/ebCCP.pdf
Business Process and Information Modeling
ebXML還以XML的形式描述了商業事務處理的規范。它包括交易,文檔流程,數字通信,數據封裝格式以及其他更多。這些規范是用來建立CPPs,描述以及共享商業事務和信息時用的。
Core Components
ebXML中另外一個重要的部分是一系列的XML標記,我們叫它核心組件。這些標記包含了商務數據,象日期,稅,賬戶,交易合同以及其他的。它指明了商業合約和實體,但對每個不同的行業,可能都不一樣。
Messaging
ebXML消息格式包含了所有相關的消息導向信息(同步或者異步,可靠性)。一般來說,一個ebXML消息包含了CPA中的可視化內容,并強制執行交易規則。 EbXML是建立在SOAP消息封裝機制上的。它擴展了SOAP的協議,增加了多層框架結構來支持附件,安全性以及傳送的可靠性。
Registry/Repository
EbXML注冊中心是存儲CPPs, CPAs, ebXML核心組件和與ebXML相關的文檔的服務。它具有強大的查詢功能,允許用戶查找相關的組件以及發掘潛在客戶。JAXR API也可以用來訪問ebXML注冊中心。商業服務定義了CPPs,并且被存儲在ebXML注冊中心,然后發布到UDDI中。一個關鍵的概念是,UDDI提供了一個全球唯一的Web服務的描述信息,但那些真實的信息,還是保存在本地的ebXML庫中。這樣的話,一個潛在的客戶首先到UDDI中查找相關內容,然后根據這些到ebXML庫中找CPPs或者其他相關文檔。
JAXM
當從商業合作伙伴那里接收一個Web服務的請求時,我們需要Java API實現一個Servlet來處理ebXML消息,就象我們用JAX/RPC來處理SOAP請求一樣。
Java API for XML Messaging (JAXM)
是集成XML消息標準(象ebXML消息或者SOAP消息)的規范。這個API是用來推動XML消息處理的,它檢測那些預定單的消息格式以及約束。它控制了所有的消息封裝機制,用一種直觀的方式分割了消息中的信息,象路由信息,發貨單。這樣,開發人員只要關注消息的有效負載,而不用去擔心那些消息的重復處理。
目前的開發人員用JAXP來實現JAXM將要提供的功能,JAXM將會提供一套非常具有針對性的API來處理基于XML的消息傳送。這將大大簡化開發人員的代碼,并使它們具有統一的接口。
JAXM和JAX/RPC的差別在于處理消息導向的中間件以及遠程過程調用的不同。JAXM注重于消息導向,而JAX/RPC是用來完成遠程過程調用的。以下是圖解。
圖 4
請注意,在JAXM 和 JAX/RPC技術成熟之前,開發人員還是依賴于第三方的SOAP APIs,象Apache SOAP, IdooXOAP, 以及 GLUE。當JAXM 和 JAX/RPC正式發布后,它將為當前不同的SOAP和ebXML消息提供統一的接口。就象JDBC位多種不同的數據庫提供統一的接口。
以上是對于讓商業合作伙伴訪問你的Web服務的討論。下面我們來討論瘦客戶端和胖客戶端。
Thin Client Connectivity
瘦客戶端(象瀏覽器或者無線設備)只對瀏覽頁面感興趣。Web服務的職責是執行需要處理的Web請求,象運行B2C交易,然后給出訂單確認。為實現這個,開發者用JSP來寫動態頁面。JSP組件技術時一種可以根據后臺數據處理的結果,來動態生成頁面的技術。它們在提供JSP組件的容器中運行。 JSP可以表現后臺用各種方法來實現的業務邏輯(e.g. EJBs,普通的Java對象,或者標準的JavaBean)。它可以生成標準的HTML或者XHTML來顯示結果。 JSP組件與其說是可編程接口,不如說是用戶界面。比方說,一個股票報價服務可能需要調用一個統計股票平均報價的應用中的Web服務,然后利用JSP技術把最終結果顯示出來。以下顯示了JSP組件的角色。
圖 5
Thick Client Connectivity
有些Web服務的連接適合用胖客戶端。比方說,公司的內部網。用戶界面的響應以及功能可能更加重要。
一個胖客戶端可以用很多種方法來聯接Web服務。比方說,可以用UDDI, WSDL, SOAP以及ebXML。這是一個性能比較低的例子,因為客戶端和服務端可能是由同樣的開發組開發的,所以不需要處理很多的XML傳送或者解析。
一個提高性能的方法是,胖客戶端通過其他更有效的端口來聯接,象Java RMI-IIOP。
V. Implementing Web Services
現在我們來看,如何在內部實現Web服務。
數據傳送和轉換
在進入Web服務之前,我們必須解決如何把傳送進來的XML數據轉換成我們自己的服務能夠方便處理的格式,然后再把處理結果轉換成XML格式返回給客戶。因此一個開發人員需要一個強壯的機制來解析XML文件,綁定到Java對象,生成XML文件,并且傳送各種不同的XML格式文件。有時由于我們的應用程序支持不同的接口(例如:B2B伙伴的SOAP,基于瀏覽器的HTML格式,或者是無線的WML訪問同樣的Web服務)我們可能需要不同的服務接口來處理這些不同客戶端傳送過來的請求。
JAXP
用來處理XML的Java APIs是一套Java本地接口,它提供了可插入到XSLT引擎中的接口SAX,DOM。這些構成了解析和處理XML文檔的基礎。這些APIs對Web服務來說,是非常底層的,它給了我們用Java來訪問,修改以及創建XML文檔的全部功能。
For more information, please see:
http://java.sun.com/xml/tutorial_intro.html
http://java.sun.com/xml/xml_jaxp.html
JAXB
XML綁定技術可以把XML文檔和Java對象進行自由轉換。用JAXB,你可以在后臺的EJB層,把XML文檔轉換成Java對象。同樣你也可以把從EJB中取出的Java對象轉換成XML文檔返回給用戶。
JAXB接口提供了比SAX和DOM更高級的方法來處理XML文檔。它提供的特性可以在XML數據和Java類之間互相映射,提供了一個簡單的方法來轉換XML數據。它比逐個解析標記更簡單。
XSLT
從商業伙伴那里傳送過來的XML文檔可能和內部使用的格式不相同,比方說商業伙伴那里用"OrderNum",而內部使用"OrderID"。
我們經常為了響應不同的客戶請求,而重新格式化XML數據文檔。舉例來說,一個商業伙伴的請求可能傳送一個SOAP表單,而一些瀏覽器用戶可能是一個XHTML。在一個更復雜的系統中,我們可能需要支持很多種不同的表現形式,象WML表單或者VoiceXML。這要求我們有一種機制來把各種XML以基本的XML響應格式來傳送給我們系統中不同的接口。
XML Stylesheet Language Transformations (XSLT)
是一種轉換XML格式的機制。一個stylesheet可以指定一系列的模版對應規則,并把它們賦給一個可遞歸的,象DOM這樣的模型。一個XSLT引擎可以用stylesheet來轉換XML文檔。XSLT stylesheet的語法是非常有表現力的,包含了循環,條件和數學表達式等。還有類似于函數(function)的機構和概念上的遞歸。
Shared Context
當兩個商業發生交易的時候,通常有一個上下文的關系。這個關系是指定給合作伙辦的一個協議,或者是一種商業規則,這樣就可以給不同的合作伙伴進行交易。此外,一個商業協作在一段時間內可能調用不同的接口。每一個這樣的調用都是處理同一個商業關系的,可能出現在整個商業生命周期中。
在J2EE Web服務中,為這個關系建一個離散的位置是一種建議的實現方法。作為一個開發人員,你應該在復雜的Web服務中需要這樣的關系,并且為你的系統結構設計一個離散的組件來控制它。目前這種關系是通過數據庫訪問(JDBC)來實現的。但是,Context API可以把Web服務中需要對這種關系的訪問操作作為一種流控制。這樣,這些共享的數據就可以由各種組件來訪問,象Servlet, JSP或者EJB組件。
Business Layer
當傳送進來的XML數據被轉換成Java對象后,這個數據已經準備被傳送到EJB商務層做處理。EJB技術是一種用Java來創建商業組件的標準。用EJB組件,你可以從容器中得到一些服務,象安全性,狀態保持,連接池,負載平衡以及失敗恢復。
在EJB2.0標準中有3中EJB組件:
Session Beans
進行客戶端的工作。一般來說,Session Bean生命周期短,執行快速的操作,象提交訂單,計算交易稅額。
Entity Beans
表現商業數據。一般來說,Entity Bean生命周期長,并且映射到后臺的存儲介質內,象RDBMS或者OODBMS系統。Entity Bean分為兩種類型:bean-managed persistent 和container-managed persistent
MessageDriven Beans
是消息導向組件。它們通過消息導向中間件來接收消息象IBM MQSeries或者TIBCO Rendezvous。消息也可以通過Java客戶端利用Java Message Service (JMS) 標準來發送。當消息到達后,一般用JMS API來訪問。
一般來說,session beans 通過調用entity bean來完成希望的操作。比方說,一個用來計算訂單價格的session bean,可能調用到表示產品和訂單的entity bean。 Message-driven beans 用來接收消息,或者傳送消息到那些session beans 或者 entity beans.
圖6顯示了一個EJB組件交互的機制。
你可以用Java Naming和JNDI API來創建,查找以及刪除EJB組件。這個API是用來訪問J2EE發布系統中外部資源的標準API,可以訪問包括數據庫驅動,消息中間件,或者創建EJB的程序。
更多 EJB資料, 請查閱:
· http://java.sun.com/products/ejb/white/white_paper.html
· http://java.sun.com/products/ejb/
· http://www.theserverside.com
· "Mastering Enterprise JavaBeans" by Ed Roman, published by John Wiley & Sons.
VI. Performing Back-End Integration
最后來討論用J2EE來開發Web服務的時候,如何與后臺系統相連,象數據庫,原先的系統和其他的商業伙伴。
Database Connectivity
為了聯接關系數據庫,開發人員必須選擇APIs: The JDBC API 是一個用來訪問支持SQL的關系數據庫API.。(這個相信大家都知道了。)
SQL/J
是用Java編寫的標準的嵌入式SQL。類似于在HTML中嵌入JSP組件。
Legacy System Connectivity
在企業級開發中,與現存的系統相連接,一直都是一個比較困難的任務。大部分企業應用都是一個大雜燴,包含象SAP R/3, Siebel, i2以及一些客戶服務系統。整合工作是一個手工任務,因為對現存的系統可用方案并不多。軟件獨立開發商被要求編寫一個在任何平臺上都可以運行的客戶適配器,但這缺乏一個統一的標準平臺。
J2EE Connector Architecture (JCA)
是在工業中應用的,一個針對現存系統的適配器。你可以用它來連接現在的系統,或者編寫你自己的適配器。它可以運行在與任何J2EE兼容的環境中。用JCA,你只要編寫一個適配器,就可以在任何J2EE環境中運行。對于軟件獨立開發商來說,這為他們提供了一個整合現存系統的方案。事實上,這些適配器正在開發中,對最終開發者來說,這的確是令人激動的。
Business Partner Connectivity
后臺系統的最后一個類型是商業伙伴的Web服務。商業伙伴用全球認定的XML標準來暴露出一些他們自己的系統,在我們發布自己的Web服務時,可能會用到他們的這些服務。一般來說,UDDI用來注冊Web服務,WSDL用來描述Web服務,SOAP和ebXML用來處理商務交易。
你的EJB組件可以調用JAP套件來訪問商業伙伴的Web服務,這在之前已經介紹過了。
用 Java API for XML Registries (JAXR) 在UDDI注冊中心查找商業伙伴的Web服務。
用 Java API for XML RPC (JAX/RPC) 處理到外部Web服務的請求。
用 Java API for XML Messaging (JAXM) 發送SOAP 或者 ebXML 消息到外部Web服務。
用 Java API for XML Parsing (JAXP) and the Java API for XML Binding (JAXB)
把Java數據轉換成適用于合作伙伴的XML格式。同樣可以用來把合作伙伴那邊的數據轉換成易于自己處理的XML格式,或者進行XSLT數據轉換。
結合使用Java標準APIs和J2EE Web服務構架,我們就可以建立強大的跨平臺的系統。利用它們,我們可以與商業伙伴共享數據,提供完整的end-to-end的Web服務解決方案。見圖7。 ?
開源在今天的軟件業已經很普遍,但開源是否意味著使用者可以對開源后的代碼為所欲為呢?答案是否定的。開源運動同樣有自己的游戲規則和道德準則。不遵行這些規則不但損害開源運動的健康發展,也會對違規者造成名譽和市場上的損失,更可能陷入法律糾紛和賠償。
現今存在的開源協議很多,而經過Open Source Initiative組織通過批準的開源協議目前有58種。我們在常見的開源協議如BSD, GPL, LGPL,MIT等都是OSI批準的協議。如果要開源自己的代碼,最好也是選擇這些被批準的開源協議。
這里我們來看四種最常用的開源協議及它們的適用范圍,供那些準備開源或者使用開源產品的開發人員/廠家參考。
現今存在的開源協議很多,而經過Open Source Initiative組織通過批準的開源協議目前有58種。我們在常見的開源協議如BSD, GPL, LGPL,MIT等都是OSI批準的協議。如果要開源自己的代碼,最好也是選擇這些被批準的開源協議。
BSD開源協議
BSD開源協議是一個給于使用者很大自由的協議。基本上使用者可以”為所欲為”,可以自由的使用,修改源代碼,也可以將修改后的代碼作為開源或者專有軟件再發布。
但”為所欲為”的前提當你發布使用了BSD協議的代碼,或則以BSD協議代碼為基礎做二次開發自己的產品時,需要滿足三個條件:
1.? 如果再發布的產品中包含源代碼,則在源代碼中必須帶有原來代碼中的BSD協議。
2.? 如果再發布的只是二進制類庫/軟件,則需要在類庫/軟件的文檔和版權聲明中包含原來代碼中的BSD協議。
3.? 不可以用開源代碼的作者/機構名字和原來產品的名字做市場推廣。
BSD代碼鼓勵代碼共享,但需要尊重代碼作者的著作權。BSD由于允許使用者修改和重新發布代碼,也允許使用或在BSD代碼上開發商業軟件發布和銷售,因此是對商業集成很友好的協議。而很多的公司企業在選用開源產品的時候都首選BSD協議,因為可以完全控制這些第三方的代碼,在必要的時候可以修改或者二次開發。
Apache Licence 2.0
Apache Licence是著名的非盈利開源組織Apache采用的協議。該協議和BSD類似,同樣鼓勵代碼共享和尊重原作者的著作權,同樣允許代碼修改,再發布(作為開源或商業軟件)。需要滿足的條件也和BSD類似:
1.需要給代碼的用戶一份Apache Licence
2.如果你修改了代碼,需要再被修改的文件中說明。
3.在延伸的代碼中(修改和有源代碼衍生的代碼中)需要帶有原來代碼中的協議,商標,專利聲明和其他原來作者規定需要包含的說明。
4. 如果再發布的產品中包含一個Notice文件,則在Notice文件中需要帶有Apache Licence。你可以在Notice中增加自己的許可,但不可以表現為對Apache Licence構成更改。
Apache Licence也是對商業應用友好的許可。使用者也可以在需要的時候修改代碼來滿足需要并作為開源或商業產品發布/銷售。
GPL
我們很熟悉的Linux就是采用了GPL。GPL協議和BSD, Apache Licence等鼓勵代碼重用的許可很不一樣。GPL的出發點是代碼的開源/免費使用和引用/修改/衍生代碼的開源/免費使用,但不允許修改后和衍生的代碼做為閉源的商業軟件發布和銷售。這也就是為什么我們能用免費的各種linux,包括商業公司的linux和linux上各種各樣的由個人,組織,以及商業軟件公司開發的免費軟件了。
GPL協議的主要內容是只要在一個軟件中使用(“使用”指類庫引用,修改后的代碼或者衍生代碼)GPL協議的產品,則該軟件產品必須也采用GPL協議,既必須也是開源和免費。這就是所謂的”傳染性”。GPL協議的產品作為一個單獨的產品使用沒有任何問題,還可以享受免費的優勢。
由于GPL嚴格要求使用了GPL類庫的軟件產品必須使用GPL協議,對于使用GPL協議的開源代碼,商業軟件或者對代碼有保密要求的部門就不適合集成/采用作為類庫和二次開發的基礎。
其它細節如再發布的時候需要伴隨GPL協議等和BSD/Apache等類似。
LGPL
LGPL是GPL的一個為主要為類庫使用設計的開源協議。和GPL要求任何使用/修改/衍生之GPL類庫的的軟件必須采用GPL協議不同。LGPL 允許商業軟件通過類庫引用 (link)方式使用LGPL類庫而不需要開源商業軟件的代碼。這使得采用LGPL協議的開源代碼可以被商業軟件作為類庫引用并發布和銷售。
但是如果修改LGPL協議的代碼或者衍生,則所有修改的代碼,涉及修改部分的額外代碼和衍生的代碼都必須采用LGPL協議。因此LGPL協議的開源代碼很適合作為第三方類庫被商業軟件引用,但不適合希望以LGPL協議代碼為基礎,通過修改和衍生的方式做二次開發的商業軟件采用。
GPL/LGPL都保障原作者的知識產權,避免有人利用開源代碼復制并開發類似的產品。