360 likes | 508 Views
JavaServer Faces и AJAX. Цветелин Андреев. Българска асоциация на разработчиците на софтуер. Съдържание. Добавяне на AJAX функционалност към съществуващи JSF приложения Изграждане на потребителски компоненти с AJAX функционалност Съществуващи библиотеки. JavaServer Faces и AJAX .
E N D
JavaServer Faces и AJAX Цветелин Андреев Българска асоциация на разработчиците на софтуер
Съдържание Добавяне на AJAX функционалност към съществуващи JSF приложения Изграждане на потребителски компоненти с AJAX функционалност Съществуващи библиотеки
JavaServer Faces и AJAX JavaServer Faces? Част от J2EE Базиран на JSP и Java Servlets Разделя бизнес логиката от презентационната част Лесен начин за разширяване на готовите компоненти
JSF Hello World • Включване на таг библиотеките <%@ taglib uri="http://java.sun.com/jsf/html" prefix="h" %> <%@ taglib uri="http://java.sun.com/jsf/core" prefix="f" %> • Дефиниране на формата <h:form id="helloForm"> <h:outputText value="#{txt.prompt}"/> <h:inputText size="40" id="nameField" value="#{personBean.name}" required="true"/> <h:commandButton action="greeting" value="#{txt.button_text}" /> </h:form>
JSF Hello World Декларация на Managed Bean в faces-config.xml faces-config.xml <managed-bean> <managed-bean-name>personBean</managed-bean-name> <managed-bean-class>demo.PersonBean</managed-bean-class> <managed-bean-scope>session</managed-bean-scope> </managed-bean> • Изписване на резултата в следващата страница <h:outputText value="#{personBean.name}" />
JSF Hello World Демонстрация
Добавяне на автоматични подсказки чрез AJAX - Servlet Клиентска част JavaScript функции за комуникация със сървърната част Прихващане на събития, свързани с полето за въвеждане на името Компонта за ивеждане на резултата от AJAX заявките Сървърна част Сърлвет, обработващ заявките
Клиентска част Връзка към JavaScript файла <script type="text/javascript" src="pages/script.js"/> • Попъп меню <div id="menu-popup1" ... ></div> • Обработка на събитията за input полето <h:inputText ... onkeyup="doCompletion(...);" ... />
Клиентска част Изпращане на заявки function doCompletion(...) { var url = "AjaxServlet?key=" + escape(target.value); ... req.onreadystatechange = processRequest; req.open("GET", url, true); req.send(null); • Обработка на резултата function parseMessages(...) { var items = req.responseXML.getElementsByTagName("items")[0]; for (loop = 0; loop < items.childNodes.length; loop++) { var item = items.childNodes[loop]; appendItem(menu, item.childNodes[0].nodeValue); }
Сървърна част AjaxServlet public class AjaxServlet extends HttpServlet • Обработка на параметрите на заявката и извличане на резулат public void doGet(...) { ... String key = (String) request.getParameter("key"); namesBean.getMatches(null, key, result); ...
Сървърна част Подготвяне и връщане на отговора public void doGet(...) { ... sb.append("<items>"); Iterator it = items.iterator(); while (it.hasNext()) { sb.append("<item>"); sb.append(it.next().toString()); sb.append("</item>"); } sb.append("</items>"); ... response.setContentType("text/xml"); response.setHeader("Cache-Control", "no-cache"); response.getWriter().write(sb.toString()); ...
Сървърна част Регистриране на сървлета web.xml <servlet> <servlet-name>Ajax Faces Servlet</servlet-name> <servlet-class>com.ceco.jsf.AjaxServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>Ajax Faces Servlet</servlet-name> <url-pattern>/AjaxServlet</url-pattern> </servlet-mapping>
Добавяне на автоматични подсказки чрез AJAX - Servlet Демонстрация
Добавяне на автоматични подсказки чрез AJAX - PhaseListener Жизнен цикъл на JSF приложението Restore View PhaseListener Пролседява жизнения цикъл Можем да прихванем всяка заявка в контекста на приложението
Клиентска част Заявката трябва да е в контекста на приложението web.xml <servlet-mapping> <servlet-name>Faces Servlet</servlet-name> <url-pattern>/faces/*</url-pattern> </servlet-mapping> var url = "faces/ajax?&key=" + escape(target.value); • Дефиниране на контекста
Сървърна част Имплементиране на PhaseListener public class AjaxListener implements PhaseListener { • Определяне на фазата от жизнения цикъл public PhaseId getPhaseId() { return PhaseId.RESTORE_VIEW; } • Филтриране на AJAX заявката public void afterPhase(PhaseEvent event) { String rootId = event.getFacesContext().getViewRoot().getViewId(); if (rootId.indexOf("ajax") != -1) { handleAjaxRequest(event); } }
Сървърна част Прекъсване на жизнения цикъл faces-config.xml <lifecycle> <phase-listener>demo.AjaxListener</phase-listener> </lifecycle> event.getFacesContext().responseComplete(); • Регистриране на потребителски PhaseListener
Добавяне на автоматични подсказки чрез AJAX - PhaseListener Демонстрация
Servlet vs. PhaseListener Приблизително еднакви по производителност и сложност PhaseListener решението е свързано с JSF При PhaseListener не се налага да се модифицира web.xml
Недостатъци Не са преизползваеми Авторът на страницата трябва да се грижи за JavaScript Авторът на страницата трябва да е запознат със сървърната част
Добавяне на автоматични подсказки чрез AJAX – Custom Component Възползва се от лесния начин за конструиране на потребителски компоненти Избягват се недостатъците на горните подходи Могат да се използват без промяна в повече приложения Използват се без познания по JavaScript
Добавяне на автоматични подсказки чрез AJAX – Custom Component Потребителската компонента отговаря за следните неща: Рендерира HTML презентацията на компонентата Грижи се за добавянето на връзка към JavaScript файла в HTML сраницата както и за предоставянето на този файл на клиента Грижи се за обработката на AJAX заявките
Добавяне на автоматични подсказки чрез AJAX – Custom Component Построяване на потребителски компоненти Дефинираме собствен таг с атрибути Имплементираме HTML рендерер Имплементираме PhaseListener Имплементираме сървърна компонента наследяваща компонентата HtmlInputText
Рендериране на HTML за компонентата Добавяне на попъп меню и прихващане на събитията от компонентата AjaxTextFieldRenderer.java protected void getEndTextToRender(...) throws IOException { ... writer.startElement("div", component); writer.writeAttribute("id", "menu-popup0", null); ... writer.writeAttribute("class", "popupFrame", null); writer.endElement("div"); ... }
Рендериране на HTML за компонентата Изключваме подсказките от браузъра AjaxTextFieldRenderer.java protected void getEndTextToRender(...) throws IOException { ... writer.writeAttribute("autocomplete", "off", null); ... writer.writeAttribute("onkeyup", "doCompletion(...)", null); ... }
Рендериране на JavaScript файла Само един път в страницата AjaxTextFieldRenderer.java protected void getEndTextToRender(...) throws IOException { ... renderScriptOnce(writer, component, context); ... } private void renderScriptOnce { Map requestMap = context.getExternalContext().getRequestMap(); Boolean scriptRendered = (Boolean)requestMap.get(RENDERED_SCRIPT_KEY); if (scriptRendered == Boolean.TRUE) { return; } requestMap.put(RENDERED_SCRIPT_KEY, Boolean.TRUE); ...
Рендериране на JavaScript файла Генерираният HTML AjaxPhaseListener.java public void afterPhase(PhaseEvent event) { String rootId = event.getFacesContext().getViewRoot().getViewId(); if (rootId.endsWith("ajaxtextfield.js")) { handleResourceRequest(event, "script.js", "text/javascript"); } ... <script type="text/javascript" src="faces/ajaxtextfield.js"/> • Обработка на заявката за JavaScript файла
Обработка на AJAX заявките По аналогичен начин на примера с PhaseListener AjaxPhaseListener.java private void handleAjaxRequest(PhaseEvent event) { ... sb.append("<items>"); Iterator it = items.iterator(); while (it.hasNext()) { sb.append("<item>"); sb.append(it.next().toString()); sb.append("</item>"); } sb.append("</items>"); ... response.setContentType("text/xml"); response.setHeader("Cache-Control", "no-cache"); response.getWriter().write(sb.toString()); ...
Модел на работа <script type="text/javascript" src="faces/ajax-textfield.js"/> Custom component PhaseListener script.js JavaScript XMLHttpRequest XMLHttpRequest Callback Name: NamesBean Son Sonya Web Page Web Container 1 2 3
Пакетиране на потребителската компонента Демонстрация
Използване на потребителската компонента Лесно, бързо, без JavaScript! inputname.jsp <%@ taglib uri="http://java.sun.com/ajaxC/txt" prefix="aj" %> ... <aj:completionField size="40" id="nameField" completionMethod="#{namesBean.getMatches}" value="#{personBean.name}" required="true" onchoose="function(item) { return chooseName(item); }" />
Използване на потребителската компонента Демонстрация
JavaServer Faces и AJAX Библиотеки с готови AJAX enabled компоненти WebStudio AjaxFaces AJAX for JavaServer Faces Свободна за сваляне Добавяне на AJAX в същесвуващи JSF приложения без JavaScript
Ресурси по темата • JSF • http://java.sun.com/javaee/javaserverfaces/ • http://www.jsftutorials.net/ • JSF и AJAX • https://bpcatalog.dev.java.net/ajax/jsf-ajax/ • https://ajax4jsf.dev.java.net/
JavaServer Faces и AJAX Въпроси?