КаталогИндекс раздела


Источник материала - Sun Microsystems

Разработка Web-приложений при помощи JavaServer Faces

Qusay H. Mahmoud
May 2003

У вас есть много вариантов выбора при построении пользовательского интерфейса для приложений на стороне сервера. Те разработчики Java, которые используют сервлеты или JavaServer Pages, часто зависят в разработке пользовательского интерфейса от компонентов пользовательского интерфейса HTML. Это происходит главным образом потому, что компоненты пользовательского интерфейса HTML являются наименьшим общим знаменателем, который поддерживают Web-браузеры. Подразумевается, конечно, что такие Web-приложения не имеют богатого пользовательского интерфейса по сравнению с самостоятельными "толстыми" клиентами и, следовательно, имеют меньшую функциональность и/или более бедную применимость. Хотя для разработки богатого пользовательского интерфейса могут использоваться аплеты, авторы страниц JSP могут не быть хорошо знакомыми с языком Java (или заинтересованными в его изучении).

Кроме того, если вы участвуете в разработке крупномасштабной Web-системы, вы, возможно, должны пройти через ряд технических решений, таких как, как реализовывать пользовательские компоненты, например, построитель запросов или просмотрщик таблиц для построения запросов к базе данных.

JavaServer Faces - это технология на стороне сервера для разработки Web-приложений с богатым пользовательским интерфейсом. При помощи JavaServer Faces вы можете решить такие технические проблемы, как создание пользовательских компонентов интерфейса. Это потому, что технология JavaServer Faces - это каркас пользовательского интерфейса для построения Web-приложений, которые выполняются на стороне сервера и передают пользовательский интерфейс клиенту. Это так! Код пользовательского интерфейса выполняется на сервере, отвечая на события, генерируемые на клиенте.

Есть сегодня и несколько других вариантов для построения богатого пользовательского интерфейса на стороне сервера, таких как Flash, Swinglets и Jade. Однако, эти решения закрытые и инструменты, которые поддерживают разработку в них, доступны только от одного производителя. JavaServer Faces является, в первую очередь, стандартом, а это означает, что разработчики не замыкаются на одном производителе. Группа экспертов, разрабатывающих спецификации, состоит действительно из представителей всех главных производителей инструментов в сообществе Java. Так что, разработчики не имеют недостатка в выборе инструментов и, возможно, смогут использовать и модифицированную версию того инструмента, который они используют сегодня. Хотя производители инструментов совместно работают над спецификациями, они будут конкурировать друг с другом в своих реализациях. Это даст преимущества сообществу разработчиков в смысле возможностей и выбора тех прикладных компонентов, которые сделает каждый производитель.

Технология JavaServer Faces базируется на Model View Controller (MVC) для отделения логики от презентации, так что, если вы имеете практику в этом, вы в JavaServer Faces будете чувствовать себя как дома.

Эта статья представляет собой ускоренный учебник с большим числом кодов-примеров, который должен ввести вас в JavaServer Faces. Статья также:

Пожалуйста, имейте в виду, что этот учебник не показывает, как вам разрабатывать пользовательские прикладные компоненты.

Обзор JavaServer Faces

JavaServer Faces - это технология, которая была введена Sun Microsystems как JSR 127 в Java Community Process (JCP). Целью было создание стандартного каркаса для компонентов пользовательского интерфейса Web-приложений. Как отмечалось выше, JavaServer Faces позволяет вам строить Web-приложения, которые выполняются на сервере Java и возвращают пользовательский интерфейс клиенту. Это технология обеспечивает Web-приложение управлением жизненного цикла через движок сервлетов и богатой компонентной моделью с обработкой событий и передачей компонентов.

Технология JavaServer Faces состоит из двух главных компонентов:

  1. Java API для представления компонентов пользовательского интерфейса, управления состоянием, обработки событий и проверки входных данных. API имеют поддержку интернационализации и доступности.
  2. Библиотека пользовательских тегов JSP для выражения интерфейса JavaServer Faces в странице JSP. Авторы страниц могут использовать эту библиотеку тегов для добавления компонентов пользовательского интерфейса в свои страницы.

Рис. 1 показывает отношение между клиентом, сервером и JavaServer Faces.

The UI runs on the server
Рис. 1: Пользовательский интерфейс выполняется на сервере

Страница JSP представляет компоненты пользовательского интерфейса, используя библиотеку пользовательских тегов JavaServer Faces вместо жесткого кодирования их в языке разметки. Пользовательский интерфейс для приложения управляется объектами, представляемыми страницей JSP.

Несколько типов пользователей могут получить выгоды от этой технологии, включая:

Эта технология также открывает рынок повторно используемых компонентов пользовательского интерфейса для Web. Разработчики и производители могут использовать JavaServer Faces как строительные блоки для разработки прикладных интерфейсов.

Одно из преимуществ JavaServer Faces - в том, что она базируется на архитектуре Model View Controller (MVC), предлагая четкое разделение между презентацией и логикой. Это может насторожить тех, кто пользуется существующими Web-каркасами, такими как Struts. Заметьте, однако, что JavaServer Faces и Struts не являются конкурирующими технологиями, фактически, они будут работать совместно. Однако JavaServer Faces имеет некоторые преимущества перед Struts. Например, в Struts есть только один способ изобразить элемент, тогда как JavaServer Faces обеспечивает несколько механизмов для изображения отдельного элемента. От разработчика страницы зависит, выбор желаемого представления, а разработчик приложения не должен знать, какой механизм использован для изображения компонента. (Вот ссылка на дополнительную информацию по интеграции JavaServer Faces и Struts.) Читатели могут отметить, что автор Struts, Craig McClanahan, является также одним из руководителей разработки спецификаций JavaServer Faces, а также сотрудником Sun Microsystems.

Генезис приложения JavaServer Faces

Приложение JavaServer Faces очень похоже на другие Web-приложения на базе технологий Java; они выполняется в контейнере сервлетов Java и содержит:

  1. Компоненты JavaBeans (или модельные компоненты) содержащие специфическую для приложения функциональность и данные
  2. Слушатели событий
  3. Страницы JSP
  4. Вспомогательные классы на стороне сервера
  5. Библиотеку прикладных тегов для изображения компонентов пользовательского интерфейса
  6. Библиотеку прикладных тегов для представления обработчиков событий и классов проверки правильности (валидаторов)
  7. Компоненты пользовательского интерфейса, представляющие объекты с сохранением состояния на сервере
  8. Валидаторы, обработчики событий и обработчики навигации. (Валидаторы используются для проверки данных на отдельных компонентах, прежде чем будут обновлены данные на стороне сервера.)

В рекомендуемую реализацию JavaServer Faces включается библиотека компонентных тегов html_basic. Однако продвинутый разработчик может разработать собственную библиотеку тегов для изображения прикладных компонентов.

Рекомендуемая реализация JavaServer Faces обеспечивает библиотеку прикладных тегов для изображения компонентов в HTML. Вот простой пример использования библиотеки тегов. Список компонентов, поддерживаемых тегами см. в спецификациях JavaServer Faces и в учебнике.

    <%@ taglib uri="http://java.sun.com/jsf/html" prefix="h" %>
    <%@ taglib uri="http://java.sun.com/jsf/core" prefix="f" %>
    <body bgcolor="white">
    <h2>What is your name?</h2>
    <f:use_faces>
    <h:form id="helloForm" formName="helloForm" >
  	<h:input_text id="username" />
  	<h:command_button id="submit" label="Submit" commandName="submit" />
    </h:form>
    </f:use_faces>

Компонентная архитектура JavaServer Faces разработана таким образом, что функциональность компонентов определяется классами компонентов, а изображение определяется отдельным рисовальщиком (renderer). Набор для рисования (render kit) определяет, как классы компонентов отображаются на компонентные теги, соответствующие определенному клиенту. Рекомендуемая реализация JavaServer Faces включает в себя стандартный RenderKit для рисования под клиента HTML. Каждый компонент JSP в HTML RenderKit состоит из функциональности компонента, определенной классом UIComponent, и атрибутов рисования, определенных Renderer. Например, теги command_button и command_hyperlink оба представляют UIComponent, но они рисуются двумя разными способами. Компонент button рисуется как кнопка, а command_hyperlink рисуется как гиперссылка.

Начало работы с JavaServer Faces

Чтобы начать экспериментировать с JavaServer Faces, вам нужен либо Java Web Services Developer Pack (Java WSDP 1.0_01), либо Tomcat4.0+.

JavaServer Faces Reference Implementation Early Access (EA3) может быть выгружен по этому адресу. Когда вы распакуете архив, вы получите такую структуру каталогов (в Windows):

c:\jsf-ea3>
     example
     lib
     some-other-files

Каталог example содержит WAR и исходные файлы для приложений-примеров. Каталог lib содержит файлы JAR, которые нужны для JavaServer Faces. Эти JAR-файлы такие:

Пожалуйста, имейте в виду, что данная реализация JavaServer Faces является предварительным релизом (early access, EA) и представляет только некоторой подмножество спецификаций. Другими словами, этот релиз еще незрелый. Заметьте также, что текущее Reference Implementation (RI) для JavaServer Faces не работает с Java WSDP 1.1. Если вы попытаетесь использовать JavaServer Faces с Java WSDP 1.1, вы получите исключение, как показано на Рис.2:


Рис 2: JavaServer Faces RI EA не работает с Java WSDP 1.1

Если вы не имеете Java WSDP 1.0_01 и захотите поэкспериментировать с JavaServer Faces RI EA3, я рекомендую вам использовать Tomcat. Для этой статьи я использовал Tomcat-4.1.24. Если вы установили Tomcat, запустите его и протестируйте, введя http://localhost:8080 в вашем Web-браузере. Будет показана страница Tomcat по умолчанию. Теперь, чтобы поэкспериментировать с некоторыми приложениями-примерами JavaServer Faces, просто скопируйте WAR-файлы (из c:\path-to-JSF-installation) в каталог webapps вашей инсталляции Tomcat. Чтобы запустить приложение, введите http://localhost:8080/demo-name. Например, я скопировал cardemo.war в каталог webapps Tomcat, а затем ввел http://localhost:8080/cardemo в моем Web-браузере. Рис.3 показывает экран, который я получил:


Рис.3: Приложение-пример JavaServer Faces Cardemo

Создание вашего собственного приложения

Этот раздел описывает шаги, выполняемые при создании ваших собственных приложений JavaServer Faces. Пример, который я использую здесь, - простая форма, которая просит пользователя ввести его/ее имя, а затем щелкнуть на кнопке Submit. Затем приложение отображает сообщение-приветствие для пользователя.

  1. Создайте следующую структуру каталогов:

    c:\tomcat4.1\webapps
                   hello
                     src (for Java files)
                     web (for web files: index.html and JSP pages...)
                       WEB-INF
                         web.xml
                         lib     (JSF JAR files)
                         classes
    

    Эта структура, в сущности, говорит, что я хочу создать новое приложение, названное hello. В подкаталоге hello я имею src (где я храню все исходные файлы Java) и web (где у меня есть подкаталог WEB-INF, содержащий web.xml, подкаталог lib и подкаталог classes).

  2. Скопируйте все JAR-файлы из c:\jsf-ea3\lib в подкаталог lib, созданный выше.

  3. Создайте файл web.xml, используемый для конфигурирования Web-приложения. В случае JavaServer Faces, он должен задавать определенные параметры конфигурации, такие как: (1) слушатель контекста сервлета, (2) сервлет для обработки запросов JavaServer Faces и (3) отображение на обрабатываемый сервлет. Кодовый Пример 1 показывает простой файл web.xml, который задает необходимые конфигурации, специфичные для JavaServer Faces этого примера.

    Кодовый Пример 1: web.xml

    <?xml version="1.0"?>
    <!DOCTYPE web-app PUBLIC
      "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
      "http://java.sun.com/dtd/web-app_2_3.dtd">
    
    <web-app>
        <listener>
            <!-- Used to initialize and destroy the application helper and register
                    a Renderer to a RenderKit -->
            <listener-class>BasicServletContextListener</listener-class>
        </listener>
    
        <!-- Faces Servlet -->
        <servlet>
            <servlet-name>Faces Servlet</servlet-name>
            <servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
            <!-- FaceServlet should be loaded when the application starts up -->
            <load-on-startup>1</load-on-startup>
        </servlet>
    
        <!-- Faces Servlet Mapping. Map the path to the servlet when a request for
                the servlet is received -->
        <servlet-mapping>
            <servlet-name>Faces Servlet</servlet-name>
            <url-pattern>/faces/*</url-pattern>
        </servlet-mapping>
    </web-app>
    

  4. Создайте страницу HTML с тегами JavaServer Faces.

    Сначала я написал страницу index.html. Когда пользователи входят в приложение, они получают эту страницу, которая позволяет им щелкнуть на приложении, чтобы запустить его, как показано в Кодовом Примере 2.

    Кодовый Пример 2: index.html

    <!doctype html public "-//w3c//dtd html 4.0 transitional//en">
    <html>
    <head>
       <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
       <meta name="GENERATOR" content="Mozilla/4.75 [en] (WinNT; U) [Netscape]">
       <title>index</title>
    </head>
    <body>
    
    <P>
    Click <a 
        href="/developer/technicalArticles/GUI/JavaServerFaces/faces/index.jsp">here</a>
    to start the application.
    </P>
    
    <br>
    <hr WIDTH="100%">
    </body>
    </html>
    

    Когда пользователь щелкает на "here," загружается страница index.jsp, как показано в Кодовом Примере 3.

    Кодовый Пример 3: index.jsp

    <HTML>
        <HEAD> <title>Hello</title> </HEAD>
        <%@ taglib uri="http://java.sun.com/jsf/html" prefix="h" %>
        <%@ taglib uri="http://java.sun.com/jsf/core" prefix="f" %>
        <body bgcolor="white">
        <h2>What is your name?</h2>
        <jsp:useBean id="UserNameBean" class="UserNameBean" scope="session" />
        <f:use_faces>
        <h:form id="helloForm" formName="helloForm" >
      	<h:input_text id="username"
    			modelReference="UserNameBean.userName"/>
      	<h:command_button id="submit" label="Submit" commandName="submit" />
        </h:form>
        </f:use_faces>
    </HTML>
    

    Эта страница JSP использует несколько важных возможностей:


  5. Напишите объект модели (компонент JavaBean), если это необходимо.

    Бин объекта модели похож на любой другой компонент JavaBeans: он имеет набор методов акцессоров. Кодовый Пример 4 показывает пример компонента JavaBean, на который ссылается страница index.jsp Кодовом Примере 3.

    Кодовый Пример 4: UserNameBean.java

    public class UserNameBean {
       String userName = null;
    
       public UserNameBean () {
       }
    
       public void setUserName(String user_name) {
          userName = user_name;
       }
    
       public String getUserName() {
          return userName;
       }
    }
    

  6. Обработайте события.

    Следующий шаг - написать класс обработчика событий для событий компонента (таких как выбор радиокнопки или щелчок на кнопке для отсылки формы). Для простых приложений вам нужно определить, к какой странице будет обращение, когда посылается форма или выбирается ссылка. Вы делаете это, реализуя интерфейс ApplicationHandler. Кодовый Пример 5 показывает пример этого. Здесь я проверяю, сгенерировано ли FormEvent кнопкой Submit страницы index.jsp. Если так, то ID дерева компонентов устанавливается на компонент дерева, связанный со страницей hello.jsp.

    Кодовый Пример 5: BasicApplicationHandler.java

    import java.util.SortedMap;
    import javax.faces.FacesException;
    import javax.faces.component.UIComponent;
    import javax.faces.context.FacesContext;
    import javax.faces.tree.Tree;
    import javax.faces.tree.TreeFactory;
    import javax.faces.FactoryFinder;
    import javax.faces.lifecycle.ApplicationHandler;
    import javax.faces.event.FormEvent;
    import javax.faces.event.FacesEvent;
    import javax.faces.event.CommandEvent;
    import com.sun.faces.RIConstants;
    
    public class BasicApplicationHandler implements ApplicationHandler{
    
        public boolean processEvent(FacesContext context, FacesEvent facesEvent) {
    
    	if (!(facesEvent instanceof FormEvent) &&
                !(facesEvent instanceof CommandEvent)) {
    	    return true;
    	}
    
            boolean returnValue = false;
            String treeId = null;
    
            if (facesEvent instanceof FormEvent) {
    	    FormEvent formEvent = (FormEvent) facesEvent;
    	    if (formEvent.getCommandName().equals("submit")) {
    	        treeId = "/hello.jsp";
     	    }
                returnValue = true;
            } else if (facesEvent instanceof CommandEvent) {
                CommandEvent commandEvent = (CommandEvent)facesEvent;
                UIComponent c = commandEvent.getComponent();
                if (c.getAttribute("target") != null) {
                    treeId = (String)c.getAttribute("target");
                    returnValue = true;
                }
            }
    
            if (null != treeId) {
                TreeFactory treeFactory = (TreeFactory)
                FactoryFinder.getFactory(FactoryFinder.TREE_FACTORY);
                context.setTree(treeFactory.getTree(context,treeId));
    
            }
    
            return returnValue;
        }
    }
    

  7. Напишите слушатель контекста.

    Если вы посмотрите внимательно в файл дескриптора развертывания, web.xml, вы заметите, что я объявил слушатель контекста сервлета (BasicServletContextListener). Контейнер сервлетов создает слушатель контекста сервлета при старте приложения, вызывает метод слушателя contextDestroyed, когда приложение выключается. Кодовый Пример 6 показывает пример слушателя контекста.

    Кодовый Пример 6: BasicServletContextListener.java

    import javax.servlet.ServletContextListener;
    import javax.servlet.ServletContextEvent;
    import javax.faces.FactoryFinder;
    import javax.faces.lifecycle.LifecycleFactory;
    import javax.faces.lifecycle.Lifecycle;
    import javax.faces.lifecycle.ApplicationHandler;
    
    public class BasicServletContextListener implements ServletContextListener {
       public BasicServletContextListener() {
       }
    
       public void contextInitialized(ServletContextEvent e) {
          ApplicationHandler handler = new BasicApplicationHandler();
            LifecycleFactory factory = (LifecycleFactory)
                FactoryFinder.getFactory(FactoryFinder.LIFECYCLE_FACTORY);
            Lifecycle lifecycle =
                factory.getLifecycle(LifecycleFactory.DEFAULT_LIFECYCLE);
            lifecycle.setApplicationHandler(handler);
       }
    
       public void contextDestroyed(ServletContextEvent e){
       }
    }
    

  8. Напишите страницу отклика.

    Когда форма index.jsp послана, вызывается обработчик приложения и пользователь перенаправляется на страницу отклика, hello.jsp, показанную в Кодовом Примере 7.

    Кодовый Пример 7: hello.jsp

    <HTML>
        <HEAD> <title>Hello</title> </HEAD>
        <%@ taglib uri="http://java.sun.com/jsf/html" prefix="h" %>
        <%@ taglib uri="http://java.sun.com/jsf/core" prefix="f" %>
        <body bgcolor="white">
        <f:use_faces>
        <h:form id="responseform" formName="responseform">
        <h2>Hello, <h:output_text id="userLabel"
    			   modelReference="UserNameBean.userName" /> </h2>
             <p>
        </h:form>
        </f:use_faces>
    </HTML>
    

  9. Откомпилируйте и запустите приложение. Последний шаг - компиляция классов Java и выполнение приложения. Введите URL http://localhost:8080/hello в вашем Web-браузере, и вы получите index.html, как показано на Рис.4.

    Application entered
    Рис.4: Приложение запущено

    Когда вы щелкните на гиперссылке "here", вы получите нечто, похожее на Рис.5.

    Application started
    Рис.5: Приложение стартовало

    Теперь введите ваше имя и щелкните на кнопке Submit. вы получите нечто, похожее на Рис.6.


    Рис.6: Приложение работает хорошо

Проверка ввода

JavaServer Faces обеспечивает ряд встроенных механизмов проверки правильности (валидаторов) и дает разработчикам возможность создавать пользовательские прикладные валидаторы путем реализации интерфейса Validator и его метода validate. Имеется такие пять встроенных валидаторов:

  1. DoubleRangeValidator: Проверяет, находится ли значение компонента в заданных границах. Значение должно быть числом с плавающей точкой или быть конвертируемым в число с плавающей точкой. Этот валидатор может использоваться в теге validate_doublerange. Вот пример:

    <input_number id="less" formatpattern="#.## size="5">
      <validate_doublerange minimum="1.0" maximum="3.14"/>
    </input_number>
    

  2. LengthValidator: Проверяет, находится ли длина компонента (который должен быть типа java.lang.String) в заданных границах. Этот валидатор может использоваться в теге validate_length. Вот пример:

    <input_text id="creditCardNum" size="16">
      <validate_length minimum="16" maximum="16"/>
    </input_text>
    

  3. LongRangeValidator: Проверяет, находится ли значение, которое должно быть как-то конвертируемым в long, в заданных границах. Этот валидатор может использоваться в теге validate_longrange. Вот пример:

    <h:input_number id="zip" formatpattern="#####" size="5">
      <validate_longrange minimum="50000" maximum="10000"/>
    </input_number>
    

  4. RequiredValidator: Проверяет, не является ли значение компонента null. Если значение имеет тип String, предполагается, что это непустая строка. Этот валидатор используется в теге validate_required. Вот пример:

    <input_text id="creditCardNum" size="16">
      <validate_required/>
      <validate_length minimum="16" maximum="16"/>
    </input_text>
    

  5. StringRangeValidator: Проверяет, находится ли значение (которое должно быть типа String) в заданных границах. Этот валидатор может использоваться в теге validate_stringrange. Вот пример:

    <input_text id="middleInitial" size="1">
      <validate_stringrange minimum="A" maximum="Z"/>
    </input_text>
    

Заключение

JavaServer Faces - это каркас пользовательского интерфейса для построения Web-приложений, который выполняется на стороне сервера и рисует пользовательский интерфейс для клиента. Он дает вам инструмент разработки, который упрощает кодирование Web-приложений Java. Sun и другие члены экспертной группы JavaServer Faces - в которую входят Borland, IBM, Macromedia и Oracle, вместе с многими другими компаниями и лицами - сейчас оценивают способы включения технологии JavaServer Faces в новое поколение инструментов, которые упрощают разработку многоуровневых Web-приложений.

Пользователи ваших Web-приложений на базе JavaServer Faces высоко оценят широкий спектр пользовательских действий, которые становятся доступными через управляющие элементы JavaServer Faces. Вы можете предложить больше возможностей, больше удобств, чем вы могли в рамках стандартного интерфейса HTML. И помните, JavaServer Faces требуют ненамного больше усилий, чем обычная конфигурация JSP, - но со значительно большими преимуществами.

Дополнительная информация

Благодарности

Особая благодарность Dennis MacNeil и Jim Inscore из Sun Microsystems, чьи замечания помогли мне улучшить эту статью.

Об авторе

Qusay H. Mahmoud занимается консультированием и обучением технологии Java. Он опубликовал множество статей по Java и является автором Distributed Programming with Java (Manning Publications, 1999) и Learning Wireless Java (O'Reilly, 2002).


КаталогИндекс раздела