分享
 
 
 

编写JSR-168 Portlet指南

王朝html/css/js·作者佚名  2008-05-31
窄屏简体版  字體: |||超大  

摘要

JSR-168是适合于portlet开发人员的java API集合。设计符合规范的JSR-168 portlet的原因有很多。可移植性就一个显而易见的好处。根据规范编写的代码更容易在门户服务器之间移动。多数基于Java的门户服务器都支持JSR-168 portlet。

另一个好处是更易于联合。当portlet符合JSR-168规范时,通过Web Services for Remote Portlets (WSRP)生产者公开JSR-168 Portlet会更容易一些。WSRP提供了一个通过Web service联合portlet内容的标准。JSR-168和WSRP 1.0 portlet功能是紧密耦合的。JSR-168 to WSRP portlet桥利用JSR-168的URL重写API。本文将阐述开发JSR-168 portlet以便获得可移植性的最佳实践。

1. 总是利用URL重写API,以获得Portlet中的内容

Java开发人员经常在如下所示jsp中编写图像的URL:

<img src="http://www.QQread.com/<%= request.getContextPath()%>/images/logo.gif"/>

这在JSR-168 portlet中是不正确的。正确的方法是:

<img src="http://www.qqread.com/j2ee/<%= renderResponse.encodeURL(renderRequest.getContextPath()+

"/images/logo.gif") %>"/>

encodeURL()方法可以采用完全路径URI或者完全限定URL。完全路径URI是最常用的。在使用JSR-168 portlet将资源嵌入Web application Archive (WAR)中时,可以使用此技术。在将图像放置到单独服务器上时,可以使用完全限定URL。专门为静态内容提供服务的缓存服务器就是一个示例,它卸掉来自门户服务器的通信量。尽管可以通过对完全限定URL使用encodeURL()来引用portlet以外的内容,但应该只在无法通过客户机访问资源时这样做。如果客户机可以直接浏览资源,则无需对URL使用encodeURL()。例如,如果有一台Web服务器,可用该服务器获得门户用户无法直接浏览的防火墙内的静态内容,则需要调用encodeURL()。如果这些内容在防火墙之外,并且门户用户可以直接浏览到Web服务器,则无需调用encodeURL()。

2. 不要将路径附加到重写URL中

传入RenderRequest的encodeUrl()方法中的URL在调用该方法之前必须是完整的。在调用该方法之后,无法添加URL的某些部分。例如,如果想从XSLT转换中生成一个URL转换,则不能将已编码的基本URL(http://foo.com/)作为参数传递,并将路径(pages/bar.jsp)附加到该转换中的已编码基本URL中。

以下调用演示了将URL编码到图像中的正确方式:

<@= renderResponse.encodeURL(renderRequest.getContextPath()+

"/images/logo.gif")@>

它使用一个.portal文件在BEA WebLogic Portal 9.2中生成以下Html片段:

<img src="http://localhost:7001/PortalWebApp/images/logo.gif;

PORTAL_TAU=W3f6FbmLLcgZq9Fpv1JHLs5rrJG8Lgj2nnDVJqdfShhRGFnsqCKZ!-545815275"/>

以下调用是不正确的。URL并不指向想要的资源。

<@= renderResponse.encodeURL(renderRequest.getContextPath()+

"/images/")+"logo.gif"@>

它使用.portal文件在WebLogic Portal 9.2中生成以下HTML文件:

<img src="http://localhost:7001/PortalWebApp/images/;

PORTAL_TAU=W3f6FbmLLcgZq9Fpv1JHLs5rrJG8Lgj2nnDVJqdfShhRGFnsqCKZ!-545815275logo.gif"/>

3. 使用名称空间限定客户端脚本变量和方法

假设您想使用portlet中的javascript验证用户输入。以下Javascript功能可能很有用:

<script>

function validate(foo) {

if (foo.bar.value=="") {

return false;

}

return true;

}

</script>

同一页面中的其他portlet可能也有一个命名为validate()的具有不同逻辑的JavaScript方法。门户框架本身可能使用JavaScript方法。这个问题的解决方法是使用客户端脚本中的名称空间方法和顶层变量。<portlet:namespace/>标记将为每个portlet生成一个惟一标识符。第一步是通过taglib directive将标记库包含在JSP中。

<%@taglib uri="http://java.sun.com/portlet" PRefix="portlet"%>

脚本中的validate()方法可以对标记加以区分。

<script>

function validate<portlet:namespace/>(foo) {

if (foo.bar.value=="") {

return false;

}

return true;

}

</script>

以下是调用带名称空间的JavaScript方法的方式:

<form action="http://www.somesite.org/servlet"

method="GET" onsubmit="return validate<portlet:namespace/>(this);">

<label for="bar">Text(required): </label>

<input type="text" name="bar" id="bar">

</form>

进入讨论组讨论。

4. 确保引用Portlet资源的内联客户端脚本符合规范

客户端脚本常常引用外部资源(如图像、电影和外部页面)来增强用户界面。常见的示例是预先加载图像以使交换图像更有效的JavaScript。以下是一个示例:

<script>

function preloadImages(){

var menuImage =

new Image();

menuImage.src = "images/icon.gif";

var menuImageDark=new Image();

menuImageDark.src = "images/icon.gif";

}

</script>

客户端脚本中的URL必须根据JSR-168规范进行重写。这些脚本必须在JSP或JSP-168 portlet类中,以便调用重写API的URL。它们不能在单独的JavaScript (.js)文件中。以下是一个包含URL重写的适当名称空间脚本在JSR-168 portlet中看起来的样子:

<script>

function <portlet:namespace/>preloadImages(){

var menuImage = new Image();

menuImage.src = "<%=renderResponse.encodeURL(renderRequest.getContextPath()+ "images/icon.gif")%>";

var menuImageDark= new Image();

menuImageDark.src = "<%=renderResponse.encodeURL(renderRequest.getContextPath()+ "images/icon_dark.gif") %>";

}

</script>

5. 总是为portlet响应声明一个内容类型

根据JSR-168规范,“portlet必须使用RenderResponse接口的setContentType方法设置响应的内容类型”。没有显式设置其内容类型的portlet仍然会成功获得编译。但WebLogic Portal不会执行没有设置其内容类型的portlet。确保您的portlet设置了其内容类型。

以下示例演示了一个正确设置其内容类型的portlet:

public class MyPortlet extends GenericPortlet {

public void doView(RenderRequest request, RenderResponse response)

throws PortletException, IOException {

response.setContentType("text/html");

PrintWriter writer = response.getWriter();

writer.println("I set my content type!

");

}

}

此示例是不正确的,但仍将获得编译:

public class MyPortlet extends GenericPortlet {

public void doView(RenderRequest request, RenderResponse response)

throws PortletException, IOException {

// no content type set!

PrintWriter writer = response.getWriter();

writer.println("I did NOT set my content type!

");

}

}

进入讨论组讨论。

6. 不要从Portlet发送Cookie

根据JSR-168 portlet规范,在HttpServletResponse上调用addCookie()实际上不会设置一个cookie。允许设置cookie的portlet容器被打破。不要调用此方法。

如果您喜欢在用户使用门户的时候基于每位用户持久存储信息,那么可以将信息存储为portlet会话中的一个属性。如果您喜欢在用户退出后持久存储信息,那么可以将信息存储到数据存储库(文件系统、数据库、LDAP等)中。

7. 将业务逻辑从表示中分离出来

有经验的开发人员都知道模型查看器控制器框架类似于Struts或Beehive,可以使开发富Web应用程序变得更容易。这同样也适用于portlet。JSR-168并不是适用于平台独立portlet的惟一理想规范。WSRP portlet在实现标准的门户(包括非Java门户)之间移动很方便。WebLogic Portal 可以通过WSRP公开Beehive和Struts portlet。

如果需要将portlet部署为JSR-168 WAR,您仍然有一些选择。将业务逻辑从JSR-168 portlet的表示逻辑中分离出来的最简单方法是指派一个JavaServer Page (JSP)。portlet处理呈现方法(比如render()和doView())中的业务逻辑。portlet使用应用程序级作用域或portlet作用域将信息传递给JSP。下面的示例将一个portlet请求指派给JSP,并传递portlet作用域中的一个字符串:

public void doView(RenderRequest request, RenderResponse response) throws PortletException, IOException {

response.setContentType("text/html");

request.setAttribute("foo","bar");

String jsp = "/pages/portal.jsp";

PortletContext ctx = getPortletContext();

PortletRequestDispatcher dispatcher = ctx.getRequestDispatcher(jsp);

dispatcher.include(request, response);

}

到达JSP(上述示例中的jsp)的路径值并不包括portlet的Web归档文件(WAR)的上下文路径。

JSR-168的指派方法允许将业务逻辑与表示分离。不过,它们缺乏MVC框架的成熟度。

适用于JSR-168开发的框架包括:

Spring Portlet MVC

WebWork

Struts Action 2

Struts Action 2是Struts和WebWork的组合,因此portlet代码库对现在而言几乎是一样的。这些框架简化了复杂portlet的开发和维护。

结束语

遵守这些指导原则会使您的portlet符合JSR-168规范。遵守规范会使您的portlet在Java门户服务器之间移动变得更容易。还会使利用WSRP联合门户内容变得更容易。

参考资料

Java Community Process JSR-168 主页

OASIS WSRP 主页

WebLogic Portal 8.1 中的 URL(中文版,Dev2Dev,2005年5月)

利用WebLogic Portal 8.1 SP3开发Java Portlets(中文版,Dev2Dev,2004年8月)

作者简介

Drew Varner

Drew Varner 是一名在BEA Federal Professional Services方面具有丰富实践经验的高级首席顾问。在过去两年中,他的工作是处理实现方面的防御和智能代理,包括JSR-168和WSRP门户技术。

进入讨论组讨论。

(出处:http://www.knowsky.com)

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有