JSF2.0实战 - 5、Button

最终界面预览

JSF2.0实战 - 5、Button_第1张图片


代码目录结构

JSF2.0实战 - 5、Button_第2张图片

上面的dojo-1.9.2.jar是dojo js库,自己打包的,建立一个META-INF/resources目录,放置dojo库,打包成jar文件

JSF2.0实战 - 5、Button_第3张图片

我选dojo做JSF组件的原因:dojo是一整套完整的javascript ui库,界面美观省去了找美工的麻烦,而且没有许可证限制,随便用。缺点:庞大、复杂、难学。但只要把dojo封装成JSF组件,我相信就可以掩盖90%以上的复杂度,供业务开发人员使用是没问题的。


Button.java

package org.dojo4j.component.form;

import javax.faces.component.FacesComponent;
import javax.faces.component.html.HtmlCommandButton;

@FacesComponent(Button.COMPONENT_TYPE)
//直接继承JSF基础组件HtmlCommandButton,这样可以直接从父类继承已实现的ActionSource2、ClientBehaviorHolder等接口
//ActionSource2是实现actionListener功能的接口,ClientBehaviorHolder是实现ajax特性的接口,自己实现太麻烦,直接从父类继承
public class Button extends HtmlCommandButton {

	public static final String COMPONENT_FAMILY = "dojo4j.form";
	
	public static final String COMPONENT_TYPE = "dojo4j.form.button";

	@Override
	public String getFamily() {
		return COMPONENT_FAMILY;
	}
}

ButtonRenderer.java

package org.dojo4j.component.form;

import java.io.IOException;
import java.util.Collection;
import java.util.List;
import java.util.Map;

import javax.faces.application.ResourceDependencies;
import javax.faces.application.ResourceDependency;
import javax.faces.component.UICommand;
import javax.faces.component.UIComponent;
import javax.faces.component.behavior.ClientBehavior;
import javax.faces.component.behavior.ClientBehaviorContext;
import javax.faces.context.FacesContext;
import javax.faces.context.ResponseWriter;
import javax.faces.render.FacesRenderer;
import javax.servlet.http.HttpServletRequest;

import com.sun.faces.renderkit.Attribute;
import com.sun.faces.renderkit.AttributeManager;
import com.sun.faces.renderkit.RenderKitUtils;

@FacesRenderer(componentFamily = Button.COMPONENT_FAMILY, rendererType = Button.COMPONENT_TYPE)
// 直接继承com.sun.faces.renderkit.html_basic.ButtonRenderer,修改部分渲染代码
@ResourceDependencies({
	//引入所需的css样式
	@ResourceDependency(library = "dojo/resources", name = "dojo.css", target = "head"), 
	//默认采用claro皮肤,以后再采取其他方式换肤
	@ResourceDependency(library = "dijit/themes/claro", name = "claro.css", target = "head")})
public class ButtonRenderer extends com.sun.faces.renderkit.html_basic.ButtonRenderer {

	@Override
	public void encodeBegin(FacesContext context, UIComponent component) throws IOException {
		rendererParamsNotNull(context, component);

		if (!shouldEncode(component)) {
			return;
		}

		String type = getButtonType(component);

		ResponseWriter writer = context.getResponseWriter();
		assert (writer != null);

		String label = "";
		Object value = ((UICommand) component).getValue();
		if (value != null) {
			label = value.toString();
		}

		Collection<ClientBehaviorContext.Parameter> params = getBehaviorParameters(component);
		if (!params.isEmpty() && (type.equals("submit") || type.equals("button"))) {
			RenderKitUtils.renderJsfJs(context);
		}

		/* 从此处理开始修改 */
		
		//引入dojo.js,因为要加入data-dojo-config属性,因此无法用@ResourceDependency方式,只能输入script标签,以后改用其他方式
		writer.startElement("script", component);
		HttpServletRequest request = (HttpServletRequest) context.getExternalContext().getRequest();
		writer.writeAttribute("src", request.getContextPath() + context.getExternalContext().getRequestServletPath()
				+ "/javax.faces.resource/dojo/dojo.js", null);
		writer.writeAttribute("data-dojo-config", "async: true, parseOnLoad: true", null);
		writer.endElement("script");
		
		//引入dijit/form/Button,略显啰嗦,以后改用其他方式
		writer.startElement("script", component);
		writer.write("require([ \"dojo/parser\", \"dijit/form/Button\" ]);");
		writer.endElement("script");
		
		writer.startElement("input", component);
		writeIdAttributeIfNecessary(context, writer, component);
		String clientId = component.getClientId(context);
		writer.writeAttribute("type", type, "type");
		writer.writeAttribute("name", clientId, "clientId");
		writer.writeAttribute("value", label, "value");
		
		//加入id label data-dojo-id data-dojo-type属性
		writer.writeAttribute("id", clientId, null);
		writer.writeAttribute("label", label, null);
		writer.writeAttribute("data-dojo-id", clientId, null);
		writer.writeAttribute("data-dojo-type", "dijit/form/Button", null);
		/* 修改结束 */

		RenderKitUtils.renderPassThruAttributes(context, writer, component, ATTRIBUTES,
				getNonOnClickBehaviors(component));

		RenderKitUtils.renderXHTMLStyleBooleanAttributes(writer, component);

		String styleClass = (String) component.getAttributes().get("styleClass");
		if (styleClass != null && styleClass.length() > 0) {
			writer.writeAttribute("class", styleClass, "styleClass");
		}

		RenderKitUtils.renderOnclick(context, component, params, null, false);

		if (component.getChildCount() == 0) {
			writer.endElement("input");
		}
	}

	// 以下是从com.sun.faces.renderkit.html_basic.ButtonRenderer复制的private代码
	private static final Attribute[] ATTRIBUTES = AttributeManager.getAttributes(AttributeManager.Key.COMMANDBUTTON);

	private static String getButtonType(UIComponent component) {
		String type = (String) component.getAttributes().get("type");
		if (type == null || (!"reset".equals(type) && !"submit".equals(type) && !"button".equals(type))) {
			type = "submit";
			component.getAttributes().put("type", type);
		}
		return type;
	}

	private static Map<String, List<ClientBehavior>> getNonOnClickBehaviors(UIComponent component) {
		return getPassThruBehaviors(component, "click", "action");
	}
}

faces-config.xml

<?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_2_1.xsd"
	version="2.1">
	<component>
		<component-type>dojo4j.form.button</component-type>
		<component-class>org.dojo4j.component.form.Button</component-class>
	</component>
</faces-config>

dojo4j.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"
	version="2.0" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-facelettaglibrary_2_0.xsd">
	<namespace>http://org.dojo4j</namespace>
	<tag>
		<tag-name>button</tag-name>
		<component>
            <component-type>dojo4j.form.button</component-type>
            <renderer-type>dojo4j.form.button</renderer-type>        
        </component>
	</tag>
</facelet-taglib>

buttonTest.xhtml

<!DOCTYPE HTML>
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:h="http://java.sun.com/jsf/html" xmlns:f="http://java.sun.com/jsf/core"
	xmlns:d4j="http://org.dojo4j">
<h:head>
	<meta charset="utf-8" />
	<title>Button Test</title>
</h:head>
<body class="claro"><!-- 先用claro样式,以后换其他方式换肤 -->
	<h:form id="form1" prependId="false"><!-- prependId去掉JSF自动生成的ID前缀,如j_idt1,j_idt2... -->
		<d4j:button value="Click Me" actionListener="#{buttonTest.click}" >
			<f:ajax execute="@form" render="text" />
		</d4j:button>
		<br/>
		<h:outputText id="text" binding="#{buttonTest.text}"/>
	</h:form>
</body>
</html>

ButtonTest.java

package test;

import javax.faces.bean.ManagedBean;
import javax.faces.component.html.HtmlOutputText;

@ManagedBean
public class ButtonTest {

	private HtmlOutputText text;
	
	public void click() {
		this.text.setValue("Button Test OK!");
	}

	public HtmlOutputText getText() {
		return text;
	}

	public void setText(HtmlOutputText text) {
		this.text = text;
	}
	
}

url:http://localhost:8080/dojo4j/faces/test/buttonTest.xhtml

JSF2.0实战 - 5、Button_第4张图片

生成的html源代码

<!DOCTYPE HTML>
<html xmlns="http://www.w3.org/1999/xhtml">
<head id="j_idt2">
<meta charset="utf-8" />
<title>Button Test</title>
<link type="text/css" rel="stylesheet" href="/dojo4j/faces/javax.faces.resource/dojo.css?ln=dojo/resources" />
<link type="text/css" rel="stylesheet" href="/dojo4j/faces/javax.faces.resource/claro.css?ln=dijit/themes/claro" />
<script type="text/javascript" src="/dojo4j/faces/javax.faces.resource/jsf.js?ln=javax.faces"></script>
</head>
<body class="claro">
	<form id="form1" name="form1" method="post" action="/dojo4j/faces/test/buttonTest.xhtml" enctype="application/x-www-form-urlencoded">
		<input type="hidden" name="form1" value="form1" />
		<script src="/dojo4j/faces/javax.faces.resource/dojo/dojo.js" data-dojo-config="async: true, parseOnLoad: true"></script>
		<script>
			require([ "dojo/parser", "dijit/form/Button" ]);
		</script>
		<input id="j_idt5" type="submit" name="j_idt5" value="Click Me" id="j_idt5" label="Click Me" data-dojo-id="j_idt5" data-dojo-type="dijit/form/Button"
			onclick="mojarra.ab(this,event,'action','@form','text');return false" /> <br />
		<span id="text"></span><input type="hidden" name="javax.faces.ViewState" id="j_id1:javax.faces.ViewState:0" value="8461977939671373327:-4614509433011281003"
			autocomplete="off" />
	</form>
</body>
</html>

下载示例代码

你可能感兴趣的:(框架,前端,JSF,dojo,JSF2.0)