JSF學習(二)——託管Bean的使用方法和技巧

最近開始學習JSF基礎,發現比較重要的一點,就是如何用編程方式訪問託管Bean。看了一些JSF的實例,不過大多都是用JSF1.1來實現的。雖然在JSF1.2的環境中也可以很好運行,但是在編譯的時候會看到降級的消息。這裏找了一些資料總結一下JSF1.1和JSF1.2訪問託管Bean的方法。

一、從JSF頁面傳遞參數給託管Bean
雖然利用h:commandLink 和h:commandButton組件,可以通過action和actionListener來觸發託管Bean中的方法,但是不能向這些方法中傳遞參數。對於動態傳遞參數,不是不可以實現,這點可以通過使用f:attribute來實現。而且f:attribute也可以很好的和actionListener聯合使用。
例子:

<h:commandLink actionListener="#{myBean.action}">
        
<f:attribute name="attrname1" value="attrvalue1" />
        
<f:attribute name="attrname2" value="attrvalue2" />
        ...   
        
<h:outputText value="Click here" />
    
</h:commandLink>
    
    
<h:commandButton value="Press here" actionListener="#{myBean.action}">
        
<f:attribute name="attrname1" value="attrvalue1" />
        
<f:attribute name="attrname2" value="attrvalue2" />
        ...
    
</h:commandButton>

這些屬性可以通過父組件的getAttributes()方法取到,父組件可以通過傳遞給actionListener的ActionEvent實例取到

public void action(ActionEvent event) 
    
{   
        String attrvalue1 
= (String) event.getComponent().getAttributes().get("attrname1");
        String attrvalue2 
= (String) event.getComponent().getAttributes().get("attrname2");
        ...
    }

變量attrvalue1和attrvalue2包含從f:attribute set進來的值。
另一個欠文雅的方式就是通過f:param組件來傳值,這個只是對h:commandLink起效。

<h:commandLink action="#{myBean.action}">
        
<f:param name="paramname1" value="paramvalue1" />
        
<f:param name="paramname2" value="paramvalue2" />
        ...
        
<h:outputText value="Click here" />
    
</h:commandLink>

這些參數可以通過FacesContext的getRequestParameterMap()方法取到。通過下面的方法,可以用f:param的name來獲取任何寫在command塊中f:param的值。

public static String getFacesParamValue(String name) 
    
{   
        
return (String) FacesContext.getCurrentInstance().getExternalContext().getRequestParameterMap().get(name);
    }

上面的方法可以用在任何Bean的方法中。舉例

public void action() 
    
{   
        String paramvalue1 
= getFacesParamValue("paramname1");   
        String paramvalue2 
= getFacesParamValue("paramname2");   
        ...
    }

變量paramvalue1和paramvalue2包含從f:param set進來的值。
不過要注意,屬性的名字要唯一,而且不能用其他組件的屬性名,比如:"id", "name", "value","binding", "rendered",等。

二、從JSF頁面傳遞組件屬性到託管Bean
f:attribute組件也可以用來訪問,任何綁定在託管Bean的UI組件的屬性。這些屬性值可以通過父組件的getAttributes()來獲得。因爲不能以方法參數的方式傳值給託管Bean綁定的UI組件的getter和setter方法,這時f:attribute就會非常有用。這裏有個UI組件綁定到託管Bean的基礎例子

<h:outputText binding="#{myBean.myText}" value="#{myBean.myTextValue}">
        
<f:attribute name="attributename" value="attributevalue" />
    
</h:outputText>

 

託管Bean代碼:

import javax.faces.component.html.HtmlOutputText;
public class MyBean 
{   
    
private HtmlOutputText myText; 
    
    
public HtmlOutputText getMyText() 
    
{   
        
return myText;  
    }
   
    
    
public String getMyTextValue() 
    
{       
        
return (String) myText.getAttributes().get("attributename");   
    }

    
    
public void setMyText(HtmlOutputText myText) 
    
{       
        
this.myText = myText;
    }

}

三、在請求之間傳遞對象(Passing objects from request to request)
如果有一個request範圍內的託管Bean,在下一個請求中想要重用這個bean的屬性,參數,或者對象,但是不想一遍又一遍的初始化這個Bean。可以用h:inputhidden來解決這個問題。這裏有個簡單的例子:

<h:form>   
        ...
        
<h:inputHidden value="#{myBean.value}" />
      ...
    
</h:form>

另一種方法就是用SessionMap來保存那些需要保存在session中的值。

public class MyBean 
{   
    
public Object getMyValue() 
    
{       
        
return FacesContext.getCurrentInstance().getExternalContext().getSessionMap().get("MyBeanMyValue"); 
    }
   
    
    
public void setMyValue(Object myValue) 
    
{       
        FacesContext.getCurrentInstance().getExternalContext().getSessionMap().put(
"MyBeanMyValue", myValue);
    }
  
      
    
// This might be useful.   
    private void resetSessionValue(Object myKey) 
    
{       
        FacesContext.getCurrentInstance().getExternalContext().getSessionMap().remove(myKey);
    }

}

四、在託管Bean之間通信
實踐時會有多個託管Bean。如果設計需要,可以利用getSessionMap()在託管Bean之間通信。
一個例子,有兩個託管Bean:

<managed-bean>
        
<managed-bean-name>myBean1</managed-bean-name>
        
<managed-bean-class>mypackage.MyBean1</managed-bean-class>
        
<managed-bean-scope>request</managed-bean-scope>
    
</managed-bean>
    
<managed-bean>
        
<managed-bean-name>myBean2</managed-bean-name>
        
<managed-bean-class>mypackage.MyBean2</managed-bean-class>
        
<managed-bean-scope>session</managed-bean-scope>
    
</managed-bean>

託管Bean myBean1和myBean2是支撐Bean MyBean1.java和MyBean2.java的實例,它們可以通過JSF頁面來訪問。不管它們的managed-bean-scope是request還是session。如果managed-bean-scope被設置成session,在整個session範圍內可以使用同一個Bean的實例;如果managed-bean-scope被設置成request,那麼每個request(form action)每次會創建一個Bean的實例。

用下面的方法,可以爲每個託管Bean set和get static的參數。可以把它寫成protected方法,放在一個超類中,讓每個託管Bean繼承,這會非常有用,或者寫入一個Util類中,自己選擇。

 

public class MySuperBean 
{   
    
protected static Object getSessionValue(Object myKey) 
    
{       
        
return FacesContext.getCurrentInstance().getExternalContext().getSessionMap().get(myKey);
    }
   
    
    
protected static void setSessionValue(Object myKey, Object myValue) 
    
{       
        FacesContext.getCurrentInstance().getExternalContext().getSessionMap().put(myKey, myValue);
    }

}


public class MyBean1 extends MySuperBean 
{   
    
public void myMethod() 
    
{       
        String myValue 
= "value1";       
        setSessionValue(
"MyBean1MyValue", myValue);
        ...   
    }

}

public class MyBean2 extends MySuperBean 
{   
    
public void myMethod() 
    
{       
        String myValue 
= (String) getSessionValue("MyBean1MyValue");
        ...   
    }

}

五、在託管Bean中訪問另一個託管Bean
如果有很多託管Bean,想要從其中一個託管Bean訪問其他的託管Bean,這裏有六中方法。
可以使用:
  1)getVariableResolver
  2)createValueBinding
  3)getELResolver (since JSF 1.2)
  4)createValueExpression (since JSF 1.2)
  5)getRequestMap
  6)getSessionMap.
舉例:假設有兩個託管Bean

<managed-bean>
    
<managed-bean-name>myBean1</managed-bean-name>
    
<managed-bean-class>mypackage.MyBean1</managed-bean-class>
    
<managed-bean-scope>request</managed-bean-scope>
</managed-bean>
<managed-bean>
<managed-bean-name>myBean2</managed-bean-name>
    
<managed-bean-class>mypackage.MyBean2</managed-bean-class>
    
<managed-bean-scope>session</managed-bean-scope>
</managed-bean>

託管Bean myBean1和myBean2是支撐Bean MyBean1.java和MyBean2.java的實例,它們可以通過JSF頁面來訪問。不管它們的managed-bean-scope是request還是session。
只是要注意的是,getRequestMap在託管Bean被設置成request的時候使用,getSessionMap在託管Bean被設置成session的時候使用。

<h:form>   
    
<h:commandButton action="#{myBean1.action1}" value="action1" />
    
<h:commandButton action="#{myBean1.action2}" value="action2" />
    
<h:commandButton action="#{myBean1.action3}" value="action3" />
    
<h:commandButton action="#{myBean1.action4}" value="action4" />
    
<h:commandButton action="#{myBean1.action5}" value="action5" />
    
<h:commandButton action="#{myBean1.action6}" value="action6" />
    
<h:outputText binding="#{myBean2.text}" />
</h:form>

MyBean1.java:

package mypackage;
import javax.faces.context.FacesContext;
public class MyBean1 
{    
    
// Using VariableResolver. NOTE: this is deprecated since JSF 1.2!   
    public void action1() 
    
{       
        FacesContext context 
= FacesContext.getCurrentInstance();       
        MyBean2 myBean2 
= (MyBean2) context.getApplication().getVariableResolver().resolveVariable(context, "myBean2");
        myBean2.getText().setValue(
"action1");   
    }
   
    
    
// Using ValueBinding. NOTE: this is deprecated since JSF 1.2!   
    public void action2() 
    
{       
        FacesContext context 
= FacesContext.getCurrentInstance(); 
        MyBean2 myBean2 
= (MyBean2) context.getApplication().createValueBinding("#{myBean2}").getValue(context);       
        myBean2.getText().setValue(
"action2");   
    }
   
    
    
// Using ELResolver. NOTE: this is implemented since JSF 1.2!  
    public void action3() 
    
{       
        FacesContext context 
= FacesContext.getCurrentInstance();
        MyBean2 myBean2 
= (MyBean2) context.getELContext().getELResolver().getValue(context.getELContext(), null"myBean2");
        myBean2.getText().setValue(
"action3");
    }
   
    
    
// Using ValueExpression. NOTE: this is implemented since JSF 1.2!   
    public void action4() 
    
{       
        FacesContext context 
= FacesContext.getCurrentInstance();
        MyBean2 myBean2 
= (MyBean2) context.getApplication().getExpressionFactory().createValueExpression(context.getELContext(), "#{myBean2}", MyBean2.class).getValue(context.getELContext());
        myBean2.getText().setValue(
"action4");   
    }
  
    
    
// Using RequestMap. NOTE: myBean2 should be request scoped!   
    public void action5() 
    
{       
        Object object 
= FacesContext.getCurrentInstance().getExternalContext().getRequestMap().get("myBean2");
        
// This only works if myBean2 is request scoped.       
        if (object != null
        
{           
            MyBean2 myBean2 
= (MyBean2) object;
            myBean2.getText().setValue(
"action5");       
        }
   
    }
   
    
    
// Using SessionMap. NOTE: myBean2 should be session scoped!   
    public void action6() 
    
{       
        Object object 
=  FacesContext.getCurrentInstance().getExternalContext().getSessionMap().get("myBean2");
        
// This only works if myBean2 is session scoped.       
        if (object != null
        
{         
            MyBean2 myBean2 
= (MyBean2) object;
            myBean2.getText().setValue(
"action6"); 
        }
   
    }


}


MyBean2.java:

package mypackage;
import javax.faces.component.html.HtmlOutputText;
public class MyBean2 
{   
    
private HtmlOutputText text;   
    
    
public HtmlOutputText getText() 
    
{       
        
return text;   
    }
   
    
    
public void setText(HtmlOutputText text) 
    
{       
        
this.text = text;   
    }

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