日韩黑丝制服一区视频播放|日韩欧美人妻丝袜视频在线观看|九九影院一级蜜桃|亚洲中文在线导航|青草草视频在线观看|婷婷五月色伊人网站|日本一区二区在线|国产AV一二三四区毛片|正在播放久草视频|亚洲色图精品一区

分享

自定義開發(fā)具有Ajax功能的JSF組件

 chanvy 2009-01-08
自定義開發(fā)具有Ajax功能的JSF組件

 

下載源代碼


〖 作者:詩特林 〗〖 大?。?0k 〗〖 發(fā)布日期:2007-12-24 〗〖 瀏覽:0 〗

  使用過VB的開發(fā)人員,對組件應該是了如指掌的了,感覺使用起來非常的方面且簡單。

   同樣的,
JSF 擁有一個與 AWT GUI 組件模型類似的組件模型??梢杂?/span> JSF 創(chuàng)建可重用組件。但不幸的是,存在一個誤解:用 JSF 創(chuàng)建組件很困難。不要相信這些從未試過它的人們的 FUD!開發(fā) JSF 組件并不困難。由于不用一遍又一遍重復相同的代碼,可以節(jié)約時間。一旦創(chuàng)建了組件,就可以容易地把組件拖到任何 JSP、甚至任何 JSF 表單中,如果正在處理的站點有 250 個頁面,這就很重要了。JSF 的大多數(shù)功能來自基類。因為所有的繁重工作都由 API 和基類完成,所以 JSF 把組件創(chuàng)建變得很容易。

JSF 組件由兩部分構(gòu)成:組件和渲染器。JSF組件類定義UI組件的狀態(tài)和行為;渲染器定義如何從請求讀取組件、如何顯示組件——通常通過HTML渲染。渲染器把組件的值轉(zhuǎn)換成適當?shù)臉擞?。事件排隊和性能驗證發(fā)生在組件內(nèi)部。

  這里采用自定義開發(fā)具有Ajax功能的JSF組件為例,進行JSF組件開發(fā)的講解。

下面是我要采取的步驟:

定義監(jiān)聽器

         創(chuàng)建一個類,擴展 PhaseListener

擴展 UIComponent

1        創(chuàng)建一個類,擴展 UIComponent

2         保存組件狀態(tài)

3         faces-config.xml 登記組件

定義渲染器或者內(nèi)聯(lián)地實現(xiàn)它

1         覆蓋 encode

2         覆蓋 decode

3         faces-config.xml 登記渲染器

創(chuàng)建定制標記,繼承 UIComponentTag

         返回渲染器類型

         返回組件類型

         設置可能使用 JSF 表達式的屬性

本文中所用到的lib如下圖所示:



一、定義監(jiān)聽器

com.sterning.jsf.ajax. AjaxListener類:

package com.sterning.jsf.ajax;

import javax.faces.component.UIComponent;
import javax.faces.component.UIViewRoot;
import javax.faces.context.FacesContext;
import javax.faces.event.PhaseEvent;
import javax.faces.event.PhaseId;
import javax.faces.event.PhaseListener;
import javax.servlet.http.HttpServletRequest;

import org.apache.commons.logging.*;

public class AjaxListener implements PhaseListener {
    
private static final transient Log log = LogFactory.getLog(com.sterning.jsf.ajax.AjaxListener.class);
    
// 下面的常量定義了請求的參數(shù),用以決定是否為Ajax組件的請求
    private static final String AJAX_PARAM_KEY = "com.sterning.jsf.ajax.AJAX_REQUEST";
    
private static final String AJAX_CLIENT_ID_KEY = "com.sterning.jsf.ajax.AJAX_CLIENT_ID";
        
    
public AjaxListener() {
    }


    
/**
     * 處理請求,從請求中獲得組件,處理后轉(zhuǎn)給response
     
*/

    
public void afterPhase(PhaseEvent event) {
        
if (log.isInfoEnabled()) { log.info("BEGIN afterPhase()"); }
        FacesContext context 
= event.getFacesContext().getCurrentInstance();        
        
        HttpServletRequest request 
= (HttpServletRequest)context.getExternalContext().getRequest();
        String ajaxParam 
= request.getParameter(AJAX_PARAM_KEY);
        
        
// 檢查Ajax參數(shù)
        if (ajaxParam != null && ajaxParam.equals("true")){
            
if (log.isInfoEnabled()) { log.info("This is an ajax request."); }
            context.responseComplete(); 
            
            
//取得Ajax組件ID
            String componentId = request.getParameter(AJAX_CLIENT_ID_KEY);  
            
if (componentId == null){
                
if (log.isWarnEnabled()) { log.warn("No Client ID found under key: " + componentId); }
            }
 else {
                handleAjaxRequest(context, componentId);
            }

            
            
//保存頁面狀態(tài)
            context.getApplication().getStateManager().saveSerializedView(context);
        }

    }

    
    
protected void handleAjaxRequest(FacesContext context, String ajaxClientId) {
        UIViewRoot viewRoot 
= context.getViewRoot();
        
        AjaxInterface ajaxComponent 
= null;
        
try {
            ajaxComponent 
= (AjaxInterface)viewRoot.findComponent(ajaxClientId);
        }
 catch (ClassCastException cce){
            
throw new IllegalArgumentException("Component found under Ajax key was not of expected type.");
        }

        
if (ajaxComponent == null){
            
throw new NullPointerException("No component found under specified client id: " + ajaxClientId);
        }

        
        ajaxComponent.handleAjaxRequest(context);
    }


    
public void beforePhase(PhaseEvent arg0) {
        
// We do nothing in the before phase.
    }


    
public PhaseId getPhaseId() {
        
return PhaseId.RESTORE_VIEW;
    }

}


 

二、擴展 UIComponent

 

1定義接口

com.sterning.jsf.ajax.AjaxInterface接口:

package com.sterning.jsf.ajax;

import javax.faces.context.FacesContext;

/**
 * 該接口應該由Ajax組件類實現(xiàn)
 
*/


public interface AjaxInterface {
    
    
public void handleAjaxRequest(FacesContext context);
}


2.實現(xiàn)接口并繼承UIComponentBase類
com.sterning.jsf.ajax.component. AjaxComponent
package com.sterning.jsf.ajax.component;

import javax.faces.component.UIComponentBase;
import javax.faces.context.FacesContext;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import com.sterning.jsf.ajax.AjaxInterface;
import com.sterning.jsf.ajax.AjaxRendererInterface;


public class AjaxComponent extends UIComponentBase implements AjaxInterface {
    
private static final transient Log log = LogFactory
            .getLog(com.sterning.jsf.ajax.component.AjaxComponent.
class);

    
public static final String DEFAULT_RENDERER_TYPE = "com.sterning.jsf.ajax.component.AjaxComponentRenderer";

    
public static final String COMPONENT_FAMILY = "com.sterning.jsf.ajax.component.AjaxComponent";

    
public static final String COMPONENT_TYPE = "com.sterning.jsf.ajax.component.AjaxComponent";                                                                                        // Handler

    
/**
     * 在構(gòu)函數(shù)中的setRendererType(AjaxComponent.DEFAULT_RENDERER_TYPE) 和getFamily
     * 是指定用來生成HTML代碼的渲染器,渲染器需要在faces-config.xml中進行配制
     
*/

    
public AjaxComponent() {
        
this.setRendererType(AjaxComponent.DEFAULT_RENDERER_TYPE);
    }


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


    
/**
     * 當Ajax發(fā)出請求時,Ajax監(jiān)聽器將執(zhí)行此方法
     
*/

    
public void handleAjaxRequest(FacesContext context) {
        
// 通過Renderer進行代理
        AjaxRendererInterface renderer = (AjaxRendererInterface) this
                .getRenderer(context);
        renderer.handleAjaxRequest(context, 
this);
    }

}


 

三、定義渲染器

下面要做的是內(nèi)聯(lián)地定義渲染器的功能。

1.定義渲染器接口

com.sterning.jsf.ajax. AjaxRendererInterface接口

package com.sterning.jsf.ajax;

import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;

public interface AjaxRendererInterface {
    
public void handleAjaxRequest(FacesContext context, UIComponent component);
}


2.實現(xiàn)接口并繼承Renderer類
com.sterning.jsf.ajax.component. AjaxComponentRenderer類
package com.sterning.jsf.ajax.component;

import java.io.IOException;

import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
import javax.faces.context.ResponseWriter;
import javax.faces.render.Renderer;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.logging.*;

import com.sterning.jsf.ajax.AjaxRendererInterface;


public class AjaxComponentRenderer extends Renderer implements
        AjaxRendererInterface 
{
    
private static final transient Log log = LogFactory
            .getLog(com.sterning.jsf.ajax.component.AjaxComponentRenderer.
class);

    
private static final String INPUT_ID = "com.sterning.jsf.ajax.component.INPUT";

    
private static final String INPUT_NAME = "com.sterning.jsf.ajax.component.INPUT";

    
private static final String BUTTON_ID = "com.sterning.jsf.ajax.component.BUTTON";

    
private static final String MESSAGE_DIV_ID = "com.sterning.jsf.ajax.component.MESSAGE_DIV";

    
private static final String CLIENT_ID = "com.sterning.jsf.ajax.component.CLIENT_ID";

    
/**
     * 定義渲染器。渲染器我們需要從Renderer類中繼承,不過我們一般情況下會繼承HtmlRenderer這個類,我們可以覆蓋decode
     * encodeBegin encodeChildren encodeEnd 來生成HTML
     
*/

    
public AjaxComponentRenderer() {
    }


    
public void encodeBegin(FacesContext context, UIComponent component)
            
throws IOException {
        
if (log.isTraceEnabled()) {
            log.trace(
"begin encodeBegin()");
        }


        HttpServletRequest request 
= (HttpServletRequest) context
                .getExternalContext().getRequest();

        AjaxComponent ajaxComp 
= (AjaxComponent) component;

        ResponseWriter out 
= context.getResponseWriter();

        String clientId 
= ajaxComp.getClientId(context);

        out.startElement(
"div", ajaxComp);
        out.writeAttribute(
"id", clientId, null);
        out.writeAttribute(
"style""border:solid; width:200; height:200;",
                
null);

        out.startElement(
"div", ajaxComp); // Message div
        out.writeAttribute("id", MESSAGE_DIV_ID, null);
        out.endElement(
"div"); // Message div

        out.startElement(
"input", ajaxComp);
        out.writeAttribute(
"type""text"null);
        out.writeAttribute(
"id", INPUT_ID, null);
        out.writeAttribute(
"name", INPUT_NAME, null);
        out.endElement(
"input");

        out.startElement(
"button", component);
        out.writeAttribute(
"type""button"null);
        out.writeAttribute(
"name", BUTTON_ID, null);
        out.writeAttribute(
"id", BUTTON_ID, null);
        out.writeAttribute(
"value", BUTTON_ID, null);
        out.writeText(
"Ajax It""null");
        out.endElement(
"button");

        
// A hidden field to hold the URL of the server for the ajax request
        out.startElement("input", ajaxComp);
        out.writeAttribute(
"id""com.sterning.jsf.ajax.component.SERVER"null);
        out.writeAttribute(
"type""hidden"null);
        out.writeAttribute(
"value", request.getScheme() + "://"
                
+ request.getServerName() + ":" + request.getServerPort()
                
+ request.getRequestURI(), null);
        out.endElement(
"input");

        
// A hidden field to hold the component Client ID
        out.startElement("input", ajaxComp);
        out.writeAttribute(
"id", CLIENT_ID, null);
        out.writeAttribute(
"type""hidden"null);
        out.writeAttribute(
"value", clientId, null);
        out.endElement(
"input");

        out.write(
"\nAjax組件\n");
        out.startElement(
"script", ajaxComp);
        out.write(
"dojo.addOnLoad(AjaxComponent.loadComponent());\n"); 
        out.endElement(
"script");
    }


    
/**
     * 處理頁面按鈕的請求, 該項按鈕通過上面的encodeBegin()方法設置
     
*/

    
public void handleAjaxRequest(FacesContext context, UIComponent component) {
        
if (log.isInfoEnabled()) {
           log.info(
"BEGIN handleAjaxRequest()");
        }

        HttpServletRequest request 
= (HttpServletRequest) context
                .getExternalContext().getRequest();

        String textField 
= request.getParameter(INPUT_NAME);
        String serverContribution 
= "SERVER RESPONSE: ";
        StringBuffer xml 
= null;

        
if (textField == null{
            
if (log.isInfoEnabled()) {
                log.info(
"No parameter found for text field.");
            }

        }
 else {
            
if (log.isTraceEnabled()) {
                log.trace(
"textField: " + textField);
            }


            xml 
= new StringBuffer("<response>");

            xml.append(
"<message>" + serverContribution + textField
                    
+ "</message>");

            xml.append(
"<status>OK</status></response>");
        }


        
if (xml == null{
            
if (log.isInfoEnabled()) {
                log.info(
"Response is null.");
            }

            xml 
= new StringBuffer(this.getErrorString());
        }

        HttpServletResponse response 
= (HttpServletResponse) context
                .getExternalContext().getResponse();

        response.setContentType(
"text/xml");
        response.setHeader(
"Cache-Control""no-cache");

        
try {
            response.getWriter().write(xml.toString());
            
if (log.isInfoEnabled()) {
                log.info(
"Response sent: " + xml);
            }

        }
 catch (IOException e) {
            
if (log.isErrorEnabled()) {
                log.error(
"Error writing ajax response.", e);
            }

        }


    }


    
protected String getErrorString() {
        
return new String(
                
"<response><message>There was a problem</message><status>ERROR</status></response>");
    }

}


 

四、創(chuàng)建定制標記

JSF 組件不是天生綁定到 JSP 上的。要連接起 JSP 世界和 JSF 世界,需要能夠返回組件類型的定制標記(然后在 faces-context文件中登記)和渲染器。

1.繼承UIComponentTagBase

com.sterning.jsf.ajax.component. AjaxComponentTag

package com.sterning.jsf.ajax.component;

import org.apache.myfaces.shared_impl.taglib.UIComponentTagBase;

import org.apache.commons.logging.*;

public class AjaxComponentTag extends UIComponentTagBase {
    
private static final transient Log log = LogFactory
            .getLog(com.sterning.jsf.ajax.component.AjaxComponentTag.
class);

    
/**
     * 定義標簽,在這一步中我們需要繼承UIComponentTag這個類,但在實際應用中,
     * 我們可以繼承他的子類,比如在例子中我們就繼承HtmlOutputTextTagBase。在標簽類中,
     * 我們必須要覆蓋getComponentType方法和getRendererType,來指定這個標簽屬于哪個組件和渲染器,
     * 這兩個屬性的返回值都應和配制文件指定的值相同。
     
*/

    
public AjaxComponentTag() {
    }


    @Override
    
public String getComponentType() {
        
return AjaxComponent.COMPONENT_TYPE;
    }


    @Override
    
public String getRendererType() {
        
return AjaxComponent.DEFAULT_RENDERER_TYPE;
    }

}

五、登記定制標記

現(xiàn)在要做的全部工作就是創(chuàng)建一個 TLD(標記庫描述符)文件,以登記定制標記

WebRoot/WEB-INF/tutorial.tld

<xml version="1.0" encoding="ISO-8859-1"?>

<!DOCTYPE taglib PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.2//EN" "http://java./dtd/web-jsptaglibrary_1_2.dtd">

<taglib xmlns="http://java./JSP/TagLibraryDescriptor">
    
<tlib-version>1.3</tlib-version>
    
<jsp-version>1.2</jsp-version>
    
<short-name>tut</short-name>
    
<uri>http://www./jsf</uri>
    
<description>JSF Tutorial - Ajax</description>
    
<tag>
        
<name>ajaxComponent</name>
        
<tag-class>com.sterning.jsf.ajax.component.AjaxComponentTag</tag-class>
        
<body-content>JSP</body-content>
        
<description>
            The AjaxComponent example.
        
</description>
        
<!-- UIComponent attributes -->
        
<attribute>
            
<name>id</name>
            
<required>false</required>
            
<rtexprvalue>false</rtexprvalue>
            
<type>java.lang.String</type>
            
<description>
                The developer-assigned ID of this component. The ID must
                be unique within the scope of the tag's enclosing naming
                container (e.g. h:form or f:subview). This value must be
                a static value.
            
</description>
        
</attribute>
        
<attribute>
            
<name>binding</name>
            
<required>false</required>
            
<rtexprvalue>false</rtexprvalue>
            
<type>java.lang.String</type>
            
<description>
                Identifies a backing bean property (of type UIComponent
                or appropriate subclass) to bind to this component
                instance. This value must be an EL expression.
            
</description>
        
</attribute>
        
<attribute>
            
<name>rendered</name>
            
<required>false</required>
            
<rtexprvalue>false</rtexprvalue>
            
<type>java.lang.String</type>
            
<description>
                A boolean value that indicates whether this component
                should be rendered. Default value: true.
            
</description>
        
</attribute>
    
</tag>
</taglib>

一旦定義了 TLD 文件,就可以開始在 JSP 中使用標記了。

WebRoot/webpages/index.jsp

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
 
<%@ page language="java" pageEncoding="GB2312"%>
<%@ taglib uri="http://java./jsf/html" prefix="h" %>
<%@ taglib uri="http://java./jsf/core" prefix="f" %>

<%@ taglib uri="http://www./jsf" prefix="tut" %>

<%--
<%@ taglib uri="http://myfaces./tomahawk" prefix="t" %>
--%>

<link rel="stylesheet" type="text/css" href='<c:url value="/includes/styles.css"/>'>
<script type="text/javascript" src='<%=request.getContextPath()%>/javascript/utils.js'></script>
<script type="text/javascript" src='<%=request.getContextPath()%>/javascript/dojo.js'></script>

<f:view>
    
<html>
        
<head>
        
</head>
        
<body>
               
<h:outputText value="自定義JSF Ajax組件"></h:outputText>
               
<form>
                   
<tut:ajaxComponent/>
               
</form>
        
</body>
    
</html>
</f:view>

 

順便,WebRoot/index.html的內(nèi)容如下:

<meta http-equiv="refresh" content="0; url=webpages/index.jsf">

另外,還有兩個js文件,分別是Utils.jsdojo.js。分別位于WebRoot/javascript目錄下,請查看源代碼。

六、配置文件

WebRoot/WEB-INF/Web.xml文件的配置如下:

<xml version="1.0" encoding="UTF-8">
<web-app xmlns="http://java./xml/ns/j2ee"
    xmlns:xsi
="http://www./2001/XMLSchema-instance" version="2.4"
    xsi:schemaLocation
="http://java./xml/ns/j2ee   http://java./xml/ns/j2ee/web-app_2_4.xsd">
    
<!--
 * <b>Created:</b> Oct, 2007<br>
 * <b>Title:</b> JSF Ajax Component<br>
-->

    
<!-- SERVLET -->
    
<servlet>
        
<servlet-name>Faces Servlet</servlet-name>
        
<servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
        
<load-on-startup>1</load-on-startup>
    
</servlet>
    
<servlet-mapping>
        
<servlet-name>Faces Servlet</servlet-name>
        
<url-pattern>*.jsf</url-pattern>
    
</servlet-mapping>
    
</web-app>

 

WebRoot/WEB-INF/faces-config.xml的代碼如下:

<xml version="1.0" encoding="UTF-8">
<!DOCTYPE faces-config PUBLIC "-//Sun Microsystems, Inc.//DTD JavaServer Faces Config 1.1//EN" "http://java./dtd/web-facesconfig_1_1.dtd">

<faces-config>
        
<component>
           
<component-type>com.sterning.jsf.ajax.component.AjaxComponent</component-type>
           
<component-class>com.sterning.jsf.ajax.component.AjaxComponent</component-class>
        
</component>              
    
<render-kit>    
        
<renderer>
            
<component-family>com.sterning.jsf.ajax.component.AjaxComponent</component-family>
            
<renderer-type>com.sterning.jsf.ajax.component.AjaxComponentRenderer</renderer-type>
            
<renderer-class>com.sterning.jsf.ajax.component.AjaxComponentRenderer</renderer-class>
        
</renderer>
    
</render-kit>
    
<!-- LIFECYCLE -->

    
<lifecycle>
        
<phase-listener>com.sterning.jsf.ajax.AjaxListener</phase-listener>
    
</lifecycle>

</faces-config>

 

其運行效果如下圖所示:



    本站是提供個人知識管理的網(wǎng)絡存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點。請注意甄別內(nèi)容中的聯(lián)系方式、誘導購買等信息,謹防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點擊一鍵舉報。
    轉(zhuǎn)藏 分享 獻花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多