日期:2014-05-16  浏览次数:20310 次

构建支持AJAX的JSF组件(二)
2.AJAX处理服务器组件
这个组件接受来自浏览器的AJAX请求,返回响应。AJAX服务器组件可以实现成
a.完全独立的HTTP服务器对象,例如通过servlet.
b.集成到JSF应用程序的AJAX服务对象。例如组件的decode()方法货PhaseListener充当AJAX服务器组件。
对于使用decode()方法充当服务器组件还要再讨论下。
虽然对于decode()的拦截方法有如下定义:“对于请求的一个非常重要的要求是:表单名称也必须做为参数传递给JSF应用程序。如果没有传递这个值,JSF应用程序会吧请求解释为 none-post-back请求,所以不会进入decode()方法。所以生成的response是非AJAX的完整HTML页面。可以用一下JavaScript代码把formName 和 ajaxreq参数组合在一起。
var formdata = "formName=" + window.document.forms[0].id + "&ajaxreq=true";
但本人查阅了部分资料发现decode()方法现在已经不能拦截AJAX post-back请求了。但即使把表单名称(window.docuent.forms[0].id)传递进去也不会被JSF应用程序当作post-back请求而进入decode()方法。官方推荐方法是使用PhaseListener充当AJAX服务器组件。
接下来给出PhaseListener的实现DataProviderPhListener.java 。在这段代码离不仅拦截了AJAX post-back请求而且还渲染了上段gridajax.js代码到页面内。
请注意
public PhaseId getPhaseId() {
        return PhaseId.ANY_PHASE;
    }
由于每次阶段变化都执行它,所以返回ANY_PHASE。在beforePhase中只接受生命周期的第六个阶段所以使用PhaseId.RENDER_RESPONSE,而在在afterPhase中只接受生命周期的第一个阶段所以使用PhaseId.RESTORE_VIEW
DataProviderPhListener.java
package phaselistener;

import java.io.BufferedReader;
import java.util.Map;
import javax.faces.context.FacesContext;
import javax.faces.event.PhaseEvent;
import javax.faces.event.PhaseId;
import javax.faces.event.PhaseListener;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.URL;
import java.net.URLConnection;
import javax.faces.FactoryFinder;
import javax.faces.context.ResponseWriter;
import javax.faces.el.EvaluationException;
import javax.faces.render.RenderKit;
import javax.faces.render.RenderKitFactory;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import util.JSONGenerator;

/**
 *
 * @author love
 */
public class DataProviderPhListener implements PhaseListener {
    public static final String RENDER_SCRIPT_VIEW_ID = "SpellCheckTextArea.ajaxScript";
    private static final String SCRIPT_RESOURCE_NAME = "/com/jsfcompref/components/component/gridajax.js";

    public PhaseId getPhaseId() {
        return PhaseId.ANY_PHASE;
    }
    /**
     * <p>Go through each component in the AJAX_VALIDATOR_COMPONENTS
     * list in request scope.
     */
    public void afterPhase(PhaseEvent event) {
        // If this is restoreView phase and the viewId is the script view id
        if(event.getPhaseId() == PhaseId.RESTORE_VIEW){
            if (-1 != event.getFacesContext().getViewRoot().getViewId().indexOf(RENDER_SCRIPT_VIEW_ID) &&
                    PhaseId.RESTORE_VIEW == event.getPhaseId()) {
                // render the script
                writeScript(event);
                event.getFacesContext().responseComplete();
            }
        }
    }

    public void beforePhase(PhaseEvent event) {
        if (event.getPhaseId() == PhaseId.RENDER_RESPONSE) {
            FacesContext context = event.getFacesContext();
            Map requestMap = context.getExternalContext().getRequestParameterMap();
            
            if (requestMap.containsKey("ajaxreq")) {
                HttpServletResponse response =
                    (HttpServletResponse) context.getExternalContext().getResponse();
                HttpServletRequest request =
                    (HttpServletRequest) context.getExternalContext().getRequest();
                response.setContentType("text/xml");
                response.setHeader("Cache-Control", "no-cache");
                try {
                    ResponseWriter writer = FacesContext.getCurrentInstance().getResponseWriter();
                    if (null == writer) {
                        RenderKitFactory rkf = (RenderKitFactory) FactoryFinder.getFactory(FactoryFinder.RENDER_KIT_FACTORY);
                        RenderKit renderKit =