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

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

Пример webserverlog

Пример приложения webserverlog, расположенный в каталоге tut-install/examples/batch/webserverlog/, демонстрирует, как использовать фреймворк пакетной обработки в Java EE для анализа файла журнала веб-сервера. В этом примере приложение читает файл журнала и находит, какой процент просмотров страниц с планшетных устройств приходится на продажи продукта.

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

Архитектура webserverlog

Приложение webserverlog состоит из следующих элементов:

  • Файл определения задания (webserverlog.xml), который использует язык спецификации задания (JSL) для определения пакетного задания с шагом фрагмента и шагом задачи. Шаг фрагмента действует как фильтр, а шаг задачи вычисляет статистику по оставшимся записям.

  • Файл журнала (log1.txt), который содержит входные данные для пакетного задания.

  • Два Java-класса (LogLine и LogFilteredLine), которые представляют элементы ввода и вывода для шага фрагмента.

  • Три пакетных артефакта (LogLineReader, LogLineProcessor и LogFilteredLineWriter), которые реализуют шаг фрагмента приложения. Этот шаг считывает элементы из файла журнала веб-сервера, фильтрует их с помощью браузера, используемого клиентом, и записывает результаты в текстовый файл.

  • Два пакетных артефакта (InfoJobListener и InfoItemProcessListener), которые реализуют два простых слушателя.

  • Пакетный артефакт (MobileBatchlet.java), который вычисляет статистику по отфильтрованным элементам.

  • Две страницы Facelets (index.xhtml и jobstarted.xhtml), которые предоставляют внешний интерфейс пакетного приложения. Первая страница показывает файл журнала, который будет обработан пакетным заданием, а вторая страница позволяет пользователю проверить состояние задания и показать результаты.

  • Managed-бин (JsfBean), доступ к которому осуществляется со страниц Facelets. Компонент отправляет задание в пакетную среду выполнения, проверяет состояние задания и считывает результаты из текстового файла.

Файл определения задания

Файл определения задания webserverlog.xml находится в каталоге WEB-INF/classes/META-INF/batch-jobs/. Файл определяет семь свойств уровня задания и два шага:


<job id="webserverlog" xmlns="http://xmlns.jcp.org/xml/ns/javaee"
     version="1.0">
    <properties>
        <property name="log_file_name" value="log1.txt"/>
        <property name="filtered_file_name" value="filtered1.txt"/>
        <property name="num_browsers" value="2"/>
        <property name="browser_1" value="Tablet Browser D"/>
        <property name="browser_2" value="Tablet Browser E"/>
        <property name="buy_page" value="/auth/buy.html"/>
        <property name="out_file_name" value="result1.txt"/>
    </properties>
    <listeners>
        <listener ref="InfoJobListener"/>
    </listeners>
    <step id="mobilefilter" next="mobileanalyzer"> ... </step>
    <step id="mobileanalyzer"> ... </step>
</job>

Первый шаг определяется следующим образом:

<step id="mobilefilter" next="mobileanalyzer">
    <listeners>
        <listener ref="InfoItemProcessListeners"/>
    </listeners>
    <chunk checkpoint-policy="item" item-count="10">
        <reader ref="LogLineReader"></reader>
        <processor ref="LogLineProcessor"></processor>
        <writer ref="LogFilteredLineWriter"></writer>
    </chunk>
</step>

Этот шаг является обычным шагом фрагмента, указывающего пакетные артефакты, реализующие каждую фазу шага. Имена пакетных артефактов не являются полностью квалифицированными именами классов, потому что пакетные артефакты являются бинами CDI, аннотированными @Named.

Второй шаг определяется следующим образом:

<step id="mobileanalyzer">
    <batchlet ref="MobileBatchlet"></batchlet>
    <end on="COMPLETED"/>
</step>

Этот шаг является шагом задачи, указывающей пакетный артефакт, который реализует этот шаг. Это последний шаг задания.

Элементы LogLine и LogFilteredLine

Класс LogLine представляет записи в файле журнала веб-сервера и определяется следующим образом:

public class LogLine {
    private final String datetime;
    private final String ipaddr;
    private final String browser;
    private final String url;

    /* ... Конструктор, геттеры и сеттеры ... */
}

Класс LogFileteredLine аналогичен этому классу, но имеет только два поля: IP-адрес клиента и URL.

Пакетные артефакты шага фрагмента

Первый шаг состоит из артефактов пакета LogLineReader, LogLineProcessor и LogFilteredLineWriter.

Артефакт LogLineReader считывает записи из файла журнала веб-сервера:

@Dependent
@Named("LogLineReader")
public class LogLineReader implements ItemReader {
    private ItemNumberCheckpoint checkpoint;
    private String fileName;
    private BufferedReader breader;
    @Inject
    private JobContext jobCtx;

    public LogLineReader() { }

    /* ... Переопределение методов  open, close, readItem и
     *     checkpointInfo... */
}

Метод open считывает свойство log_file_name и открывает файл журнала с буферизованным читателем. В этом примере файл журнала был включён в приложение в webserverlog/WEB-INF/classes/log1.txt:

fileName = jobCtx.getProperties().getProperty("log_file_name");
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
InputStream iStream = classLoader.getResourceAsStream(fileName);
breader = new BufferedReader(new InputStreamReader(iStream));

Если предоставляется объект контрольной точки, метод open продвигает читателя до последней контрольной точки. В противном случае этот метод создаёт новый объект контрольной точки. Объект контрольной точки отслеживает номер строки из последнего подтверждённого фрагмента.

Метод readItem возвращает новый объект LogLine или null в конце файла журнала:

@Override
public Object readItem() throws Exception {
    String entry = breader.readLine();
    if (entry != null) {
        checkpoint.nextLine();
        return new LogLine(entry);
    } else {
        return null;
    }
}

Артефакт LogLineProcessor получает список браузеров из свойств задания и фильтрует записи журнала в соответствии со списком:

@Override
public Object processItem(Object item) {
    /* Получение списка интересующих браузеров */
    if (nbrowsers == 0) {
        Properties props = jobCtx.getProperties();
        nbrowsers = Integer.parseInt(props.getProperty("num_browsers"));
        browsers = new String[nbrowsers];
        for (int i = 1; i < nbrowsers + 1; i++)
            browsers[i - 1] = props.getProperty("browser_" + i);
    }

    LogLine logline = (LogLine) item;
    /* Фильтрация только браузеров мобильных и планшетных устройств */
    for (int i = 0; i < nbrowsers; i++) {
        if (logline.getBrowser().equals(browsers[i])) {
            return new LogFilteredLine(logline);
        }
    }
    return null;
}

Артефакт LogFilteredLineWriter считывает имя выходного файла из свойств задания. Метод open открывает файл для записи. Если предоставлен объект контрольной точки, артефакт продолжает запись в конец файла. В противном случае файл перезаписывается, если он существует. Метод writeItems записывает отфильтрованные элементы в выходной файл:

@Override
public void writeItems(List<Object> items) throws Exception {
    / * Запись отфильтрованных строк в выходной файл * /
    for (int i = 0; i < items.size(); i++) {
        LogFilteredLine filtLine = (LogFilteredLine) items.get(i);
        bwriter.write(filtLine.toString());
        bwriter.newLine();
    }
}

Пакетные артефакты слушателя

Пакетный артефакт InfoJobListener реализует простой слушатель, который записывает сообщения журнала, когда задание начинается и когда оно заканчивается:

@Dependent
@Named("InfoJobListener")
public class InfoJobListener implements JobListener {
    ...
    @Override
    public void beforeJob() throws Exception {
        logger.log(Level.INFO, "The job is starting");
    }

    @Override
    public void afterJob() throws Exception { ... }
}

Пакетный артефакт InfoItemProcessListener реализует интерфейс ItemProcessListener для шагов фрагмента:

@Dependent
@Named("InfoItemProcessListener")
public class InfoItemProcessListener implements ItemProcessListener {
    ...
    @Override
    public void beforeProcess(Object o) throws Exception {
        LogLine logline = (LogLine) o;
        llogger.log(Level.INFO, "Processing entry {0}", logline);
    }
    ...
}

Пакетный артефакт шага задачи

Шаг задачи реализуется артефактом MobileBatchlet, который вычисляет, какой процент отфильтрованных записей журнала являются покупками:

@Override
public String process() throws Exception {
    /* Получение свойств из файла определения задания */
    ...
    /* Подсчёт выходных данных предыдущего шага фрагмента */
    breader = new BufferedReader(new FileReader(fileName));
    String line = breader.readLine();
    while (line != null) {
        String[] lineSplit = line.split(", ");
        if (buyPage.compareTo(lineSplit[1]) == 0)
            pageVisits++;
        totalVisits++;
        line = breader.readLine();
    }
    breader.close();
    /* Запись результата */
    ...
}

Страницы JavaServer Faces

Страница index.xhtml содержит текстовую область (textarea), в которой отображается журнал веб-сервера. На странице есть кнопка, позволяющая пользователю отправить пакетное задание и перейти на следующую страницу:

<body>
    ...
    <textarea cols="90" rows="25"
              readonly="true">#{jsfBean.getInputLog()}</textarea>
    <p> </p>
    <h:form>
        <h:commandButton value="Start Batch Job"
                         action="#{jsfBean.startBatchJob()}" />
    </h:form>
</body>

Эта страница вызывает методы Managed-бина, чтобы показать файл журнала и отправить пакетное задание.

Страница jobstarted.xhtml предоставляет кнопку для проверки текущего состояния пакетного задания и отображает результаты после его завершения:

<p>Current Status of the Job: <b>#{jsfBean.jobStatus}</b></p>
<p>#{jsfBean.showResults()}</p>
<h:form>
    <h:commandButton value="Check Status"
                     action="jobstarted"
                     rendered="#{jsfBean.completed==false}" />
</h:form>

Managed-бин

Managed-бин JsfBean передаёт задание в пакетную среду выполнения, проверяет статус задания и считывает результаты из текстового файла.

Метод startBatchJob передаёт пакетное задание на выполнение:

/* Отправка пакетного задания на выполнение.
 * Метод навигации JSF (возвращает имя следующей страницы) * /
public String startBatchJob() {
    jobOperator = BatchRuntime.getJobOperator();
    execID = jobOperator.start("webserverlog", null);
    return "jobstarted";
}

Метод getJobStatus проверяет статус задания:

/ * Получение статуса задания из пакетной среды выполнения * /
public String getJobStatus() {
    return jobOperator.getJobExecution(execID).getBatchStatus().toString();
}

Метод showResults считывает результаты из текстового файла.

Запуск webserverlog

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

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

Запуск webserverlog с IDE NetBeans

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

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

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

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

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

  6. На вкладке «Проекты» кликните правой кнопкой мыши проект webserverlog и выберите «Выполнить».

    Эта команда собирает и упаковывает приложение в WAR-файл webserverlog.war, расположенный в каталоге target/, развёртывает его на сервере и запускает окно веб-браузера по следующему URL:

    http://localhost:8080/webserverlog/

Запуск webserverlog с использованием Maven

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

  2. В окне терминала перейдите в:

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

    mvn install
  4. Откройте окно веб-браузера по следующему URL:

    http://localhost:8080/webserverlog/

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