“portal”一詞中文翻譯爲“門戶”,所謂門戶是指各種信息的集成。
rose portal基於rose框架,是rose的一個插件。這個技術不是基於JavaEE的portlet規範,您只需要使用標準的servlet容器即可實現,而且更簡單。
本示例示範如何使用rose portal (基於servlet規範),在一個門戶可以顯示兩個獨立的“信息”
創建控制器
1個是Portal主控,另外2個是窗口控制器 1) 在controllers或子目錄下創建Portal控制器:PortalController,創建處理方法,並聲明Portal參數
package ninja.paoding_rose.test.controllers;
import net.paoding.rose.web.annotation.Path;
import net.paoding.rose.web.annotation.rest.Get;
import net.paoding.rose.web.portal.Portal;
@Path("portal")
public class PortalController {
// 標註@Get,表示這個方法要處理的是對/portal的GET請求
// 在主控控制方法上聲明Portal參數即表示這個頁面是portal,就這樣!
@Get
public String home(Portal portal) throws Exception {
// 使用addWindow向這個portal頁面加入各種子信息(我們成爲窗口)
portal.addWindow("docin","/windows/docin");
// 第一個參數是用於標識該窗口,使得portal頁面中可以引用到這個窗口的html //
// 第二個參數表示這個窗口的地址(可以包含參數),這個地址等價於forward的地址(也就是這裏只要能forward的地址都可以,無論是否是rose框架的,甚至可以是一個jsp頁面)
// // 因此,地址沒有說一定要以"/windows"開始
portal.addWindow("ninja","/windows/ninja?name=value");
return "portal_page";
}
}
2) 在controllers.windows下創建可被/windows/docin,/windows/ninja 訪問的控制器以及方法 DocinController.java
package ninja.paoding_rose.test.controllers.windows;
import net.paoding.rose.web.Invocation;
import net.paoding.rose.web.annotation.Path;
import net.paoding.rose.web.annotation.rest.Get;
@Path("docin")
public class DocinController {
// 這個方法處理"/windows/weather",它只是返回一串中文,而非jsp、vm等頁面
@Get
public String docin(Invocation inv) {
return "@豆丁豆丁豆丁豆丁豆丁豆丁豆丁!";
}
}
NinjaController.java
package ninja.paoding_rose.test.controllers.windows;
import java.util.ArrayList;
import java.util.List;
import net.paoding.rose.web.Invocation;
import net.paoding.rose.web.annotation.Path;
import net.paoding.rose.web.annotation.rest.Get;
import net.paoding.rose.web.portal.Window;
@Path("ninja")
public class NinjaController {
// 在控制器使用全局變量並不好,在此僅是一個演示而已
private int count;
// 方法名是什麼不要緊,關進是@Get代表了這個方法用於處理對/ninja的GET請求
@Get
public String ninja(Invocation inv, Window window) {
List<String> list = new ArrayList<String>();
list.add("偷襲");
list.add("忍術");
list.add(String.valueOf(count++));
inv.addModel("todolist", list); //
// 返回頁面,rose將從這個模塊對應的/views/windows下找名字以ninja開始的頁面
return "ninja";
}
}
webapp/views下創建PortalController需要的portal_page.jsp (這裏亦可以用rose 所支持的.vm文件)
<%@ page language="java" contentType="text/html; charset=utf-8"
pageEncoding="utf-8"%>
<html>
<head>
<link href="/static/portal.css" rel="stylesheet" type="text/css" media="all" />
<title>Portal</title>
</head>
<body>
<h2>Portal</h2>
<div class="window">
<div class="title">豆丁</div>
<!--這裏使用$weather的"weather"即是第一個window的標識-->
<div class="content">${docin}</div>
</div>
<div class="window">
<div class="title">忍者</div>
<!--$todo實際是一個Window對象,velocity會調用其toString()輸出html的-->
<div class="content">${ninja}</div>
</div>
</body>
</html>
window頁面
webapp/views/windows創建ninjaController需要的頁面 ninja.jsp (亦可以用ninja.vm 但寫法很不同。)
<%@ page import="java.util.*" %>
<ul>
<%
List<String> result = (List<String>)request.getAttribute("todolist");
for(String oneItem : result){
%>
<li><%=oneItem %></li>
<%
}
%>
</ul>
併發數配置
在web.xml的<web-app>下配置併發參數值:
<context-param> <param-name>portalExecutorCorePoolSize</param-name> <param-value>200</param-value> </context-param>
如果沒有配置以上參數,默認portalExecutorCorePoolSize取1,相當於除了http主線程外只有另外1個執行線程, 這對程序的正確性沒有任何影響,只是併發能力下降了,整個portal的執行時間也會變長。
高級話題
1) 可以在PortalController.home方法上設置@PortalSetting(timeout = 100)表示最多等待各個窗口100ms(包括window的頁面渲染耗費時間)
2) 可以通過引入xiaonei-commons-interceptors的@Throughput(maxConcurrent = 20)放置在window的xxx方法上,控制最多併發數
3) 可在web.xml配置全局參數設置poral執行器的線程池參數:portalExecutorCorePoolSize、portalExecutorMaxPoolSize、portalExecutorKeepAliveSeconds
參數意義分別參考java.util.concurrent.ThreadPoolExecutor的corePoolSize、maximumPoolSize、keepAliveTime說明
4) 在portal-home頁面中的$weather實際是一個net.paoding.rose.web.portal.Window對象,因此可通過$weather.success 判斷window的執行是否完成並且是200的,通過$weather.statusCode等了解具體的執行情況。詳細請參考net.paoding.rose.web.portal.Window類屬性列表。
5) 可在window的控制器TodoController.xxx方法中聲明Window window對象,通過window.setTilte(title)或window.set(name, value)相關屬性,並在portal-home.vm使用$todo.title 在todo.vm中,則除了使用todo的名字使用$todo.title,也可以通過$window.title來使用。每個$window在不同的窗口的頁面代表自己的Window對象,不會“亂串”
啓動後,訪問http://[yourlocal]/[yourprojectname]/portal
可以看到 兩個div(這裏可以叫做window) 分別通過不同的controller 返回數據。
想了解vm頁面用法請參考:
http://code.google.com/p/paoding-rose/wiki/Rose_Portal_Demo
此鏈接爲paoding-rose的project home 裏面也有paoding-rose 其它方面的介紹
國人罕見的開源項目, 用着也很不錯。 祝願其團隊日益強大、此項目風靡國內外。
-----------------------
補充些東西:
portal 的真正意義在於, 在一個頁面上如果一個模塊down 掉,其它模塊還能正常使用。
如人人網的用戶個性主頁,“用戶評論” 模塊出現異常,在之前的服務器架構上則會導致整個頁面出現異常(因爲是由一個controller處理的請求) 。 可能有人說 我用ajax。可以。但ajax是一個頁面的多個模塊同時向服務器發了多個請求。爲服務器增壓。而且完全用js 控制頁面,也會出現很多不兼容問題。
現在最好的解決方案問世:rose 的portal 整個請求由一個控制器來處理並由這個控制器分發給每個window 的控制器。這些大家都能理解。但關鍵點在於它的意義。 就在於 portal 的 home 方法的超時配置:@PortalSetting(timeout = 100)
和 併發配置:
<context-param> <param-name>portalExecutorCorePoolSize</param-name> <param-value>200</param-value> </context-param>
代碼不想再一點點上貼,直接發個包兒吧 見附件。