- 浏览: 6130 次
- 性别:
- 来自: 珠海
文章分类
最新评论
1. 序言 2
2. 简单的Noncomposite Component 3
3. 能接受参数的Noncomposite Component 5
4. 能与页面交互的Noncomposite Component 6
5. Behavior和Renderer分离的Noncomposite Component 9
1. 序言
JSF2.0标准被JCP通过并正式发布已有一年多(2009年6月份通过的),其标准实现jsf-api-2.0.3.jar也一再更新版本,各种开源社区对应的版本也相继发布,如:IceFace、OpenFaces、PrimeFaces等,IceFace也发布了netbean和eclipse3.6的可视化插件,JSF2.0生机勃勃,呈现出一片繁荣景象。
Composite Component JSF2(复合组件)提供了Composite Component的创建方法,避免了通过Java代码生成html标记的繁琐,只需要基于现有的JSF tag进行组合即可。IceFace、OpenFaces、PrimeFaces提供了各种的炫酷UI Components,但JSF的开源社区都忙于商业支持,而很少对free的用户进行友好及时的支持。 <<The Complete Reference-Java Server Faces2.0>>一书提到如果有别人已经造好的车轮子,就没有必要自己造车轮。但是为了学习JSF的内部机制,还是很有必要编写传统的Non Composite Component,同时在我们很难获得开源社区的支持的现实下,自己制造车轮子,一方面为了自己用,另一方面也是为了更好的理解JSF和其他开源库,第三方的JSF库有问题自己能够解决,而不必依赖别人,Non Composite Component的基本结构如下图所示:
图1 1 Non Composite Component的基本结构
本文所有代码采用技术:eclipse3.6+jdk6+tomcat6,JSF选用标准实现Mojarra 2.0.3-b03。
本文的所有的源代码可以从http://dazen.sourceforge.net/下载。
本文从易到难,先后介绍4个Non Composite Component。
2. 简单的Noncomposite Component
学习新事物,我们自然想到Hello world,本文也不例外,我们从hello world开始,首先开发一个最为简单的输出hello world的Non Composite Component:HtmlHelloWorld。UI component包括两部分:
1、一个HtmlHelloWorld.java类文件,这个类提供组件的核心功能,包括在html中的展现信息和呈现方式等。
2、一个配置文件:helloworld-taglib.xml,即组件的Facelet tag library descriptor (TLD)。
在eclipse中创建dynamic web project,或者下载源代码后直接导入工程即可,工程名称为jsfdemo。
创建HtmlHelloWorld.java类文件,代码如下:
package com.dazen.components.component;
import java.io.IOException;
import javax.faces.component.FacesComponent;
import javax.faces.component.UIComponentBase;
import javax.faces.context.FacesContext;
import javax.faces.context.ResponseWriter;
@FacesComponent(value = "HtmlHelloWorld")
public class HtmlHelloWorld extends UIComponentBase {
@Override
public String getFamily() {
return null;
}
@Override
public void encodeAll(FacesContext context) throws IOException {
ResponseWriter writer = context.getResponseWriter();
writer.startElement("div", this);
writer.writeAttribute("style", "color : red", null);
writer.writeText("HelloWorld! today is: " + new java.util.Date(), null);
writer.endElement("div");
}
}
在代码中才采用注解的方式进行了组件注册:@FacesComponent(value = "HtmlHelloWorld"),否则需要在faces-config.xml中进行如下配置:
<component>
<component-type>HtmlHelloWorld</component-type>
<component-class>
com.dazen.components.component.HtmlHelloWorld
</component-class>
</component>
在WEB-INF目录下创建文件:Facelet tag library descriptor (TLD):helloworld.taglib.xml,文件内容如下:
<?xml version='1.0' encoding='UTF-8'?>
<facelet-taglib 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-facelettaglibrary_2_0.xsd"
version="2.0">
<namespace>http://dazen.com/example</namespace>
<tag>
<tag-name>helloworld</tag-name>
<component>
<component-type>HtmlHelloWorld</component-type>
</component>
</tag>
</facelet-taglib>
至此,第一个Non Composite Component开发完毕,下面写一个xhtml文件:component.xhtml来调用该组件:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:vt="http://dazen.com/example">
<h:head>
<title>A Simple JavaServer Faces 2.0 View</title>
</h:head>
<h:body>
<h:form>
<p><vt:helloworld /></p>
</h:form>
</h:body>
</html>
IE中显示效果:
图2 1 组件调用效果
3. 能接受参数的Noncomposite Component
一个组件一般要接受在调用时传递过来的参数。首先创建类文件:ParamHelloWorld.java,代码如下:
package com.dazen.components.component;
import java.io.IOException;
import javax.faces.component.FacesComponent;
import javax.faces.component.UIComponentBase;
import javax.faces.context.FacesContext;
import javax.faces.context.ResponseWriter;
@FacesComponent(value = "ParamHelloWorld")
public class ParamHelloWorld extends UIComponentBase {
@Override
public String getFamily() {
return null;
}
@Override
public void encodeAll(FacesContext context) throws IOException {
ResponseWriter writer = context.getResponseWriter();
writer.startElement("div", this);
writer.writeAttribute("style", "color : red", null);
String message = (String) this.getAttributes().get("hellomsg");
if (null == message) {
writer.writeText("HelloWorld! today is: " + new java.util.Date(),
null);
} else {
writer.writeText(message, null);
}
writer.endElement("div");
}
}
这个组件可以接受参数名为: hellomsg的参数。
然后在helloworld.taglib.xml中添加如下代码来注册该组件:
<tag>
<tag-name>paramhelloworld</tag-name>
<component>
<component-type>ParamHelloWorld</component-type>
</component>
</tag>
最后创建调用该组件的页面文件:param_component.xhtml,代码如下:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:vt="http://dazen.com/example">
<h:head>
<title>A Simple JavaServer Faces 2.0 View</title>
</h:head>
<h:body>
<h:form>
<vt:paramhelloworld hellomsg="Hello JSF! "/>
</h:form>
</h:body>
</html>
执行效果如下图所示:
图3 1 可传参数的组件
4. 能与页面交互的Noncomposite Component
首先创建类文件:InputHelloWorld.java,代码如下:
package com.dazen.components.component;
import java.io.IOException;
import java.util.Map;
import javax.faces.component.FacesComponent;
import javax.faces.component.UIInput;
import javax.faces.component.UINamingContainer;
import javax.faces.context.FacesContext;
import javax.faces.context.ResponseWriter;
@FacesComponent(value = "InputHelloWorld")
public class InputHelloWorld extends UIInput {
public InputHelloWorld() {
setRendererType(null); // this component renders itself
}
@Override
public void encodeEnd(FacesContext context) throws IOException {
String clientId = getClientId(context);
char sep = UINamingContainer.getSeparatorChar(context);
encodeInputField(context, clientId + sep + "inputfield");
encodeSubmitButton(context, clientId + sep + "submit");
encodeOutputField(context);
}
private void encodeInputField(FacesContext context, String clientId)
throws IOException {
// Render a standard HTML input field
ResponseWriter writer = context.getResponseWriter();
writer.startElement("input", this);
writer.writeAttribute("type", "text", null);
writer.writeAttribute("name", clientId, "dazen_Id");
Object value = getValue();
if (value != null) {
writer.writeAttribute("value", value.toString(), "value");
}
writer.writeAttribute("size", "6", null);
writer.endElement("input");
}
private void encodeSubmitButton(FacesContext context, String clientId)
throws IOException {
// render a submit button
ResponseWriter writer = context.getResponseWriter();
writer.startElement("input", this);
writer.writeAttribute("type", "Submit", null);
writer.writeAttribute("name", clientId, "dazen_Id");
writer.writeAttribute("value", "Click Me!", null);
writer.endElement("input");
}
private void encodeOutputField(FacesContext context) throws IOException {
ResponseWriter writer = context.getResponseWriter();
String hellomsg = (String) getAttributes().get("value");
writer.startElement("p", this);
writer.writeText("You entered: " + hellomsg, null);
writer.endElement("p");
}
@Override
public void decode(FacesContext context) {
Map requestMap = context.getExternalContext().getRequestParameterMap();
String clientId = getClientId(context);
char sep = UINamingContainer.getSeparatorChar(context);
String submitted_hello_msg = ((String) requestMap.get(clientId + sep
+ "inputfield"));
setSubmittedValue(submitted_hello_msg);
}
}
这个组件可以由用户输入信息并反馈给用户。 基本流程是,用户在页面上输入数据,点击按钮后,一般采用PostBack的方法将数据传递到JSF的 Serverlet,在后台的Renderer的decode方法内部通过 FacesContext.getExternalContext().getRequestParameterMap()获取Map对象,然后通过 key去查找用户的输入数据。
然后在helloworld.taglib.xml中添加如下代码来注册该组件:
<tag>
<tag-name>inputhelloworld</tag-name>
<component>
<component-type>InputHelloWorld</component-type>
</component>
</tag>
最后创建调用该组件的页面文件:input_component.xhtml,代码如下:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:vt="http://dazen.com/example">
<h:head>
<title>A Simple JavaServer Faces 2.0 View</title>
</h:head>
<h:body>
<h:form>
<vt:inputhelloworld/>
</h:form>
</h:body>
</html>
执行效果如下图所示:
图4 1 可交互的组件
5. Behavior和Renderer分离的Noncomposite Component
通常一个UI Component包含了两个部分:Behavior和Renderer.两者一般都分别实现,UIComponent类用来实现Behavior,比如处理事件,通过EL绑定属性等等。专门实现一个Renderer类来负责Encoding和Decoding。Encoding指的是生成可以在客户端显示的标记语言,比如html等,Decoding用来将客户端传来的请求(通常以某种标记语言风格)转换成Java变量。
首先创建Renderer类文件:HtmlInputRenderer.java,代码如下:
package com.dazen.components.renderer;
import java.io.IOException;
import java.util.Map;
import javax.faces.component.UIComponent;
import javax.faces.component.UINamingContainer;
import javax.faces.context.FacesContext;
import javax.faces.context.ResponseWriter;
import javax.faces.render.FacesRenderer;
import javax.faces.render.Renderer;
import com.dazen.components.component.HtmlInput;
@FacesRenderer(componentFamily="javax.faces.Input",
rendererType="HtmlInputRenderer")
public class HtmlInputRenderer extends Renderer {
public void decode(FacesContext context, UIComponent component) {
Map requestMap = context.getExternalContext().getRequestParameterMap();
String clientId = component.getClientId(context);
char sep = UINamingContainer.getSeparatorChar(context);
String symbol = ((String) requestMap.get(clientId + sep + "inputfield"));
HtmlInput myComponent = (HtmlInput) component;
myComponent.setSubmittedValue(symbol);
}
@Override
public void encodeEnd(FacesContext context, UIComponent component)
throws IOException {
String clientId = component.getClientId(context);
char sep = UINamingContainer.getSeparatorChar(context);
encodeInputField(context, clientId + sep + "inputfield", component);
encodeSubmitButton(context, clientId + sep + "submit", component);
encodeOutputField(context, component);
}
private void encodeInputField(FacesContext context, String clientId,
UIComponent component) throws IOException {
ResponseWriter writer = context.getResponseWriter();
writer.startElement("input", component);
writer.writeAttribute("type", "text", null);
writer.writeAttribute("name", clientId, "dazenId");
HtmlInput myComponent = (HtmlInput) component;
String value = (String) myComponent.getSubmittedValue();
if (value != null) {
writer.writeAttribute("value", value, "value");
}
writer.writeAttribute("size", "6", null);
writer.endElement("input");
}
private void encodeSubmitButton(FacesContext context, String clientId,
UIComponent component) throws IOException {
ResponseWriter writer = context.getResponseWriter();
writer.startElement("input", component);
writer.writeAttribute("type", "Submit", null);
writer.writeAttribute("name", clientId, "dazenId");
writer.writeAttribute("value", "Click Me!", null);
writer.endElement("input");
}
private void encodeOutputField(FacesContext context, UIComponent component)
throws IOException {
ResponseWriter writer = context.getResponseWriter();
String hellomsg = (String) component.getAttributes().get("value");
writer.startElement("p", component);
writer.writeText("You entered: " + hellomsg, null);
writer.endElement("p");
}
}
然后创建Behavior类文件:HtmlInput.java,
package com.dazen.components.component;
import javax.faces.component.FacesComponent;
import javax.faces.component.UIInput;
@FacesComponent(value = "HtmlInput")
public class HtmlInput extends UIInput {
}
因为HtmlInput类继承了UIInput类,所以自然拥有了getFamily,get/setSubmittedValue等方法的实现。
然后在helloworld.taglib.xml中添加如下代码来注册该组件:
<tag>
<tag-name>htmlinput</tag-name>
<component>
<component-type>HtmlInput</component-type>
<renderer-type>HtmlInputRenderer</renderer-type>
</component>
</tag>
最后创建调用该组件的页面文件:renderer_component.xhtml,代码如下:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:vt="http://dazen.com/example">
<h:head>
<title>A Simple JavaServer Faces 2.0 View</title>
</h:head>
<h:body>
<h:form>
<vt:htmlinput/>
</h:form>
</h:body>
</html>
执行效果如下图所示:
图5 1 Behavior和Renderer分离的组件
通过Behavior和Renderer的分离可以开发出能自动适应不同客户端设备的组件,到达如下效果:
图5 2 适应不同设备的组件
更多的知识请查阅《The Complete Reference-Java Server Faces2.0.pdf》和《Core JavaServer Faces 3rd Edition.pdf》等资料。
如对本文有任何问题,可以联系作者:
Email:dazen_erp@163.com;
2. 简单的Noncomposite Component 3
3. 能接受参数的Noncomposite Component 5
4. 能与页面交互的Noncomposite Component 6
5. Behavior和Renderer分离的Noncomposite Component 9
1. 序言
JSF2.0标准被JCP通过并正式发布已有一年多(2009年6月份通过的),其标准实现jsf-api-2.0.3.jar也一再更新版本,各种开源社区对应的版本也相继发布,如:IceFace、OpenFaces、PrimeFaces等,IceFace也发布了netbean和eclipse3.6的可视化插件,JSF2.0生机勃勃,呈现出一片繁荣景象。
Composite Component JSF2(复合组件)提供了Composite Component的创建方法,避免了通过Java代码生成html标记的繁琐,只需要基于现有的JSF tag进行组合即可。IceFace、OpenFaces、PrimeFaces提供了各种的炫酷UI Components,但JSF的开源社区都忙于商业支持,而很少对free的用户进行友好及时的支持。 <<The Complete Reference-Java Server Faces2.0>>一书提到如果有别人已经造好的车轮子,就没有必要自己造车轮。但是为了学习JSF的内部机制,还是很有必要编写传统的Non Composite Component,同时在我们很难获得开源社区的支持的现实下,自己制造车轮子,一方面为了自己用,另一方面也是为了更好的理解JSF和其他开源库,第三方的JSF库有问题自己能够解决,而不必依赖别人,Non Composite Component的基本结构如下图所示:
图1 1 Non Composite Component的基本结构
本文所有代码采用技术:eclipse3.6+jdk6+tomcat6,JSF选用标准实现Mojarra 2.0.3-b03。
本文的所有的源代码可以从http://dazen.sourceforge.net/下载。
本文从易到难,先后介绍4个Non Composite Component。
2. 简单的Noncomposite Component
学习新事物,我们自然想到Hello world,本文也不例外,我们从hello world开始,首先开发一个最为简单的输出hello world的Non Composite Component:HtmlHelloWorld。UI component包括两部分:
1、一个HtmlHelloWorld.java类文件,这个类提供组件的核心功能,包括在html中的展现信息和呈现方式等。
2、一个配置文件:helloworld-taglib.xml,即组件的Facelet tag library descriptor (TLD)。
在eclipse中创建dynamic web project,或者下载源代码后直接导入工程即可,工程名称为jsfdemo。
创建HtmlHelloWorld.java类文件,代码如下:
package com.dazen.components.component;
import java.io.IOException;
import javax.faces.component.FacesComponent;
import javax.faces.component.UIComponentBase;
import javax.faces.context.FacesContext;
import javax.faces.context.ResponseWriter;
@FacesComponent(value = "HtmlHelloWorld")
public class HtmlHelloWorld extends UIComponentBase {
@Override
public String getFamily() {
return null;
}
@Override
public void encodeAll(FacesContext context) throws IOException {
ResponseWriter writer = context.getResponseWriter();
writer.startElement("div", this);
writer.writeAttribute("style", "color : red", null);
writer.writeText("HelloWorld! today is: " + new java.util.Date(), null);
writer.endElement("div");
}
}
在代码中才采用注解的方式进行了组件注册:@FacesComponent(value = "HtmlHelloWorld"),否则需要在faces-config.xml中进行如下配置:
<component>
<component-type>HtmlHelloWorld</component-type>
<component-class>
com.dazen.components.component.HtmlHelloWorld
</component-class>
</component>
在WEB-INF目录下创建文件:Facelet tag library descriptor (TLD):helloworld.taglib.xml,文件内容如下:
<?xml version='1.0' encoding='UTF-8'?>
<facelet-taglib 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-facelettaglibrary_2_0.xsd"
version="2.0">
<namespace>http://dazen.com/example</namespace>
<tag>
<tag-name>helloworld</tag-name>
<component>
<component-type>HtmlHelloWorld</component-type>
</component>
</tag>
</facelet-taglib>
至此,第一个Non Composite Component开发完毕,下面写一个xhtml文件:component.xhtml来调用该组件:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:vt="http://dazen.com/example">
<h:head>
<title>A Simple JavaServer Faces 2.0 View</title>
</h:head>
<h:body>
<h:form>
<p><vt:helloworld /></p>
</h:form>
</h:body>
</html>
IE中显示效果:
图2 1 组件调用效果
3. 能接受参数的Noncomposite Component
一个组件一般要接受在调用时传递过来的参数。首先创建类文件:ParamHelloWorld.java,代码如下:
package com.dazen.components.component;
import java.io.IOException;
import javax.faces.component.FacesComponent;
import javax.faces.component.UIComponentBase;
import javax.faces.context.FacesContext;
import javax.faces.context.ResponseWriter;
@FacesComponent(value = "ParamHelloWorld")
public class ParamHelloWorld extends UIComponentBase {
@Override
public String getFamily() {
return null;
}
@Override
public void encodeAll(FacesContext context) throws IOException {
ResponseWriter writer = context.getResponseWriter();
writer.startElement("div", this);
writer.writeAttribute("style", "color : red", null);
String message = (String) this.getAttributes().get("hellomsg");
if (null == message) {
writer.writeText("HelloWorld! today is: " + new java.util.Date(),
null);
} else {
writer.writeText(message, null);
}
writer.endElement("div");
}
}
这个组件可以接受参数名为: hellomsg的参数。
然后在helloworld.taglib.xml中添加如下代码来注册该组件:
<tag>
<tag-name>paramhelloworld</tag-name>
<component>
<component-type>ParamHelloWorld</component-type>
</component>
</tag>
最后创建调用该组件的页面文件:param_component.xhtml,代码如下:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:vt="http://dazen.com/example">
<h:head>
<title>A Simple JavaServer Faces 2.0 View</title>
</h:head>
<h:body>
<h:form>
<vt:paramhelloworld hellomsg="Hello JSF! "/>
</h:form>
</h:body>
</html>
执行效果如下图所示:
图3 1 可传参数的组件
4. 能与页面交互的Noncomposite Component
首先创建类文件:InputHelloWorld.java,代码如下:
package com.dazen.components.component;
import java.io.IOException;
import java.util.Map;
import javax.faces.component.FacesComponent;
import javax.faces.component.UIInput;
import javax.faces.component.UINamingContainer;
import javax.faces.context.FacesContext;
import javax.faces.context.ResponseWriter;
@FacesComponent(value = "InputHelloWorld")
public class InputHelloWorld extends UIInput {
public InputHelloWorld() {
setRendererType(null); // this component renders itself
}
@Override
public void encodeEnd(FacesContext context) throws IOException {
String clientId = getClientId(context);
char sep = UINamingContainer.getSeparatorChar(context);
encodeInputField(context, clientId + sep + "inputfield");
encodeSubmitButton(context, clientId + sep + "submit");
encodeOutputField(context);
}
private void encodeInputField(FacesContext context, String clientId)
throws IOException {
// Render a standard HTML input field
ResponseWriter writer = context.getResponseWriter();
writer.startElement("input", this);
writer.writeAttribute("type", "text", null);
writer.writeAttribute("name", clientId, "dazen_Id");
Object value = getValue();
if (value != null) {
writer.writeAttribute("value", value.toString(), "value");
}
writer.writeAttribute("size", "6", null);
writer.endElement("input");
}
private void encodeSubmitButton(FacesContext context, String clientId)
throws IOException {
// render a submit button
ResponseWriter writer = context.getResponseWriter();
writer.startElement("input", this);
writer.writeAttribute("type", "Submit", null);
writer.writeAttribute("name", clientId, "dazen_Id");
writer.writeAttribute("value", "Click Me!", null);
writer.endElement("input");
}
private void encodeOutputField(FacesContext context) throws IOException {
ResponseWriter writer = context.getResponseWriter();
String hellomsg = (String) getAttributes().get("value");
writer.startElement("p", this);
writer.writeText("You entered: " + hellomsg, null);
writer.endElement("p");
}
@Override
public void decode(FacesContext context) {
Map requestMap = context.getExternalContext().getRequestParameterMap();
String clientId = getClientId(context);
char sep = UINamingContainer.getSeparatorChar(context);
String submitted_hello_msg = ((String) requestMap.get(clientId + sep
+ "inputfield"));
setSubmittedValue(submitted_hello_msg);
}
}
这个组件可以由用户输入信息并反馈给用户。 基本流程是,用户在页面上输入数据,点击按钮后,一般采用PostBack的方法将数据传递到JSF的 Serverlet,在后台的Renderer的decode方法内部通过 FacesContext.getExternalContext().getRequestParameterMap()获取Map对象,然后通过 key去查找用户的输入数据。
然后在helloworld.taglib.xml中添加如下代码来注册该组件:
<tag>
<tag-name>inputhelloworld</tag-name>
<component>
<component-type>InputHelloWorld</component-type>
</component>
</tag>
最后创建调用该组件的页面文件:input_component.xhtml,代码如下:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:vt="http://dazen.com/example">
<h:head>
<title>A Simple JavaServer Faces 2.0 View</title>
</h:head>
<h:body>
<h:form>
<vt:inputhelloworld/>
</h:form>
</h:body>
</html>
执行效果如下图所示:
图4 1 可交互的组件
5. Behavior和Renderer分离的Noncomposite Component
通常一个UI Component包含了两个部分:Behavior和Renderer.两者一般都分别实现,UIComponent类用来实现Behavior,比如处理事件,通过EL绑定属性等等。专门实现一个Renderer类来负责Encoding和Decoding。Encoding指的是生成可以在客户端显示的标记语言,比如html等,Decoding用来将客户端传来的请求(通常以某种标记语言风格)转换成Java变量。
首先创建Renderer类文件:HtmlInputRenderer.java,代码如下:
package com.dazen.components.renderer;
import java.io.IOException;
import java.util.Map;
import javax.faces.component.UIComponent;
import javax.faces.component.UINamingContainer;
import javax.faces.context.FacesContext;
import javax.faces.context.ResponseWriter;
import javax.faces.render.FacesRenderer;
import javax.faces.render.Renderer;
import com.dazen.components.component.HtmlInput;
@FacesRenderer(componentFamily="javax.faces.Input",
rendererType="HtmlInputRenderer")
public class HtmlInputRenderer extends Renderer {
public void decode(FacesContext context, UIComponent component) {
Map requestMap = context.getExternalContext().getRequestParameterMap();
String clientId = component.getClientId(context);
char sep = UINamingContainer.getSeparatorChar(context);
String symbol = ((String) requestMap.get(clientId + sep + "inputfield"));
HtmlInput myComponent = (HtmlInput) component;
myComponent.setSubmittedValue(symbol);
}
@Override
public void encodeEnd(FacesContext context, UIComponent component)
throws IOException {
String clientId = component.getClientId(context);
char sep = UINamingContainer.getSeparatorChar(context);
encodeInputField(context, clientId + sep + "inputfield", component);
encodeSubmitButton(context, clientId + sep + "submit", component);
encodeOutputField(context, component);
}
private void encodeInputField(FacesContext context, String clientId,
UIComponent component) throws IOException {
ResponseWriter writer = context.getResponseWriter();
writer.startElement("input", component);
writer.writeAttribute("type", "text", null);
writer.writeAttribute("name", clientId, "dazenId");
HtmlInput myComponent = (HtmlInput) component;
String value = (String) myComponent.getSubmittedValue();
if (value != null) {
writer.writeAttribute("value", value, "value");
}
writer.writeAttribute("size", "6", null);
writer.endElement("input");
}
private void encodeSubmitButton(FacesContext context, String clientId,
UIComponent component) throws IOException {
ResponseWriter writer = context.getResponseWriter();
writer.startElement("input", component);
writer.writeAttribute("type", "Submit", null);
writer.writeAttribute("name", clientId, "dazenId");
writer.writeAttribute("value", "Click Me!", null);
writer.endElement("input");
}
private void encodeOutputField(FacesContext context, UIComponent component)
throws IOException {
ResponseWriter writer = context.getResponseWriter();
String hellomsg = (String) component.getAttributes().get("value");
writer.startElement("p", component);
writer.writeText("You entered: " + hellomsg, null);
writer.endElement("p");
}
}
然后创建Behavior类文件:HtmlInput.java,
package com.dazen.components.component;
import javax.faces.component.FacesComponent;
import javax.faces.component.UIInput;
@FacesComponent(value = "HtmlInput")
public class HtmlInput extends UIInput {
}
因为HtmlInput类继承了UIInput类,所以自然拥有了getFamily,get/setSubmittedValue等方法的实现。
然后在helloworld.taglib.xml中添加如下代码来注册该组件:
<tag>
<tag-name>htmlinput</tag-name>
<component>
<component-type>HtmlInput</component-type>
<renderer-type>HtmlInputRenderer</renderer-type>
</component>
</tag>
最后创建调用该组件的页面文件:renderer_component.xhtml,代码如下:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:vt="http://dazen.com/example">
<h:head>
<title>A Simple JavaServer Faces 2.0 View</title>
</h:head>
<h:body>
<h:form>
<vt:htmlinput/>
</h:form>
</h:body>
</html>
执行效果如下图所示:
图5 1 Behavior和Renderer分离的组件
通过Behavior和Renderer的分离可以开发出能自动适应不同客户端设备的组件,到达如下效果:
图5 2 适应不同设备的组件
更多的知识请查阅《The Complete Reference-Java Server Faces2.0.pdf》和《Core JavaServer Faces 3rd Edition.pdf》等资料。
如对本文有任何问题,可以联系作者:
Email:dazen_erp@163.com;
- JSF2自定义组件手记.pdf (125.5 KB)
- 下载次数: 50
相关推荐
这个"JSF2自定义组件编程系列第五部分 源代码"着重讲解了如何将复合组件(Composite Component)打包到JAR文件中,并通过Maven3、JSF2、Ubuntu操作系统、GlassFish v3.0.1应用服务器以及Emacs JDEE集成开发环境进行...
2. **创建自定义组件**:通常涉及以下步骤: - 定义Java类:继承自UIComponent或其子类,并添加必要的属性和方法。 - 创建FacesComponent注解:用于声明组件的元数据,如标签名称、组件类型等。 - 实现渲染逻辑:...
【JSF创建自定义组件】 JSF(JavaServer Faces)是一种用于构建Web应用程序的MVC框架,它允许开发者创建可重用的UI组件。在JSF中,自定义组件允许开发人员扩展框架的功能,以满足特定项目的需求。下面将详细解释...
### JSF自定义组件知识点详解 #### 一、JSF生命周期与组件概述 **1.1 JSF生命周期** JavaServer Faces (JSF) 是一种基于Java的Web应用框架,主要用于构建用户界面。为了更好地理解如何自定义JSF组件,首先需要...
在JSF 2.0版本中,它引入了许多改进和新特性,其中包括对自定义组件的强大支持。自定义组件允许开发人员根据特定需求创建自己的UI组件,这些组件可以扩展和定制,以满足应用程序的独特功能。 自定义组件的核心概念...
【JSF自定义组件实现详解】 在JavaServer Faces (JSF)框架中,自定义组件允许开发者根据项目需求创建具有特定功能的UI元素。本文将引导你逐步了解如何在JSF中实现一个自定义组件,从基础开始,一步步构建一个简单的...
在JavaServer Faces (JSF) 2.0中,自定义组件是开发人员扩展框架功能的关键方式。通过创建自定义组件,你可以构建符合特定需求的用户界面元素,这些元素可以复用并集成到多个JSF应用程序中。本教程将深入探讨如何在...
### JSF自定义组件知识点详解 #### 一、JSF生命周期与组件概述 **1.1 JSF生命周期** JavaServer Faces (JSF) 是一种基于Java的Web应用框架,主要用于构建用户界面。为了更好地理解如何自定义JSF组件,首先需要...
本教程将深入探讨如何在JSF环境中创建自定义组件。 ### 1. 自定义组件概述 在JSF中,组件是UI的基本构建块,可以是简单的HTML元素,如按钮或输入框,也可以是复杂的组件,如表格或下拉菜单。自定义组件允许开发者...
**JSF自定义组件开发详解** JavaServer Faces (JSF) 是一个用于构建Web应用程序的Java框架,它提供了一种模型-视图-控制器(MVC)架构来简化开发过程。在JSF中,自定义组件是扩展其功能的关键部分,允许开发者根据...
**JSF分页组件2详解** JavaServer Faces (JSF) 是Java平台上的一个用于构建Web应用程序的MVC(Model-View-Controller)框架。在处理大量数据时,分页功能是必不可少的,它能够帮助用户更有效地浏览和管理信息。在...
jsf官方实现默认是不支持multipart/form-data类型的表单的,为了使jsf能够解析multipart/form-data表单的数据,我参考了myfaces1.1的方式,然后按照commons-fileupload1.2重构了部分代码(myfaces1.1使用的是commons...
JSF加入Ajax功能的下拉框自定义组件,含源代码。
在JavaServer Faces (JSF)框架中,自定义组件是扩展其功能的关键手段,它允许开发者根据特定需求创建具有独特特性的UI组件。本章将深入探讨如何自定义JSF组件,并通过实例讲解开发过程。 首先,JSF组件模型借鉴了...
本实例将带你深入理解如何在JSF中创建自定义的转换器和验证器。 首先,我们来了解**转换器(Converter)**。在JSF中,转换器用于将用户界面(UI)组件的值转换为模型对象,反之亦然。这在处理不同数据类型时特别...
自定义分页呈现器的核心思想在于实现JSF中的自定义渲染器(Renderer),该渲染器负责绘制特定UI组件的表现形式。通过这种方式,可以实现显示逻辑与业务逻辑的分离,并提高代码的复用性和可维护性。 #### 实现步骤 ...
JavaScript Faces (JSF) 是Java平台上用于构建用户界面的一个组件模型框架,主要应用于Web应用程序的开发。在JSF 1.2版本中,为了确保数据输入的正确性和一致性,开发者可以自定义验证器来实现特定的数据验证逻辑。...
JSF(JavaServer Faces)是Java平台上用于...通过学习和理解"JSF1.2日历组件",开发者不仅能掌握JSF自定义组件的开发技术,还能深入理解JSF的MVC架构、组件生命周期和事件处理机制,这对提升Web开发技能非常有帮助。
JSF允许开发者创建自定义组件,以满足特定需求。这通常涉及到创建一个实现`UIComponent`子类的Java类,定义组件的行为和外观。同时,需要一个Facelets标签库描述文件(taglib.xml)来注册组件,以及一个Facelets模板...