当前位置: 代码迷 >> JavaScript >> 构建支持AJAX的JSF组件(2)
  详细解决方案

构建支持AJAX的JSF组件(2)

热度:260   发布时间:2012-11-04 10:42:42.0
构建支持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 = rkf.getRenderKit(context, context.getViewRoot().getRenderKitId());
                        writer = renderKit.createResponseWriter(response.getWriter(), "text/html", request.getCharacterEncoding());
                        context.setResponseWriter(writer);
                    }
                    JSONGenerator jsonGen = new JSONGenerator(request.getParameter("input"), context);
                    String jsonOut = jsonGen.getJsonResponse();
                    writer.write(jsonOut);
                    context.responseComplete();
//             return;
                } catch (EvaluationException ee) {
                    ee.printStackTrace();
                } catch (IOException ioe) {
                    ioe.printStackTrace();
                }
            }
        }
    }

    private void writeScript(PhaseEvent event) {
        URL url = getClass().getResource(SCRIPT_RESOURCE_NAME);
        URLConnection conn = null;
        InputStream stream = null;
        BufferedReader bufReader = null;
        HttpServletResponse response = (HttpServletResponse) event.getFacesContext().getExternalContext().getResponse();
        OutputStreamWriter outWriter = null;
        String curLine = null;
        response.setCharacterEncoding("GBK");
        try {
            outWriter = new OutputStreamWriter(response.getOutputStream(),
                    response.getCharacterEncoding());
            conn = url.openConnection();
            conn.setUseCaches(false);
            stream = conn.getInputStream();
            bufReader = new BufferedReader(new InputStreamReader(stream));
            response.setContentType("text/javascript;charset=UTF-8");
            response.setStatus(200);
            while (null != (curLine = bufReader.readLine())) {
                outWriter.write(curLine + "\n");
            }
            outWriter.flush();
            outWriter.close();

        } catch (Exception e) {
            String message = null;
            message = "Can't load script file:" +
                    url.toExternalForm();

            try {
                response.sendError(HttpServletResponse.SC_BAD_REQUEST, message);
            } catch (IOException f) {
                f.printStackTrace();
            }
        }


    }
}

这里使用了一个助手类JSONGenerator用于将查询数据库得到的结果转化成dojo.Grid可以接受的JSON格式这里的数据库查询操作使用了NetBean提供的DataProvider。感觉很像.NET的数据绑定技术。
JSONGenerator.java
package util;

import com.sun.data.provider.impl.CachedRowSetDataProvider;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Date;
import javax.faces.application.FacesMessage;
import javax.faces.context.FacesContext;
import javax.faces.el.ValueBinding;
import javax.sql.rowset.CachedRowSet;
import org.json.JSONArray;
import org.json.JSONObject;
import webapplication3.SessionBean1;

/**
 *
 * @author love
 */
public class JSONGenerator {
    private String jsonResponse;
    private CachedRowSetDataProvider personDataProvider = new CachedRowSetDataProvider();

    public CachedRowSetDataProvider getPersonDataProvider() {
        return personDataProvider;
    }

    public void setPersonDataProvider(CachedRowSetDataProvider crsdp) {
        this.personDataProvider = crsdp;
    }

    public JSONGenerator(String input,FacesContext context){
        ValueBinding vb = context.getApplication().createValueBinding("#{SessionBean1.personRowSet}");
        personDataProvider.setCachedRowSet((CachedRowSet) vb.getValue(context));
//        SessionBean1  sessionb = (SessionBean1)context.getApplication().getVariableResolver().resolveVariable(context, "SessionBean1");
        SessionBean1  sessiona = (SessionBean1)context.getApplication().getELResolver().getValue(context.getELContext(), null, "SessionBean1");
//        SessionBean1 sessionb = (SessionBean1) JSFUtil.getManagedObject("#{SessionBean1}",SessionBean1.class);
        try {
            sessiona.getPersonRowSet().setObject(1, input.toUpperCase()+"%");
            personDataProvider.refresh();
            CachedRowSet cache = personDataProvider.getCachedRowSet();
            cache.execute();
            ResultSet rs = cache.getOriginal();
             JSONArray list = new JSONArray();
            try {
                while (rs.next()) {
                    JSONObject jsobj = new JSONObject();
                    String id = rs.getString("PERSONID");
                    String name = rs.getString("NAME");
                    String job = rs.getString("JOBTITLE");
                    String fre = rs.getString("FREQUENTFLYER");
                    Date date = rs.getDate("LASTUPDATED");
                    jsobj.put("LASTUPDATED", date==null?"":date);
                    jsobj.put("FREQUENTFLYER", !fre.isEmpty()?fre:"");
                    jsobj.put("JOBTITLE", !job.isEmpty()?job:"");
                    jsobj.put("NAME", !name.isEmpty()?name:"");
                    jsobj.put("PERSONID", !id.isEmpty()?id:"");
                    list.put(jsobj);
                }
                String jsonText = list.toString();
                jsonText = jsonText.replace('\"', '\'');
                jsonResponse = "{" + String.format("identifier: 'PERSONID', label: 'NAME', items: %1$s", jsonText) + "}";
            } catch (SQLException ex) {
                context.addMessage(null,
              new FacesMessage(FacesMessage.SEVERITY_ERROR, "Cannot switch to person " + personDataProvider.getValue("PERSON.PERSONID"), null));
            }
        }catch (Exception e) {
			e.printStackTrace();
		}
    }

    /**
     * @return the jsonResponse
     */
    public String getJsonResponse() {
        return jsonResponse;
    }

    /**
     * @param jsonResponse the jsonResponse to set
     */
    public void setJsonResponse(String jsonResponse) {
        this.jsonResponse = jsonResponse;
    }
}


  相关解决方案