Hello World,一個簡單的JSR 168 portlet(轉載)from smoking_boy
Posted on 2006-08-11 11:23 毛里求斯的化石 閱讀(646) 評論(0) 編輯 收藏 所屬分類: portal相關本文以Hello World為例,介紹如何使用JSR 168 API編寫portlet,打包成portlet應用,部署portlet應用到portlet容器上。最后給出JSR 168的參考實現-Apache pluto的安裝配置。
在過去三年中,企業面臨著信息、流程的整合問題,"企業門戶"和"企業應用集成"一時間成了IT業內熱門的課題。國內外IT廠商和開源組織順時而動,開發了各種企業門戶服務器。單是Java陣營,IBM公司發布了WebSphere Portal Server 1.2/2.1/4.x/5.x, Apache Software Foundation推出了JetSpeed、BEA、Oracle、SAP、Sun也推出了各自的Portal服務器。這些Portal服務器各自提供不同的Java API給應用系統開發商開發Portlet,應用系統開發人員不得不為不同的Portal服務器使用互不通用的API開發功能相同的Portlet。人們翹首以待,希望有一天能象編寫Java Servlet那樣,使用一種API編寫能運行在大多數Portal服務器上的Portlet應用。
經過近兩年時間的漫長等待,2003年10月7日,Java Community Process(JCP)發布了JSR168: Portlet Specification 1.0的最終版本。該規范包含如下內容(參見 參考3)
定義了portlet運行環境 - portlet容器
定義了portlet容器和portlet之間的API
提供了portlet存儲持久性和非持久性數據的機制
提供了portlet包含servlet和JSP的機制
定義了portlet打包,方便部署
保證了portlet在JSR 168門戶中的二進制移植
能夠以WSRP協議把JSR 168 portlet作為遠程portlet運行。
JSR 168規范獲得了業內的廣泛支持,JSR 168專家組包括主要的Portal廠商,包括Apache、BEA、 IBM、 Oracle、 Sun等公司和組織。IBM在Apache以開放源碼項目的方式提供了該規范的參考實現pluto,并在WebSphere Portal Server 5.0.2中提供了JSR 168的支持。
本文以Hello World為例,介紹如何使用JSR 168 API編寫portlet,打包成portlet應用 源碼包下載,部署portlet應用到portlet容器上。最后給出JSR 168的參考實現-Apache pluto的安裝配置。
現在讓我們開始吧。
portlet項目的最基本的幾個目錄是:
HelloWorld\JavaSource 放置Java源代碼
HelloWorld\WebContent\Web-INF\classes 放置Java Class文件
HelloWorld\WebContent\Web-INF\lib放置jar文件,比如jstl.jar 、standard.jar (JSTL - JSP Standard Tag Library及Apache的JSTL的實現)
HelloWorld\WebContent\Web-INF\tld 放置taglib定義文件,比如portlet.tld或者portlet.tld(portlet JSP tag)這些目錄下面的jar文件和tld文件可以從安裝好的pluto中找到。
下面是HelloWorldPortlet.java的代碼。相關連的另外兩個Java源文件,在本文末尾有 源碼包下載的鏈接。
注意:
1.import語句,這里使用的全部是java或者javax標準類庫,說明這個portlet代碼應該是可以運行在支持相應標準的服務器上面。
2.對于一些常量,使用了public static final修飾符。有助于提供java代碼的性能。
3.processAction方法是Portlet的核心方法之一,例子代碼在這里處理jsp中FORM表單提交的數據,并把得到的數據放到一個Java Bean中,該Java Bean又被放到PortletSession中供jsp文件調用。
proccessAction處理完畢后,portlet引擎會運行portlet的doView方法。doView方法根據邏輯、輸入數據或者配置,調用不同的jsp文件進行數據展示。
|
jsp文件中首先聲明它不需要創建新的HTTP Session,返回頁面的內容是html頁面。然后import聲明需要引用標準java類庫java.util,javax.portlet,以及我們自己的類庫com.ibm.spc。接著聲明使用portlet標記庫。<portlet:defineObjects/>使用portlet標記庫的標記defineObjects,定義了jsp中要使用3個變量:
|
|
接下來,從<portlet:defineObjects/>語句定義的變量renderRequest當中獲取PortletSession,進而得到session當中保存的數據并顯示在JSP頁面上。
|
最后部分是使用portlet標記庫的另一個標記actionURL產生一個URL指向當前頁面中的這個portlet,生成的URL能夠觸發當前portlet的action請求,或者說這個URL能夠觸發當前portlet的processAction方法。
|
編寫好portlet的java代碼,現在我們可以把它編譯成二進制class文件。
下面的腳本中使用JAVA_HOME環境變量指向WebSphere Application Server 5.0.2中的IBM JDK 1.3.1。
腳本中使用CP變量指向Tomcat 4.1中帶的Servlet 2.3類庫,以及pluto的JSR 168 portlet類庫。腳本最后的動作是編譯HelloWorld portlet,并把編譯好的class文件放到WebContent\WEB-INF\classes目錄。
注意:
WebSphere Portal Server 5.0.2中使用的WebSphere Application Server 企業版5.0.2;Tomcat 4.1使用的JDK 1.3.1。
WebSphere Application Server 5.1中的JDK是1.4.1版本。
|
Portlet應用也是一個J2EE Web應用,擁有一個Web應用部署描述文件web.xml。web.xml文件中taglib標記部分是關于Portlet Tag Library的定義,在Portlet 應用的jsp文件中可以使用這種Tag Lib。
下面代碼片斷聲明使用uri是 http://java.sun.com/portlet的tag lib,tag lib的前綴是portlet。關于Portlet Tag Library請參考Java Portlet Specification。
注意:2004年2月的pluto中portlet部署程序中不能分析處理web.xml文件中welcome-file的標記,相信Apache會在后繼的版本中修正這個問題。解決辦法是,或者從web.xml文件中去除有關的tag;或者修改pluto代碼,為servletdefinitionmapping.xml文件添加welcome-file標記,為org.apache.pluto.portalImpl.om.servlet.impl. WebApplicationDefinitionImpl java類添加一個字段來解決這個問題。
|
每個Portlet應用除了Web應用部署描述文件web.xml外,還有一個Portlet部署描述文件 - portlet.xml。該文件中包括該Portlet Application中一個或者多個portlet的定義。
下面的portlet.xml文件中首先是<portlet-app/>,其中引用了sun公司的關于portlet描述文件的名字空間的定義文件portlet-app_1_0.xsd。然后是各個<portlet/>定義,包括名字和描述信息,國際化的名字和描述信息,portlet的class類名,portlet的初始化參數、國際化用戶界面中使用的資源文件。HelloWorld Portlet有一個初始化參數wps.markup,在我們的portlet代碼中使用renderRequest.getProperty("wps.markup")獲得這個初始化參數的值。
我們使用JDK的命令jar把class文件、jsp文件、jar包、JSP標記庫、web部署描述文件web.xml、portlet部署描述文件portlet.xml等打包成web archive文件。
|
pluto提供了部署打包成war格式portlet應用的命令行工具。名叫Deploy的部署工具會做兩件事情:
1. 分析portlet應用war文件中的web.xml文件和portlet.xml文件,修改web.xml以添加和pluto運行環境相關的servlet定義和servlet運行參數
2. 把portlet作為Web應用部署到Tomcat服務器上面
在我們的例子中,Deploy工具修改web.xml文件,添加一個名叫HelloWorldPortlet的servlet定義,并為這個servlet添加了portlet-guid的參數,參數值HelloWorld.HelloWorldPortlet。其中<servlet-name>值來源于portlet.xml文件中<portlet-name>標記,portlet-guid參數的值是war文件的前面部分和portlet.xml文件中<portlet-name>標記的值的組合。
|
Deploy的語法是:
|
下面的例子腳本中,Tomcat所有Web應用都部署在TOMCAT-webapps-directory目錄下面,比如%tomcat.home%/webapps;<TOMCAT-pluto-webmodule-name>參數是pluto web應用的名稱,比如 pluto;web-archive參數是我們要部署的portlet應用打包文件, D:/workspace/JSR168Portlet/HelloWorld/build/HelloWorld.war;<build-container-dir>是portlet部署工具的工作路徑,比如當前路徑,Deploy工具會在相對于工作路徑的路徑下面找尋相關文件。
|
注意:2004年2月份的pluto部署以后,可能缺少一個文件,具體路徑和文件名稱是tomcat.home\webapps\pluto\WEB-INF\portal\src\webapp\WEB-INF\tld\portlet.tld。
修改%tomcat.home.pluto%\webapps\pluto\WEB-INF\data\portletentityregistry.xml文件,加入我們的portlet的注冊信息。其中application屬性<definition-id>指向HelloWorld應用的war文件名稱的前半部分,portlet屬性definition-id指向HelloWorld應用的web.xml文件中portlet-guid的值。這樣,portlet容器pluto就能夠根據這個注冊文件找到相應web應用的servlet了。
|
修改%tomcat.home.pluto%\webapps\pluto\WEB-INF\data\ pageregistry.xml文件,添加一段fragment,把我們的portlet注冊到頁面上。其中名為portlet的參數的值是portletentityregistry.xml文件中注冊的portlet的應用id和portlet id的組合。
|
現在重新啟動Tomcat,我們終于看到盼望已久的JSR 168 portlet了。
在頁面中輸入IBM Innovation Center,你將看到
根據JSR 168 Request,IBM在Apache以開放源碼的方式提供了JSR 168的參考實現。
安裝Apache pluto,我們需要
1)Maven 1.0-beta-10或者更高版本,下載網址 http://maven.apache.org/start/download.html
2)JDK 1.3或者更高
3)Servlet 2.3引擎
Tomcat 4.1.18-LE w/JDK 1.4
或者
Tomcat 4.1.24 w/ JDK 1.3
4)CVS Client for windows
本人使用的測試環境是IBM JDK 1.3.1, jakarta-tomcat-4.1.29, v. 1.0-rc1-SNAPSHOT。
我們需要使用cvs客戶端以匿名方式下載pluto代碼。注意:cvs客戶端不能使用代理,必須用直接的internet連接。
|
安裝好JDK、maven、Tomcat以后,進入pluto源碼目錄,拷貝build.properties.sample 文件為build.properties文件。在build.properties文件中指定tomcat安裝路徑,注意windows平臺上面或者使用/或者是\\作為路徑的分割符。如果你在公司防火墻的后面或者其他原因必須通過代理服務器訪問internet的話,那么需要指定代理服務器參數maven.proxy.host和maven.proxy.port。
|
現在,我們執行maven命令就可以開始pluto的安裝了。Maven將安裝pluto到Tomcat服務器上面,安裝名為testsuite的測試用portlet應用到Tomcat上,配置pluto以運行testsuite中的例子portlet。
啟動tomcat以后,通過http://localhost:8080/pluto/portal/就可以訪問到pluto的演示頁面了。
|
相信JSR 168標準會象Servlet標準那樣得到應用服務器廠商和廣大應用開發商的大力支持。上面的HelloWorld portlet現在可以運行在Apache pluto上面和IBM WebSphere Portal Server 5.0.2上面,相信也能運行在其他支持該標準的Portal服務器上。