JSR-168 Portlet指南(讲述具体实施168规范的实际,高级)

  • 格式:doc
  • 大小:43.50 KB
  • 文档页数:6

摘要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="/<%= request.getContextPath()%>/images/logo.gif"/> 这在JSR-168 portlet中是不正确的。

正确的方法是:<img src="<%= 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(/)作为参数传递,并将路径(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!-545815275l ogo.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="/portlet" prefix="portlet"%> 脚本中的validate()方法可以对标记加以区分。

<script>function validate<portlet:namespace/>(foo) {if (foo.bar.value=="") {return false;}return true;}</script>以下是调用带名称空间的JavaScript方法的方式:<form action="/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。