Java Platform, Enterprise Edition (Java EE) 8
Учебник по Java EE

Назад Вперёд Содержание

Пример CDI gunessnumber-cdi

Пример guessnumber-cdi сложнее примера simplegreeting и иллюстрирует использование методов-производителей, а также областей видимости сессии и приложения. Примером является игра, в которой вы пытаетесь угадать число менее чем за десять попыток. Он похож на пример guessnumber-jsf, описанный в главе 8 «Введение в Facelets», за исключением того, что вы можете продолжать угадывать, пока не получите правильный ответ или пока не используете все десять попыток.

Пример включает четыре исходных файла, страницу и шаблон Facelets и файлы конфигурации. Файлы конфигурации и шаблон такие же, как и в примере simplegreeting.

Здесь рассматриваются следующие темы:

Исходный код guessnumber-cdi

Четыре исходных файла для примера guessnumber-cdi:

  • Интерфейс квалификатора @MaxNumber

  • Интерфейс квалификатора @Random

  • Managed-бин Generator, который определяет методы-производители

  • Managed-бин UserNumberBean

Исходные файлы находятся в каталоге tut-install/examples/cdi/guessnumber-cdi/src/main/java/javaeetutorial/guessnumber.

Интерфейсы квалификаторов @MaxNumber и @Random

Интерфейс квалификатора @MaxNumber определяется следующим образом:

package guessnumber;

import java.lang.annotation.Documented;
import static java.lang.annotation.ElementType.FIELD;
import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.ElementType.PARAMETER;
import static java.lang.annotation.ElementType.TYPE;
import java.lang.annotation.Retention;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
import java.lang.annotation.Target;
import javax.inject.Qualifier;

@Target({TYPE, METHOD, PARAMETER, FIELD})
@Retention(RUNTIME)
@Documented
@Qualifier
public @interface MaxNumber {
}

Интерфейс квалификатора @Random определяется следующим образом:

package guessnumber;

import java.lang.annotation.Documented;
import static java.lang.annotation.ElementType.FIELD;
import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.ElementType.PARAMETER;
import static java.lang.annotation.ElementType.TYPE;
import java.lang.annotation.Retention;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
import java.lang.annotation.Target;
import javax.inject.Qualifier;

@Target({TYPE, METHOD, PARAMETER, FIELD})
@Retention(RUNTIME)
@Documented
@Qualifier
public @interface Random {
}

Managed-бин Generator

Managed-бин Generator содержит два метода-производителя для приложения. Бин имеет аннотацию @ApplicationScoped, чтобы указать, что его контекст распространяется на время взаимодействия пользователя с приложением:

package guessnumber;

import java.io.Serializable;
import javax.enterprise.context.ApplicationScoped;
import javax.enterprise.inject.Produces;

@ApplicationScoped
public class Generator implements Serializable {

    private static final long serialVersionUID = -7213673465118041882L;

    private final java.util.Random random =
        new java.util.Random( System.currentTimeMillis() );

    private final int maxNumber = 100;

    java.util.Random getRandom() {
        return random;
    }

    @Produces @Random int next() {
        return getRandom().nextInt(maxNumber + 1);
    }

    @Produces @MaxNumber int getMaxNumber() {
        return maxNumber;
    }

}

Managed-бин UserNumberBean

Managed-бин UserNumberBean, Managed-бин для приложения JavaServer Faces, обеспечивает логику игры. Этот бин выполняет следующие действия:

  • Реализует set- и get- методы для полей компонента

  • Инъецирует объекты двух квалификаторов

  • Предоставляет метод reset, который позволяет начать новую игру.

  • Предоставляет метод check, который определяет, угадал ли пользователь число

  • Предоставляет метод validateNumberRange, который определяет валидность ввода пользователя

Бин определяется следующим образом:

package guessnumber;

import java.io.Serializable;
import javax.annotation.PostConstruct;
import javax.enterprise.context.SessionScoped;
import javax.enterprise.inject.Instance;
import javax.faces.application.FacesMessage;
import javax.faces.component.UIComponent;
import javax.faces.component.UIInput;
import javax.faces.context.FacesContext;
import javax.inject.Inject;
import javax.inject.Named;

@Named
@SessionScoped
public class UserNumberBean implements Serializable {

    private static final long serialVersionUID = -7698506329160109476L;

    private int number;
    private Integer userNumber;
    private int minimum;
    private int remainingGuesses;

    @MaxNumber
    @Inject
    private int maxNumber;

    private int maximum;

    @Random
    @Inject
    Instance<Integer> randomInt;

    public UserNumberBean() {
    }

    public int getNumber() {
        return number;
    }

    public void setUserNumber(Integer user_number) {
        userNumber = user_number;
    }

    public Integer getUserNumber() {
        return userNumber;
    }

    public int getMaximum() {
        return (this.maximum);
    }

    public void setMaximum(int maximum) {
        this.maximum = maximum;
    }

    public int getMinimum() {
        return (this.minimum);
    }

    public void setMinimum(int minimum) {
        this.minimum = minimum;
    }

    public int getRemainingGuesses() {
        return remainingGuesses;
    }

    public String check() throws InterruptedException {
        if (userNumber > number) {
            maximum = userNumber - 1;
        }
        if (userNumber < number) {
            minimum = userNumber + 1;
        }
        if (userNumber == number) {
            FacesContext.getCurrentInstance().addMessage(null,
                new FacesMessage("Correct!"));
        }
        remainingGuesses--;
        return null;
    }

    @PostConstruct
    public void reset() {
        this.minimum = 0;
        this.userNumber = 0;
        this.remainingGuesses = 10;
        this.maximum = maxNumber;
        this.number = randomInt.get();
    }

    public void validateNumberRange(FacesContext context,
                                    UIComponent toValidate,
                                    Object value) {
        int input = (Integer) value;

        if (input < minimum || input > maximum) {
            ((UIInput) toValidate).setValid(false);

            FacesMessage message = new FacesMessage("Invalid guess");
            context.addMessage(toValidate.getClientId(context), message);
        }
    }
}

Страница Facelets

В этом примере используется тот же шаблон, что и в примере simplegreeting. Файл index.xhtml, однако, устроен более сложно.


<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
          "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html lang="en"
      xmlns="http://www.w3.org/1999/xhtml"
      xmlns:ui="http://xmlns.jcp.org/jsf/facelets"
      xmlns:h="http://xmlns.jcp.org/jsf/html">
    <ui:composition template="/template.xhtml">

        <ui:define name="title">Guess My Number</ui:define>
        <ui:define name="head">Guess My Number</ui:define>
        <ui:define name="content">
            <h:form id="GuessMain">
                <div style="color: black; font-size: 24px;">
                    <p>I'm thinking of a number from
                    <span style="color: blue">#{userNumberBean.minimum}</span>
                    to
                    <span style="color: blue">#{userNumberBean.maximum}</span>.
                    You have
                    <span style="color: blue">
                        #{userNumberBean.remainingGuesses}
                    </span>
                    guesses.</p>
                </div>
                <h:panelGrid border="0" columns="5" style="font-size: 18px;">
                    <h:outputLabel for="inputGuess">Number:</h:outputLabel>
                    <h:inputText id="inputGuess"
                                 value="#{userNumberBean.userNumber}"
                                 required="true" size="3"
disabled="#{userNumberBean.number eq userNumberBean.userNumber or userNumberBean.remainingGuesses le 0}"
                               validator="#{userNumberBean.validateNumberRange}">
                    </h:inputText>
                    <h:commandButton id="GuessButton" value="Guess"
                                     action="#{userNumberBean.check}"
disabled="#{userNumberBean.number eq userNumberBean.userNumber or userNumberBean.remainingGuesses le 0}"/>
                    <h:commandButton id="RestartButton" value="Reset"
                                     action="#{userNumberBean.reset}"
                                     immediate="true" />
                    <h:outputText id="Higher" value="Higher!"
rendered="#{userNumberBean.number gt userNumberBean.userNumber and userNumberBean.userNumber ne 0}"
                                  style="color: #d20005"/>
                    <h:outputText id="Lower" value="Lower!"
rendered="#{userNumberBean.number lt userNumberBean.userNumber and userNumberBean.userNumber ne 0}"
                                  style="color: #d20005"/>
                </h:panelGrid>
                <div style="color: #d20005; font-size: 14px;">
                    <h:messages id="messages" globalOnly="false"/>
                </div>
            </h:form>
        </ui:define>

    </ui:composition>
</html>

Страница Facelets представляет пользователю минимальные и максимальные значения и количество оставшихся попыток. Взаимодействие пользователя с игрой происходит в таблице panelGrid, содержащей поле ввода, кнопки Guess и Reset и поле, появляющееся если предположение выше или ниже правильного числа. Каждый раз, когда пользователь кликает Guess, вызывается метод userNumberBean.check для сброса максимального или минимального значения или, если предположение верно, для генерации FacesMessage. Метод userNumberBean.validateNumberRange определяет валидность каждого предположения.

Выполнение примера guessnumber-cdi

Вы можете использовать IDE NetBeans или Maven для сборки, упаковки, развёртывания и запуска приложения guessnumber-cdi.

Здесь рассматриваются следующие темы:

Сборка, упаковка и развёртывание guessnumber-cdi с IDE NetBeans

  1. Удостоверьтесь, чтобы GlassFish Server был запущен (см. Запуск и остановка сервера GlassFish).

  2. В меню Файл выберите Открыть проект.

  3. В диалоговом окне Открыть проект перейдите к:

    tut-install/examples/cdi
  4. Выберите каталог guessnumber-cdi.

  5. Нажмите Открыть проект.

  6. На вкладке Проекты кликните правой кнопкой мыши проект guessnumber-cdi и выберите Сборка.

    Эта команда собирает и упаковывает приложение в WAR-файл guessnumber-cdi.war, расположенный в каталоге target, а затем развёртывает его на сервере GlassFish.

Сборка, упаковка и развёртывание guessnumber-cdi с использованием Maven

  1. Удостоверьтесь, чтобы GlassFish Server был запущен (см. Запуск и остановка сервера GlassFish).

  2. В окне терминала перейдите в следующий каталог:

    tut-install/examples/cdi/guessnumber-cdi/
  3. Введите следующую команду для развёртывания приложения:

    mvn install

    Эта команда собирает и упаковывает приложение в WAR-файл guessnumber-cdi.war, расположенный в каталоге target, а затем развёртывает его на сервере GlassFish.

Запуск guessnumber

  1. В веб-браузере введите следующий URL:

    http://localhost:8080/guessnumber-cdi

    Откроется страница Guess My Number.

  2. На странице Guess My Number введите число в поле Number и нажмите Guess.

    Минимальные и максимальные значения изменяются вместе с оставшимся количеством попыток.

  3. Продолжайте угадывать числа, пока не получите правильный ответ или не исчерпаете все попытки.

    Если вы дали правильный ответ или у вас закончились попытки, поле ввода и кнопка Guess отображаются серым цветом.

  4. Нажмите Reset, чтобы снова сыграть в игру с новым случайным числом.


Назад Вперёд Содержание
Логотип Oracle  Copyright © 2017, Oracle и/или её дочерних компаний. Все права защищены. Версия перевода 1.0.5 (Java EE Tutorial — русскоязычная версия)