以下文字转载自:http://dev2dev.bea.com.cn/techdoc/2007/03/java-soa-writing-jsr-168-portlets.html
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(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开发的框架包括:
Struts Action 2是Struts和WebWork的组合,因此portlet代码库对现在而言几乎是一样的。这些框架简化了复杂portlet的开发和维护。
结束语
遵守这些指导原则会使您的portlet符合JSR-168规范。遵守规范会使您的portlet在Java门户服务器之间移动变得更容易。还会使利用WSRP联合门户内容变得更容易。
参考资料
分享到:
相关推荐
【JSR-168 Portlet开发指南】 JSR-168,全称为Java Specification Request 168,是Java社区制定的一项标准,旨在为portlet开发者提供一套API,以实现portlet的可移植性和互操作性。Portlet是一种组件化的应用程序,...
"JSR-168 Portlet中文指南大全.doc"这个文档很可能详细介绍了JSR-168标准的各个方面,包括但不限于上述概念,可能还包括如何开发portlet、配置portlet容器、实现portlet间的通信等实践指导。对于想要学习和实施JSR-...
### JSR168规范详解:The Java Portlet Specification #### 引言 JSR168(Java Specification Request 168)是一项重要的技术规范,它为门户服务器中的组件开发提供了一套标准化的方法。这一规范得到了业界主要...
- **编写简单的 JSR-168 Portlet**:遵循 JSR-168 规范编写基本的 Portlet。 - **Struts Portlet 指南**: - **编写 Struts Portlet**:结合 Struts 框架开发功能丰富的 Portlet。 - **添加 Action**:实现用户...
JSR-168标准确保了Portlet的互操作性和可移植性,使得开发者能够更容易地为多种门户环境开发应用。 - **推荐工具** - JDK 1.5.0 或 JDK 1.4.2:这是开发Portlet所需的最低Java版本。使用JDK 1.5可以利用更多的新...
Portlet是Java Portlet API(JSR-168和JSR-286)定义的一种标准组件模型,用于构建可插入到门户中的交互式小应用程序。一个portlet可以看作是门户中的一个小窗口,用户可以通过门户页面上的portlet来访问不同的功能...
它支持JSR-168(Portlet API 1.0)和JSR-286(Portlet API 2.0)标准,允许开发者使用Java来编写portlet,这些portlet可以与不同的内容管理系统、目录服务、邮件系统等集成。 在"gridsphere-2.2.10-src.zip"中,...
- **Portlet与Servlet的区别**:Portlet是一种特定类型的Web组件,它遵循Java Portlet API(JSR-168)规范,可以在门户环境中运行。而Servlet则是一种通用的Web组件,用于处理HTTP请求。 - **优势**:Portlet提供了...
- **Struts Portlet指南**: - **写一个非常简单的StrutsPortlet**:Struts是一个流行的MVC框架,可以用来构建复杂的Portlet。从简单的例子开始,逐步深入学习如何使用Struts来开发Portlet。 - **添加一个Action**...
在myeclipse6中,选择“File” > “New” > “Other” > “Web” > “Portlet Project”,输入项目名(例如:HelloWorldPortalDemo),选择Pluto作为portlet容器,遵循JSR 168或JSR 286标准,然后点击“Finish”。...
2. **创建项目**: 启动 Eclipse IDE,依次选择 `New -> Other -> JSR168 Portlet Project Creator`,然后按照向导提示完成项目创建。 3. **编写代码**: 根据需求编写 Portlet 的功能代码。 4. **部署应用**: 将编写...
- **目标受众**:本指南适合对 JSR-168 Portals 不熟悉或想要评估此技术特点的新用户。 - **进一步阅读**:更多详细的信息可以在 Liferay 的官方 User Guide 和 Development Guide 中找到。 - **技术支持**:如需...
七、支持JSR-168 Portlet Spring 2.0开始支持portlet开发,这使得它可以在portlet容器中运行,如Liferay和Websphere Portal Server,拓宽了Spring的应用范围。 八、MVC测试 Spring提供了一套强大的测试框架,包括...
- **JSR 168**:JSR 168是Java Portlet API的一个版本,它为portlet开发者提供了一个标准化的框架,使得portlet可以在支持JSR 168规范的任何门户容器中运行。 - **WSRP**:Web Services for Remote Portlets(WSRP)...
- **JSR 168**: 这是Java Portlet API的一个版本,定义了portlet与portlet容器之间的交互接口。 - **WSRP (Web Services for Remote Portlets)**: 一种允许portlet远程部署的标准,使得portlet可以在不同的服务器...
- **编写自己的 Portlet**:根据JSR168规范开发新的Portlet。 - **分析 Portlet**:深入了解Portlet的工作原理和技术细节。 - **创建自己的 Portlet**:完成从设计到部署的全过程。 综上所述,Liferay 6.0是一款...
本手册提供了关于使用Java标准Portlet API (JSR 168)进行portlet开发的详尽指南。通过遵循这些步骤和建议,开发者不仅能够掌握基本的API用法,还能了解与portlet开发相关的各种挑战和解决方案,从而更好地构建出高效...
- **Java Portlet Specification**:介绍了当前版本的Java Portlet规范(如JSR 168、JSR 286等),包括其发展历程、特点和优势。 - **Portlet生命周期**:阐述了Portlet从创建到销毁的整个生命周期过程,以及在这个...