[an error occurred while processing this directive] IT • archiv :: Print

IT • archiv


[an error occurred while processing this directive]

[an error occurred while processing this directive]

Проверка ввода данных на Java с использованием схем XML. Часть 3

[an error occurred while processing this directive](none) [an error occurred while processing this directive](none)[an error occurred while processing this directive] ::
[an error occurred while processing this directive](none)
[an error occurred while processing this directive]([an error occurred while processing this directive] Бретт МакЛафлин [an error occurred while processing this directive])

[an error occurred while processing this directive](none)

Разбор данных схем XML для проверки данных.

Data Validation
PDF versionPDF версия
Обзор
Схемы XML могут обеспечить лучший способ проверки данных в приложениях Java, чем простое использование конструкций if-then-else. В этой статье Бретт продолжает строить среду проверки правильности ввода данных и завершает обсуждение, начатое в последней статье. Читатель узнает, как выполнять разбор схем XML, строить на Java представление ограничений, заданных схемами и применять эти ограничения к данные приложения. (3600 слов)

Случилось страшное. Гек, возможно, ты стал частью этой проблемы, причем не один раз. Какой проблемы? Проверки данных. Мы, программисты, самолюбиво вытаскиваем инструментарий кодов, примочек и хитростей и испытываем их на работах и проектах, над которыми трудимся. Но в каждом приложении, когда приходит время проверки данных, мы скатываемся к изобретению колеса. Мы пишем и переписываем код заново, упуская возможность добавить его в наш инструментальный набор.

С другой стороны, сегодня все повернуты на XML. Использование расширяемого языка разметки оказалось сегодня более популярным, чем взлом ядра Linux, и это даже начальника заставляет радоваться. Как же совместить эти две вещи? XML и особенно схема XML являются прекрасным средством описания ограничений для данных Java. А при наличии простой среды на Java можно встраивать эти ограничения в объекты Java и сравнивать с ними данные приложения. В окончательном результате получаем гибкую, надежную среду, построенную на XML для всех случаев проверки данных Java.

В этой статье мы рассмотрим вопрос разбора схемы XML и построения набора ограничений. После того как ограничения можно будет использовать в программе на Java, мы остановимся на процессе сравнения данных с этими ограничениями. Наконец, в приложение будет встроено средство ввода данных и определения, какие ограничения следует установить на эти данные. Но прежде мы вспомним, что уже успели рассмотреть в этой серии.

Во вводной статье

в части 1, мы много говорили о проверке в общем. Были рассмотрены некоторые общераспространенные и неудачные практики, которые можно встретить в коде, в частности, случай жесткого задания ограничений в коде. Конечно, код при этом не может быть универсальным, поэтому мы рассмотрели несколько вспомогательных классов, например, класс ParameterParser Джейсона Хантера из Программирования Сервлетов Java. Этот класс позволяет выполнять простые преобразования формата String, в котором сервлеты получают данные различных других форматов Java, таких как int, float и boolean. Однако, в таком случае мы все еще на решили общих для проверки проблем, таких как проверка диапазона и указание ограничений перечислимого типа. В заключение возможным решением был назван XML и показано, почему документ XML превосходит стандартные файлы свойств Java.

В части 2 рассматривалась среда проверки. Опираясь на простые примеры, мы разработали четыре основных класса, необходимых в нашем коде:

Код класса Constraint был продемонстрирован полностью, с методами установки разрешенных значений, типа данных, наборов разрешенных величин. Если требовалось добавить дополнительные типы ограничений, например, сравнение по шаблону, их можно добавлять в этот класс. Также был рассмотрен класс Validator, где был опущен участок разбора схемы, о котором мы будем говорить в этой статье.

Теперь мы готовы перейти к деталям, не так ли? В этой статье мы начнем с разбора схем XML, и построения ограничений. Затем мы рассмотрим вопрос использования этих ограничений для проверки правильности ввода данных в классе Validator.

Разбор схемы

Для разбора схемы напишем класс schemaParser. Этот класс выполняет одну задачу: разбор схемы XML. В процессе разбора, он должен прочитать каждый атрибут схемы XML и создать для него экземпляр класса Constraint. Приведем пример простой схемы XML, чтобы освежить память. Этот пример все еще касается магазина обуви, который мы обсуждали в предыдущей статье, но имеет дополнительные ограничения:

<?xml version="1.0"?>

<schema targetNamespace="http://www.buyShoes.com"
         xmlns="http://www.w3.org/1999/XMLschema"
         xmlns:buyShoes="http://www.buyShoes.com"
 >

   <attribute name="shoeSize">
    <simpleType baseType="integer">
       <minExclusive value="0" />
      <maxInclusive value="20" />
    </simpleType>
   </attribute>

  <attribute name="width">
    <simpleType baseType="string">
       <enumeration value="A" />
      <enumeration value="B" />
      <enumeration value="C" />
      <enumeration value="D" />
      <enumeration value="DD" />
    </simpleType>
   </attribute>

  <attribute name="brand">
    <simpleType baseType="string">
      <enumeration value="Nike" />
      <enumeration value="Adidas" />
      <enumeration value="Dr. Marten" />
       <enumeration value="V-Form" />
      <enumeration value="Mission" />
    </simpleType>
  </attribute>>

  <attribute name="numEyelets">
    <simpleType baseType="integer">
      <minInclusive value="0" />
    </simpleType>
  </attribute>

</schema>

schemaParser должна проводить разбор файла из примера и создавать экземпляр класса Constraint для атрибута "shoeSize". Этот класс должен иметь тип данных "int". Заметим, что он не работает с "integer", потому что это тип данных схемы XML. Напротив, класс Constraint преобразует этот тип данных (используя класс DataConverter) в эквивалент на Java. Затем он получает значения 0 как минимальное (исключительно) и 20 как максимальное (включительно). В этом ограничении минимальное (исключительно), максимальное (включительно) и дозволенные значения не будут использоваться, так как они не указаны; другое ограничение может содержать дозволенные значения, и не содержать границ диапазона. Имея это в виду, начнем строить шаблон класса.

Шаблон класса schemaParser

Класс schemaParser имеет два метода public. Конструктор класса принимает java.net.URL, указывающий на схему XML для разбора. Этот метод должен затем запустить private-методы, которые выполнят разбор и построят ограничения. Когда по окончании разбора экземпляр класса будет создан, клиенту потребуется доступ к встроенным ограничениям. Для этого разрабатываются два метода: getConstraints(), который возвращает список объектов Constraint, полученных в результате разбора, и getConstraint(String constraintName), который возвращает Constraint для заданного имени (если он существует).

Ниже приводим шаблон этого класса. Он занимается вводом различных необходимых для задачи классов, описывает хранилище, которое будет использоваться методом parseschema(). После разработки шаблона мы рассмотрим способы выполнения реального разбора.

package org.enhydra.validation;

import java.io.IOException;
import java.net.URL;
import java.util.Map;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;

// JDOM classes used for document representation
import org.jdom.Attribute;
import org.jdom.Document;
import org.jdom.Element;
import org.jdom.JDOMException;
import org.jdom.Namespace;
import org.jdom.input.SAXBuilder;

import org.enhydra.validation.Constraint;

/**
 * <p>
 * Класс <code>schemaParser</code> разбирает схему XML и создает
 * из нее объекты <code>{@link Constraint}</code>.
 * </p>
 */
public class schemaParser {

    /** URL схемы */
    private URL schemaURL;

    /** Ограничения схемы */
    private Map constraints;

    /** пространство имен схемы XML */
    private Namespace schemaNamespace;

    /** URI пространства имен схемы XML */
    private static final String SCHEMA_NAMESPACE_URI =
        "http://www.w3.org/1999/XMLschema";

    /**
     * <p>
     * Создаем новый <code>schemaParser</code>, по
      * URL схемы.
     * </p>
     *
     * @param schemaURL <code>URL</code> схемы.
     * @throws <code>IOException</code> — по ошибке разбора.
     */
    public schemaParser(URL schemaURL) throws IOException {
        this.schemaURL = schemaURL;
        constraints = new HashMap();
        schemaNamespace =
             Namespace.getNamespace(SCHEMA_NAMESPACE_URI);

        // Разбор схемы и подготовка ограничений
        parseschema();
    }

    /**
     * <p>
     * Возврат ограничений, найденных в документе.
     * </p>
     *
     * @return <code>Map</code> — ограничения, описанные в схеме.
     */
    public Map getConstraints() {
        return constraints;
    }

    /**
     * <p>
     * Выборка объекта <code>Constraint</code> по
     * заданному имени. Если не найдено,
     * возвращается <code>null</code>.
     * </p>
     *
     * @param constraintName имя ограничения.
     * @return <code>Constraint</code> — ограничение для
     * заданного имени.
     */
    public Constraint getConstraint(String constraintName) {
        Object o = constraints.get(constraintName);
        if (o != null) {
            return (Constraint)o;
        } else {
            return null;
        }
    }

    /**
     * <p>
     * Работа по разбору схемы.
     * </p>
     *
     * @throws <code>IOException</code> — ошибка разбора.
     */
    private void parseschema() throws IOException {
        // Разбор схемы и построение ограничений
    }
}
    }

Пока все очевидно, не так ли? Следует заметить, что конструктор и метод класса parseschema() могут сгенерировать IOException при возникновении проблем. Это позволяет создать в воде средство сообщения об ошибках клиенту, использующему среду проверки. Это тип Exception, который может сгенерировать любой код на Java при использовании URL, поэтому в коде можно не проверять наличие такого типа ошибки; вместо этого они лишь вставляются в цепь вызовов.

Еще один важный момент, на который следует обратить внимание — переменная schemaNamespace. Эта переменная содержит объект JDOM Namespace для пространства имен схемы XML Если снова посмотреть на документ схемы XML (показанный выше), URI пространства имен схемы XML назначается по умолчанию. Это значит, что все элементы схемы без префикса (то есть все элементы) берутся из стандартного пространства имен, пространства схемы XML. Схема XML, приняв по умолчанию объект JDOM Namespace, поможет находить элементы в документе; в следующем разделе мы покажем, как все это работает вместе.

Имея шаблон, нам нужно теперь выполнить разбор схемы XML.

XML, схемы и JDOM

Ключом к построению класса schemaParser является возможность выполнять разбор схемы XML. Многие парзеры XML, такие как Apache Xerces, имеют опции для проверки схем; однако, не следует использовать эти опции. На деле нам вообще не хочется использовать схему как схему XML. Потому что все парзеры, по крайней мере в их текущем состоянии, используют специальные структуры для построения XML. В результате появляется неэкспортируемый код, враг любого программиста на Java.

Вместо этого класс schemaParser может рассчитывать на то, что документ схемы XML тоже является документом XML. Он соответствует правилам синтаксиса XML, и поэтому его можно рассматривать как произвольный документ XML. Поэтому парзер может читать схему XML как документ XML и работать с ним как с любым другим документом, с которым она может работать. Это то, что выполняет метод parseschema().

Используя модель JDOM, которую можно получить в Ресурсах, метод parseschema() использует сначала SAX для чтения URL схемы, и строит объект JDOM Document. Теперь на сцене появляется переменная schemaNamespace. Элемент attribute схемы XML представляет все необходимые ограничения, так что как только документ считан в память, ограничения, записанные в документе просто разыскиваются как именованные атрибуты в пространстве имен. Затем, каждый из найденных объектов (представленных объектом класса JDOM Element) передаются во вспомогательный метод handleAttribute(). Это выполняется следующим образом:

    /**
     * <p>
     * Разбор схемы.
     * </p>
     *
     * @throws <code>IOException</code> — по ошибке.
     */
    private void parseschema() throws IOException {
        /**
         * Создать объект генерации представления JDOM для схемы XML,
         * не прибегая к проверке в Apache Xerces.
         */
         SAXBuilder builder = new SAXBuilder();

        try {
            Document schemaDoc = builder.build(schemaURL);

            // Обработка атрибутов
            List attributes = schemaDoc.getRootElement()
                                          .getChildren("attribute",
                                                        schemaNamespace);
            for (Iterator i = attributes.iterator(); i.hasNext(); ) {
                // по всем узлам
                Element attribute = (Element)i.next();
                handleAttribute(attribute);
            }

            // обработка атрибутов сложных вложенных типов

        } catch (JDOMException e) {
            throw new IOException(e.getMessage());
        }
    }

Здесь также имеем понятный код, соответствующий разработанной концепции. Метод getChildren() возвращает список (Java List) элементов, удовлетворяющих заданному критерию; затем код проходит по всем элементам списка List, рассматривая каждый элемент, представляющий собой ограничение, запускает метод handleAttribute(). Теперь создадим этот метод, который выполняет эту работу.

Обработка атрибутов

Не станем долго задерживаться на методе класса handleAttribute(); теперь читатель понимает, как работает schemaParser и как просто работать с JDOM. Метод handleAttribute() получает от JDOM Element, который представляет ограничение на данные. Его задача — создать новое ограничение и добавить его к списку ограничений в экземпляре класса.

Сначала создается новый объект Constraint. Затем метод handleAttribute() начинает просматривать различные опции, которые может иметь это ограничение и извлекает данные для каждой опции. Если данные существуют, он устанавливает данные для экземпляра Constraint. Если нет, он просто переходит к опциям следующего ограничения. В показанном здесь методе обследуются и устанавливаются имена, типы данных, разрешенные значения и диапазоны этих данных:

    /**
     * <p>
     * преобразование атрибута в ограничениея.
     * </p>
     *
     * @throws <code>IOException</code> по ошибка разбора.
     */
    private void handleAttribute(Element attribute)
         throws IOException {

        // взять имя атрибута а создать Constraint
        String name = attribute.getAttributeValue("name");
        if (name == null) {
            throw new IOException("All schema attributes must have names.");
        }
        Constraint constraint = new Constraint(name);

        // проверить тип данных ограничения
        String schemaType = attribute.getAttributeValue("type");
        if (schemaType != null) {
            constraint.setDataType(
                 DataConverter.getInstance().getJavaType(schemaType));
        }

        // взять simpleType — если нет, закончили атрибут
        Element simpleType = attribute.getChild("simpleType", schemaNamespace);
        if (simpleType == null) {
            return;
        }

        // обработка типа данных
        schemaType = simpleType.getAttributeValue("baseType");
        if (schemaType == null) {
            throw new IOException(
	"No data type specified for ограничение " + name);
        }
        constraint.setDataType (DataConverter.getInstance().getJavaType(schemaType));

        // Обработка дозволенных величин
        List allowedValues = simpleType.getChildren(
		"enumeration", schemaNamespace);
        if (allowedValues != null) {
            for (Iterator i=allowedValues.iterator(); i.hasNext(); ) {
                Element allowedValue = (Element)i.next();
                constraint.addAllowedValue
	(allowedValue.getAttributeValue("value"));
            }
        }

        // Handle ranges
        Element boundary = simpleType.getChild("minExclusive", schemaNamespace);
        if (boundary != null) {
            Double value = new Double(boundary.getAttributeValue("value"));
            constraint.setMinExclusive(value.doubleValue());
        }
        boundary = simpleType.getChild("minInclusive", schemaNamespace);
        if (boundary != null) {
            Double value = new Double(boundary.getAttributeValue("value"));
            constraint.setMinInclusive(value.doubleValue());
        }
        boundary = simpleType.getChild("maxExclusive", schemaNamespace);
        if (boundary != null) {
            Double value = new Double(boundary.getAttributeValue("value"));
            constraint.setMaxExclusive(value.doubleValue());
        }
        boundary = simpleType.getChild("maxInclusive", schemaNamespace);
        if (boundary != null) {
            Double value = new Double(boundary.getAttributeValue("value"));
            constraint.setMaxInclusive(value.doubleValue());
        }

        // Сохранить ограничение
        constraints.put(name, constraint);
    }

Если необходимы другие ограничения, например шаблоны сравнения, или, возможно, более сложные типы данных, можно развить метод handleAttribute(). Для таких вещей, как сравнение по шаблону, надо будет добавить код для получения элемента шаблона pattern из ограничения и обработать его значение:

    Element pattern =
	simpleType.getChild("pattern", schemaNamespace);
    if (pattern != null) {
        String patternValue =
	pattern.getAttributeValue("value");
        // установить шаблон в объекте Constraint
    }

Надо внести также изменения в класс Constraint и добавить пару методов. Изменение типа данных, однако, вызывает изменения во вспомогательном классе, который здесь используется — DataConverter. Этот класс выполняет преобразование типа схемы XML в тип Java, например из integer (тип схемы) в int (тип Java). В DataConverter можно добавить новый тип данных, возможно, когда схема XML станет более развитой или увеличатся потребности пользователя. DataConverter, само собой, включен в исходный код, доступный для загрузки с этой статьей.

После завершения работы этого метода, работа конструктора класса schemaParser также завершена, и управление передается вызвавшей программе. В этот момент (исходный конструктор Validator) может использовать методы getConstraints() или getConstraint() для получения данных ограничения и работать с ними. На деле, это и есть задача, решаемая методом класса Validator isValid()! Мы к этому еще вернемся.

Проверка правильности данных

Итак, осталось рассмотреть главный интерфейс, класс Validator. Это тот самый класс, с которым будет работать клиент, ведь класс schemaParser будет скрыт от клиента. В частности, клиент будет вызывать метод isValid(), чтобы проверить соответствие определенных значений заданным ограничениям. Метод используется следующим образом:

    String shoeSize =
 	req.getParameterValue("shoeSize");
    if (!Validator.getInstance().isValid(
	shoeSize, "shoeSize")) {
        // Сообщить об ошибке клиенту
    }

    // Продолжить обработку с данным размером ботинок

Так просто все и будет работать — задать значение (в формате String), сообщить имя ограничения для проверки. isValid() вернет заключение о правильном или неправильном вводе данных для указанного ограничения. Этот результат можно использоваться для того, чтобы либо сообщить клиенту об ошибке, либо о том, что он может продолжить работу с данными с уверенностью, что они удовлетворяют ограничениям, заданным в схеме XML.

Метод isValid() в действительности не является очень сложным, поскольку вся работа по получению ограничений на данные была выполнена в классе schemaParser. Сначала, этот метод получает объект Constraint для заданного имени ограничения; если ограничений для имени не существует, возвращается значение true. В основном, ни одно из ограничений не соответствует (в данной реализации) проверяемым данным. Вариантом реализации этого метода может быть генерирование Exception или выполнение других действий, необходимых для обработки ошибки.

После получения объекта Constraint из класса schemaParser, начинается проверка данных. Следующий код демонстрирует применение этого метода с пояснениями в комментариях вместо кода проверки. Ниже мы коснемся каждого из них по очереди.

    /**
     * <p>
     * проверка значения данных (
     * в формате <code>String</code>) на соответствие
     * определенным ограничениям, если есть соответствие,
     * возврат <code>true</code>.
     * </p>
     *
     * @param constraintName идентификатор ограничения на данные.
     * @param data <code>String</code> — данные для проверки.
     * @return <code>boolean</code> -
     * соответствуют или нет данные ограничениям.
     */
    public boolean isValid(String constraintName, String data) {
        // проверить по правильному ограничению
        Object o = constraints.get(constraintName);

        // если нет ограничения, то правильные данные
        if (o == null) {
            System.out.println(
		"No constraint found for " + constraintName);
            return true;
        }
        Constraint constraint = (Constraint)o;

        // проверка типа данных

        // проверка разрешенных значений

        // проверка диапазона

        // если мы здесь, проверка завершена успешно
        return true;
    }

Опять же, здесь нет ничего необычного!? Стоит отметить, что здесь продемонстрированы также некоторые основные принципы дизайна. Возможно, читатель скажет, "Ну да, это же невероятно просто. Неужели автору платят за это?" Да, платят! (<grin/>) Если серьезно, для этой серии статей пришлось создать много строк кода, и я проделал рассуждения в точности в той последовательности, в которой я его создавал. Если поместить весь код в одну библиотеку, он будет выглядеть гораздо более сложно. Автору приходит масса писем с вопросом, "Не могли бы Вы выслать коды ? Я прочел часть 2, но этого недостаточно для разработки." По мнению автора, можно написать весь необходимый код в том же порядке, в котором следует его части в данной серии. Какой здесь можно сделать вывод? Следует начать с дизайна (части 1 и 2) и кодировать клиентский интерфейс (часть 2). Затем заполнить один за другим пробелы части 3, этой статьи. Наконец, надо проверить работу классов и добавить необходимые усовершенствования (часть 4, в следующем выпуске). В заключении этого процесса, разработчик будет приятно удивлен значительным улучшением программного обеспечения.

Рассмотрим, наконец, специфические вопросы проверки, заключенные в методе isValid().

Типы данных

Прежде всего, проверяется тип данных. Это делается простым вызовом вспомогательного метода correctDataType. Мы не приводим его, поскольку он занимает много места и несет мало информации. Он берет тип данных вызовом метода getDataType() класса Constraint, и преобразовывает данные типа String в полученный тип. Если преобразование безуспешно, метод явно возвращает false. Иначе, данные считаются правильными (по крайней мере с точки зрения типа), и метод возвращает true. Покажем участок кода для проверки правильности типа данных:

        // проверка типа данных
        if (!correctDataType(data, constraint.getDataType())) {
            return false;
        }

Разрешенные значения

Проверка разрешенных значений выполняется еще проще. Экземпляр Constraint проверяется на существование списка разрешенных значений в ограничении. Если есть, выбираются значения, в виде списка Java List, вызовом метода getAllowedValues(). Затем выполняется проверка на предмет наличия полученных данных в этом списке значений. Если да, то проверка может продолжаться, однако, если значения не найдены, выполнение прерывается и возвращается false. Приводим пример такой функциональности:

        // проверка разрешенных значений
        if (constraint.hasAllowedValues()) {
            List allowedValues = constraint.getAllowedValues();
            if (!allowedValues.contains(data)) {
                return false;
            }
        }

Одно замечание: следует внимательно использовать метод getAllowedValues(). Надо помнить, что проверка является в этом случае зависимой от регистра. Если необходимо сделать сравнение независимым от регистра символов, когда строчные буквы считается эквивалентными прописным, придется самостоятельно обойти весь список. Для каждого значения, надо будет выполнить метод equalsIgnoreCase() над java.lang.String и убедиться, что значения равны без учета регистра символов. Это одно из видоизменений, которое может быть полезным в прикладном коде.

Проверка диапазона

Последний участок проверки правильности данных заключается в выполнении проверки диапазона. Эта проверка немного хитрее, так как схема XML обеспечивает два типа минимальных значений (включительное и исключительное) и два типа максимальных значений (опять же, включительное и исключительное). Если при этом возникает желание вычесть или прибавить очень малое число к минимальной и к максимальной границам соответственно, с последующим вызовом floor и ceil, при этом можно потерять точность. Это слишком опасно, так как значения могут оказаться не очень точными. Вместо этого следует использовать различные операнды для каждой проверки:

Граница Оператор
Минимум (Исключительно) <=
Минимум (Включительно) <
Минимум (Включительно) >=
Максимум (Включительно) >

Конечно, такие эти операции должны работать только с числовыми величинами. Для этого значение String сначала преобразуется в double. Следующий код выполняет проверку диапазона:

        // проверка диапазона
        try {
            double doubleValue = new Double(data).doubleValue();
            if (constraint.hasMinExclusive()) {
                if (doubleValue <= constraint.getMinExclusive()) {
                    return false;
                }
            }
            if (constraint.hasMinInclusive()) {
                if (doubleValue < constraint.getMinInclusive()) {
                    return false;
                }
            }
            if (constraint.hasMaxExclusive()) {
                if (doubleValue >= constraint.getMaxExclusive()) {
                    return false;
                }
            }
            if (constraint.hasMaxInclusive()) {
                if (doubleValue > constraint.getMaxInclusive()) {
                    return false;
                }
            }
        } catch (NumberFormatException e) {
            // если преобразование в число невозможно, тип данных все равно
            // не численный, проверка уже закончилась бы неудачно,
            // поэтому можно игнорировать исключение.
        }

Верьте или нет, но мы сделали все, что хотели! Метод isValid() завершен, а это означает, что завершен класс Validator. Клиентская часть имеет теперь возможность импортировать несколько классов и использовать рассмотренную здесь среду проверки. Хотя может показаться, что мы достигли конца пути, не самом деле это не так. Во-первых, надо сказать о некоторых изменениях в коде (основанных на большом количестве отзывов), которые не были показаны здесь. Во-вторых, у существуют варианты по развитию этой серии, то есть мы вернемся к обсуждению этой темы через месяц.

Развитие API

Классы проверки правильности постоянно изменяются, как и любой другой код. Со времени написания последней статьи я получил множество откликов. Среди них было немного полезных писем от людей, работавших с моим кодом и исправивших несколько тонких ошибок. Метод не был синхронизирован, где следовало, сравнивались числовые значения с константами Double.NaN (эта проверка никогда не вернет true) и несколько других. Это здорово, так как это улучшает код, и это одно из преимуществ открытого кода! В любом случае, я сделал эти исправления, а также внес свои, получив обновленный исходный код, который можно загрузить из раздела Ресурсы. Если читатель работает с кодом последней статьи, ему следует взять обновления. И, если все пойдет хорошо, мы откроем еще больше пикантных моментов в следующей статье, а код снова будет обновлен!

Заключение

Будем надеяться, читатель получил удовольствие от заполнения пустот в шаблоне среды, оставшихся от последней статьи. Теперь код стал многоцелевым и может быть использован многими приложениями. Однако, еще можно сделать несколько улучшений. Когда возникает ошибка проверки, возвращается простое значение false, по которому нельзя определить, в чем была проблема. Это очевидно является недостатком, так как любая хорошая программа должна не только проверять данные, но также информировать клиента об ошибках, возникших при обработке данных. Кроме того, мы до сих пор не испробовали реальный пример работы кода. По этим причинам, JavaWorld согласился расширить эту серию еще одной частью. В следующей, и последней (обещаю!) статье, будут раскрыты способы изменения кода для обеспечения информации о возникающих ошибках. Мы исследуем простую структуру исключений Exception для кода и обсудим вопрос ее использования для лучшей обработки ошибок. В заключении, мы рассмотрим реальный пример, использующий сервлеты совместно со средой проверки. До встречи на страницах журнала.

Об авторе

Бретт МакЛафлин — стратег по Enhydra в Lutris Technologies, специализирующийся на архитектурах распределенных систем. Он является автором Java and XML и работает с такими технологиями как сервлеты Java, технология Enterprise JavaBeans, XML, приложения бизнес-ту-бизнес. Недавно он организовал проект JDOM совместно с Джейсоном Хантером, в котором разработал простой API для работы с XML из приложений Java. МакЛафлин активно участвует в разработке проекта Apache Cocoon и сервера EJBoss EJB, и является сооснователем проекта Apache Turbine.

Ресурсы

Интересует JDOM? Читайте статьи JavaWorld:

Reprinted with permission from the November 2000 edition of JavaWorld magazine. Copyright © ITworld.com, Inc., an IDG Communications company.
View the original article at: http://www.javaworld.com/ javaworld/jw-11-2000/jw-1110-validation3.html

[an error occurred while processing this directive]
[an error occurred while processing this directive] Перевод на русский © Андрей Ковалев, к.т.н., доцент МИЭТ, 2000
< Вернуться на caйт :: Copyright © 1999 — 2010, IT • archiv.