http://www-128.ibm.com/developerworks/cn/websphere/library/techarticles/yangjiang/0502/wsrp.html
楊江 軟件工程師 2005 年 3 月
本文介紹了WSRP 標(biāo)準(zhǔn),并在兩臺(tái)服務(wù)器上分別部署遠(yuǎn)程 portlet 來驗(yàn)證通過 WSRP 進(jìn)行的互操作。
概要 首先隨同本文在IBM WebSphere Portal 5.1服務(wù)器上以WSRP協(xié)議發(fā)布本地Portlet為Remote Portlet,通過WSRP協(xié)議消費(fèi)剛剛發(fā)布的Remote Portlet;然后在WSRP參考實(shí)現(xiàn)Apache WSRP4J上以WSRP協(xié)議發(fā)布本地Portlet為Remote Portlet,使用WSRP4J自帶的WSRP Consumer測(cè)試剛剛發(fā)布的Remote Portlet;最后我們?cè)赪ebSphere Portal服務(wù)器上消費(fèi)WSRP4J上發(fā)布的Remote Portlet以檢驗(yàn)WSRP在不同應(yīng)用服務(wù)器間的交互性。
引言 OASIS Web Services for Remote Portlets 技術(shù)委員會(huì)從2002年開始制定WSRP 1.0標(biāo)準(zhǔn),目的是開發(fā)一個(gè)允許門戶之間、門戶與其他應(yīng)用之間,能夠以即插即用的方式進(jìn)行用戶界面的交互的Web Service標(biāo)準(zhǔn)。
2003年9月3日,OASIS組織發(fā)布了WSRP:Web Services for Remote Portlets 1.0標(biāo)準(zhǔn)。WSRP使支持WSRP的容器和符合WSRP的任何門戶之間能夠進(jìn)行Portlet級(jí)別的互操作性。它的定義包括Remote Portlet的一個(gè)WSDL(Web Services Description Language ,Web服務(wù)描述語言)接口、通過WSDL定義的一套R(shí)emote Portlet交互的語義,以及WSRP服務(wù)產(chǎn)生的標(biāo)記片斷的規(guī)則。
有了WSRP標(biāo)準(zhǔn),企業(yè)門戶不僅可以混合使用不同廠商的門戶服務(wù)器,靈活地部署Portlets,使用WSRP將企業(yè)門戶中各個(gè)門戶服務(wù)器統(tǒng)一起來,充分利用到不同門戶服務(wù)器的特有功能和產(chǎn)品特性。企業(yè)門戶還可以通過WSRP遠(yuǎn)程調(diào)用合作伙伴提供的遠(yuǎn)程Portlet服務(wù),把合作伙伴的遠(yuǎn)程Portlet直接放到本企業(yè)的門戶界面中,使得企業(yè)和合作伙伴的溝通更加方便快捷。
WSRP給服務(wù)供應(yīng)商帶來了新的商機(jī)。服務(wù)供應(yīng)商可以提供Remote Portlet服務(wù),比如天氣預(yù)報(bào)、股票、新聞、網(wǎng)上定票等服務(wù),企業(yè)只需要通過Internet和WSRP協(xié)議就可以方便的在企業(yè)門戶中使用到這些服務(wù),不需要編寫任何代碼。
在WSRP服務(wù)最常見的應(yīng)用模式中,WSRP 服務(wù)是包括表示層與應(yīng)用程序邏輯的可視的遠(yuǎn)程門戶服務(wù);門戶服務(wù)器既可以是Remote Portlet的提供者,也可以是Remote Portlet的消費(fèi)者。門戶服務(wù)器可以通過Internet,使用WSRP協(xié)議把本地Portlet暴露為Remote Portlet,這樣門戶服務(wù)器就是WSRP服務(wù)的提供者。門戶服務(wù)器也可以通過WSRP通用代理跨過 Internet網(wǎng)絡(luò),使用WSRP協(xié)議調(diào)用遠(yuǎn)程的WSRP服務(wù),這樣門戶服務(wù)器就是WSRP服務(wù)的消費(fèi)者。
WSRP提供者也可以把WSRP服務(wù)作為Web Service注冊(cè)到UDDI服務(wù)器上,而WSRP消費(fèi)者可以到UDDI服務(wù)器上查找需要的WSRP服務(wù),進(jìn)而通過Portlet 代理訪問遠(yuǎn)程WSRP服務(wù)。
圖1 即插即用的WSRP服務(wù)
需要特別指出的是,WSRP服務(wù)的消費(fèi)者也可以是普通的應(yīng)用程序,通過WSRP協(xié)議訪問后臺(tái)WSRP Portlet服務(wù),通過COM組件或者ActiveX控件顯示W(wǎng)SRP服務(wù)返回的標(biāo)記片斷。IBM Workplace Client Technology(基于Eclipse Rich Client Platform)中將提供WSRP消費(fèi)者Plug-in,把Remote Portlet集成到其用戶界面中來。
本文適用于門戶架構(gòu)師、WebSphere Portal管理員,具有一些 Web Service、WebSphere Portal服務(wù)器方面的經(jīng)驗(yàn)會(huì)有所幫助。
在WebSphere Portal上安裝部署WSRP服務(wù) 2002年初,IBM在WebSphere Portal 4.0中提供了其專有技術(shù)RPWS,通過Web Service把Portlet發(fā)布為Remote Portlet;2004年初,IBM在WebSphere Portal 5.0 Fixpack 2開始提供WSRP的技術(shù)預(yù)覽;2004年11月,IBM在WebSphere Portal 5.1中提供WSRP的全面支持。
1.安裝Portlet IBM在WebSphere Portal and Lotus Workplace Catalog網(wǎng)站上提供了叫做WebSphere Portal V5.1 Sample Code的應(yīng)用(Portlet Application),其中有基于Struts框架的使用IBM Portlet API的portlets,也有使用JSR 168 API編寫的portlets。任何人都可以通過IBM Portlet代碼"1wp10004n" 檢索并免費(fèi)下載這個(gè)應(yīng)用。下面我們?cè)赪ebSphere Portal上面部署這個(gè)Portlet。解壓縮下載的1wp10004n.zip文件,進(jìn)入1wp10004n\Basic\JSR168目錄,我們會(huì)看到j(luò)srHelloJSP.war等4個(gè)war文件,這些war文件都是打包的JSR 168 Portlet例子應(yīng)用。
在WebSphere Portal管理頁面中選擇Portlet 管理-> Web 模塊,選擇"安裝"命令按鈕,選擇jsrHelloJSP.war文件,選擇"下一步"開始安裝即可。在Portlet 管理 ->Portlets可以檢索到剛剛安裝的Hello JSP (JSR 168)。最后我們把這個(gè)Portlet放到測(cè)試頁面上。結(jié)果如圖2。
圖2 Hello JSP(JSR 168)運(yùn)行結(jié)果
2.提供portlet 在WebSphere Portal管理頁面中選擇Portlet 管理-> Web 模塊,搜索標(biāo)題的開頭為"Hello"的Portlet,在"Hello JSP(JSR 168)"小程序的右邊有五個(gè)命令按鈕,選擇最左邊的"提供portlet"按鈕,就可以把這個(gè)Portlet發(fā)布為Remote Portlet。
圖3提供portlet
在Portlet管理界面中我們看到"成功將portlet Hello JSP(JSR 168)提供為Web服務(wù)",并且這個(gè)Portlet顯示出"已提供"的標(biāo)記。
圖4 已提供Portlet
我們剛剛安裝了一個(gè)JSR 168 Portlet,通過WSRP把這個(gè)portlet提供為Remote Portlet。下面我們將消費(fèi)這個(gè)Remote Portlet。
3.注冊(cè)WSRP Producer 在WebSphere Portal管理頁面中選擇Portlet 管理->Web Service,選擇新建Producer。輸入標(biāo)題,輸入WPS 5.1的WSDL服務(wù)定義的URL,比如http://wps51.cn.ibm.com:9081/wps/wsdl/wsrp_service.wsdl
圖5新建Producer
4.消費(fèi)Remote Portlet 在WebSphere Portal管理頁面中選擇Portlet 管理->Web模塊,選擇"使用"命令按鈕,鼠標(biāo)左鍵點(diǎn)擊剛注冊(cè)的Web Service Provider。
圖 6使用portlet
WebSphere Portal作為WSRP的消費(fèi)者,通過WSRP協(xié)議檢索WSRP提供者提供的Remote Portlet。在圖7我們看到剛剛注冊(cè)的"WSRP Producer on WP 5.1"提供了多個(gè)Remote Portlet,"選擇"Hello JSP(JSR 168),確認(rèn),在圖8中我們看到一個(gè)叫做RP[Hello JSP(JSR 168)]的Portlet,我們可以把這個(gè)Remote Portlet象本地Portlet一樣部署到測(cè)試頁面上,運(yùn)行結(jié)果如圖9所示。
圖 7 選擇Web service
圖 8選擇Web service的結(jié)果
圖 9 包含Remote Portlet的測(cè)試頁面
安裝JSR 168參考實(shí)現(xiàn)Apache Pluto Apache Software Foundation 在2004年12月22日發(fā)布了 Java Portlet Specification 1.0參考實(shí)現(xiàn)Pluto 1.0.1-rc2版本。版本號(hào)中的rc表示release candidate,rc2表示這個(gè)版本已經(jīng)是第二個(gè)發(fā)布候選版本,離正式版本1.0.1的發(fā)布已經(jīng)很近了。
1 安裝Pluto二進(jìn)制發(fā)行版本 Pluto提供了四種打包方式,其中最簡(jiǎn)單的打包方式是和Tomcat 5.5.4(Build Oct 29 2004)捆綁在一起的二進(jìn)制發(fā)行版本,只要在Pluto下載網(wǎng)站下載pluto-1.0.1-rc2.zip文件,解壓縮到指定目錄就可以了。注意:pluto-1.0.1-rc1二進(jìn)制發(fā)行版本采用的是Tomcat 5.0.28。
如果在啟動(dòng)Tomcat的時(shí)候提示啟動(dòng)系統(tǒng)找不到文件 -Djava.endorsed.dirs=,那么可以在命令行下面執(zhí)行 set JAVA_HOME=c:\jdk1.5.0
圖 10 Pluto界面
2 安裝Pluto源代碼發(fā)行版本 Pluto另外一種常用的發(fā)行版本是源代碼發(fā)行版本,目前,要在Pluto上自動(dòng)部署新的portlet,必須使用這種版本。在Pluto下載網(wǎng)站下載pluto-src-1.0.1-rc2.zip文件,參考Pluto安裝指南進(jìn)行安裝即可。
安裝這種發(fā)行版本,事先要下載Tomcat、Marven,在部署的時(shí)候要求有Internet連接,部署程序會(huì)從Internet上下載需要的java package。
注意,pluto-src-1.0.1-rc2可以使用JDK 1.4.2進(jìn)行部署,但是不能使用JDK 1.5進(jìn)行部署。使用JDK 1.5會(huì)報(bào)如下錯(cuò)誤:
pluto-src-1.0.1-rc2\portal\src\java\org\apache\pluto\portalImpl\om\common\impl\LanguageImpl.java:58: as of release 1.5, 'enum' is a keyword, and may not be used as an identifier (try -source 1.4 or lower to use 'enum' as an identifier)
3 使用Pluto源代碼發(fā)行版本在在Pluto上部署Portlet 設(shè)置JAVA_HOME、MAVEN_HOME、PATH等環(huán)境變量。
set JAVA_HOME=C:\j2sdk1.4.2 SET MAVEN_HOME=C:\apache\maven-1.0.2 SET PATH=%MAVEN_HOME%\bin;%PATH%
拷貝WebSphere Portal V5.1 Sample Code中的jsrHelloJSP.war到c:\apache目錄。
進(jìn)入Pluto源代碼發(fā)行版本的根目錄,調(diào)用maven部署Portlet到Pluto。
CD C:\apache\pluto-src-1.0.1-rc2 maven deploy -Ddeploy=c:\apache\jsrHelloJSP.war
注意:下面的部署新的portlet操作在Pluto
1.0.1-rc2源代碼版本版本中不能工作,但是可以在Pluto運(yùn)行版本中可以正常工作。
進(jìn)入Pluto的webapps目錄,我們會(huì)看到有個(gè)jsrHelloJSP目錄,這里就是部署后的Portlet目錄。
Pluto部署代碼在jsrHelloJSP\WEB-INF\tld目錄下面增加了一個(gè)portlet.tld文件,同時(shí)在web.xml文件中增加了對(duì)做個(gè)portlet.tld文件的引用。
<taglib>
<taglib-uri>http://java.sun.com/portlet</taglib-uri>
<taglib-location>/WEB-INF/tld/portlet.tld</taglib-location>
</taglib>
|
我們需要手工刪除部署后的web.xml文件中對(duì)于std-portlet.tld的引用內(nèi)容:
<taglib>
<taglib-uri>http://java.sun.com/portlet</taglib-uri>
<taglib-location>/WEB-INF/tld/std-portlet.tld</taglib-location>
</taglib>
|
部署Portlet到頁面的方法參考Pluto安裝指南即可。需要注意的是Pluto安裝指南中application ID指的就是應(yīng)用名稱jsrHelloWorld,PortletID指的是web.xml文件中的portlet-guid參數(shù)值。
<init-param>
<param-name>portlet-guid</param-name>
<param-value>jsrHelloJSP.Hello JSP Portlet name</param-value>
</init-param>
|
安裝WSRP 參考實(shí)現(xiàn)Apache WSRP4J
1 安裝WSRP4J 閱讀WSRP4J安裝文檔,下載Tomcat 5(比如jakarta-tomcat-5.0.30版本),解壓縮到c:\apache\ jakarta-tomcat-5.0.30-wsrp4j。
如果在啟動(dòng)Tomcat的時(shí)候提示啟動(dòng)系統(tǒng)找不到文件 -Djava.endorsed.dirs=,那么可以在命令行下面執(zhí)行 set JAVA_HOME=C:\j2sdk1.4.2或者把這一行加入到bin\startup.bat和bin\shutdown.bat里面。
注意:WSRP4J使用的Pluto不是最新的版本,所以WSRP4J要使用JDK 1.4.2,而不是最新的Pluto使用的JDK 1.5。
參考http://ws.apache.org/wsrp4j/contributing/cvs.html,使用cvs client下載WSRP4J源代碼。
set path="C:\Program Files\CVS for NT";%path%
cvs -d :pserver:anoncvs@cvs.apache.org:/home/cvspublic login
password: anoncvs
cvs -d :pserver:anoncvs@cvs.apache.org:/home/cvspublic checkout ws-wsrp4j
|
更改下面三個(gè)目錄下面的build.properties.example文件的文件名為build.properties
ws-wsrp4j\build\
ws-wsrp4j\portlets\proxyportlet
ws-wsrp4j\portlets\wsrptest
|
修改上述三個(gè)文件build.properties,設(shè)置TOMCAT_HOME=C:/apache/ jakarta-tomcat-5.0.30-wsrp4j
安裝WSRP4J到Tomcat 5:
set JAVA_HOME=C:\j2sdk1.4.2
set path=%JAVA_HOME%\bin;%path%
cd ws-wsrp4j\build
install-swing-consumer
install-provider-pluto
|
最后顯示下面字樣,就是已經(jīng)成功安裝了基于Pluto的WSRP provider,并且安裝了一個(gè)測(cè)試用Portlet-'wsrptest'。
prepare-producer:
Created dir: C:\Apache\jakarta-tomcat-5.0.30-wsrp4j\webapps\wsrp
…
prepare-provider-pluto:
Copying 13 files to C:\Apache\jakarta-tomcat-5.0.30-wsrp4j\webapps\wsrp
Copying 1 file to C:\Apache\jakarta-tomcat-5.0.30-wsrp4j\webapps\wsrp\WEB-INF\lib
…
BUILD SUCCESSFUL
Total time: 3 seconds
|
2 測(cè)試WSRP4J消費(fèi)者程序 啟動(dòng)Tomcat,缺省Tomcat監(jiān)聽8080端口。
set JAVA_HOME=C:\j2sdk1.4.2
Cd C:\apache\jakarta-tomcat-5.0.30-wsrp4j\bin
startup.bat
|
執(zhí)行腳本C:\apache\ws-wsrp4j\tools\tunnel.bat以啟動(dòng)Apache Axis TCP Monitor,這個(gè)Monitor一般用于web service debug。通常Tomcat監(jiān)聽8080端口,tunnel腳本缺省監(jiān)聽8081端口并且向8080端口寫數(shù)據(jù)。
set CLASSPATH=C:\apache\ws-wsrp4j\driver\SwingConsumer\lib\axis.jar
rem java org.apache.axis.utils.tcpmon [listening_port] [target_host] [target_port]
java org.apache.axis.utils.tcpmon 8081 localhost 8080
|
運(yùn)行WSRP Consumer(消費(fèi)程序,調(diào)用遠(yuǎn)程Remote Portlet),缺省WSRP Consumer通過8081連接WSRP Producer。
cd C:\apache\ws-wsrp4j\driver\SwingConsumer
run.bat
|
圖 11 WSRP4J Consumer
3 在WSRP4J上發(fā)布新的Remote Portlet 從%Pluto_Home%\webapps目錄下拷貝testsuite目錄到%WSRP4J_Home%\webapps目錄下。
從%Pluto_Home%\webapps\pluto\WEB-INF\data\portletentityregistry.xml文件中拷貝testsuite.TestPortlet1的定義到%WSRP4J_Home%\webapps\wsrp\WEB-INF\data\portletentityregistry.xml文件中。
<application id="3">
<definition-id>testsuite</definition-id>
<portlet id="1">
<definition-id>testsuite.TestPortlet1</definition-id>
<preferences>
<pref-name>TestName4</pref-name>
<pref-value>TestValue4</pref-value>
<read-only>true</read-only>
</preferences>
</portlet>
</application>
|
你也可以通過Pluto源代碼的maven deploy命令在Pluto上面部署新的Portlet,然后把相應(yīng)的目錄(比如jsrHelloJSP)拷貝到%WSRP4J_Home%\webapps目錄下,然后編輯相應(yīng)的WSRP4J portlet注冊(cè)文件。
4 為WSRP4J Consumer提供新的WSRP Portlet服務(wù) 接下來為WSRP Consumer配置要消費(fèi)的Remote Portlet的handler、放置Remote Portlet的測(cè)試頁面。在driver/SwingConsumer/persistence/portlets目錄下面增加一個(gè)文件,org.apache.wsrp4j.consumer.driver.WSRPPortletImpl@WSRP4J_3_1.xml。
<?xml version="1.0"?>
<Portlet>
<portlet-key>
<portlet-handle>3.1</portlet-handle>
<producer-id>1</producer-id>
</portlet-key>
<parent-handle>3.1</parent-handle>
</Portlet>
|
修改driver/SwingConsumer/persistence/pages/org.apache.wsrp4j.consumer.app.driver.PageImpl@WSRP4JTestPortlets.xml文件,
<?xml version="1.0" encoding="UTF-8"?>
<page pageID="1" title="WSRP4J Test"><portlet-key xsi:type="java:org.apache.wsrp4j.consumer.driver.PortletKeyImpl" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<portlet-handle>3.1</portlet-handle>
<producer-id>1</producer-id>
</portlet-key></page>
|
重新啟動(dòng)WSRP服務(wù)和WSRP消費(fèi)者程序,運(yùn)行結(jié)果如下:
圖12 WSRP Consumer測(cè)試新增加的Remote Portlet - Pluto testsuite
如果是把jsrHelloJSP portlet發(fā)布到WSRP4J上面,運(yùn)行結(jié)果如下:
圖 13 WSRP Consumer測(cè)試新增加的Remote Portlet - jsrHelloJSP
WebSphere Portal調(diào)用WSRP4J發(fā)布的Remote Portlet 現(xiàn)在我們已經(jīng)有兩個(gè)WSRP的支撐環(huán)境了,他們都能各自獨(dú)立地發(fā)布和消費(fèi)Remote Portlet?,F(xiàn)在讓我們測(cè)試一下他們的互通性。
1. 注冊(cè)WSRP Producer 在WebSphere Portal管理頁面中選擇Portlet 管理->Web Service,選擇"新建Producer"。輸入標(biāo)題,輸入WSRP4J的WSDL服務(wù)定義的URL,比如http://localhost:8081/wsrp/wsdl/wsrp4j_service.wsdl。
圖14 新建Producer
圖15 成功創(chuàng)建Producer
2.消費(fèi)Remote Portlet 在WebSphere Portal管理頁面中選擇Portlet 管理->Web模塊,選擇"使用"命令按鈕,鼠標(biāo)左鍵點(diǎn)擊剛注冊(cè)的Web Service Provider。 WebSphere Portal作為WSRP的消費(fèi)者,通過WSRP協(xié)議檢索WSRP提供者提供的Remote Portlet。在圖16我們看到WSRP4J提供了多個(gè)Remote Portlet,"選擇"Hello JSP portlet (JSR 168) 和WSRP Test Portlet。我們可以把這個(gè)Remote Portlet象本地Portlet一樣部署到測(cè)試頁面上,運(yùn)行結(jié)果如圖17所示 。
圖 16 選擇Web service
圖17 WebSphere Portal消費(fèi)WSRP4J提供的Remote Portlet
注意事項(xiàng): 1.如果需要通過不同的IP地址和端口訪問WSRP4J,需要修改WSRP4J的webapps\wsrp\wsdl\wsrp4j_service.wsdl文件中的主機(jī)名和端口號(hào)。
2. WebSphere注冊(cè)WSRP4J為web service producer后,這個(gè)Producer的Registration handle 為192.168.200.132_1107045794015_2(例子)。相應(yīng)的WSRP4J會(huì)產(chǎn)生一個(gè)兩個(gè)文件登記WebSphere Portal為Consumer,這兩個(gè)文件分別是org.apache.wsrp4j.producer.driver.RegistrationImpl@14647882.xml,和org.apache.wsrp4j.producer.provider.driver.ConsumerPortletRegistrationImpl@192.168.200.132_1107045794015_2.xml。
3. WebSphere Portal在"消費(fèi)"WSRP4J提供的Remote Portlet的時(shí)候,WSRP會(huì)修改webapps\wsrp\WEB-INF\data\ portletentityregistry.xml文件。
比如這個(gè)文件中原始的關(guān)于jsrHelloJSP的注冊(cè)信息如下:
<application id="5">
<definition-id>jsrHelloJSP</definition-id>
<portlet id="1">
<definition-id>jsrHelloJSP.Hello JSP Portlet name</definition-id>
<preferences>
<pref-name>TestName4</pref-name>
<pref-value>TestValue4</pref-value>
<read-only>true</read-only>
</preferences>
</portlet>
</application>
|
在WebSphere Portal把jsrHelloJSP注冊(cè)以后,WSRP4J會(huì)復(fù)制一份portlet的定義,并且指定新的portlet的id(比如192.168.200.132_1107046841484_0)。結(jié)果如下:
<application id="5">
<definition-id>jsrHelloJSP</definition-id>
<portlet id="192.168.200.132_1107046841484_0">
<definition-id>jsrHelloJSP.Hello JSP Portlet name</definition-id>
<preferences>
<pref-name>TestName4</pref-name>
<pref-value>TestValue4</pref-value>
<read-only>true</read-only>
</preferences>
</portlet>
<portlet id="1">
<definition-id>jsrHelloJSP.Hello JSP Portlet name</definition-id>
<preferences>
<pref-name>TestName4</pref-name>
<pref-value>TestValue4</pref-value>
<read-only>true</read-only>
</preferences>
</portlet>
</application>
|
4. 通過WSRP注冊(cè)的Portlet的標(biāo)題是從該P(yáng)ortlet的portlet.xml文件中portlet-info->title標(biāo)記中獲得的。
<portlet-info>
<title>Hello JSP portlet (JSR 168) Title</title>
<short-title>Hello Title</short-title>
<keywords>WSRP, Hello JSP</keywords>
</portlet-info>
|
結(jié)束語 WSRP規(guī)范小組和JSR 168 Portlet規(guī)范小組聯(lián)系非常緊密,最初的WSRP規(guī)范中定義的Portlet是要求滿足JSR 168標(biāo)準(zhǔn)的Portlet,支持J2EE/JSR 168規(guī)范的門戶服務(wù)器很多都宣稱將支持WSRP規(guī)范。IBM WebSphere Portal不僅可以把JSR 168 Portlet發(fā)布為Remote Portlet,而且也可以把IBM version 4 portlet API編寫的Portlet發(fā)布為Remote Portlet。微軟在2004年發(fā)布了WSRP Web Part toolkit for SharePoint,以支持SharePoint消費(fèi)Remote Portlet。
參考資料
關(guān)于作者 楊江,IBM Innovation Center高級(jí)信息工程師,主要從事WebSphere Portal Server和WebSphere Application Server的技術(shù)支持工作,對(duì)Linux、Web Service和Web安全有濃厚興趣。您可以通過yjiang@cn.ibm.com和他聯(lián)系。 |

|