首先编写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的,所以不能省略。到这里,整个例子完成。