paomo30000 发表于 2013-1-23 02:52:55

构建支持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.id + "&ajaxreq=true";”
但本人查阅了部分资料发现decode()方法现在已经不能拦截AJAX post-back请求了。但即使把表单名称(window.docuent.forms.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));//      SessionBean1sessionb = (SessionBean1)context.getApplication().getVariableResolver().resolveVariable(context, "SessionBean1");      SessionBean1sessiona = (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;    }}
页: [1]
查看完整版本: 构建支持AJAX的JSF组件(二)