jsf幾個常用取值方法和技巧總結(持續更新)
1、獲取managedbean或是解析表達式
有三種方法
(1)
[code]
FacesContext context =FacesContext.getCurrentInstance();
ValueBinding binding =
context.getApplication().createValueBinding("#{bean}");
YourBean bean = (YourBean ) binding.getValue(context);
[/code]
(2)
[code]
FacesContext ctx = FacesContext.getCurrentInstance();
VariableResolver variableResolver =ctx.getApplication().getVariableResolver();
YourBean bean = (YourBean ) variableResolver.resolveVariable(ctx, "bean");
[/code]
(3)
[code]
Application application=context.getApplication();
YourBean ManageBeanProperty=(YourBean )application.evaluateValueExpressionGet(context,"#{bean}",YourBean .class);
[/code]
第3種方法只對jsf1.2可用。(evaluateValueExpressionGet方法1.1種沒有)
其實還有一種方法。后面會提到。
2、對于已知范圍和名字的bean,可以
externalContext.getRequestMap().get(beanName)
externalContext.getSessionMap().get(beanName)
externalContext.getApplicationMap().get(beanName)
3、FacesContext
組件實例相關
facesContext.getViewRoot()
可以獲取ViewRoot,然后遞歸循環其children得到整個組件樹,
可以實現:
(1)根據組建id得到組件。
(2)得到form,添加新的組件到此集合,或是改變form的屬性。
(3)得到某個類型的所有組件,然后加上監聽器。
。。。。。
從這個root入手,再加上事件,綁定和分析,幾乎可以完全控制整個組件樹。
4、Application
獲取方式Application application=facesContext.getApplication();
用處可以見下面的代碼:
(1)組件類型的注冊和組件集合的獲取
(2)converter,validator的。。。
(3)屬性分析器和變量分析器的。。。
(4)NavigationHandler、ViewHandler....
(5)添加一個listener
(6)創建一個組件的實例
(7)創建一個值綁定或方法綁定
大部分全局性配置的東西都在這兒可以找到。而且幾乎都是可以熱替換的。
其中5、6比較常用。
5、RuntimeConfig
獲取方式RuntimeConfig runtimeConfig = RuntimeConfig.getCurrentInstance();
兩個功能:
(1)獲取配置文件中所有的導航規則,或者運行時添加新的導航規則。
(2)獲取配置文件中所有的managedmean類型,或者運行時添加一個新的managedmean類型。
第一條可以實現通過一個給定的url,動態添加一條規則,然后在action中return起outcome字符串。
后一條可以獲取給定的bean的class全稱,實例化一個bean。或者動態配置一個bean。
6、ExternalContext
servlet相關操作和各種參數
(1)獲取response和request、session、servletContext
(2)redirect和dispacth
(3)獲取resquest、session、application、servlet參數
(4)獲取資源和url本地路徑
(5)encode url
7、綁定List和Map
使用JSF開發時,經常遇到要把MBean中的一個List或Map中的值通過EL顯示在頁面上,EL中訪問Map或List的方法如下:
假設FacesConfig中配置一個bean的MBean,它的類中定義了一個List類型的list屬性和一個Map型的map屬性。
首先是訪問List,頁面中引用bean中list屬性的方法為:#{bean.list[index]}
而對于Map,EL可以把Key作為一個屬性來讀取,因此對map的訪問可以寫為:#{bean.map.key},當然這樣可以解決基本的問題,但是如果map中的key是一個包含了空格或特殊字符的String,那么很明顯,這個字符串不符合作為屬性名的條件,那么用上面的方法去訪問明顯是有問題的,所以我們很可以用另外一種方法訪問Map中的value,#{bean.map['key']}。同時可以看到,因為EL中的內建對象基本都是用Map實現的,因此,EL中的訪問方法也是:#{sessionScope['key']}。
8、JSF動態為DataTable添加列
開發JSF的朋友可能會遇到這樣的問題,如果DataTable的列不固定,需要動態生成, 該如何實現呢。
假設FacesConfig中配置一個名為bean的MBean,該MBean中需定義一個類型為javax.faces.component.html.HtmlDataTable類型的變量dt,頁面中的DataTable設置bingding="#{bean.dt}"。
首先了解一下JSF中DataTable的渲染方式:
DataTable
--<Header> UIComponent
--<Children>List<HtmlColumn>
----<HtmlColumn>
------<Header>UIComponent
----<Children>List<UIComponent>
因此,要在后臺變更DataTable的狀態,可以用dt.setHeader(UIComponent)設置DataTable的表頭,然后可以往dt.getChildren()中添加HtmlColumn類型的列,同樣,列中也可以由Header和Children組成。代碼實現如下:
private void initialReportTable(List<ExcelReport> reportList) ...{
dt.getChildren().clear();
for (ExcelReport report : reportList) ...{
HtmlColumn column = new HtmlColumn();
HtmlOutputText header = new HtmlOutputText();
header.setValueExpression("value",
getValueExpression("#{rmaReport.captions.c"
+ report.getPosition() + "}"));
column.setHeader(header);
HtmlOutputText value = new HtmlOutputText();
String ve = getVEString(report);
System.out.println(report.getCaption() + " : " + ve);
value.setValueExpression("value", getValueExpression(ve));
column.getChildren().add(value);
dt.getChildren().add(column);
}
}其中,動態建立控件的方法為直接創建一個控件,然后通過ValueExpression來設置控件在運行時顯示的值,如果是Column中的數據,則可以使用#{tableVar.ColumnName}格式的EL表達式。
9、 JSF動態生成組件
用過Servlet和JSP的開發者對動態生成組件應該是情有獨鐘了,可以根據數據的情況生成特定的組件,這樣增大了Form的靈活性,那么JSF中如何生成動態的窗體呢,其實非常簡單。主要邏輯就是通過FacesContext得到viewRoot對象,然后通過viewRoot對象的getChildren方法可以得到viewRoot下的所有第一級組件,然后分別對每個組件的getChildren方法進行遞歸調用,就可以得到整個組件樹,當然可以對某個組件的getChildren得到的List使用add方法添加組件了,代碼如下,頁面有兩個commandButton,其中一個可以添加一個TextBox控件,另外一個可以在console打印出當前的組件列表。
package net.moon;
import java.util.List;
import javax.faces.component.UIComponent;
import javax.faces.component.UIViewRoot;
import javax.faces.component.html.HtmlInputText;
import javax.faces.context.FacesContext;
public class DymaComponent ...{
private UIViewRoot viewRoot;
private static int inputIndex = 0;
private List<UIComponent> getComponentChildren(UIComponent component)...{
List<UIComponent> componentList = null;
System.out.println(component.getId());
if(component.getChildCount() > 0)...{
for(UIComponent ui : component.getChildren())...{
componentList = getComponentChildren(ui);
}
}
return componentList;
}
public String getComponentsList()...{
viewRoot = FacesContext.getCurrentInstance().getViewRoot();
for(UIComponent component : viewRoot.getChildren())...{
getComponentChildren(component);
}
return null;
}
public String addTextBox()...{
viewRoot = FacesContext.getCurrentInstance().getViewRoot();
UIComponent form1 = viewRoot.getChildren().get(0);
HtmlInputText input = new HtmlInputText();
input.setId("input" + (inputIndex++));
input.setValue("Input 1");
input.setRendered(true);
form1.getChildren().add(input);
return null;
}
}
<%...@ page contentType="text/html; charset=UTF-8" %>
<%...@ taglib uri="http://java.sun.com/jsf/html" prefix="h" %>
<%...@ taglib uri="http://java.sun.com/jsf/core" prefix="f" %>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<title></title>
</head>
<body>
<f:view>
<h:form id="form1">
<h:commandButton id="commmand1" action="#{dymaComponent.getComponentsList}" value="Print ViewRoot"></h:commandButton>
<h:commandButton action="#{dymaComponent.addTextBox}" value="Add TextBox"></h:commandButton>
</h:form>
</f:view>
</body>
</html>
<?xml version="1.0" encoding="UTF-8"?>
<faces-config
xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-facesconfig_1_2.xsd"
version="1.2">
<managed-bean>
<managed-bean-name>
dymaComponent</managed-bean-name>
<managed-bean-class>
net.moon.DymaComponent</managed-bean-class>
<managed-bean-scope>
session</managed-bean-scope>
</managed-bean>
</faces-config>