JSF和Spring的集成

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>serviceLocatorBean</managed-bean-name> 
        <managed-bean-class>com.skysoft.rbac.dao.ServiceLocatorBean</managed-bean-class> 
        <managed-bean-scope>session</managed-bean-scope> 
    </managed-bean> 
    <managed-bean> 
        <managed-bean-name>User</managed-bean-name> 
        <managed-bean-class>com.skysoft.rbac.User</managed-bean-class> 
        <managed-bean-scope>request</managed-bean-scope> 
        <managed-property> 
             <property-name>serviceLocator<property-name> 
             <property-class>com.skysoft.rbac.dao.ServiceLocatorBean<property-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>RequestHandled</filter-name> 
            <filter-class>de.mindmatters.faces.spring.support.RequestHandledFilter</filter-class> 
        </filter> 
            
        <filter-mapping> 
            <filter-name>RequestHandled</filter-name> 
            <url-pattern>*.faces</url-pattern> 
        </filter-mapping> 
       
         
        <listener> 
            <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> 
        </listener> 
        .........  
    </web-app> 
下面的一些說明,都可以通過下載這個Spring相關項目得到,列在這裏只爲演示上面的說明的功能.
WEB-INF/faces-config.xml

<managed-bean> 
    <managed-bean-name>jsfBean</managed-bean-name> 
    <managed-bean-class>example.NameBean</managed-bean-class> 
    <managed-bean-scope>session</managed-bean-scope> 
    <managed-property> 
        <property-name>name</property-name> 
    </managed-property> 
</managed-bean> 
 
       <managed-bean> 
              <managed-bean-name>scopedAccessSpringBean</managed-bean-name> 
       <managed-bean-class>de.mindmatters.faces.spring.SpringBeanScope</managed-bean-class> 
              <managed-bean-scope>session</managed-bean-scope> 
       </managed-bean> 
 
<managed-bean> 
    <managed-bean-name>referencingBean</managed-bean-name> 
    <managed-bean-class>example.ReferencingBean</managed-bean-class> 
    <managed-bean-scope>session</managed-bean-scope> 
    <managed-property> 
        <property-name>referencedBean</property-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"/> 
參考:
http://jsf-spring.sourceforge.net/   JSF-Spring,Spring相關項目官方站點,提供本文介紹的框架下載以及實例下載.
http://www.javaworld.com/javaworld/jw-07-2004/jw-0719-jsf.html一篇關於JSF和Spring的文章.



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章