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;   
    }

}

你可能感兴趣的:(JSF学习)