JSF接受属性的自定义组件

作者在 2008-02-01 09:37:38 发布以下内容
        现在来写个接受属性的自定义组件例子。跟前面介绍的纯输出自定义组件的流程大致相同,增加了得到属性以及根据属性的不同值来处理逻辑的代码。这个例子就是根据race属性的不同来显示各个race有哪些hero(玩魔兽的人知道的,嘿嘿)。
        首先编写HtmlHero.java:

package src;

import javax.faces.component.*;

import javax.faces.context.*;

import java.io.*;

public class HtmlHero extends UIComponentBase {

public void encodeBegin(FacesContext context) throws IOException {

ResponseWriter ut = context.getResponseWriter();

String race = (String)getAttributes().get("race");//这句话是得到页面上组件的race属性,然后做处理

String heroes = hero(race);

out.write(heroes);

}

public String getFamily() {

return null;

}

/*简单的属性处理方法*/

public String hero(String race) {

String heroes = "";

if(race.equals("Hum")) heroes = " heroes are:AM, MK, PAL, BMG";

else if(race.equals("Orc")) heroes = " heroes are:FS, BM, TC, SH";

else if(race.equals("Ud")) heroes = " heroes are:DK, LICH, DL, CL";

else if(race.equals("Ne")) heroes = " heroes are:DH, POM, KOG, WD";

else heroes = ":Unknown race";

return heroes;

}

}
        同样需要继承UIComponentBase,并覆盖getFamily方法的时候,return null。
        然后编写该组件的标签类HtmlHeroTag.java。这里就有很大不同了。

package src;

import javax.faces.application.Application;

import javax.faces.component.UIComponent;

import javax.faces.context.FacesContext;

import javax.faces.el.ValueBinding;

import javax.faces.webapp.UIComponentTag;

public class HtmlHeroTag extends UIComponentTag {

String race = "";

public String getComponentType() {

return "HtmlHero";

}

public String getRendererType() {

return null;

}

protected void setProperties(UIComponent component) {

super.setProperties(component);//必须有这一句!

if(isValueReference(race)) {

FacesContext context = FacesContext.getCurrentInstance();

Application app = context.getApplication();

ValueBinding binding = app.createValueBinding("race");

component.setValueBinding("race", binding);

} else {

component.getAttributes().put("race", race);

}

}

public String getRace() {

return race;

}

public void setRace(String race) {

this.race = race;

}

}
        除了覆盖getComponentType方法和getRendererType方法外,还多了一个setProperties方法。在这个方法里面,首先调用父类的setProperties方法,然后再判断页面上的属性是否是一个JSF的表达式语言(类似"#{beanName.propertyName}")。如果是表达式语言,就创建并绑定、保存值;否则,就直接调用getAttributes().put()方法来保存值。
        然后写一个tld文件来声明这个标签。我的是WEB-INF/tlds/HtmlHero.tld:

<?xml version="1.0" encoding="UTF-8"?>

<taglib version="2.0">

<tlib-version>1.0</tlib-version>

<short-name>jsf-custom-components</short-name>

<uri>http://coreservlets.com/jsf/simple</uri>

<tag>

<description>

Output heroes of the selected race

</description>

<name>Hero</name>

<tag-class>src.HtmlHeroTag</tag-class>

<body-content>empty</body-content>

<attribute><name>id</name></attribute>

<attribute><name>rendered</name></attribute>

<attribute>

<name>race</name>

<required>true</required>

</attribute>

</tag>

</taglib>

        其实,如果你还想写几个自定义标签的话,只需要在这个tld文件里面加相应的<tag>内容就行了。页面上引入的时候,是根据<uri>来找tld文件的。然后根据<tag>里面<name>来使用各个不同的标签。红色部分就是说明race属性是必需的。
        然后在你的faces-config.xml文件中加入你的组件声明:

<component>

<component-type>HtmlHero</component-type>

<component-class>src.HtmlHero</component-class>

</component>

        重申一遍,<component-type>对应组件标签类中,getComponentType返回的字符串,而<component-class>则对应你自己编写的标签类。
        最后就是页面文件了。htmlHero.jsp:

<%@ page language="java" contentType="text/html; charset=ISO-8859-1"

pageEncoding="ISO-8859-1"%>

<%@taglib uri="http://java.sun.com/jsf/core" prefix="f" %>

<%@taglib uri="http://java.sun.com/jsf/html" prefix="h" %>

<%@taglib uri="http://coreservlets.com/jsf/simple" prefix="custom" %>

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">

<html>

<head>

<meta. http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">

<title>Html Hero Page</title>

</head>

<body>

<f:view>

<h1>Hum<custom:Hero race="Hum" /></h1><br/>

<h1>Orc<custom:Hero race="Orc" /></h1><br/>

<h1>Ud<custom:Hero race="Ud" /></h1><br/>

<h1>Ne<custom:Hero race="Ne" /></h1><br/>

<h1>Zerg<custom:Hero race="Zerg" /></h1>

</f:view>

</body>

</html>

        红色部分首先通过uri来找到唯一对应的tld文件,并定义前缀为custom。如果我们要使用自定义的组件,只需要写<custom:tag-name>就可以了。例如,这里是<custom:Hero>。同时,该组件的race属性因为声明过是required的,所以不能省略。到这里,整个例子完成。
默认分类 | 阅读 2158 次
文章评论,共0条
游客请输入验证码