JSF页面间传值精辟总结

最近开始学习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_r(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_r(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页面参数的传递及加载数据(又一篇)

在同一个页面实现功能,可以用ActionListener或用Action过程指向自身。

在不同的页面之间导航,可以用Action或Action过程,用ActionListener来处理传递的参数,加载数据。

 

一般的流程是:向一个页面传递参数,并依参数对这个页面的数据进行初始化,加载数据,然后再在视图jsp中显示数据。当然,简单的页面不需要接受参数,甚至不用加载数据。

 

由一个页面向另一个页面传递参数方法:

a.在facesconfig.xml的配置文件中,向该页面的ManageredBean的ManageredProperty注入request的参数#{param.name}

 

b.先获取该页面的ManageredBean,在代码中向它设值。

//获取BackingBean

Object BackingBean= FacesContext.getCurrentInstance().getApplication().getVariableResolver().resolveVariable(context, "BeanName");

 

c.向request中设值,再在该页面的ManageredBean中读取。

//设request值

FacesContext.getCurrentInstance().getExternalContext.getRequestMap().put("someKey", "someValue"); 

//读request值

Map params = FacesContext.getCurrentInstance().getExternalContext().getRequestParameterMap();

String someValue = params.get(" id ");

 

d.设置ActionListener(一般用于处理页面部件的事件。)

 

e.设置Session(Application)或用作用范围为Session(Application)的ManagerdBean.(该两类Bean存活范围长,占用服务器资源,开销较大,不能大量使用。一般不用于向另一个页面传递参数。)

  

JSF页面初始化数据的方法(实际上是初始化它的BackingBean,让它依据不同的条件(参数)装载数据):  

1.在BackingBean的无参数的构造函数中初始化(如读取向它传递的Request等值、读取数据库或文件中持久的数据)

缺点:必须放弃ManageredProperty的注入,用Request来传递参数。因为构造函数先执行,然后再来注入属性值。

优点是:简单,易用,不易出错。且可以直接用标准Url方式调用,如/ok.jsf?name=john,与其它的java web程序好兼容。

 

2.利用ManageredBean的ManagerdProperty的值注入。包括注入Request参数 如#{parap.name}.在get或Set某一属性时,依据传递的参数来初始化数据。

(在set某个属性时初始化,容易产生有些属性还没有被注入初始化,而在get某个属性时初始化数据,又有可能该属性未被调用,则无法完成初始化工作了。)

 

3.在代码Action中转向前获取该页面的BackingBean,来初始化它。

缺点是:依赖于代码Action,不能直接用URL。容易产生BackingBean中的相互依赖。

 

4.用ActionListener侦听某个Action执行后,再来解析Request参数或jsf部件值,来加载数据。








  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值