[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 сервлетов с использованием Reflection. Часть 1

[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)

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

Code Tutorial
PDF versionPDF версия
Обзор
Используя этот платформо-независимый каркас, можно легко использовать удобные объектно-ориентированные концепции программирования, такие как инкапсуляция, на стороне сервера. Майкл выбрал использование сервлетов в примере этого каркаса из-за их доступности и применимости. Любая другая серверная платформа (например, CORBA, RMI, Netscape Application Server) может применима в этом каркасе с минимальным количеством замены кода. (1500 слов)

Скрипты стандартного интерфейса обмена данными (CGI), языки подобные Perl, могут иметь также много возможностей, как и Java Servlet API, но сервлеты существенно превосходят по скоростным и динамическим характеристикам их CGI кузенов, если сравнивать их функциональные возможности.

Многие разработчики, кто сделал переход от создания CGI сценария к Java сервлетам, продолжили стиль программирования CGI и в Java, даже при том, что этот стиль не может быть наиболее эффективным вариантом для них. Рассмотрите этот пример: программисты обычно используют сервлеты, чтобы интерпретировать ввод в окно Web броузера, определить соответствующий образ действия, и затем выдать результат пользователю. Процесс работы сервлета таким образом четырехкратен: управление, бизнес логика, доступ к данным, и вывод результата. В каркасе CGI, единственный CGI сценарий управлял этим полным процессом. Те кто продолжают программировать в стиле CGI часто создают монолитные сервлеты, чтобы управлять всеми четырьмя из этих действий.

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

Краткий обзор Каркаса

Действия, обычно выполняемые в модели запроса-ответ имеют четыре общих характеристики:

Этот каркас не зависит от наличия Java сервлетов. Все что требуется — это соглашение среди разработчиков о том какие объекты применять. Некоторые разработчики должны быть ответственны за код контроллера, который может быть сервлетом, CORBA или RMI сервером, или Netscape Application Server AppLogics. Другая команда разработчиков не должна быть обеспокоенна относительно способа выполнения компонентов контроллера; им требуется знать только методы, которые есть у контроллера.

Как создать каркас сервлетов?

Вы можете создать сервлет каркас, назначив обязанности для различных элементов системы. Это в свою очередь требует установления интерфейсов. Границы между составными группами должны быть проведены так, чтобы никакой объект одной группы не мог использоваться любым объектом вне этой группы. Например, убедитесь, что никакой платформо-зависимый объект (вроде HttpservletRequest) или метод не используется любым другим компонентом входящим в состав контроллера.

Система с сегментной организацией может быть полностью автономной. Например, команда, разрабатывающая компоненты данных может работать на поддержание следующего интерфейса (простой случай), или чего-то подобного:

public interface DataInterface
{
 public void initializeDataObject();
 public void beginTransaction();
 public void commitTransaction();
 public void rollbackTransaction();
 public void executeSQL(String sqlString);
}

Это — простой интерфейс для регистрации действий пользователя или ввода пользователя в базу данных. Так как все DataObjects должны удовлетворять DataInterface, один объект может выполниь все задачи связанные со взаимодействием с базой данных. И никакой компонент вне функциональности обработки данных не должен иметь дело с connection pooling или параметрами базы данных.

Точно так же можно создать объекты для управления задачами связанными с выдачей результатов, использующими интерфейс, подобный следующему:

public interface PresentationInterface { public void initializePresentation(ProxyInterface proxy) throws IOException; public void output(String text) throws IOException; public void finalizePresentation() throws IOException; }

Запомните, что этот интерфейс встраивается в любой объект, ответственным за вывод результата. Также уточните разницу между двумя интерфейсами. PresentationInterface содержит метод с параметром, называемым PresentationService. PresentationServicesInterface — это ключ к каркасу, поскольку это — контроллер в каркасе.

Реализация ProxyInterface- это простой путь взаимодействия для всех платформ-зависимых функциональных возможностей. Объект Presentation не должен знать особенности реализации уровня, вывода результата. Будь то апплет, сервлет, или сокет, методы интерфейса должны быть реализованы.

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

public interface ProxyInterface
 {
  public DataInterface
               getDataObject(String name);
  public PresentationInterface
               getPresentationObject(String name);
  public BusinessInterface
               getBusinessObject(String name);
 }

Так как этот интерфейс совершенно универсален, то он может использоваться как прокси для запросов, реализованных при помощи сервлетов или других серверных программам, типа Netscape Application Server's AppLogics. Задача состоит в том, чтобы создать структуру такой, чтобы вся информация, характерная для платформы развертывания содержалась в реализации ProxyInterface, или в малом подмножестве классов. Это позволит разработчикам писать код независимый от собственных методов или переменных, таким образом увеличивая эффективность команды разработчиков.

Последний компонент нашего расширяемого каркаса — BusinessInterface:

public interface BusinessInterface
 {
  public void init
     (ProxyInterface proxy, Hashtable parameters)
     throws Exception;
 }

Обращение к этому интерфейсу происходит для каждого запроса, сделанного к каркасу. Этот интерфейс содержит метод через который входные параметры проходят от сервлета к бизнес объекту. Кроме того, к нему передается прокси, чтобы снабдить его средствами, необходимыми для выполнения его задачи.

Мы создали каркас через который мы можем пропускать бизнес объекты, для выполнения индивидуальных запросов пользователей — включая все данные и проблемы выдачи результата — без знаний индивидуальной платформы, на которой они постоянно находятся. Теперь, как мы узнаем, какой бизнес объект загрузить?

Динамическая загрузка бизнес объектов

Java Reflection API обеспечивает простой механизм для реализации этого каркаса. В этой первой части нашей серии, сам Reflection не используется. Пока, мы будем использовать метод class.forName (...) для загрузки соответствующего бизнес объекта:

private static BusinessInterface
  loadBusinessObject(String actionName)
  {
   BusinessInterface bi = null;

   try
   {
    // attempt to retrieve the class from the class loader
    Class c = Class.forName(actionName + BUSINESS_OBJECT);

    // Initialize a class array
    // with no elements (used in the constructor)
    Class[] parameterTypes = new Class[0];

    // Locate the constructor with no arguments
    Constructor constructor =
     c.getConstructor(parameterTypes);

    // Initialize an object array with
    // no elements (used in the newInstance method)
    Object[] initargs = new Object[0];

    // Load the new instance of
    // the business interface implementor
    bi = (BusinessInterface)
    constructor.newInstance(initargs);

   }
   catch (Exception e)
   {
    // If there is an error,
    // create an ErrorBusinessObject (for now)
    bi = (BusinessInterface) new ErrorBusinessObject();

    e.printStackTrace();
   }

   return bi;
  }

Этот метод содержится в классе BusinessObjectFactory и динамически загружает бизнес объект, основанный на названии действия, полученным от прокси. В случае, если происходит исключительная ситуация, создается объект для управления аварийной ситуацией. В этом примере эту обработку берет на себя конструктор по умолчанию, но он может быть адаптирован к любым условиям.

Есть две главные выгоды в загрузке бизнес объектов динамически: во-первых, вы избежите шага регистрации, во-вторых, сможете добавлять функциональные возможности в приложение на лету. Оба из этих преимуществ происходят от того, что не имеется никакой потребности в определении аппаратного ядра возможных действий, содержащихся в сервлете.

В части 2 из этой серии, я буду подробно останавливаться на преимуществах Reflection API и покажу несколько перимуществ от применения этого каркаса. Reflection позволит сократить код при большом увеличении функциональных возможностей.

Пример каркаса

Чтобы завершить объяснение этого каркаса, я создал простой пример, используя интерфейсы и класс Factory, обсужденный выше. В этом примере сервлет используется как контроллер, интерфейс данных, и интерфейс выдачи результата. Пример использует чрезвычайно простые бизнес объекты которые показывают динамическое поведение, содержащееся в сервлетах, но не содержат законченные функциональные возможности системы, так как это лежит вне возможностей этой статьи.

Метод service класса Proxyservlet- это основа каркаса:

public void service
    (HttpservletRequest req, HttpservletResponse res)
    throws servletException, IOException
  {
   // convert the request into a hashtable
   Hashtable requestHT = getHashtableFromRequest(req);

   // retrieve the actionName from the hashtable
   actionName = getCurrentAction(requestHT);

   // Create a business Object
   BusinessInterface bi = getBusinessObject(actionName);

   try
   {
    // Initialize the business object
    bi.init( (ProxyInterface) this, requestHT);
   } catch (Exception e)
   {
   // Any exception handling code goes here
   }
  }

В коде приведенном выше, сервлет преобразует HttpservletRequest в простую hashtable содержащую пары названия-значения. Потом находит в ней actionName и создает реализацию BusinessInterface. На заключительном этапе инициализирует BusinessInterface и запускает его, это позволит в дальнейшем выполнить любую необходимую обработку.

Этот простой пример игнорирует часть которая может быть в методе service. Выполнение этой обработки может быть передано сервлету или бизнес объекту через методы в прокси интерфейсе. Это решение принимает разработчик по мере необходимости при реализации проекта.

Обработка ошибок

Одна ключевая вещь, которую необходимо запомнить в вышеупомянутом отрывке кода, это блок try-catch окружающий метод init объекта BusinessInterface. Этот try-catch блок фактически гарантирует, что вся обработка ошибок может быть выполнена в пределах контроллера. Это позволяет разработчикам управлять незначительными исключительными ситуациями в пределах их бизнес объекта и передавать важные исключения выше, чтобы гарантировать, что все исключительные ситуации будут обработаны вместе.

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

Выводы

Эта статья описала выгоды от использования каркаса при разработке серверного кода, который поддерживает модель реакции на запрос, связанную с Servlet API. При этом я представил значение независимого от платформы каркаса и места для единственного размещения обработки ошибок. Я также сослался на выгоды, о которых я буду говорить в части 2, доступные при помощи настоящего Reflection.

Использование этого каркаса позволяет разработчикам эффективно проектировать объектно-ориентированное, серверное решение без привязки к конкретной платформе. Это обеспечивает ключевые выгоды если вы хотите добавить новые возможности к системе, или если вы позже решите портировать это на другое серверное решение.

Добавление новых характеристик в систему не требует синхронизации с базовым кодом, так как нет ничего жестко закодированного. Сервлет обработает любую дополнительную бизнес логику путем динамической загрузки класса.

Общий обработчик ошибок каркаса необходим при разработке, ориентированной на сервлет, потому что это гарантирует, что пользовательский опыт на Web сайте будет непротиворечивым и общим ко всем функциональным возможностям, содержащимся на этом сайте. Единственный компонент отвечающий за обработку ошибок также выгоден разработчикам, потому что это позволяет им избежать построения обработчиков ошибок в каждом объекте.

Этот каркас, в свою очередь, страдает от некоторых накладных расходов из-за изоляции компонентов, но это гарантирует, что не имеется никаких перекрестных зависимостей.

Вторая часть этой части продемонстрирует приложения этого каркаса, расширенного использованием кодом Reflection, чтобы осуществить валидацию на стороне сервера, обработку ошибок, доступ к данным, и выдачу результата.

Об авторе

Майкл Цимерман — консультант, специализирующийся в решениях, основанные на Java / Internet. Майкл предоставляет Java/Internet архитектуры и разработки для компаний, входящих в состав Fortune 500.

Ресурсы

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

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