以下列出的是 HttpClient 提供的主要的功能,要知道更多詳細的功能可以參見 HttpClient 的主頁。
下面將逐一介紹怎樣使用這些功能。首先,我們必須安裝好 HttpClient。
下面是個我寫的程序:
package com.newpalm.unicomfetch.threads;
import java.util.Vector;
import org.apache.commons.httpclient.Cookie;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.NameValuePair;
import org.apache.commons.httpclient.cookie.CookiePolicy;
import org.apache.commons.httpclient.cookie.CookieSpec;
import org.apache.commons.httpclient.methods.GetMethod;
import org.apache.commons.httpclient.methods.PostMethod;
import org.htmlparser.Node;
import org.htmlparser.Parser;
import org.htmlparser.tags.TableColumn;
import org.htmlparser.tags.TableRow;
import org.htmlparser.tags.TableTag;
import org.htmlparser.visitors.ObjectFindingVisitor;
/**
* 用來演示登錄表單的示例
* @author Liudong
*/
public class FormLoginDemo {
public static void main(String[] args) throws Exception{
Parser parser = null;
ObjectFindingVisitor visitor = null;
HttpClient client = new HttpClient();
//模擬登錄頁面
PostMethod post = new PostMethod("<a href="http://211.90.119.58:9999/SPLogin.aspx"><span style="color: #78ba00;">http://211.90.119.58:9999/SPLogin.aspx</span></a>");
NameValuePair name = new NameValuePair("txtHandsetNumber", "123456");
NameValuePair pass = new NameValuePair("txtPassword", "123456");
NameValuePair __VIEWSTATE = new NameValuePair("__VIEWSTATE", "dDwtMTUxMzkxNTQ0Mzt0PDtsPGk8MT47PjtsPHQ8O2w8aTwxPjs+O2w8dDxwPGw8VGV4dDs+O2w8XDxtYXJxdWVlIERpcmVjdGlvbj0idXAiIGJlaGF2aW9yPSJzY3JvbGwiICBoZWlnaHQ9JzE1MCcgc2Nyb2xsZGVsYXk9MzAwIG9ubW91c2VvdmVyPSd0aGlzLnN0b3AoKScgb25tb3VzZW91dD0ndGhpcy5zdGFydCgpJ1w+XDxpbWcgc3JjPSJpbWFnZS9kZWZhdWx0X2NhbGxfaWNvbi5naWYiIHdpZHRoPSI0IiBoZWlnaHQ9IjciXD4mbmJzcFw7Jm5ic3BcO1w8YSBocmVmID0iIyIgb25jbGljaz0ib3BlbldpbmRvdygnL0J1bGxldGluLmFzcHg/QnVsbGV0aW5JZD0yMycpIlw+c3DkuJrliqHmjqXlhaXms6jmhI/kuovpoblcPC9hXD4KXDxiclw+XDxiclw+XDwvbWFycXVlZVw+Oz4+Ozs+Oz4+Oz4+O2w8YnRuTG9naW47Pj4pKEgdIvj1JmRdgJaS7sGzD39jZg==");
NameValuePair btnLoginx = new NameValuePair("btnLogin.x", "0");
NameValuePair btnLoginy = new NameValuePair("btnLogin.y", "5");
post.setRequestBody(new NameValuePair[]{name,pass,__VIEWSTATE,btnLoginx,btnLoginy});
int status = client.executeMethod(post);
post.releaseConnection();
//查看cookie信息
CookieSpec cookiespec = CookiePolicy.getDefaultSpec();
Cookie[] cookies = client.getState().getCookies();
if (cookies.length == 0) {
System.out.println("None");
} else {
for (int i = 0; i < cookies.length; i++) {
System.out.println(cookies[i].toString());
}
}
//訪問所需的頁面
GetMethod get = new GetMethod("<a href="http://211.90.119.58:9999/PhoneSearch/PhoneSearch.aspx"><span style="color: #78ba00;">http://211.90.119.58:9999/PhoneSearch/PhoneSearch.aspx</span></a>");
client.executeMethod(get);
visitor = new ObjectFindingVisitor(TableTag.class);
parser = new Parser();
parser.setInputHTML(get.getResponseBodyAsString());
parser.setEncoding("GBK");
parser.visitAllNodesWith(visitor);
//取得要解析的頁面數
Node[] tables = visitor.getTags();
TableTag tableTag = (TableTag) tables[tables.length-1];
TableRow[] rows = tableTag.getRows();
TableRow row = rows[0];
TableColumn[] col = row.getColumns();
int pageNumber = Integer.parseInt(col[0].getChildrenHTML().substring(25, 29));
get.releaseConnection();
for(int i=1;i<pageNumber;i++){
PostMethod pt = new PostMethod("<a href="http://211.90.119.58:9999/PhoneSearch/PhoneSearch.aspx"><span style="color: #78ba00;">http://211.90.119.58:9999/PhoneSearch/PhoneSearch.aspx</span></a>");
NameValuePair txtPage = new NameValuePair("txtPage",Integer.toString(i));
__VIEWSTATE = new NameValuePair("__VIEWSTATE", "")
NameValuePair __EVENTTARGET = new NameValuePair("__EVENTTARGET", "");
NameValuePair __EVENTARGUMENT = new NameValuePair("__EVENTARGUMENT", "");
NameValuePair TBMDN = new NameValuePair("TBMDN", "");
NameValuePair TBServiceType = new NameValuePair("TBServiceType", "");
NameValuePair TBStartTime = new NameValuePair("TBStartTime", "");
NameValuePair TBEndTime = new NameValuePair("TBEndTime", "");
NameValuePair btnGotox = new NameValuePair("btnGoto.x", "26");
NameValuePair btnGotoy = new NameValuePair("btnGoto.y", "13");
pt.setRequestBody(new NameValuePair[]{__EVENTTARGET,__EVENTARGUMENT,__VIEWSTATE,TBMDN,TBServiceType,TBStartTime,TBEndTime,txtPage,btnGotox,btnGotoy});
int a = client.executeMethod(pt);
parser.setInputHTML(pt.getResponseBodyAsString());
parser.setEncoding("GBK");
parser.visitAllNodesWith(visitor);
tables = visitor.getTags();
tableTag = (TableTag) tables[tables.length-3];
rows = tableTag.getRows();
row = rows[1];
col = row.getColumns();
System.out.println(col[4].getChildrenHTML().toString());
get.releaseConnection();
}
}
}
下面介紹在使用HttpClient過程中常見的一些問題。
某目標頁的編碼可能出現在兩個地方,第一個地方是服務器返回的http頭中,另外一個地方是得到的html/xml頁面中。
根據RFC2616中對自動轉向的定義,主要有兩種:301和302。301表示永久的移走(Moved Permanently),當返回的是301,則表示請求的資源已經被移到一個固定的新地方,任何向該地址發起請求都會被轉到新的地址上。302表示暫時 的轉向,比如在服務器端的servlet程序調用了sendRedirect方法,則在客戶端就會得到一個302的代碼,這時服務器返回的頭信息中 location的值就是sendRedirect轉向的目標地址。
HttpClient支持自動轉向處理,但是象POST和PUT方式這種要求接受后繼服務的請求方式,暫時不支持自動轉向,因此如果碰到POST方 式提交后返回的是301或者302的話需要自己處理。就像剛才在POSTMethod中舉的例子:如果想進入登錄BBS后的頁面,必須重新發起登錄的請 求,請求的地址可以在頭字段location中得到。不過需要注意的是,有時候location返回的可能是相對路徑,因此需要對location返回的 值做一些處理才可以發起向新地址的請求。
另外除了在頭中包含的信息可能使頁面發生重定向外,在頁面中也有可能會發生頁面的重定向。引起頁面自動轉發的標簽是:<meta http-equiv=”refresh” content=”5; url=http://www.ibm.com/us”>。如果你想在程序中也處理這種情況的話得自己分析頁面來實現轉向。需要注意的是,在上面那 個標簽中url的值也可以是一個相對地址,如果是這樣的話,需要對它做一些處理后才可以轉發。
HttpClient提供了對SSL的支持,在使用SSL之前必須安裝JSSE。在Sun提供的1.4以后的版本中,JSSE已經集成到JDK中, 如果你使用的是JDK1.4以前的版本則必須安裝JSSE。JSSE不同的廠家有不同的實現。下面介紹怎么使用HttpClient來打開Https連 接。這里有兩種方法可以打開https連接,第一種就是得到服務器頒發的證書,然后導入到本地的keystore中;另外一種辦法就是通過擴展 HttpClient的類來實現自動接受證書。
方法1,取得證書,并導入本地的keystore:
2. 單擊”View Certificate”,在彈出的對話框中選擇”Details”,然后再單擊”Copy to File”,根據提供的向導生成待訪問網頁的證書文件
3. 向導第一步,歡迎界面,直接單擊”Next”,
4. 向導第二步,選擇導出的文件格式,默認,單擊”Next”,
5. 向導第三步,輸入導出的文件名,輸入后,單擊”Next”,
6. 向導第四步,單擊”Finish”,完成向導
7. 最后彈出一個對話框,顯示導出成功
|
其中參數alias后跟的值是當前證書在keystore中的唯一標識符,但是大小寫不區分;參數file后跟的是剛才通過IE導出的證書所在的路徑和文件名;如果你想刪除剛才導入到keystore的證書,可以用命令:
|
|
運行該程序可能出現的問題:
1. 拋出異常java.net.SocketException: Algorithm SSL not available。出現這個異常可能是因為沒有加JSSEProvider,如果用的是IBM的JSSE Provider,在程序中加入這樣的一行:
|
或者也可以打開<java-home>"lib"security"java.security,在行
|
后面加入security.provider.3=com.ibm.jsse.IBMJSSEProvider
2. 拋出異常java.net.SocketException: SSL implementation not available。出現這個異常可能是你沒有把ibmjsse.jar拷貝到<java-home>"lib"ext"目錄下。
3. 拋出異常javax.net.ssl.SSLHandshakeException: unknown certificate。出現這個異常表明你的JSSE應該已經安裝正確,但是可能因為你沒有把證書導入到當前運行JRE的keystore中,請按照前 面介紹的步驟來導入你的證書。
方法2,擴展HttpClient類實現自動接受證書
因為這種方法自動接收所有證書,因此存在一定的安全問題,所以在使用這種方法前請仔細考慮您的系統的安全需求。具體的步驟如下:
|
|
HttpClient中使用代理服務器非常簡單,調用HttpClient中setProxy方法就可以,方法的第一個參數是代理服務器地址,第二個參數是端口號。另外HttpClient也支持SOCKS代理。
Dec 2nd 2010 | from PRINT EDITION
TOWARDS the end of 2003 and early in 2004 China’s most senior leaders put aside the routine of governing 1.3 billion people to spend a couple of afternoons studying the rise of great powers. You can imagine history’s grim inventory of war and destruction being laid out before them as they examined how, from the 15th century, empires and upstarts had often fought for supremacy. And you can imagine them moving on to the real subject of their inquiry: whether China will be able to take its place at the top without anyone resorting to arms.
In many ways China has made efforts to try to reassure an anxious world. It has repeatedly promised that it means only peace. It has spent freely on aid and investment, settled border disputes with its neighbours and rolled up its sleeves in UN peacekeeping forces and international organisations. When North Korea shelled a South Korean island last month China did at least try to create a framework to rein in its neighbour.
But reasonable China sometimes gives way to aggressive China. In March, when the North sank a South Korean warship, killing 46 sailors, China failed to issue any condemnation. A few months later it fell out with Japan over some Chinese fishermen, arrested for ramming Japanese coastguard vessels around some disputed islands—and then it locked up some Japanese businessmen and withheld exports of rare earths vital for Japanese industry. And it has forcefully reasserted its claim to the Spratly and Paracel Islands and to sovereignty over virtually the entire South China Sea.
As the Chinese leaders’ history lesson will have told them, the relationship that determines whether the world is at peace or at war is that between pairs of great powers. Sometimes, as with Britain and America, it goes well. Sometimes, as between Britain and Germany, it does not.
So far, things have gone remarkably well between America and China. While China has devoted itself to economic growth, American security has focused on Islamic terrorism and war in Iraq and Afghanistan. But the two mistrust each other. China sees America as a waning power that will eventually seek to block its own rise. And America worries about how Chinese nationalism, fuelled by rediscovered economic and military might, will express itself (see our special report).
The Peloponnesian pessimists
Pessimists believe China and America are condemned to be rivals. The countries’ visions of the good society are very different. And, as China’s power grows, so will its determination to get its way and to do things in the world. America, by contrast, will inevitably balk at surrendering its pre-eminence.
They are probably right about Chinese ambitions. Yet China need not be an enemy. Unlike the Soviet Union, it is no longer in the business of exporting its ideology. Unlike the 19th-century European powers, it is not looking to amass new colonies. And China and America have a lot in common. Both benefit from globalisation and from open markets where they buy raw materials and sell their exports. Both want a broadly stable world in which nuclear weapons do not spread and rogue states, like Iran and North Korea, have little scope to cause mayhem. Both would lose incalculably from war.
The best way to turn China into an opponent is to treat it as one. The danger is that spats and rows will sour relations between China and America, just as the friendship between Germany and Britain crumbled in the decades before the first world war. It is already happening in defence. Feeling threatened by American naval power, China has been modernising its missiles, submarines, radar, cyber-warfare and anti-satellite weapons. Now America feels on its mettle. Recent Pentagon assessments of China’s military strength warn of the threat to Taiwan and American bases and to aircraft-carriers near the Chinese coast. The US Navy has begun to deploy more forces in the Pacific. Feeling threatened anew, China may respond. Even if neither America nor China intended harm—if they wanted only to ensure their own security—each could nevertheless see the other as a growing threat.
Some would say the solution is for America to turn its back on military rivalry. But a weaker America would lead to chronic insecurity in East Asia and thus threaten the peaceful conduct of trade and commerce on which America’s prosperity depends. America therefore needs to be strong enough to guarantee the seas and protect Taiwan from Chinese attack.
How to take down the Great Wall
History shows that superpowers can coexist peacefully when the rising power believes it can rise unhindered and the incumbent power believes that the way it runs the world is not fundamentally threatened. So a military build-up needs to be accompanied by a build-up of trust.
There are lots of ways to build trust in Asia. One would be to help ensure that disputes and misunderstandings do not get out of hand. China should thus be more open about its military doctrine—about its nuclear posture, its aircraft-carriers and missile programme. Likewise, America and China need rules for disputes including North Korea (see article), Taiwan, space and cyber-warfare. And Asia as a whole needs agreements to help prevent every collision at sea from becoming a trial of strength.
America and China should try to work multilaterally. Instead of today’s confusion of competing venues, Asia needs a single regional security forum, such as the East Asia Summit, where it can do business. Asian countries could also collaborate more in confidence-boosting non-traditional security, such as health, environmental protection, anti-piracy and counter-terrorism, where threats by their nature cross borders.
If America wants to bind China into the rules-based liberal order it promotes, it needs to stick to the rules itself. Every time America breaks them—by, for instance, protectionism—it feeds China’s suspicions and undermines the very order it seeks.
China and America have one advantage over history’s great-power pairings: they saw the 20th century go disastrously wrong. It is up to them to ensure that the 21st is different.
譯者注:WordPress是最受歡迎的博客發布平臺之一,具有免費,高度可定制、容易安裝和使用等特色。由于Wordpress是如此流行和受歡迎,你可以找到大量的Wordpress開發以及管理等方面的資源,豐富的用戶指南讓你能夠快速的上手使用。參考資料:30個頂級Wordpress培訓視頻指南與教程
有很多天才設計師選擇發表免費的wordpress主題。大多數時候,對于他們來說唯一的一點小要求就是保留他們的設計元素,并鏈接到他們的網站(非常合理的要求)。
在本文中,我們整理了50個優秀的、高質量的、免費的Wordpress主題給大家。這些主題包含了制作精細且華麗的主題,也有簡潔清爽的主題,你可以找到適合你的設計品位的wordpress主題。
說明: 請務必檢查主題的許可協議,不要違反使用限制(如果有的話),并且保留設計師的設計屬性[footer中的設計信息],即使設計師沒有要求你這么做。[互聯網營銷博客注:設 計一個漂亮的wordpress theme,需要花費設計師很多的時間和精力,如果你喜歡這些免費的wordpress主題,請尊重設計師的勞動成果。]
譯者注:在本文中介紹的wordpress主題均為英文模板,對于使用英文寫博客的朋友來說,這里還有我收集的3個英文寫作軟件可以參考,都有免費試用版本可供下載:1、Whitesmoke - 最適合ESL使用的英文寫作和語法糾錯軟件,支持mac os。2、Stylewriter - 最適合公司,組織,作家使用的plain english寫作軟件。3、Ginger Software - 英文拼寫和語法檢查軟件,和whitesmoke差不多,但更為專業的英文寫作工具。
為了向你展示這些 CSS Hack 是否正常運作,我新建六個 P 標簽,并給每一個 P 標簽一個特有的 id。這將向你展示 CSS Hack 的運作情況。
<p id="opera">我來自 Opera 7.2 - 9.5</p>
<p id="safari">我是神奇的 Safari</p>
<p id="firefox">我來自 Firefox</p>
<p id="firefox12">我是你爺爺 Firefox 1 - 2 </p>
<p id="ie7">我是囧 IE 7</p>
<p id="ie6">我是腦瘸 IE 6</p>
然后我讓這些 P 標簽默認都不顯示
<style type="text/css"> body p{display: none;} </style>
使用 IE CSS 條件注釋區分 IE 瀏覽器
最簡單的區分 IE 瀏覽器的方法自然是使用他們的條件注釋。 微軟創建了一個強大的語法來讓我們去實現這個功能。我不想再詳細地介紹 IE 條件注釋了,我想你在搜索引擎能搜索到上萬個搜索條目,我這里只要這兩個:
<!--[if IE 7]>
<style type="text/css">
</style> <![endif]-->
<!--[if IE 6]>
<style type="text/css"> </style>
<![endif]-->
使用 CSS 解析器 Hacks 區分 IE
雖說 IE 條件注釋十分簡單好用,但是如果你想把全部的 CSS 放到一個文件里的 話,那么你不得不使用別的方法。注意這里的 IE 7 Hack將只對 IE7 有效,因為 IE6 根本不知道 > 選擇符。同時你也得注意 > 選擇符對于其他瀏覽器同樣是無效的。
html > body #ie7 {*display: block;}
body #ie6 {_display: block;}
CSS Hack 區分 Firefox
第一個使用了 body:empty 來區分 Firefox 1 和 2 。第二個 hack使用了全部 Firefox 瀏覽器的專有擴展 -moz。 -moz 只對 Firefox有效,使用這個 Hack 大可不必擔心其他瀏覽器的影響。
body:empty #firefox12 {display: block;}
@-moz-document url-prefix() {#firefox { display: block; }}
CSS Hack 區分 Safari
Safari 的 CSS hack 與 Firefox 的 hack 看起來很像,使用的是 Safari瀏覽器的專有擴展 -webkit 且只對 Safari 瀏覽器有效。
@media screen and (-webkit-min-device-pixel-ratio:0) {#safari { display: block; }}
CSS Hack 區分 Opera
@media all and (-webkit-min-device-pixel-ratio:10000), not all and (-webkit-min-device-pixel-ratio:0) {head~body #opera { display: block; }}
然后,全部合在一起便是
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>CSS Browser Hacks - 52css.com</title>
<style type="text/css">
body p {
display: none;
}
html:first-child #opera {
display: block;
}
html > body #ie7 {
*display: block;
}
body #ie6 {
_display: block;
}
body:empty #firefox12 {
display: block;
}
@-moz-document url-prefix() {
#firefox {
display: block;
}
}
@media screen and (-webkit-min-device-pixel-ratio:0) {
#safari {
display: block;
}
}
@media all and (-webkit-min-device-pixel-ratio:10000), not all and (-webkit-min-device-pixel-ratio:0) {
head~body #opera {
display: block;
}
}
</style>
</head>
<body>
<p id="opera">我來自 Opera 7.2 - 9.5</p>
<p id="safari">我是神奇的 Safari</p>
<p id="firefox">我來自 Firefox</p>
<p id="firefox12">我是你爺爺 Firefox 1 - 2 </p>
<p id="ie7">我是囧 IE 7</p>
<p id="ie6">我是腦瘸 IE 6</p>
</body>
</html>
CSS Hack 雖好且方便兼容各瀏覽器,但是通不過 W3C 驗證,所以還得自己權衡是否有必要去使用。
"一切都在流動,沒有什么是持久的。一切都在融化,沒有什么是固定不變的" - 赫拉克利特(Heracleitus)
大約在2003年中的時候,SOA的概念逐漸進入人們的視野,一時間眾人樂此不疲的發表各自對SOA的見解。SOA已經成 為IT業,尤其是軟件開發及系統集成領域從業者的熱門話題。很多的權威機構也紛紛預測SOA的美妙前景,例如,Gartner 預言,到了 2008 年,至少 60% 的企業將使用 SOA 作為其IT架構。拋開喧囂躁動以及隨聲附和,對于軟件開發者而言,經過了一年多的概念灌輸,伴隨著不斷增長的困惑,更多的人希望能靜下心來看一看:究竟怎 樣的系統架構是符合SOA設計的,而又有哪些技術可以用來實現SOA呢?特別是企業服務總線(Enterprise Service Bus, ESB), 看起來更是SOA中一個玄虛的概念,本系列文章將通過實際的案例分析來詳細講解在SOA系統中是怎樣實施ESB的。
本系列文章將直接面向廣大的軟件開發人員, 首先以直觀的方式介紹什么是ESB, 然后引入一個實際案例,以此為基礎,詳細介紹怎樣一步一步實現ESB。現在我們談論SOA和ESB的時候都不再是空中樓閣,IBM作為SOA的倡導者,已 經提供了很好的產品來實現我們的設想。我們會在本系列中的第二、第三部分中分別介紹基于WebSphere 6 和IBM EAI產品的兩種實現方式, 然后在第四部分中介紹在復雜的企業應用場景中總線(Bus)怎樣互聯, 怎樣擴展。希望通過本系列文章,能讓廣大讀者朋友快速掌握ESB的實際開發技巧。
關于SOA的概念,你可以找到很多的文章從不同的角度來描述它,不同的軟件提供商也有不同的定義方式。BEA有流體計算, 微軟有Indigo 和SOA-building, SAP有ESA。 每個人都可以從不同的視角來理解SOA,從程序員的角度,SOA是一種全新的開發技術,新的組件模型,比如說Web Service;從架構設計師的角度,SOA就是一種新的設計模式,方法學;從業務分析人員的角度,SOA就是基于標準的業務應用服務。從概念的角 度,IBM對SOA的定義是最為全面的,既SOA是一種構造分布式系統的方法,它將業務應用功能以服務的形式提供給最終用戶應用或其他服務。SOA包括如 下要素:
本文針對的讀者是軟件開發人員,站在開發人員的角度,往往希望軟件開發能夠滿足對于開發效率、可靠性、易維護性、易管理等多方面的更高要求。讓我們通過回顧軟件開發的演化過程來看一看SOA出現的必然性:
我們注意到,SOA同樣也強調重用(Reuse), 但是相對于傳統的代碼重用,對象重用,和部件重用,SOA的重用粒度更粗。SOA的重用在于業務級的應用,即服務的重用,這與軟件的發展規律是相一致的。 在軟件發展的過程中,軟件重用的對象越來越接近我們的現實生活。通過部件的重用,軟件的開發更具效率,并且開始試圖用組件表達業務模式。但是,IT人員仍 很難對業務人員解釋清楚IT結構怎樣映射到業務模型上。然而,IT架構與業務模型的彌合是不可避免的方向。現代企業的業務環境所面臨的最大挑戰就是變化, 規則在變,需求在變,而對變化做出最快的反應,盡快地適應變化,成為企業占得先機,成功運作的關鍵。很多企業的業務環境依賴于他們的IT架構,因此,IT 部門往往直接承載了業務變化帶來的壓力。每一個具體的業務變化,都直接反應到對現有的IT平臺的要求:要么企業IT架構本身對變化自適應,要么IT架構能 夠在短時間內根據新的業務規則做出調整。這就是SOA架構提出的根本原因,我們需要一種更加貼近業務的IT架構,能夠直接描繪業務,對那些不懂IT技術的 業務領域專家來說,業務服務卻是他們最熟悉的,也就是說是SOA把軟件重用的對象從IT人員上升到了業務人員。因此,我們可以說SOA與其它的模式相比, 最大的進步在于它與業務的關聯性,"服務"對應到實際業務。IT通過"服務"與業務發生了密切的關系,業務人員和IT人員都可以專注于業務邏輯的實現,而 共同的語言就是"服務"。
但不是什么場合都適用SOA。通常來講,SOA適用于較為復雜的IT架構,經常需要與外部復雜的IT環境交互,并且需要快 速地應對頻繁發生的業務變化。就像你不可能在控制洗衣機的芯片上使用EJB開發一樣,如果你的IT環境規模很小,足以靈活地應對變化,不需要與其他的異構 IT環境頻繁交互,那么SOA帶來的好處就不足以抵消它給你帶來的系統復雜性。但是,即令如此,你也并沒有被完全排除在SOA的大趨勢之外。SOA是如此 地倍受矚目,我們可以預見到它的迅猛發展,因此即使你的內部IT架構本身并不是基于SOA的,你也還有機會參與到未來的SOA架構中去。例如,將你的某個 業務以服務的形式發布到某個外部SOA平臺上供別人使用,作為第三方SOA平臺的一個服務提供者(Service Provider)存在。
在選擇SOA的實施方案時,要記住,軟件的具體實現技術諸如Web 服務與SOA是兩回事,SOA是一個概念,方法學, 或者用一個更時髦的詞:一種模型。而Web 服務呢?它是一種具體的實現技術,就像EJB一樣。SOA ≠ Web服務。不過公平地講,Web 服務倒確實是目前最適合實現SOA的技術之一,用Web 服務來封裝業務服務是個不錯的選擇。因為Web服務是標準的,WS-I協議保證了來自不同廠商的Web服務即使運行在不同的平臺上,底層的實現機理不同也 可以順利交互,這是以前的任何一種技術如CORBA,EJB,或DCOM都不能做到的。而且,Web服務的定義與實現是分開描述的,即松散耦合,因此,可 以很方便地替換服務的內在實現而不會對現有的系統造成任何沖擊,這也極大地促進了IT架構的靈活性。
對于SOA更進一步的了解,可以參考IBM developerWorks上其他SOA相關的文章(請參見參考資料),我們的系列文章將主要討論ESB,因此不再此過多地論述SOA了。為了使我們下面的論述更順暢,請先牢記典型的SOA架構有哪些基本的要求:
讓我們暫時回到網絡技術不普及的時代,你怎樣在兩臺機器之間傳遞文件?我還記得為了給實驗室的每臺機器安裝Borland C++的環境,猜猜我動用了什么:一根"串口線"。不過,我仍然覺得慶幸,好在每臺機器都運行同樣的操作系統- DOS(很少有人還記得DOS中有Interlnk這樣一個命令吧), 用來通過串口線在兩臺機器間傳遞流文件。否則我將不得不用軟盤來拷貝所有的安裝文件。我那個時候的夢想就是,哪一天有這么一個叫做"網絡"的東西能夠把實 驗室里面所有機器都連接起來,而不用我在各機器之間跑來跑去。
讓我們回歸主題,你現在已經基本明白了什么是SOA。假定你已經按照SOA的思想提煉出了各種業務服務,公布出來,同樣, 你發現其他很多人也做了同樣的事情。大家都很振奮,開始踴躍的嘗試,我調用你的一個服務,你調我的一個服務。啊哈!大家都SOA了。且慢,那么這個SOA 給你們帶來了什么好處呢?Ok,現在我可以在J2EE環境里調用.Net的組件了,但是原來沒有SOA的時候也可以做到的呀。只要兩個節點之間互相認可對 方的方式,即使不存在公開/統一的服務界面也可以實現點到點的互聯。因此我們不得不承認,如果我們只有服務,而服務的請求者和服務的提供者之間仍然需要這 種顯式的點到點的調用,那么這就不是一個典型的SOA架構。請看圖二,服務的參與雙方都必須建立1對1 的聯系。這樣一個結構與我十幾年前的那種互聯的方式何其相似!但是,還記得我們上面提到的SOA三個基本要素嗎?顯然第三點沒有做到。
因此,在SOA中,我們還需要這樣一個中間層,能夠幫助實現在SOA架構中不同服務之間的智能化管理。最容易想到的是這樣 一個HUB-Spoke結構,在SOA架構中的各服務之間設置一個類似于Hub的中間件,由它充當整個SOA架構的中央管理器的作用。請看圖三,現在服務 的請求者和提供者之間有了一個智能的中轉站, 服務的請求者不再需要了解服務提供者的細節。不錯!看上去是一個好的SOA結構。事實上,傳統的EAI就是通過這樣一種方式來試圖解決企業內部的應用整合 問題。
EAI的目標是支持對現有IT系統的重新利用,通過EAI技術能夠將不同的軟件和系統串聯起來,延長這些應用系統的生命周 期。傳統的EAI,往往使用如CORBA和COM等的消息中間件進行分布式,跨平臺的程序交互,修改企業資源規劃以達到新的目標,使用中間件、XML等方 法來進行數據分配。因此,實際上傳統的EAI是部件級的重用。很不幸的是,基于部件的架構沒有統一的標準,因此,各個廠商都有各自不同的EAI解決方案, 你會看到各種各樣的中間件平臺。如果EAI碰到了異構的IT環境,就必須分別考慮怎樣在各個不同的中間件之間周旋,來實現合理的互聯方式,你不得不考慮各 種復雜的可能性。因此,你所見過的大多數傳統EAI解決方案都比較笨重。
再回顧一下我們上面介紹過的SOA的應用場景:復雜的企業級架構。如果我們選擇Hub的模式來構建SOA基礎架構,從純粹 邏輯的角度,可能會出現哪些問題呢?首先,整個SOA架構的性能,如果每個服務的請求都經過中央Hub的中轉,那么Hub的負擔會很重,速度會隨著參與者 的增多而愈來愈慢;其次,這樣的系統會很脆弱,一旦Hub出錯,整個SOA架構都會癱瘓;最后,這樣的架構會破壞SOA的開放性原則,參與者運行在一個相 對封閉的環境中,擴展起來十分麻煩。因此,這也不是理想的SOA架構。
好了,現在該ESB登場了,請看我們的正解:
它與前面的Hub結構有什么不同呢?首先,它比單一Hub的形式更開放,總線結構有無限擴展的可能;其次,真正體現了 SOA的理念, 一切皆為服務,服務在總線(BUS)中處于平等的地位。即使我們需要一些Hub,那么它們也是以某種服務的形式部署在總線上,相比上面的結構要靈活的多。 這就是ESB,我們需要給它一個明確的定義:ESB是一種在松散耦合的服務和應用之間標準的集成方式。它可以作用于:
很不幸,上面的定義看上去很拗口,我們暫且用一句較通俗的話來描述它:ESB就是在SOA架構中實現服務間智能化集成與管 理的中介。而它與SOA的關系要相對好理解一些:ESB是邏輯上與SOA 所遵循的基本原則保持一致的服務集成基礎架構,它提供了服務管理的方法和在分布式異構環境中進行服務交互的功能。可以這樣說,ESB是特定環境下(SOA 架構中)實施EAI的方式: 首先,在ESB系統中,被集成的對象被明確定義為服務,而不是傳統EAI中各種各樣的中間件平臺,這樣就極大簡化了在集成異構性上的考慮,因為不管有怎樣 的應用底層實現,只要是SOA架構中的服務,它就一定是基于標準的。
其次,ESB明確強調消息(Message)處理在集成過程中的作用,這里的消息指的是應用環境中被集成對象之間的溝通。 以往傳統的EAI實施中碰到的最大的問題就是被集成者都有自己的方言,即各自的消息格式。作為基礎架構的EAI系統,必須能夠對系統范疇內的任何一種消息 進行解析。傳統的EAI系統中的消息處理大多是被動的,消息的處理需要各自中間件的私有方式支持,例如API的方式。因此盡管消息處理本身很重要,但消息 的直接處理不會是傳統EAI系統的核心。ESB系統由于集成對象統一到服務,消息在應用服務之間傳遞時格式是標準的,直接面向消息的處理方式成為可能。如 果ESB能夠在底層支持現有的各種通訊協議,那么對消息的處理就完全不考慮底層的傳輸細節,而直接通過消息的標準格式定義來進行。這樣,在ESB中,對消 息的處理就會成為ESB的核心,因為通過消息處理來集成服務是最簡單可行的方式。這也是ESB中總線(Bus)功能的體現。其實,總線的概念并不新鮮,傳 統的EAI系統中,也曾經提出過信息總線的概念,通過某種中間件平臺,如CORBA來連接企業信息孤島,但是,ESB的概念不僅僅是提供消息交互的通道, 更重要的是提供服務的智能化集成基礎架構。
最后,事件驅動成為ESB的重要特征。通常服務之間傳遞的消息有兩種形式,一種是調用(Call), 即請求/回應方式,這是常見的同步模式。還有一種我們稱之為單路消息(One-way),它的目的往往是觸發異步的事件, 發送者不需要馬上得到回復。考慮到有些應用服務是長時間運行的,因此,這種異步服務之間的消息交互也是ESB必須支持的。除此之外,ESB的很多功能都可 以利用這種機制來實現,例如,SOA中服務的性能監控等基礎架構功能,需要通過ESB來提供數據,當服務的請求通過ESB中轉的時候,ESB很容易通過事 件驅動機制向SOA的基礎架構服務傳遞信息。
首先,我們來看一看ESB有哪些基本的功能。既然ESB會以中介的身份出現,它就必須有兩方面的考慮,首先它必須了解被它 中介的兩個端點:1)服務的請求者以及請求者對服務的要求,2)服務的提供者和它所提供服務的描述;其次,它必須具有某種機制能夠完成中介的任務。我們把 這兩類考慮歸納為ESB的兩個基本功能:面向服務的原數據(MetaData)管理功能 和中介(Mediation)功能。 作為SOA的重要構成部分,ESB承擔的重任還包括怎樣將企業架構中已存在的業務服務連接到總線上來,我們稱之為適配器(Adapter)功能。盡管服務 本身已經用公開的接口來描述,但具體的實現還是運行在不同的環境中,因此,ESB還應該提供對服務底層協議的支持,譬如應用協議J2ee,.Net, 通訊協議如Http,JMS等等。除此之外,還需要對具體應用中涉及到的服務加以管理,如性能,可靠性,安全性等等。
ESB 提供了最基本的功能來保障SOA系統的運行,這些功能應該包含下列內容:
很多時候,很難界定哪些功能是應該由SOA的基礎架構(infrastructure)提供的,而哪些應該放在ESB的范 疇內來解決。筆者認為,放大或突出ESB在SOA架構中的地位并不很恰當。比較合理的解釋是:ESB應該構筑在完善的SOA架構上,做它應該做的事-服務 集成。至于怎樣集成,應該根據你的上下文環境,考慮有哪些SOA的基礎設施可供你使用,然后再基于SOA的基礎架構來實現你的ESB設計。
在更高的層次,ESB還提供諸如服務代理,協議轉換等等功能,我們稱之為ESB的應用模式(ESB usage pattern)。作為SOA架構的服務集成功能提供者,我們可以總結出的一些比較常用的應用模式,例如:
1)協議轉換模型,用于當服務的請求者與服務提供者基于不同協議時的消息轉換情形
2)消息廣播模式,用于事件驅動多個動作或者消息廣播的情形
3)服務匹配模式,用于需要動態選擇服務提供者的情形,例如可以根據消息的內容,或負載情況,或服務級別約定(SLA),來為服務請求者選擇合適的服務。
這里我們只列舉了3個典型的模式,而這樣的例子實在太多了,發揮你的創造性,你還會想出來更多的,這也是ESB的魅力所 在。但是,在ESB的設計上,注意不能喧賓奪主,ESB的功能在于幫助服務的集成,而不是參與業務邏輯。業務邏輯應該封裝在業務服務中,或通過業務編排服 務(Process Service)來組織。
關于ESB,目前還沒有被一致接受的標準。我們可以通過選擇成熟的EAI 中間件來實現服務的集成與互操作性。這樣做的好處是你的開發過程會很順暢,因為它已經足夠穩定且有豐富的工具支持。通常這樣的EAI產品在目前階段都還不 是基于開放的標準,例如IBM的WebSphere MQ5.3,作為IBM EAI實現ESB的消息平臺,就不是開放的標準。如果一定要選擇開放標準的ESB實現方式,Web 服務加上WS-* 協議幾乎是我們唯一的選擇,但畢竟SOA、ESB仍處于起步的階段,一方面我們還沒有很成熟的產品支持所有的WS-*協議,另一方面這些WS-* 協議本身還處在頻繁變化的階段。因此當你選擇ESB實施方案的時候,最好考慮平衡ESB實施、開發的工作量。
這里你可能會有疑問,既然SOA架構追求開放性,為什么我們要容忍用私有的ESB產品如IBM WBI/MQ來構建SOA架構的集成環境?這是一個好問題。SOA始終是我們追求的大目標,開放是必然的趨勢,這是毋庸置疑的。但是,請注意ESB的定 義,至少到目前為止,還沒有明確的要求它的實現一定是開放的,每一個軟件供應商對它都可能有不同的理解和實現的策略。我們不用懷疑ESB將來的開放之路, 但至少在目前階段,我們不能坐下來等待它的到來。 其實,ESB充當的是SOA中的中介角色,因此,即使將來ESB變化了,對服務的請求者和服務的提供者都不會造成很大的沖擊,因為它本來就是對用戶透明 的。舉個例子,J2EE,它的標準一直在變化中,但是大家通常都能接受它的變化,社會總是要進步的,IT也一樣。你不可能因為J2EE 兩年以后要出1.6就不再使用現在的1.4了。
IBM目前可以用于ESB實施的產品也可以分為兩大陣營:
現有的EAI解決方案,可能涉及如下的IBM軟件產品:
WAS6 中提供了嶄新的消息服務平臺WPM(WebSphere platform messaging),并基于這一平臺提供了ESB的一個具體實現- SIBus(Service Integration Bus) 它可以支持同步和異步的消息通信。總線(Bus)通過互聯的消息引擎管理消息源。同時支持基于Web服務和JMS,MQ格式的消息交互。你可以從WAS6 身上看到IBM戰略的變化,SIBus只是IBM加大對于SOA支持的一步,你還會很快看到更多的變化,例如獨立的ESB產品,ESB的開發工具等等。但 是,你完全不必擔心,這些變化都會保持兼容性,現在SOA的投入,無論是以哪一種方式,都會在IBM的SOA整體考慮之中。
上述的兩種方案并不是對立的,你可以選擇基于成熟產品實現ESB,也可以嘗試一下IBM的最新技術。這兩種方案甚至可以互聯,見圖八。我們將在系列的第四部分講解這一較為復雜的場景。
在本系列文章接下來的三部分中,我們將繼續詳細描述ESB的具體實現步驟。
本文向您介紹了SOA以及ESB 的基本知識,確定了一些 ESB 實現中最常見的基本功能,論述了ESB產生的必要性,以及ESB在SOA中的地位。
李珉,IBM SOA Design Center 高級工程師,技術經理,曾領導WAS6 SIBus的測試工作,對ESB的技術發展一直有所關注。
1996年,Gartner最早提出SOA。2002年12月,Gartner提出SOA是"現代應用開發領域最重要的課題",SOA并不是一個新事 物,IT組織已經成功建立并實施SOA應用軟件很多年了,BEA、IBM、等廠商看到了它的價值,紛紛跟進。SOA的目標在于讓IT變得更有彈性,以更快 地響應業務單位的需求,實現實時企業(Real-Time Enterprise,這是Gartner為SOA描述的愿景目標)。而BEA的CIO Rhonda早在2001年6月就提出要將BEA的IT基礎架構轉變為SOA,并且從對整個企業架構的控制能力、提升開發效率、加快開發速度、降低在客戶 化和人員技能的投入等方面取得了不錯的成績。
SOA是在計算環境下設計、開發、應用、管理分散的邏輯(服務)單元的一種規范。這個定義決定了SOA的廣泛性。SOA要求開發者從服務集成的 角度來設計應用軟件,即使這么做的利益不會馬上顯現。SOA要求開發者超越應用軟件來思考,并考慮復用現有的服務,或者檢查如何讓服務被重復利用。SOA 鼓勵使用可替代的技術和方法(例如消息機制),通過把服務聯系在一起而非編寫新代碼來構架應用。經過適當構架后,這種消息機制的應用允許公司僅通過調整原 有服務模式而非被迫進行大規模新的應用代碼的開發,使得在商業環境許可的時間內對變化的市場條件做出快速的響應。
SOA也不僅僅是一種開發的方法論--它還包含管理。例如,應用SOA后,管理者可以方便的管理這些搭建在服務平臺上的企業應用,而不 是管理單一的應用模塊。其原理是,通過分析服務之間的相互調用,SOA使得公司管理人員方便的拿到什么時候、什么原因、哪些商業邏輯被執行的數據信息,這 樣就幫助了企業管理人員或應用架構師迭代地優化他們的企業業務流程、應用系統。
SOA的一個中心思想就是使得企業應用擺脫面向技術的解決方案的束縛,輕松應對企業商業服務變化、發展的需要。企業環境中單個應用程序 是無法包容業務用戶的(各種)需求的,即使是一個大型的ERP解決方案,仍然不能滿足這個需求在不斷膨脹、變化的缺口,對市場快速做出反應,商業用戶只能 通過不斷開發新應用、擴展現有應用程序來艱難的支撐其現有的業務需求。通過將注意力放在服務上,應用程序能夠集中起來提供更加豐富、目的性更強的商業流 程。其結果就是,基于SOA的企業應用系統通常會更加真實地反映出與業務模型的結合。服務是從業務流程的角度來看待技術的--這是從上向下看的。這種角度 同一般的從可用技術所驅動的商業視角是相反的。服務的優勢很清楚:它們會同業務流程結合在一起,因此能夠更加精確地表示業務模型、更好地支持業務流程。相 反我們可以看到以應用程序為中心的企業應用模型迫使業務用戶將其能力局限為應用程序的能力。
企業流程(enterprise process)是流經企業框架的空氣,它賦予業務模型里的組件以生命,并更加清晰地定義了它們之間的關系。流程定義了同業務模型進行交互操作的專門方 法。例如,會計可能是企業服務系統的一個組件--但是將發票寄給客戶卻是一個業務流程。服務被定義用來支持業務流程,因而貫穿整個流程始終的是:各種服務 組件在流程和邏輯實現過程中的裝配操作。理解業務流程是定制服務的關鍵所在。
二、SOA 的描述所適用的原則
圖 1說明了這些原則。注意,雖然 Web 服務技術非常符合這些原則,但它并不是唯一符合這些原則的技術。
為了實現 SOA,應用程序和基礎架構都必須支持 SOA 原則。啟用 SOA 應用程序涉及到創建服務接口,服務接口可以直接也可以間接地通過使用適配器用于現有的或新的功能。從最基本的級別來看,啟用該基礎架構涉及到規劃功能來將服務請求路由和傳遞給正確的服務提供者。然而,基礎架構支持在不影響服務的客戶端的情況下由另一個服務實現替代原有的服務實現也是至關重要的。這不僅需要根據 SOA 原則指定服務接口,而且需要基礎架構允許客戶端代碼以獨立于所涉及的服務位置和通信協議的方式來調用服務。
三、ESB是什么?
根據維基百科的ESB定義,ESB有如下特性:
對于其中一些廠商(IBM、微軟)來說,ESB是將一系列能力聯結在一起的一種模式,而其他廠商認為ESB是一種產品。在2005年,微軟Identity Platform的產品經理Rich Turner寫道:
ESB[產品]是一根聰明的管子,用來連接各個愚笨的節點。[……]Web Service的途徑讓節點本身也變得聰明,減少了對底下聰明管道的需要,并確保了跨越任何平臺與設備的開放的通訊。