jsr168 portlet(struts2+spring2.5+hibernate3.3)


jsr168? portal? portlet? 這些概念大家翻翻資料隨處可見,我在這裏就不多說了。
通過一些資料收集,發現現在國內開發人員用的比較多的portal有:liferay,jetspeed,pluto potal,websphere portal ,lightportal,openportal等.
通過現有資料得出結論:
1.liferay,jetspeed
現在商業項目還沒有人成功在此基礎上進行過二次開發,因爲liferay二次開發難度很大,運用技術太多,沒有文檔說明,源代碼中的註釋很少,不方便二次開發,而jetspeed2目前好像還不能集成其他開源框

架(ssh)這樣的案例。
2.websphere portal
很多政府門戶的成功案例,包括武煙的門戶也是採用此portal,能夠獨立出自己寫的符合jsr168標準的portlet程序,開發難度較小,能夠結合ssh框架,但是該portal的所有版本產品屬於商業產品。
3.pluto
該portal提供一個portlet的容器,但不是一個完整的portal,但是能夠運行符合portlet的程序,二次開發難度較小,有成功的非商業性的案例。
4.lightportal
採用ajax前臺web的開源portal,但是發現加載速度極其緩慢。
其他的就不在這裏一一介紹了。

在網上搜索隨處可見無框架集成的portlet程序,隨處可見websphere portal下struts2 portlet程序,但是就是沒有一個網站詳細給出pluto下框架(ssh)實現portlet,導致很多開發人員在網上
提出這樣的疑問:

能否在pluto portal中運行 編寫的struts2 portlet?
我嘗試寫了一個struts2的portlet在pluto portal下運行,爲何不成功,是不是pluto下不支持struts2 portlet? 等等這樣一系列的問題,

struts官方給出了一個struts2 portlet的程序,採用的pluto portal運行portlet,地址:http://struts.apache.org/2.0.11.1/docs/struts-2-portlet-tutorial.html
IBM developerworks 給出了一個使用 Spring 2 Portlet MVC 框架構建 Portlet 應用,地址:http://www.ibm.com/developerworks/cn/java/j-lo-spring2-portal/

下面我就apatch的pluto portal來實現一個portlet,框架採用struts2.1+spring2.5+hibernate3.3,這也是網上獨一無二的例子。

pluto2容器的安裝和配置

首頁
http://portals.apache.org/pluto/
下載得到文件
pluto-2.0.0-src.zip

1.解壓縮到指定目錄下(本例以E:\source\pluto目錄),那麼在E:\source\pluto目錄下含有pluto-2.0.0文件夾

2.tomcat5以上版本下載,並配置環境變量(如:tomcat5存放在D:\tool\tomcat5)

3.下載maven2(利用構建配置文件進行編譯),解壓縮得到apache-maven-2.2.1文件夾(比如解壓到E:\tool\apache-maven-2.2.1),相應配置環境變量。

4.修改maven2的配置
路徑E:\tool\apache-maven-2.2.1\conf上的settings.xml
增加 <pluginGroups> 元素:
<settings>
...
<pluginGroups>
    <pluginGroup>org.apache.portals.pluto</pluginGroup>
</pluginGroups>
...
</settings>

並保存。

 

5.命令行進去pluto-2.0.0所在目錄,如下圖:

 


6.分別執行以下命令(把編譯好的文件發佈到tomcat5下,提示build successful 安裝成功):
mvn clean
mvn install
mvn pluto2:install -DinstallDir=D:\tool\tomcat5  

pluto2 的相關文件就被髮布到tomcat5 相應目錄下了。

 

7.成功發佈後,tomcat根目錄下自動添加了PlutoDomain文件夾,該文件夾下是pluto兩個例子的war包,common文件夾、shared文件夾下會添加相應的jar包,因爲使用到了struts2,spring,hibernate,因此
在shared的lib目錄下,common下的lib目錄下,common的endorsed目錄下,需要手動添加一些jar包,相應目錄下的jar包,可在下方指定下載處進行下載。

8.編輯 D:\tool\tomca5\conf\tomcat-users.xml 文件,
添加角色 pluto,並在該角色下新增一個用戶,以下爲示例文件:
<tomcat-users>
<role rolename="pluto"/>
<role rolename="tomcat"/>
<role rolename="manager"/>
<user username="pluto" password="pluto" roles="pluto,tomcat,manager"/>
</tomcat-users>

修改tomcat的端口(本例爲:8088),啓動tomcat,訪問http://localhost:8088/pluto/portal
出現如下圖所示內容表示安裝成功:

 

輸入
用戶名:pluto
密碼:pluto

進入主界面,主界面中的所有其他portal頁都是pluto提供的portlet例子,只有Pluto Admin的portal頁下    是對你自己編寫的portlet程序進行發佈操作的入口,如果自己編寫的portlet程序有任何一點

錯誤,在Pluto Admin頁下的portlet Application的下拉菜單下是看不到你編寫發佈的portlet程序,下圖是我刪除了pluto 中自帶的所有portal 頁,除了Pluto Admin portal頁,然後添加了自己的portal頁,並在自己portal頁中添加了自己的兩個portlet程序的效果(左側是沒有采用框架實現的,右側是採用了struts2+spring2.5+hibernate3.3 實現的):

 

首先添加自己發佈到tomcat下自己寫的兩個portlet,默認情況下,Portlet Application中只有兩個portlet(Pluto Testsuite、Apach Pluto Portal Driver ),如果自己編寫的portlet無錯誤的話,發佈到tomcat下後,在pluto的Portlet Application 的下拉菜單下會出現自己編寫的portlet,如下圖:

 

 

 

添加一個portal Page,本例爲My Portlet,然後指定自己的portlet添加後的效果:

圖一: 

 圖二:

 

圖三:

上述就是一個簡單的struts2+spring2.5+hibernate3.3 jsr168 portlet的CRUD的例子,下面就源代碼講解一下。

 

本例jdk版本爲1.6,利用註解的方式進行事務的和注入的配置,本例並沒有很規範的對接口和實現進行存放包的分離,本例主要展示的是如何來利用struts2+spring2.5+hibernate3.3實現portlet的,望大家見諒。

 

對於以上框架加入portlet主要是對配置文件改動較大,對代碼本身編寫變化不大,下面就幾個關鍵的文件解釋一下:

1) struts.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE struts PUBLIC                                                  
    "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
    "http://struts.apache.org/dtds/struts-2.0.dtd">
<struts>
     	<package name="view" namespace="/view" extends="struts-portlet-default">
			<action name="view" class="com.opensymphony.xwork2.ActionSupport">
				<result>/WEB-INF/jsp/input.jsp</result>
			</action>	
			<action name="login-*" class="loginAction" method="{1}">
				<result name="success" type="redirectAction">login-listUsers</result>
				<result name="listUsers">/WEB-INF/jsp/list-users.jsp</result>
				<result name="prepareUpdate">/WEB-INF/jsp/modify-user.jsp</result>
				<result name="updateSuccess" type="redirectAction">login-listUsers</result>
				<result name="deleteSuccess" type="redirectAction">login-listUsers</result>
				<result name="addSuccess" type="redirectAction">login-listUsers</result>
				<result name="fail">/WEB-INF/jsp/fail.jsp</result>
			</action>			
        </package>	
     	<package name="edit" namespace="/edit" extends="struts-portlet-default">
			<action name="edit" class="com.opensymphony.xwork2.ActionSupport">
				<result>/WEB-INF/jsp/edit.jsp</result>
			</action>			
        </package>	 
     	<package name="help" namespace="/help" extends="struts-portlet-default">
			<action name="help" class="com.opensymphony.xwork2.ActionSupport">
				<result>/WEB-INF/jsp/help.jsp</result>
			</action>			
        </package>	 
</struts>

 1.紅色部分代表portlet的三種模式,查看、編輯、幫助,點擊每種模式後,會返回相關的頁面,參數名稱與portlet.xml中紅色部分相關。

2.因爲要實現portlet,因此繼承採用"struts-portlet-default","struts-portlet-default"本身也是繼承"struts-default","struts-portlet-default"來源於struts2-portlet-plugin-2.1.3-SNAPSHOTjar包,查看該jar包中struts-plugin.xml一目瞭然。

 

2) portlet.xml

 

<?xml version="1.0" encoding="UTF-8"?>
<portlet-app
version="1.0"
xmlns="http://java.sun.com/xml/ns/portlet/portlet-app_1_0.xsd"
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xsi:schemaLocation="http://java.sun.com/xml/ns/portlet/portlet-app_1_0.xsd http://java.sun.com/xml/ns/portlet/portlet-app_1_0.xsd"
   id="ssh-portlet">
	<portlet id="ssh-portlet">
	<description xml:lang="EN">sshPortletDemo</description>
		<portlet-name>sshPortletDemo</portlet-name>
		<display-name xml:lang="EN">>sshPortletDemo</display-name>
		<portlet-class>
			org.apache.struts2.portlet.dispatcher.Jsr168Dispatcher
		</portlet-class>
		<init-param>
			<name>viewNamespace</name>
			<value>/view</value>
		</init-param>
		<init-param>
			<name>editNamespace</name>
			<value>/edit</value>
		</init-param>
		<init-param>
			<name>helpNamespace</name>
			<value>/help</value>
		</init-param>
		<init-param>
			<name>defaultViewAction</name>
			<value>view</value>
		</init-param>
		<init-param>
			<name>defaultEditAction</name>
			<value>edit</value>
		</init-param>
		<init-param>
			<name>defaultHelpAction</name>
			<value>help</value>
		</init-param>
		<expiration-cache>0</expiration-cache>
		<supports>
			<mime-type>text/html</mime-type>
			<portlet-mode>view</portlet-mode>
			<portlet-mode>edit</portlet-mode>
			<portlet-mode>help</portlet-mode>
		</supports>
		<supported-locale>en</supported-locale>
		<portlet-info>
			<title>sshPortletDemo</title>
			<short-title>sshPortletDemo</short-title>
			<keywords>sshPortletDemo</keywords>
		</portlet-info>
	</portlet>
</portlet-app>

1.<portlet-name>XXX<portlet-name>指定自己編寫的portlet程序的名稱,該屬性的名稱於web.xml中紅色部分保持一致(基本概念)。

2.類「org.apache.struts2.portlet.dispatcher.Jsr168Dispatcher」在將 Struts2
集成到 Portlet 中起到了關鍵作用,該類將 Portlet 操作分發給 Struts2。

3.紅色部分指定初始化portlet模式的命名,與struts.xml內容相關。

3) web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns="http://java.sun.com/xml/ns/javaee"
	xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
	xsi:schemaLocation="http://java.sun.com/xml/ns/javaee 
	http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
	id="WebApp_ID" version="2.5">
<display-name>sshPortlet</display-name>
  <filter>
  	<filter-name>struts</filter-name>
  	<filter-class>
  		org.apache.struts2.dispatcher.FilterDispatcher
  	</filter-class>
  </filter>
	<filter>
		<filter-name>hibernateFilter</filter-name>
		<filter-class>
			com.yale.sshpluto.service.conf.MyOpenSessionInViewFilter
		</filter-class>
		<init-param>
			<param-name>singleSession</param-name>
			<param-value>true</param-value>
		</init-param>
	</filter>
	<filter-mapping>
		<filter-name>hibernateFilter</filter-name>
		<url-pattern>/*</url-pattern>
	</filter-mapping>
  <!-- 所有文件都可以使用struts標籤 -->
  <!--  -->
  <filter-mapping>
  	<filter-name>struts</filter-name>
  	<url-pattern>/*</url-pattern>
  </filter-mapping>
  
<!-- struts config end -->  
	<context-param>
		<param-name>servletmapping</param-name>
		<param-value>/*</param-value>
	</context-param>	

<!-- 解決中文輸入問題,我們在web.xml中加入過濾器 -->
	<filter>
		<filter-name>CharacterEncodingFilter</filter-name>
		<filter-class>com.yale.sshpluto.service.conf.CharacterEncodingFilter</filter-class>
		<init-param>
			<param-name>encoding</param-name>
			<param-value>GB2312</param-value>
		</init-param>
		<init-param>
			<param-name>ignore</param-name>
			<param-value>true</param-value>
		</init-param>
	</filter>
	<filter-mapping>
		<filter-name>CharacterEncodingFilter</filter-name>
		<url-pattern>/CharacterEncodingFilter</url-pattern>
	</filter-mapping>	
	<filter-mapping>
		<filter-name>CharacterEncodingFilter</filter-name>
		<servlet-name>action</servlet-name>
	</filter-mapping>
	
<!-- log4j start -->
	<context-param>
		<param-name>webAppRootKey</param-name>
		<param-value>webApp.root</param-value>
	</context-param>

	<context-param>
		<param-name>log4jConfigLocation</param-name>
		<param-value>/WEB-INF/log4j.properties</param-value>
	</context-param>

	<context-param>
		<param-name>log4jRefreshInterval</param-name>
		<param-value>600000</param-value>
	</context-param>
	<listener>
		<listener-class>
			org.springframework.web.util.Log4jConfigListener
		</listener-class>
	</listener>	
<!-- log4j end -->	
<!-- 
通過這樣的配置,程序在啓動的時候,會首先初始化Spring框架自帶的ContextLoaderServlet,
這個Servlet的作用就是讀取由contextConfigLocation指定的Spring配置文件的位置,
初始化Spring框架的Context對象,並將這個對象保存在ServletContext中,留待Action調用。
 -->
<context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>/WEB-INF/applicationContext.xml,/WEB-INF/applicationContext-*.xml,/WEB-INF/action-servlet.xml</param-value>
</context-param>
	<listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>
	<servlet id="sshPortletDemo">
        <servlet-name>sshPortletDemo</servlet-name> 
	    <servlet-class>org.apache.pluto.core.PortletServlet</servlet-class>
            <init-param> 
              <param-name>portlet-class</param-name> 
              <param-value>org.apache.struts2.portlet.dispatcher.Jsr168Dispatcher</param-value> 
            </init-param> 	
			 <init-param><!--portlet的名字必須和portlet.xml中portlet的名字一致-->
			  <param-name>portlet-name</param-name>
			  <param-value>sshPortletDemo</param-value>
			 </init-param>	  
	        <load-on-startup>1</load-on-startup>
	</servlet>	
	<servlet-mapping>
		<servlet-name>sshPortletDemo</servlet-name>
		<url-pattern>/PlutoInvoker/*</url-pattern>
	</servlet-mapping>	
<!-- spring end -->
</web-app>

 

上述文件的配置在文件中都有相應的註釋,寫的非常詳細,<url-pattern>/PlutoInvoker/*</url-pattern>這種方式是pluto特定的寫法,不能進行修改。

4) list-users.jsp

<s:url id="deleteUrl" action="login-delete" portletUrlType="action">
 <s:param name="userId"><s:property value="userId"/></s:param>
</s:url>

增加了紅色部分的屬性,該屬性指明請求的方式是採用portlet還是action,我們這裏指明採用action,如果指明portlet,將出現呈現錯誤(和portlet的請求、呈現方式有關係,這個是portlet的基礎知識,這裏就不敷衍,網上搜的一下就出來瞭解釋)。

 

上述就是幾個重要文件的內容解釋,其他文件有基礎的開發人員,一看便知,這裏就不說明了,對pluto本身的jsp、xml、java文件,可以根據自己的需要進行相應的修改,源代碼比較簡單,修改也很方便。

 

 

源代碼下載:

 

 1)jar包存放目錄:

  endorsed.rar中的jar包存放在tomcat下的endorsed目錄下

  lib.rar中的jar包存放在tomcat下的lib目錄下

  shared-lib中的jar包存放在tomcat\shared\lib目錄下

  ssh-lib1、ssh-lib2中的jar包存放在工程的lib目錄下

2)工程源代碼:plutoportletssh.rar