Spring与WebLogic Portal的基本交互
来源:dev2dev
简介
BEA WebLogic Portal提供企业门户基础架构,用于简化门户开发。这包括一个用于开发门户的图形环境,以及基于浏览器的组装工具。本文中使用的版本是BEA WebLogic Portal 8.1 with Service Pack 6。
Spring Framework鼓励使用分层的架构,通过其控制反转容器,这种架构可以集中配置和控制应用程序对象。Spring提供多种抽象层和集成,但是这个例子只演示了Spring的核心功能。本文中使用的版本是Spring Framework 1.2.8。要了解对Spring的基本介绍,请参见Better J2EEing with Spring(Dev2Dev, 2005年7月)一文。
本文中考虑了两个用例,它们均专注于Spring提供的核心功能。一个例子演示了如何在WebLogic Portal页面流中使用Spring功能,另一个例子则演示了如何在WebLogic Portal 支持文件中使用Spring功能。
本文逐个考察了上述两个用例,并描述了如何实现它们。
演示应用程序的架构
本文附带了一个演示应用程序,它由一个使用BEA WebLogic Workshop创建的单页面门户组成。它是一个基于文件的门户,有4个portlet,排成2列,构成了一个简单的矩阵,如图1所示。
图 1. 带有两类portlet的portle矩阵,以两种不同方式对这两类portlet进行声明性配置。
其中两个portlet是页面流portlet的实例,而其他两个portlet则是使用Java 支持文件的实例。每个portlet都有自己的BeanName portlet参数。这个参数的值就是Spring bean的名称,这个名称定义在Spring配置文件applicationContext.xml中。我们把其中一个Spring bean实现为简单的Java类,其功能是使用Hashtable保存和检索员工记录,而在一个Java类中实现了其他的Spring bean, 这个类的功能是使用JDBC访问安装的默认数据库,从而保存和检索员工记录。
这4个portlet实例组成了一个简单的矩阵。一个页面流使用Hashtable bean,而另一个页面流则使用JDBC bean。类似地,一个支持文件portlet使用Hashtable bean,而另一个支持文件使用JDBC bean。两个页面流portlet都是同一个portlet实现的实例。惟一的区别在于portlet参数的值是Hashtable还是JDBC bean。类似地,两个支持文件portlet中也使用了相同的代码。
下面的例子使用了相同的Spring应用程序上下文,而这个上下文是使用web.xml中的一个Spring ContextLoaderListener项创建的。使用这一项,Spring就会使当前的应用程序上下文成为单独可用的上下文。web.xml文件位于应用程序的WEB-INF目录中,而且需要另外的侦听器来初始化上下文。
这就是web.xml中那个另外的侦听器:
org.springframework.web.context.ContextLoaderListener
默认情况下,Spring会查找一个位于相同WEB-INF目录下名为applicationContext.xml的应用程序上下文配置文件。对于此演示应用程序,文件定义了两个员工服务bean,其中分别包含对两个员工bean的引用。这两个员工服务的定义是一样的,除了员工服务类名之外。一个bean引用了EmployeeServiceHashtable类,而另一个bean引用了EmployeeServiceJDBC类。这两个类均实现了EmployeeService接口。
页面流用例
页面流定义了一个JSP,它带有一个表单,用于接受用户输入的员工ID以便进行查找。这个表单提交给一个Employee Lookup动作,该动作将会检索在portlet参数中指定的Spring bean。如果找到员工信息,就会把员工对象转发给JSP,然后JSP就会显示该员工的详细信息。
我们编写了一个便捷的方法,用于获取Spring应用程序上下文。这就是上面使用ContextLoaderListener创建的单独应用程序上下文。下面给出这个便捷方法的代码:
WebApplicationContext getSpringContext() {
return WebApplicationContextUtils.getWebApplicationContext(
getServlet().getServletContext());
}
下面是员工lookup 动作的代码:
PortletBackingContext context =
PortletBackingContext.getPortletBackingContext(getRequest());
PortletPreferences preferences =
context.getPreferences(getRequest());
EmployeeService service= (EmployeeService) getSpringContext().
getBean(preferences.getValue("BeanName",""),
com.bea.spring.example.EmployeeService.class);
Employee emp = null;
Forward f = null;
try {
emp = service.getEmployee(Integer.parseInt(form.employeeLookupId));
f = new Forward("success", "Employee", emp);
}
catch(Exception e) {
f = new Forward("notFound");
}
return f;
员工查找动作的前两行代码使portlet参数选择变为可用。接下来的一行使用便捷方法获取Spring上下文和参数选择,以便获得bean的名称。Spring getBean()方法返回指定的bean。把类名传递给getBean() 方法是可选的,但是这样做可以实现类型安全,确保返回的对象真正实现了EmployeeService接口。在try块中,员工服务查询了用户在前面表单中输入的员工ID。
这段代码演示了如何协同使用Spring和WebLogic Portal;它并不知道哪个bean被实例化,只是要求bean实现EmployeeService接口。Portlet参数提供bean的名称,而applicationContext.xml提供bean的定义。Spring框架负责提供bean,而页面流负责获得和显示搜索结果。
支持文件用例
与页面流的例子一样,JSP给出一个表单,便于用户输入要查找的员工ID。然而,这个JSP使用handlePostbackData()方法提交到一个Java支持文件。这个方法经历同样的步骤,从Spring应用程序上下文获得portlet参数、Spring应用程序上下文和指定的bean。作为结果的Employee对象以属性的形式附加在请求上,以便于随后进行显示。
下面是Java支持文件中的代码:
PortletBackingContext context =
PortletBackingContext.getPortletBackingContext(request);
PortletPreferences preferences = context.getPreferences(request);
String source=(String)preferences.getValue("BeanName","");
WebApplicationContext wac =
WebApplicationContextUtils.getWebApplicationContext(
request.getSession().getServletContext());
EmployeeService service = (EmployeeService)wac.getBean(source,
com.bea.spring.example.EmployeeService.class);
try
{
request.setAttribute("Source",source);
request.setAttribute("Employee",
service.getEmployee(Integer.parseInt(
request.getParameterValues("employeeId")[0])));
}
catch(Exception e)
{
e.printStackTrace();
return false;
}
return true;
“Source”属性仅用于传递portlet参数中指定的bean名称。与页面流的例子一样,这段代码不知道哪个bean被实例化,只是要求bean实现EmployeeService接口。
结束语
这个演示应用程序说明了如何协同使用BEA WebLogic Portal和Spring框架。两个用例演示了如何使用portlet参数和Spring XML配置文件来控制将哪个bean实例化。这种方法让门户可以在应用程序上下文中利用Spring bean提供的功能。结合这两种技术所带来的强大功能可以帮助开发人员交付灵活的应用程序。