JSF和Spring的集成

日期: 2009-10-22 作者:雨滂沱 来源:TechTarget中国 英文

  JSF和Spring集成的资料比较少,原理是获得彼此的上下文引用,以此进一步获得各自管理的bean,这是可能的,因为两者是web应用框架都遵循servlet规范,为二者整合提供了可能和基础。

  在 Spring中ApplicationContext是相当重要的类,对于web应用,它还包装了 javax.servlet.ServletContext,为web应用提供了所有可以利用的数据,包括可管理bean,Faces中通过 FacesContext类可以获得所有可以利用的资源,同样包括JSF的可管理支持bean,它们都围绕着ServletContext提供了自己的门面,通过各自的门面在Servlet容器的世界里彼此相通。

  本文介绍两种方式,实现二者集成:

  1. 通过写自己的类来完成二者的连通,实际上只是获得彼此世界里存活的bean,对于JSF中事件处理可能需要更进一步的构思和编码,为了这点,第二个方法介绍了一种框架。

  2. 使用框架完成二者集成。

  一  自己动手,下面的代码以示例为主,其它涉及的类和接口略去

  这个工具类提供在JSF世界里查找Spring管理的bean。也实现在Spring中查找JSF组件的方法。

package com.skysoft.rbac.dao;  
import org.springframework.context.ApplicationContext;  
import org.springframework.web.context.support.WebApplicationContextUtils;  
import javax.faces.context.FacesContext;  
import javax.servlet.ServletContext;  
import javax.faces.el.ValueBinding;  
import javax.faces.FactoryFinder;  
import javax.faces.application.Application;  
import javax.faces.application.ApplicationFactory;  
public final class SpringFacesUtil {  
  public SpringFacesUtil() {  
  }  
  /**  
   * 从Spring中查找bean.  
   * @param beanname String  
   * @return Object  
   */  
  public static Object findBean(String beanname) {  
    ServletContext context = (ServletContext) FacesContext.getCurrentInstance().  
        getExternalContext().getContext();  
    ApplicationContext appctx = WebApplicationContextUtils.  
        getRequiredWebApplicationContext(context);  
    return appctx.getBean(beanname);  
  }  
  /**  
   * 从JSF中查找bean.  
   * @param beanname String  
   * @return Object  
   */  
  public static Object lookupBean(String beanname) {  
    Object obj = getValueBinding(getJsfEl(beanname)).getValue(FacesContext.  
        getCurrentInstance());  
    return obj;  
  }  
  private static ValueBinding getValueBinding(String el) {  
    return getApplication().createValueBinding(el);  
  }  
  private static Application getApplication() {  
    ApplicationFactory appFactory = (ApplicationFactory) FactoryFinder.  
        getFactory(FactoryFinder.APPLICATION_FACTORY);  
    //FactoryFinder.FACES_CONTEXT_FACTORY  
    //FactoryFinder.RENDER_KIT_FACTORY  
    return appFactory.getApplication();  
  }  
  private static String getJsfEl(String value) {  
    return “#{” + value + “}”;  
  }  
}

  下面定义一个由JSF管理的bean:

package com.skysoft.rbac.dao;  
   
import javax.servlet.ServletContext;  
import org.springframework.context.ApplicationContext;  
import org.springframework.web.context.support.WebApplicationContextUtils;  
import org.skysoft.struts.jsf.util.FacesUtils;  
public class ServiceLocatorBean  
    implements ServiceLocator {  
  private static final String DAO_SERVICE_BEAN_NAME = “userDAO”;  
  //这个dao就是由Spring提供的管理bean,这个dao可以使用Hibernate实现.  
  private UserDAO dao;  
  public ServiceLocatorBean() {  
    this.dao = (UserDAO)SpringFacesUtil.findBean(DAO_SERVICE_BEAN_NAME);  
  }  
  public UserDAO getDao() {  
    return dao;  
  }  
}  

  下面是一个使用ServiceLocatorBean的类。

   public class UserDAOImp  
    extends HibernateDaoSupport implements UserDAO {  
  private UserDAO dao;  
  private List list;  
  public UserDAOImp() {}  
  public List getList() {  
    if (list == null) {  
      list = dao.getList();  
    }  
    return list;  
  }  
  public UserDAO getDao() {  
    return dao;  
  }  
  public void setDao(UserDAO dao) {  
    this.dao = dao;  
  }  
}

  下面是一个使用ServiceLocatorBean的类:

public class UserDAOImp  
  extends HibernateDaoSupport implements UserDAO {  
  private UserDAO dao;  
  private List list;  
  public UserDAOImp() {}  
  public List getList() {  
    if (list == null) {  
      list = dao.getList();  
    }  
    return list;  
  }  
  public UserDAO getDao() {  
    return dao;  
  }  
  public void setDao(UserDAO dao) {  
    this.dao = dao;  
  }  
}

  在faces-config.xml中的配置:

<managed-bean> 
<managed-bean-name>serviceLocatorBeanmanaged-bean-name> 
<managed-bean-class>com.skysoft.rbac.dao.ServiceLocatorBeanmanaged-bean-class> 
<managed-bean-scope>sessionmanaged-bean-scope> 
managed-bean> 
<managed-bean> 
<managed-bean-name>Usermanaged-bean-name> 
<managed-bean-class>com.skysoft.rbac.Usermanaged-bean-class> 
<managed-bean-scope>requestmanaged-bean-scope> 
<managed-property> 
<property-name>serviceLocatorproperty-name> 
<property-class>com.skysoft.rbac.dao.ServiceLocatorBeanproperty-class> 
<value>#{serviceLocatorBean}value> 
      managed-property> 
managed-bean>

  在applicationContext.xml中的配置:

<bean id=”userDAO” class=”com.skysoft.rbac.dao.UserDAOImp”> 
      <property name=”sessionFactory”> 
             <ref local=”sessionFactory” /> 
      property> 
bean>

  二 使用框架

  1.介绍

  这个框架是Spring相关项目,提供一个包de.mindmatters.faces.spring,这个包包含JSF和Spring框架综合集成的粘合代码,这些代码以独立于一个实现的方式完成,这样它能和任何JSF实现一起使用。

  本包的提供的代码主要目的是尽可能透明的集成两个框架,主要特征:

  ◆JSF/JSP开发者应该能访问Spring管理的Beans,就好象它们是由JSF管理的。
  ◆JSF可管理beans应能集成入Spring。
  ◆RequestHandledEvent事件也应该能被发布到Spring。

  2.JSF配置集成

  本包构造了一个基于faces配置文件(e.g. /WEB-INF/faces-config.xml)的WebApplicationContext类, 让它成为遵循”spring-beans” DTD配置文件(e.g. defined in /WEB-INF/applicationContext.xml)来配置的ApplicationContext的孩子,这样依从”faces- config” DTD的WebApplicationContext就是全特征的,即自动拥有如下功能:

  1)JSF可管理beans实现了Spring的*Aware interfaces:

  ◆ApplicationContextAware
  ◆BeanFactoryAware
  ◆BeanNameAware
  ◆ResourceLoaderAware
  ◆ServletContextAware

  2)JSF可管理beans实现Spring的lifecycle interfaces:
  
  InitializingBean
  DisposableBean
  ◆实现Spring的FactoryBean interface
  ◆实现Spring的ApplicationListener interface
  ◆发布ApplicationEvent事件。
  ◆从资源中读取消息。
  等等,更多可看Spring。

  3 访问方式

  1) 从JSF中程序化的访问Spring管理的beans。

  因为在FacesWebApplicationContext和ApplicationContext之间有层次关系,所以你的JSF可管理支持beans 能容易的实现ApplicationContextAware接口,并能通过getBean方法访问它而不管它是否定义在 FacesWebApplicationContext中还是定义在父ApplicationContext类对象中。

  2) 通过JSF EL从JSF中访问Spring管理的beans。

  能够使用JSF EL访问beans无论你引用的bean由JSF管理还是由Spring管理.两个bean上下文在存取时间合并。

  a) 直接访问:
如果一个带有请求名字的bean只存在于Spring上下文内的话,这个bean被使用,bean的singleton属性设置被完全保持。

  b) 区域化访问(scoped access):

  如果你要从JSF定义bean的作用域的能力上得益还想让那个bean由Spring管理,那么就要在两个上下文中定义,只是对于JSF上下文中的定义的类类型要使用de.mindmatters.faces.spring.SpringBeanFactory类,你还应该设置那个bean的 singleton属性到false,因这能覆盖你的作用域设置.在你使用JSF EL访问bean时,你总能获得一个遵从你在JSF上下文中定义的作用域设置的由Spring管理的bean的实例.

  三 用法

  通常,就象设置任何其它JSF web应用一样设置你的web应用,下面的样例配置展示怎样使能上面提到的特征。

  在web.xml配置中必须加入下列配置条目,同时注意把该库的jsf-spring.jar放在适当的位置。

<web-app> 
    ………  
         
    <filter> 
        <filter-name>RequestHandledfilter-name> 
        <filter-class>de.mindmatters.faces.spring.support.RequestHandledFilterfilter-class> 
    filter> 
        
    <filter-mapping> 
        <filter-name>RequestHandledfilter-name> 
        <url-pattern>*.facesurl-pattern> 
    filter-mapping> 
   
     
    <listener> 
        <listener-class>org.springframework.web.context.ContextLoaderListenerlistener-class> 
    listener> 
    ………  
web-app>

  下面的一些说明,都可以通过下载这个Spring相关项目得到,列在这里只为演示上面的说明的功能。


WEB-INF/faces-config.xml
<managed-bean> 
    <managed-bean-name>jsfBeanmanaged-bean-name> 
    <managed-bean-class>example.NameBeanmanaged-bean-class> 
    <managed-bean-scope>sessionmanaged-bean-scope> 
    <managed-property> 
        <property-name>nameproperty-name> 
    managed-property> 
managed-bean> 
 
       <managed-bean> 
              <managed-bean-name>scopedAccessSpringBeanmanaged-bean-name> 
       <managed-bean-class>de.mindmatters.faces.spring.SpringBeanScopemanaged-bean-class> 
              <managed-bean-scope>sessionmanaged-bean-scope> 
       managed-bean> 
 
<managed-bean> 
    <managed-bean-name>referencingBeanmanaged-bean-name> 
    <managed-bean-class>example.ReferencingBeanmanaged-bean-class> 
    <managed-bean-scope>sessionmanaged-bean-scope> 
    <managed-property> 
        <property-name>referencedBeanproperty-name> 
        <value>#{managedPropertyAccessSpringBean}value> 
    managed-property> 
managed-bean> 
WEB-INF/applicationContext.xml (partial)  
  <bean id=”directAccessSpringBean” class=”example.NameBean”/> 
  <bean id=”scopedAccessSpringBean” class=”example.NameBean” singleton=”false”/> 
  <bean id=”managedPropertyAccessSpringBean” class=                                                                   “example.NameBean” singleton=”false”/>

我们一直都在努力坚持原创.......请不要一声不吭,就悄悄拿走。

我原创,你原创,我们的内容世界才会更加精彩!

【所有原创内容版权均属TechTarget,欢迎大家转发分享。但未经授权,严禁任何媒体(平面媒体、网络媒体、自媒体等)以及微信公众号复制、转载、摘编或以其他方式进行使用。】

微信公众号

TechTarget微信公众号二维码

TechTarget

官方微博

TechTarget中国官方微博二维码

TechTarget中国

相关推荐

  • Spring针对Java 8升级

    Java 8刚刚在几周前发布。后来Spring Framework项目负责人发表了题为《企业项目中的Java 8》的文章。文中,指出那些著名的Java EE应用服务器如何不允许轻松升级。

  • 软件项目成功:项目的处理

    在软件项目成功的因素中有我们谈及了问题域和社区,然这两者并不是软件项目本身。你可以把分类当作问题领域连续讨论几个星期,但分类的问题跟实际执行分类的库并不一样。

  • Rails 4.1改进启动时间和响应布局

    在经历了两个候选版本后,Rails团队刚刚发布了Rails 4.1.0。以“单点版本(point release)”发布意在说明更改向后兼容,可以无痛升级。

  • 你应该远离的六个Java特性

    近日,Tarnovski撰文谈到了普通开发者应该尽量避免使用的6个Java特性,这些特性常见于各种框架或库当中,使用这些特性也许会给你所开发的应用带来灾难。