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; } }