В данной лекции мы рассмотрим техники разработки компонентов Web-приложений на основе платформ J2EE и .NET. Общая архитектура такого приложения может быть представлена схемой, изображенной на рис. 14.1. Обе платформы предоставляют специальную поддержку для разработки компонентов на двух уровнях: уровне интерфейса пользователя (WebUI) и уровне связи с данными.
(рис 14.1) Общая схема архитектуры Web-приложений J2EE и .NETПользовательский интерфейс Web-приложений основан на генерации
Основные отличия между техниками разработки компонентов этих двух уровней, используемыми в рамках J2EE и .NET, можно сформулировать следующим образом.
В .NET нет специально выделенного вида компонентов, предназначенного для реализации бизнес-логики — она может реализовываться с помощью обычных классов, что часто удобнее. Это положение должно измениться с выходом EJB 3.0.
В .NET-приложениях все предлагаемые способы представления данных являются объектными обертками вокруг реляционного представления — в любом случае приходится работать с данными как с набором таблиц. В .NET нет автоматической поддержки их преобразования в систему взаимосвязанных объектов и обратно.
В рамках приложений, построенных по технологии J2EE, связь с базой данных и бизнес-логику, скрытую от пользователя, принято реализовывать с помощью компонентов Enterprise
Возможны и другие способы реализации этих функций. Например, бизнес-логика может быть реализована непосредственно в методах объектов пользовательского интерфейса, а обмен данными с базой данных — через интерфейс JDBC. При этом, однако, теряется возможность переиспользования функций бизнес-логики в разных приложениях на основе единой базы данных, а также становится невозможным использование автоматических транзакций при работе с данными. Транзакции в этом случае нужно организовывать с помощью явных обращений к
Для разработки набора
Правила создания
Представляют данные приложения и основные методы работы с ними.
Представляют независимую от пользовательского интерфейса и конкретных типов данных логику работы приложения, называемую иногда бизнес-логикой.
Тоже предназначены для реализации бизнес-логики. Но, если
Далее описываются основные правила построения
Этот интерфейс декларирует методы компонента, к которым можно обращаться удаленно, т.е. из компонентов, работающих в рамках другого процесса или на другой машине.
Удаленный интерфейс должен наследовать интерфейс javax.ejb.EJBObject (в свою очередь, наследующий java. ).
Для getName()/void setName(Type) ), служащих для работы с отдельными полями данных или компонентами, связанными с этим компонентом по ссылкам. Это могут быть и часто используемые дополнительные операции, как-то выражающиеся через операции с отдельными полями данных, в том числе и вычислимые свойства. Например, для книги в базе данных приложения хранится набор ссылок на данные об ее авторах, а число авторов может быть часто используемым свойством книги, вычисляемым по этому набору ссылок.
Для
По назначению этот интерфейс полностью аналогичен удаленному, но декларирует методы компонента, которые можно вызывать только в рамках того же процесса. Этот интерфейс служит для увеличения производительности приложений, в которых взаимодействия между компонентами происходят в основном в рамках одного процесса. При этом они могут использовать локальные интерфейсы друг друга, не привлекая сложный механизм реализации удаленных вызовов методов. Однако при использовании локального интерфейса компонентаo нужно обеспечить развертывание этого компонента в рамках того же
Локальный интерфейс должен наследовать интерфейсу javax.ejb.EJBLocalObject.
Исходные интерфейсы служат для поиска и создания компонентов. Такой интерфейс может декларировать метод поиска findByPrimaryKey(…) и метод создания такого компонента с указанным значением первичного ключа create(…). Могут быть также определены методы, создающие компонент по набору его данных или возвращающие коллекцию компонентов, данные которых соответствуют аргументам такого метода. Например, метод, создающий компонент, который представляет книгу с данным названием, createByTitle(String title), или метод, находящий все книги с данным набором авторов Collection findByAuthors(Collection authors).
Удаленный исходный интерфейс предназначен для создания и поиска компонентов извне того процесса, в котором они работают. Его методы возвращают ссылку на удаленный интерфейс компонента или коллекцию таких ссылок.
Такой интерфейс должен наследовать интерфейсу javax.ejb.EJBHome (являющемуся наследником java. ).
Имеет то же общее назначение, что и удаленный исходный интерфейс, но служит для работы с компонентами в рамках одного процесса. Соответственно, его методы поиска или создания возвращают ссылку на локальный интерфейс компонента или коллекцию таких ссылок.
Должен наследовать интерфейсу javax.ejb.EJBLocalHome.
Этот класс реализует методы удаленного и локального интерфейсов (но не должен реализовывать сами эти интерфейсы!). Он определяет основную функциональность компонента.
Для javax.ejb.EntityBean. Свойства, соответствующие полям хранимых данных или ссылкам на другие getName()/setName(). В этом случае
Для javax.ejb.SessionBean и все методы удаленного и локального интерфейсов.
Кроме того, класс компонента может (а иногда и должен) реализовывать некоторые методы, которые вызываются
Например, при ejbCreate(). Для null и всегда должен быть реализован в классе компонента. Для void, а на вход принимает какие-то параметры, служащие для createSomeSuffix(…) в классе компонента должен быть реализован
метод ejbCreateSomeSuffix(…) с теми же типами параметров. Для void.
Другие методы жизненного цикла компонента, которые можно перегружать в классе компонента, декларированы в базовых интерфейсах компонентов соответствующего вида ( javax.ejb.EntityBean или javax.ejb.SessionBean ). Это, например, ejbActivate() и ejbPassivate(), вызываемые при активизации и деактивизации экземпляра компонента; ejbRemove(), вызываемый перед удалением экземпляра компонента из памяти; для ejbStore() и ejbLoad(), вызываемые при сохранении данных экземпляра в базу приложения или при их загрузке оттуда.
Схема жизненного цикла
Жизненный цикл
(рис 14.2) Жизненный цикл EJB компонента данных
Схема жизненного цикла ejbCreate() сразу переводит компонент в активное состояние.
(рис 14.3) Жизненный цикл сеансового компонента с состояниемЖизненный цикл
Декларируется только для
Определяет набор данных, которые образуют первичный ключ записи базы данных, соответствующей одному экземпляру компонента.
Чаще всего это библиотечный класс, например, String или Integer. Пользовательский класс необходим, если первичный ключ составной, т.е. состоит из нескольких значений простых типов данных. В таком классе должен быть определен конструктор без параметров и правильно перегружены методы equals() и hashCode(), чтобы java.io.Serializable.
(рис 14.4) Жизненный цикл сеансового компонента без состоянияНиже приведены примеры декларации класса компонента и интерфейсов для
В рамках этой схемы, состоящей из таблиц, где хранятся данные книг и организаций-издателей, каждая книга связана с одним и только одним издателем, а каждый издатель может иметь ссылки на некоторое множество книг (возможно, пустое). Каждая таблица имеет поле ID, являющееся первичным ключом. Таблица Book имеет поле PublisherID, содержащее значение ключа записи об издателе данной книги.
(рис 14.5) Пример схемы БДПримеры кода удаленных интерфейсов для компонентов, представляющих данные о книгах и издателях в рамках EJB-приложения:
package ru.msu.cmc.prtech.examples;
import java.rmi.RemoteException;
import java.util.Collection;
import javax.ejb.EJBObject;
public interface PublisherRemote extends EJBObject
{
public String getTitle () throws RemoteException;
public void setTitle (String title) throws RemoteException;
public Collection getBooks ()throws RemoteException;
public void setBooks (Collection books)
throws RemoteException;
public void addBook (String title, String isbn)
throws RemoteException;
public void removeBook (String title, String isbn)
throws RemoteException;
}
package ru.msu.cmc.prtech.examples;
import java.rmi.RemoteException;
import javax.ejb.EJBObject;
public interface BookRemote extends EJBObject
{
public String getTitle () throws RemoteException;
public void setTitle (String title) throws RemoteException;
public String getISBN () throws RemoteException;
public void setISBN (String isbn) throws RemoteException;
public PublisherRemote getPublisher () throws RemoteException;
public void setPublisher (PublisherRemote publisher)
throws RemoteException;
}
Примеры кода удаленных исходных интерфейсов.
package ru.msu.cmc.prtech.examples;
import java.rmi.RemoteException;
import javax.ejb.CreateException;
import javax.ejb.EJBHome;
import javax.ejb.FinderException;
public interface PublisherHomeRemote extends EJBHome
{
public PublisherRemote create (Integer id)
throws CreateException, RemoteException;
public PublisherRemote findByPK (Integer id)
throws FinderException, RemoteException;
}
package ru.msu.cmc.prtech.examples;
import java.rmi.RemoteException;
import javax.ejb.CreateException;
import javax.ejb.EJBHome;
import javax.ejb.FinderException;
public interface BookHomeRemote extends EJBHome
{
public BookRemote create (Integer id)
throws CreateException, RemoteException;
public BookRemote createBook (String title, String isbn)
throws CreateException, RemoteException;
public BookRemote findByPK (Integer id)
throws FinderException, RemoteException;
}
Примеры кода классов компонентов. Показано, как реализовывать дополнительные, не поддерживаемые контейнером автоматически, методы работы со связями между данными об издателях и книгах и дополнительные методы создания компонентов.
package ru.msu.cmc.prtech.examples;
import java.util.Collection;
import java.util.Iterator;
import java.rmi.RemoteException;
import javax.ejb.CreateException;
import javax.ejb.EntityBean;
import javax.naming.InitialContext;
import javax.naming.NamingException;
public abstract class PublisherBean implements EntityBean
{
public Integer ejbCreate (Integer pk)
{
setId(pk);
return null;
}
public void ejbPostCreate (Integer pk) { }
public abstract Integer getId ();
public abstract void setId (Integer pk);
public abstract String getTitle ();
public abstract void setTitle (String title);
public abstract Collection getBooks ();
public abstract void setBooks (Collection books);
public void addBook (String title, String isbn)
{
try
{
InitialContext context = new InitialContext();
BookHomeRemote bookHome =
(BookHomeRemote)context.lookup("BookHomeRemote");
BookRemote book = bookHome.createBook(title, isbn);
Collection books = getBooks();
books.add(book);
}
catch (NamingException e) { e.printStackTrace(); }
catch (CreateException e) { e.printStackTrace(); }
catch (RemoteException e) { e.printStackTrace(); }
}
public void removeBook (String title, String isbn)
{
Collection books = getBooks();
Iterator it = books.iterator();
try
{
while(it.hasNext())
{
BookRemote book = (BookRemote)it.next();
if( book.getTitle().equals(title)
book.getISBN().equals(isbn)
)
{
it.remove();
break;
}
}
}
catch (RemoteException e) { e.printStackTrace(); }
}
}
package ru.msu.cmc.prtech.examples;
import javax.ejb.EntityBean;
public abstract class BookBean implements EntityBean
{
public Integer ejbCreate (Integer pk)
{
setId(pk);
return null;
}
public void ejbPostCreate (Integer pk) { }
public Integer ejbCreateBook (String title, String isbn)
{
setTitle(title);
setISBN(isbn);
return null;
}
public void ejbPostCreateBook (String title, String isbn) { }
public abstract Integer getId ();
public abstract void setId (Integer pk);
public abstract String getTitle ();
public abstract void setTitle (String title);
public abstract String getISBN ();
public abstract void setISBN (String isbn);
public abstract PublisherRemote getOrganization ();
public abstract void setOrganization (PublisherRemote pr);
}
javax.jms.MessageListener. Вместе с этим интерфейсом класс javax.ejb.MessageDrivenBean.
Первый интерфейс требует определения метода void onMessage(javax.jms.Message), который разбирает содержимое пришедшего сообщения и определяет способ его обработки. Кроме того, нужно определить методы void ejbCreate() для создания компонента и void ejbRemove() для освобождения ресурсов при его удалении.
Жизненный цикл
Пример реализации класса
package ru.msu.cmc.prtech.examples;
import javax.ejb.EJBException;
import javax.ejb.MessageDrivenBean;
import javax.ejb.MessageDrivenContext;
import javax.jms.MapMessage;
import javax.jms.Message;
import javax.jms.MessageListener;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
public class TransferProcessorBean
implements MessageDrivenBean, MessageListener
{
Context context;
public void setMessageDrivenContext (MessageDrivenContext mdc)
throws EJBException
{
try { context = new InitialContext(); }
catch (NamingException e) { throw new EJBException(e); }
}
public void ejbCreate() { }
public void onMessage (Message msg)
{
MapMessage message = (MapMessage)msg;
try
{
Integer publisherPK = (Integer)message.getObject("Publisher");
String title = (String)message.getObject("Title");
String isbn = (String)message.getObject("ISBN");
PublisherHomeRemote publisherHome =
(PublisherHomeRemote)context.lookup("PublisherHomeRemote ");
PublisherRemote publisher = publisherHome.findByPK(publisherPK);
publisher.addBook(title, isbn);
}
catch (Exception e) { throw new EJBException(e); }
}
public void ejbRemove () throws EJBException
{
try { context.close(); }
catch (NamingException e) { }
}
}
Помимо декларации интерфейсов и классов компонентов, для построения
Чаще всего дескрипторы развертывания не пишут вручную, их готовят с помощью специализированных инструментов для развертывания J2EE-приложений или сред разработки (например, такими возможностями обладает среда NetBeans 4.0 [3]). Здесь мы опишем только часть содержимого
Заголовок
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE ejb-jar PUBLIC "-//Sun Microsystems, Inc.//DTD Enterprise JavaBeans 2.0//EN"
http://java.sun.com/j2ee/dtds/ejb-jar_2_1.dtd">
<ejb-jar>Обязательный элемент.
Это корневой тег
<enterprise-beans>Обязательный элемент, должен появиться внутри <ejb-jar> ровно один раз.
Содержит набор описаний отдельных <entity>, <session>, <message-driven>.
<entity> и <session>Эти теги вложены в тег <enterprise-beans> и служат для описания, соответственно,
<ejb-name>Требуется ровно один.
Задает имя компонента.
<home>Необязателен, начиная с EJB 2.0. В EJB 1.1 требуется ровно один.
Указывает полное имя удаленного исходного интерфейса.
<remote>Необязателен, начиная с EJB 2.0. В EJB 1.1 требуется ровно один.
Указывает полное имя удаленного интерфейса.
<local-home>Необязателен.
Указывает полное имя локального исходного интерфейса.
<local>Необязателен.
Указывает полное имя локального интерфейса.
<ejb-class>Требуется ровно один.
Указывает полное имя класса компонента.
<primkey-field>Необязателен, используется в описании
Указывает имя поля, являющегося первичным ключом (если он состоит только из одного поля и синхронизацией компонента с базой данных управляет контейнер).
<prim-key-class>Требуется ровно один, используется в описании
Указывает имя класса первичного ключа. Можно отложить точное определение класса первичного ключа до развертывания, тогда в этом поле указывается java.lang.Object.
<persistence-type>Требуется ровно один, используется в описании
Имеет значения Bean или Container, в зависимости от того, управляется ли синхронизация компонента с базой данных самим компонентом или контейнером.
<cmp-version>Необязателен.
Указывает версию спецификаций EJB, в соответствии с которой разработан компонент, что определяет способ управления этим компонентом. Может иметь значения 2.x и 1.x.
<abstract-schema-name>Необязателен.
Задает уникальный идентификатор компонента для использования в запросах на языке EJB QL, который используется для описания запросов к схеме данных при реализации
<cmp-field>Один или более, используется в описании
Каждый такой элемент описывает одно поле данных, синхронизация которого с СУБД управляется <description> с описанием поля и должен содержать тег <field-name> с именем поля. В EJB 2.0 это имя совпадает с именем getName() и setName() ), а в EJB 1.1 — с именем одного из полей класса компонента.
<security-role-ref>Один или более, необязателен.
Указывает роли, используемые данным компонентом. Они при работе приложения служат для авторизации доступа — сопоставляются с ролями, которым разрешен доступ к тому или иному методу.
Может содержать тег <description> (необязателен) и теги <role-name> (обязателен), <role-link> (необязателен, служит для сопоставления указанного имени роли с логической ролью, описанной в <security-role> раздела <assembly-descriptor> ).
<security-identity>Необязателен.
Определяет, какую логическую роль будет играть данный компонент при обращениях к другим компонентам. Для этого может быть использован вложенный тег <run-as><role-name>…</role-name></run-as> для указания имени конкретной логической роли, или <use- для указания того, что нужно использовать роль вызывающего клиента.
<session-type>Требуется ровно один, используется в описании
Имеет значения Stateful или , в зависимости от того, использует ли данный компонент
<transaction-type>Требуется ровно один, используется в описании
Имеет значения Container или Bean, в зависимости от того, управляет ли транзакциями данного компонента контейнер или он сам. В первом случае соответствующие транзакции должны быть описаны в разделе <assembly-descriptor> (см. далее).
<query>Один или более, необязателен.
Используется для описания запросов, с чьей помощью реализуются некоторые методы <query-method>. Сам код запроса описывается внутри элемента CDATA во вложенном теге <ejb-ql>.
Например
<query>
<query-method>
<method-name>findByName</method-name>
<method-params>
<method-param>java.lang.String</method-param>
</method-params>
</query-method>
<ejb-ql>
<!CDATA[
SELECT OBJECT(c) FROM Client c WHERE c.name = ?1
]]
</ejb-ql>
</query>
<relationships>Необязателен. Вложен в <ejb-jar>.
Описывает набор отношений между компонентами, которые соответствуют связям в схеме базы данных и автоматически поддерживаются контейнером. Каждое отношение описывается с помощью вложенного тега <ejb-relation>.
<ejb-relation>Описывает одно отношение и может иметь следующие элементы.
<ejb-relation-name>Необязателен, только один. Задает имя отношения.
<ejb-relationship-role>Обязательно два. Описывает одну роль в рамах отношения. В описании роли должны присутствовать следующие данные.
<ejb-relationship-role-name>.<multiplicity> и может иметь значения One или Many.<relationship-role-source> внутри тега <ejb-name> в виде имени, которое присвоено компоненту в рамках данного дескриптора.<cmr-field>, во вложенном теге <cmr-field-name>, и для него в классе компонента должно быть определено абстрактное свойство с тем же именем.<assembly-descriptor>Этот обязательный тег внутри <ejb-jar> содержит дополнительные указания для сборки компонентов, в частности следующие.
<container-transaction>Один или более, необязателен.
Содержит необязательный элемент <description>, а также приведенные ниже.
Для
<method>Один или более.
Содержит тег <ejb-name>, указывающий имя компонента, и <method-name>, указывающий имя метода или знак *, который обозначает применение указанного атрибута ко всем методам.
Может также включать элементы <description>, <method-params> и <method-intf>, который может иметь значения Remote, Home, Local, Local-Home, в зависимости от того, в каком интерфейсе этот метод декларирован — для поддержки возможности декларировать методы с одним именем и набором параметром в разных интерфейсах.
<trans-attribute>Ровно один.
Определяет атрибут транзакции, управляющий политикой включения в транзакции или создания новых транзакций.
Для
Может иметь значения NotSupported, Supports, Required, RequiresNew, . Об их смысле рассказывалось в предыдущей лекции.
<security-role>Один или более, необязателен.
Определяет роли, служащие для контроля доступа к методам компонентов. В таком элементе должен содержаться тег <role-name>, задающий
<method-permission> Один или более, необязателен.
Указывает правила доступа ролей, определенных в тегах <security-role>, к методам компонентов.
Содержит необязательный тег <description>, один или несколько тегов <role-name> и один или несколько тегов <method> (см. выше), кроме того, в нем может присутствовать тег <, который обозначает отсутствие проверки прав доступа во время работы, даже если они описаны.
Каждый тег <method> содержит тег <ejb-name>, указывающий имя компонента, и <method-name>, указывающий имя метода или знак *, который обозначает применение указанного атрибута ко всем методам.
<exclude-list>Необязателен.
Содержит один или несколько тегов <method> (см. выше), определяющих методы, которые не должны вызываться при работе приложения. Каждый вызов такого метода создает исключительную ситуацию.
В среде .NET нет средств, полностью аналогичных тем, которые предоставляются в J2EE для разработки
Классы ADO.NET располагаются в сборке System.Data (дополнительные классы можно найти в System.Data.OracleClient и System.Data.SqlXml ) и пространстве имен System.Data, вместе с вложенными в него пространствами.
Основным классом, с помощью которого представляются данные из базы данных, является System.Data.DataSet. Он представляет набор таблиц, связанных между собой некоторыми связями и выполняющими определенные ограничения. Каждая таблица представляется объектом класса System.Data.DataTable, каждая связь — объектом класса System.Data.Relation, каждое ограничение — объектом класса System.Data.Constraint. Структура таблиц описывается с помощью их полей (представляемых объектами System.Data.DataColumn ). Содержимое одной таблицы представлено как набор объектов-записей, имеющих тип System.Data.DataRow.
Из перечисленных классов только DataSet и DataTable являются
Объект класса DataSet может представлять собой и набор данных документа XML. Получить такой объект можно с помощью класса System.Xml.XmlDataDocument.
Само взаимодействие с источником данных происходит с помощью объектов классов DataAdapter, DataReader, DbConnection, DbTransaction, DbCommand и производных от них, специфичных для того или иного вида источников данных (в рамках поставляемых в составе среды Visual Studio .NET библиотек имеются специфичные классы для работы с источниками ODBC, OleDB, MS SQL Server, Oracle). Все перечисленные классы находятся в пространстве имен System.Data.Common, а их производные для данного вида источников данных — в соответствующем этому виду источников подпространстве System.Data.
Объекты классов DataAdapter и DataReader служат для чтения и записи данных в виде объектов DataSet. Остальные классы используются для определения соединений, организации транзакций, определения и выполнения SQL-команд по чтению или изменению данных.
Ниже приводится простой пример работы с данными с помощью библиотек ADO.NET.
DbConnection connection = new SqlConnection("Data Source=localhost;" +
"Integrated Security=SSPI;Initial Catalog=DBCatalog");
DbCommand command = new SqlCommand("SELECT ID, Title, ISBN FROM Book",
connection);
DataAdapter adapter = new SqlDataAdapter();
Adapter.SelectCommand = command;
connection.Open();
DataSet dataset = new DataSet();
adapter.Fill(dataset, "Book");
connection.Close();
Прежде чем перейти к построению интерфейса пользователя в Web-приложениях на основе J2EE и .NET, стоит рассмотреть основные элементы
HTTP (Hypertext Transfer Protocol, протокол передачи гипертекста) представляет собой протокол прикладного уровня, использующий для пересылки данных протокол транспортного уровня. Достаточно подробное описание его можно найти в [5,6].
Сообщения HTTP бывают двух видов: запросы клиента и ответы сервера.
Запрос HTTP состоит из идентификации метода запроса, универсального идентификатора запрашиваемого ресурса (Universal Resource Identifier, URI), указания версии протокола и, возможно, набора заголовков с дополнительной информацией, а также поля данных общего вида.
<Request> ::= GET <URI> CrLf
| <Method> <URI> <HTTP-Version> CrLf
<Req-Header>* ( <Data> )?
<Req-Header> ::= <Field> : <Value> CrLf
CrLf ::= '\r''\n'
Основные методы
GETСлужит для получения любой информации по URI запроса, обычно — документа, хранящегося по указанному адресу или генерируемого по запросу с таким URI. Может иметь заголовок If-Modified-Since, который предписывает не посылать тело запрашиваемого ресурса, если он не изменялся с указанной даты.
POSTСлужит для создания нового ресурса, связанного с указанным по URI. Чаще всего используется для аннотации ресурсов, добавления сообщений в группы новостей, дистанционной работы с базами данных. Реальная обработка такого запроса зависит от содержащегося в нем URI.
Остальные методы — HEAD, PUT, DELETE, LINK, UNLINK — используются гораздо реже.
Заголовки запроса служат для передачи дополнительной информации об этом запросе или о клиенте. Заголовок состоит из идентификатора поля и его значения, разделенных двоеточием, и бывает одного из следующих типов.
FromСодержит e-mail адрес пользователя, под чьим именем работает клиент.
Пример: From:
Accept, Accept-Encoding, Accept-Charset и Accept-LanguageВ таком заголовке через запятую перечисляются возможные форматы (соответственно, кодировки, используемые таблицы символов и языки) ответов на данный запрос.
Пример: Accept: text/
User-AgentСодержит название используемой клиентской программы.
RefererИспользуется для указания адреса ресурса, с которого был получен данный запрос.
If-Modified-SinceИспользуется для отмены ответной пересылки документов, модифицированных не позднее указанной даты, с целью снижения нагрузки на сеть.
AuthorizationСодержит авторизационную информацию, специфичную для используемых сервером протоколов авторизации.
ChargeToСодержит информацию о том, куда выставить счет за обработку запроса.
PragmaСодержит дополнительные директивы для промежуточных серверов, например, прокси-серверов.
Пример запроса.
GET /locate?keywords=HTTP+description HTTP/1.1 Date: Mon, 15 Dec 2004 12:18:15 GMT Accept: image/gif, image/jpg, */* Accept-Charset: iso-8859-1, *, utf-8 Accept-Language: en Connection: keep-Alive User-Agent: Mozilla/4.7 [en] (Win98; u)
| Группа кодов | Код | Фраза-объяснение, следующая за кодом | Значение кода |
|---|---|---|---|
| 1xx | Информационное сообщение | ||
| 2xx | Успешная обработка | ||
| 200 | OK | Вcе нормально | |
| 201 | Created | Документ создан | |
| 3xx | Перенаправление запроса | ||
| 301 | Moved Permanently | Ресурс перемещен | |
| 302 | Moved |
Ресурс перемещен временно | |
| 4xx | Ошибка клиента | ||
| 400 | Bad Request | Некорректно составленный запрос | |
| 401 | Нужна аутентификация клиента | ||
| 403 | Forbidden | Доступ к ресурсу запрещен | |
| 404 | Not Found | Запрашиваемый ресурс отсутствует | |
| 5xx | Ошибка сервера | ||
| 500 | Internal |
Внутренняя ошибка сервера |
Ответ сервера на HTTP-запрос состоит либо только из запрашиваемого клиентом документа, либо в дополнение к нему содержит код статуса ответа и, возможно, несколько заголовков ответа.
<Response> ::= ( <Content> )?
| <HTTP-Version> <Code> <Explanation> CrLf
<Resp-Header>* ( <Content> )?
<Resp-Header> ::= <Field> : <Value> CrLf
CrLf ::= '\r''\n'
Некоторые коды статуса ответа поясняются в табл. 12.
Возможны следующие заголовки ответа:
AllowedПеречисляются через пробел доступные для пользователя методы запросов по данному URI.
PublicПеречисляет доступные всем методы запросов.
Content-Length, Content-Type, Content-Encoding и Content-LanguageЗадают размер содержимого в байтах (подразумевается, что содержимое имеет бинарный формат и не должно разбиваться на строки при чтении), его формат или MIME-тип, кодировку и язык.
DateДата создания содержащегося документа или объекта.
Last-ModifiedДата последнего изменения содержащегося объекта.
ExpiresДата, после которой содержащийся объект считается устаревшим.
URIURI содержащегося объекта.
TitleЗаголовок содержащегося документа.
ServerОписывает серверную программу.
Retry-AfterОпределяет промежуток времени на обработку запроса, до прохождения которого не надо направлять запрос повторно, если ответа на него еще нет.
Пример HTTP-ответа.
HTTP/1.0 200 OK Content-Length: 2109 Content-Type: text/html Expires: 0 Last-Modified: Thu, 08 Feb 2001 09:23:17 GMT Server: Apache/1.3.12 <HTML> <HEAD> <TITLE> … </TITLE> </HEAD> <BODY> … </BODY> </HTML>
Компоненты пользовательского интерфейса в Web-приложениях, построенных как по технологии J2EE, так и по .NET, реализуют обработку HTTP-запросов, приходящих от браузера, и выдают в качестве результатов HTTP-ответы, содержащие сгенерированные HTML-документы с запрашиваемыми данными. Сами запросы автоматически строятся браузером на основе действий пользователя — в основном, переходов по ссылкам и действий с элементами управления в HTML-формах.
Если стандартных
В рамках J2EE версии 1.4 два основных вида компонентов WebUI —
Интерфейс Java- javax. и javax., являющихся частью J2EE SDK. Первый пакет содержит классы, описывающие независимые от протокола
Основные классы и интерфейсы пакета javax. следующие.
HttpServletПредназначен для реализации void doGet(HttpServletRequest, HttpServletResponse), определяющий обработку GET-запросов, и void doPost(HttpServletRequest, HttpServletResponse), обрабатывающий POST-запросы. В обоих методах первый параметр содержит всю информацию о запросе, а второй — о генерируемом ответе.
HttpServletRequest и HttpServletResponse — интерфейсы, содержащие методы для получения и установки (второй) заголовков и других атрибутов HTTP-запросов и ответов. Второй интерфейс также содержит метод, возвращающий поток вывода для построения содержимого ответа.CookieКласс, представляющий закладки сервера, которые хранятся на клиентской машине для запоминания информации о данном пользователе.
HTTPSessionИнтерфейс, предоставляющий методы для управления сеансом обмена HTTP-сообщениями. Информация о сеансе используется в том случае, если она должна быть доступна нескольким
При развертывании J2EE-приложения, помимо самих классов
Web-приложение поставляется в виде архива .war, содержащего все его файлы. На самом деле это zip-архив, расширение .war нужно для того, чтобы Web-контейнер узнавал архивы развертываемых на нем Web-приложений. Содержащаяся в этом архиве структура директорий Web-приложения должна включать директорию WEB-INF, вложенную непосредственно в корневую директорию приложения. Директория WEB-INF содержит две поддиректории — classes для .class-файлов
Заголовок
<!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc...ВЕВ Web Application 2.2.. EN" http://java.sun.com/j2ee/dtds/web-app_2_2.dtd>
Содержимое <web-app>. В нем указывается список
<servlet>
<servlet-name>ServletName</servlet-name>
<servlet-class>com.company.deprtment.app.ServletClassName</servlet-class>
<description>…</description>
<init-param>
<param-name>ParameterName</param-name>
<param-value>ParameterValue</param-value>
<description>…</description>
</init-param>
</servlet>
Значения параметров инициализации String getInitParameter(String) и Enumeration getInitParametersNames() связанных с ServletContext.
Отображение
<servlet-mapping> <servlet-name>ServletName</servlet-name> <url-pattern>URL</url-pattern> </servlet-mapping>
При работе Web-приложения doGet(), в котором HTML-элементы записываются в поток содержимого ответа в неизменном виде, а элементы Java-кода преобразуются в код, записывающий некоторые данные в тот же поток на основании параметров запроса или данных приложения.
Для развертывания
Основные интерфейсы и базовые классы javax..
Элементами
Директивы имеют следующий общий синтаксис.
<%@ directive attribute1="value1" ... attributeN="valueN" %>.
Основные директивы
import = "имена включаемых классов и пакетов через запятую"Порождает соответствующую Java-директиву import в сгенерированном коде
contentType = "MIME-тип[;charset=таблица символов]"Задает тип MIME для генерируемого документа. По умолчанию используется text/html. Эквивалентен скриплету
<% response.setContentType(MIME-тип); %> (см. далее).
isThreadSafe = "true|false"Значение true позволяет использовать один экземпляр
session = "true|false"Значение true предписывает привязать
autoFlush = "true|false"Определяет необходимость сбрасывать буфер вывода при заполнении.
buffer = "размер в KB|none"Задает размер буфера для выходного потока
extends = "наследуемый класс"Определяет класс, наследуемый сгенерированным из данной
errorPage = "url странички с информацией об ошибках"Определяет страницу, которая используется для обработки исключений, не обрабатываемых в рамках данной.
isErrorPage = "true|false"Допускает или запрещает использование данной страницы в качестве страницы обработки ошибок.
language = "java"Определяет язык программирования, применяемый в скриптовых элементах данной страницы. Пока есть возможность использовать только Java. Впоследствии предполагается (аналогично .NET) разрешить использование других языков, код которых будет также транслироваться в байт-код, интерпретируемый JVM.
include обеспечивает статическое (в ходе трансляции file, значением которого должна быть строка, задающая URL taglib указывает используемую в данной странице библиотеку пользовательских тегов. Она имеет два атрибута — uri, значением которого является URI библиотеки, и prefix, определяющий префикс тегов из данной библиотеки. Префикс употребляется в дальнейшем с тегами только данной библиотеки. Он не может быть пустым и не должен совпадать с одним из зарезервированных префиксов jsp , jspx, java, javax, servlet , sun, sunw.Теги или действия определяют основные действия, выполняемые при обработке данных и построении результирующего документа.
Теги могут быть стандартными, использование которых возможно в любой странице без дополнительных объявлений, или пользовательскими, которые могут употребляться, только если предварительно с помощью директивы taglib была подключена содержащая их библиотека. Любой тег имеет следующий синтаксис.
<tagprefix:tag attribute1="value1" … attributeN="valueN" />
Теги могут содержать вложенные теги, такие как . В этом случае они выглядят следующим образом.
<tagprefix:tag attribute1="value1" … attributeN="valueN"> … (вложенные теги) </tagprefix:tag>
Стандартные теги имеют префикс , а префикс пользовательских тегов определяется в директиве taglib, подключающей содержащую их библиотеку.
Имеется довольно много стандартных тегов. Основные из них следующие.
jsp :includeОпределяет динамическое включение некоторой страницы или файла в данную страницу при обработке запроса. С помощью вложенных тегов может указывать один или несколько пар параметр-значение в качестве параметров включаемой страницы.
Имеет атрибуты page, определяющий URL включаемой страницы, и flush, имеющий значения true или false в зависимости от того, нужно ли сразу после включения сбросить буфер выходного потока в генерируемом ответе или нет.
jsp :useBeanОпределяет используемый объект или компонент. Фактически такой тег эквивалентен декларации переменной определенного типа, инициализируемой определенным объектом и доступной в рамках некоторого контекста.
Имеет следующие атрибуты.
id = "имя объекта"Задает имя объекта, которое будет использоваться в коде
class = "класс объекта"Задает класс этого объекта.
scope = "page|request|session|application"Задает область видимости декларируемого объекта.
type = "тип используемой ссылки на объект"Указанный тип должен быть предком класса объекта. Это тип декларируемой переменной, а класс объекта определяет истинный тип объекта, хранящегося в ней.
jsp :setProperty, jsp :getPropertyУстанавливает или получает значение свойства объекта.
Атрибут name определяет имя объекта, чье свойство используется, а атрибут property — имя свойства.
Тег записывает полученное значение свойства в результирующий документ в виде строки (результата вызова toString() для этого значения).
Тег имеет также дополнительный атрибут — либо value, значение которого присваивается свойству, либо param, который указывает имя параметра запроса, значение которого записывается в свойство. Если в теге вместо имени свойства в атрибуте property указан символ *, то всем свойствам указанного объекта с именами, совпадающими с именами параметров запроса, будут присвоены значения соответствующих параметров.
jsp :forwardЭтот тег употребляется для перенаправления запроса на обработку другой странице. URL этой страницы указывается в качестве значения атрибута page. В качестве этого URL может использоваться
С помощью вложенных тегов можно передать одно или несколько значений параметров странице, на которую переключается управление.
jsp :pluginЭтот тег вставляет аплет или компонент . Кроме того, имеет следующие атрибуты.
type = "bean|applet"Задает вид вставляемого компонента.
code = "имя файла класса компонента (включая расширение .class)"codebase = "имя директории, в которой находится файл класса компонента"Если этот атрибут отсутствует, используется директория, содержащая данную
name = "имя используемого экземпляра компонента"archive = "список разделенных запятыми путей архивных файлов, которые будут загружены перед загрузкой компонента"Эти архивы содержат дополнительные классы и библиотеки, необходимые для работы компонента.
align = "bottom|top|middle|left|right"Задает положение экземпляра компонента относительно базовой строки текста содержащего его HTML-документа.
height = "высота изображения объекта в точках"width = "ширина изображения объекта в точках"hspace = "ширина пустой рамки вокруг объекта в точках"vspace = "высота пустой рамки вокруг объекта в точках"jreversion = "версия JRE , необходимая для работы компонента"По умолчанию используется версия 1.1.
Пользовательские теги могут быть определены для выполнения самых разнообразных действий. Одна из наиболее широко используемых библиотек тегов core (подключаемая с помощью директивы <%@ taglib uri="http://java.sun.com/ ), содержит теги, представляющие все конструкции языка Java.
Например, с помощью тега <c:set var="variable" value="value" /> можно присвоить значение value в переменную variable, с помощью тега <c:if test="expression">…</c:if> можно выполнить код expression имеет значение true, с помощью тега <c:forEach var="variable" items="collection">…</c:forEach> можно выполнить содержащийся в нем код для всех элементов коллекции collection, используя для обращения к текущему элементу переменную variable.
Таким образом, весь код, который может быть записан в виде скриптовых элементов (см. далее), можно записать и в виде тегов. Применение тегов при этом вносит некоторые неудобства для Java-программиста. Но оно же делает код
Скриптовые элементы могут иметь один из следующих трех видов.
<%! код на Java %>
<% код на Java %>
<% = выражение на Java %>
${выражение на Java}
#{выражение на Java}
Различий между первым и вторым способом представления выражений практически нет. Выражение третьего типа вычисляется отлаженно — вычисление его значения происходит только тогда, когда это значение действительно понадобится.
Комментарии в коде <%-- … --%>. Встречающийся в них код не обрабатывается во время трансляции и не участвует в работе полученного <!-- … --> обрабатываются так же, как и в других местах — они генерируют содержимое комментариев в результирующем HTML-документе.
Помимо объявленных в объявлениях и тегах переменных в скриптовых элементах могут использоваться неявно доступные объекты, связанные с результирующим
request — запрос клиента (тип ServletRequest ).param — параметры запроса (тип Map ).response — ответ сервера (тип ServletResponse ).out — выходной поток PrintWriter ).session — сеанс (тип HttpSession ).application —приложение ( ServletContext ).config — конфигурация ServletConfig ).pageContext — javax.servlet .jsp .PageContext ).exception — произошедшее исключение.Ниже приведен пример
<%@ page import="java.util.Date, java.util.Iterator,
com.company.Client" %>
<jsp:useBean id="clients" class="com.company.ClientList"
scope="page" />
<jsp:useBean id="convertor" class="com.company.ExchangeRate"
scope="page" />
<html>
<head>
<title>Table of clients</title>
</head>
<body>
<h3 align="center">Table of clients</h3>
Created on <%= new Date() %> <br><br>
<table width="98%" border="1" cellspacing="1" cellpadding="1">
<tr>
<%!
private double dollarsToRubles(double m)
{
return m*convertor.getDollarToRubleRate(new Date());
}
%>
<th width="50%" scope="col">Client</th>
<th width="25%" scope="col">Balance, dollars</th>
<th width="25%" scope="col">Balance, rubles</th>
</tr>
<%
Iterator it = clients.getNumberOfClients().iterator();
while(it.hasNext())
{
Client сlient = (Client)it.next();
%>
<tr>
<td> ${client.getFullName()} </td>
<td> ${client.getBalance()} </td>
<td> ${dollarsToRubles(client.getBalance())} </td>
</tr>
<%
}
%>
</table> <br><br>
<jsp: include page="footer.txt" flush= "true" />
</body>
</html>
Разработка компонентов пользовательского интерфейса Web-приложений в рамках .NET выделена в виде отдельной технологии ASP.NET [9,10] и в целом очень похожа на разработку тех же компонентов в J2EE. В .NET имеются те же виды компонентов: элементы управления, представленные серверными элементами управления HTML (HTML server controls) и просто серверными элементами управления (Web Server Controls), обработчики http-запросов (аналог IHttpHandler и IHttpAsyncHandler, и так называемые Web-формы (Web-forms), аналог
Элементы управления WebUI в .NET могут быть размещены на HTML-страницах, но выполняются на сервере. Библиотеки таких компонентов находятся в сборке System.Web и в пространстве имен System.Web.UI, вместе с его подпространствами. Их употребление в рамках HTML-документа оформляется в виде специальных тегов с атрибутом runat, имеющим значение server. Ниже приведен пример использования компонента System.Web.UI.WebControls.Button в коде Web-формы:
<%@ Page Language="C#" AutoEventWireup="True" %>
<html>
<head>
<script language="C#" runat=server>
void OnButtonClick(object sender, EventArgs e)
{
Message.Text="Hello World!!";
}
</script>
</head>
<body>
<form runat="server">
<h3>Button Example</h3>
Click on the submit button.<br><br>
<asp:Button id="MyButton"
Text="Submit"
OnClick="OnButtonClick"
runat="server"/>
<p>
<asp:label id="Message" runat="server"/>
</form>
</body>
</html>
Аналогом System.Web.IHttpHandler и System.Web.IHttpAsyncHandler. Оба они являются частью программного интерфейса Web-сервера Microsoft (Internet Server Application Program Interface, ISAPI). Первый интерфейс предназначен для синхронной обработки запросов, с блокированием на время обработки вызвавшего ее потока Web-сервера. Второй интерфейс позволяет реализовывать такую обработку в отдельном потоке.
Единственный метод первого интерфейса — void ProcessRequest (System.Web.HttpContext context). Все данные, связанные с запросом, ответом на него, приложением и контекстом, в котором работает данный обработчик, можно получить, используя различные свойства параметра этого метода.
Интерфейс IHttpAsyncHandler имеет два метода — IAsyncResult BeginProcessRequest( HttpContext context, AsyncCallback cb, object extraData) и void EndProcessRequest( IAsyncResult result). Первый вызывается при передаче запроса данному обработчику, второй — для прекращения обработки.
Специальные конструкции
Директивы <%@ directive attribute1="value1" ... attributeN="valueN" %>. Список директив шире, чем в Import, аналог include, директива Control для описания пользовательских элементов управления, директива Register для определения синонимов (алиасов), и пр.
Объявления полей данных и методов в Web-формах обрамляются в тег <script> … </script>. Такой тег должен иметь атрибут runat со значением server и атрибут language, который определяет язык кода, написанного внутри тега. Он может также иметь атрибут src для указания URL файла, код из которого должен быть вставлен перед содержимым тега.
Конструкции встроенного кода обрамляются в тег <% … %>. Как и в <%=… %>. Комментарии тоже оформляются, как и в <%-- … --%>.
Конструкции привязки к данным имеют синтаксис <%# expression %> и работают примерно так же, как и выражения встроенного кода. Они могут использоваться и в значениях атрибутов элементов управления.
Конфигурационные файлы компонентов .NET, являющиеся аналогами configuration. Он может содержать теги location, которые определяют конфигурацию для ресурсов, путь к которым указывается в атрибуте path таких тегов. Теги location для компонентов ASP.NET содержат тег system.web, который, в свою очередь, может содержать следующие теги (перечислены не все возможные, более полную информацию см. в [11]).
authenticationОпределяет используемый вид аутентификации — атрибут mode задает используемый механизм (Windows, Forms, forms описывают свойства отдельных форм, используемых для аутентификации.
authorizationОпределяет права доступа для пользователей, ролей и отдельных методов HTTP-запросов. Разрешения на доступ указываются в атрибутах вложенного теги allow, запреты — в атрибутах вложенного тега deny.
compilationОпределяет параметры компиляции компонента ASP.NET.
customErrorsОпределяет специфические для данного приложения ошибки и URL, на которые переходит управление при возникновении этих ошибок.
globalizationОпределяет кодировки и локализацию запросов и ответов.
httpHandlersОпределяет отображение адресов и методов запросов на обрабатывающие их объекты типа IHttpHandelr или IHttpHandlerFactory.
pagesОпределяет настройки для отдельных страниц.
sessionStateОписывает настройки для поддержки
В данной лекции мы рассмотрим техники разработки компонентов Web-приложений на основе платформ J2EE и .NET. Общая архитектура такого приложения может быть представлена схемой, изображенной на рис. 14.1. Обе платформы предоставляют специальную поддержку для разработки компонентов на двух уровнях: уровне интерфейса пользователя (WebUI) и уровне связи с данными.
(рис 14.1) Общая схема архитектуры Web-приложений J2EE и .NETПользовательский интерфейс Web-приложений основан на генерации
Основные отличия между техниками разработки компонентов этих двух уровней, используемыми в рамках J2EE и .NET, можно сформулировать следующим образом.
В .NET нет специально выделенного вида компонентов, предназначенного для реализации бизнес-логики — она может реализовываться с помощью обычных классов, что часто удобнее. Это положение должно измениться с выходом EJB 3.0.
В .NET-приложениях все предлагаемые способы представления данных являются объектными обертками вокруг реляционного представления — в любом случае приходится работать с данными как с набором таблиц. В .NET нет автоматической поддержки их преобразования в систему взаимосвязанных объектов и обратно.
В рамках приложений, построенных по технологии J2EE, связь с базой данных и бизнес-логику, скрытую от пользователя, принято реализовывать с помощью компонентов Enterprise
Возможны и другие способы реализации этих функций. Например, бизнес-логика может быть реализована непосредственно в методах объектов пользовательского интерфейса, а обмен данными с базой данных — через интерфейс JDBC. При этом, однако, теряется возможность переиспользования функций бизнес-логики в разных приложениях на основе единой базы данных, а также становится невозможным использование автоматических транзакций при работе с данными. Транзакции в этом случае нужно организовывать с помощью явных обращений к
Для разработки набора
Правила создания
Представляют данные приложения и основные методы работы с ними.
Представляют независимую от пользовательского интерфейса и конкретных типов данных логику работы приложения, называемую иногда бизнес-логикой.
Тоже предназначены для реализации бизнес-логики. Но, если
Далее описываются основные правила построения
Этот интерфейс декларирует методы компонента, к которым можно обращаться удаленно, т.е. из компонентов, работающих в рамках другого процесса или на другой машине.
Удаленный интерфейс должен наследовать интерфейс javax.ejb.EJBObject (в свою очередь, наследующий java. ).
Для getName()/void setName(Type) ), служащих для работы с отдельными полями данных или компонентами, связанными с этим компонентом по ссылкам. Это могут быть и часто используемые дополнительные операции, как-то выражающиеся через операции с отдельными полями данных, в том числе и вычислимые свойства. Например, для книги в базе данных приложения хранится набор ссылок на данные об ее авторах, а число авторов может быть часто используемым свойством книги, вычисляемым по этому набору ссылок.
Для
По назначению этот интерфейс полностью аналогичен удаленному, но декларирует методы компонента, которые можно вызывать только в рамках того же процесса. Этот интерфейс служит для увеличения производительности приложений, в которых взаимодействия между компонентами происходят в основном в рамках одного процесса. При этом они могут использовать локальные интерфейсы друг друга, не привлекая сложный механизм реализации удаленных вызовов методов. Однако при использовании локального интерфейса компонентаo нужно обеспечить развертывание этого компонента в рамках того же
Локальный интерфейс должен наследовать интерфейсу javax.ejb.EJBLocalObject.
Исходные интерфейсы служат для поиска и создания компонентов. Такой интерфейс может декларировать метод поиска findByPrimaryKey(…) и метод создания такого компонента с указанным значением первичного ключа create(…). Могут быть также определены методы, создающие компонент по набору его данных или возвращающие коллекцию компонентов, данные которых соответствуют аргументам такого метода. Например, метод, создающий компонент, который представляет книгу с данным названием, createByTitle(String title), или метод, находящий все книги с данным набором авторов Collection findByAuthors(Collection authors).
Удаленный исходный интерфейс предназначен для создания и поиска компонентов извне того процесса, в котором они работают. Его методы возвращают ссылку на удаленный интерфейс компонента или коллекцию таких ссылок.
Такой интерфейс должен наследовать интерфейсу javax.ejb.EJBHome (являющемуся наследником java. ).
Имеет то же общее назначение, что и удаленный исходный интерфейс, но служит для работы с компонентами в рамках одного процесса. Соответственно, его методы поиска или создания возвращают ссылку на локальный интерфейс компонента или коллекцию таких ссылок.
Должен наследовать интерфейсу javax.ejb.EJBLocalHome.
Этот класс реализует методы удаленного и локального интерфейсов (но не должен реализовывать сами эти интерфейсы!). Он определяет основную функциональность компонента.
Для javax.ejb.EntityBean. Свойства, соответствующие полям хранимых данных или ссылкам на другие getName()/setName(). В этом случае
Для javax.ejb.SessionBean и все методы удаленного и локального интерфейсов.
Кроме того, класс компонента может (а иногда и должен) реализовывать некоторые методы, которые вызываются
Например, при ejbCreate(). Для null и всегда должен быть реализован в классе компонента. Для void, а на вход принимает какие-то параметры, служащие для createSomeSuffix(…) в классе компонента должен быть реализован
метод ejbCreateSomeSuffix(…) с теми же типами параметров. Для void.
Другие методы жизненного цикла компонента, которые можно перегружать в классе компонента, декларированы в базовых интерфейсах компонентов соответствующего вида ( javax.ejb.EntityBean или javax.ejb.SessionBean ). Это, например, ejbActivate() и ejbPassivate(), вызываемые при активизации и деактивизации экземпляра компонента; ejbRemove(), вызываемый перед удалением экземпляра компонента из памяти; для ejbStore() и ejbLoad(), вызываемые при сохранении данных экземпляра в базу приложения или при их загрузке оттуда.
Схема жизненного цикла
Жизненный цикл
(рис 14.2) Жизненный цикл EJB компонента данных
Схема жизненного цикла ejbCreate() сразу переводит компонент в активное состояние.
(рис 14.3) Жизненный цикл сеансового компонента с состояниемЖизненный цикл
Декларируется только для
Определяет набор данных, которые образуют первичный ключ записи базы данных, соответствующей одному экземпляру компонента.
Чаще всего это библиотечный класс, например, String или Integer. Пользовательский класс необходим, если первичный ключ составной, т.е. состоит из нескольких значений простых типов данных. В таком классе должен быть определен конструктор без параметров и правильно перегружены методы equals() и hashCode(), чтобы java.io.Serializable.
(рис 14.4) Жизненный цикл сеансового компонента без состоянияНиже приведены примеры декларации класса компонента и интерфейсов для
В рамках этой схемы, состоящей из таблиц, где хранятся данные книг и организаций-издателей, каждая книга связана с одним и только одним издателем, а каждый издатель может иметь ссылки на некоторое множество книг (возможно, пустое). Каждая таблица имеет поле ID, являющееся первичным ключом. Таблица Book имеет поле PublisherID, содержащее значение ключа записи об издателе данной книги.
(рис 14.5) Пример схемы БДПримеры кода удаленных интерфейсов для компонентов, представляющих данные о книгах и издателях в рамках EJB-приложения:
package ru.msu.cmc.prtech.examples;
import java.rmi.RemoteException;
import java.util.Collection;
import javax.ejb.EJBObject;
public interface PublisherRemote extends EJBObject
{
public String getTitle () throws RemoteException;
public void setTitle (String title) throws RemoteException;
public Collection getBooks ()throws RemoteException;
public void setBooks (Collection books)
throws RemoteException;
public void addBook (String title, String isbn)
throws RemoteException;
public void removeBook (String title, String isbn)
throws RemoteException;
}
package ru.msu.cmc.prtech.examples;
import java.rmi.RemoteException;
import javax.ejb.EJBObject;
public interface BookRemote extends EJBObject
{
public String getTitle () throws RemoteException;
public void setTitle (String title) throws RemoteException;
public String getISBN () throws RemoteException;
public void setISBN (String isbn) throws RemoteException;
public PublisherRemote getPublisher () throws RemoteException;
public void setPublisher (PublisherRemote publisher)
throws RemoteException;
}
Примеры кода удаленных исходных интерфейсов.
package ru.msu.cmc.prtech.examples;
import java.rmi.RemoteException;
import javax.ejb.CreateException;
import javax.ejb.EJBHome;
import javax.ejb.FinderException;
public interface PublisherHomeRemote extends EJBHome
{
public PublisherRemote create (Integer id)
throws CreateException, RemoteException;
public PublisherRemote findByPK (Integer id)
throws FinderException, RemoteException;
}
package ru.msu.cmc.prtech.examples;
import java.rmi.RemoteException;
import javax.ejb.CreateException;
import javax.ejb.EJBHome;
import javax.ejb.FinderException;
public interface BookHomeRemote extends EJBHome
{
public BookRemote create (Integer id)
throws CreateException, RemoteException;
public BookRemote createBook (String title, String isbn)
throws CreateException, RemoteException;
public BookRemote findByPK (Integer id)
throws FinderException, RemoteException;
}
Примеры кода классов компонентов. Показано, как реализовывать дополнительные, не поддерживаемые контейнером автоматически, методы работы со связями между данными об издателях и книгах и дополнительные методы создания компонентов.
package ru.msu.cmc.prtech.examples;
import java.util.Collection;
import java.util.Iterator;
import java.rmi.RemoteException;
import javax.ejb.CreateException;
import javax.ejb.EntityBean;
import javax.naming.InitialContext;
import javax.naming.NamingException;
public abstract class PublisherBean implements EntityBean
{
public Integer ejbCreate (Integer pk)
{
setId(pk);
return null;
}
public void ejbPostCreate (Integer pk) { }
public abstract Integer getId ();
public abstract void setId (Integer pk);
public abstract String getTitle ();
public abstract void setTitle (String title);
public abstract Collection getBooks ();
public abstract void setBooks (Collection books);
public void addBook (String title, String isbn)
{
try
{
InitialContext context = new InitialContext();
BookHomeRemote bookHome =
(BookHomeRemote)context.lookup("BookHomeRemote");
BookRemote book = bookHome.createBook(title, isbn);
Collection books = getBooks();
books.add(book);
}
catch (NamingException e) { e.printStackTrace(); }
catch (CreateException e) { e.printStackTrace(); }
catch (RemoteException e) { e.printStackTrace(); }
}
public void removeBook (String title, String isbn)
{
Collection books = getBooks();
Iterator it = books.iterator();
try
{
while(it.hasNext())
{
BookRemote book = (BookRemote)it.next();
if( book.getTitle().equals(title)
book.getISBN().equals(isbn)
)
{
it.remove();
break;
}
}
}
catch (RemoteException e) { e.printStackTrace(); }
}
}
package ru.msu.cmc.prtech.examples;
import javax.ejb.EntityBean;
public abstract class BookBean implements EntityBean
{
public Integer ejbCreate (Integer pk)
{
setId(pk);
return null;
}
public void ejbPostCreate (Integer pk) { }
public Integer ejbCreateBook (String title, String isbn)
{
setTitle(title);
setISBN(isbn);
return null;
}
public void ejbPostCreateBook (String title, String isbn) { }
public abstract Integer getId ();
public abstract void setId (Integer pk);
public abstract String getTitle ();
public abstract void setTitle (String title);
public abstract String getISBN ();
public abstract void setISBN (String isbn);
public abstract PublisherRemote getOrganization ();
public abstract void setOrganization (PublisherRemote pr);
}
javax.jms.MessageListener. Вместе с этим интерфейсом класс javax.ejb.MessageDrivenBean.
Первый интерфейс требует определения метода void onMessage(javax.jms.Message), который разбирает содержимое пришедшего сообщения и определяет способ его обработки. Кроме того, нужно определить методы void ejbCreate() для создания компонента и void ejbRemove() для освобождения ресурсов при его удалении.
Жизненный цикл
Пример реализации класса
package ru.msu.cmc.prtech.examples;
import javax.ejb.EJBException;
import javax.ejb.MessageDrivenBean;
import javax.ejb.MessageDrivenContext;
import javax.jms.MapMessage;
import javax.jms.Message;
import javax.jms.MessageListener;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
public class TransferProcessorBean
implements MessageDrivenBean, MessageListener
{
Context context;
public void setMessageDrivenContext (MessageDrivenContext mdc)
throws EJBException
{
try { context = new InitialContext(); }
catch (NamingException e) { throw new EJBException(e); }
}
public void ejbCreate() { }
public void onMessage (Message msg)
{
MapMessage message = (MapMessage)msg;
try
{
Integer publisherPK = (Integer)message.getObject("Publisher");
String title = (String)message.getObject("Title");
String isbn = (String)message.getObject("ISBN");
PublisherHomeRemote publisherHome =
(PublisherHomeRemote)context.lookup("PublisherHomeRemote ");
PublisherRemote publisher = publisherHome.findByPK(publisherPK);
publisher.addBook(title, isbn);
}
catch (Exception e) { throw new EJBException(e); }
}
public void ejbRemove () throws EJBException
{
try { context.close(); }
catch (NamingException e) { }
}
}
Помимо декларации интерфейсов и классов компонентов, для построения
Чаще всего дескрипторы развертывания не пишут вручную, их готовят с помощью специализированных инструментов для развертывания J2EE-приложений или сред разработки (например, такими возможностями обладает среда NetBeans 4.0 [3]). Здесь мы опишем только часть содержимого
Заголовок
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE ejb-jar PUBLIC "-//Sun Microsystems, Inc.//DTD Enterprise JavaBeans 2.0//EN"
http://java.sun.com/j2ee/dtds/ejb-jar_2_1.dtd">
<ejb-jar>Обязательный элемент.
Это корневой тег
<enterprise-beans>Обязательный элемент, должен появиться внутри <ejb-jar> ровно один раз.
Содержит набор описаний отдельных <entity>, <session>, <message-driven>.
<entity> и <session>Эти теги вложены в тег <enterprise-beans> и служат для описания, соответственно,
<ejb-name>Требуется ровно один.
Задает имя компонента.
<home>Необязателен, начиная с EJB 2.0. В EJB 1.1 требуется ровно один.
Указывает полное имя удаленного исходного интерфейса.
<remote>Необязателен, начиная с EJB 2.0. В EJB 1.1 требуется ровно один.
Указывает полное имя удаленного интерфейса.
<local-home>Необязателен.
Указывает полное имя локального исходного интерфейса.
<local>Необязателен.
Указывает полное имя локального интерфейса.
<ejb-class>Требуется ровно один.
Указывает полное имя класса компонента.
<primkey-field>Необязателен, используется в описании
Указывает имя поля, являющегося первичным ключом (если он состоит только из одного поля и синхронизацией компонента с базой данных управляет контейнер).
<prim-key-class>Требуется ровно один, используется в описании
Указывает имя класса первичного ключа. Можно отложить точное определение класса первичного ключа до развертывания, тогда в этом поле указывается java.lang.Object.
<persistence-type>Требуется ровно один, используется в описании
Имеет значения Bean или Container, в зависимости от того, управляется ли синхронизация компонента с базой данных самим компонентом или контейнером.
<cmp-version>Необязателен.
Указывает версию спецификаций EJB, в соответствии с которой разработан компонент, что определяет способ управления этим компонентом. Может иметь значения 2.x и 1.x.
<abstract-schema-name>Необязателен.
Задает уникальный идентификатор компонента для использования в запросах на языке EJB QL, который используется для описания запросов к схеме данных при реализации
<cmp-field>Один или более, используется в описании
Каждый такой элемент описывает одно поле данных, синхронизация которого с СУБД управляется <description> с описанием поля и должен содержать тег <field-name> с именем поля. В EJB 2.0 это имя совпадает с именем getName() и setName() ), а в EJB 1.1 — с именем одного из полей класса компонента.
<security-role-ref>Один или более, необязателен.
Указывает роли, используемые данным компонентом. Они при работе приложения служат для авторизации доступа — сопоставляются с ролями, которым разрешен доступ к тому или иному методу.
Может содержать тег <description> (необязателен) и теги <role-name> (обязателен), <role-link> (необязателен, служит для сопоставления указанного имени роли с логической ролью, описанной в <security-role> раздела <assembly-descriptor> ).
<security-identity>Необязателен.
Определяет, какую логическую роль будет играть данный компонент при обращениях к другим компонентам. Для этого может быть использован вложенный тег <run-as><role-name>…</role-name></run-as> для указания имени конкретной логической роли, или <use- для указания того, что нужно использовать роль вызывающего клиента.
<session-type>Требуется ровно один, используется в описании
Имеет значения Stateful или , в зависимости от того, использует ли данный компонент
<transaction-type>Требуется ровно один, используется в описании
Имеет значения Container или Bean, в зависимости от того, управляет ли транзакциями данного компонента контейнер или он сам. В первом случае соответствующие транзакции должны быть описаны в разделе <assembly-descriptor> (см. далее).
<query>Один или более, необязателен.
Используется для описания запросов, с чьей помощью реализуются некоторые методы <query-method>. Сам код запроса описывается внутри элемента CDATA во вложенном теге <ejb-ql>.
Например
<query>
<query-method>
<method-name>findByName</method-name>
<method-params>
<method-param>java.lang.String</method-param>
</method-params>
</query-method>
<ejb-ql>
<!CDATA[
SELECT OBJECT(c) FROM Client c WHERE c.name = ?1
]]
</ejb-ql>
</query>
<relationships>Необязателен. Вложен в <ejb-jar>.
Описывает набор отношений между компонентами, которые соответствуют связям в схеме базы данных и автоматически поддерживаются контейнером. Каждое отношение описывается с помощью вложенного тега <ejb-relation>.
<ejb-relation>Описывает одно отношение и может иметь следующие элементы.
<ejb-relation-name>Необязателен, только один. Задает имя отношения.
<ejb-relationship-role>Обязательно два. Описывает одну роль в рамах отношения. В описании роли должны присутствовать следующие данные.
<ejb-relationship-role-name>.<multiplicity> и может иметь значения One или Many.<relationship-role-source> внутри тега <ejb-name> в виде имени, которое присвоено компоненту в рамках данного дескриптора.<cmr-field>, во вложенном теге <cmr-field-name>, и для него в классе компонента должно быть определено абстрактное свойство с тем же именем.<assembly-descriptor>Этот обязательный тег внутри <ejb-jar> содержит дополнительные указания для сборки компонентов, в частности следующие.
<container-transaction>Один или более, необязателен.
Содержит необязательный элемент <description>, а также приведенные ниже.
Для
<method>Один или более.
Содержит тег <ejb-name>, указывающий имя компонента, и <method-name>, указывающий имя метода или знак *, который обозначает применение указанного атрибута ко всем методам.
Может также включать элементы <description>, <method-params> и <method-intf>, который может иметь значения Remote, Home, Local, Local-Home, в зависимости от того, в каком интерфейсе этот метод декларирован — для поддержки возможности декларировать методы с одним именем и набором параметром в разных интерфейсах.
<trans-attribute>Ровно один.
Определяет атрибут транзакции, управляющий политикой включения в транзакции или создания новых транзакций.
Для
Может иметь значения NotSupported, Supports, Required, RequiresNew, . Об их смысле рассказывалось в предыдущей лекции.
<security-role>Один или более, необязателен.
Определяет роли, служащие для контроля доступа к методам компонентов. В таком элементе должен содержаться тег <role-name>, задающий
<method-permission> Один или более, необязателен.
Указывает правила доступа ролей, определенных в тегах <security-role>, к методам компонентов.
Содержит необязательный тег <description>, один или несколько тегов <role-name> и один или несколько тегов <method> (см. выше), кроме того, в нем может присутствовать тег <, который обозначает отсутствие проверки прав доступа во время работы, даже если они описаны.
Каждый тег <method> содержит тег <ejb-name>, указывающий имя компонента, и <method-name>, указывающий имя метода или знак *, который обозначает применение указанного атрибута ко всем методам.
<exclude-list>Необязателен.
Содержит один или несколько тегов <method> (см. выше), определяющих методы, которые не должны вызываться при работе приложения. Каждый вызов такого метода создает исключительную ситуацию.
В среде .NET нет средств, полностью аналогичных тем, которые предоставляются в J2EE для разработки
Классы ADO.NET располагаются в сборке System.Data (дополнительные классы можно найти в System.Data.OracleClient и System.Data.SqlXml ) и пространстве имен System.Data, вместе с вложенными в него пространствами.
Основным классом, с помощью которого представляются данные из базы данных, является System.Data.DataSet. Он представляет набор таблиц, связанных между собой некоторыми связями и выполняющими определенные ограничения. Каждая таблица представляется объектом класса System.Data.DataTable, каждая связь — объектом класса System.Data.Relation, каждое ограничение — объектом класса System.Data.Constraint. Структура таблиц описывается с помощью их полей (представляемых объектами System.Data.DataColumn ). Содержимое одной таблицы представлено как набор объектов-записей, имеющих тип System.Data.DataRow.
Из перечисленных классов только DataSet и DataTable являются
Объект класса DataSet может представлять собой и набор данных документа XML. Получить такой объект можно с помощью класса System.Xml.XmlDataDocument.
Само взаимодействие с источником данных происходит с помощью объектов классов DataAdapter, DataReader, DbConnection, DbTransaction, DbCommand и производных от них, специфичных для того или иного вида источников данных (в рамках поставляемых в составе среды Visual Studio .NET библиотек имеются специфичные классы для работы с источниками ODBC, OleDB, MS SQL Server, Oracle). Все перечисленные классы находятся в пространстве имен System.Data.Common, а их производные для данного вида источников данных — в соответствующем этому виду источников подпространстве System.Data.
Объекты классов DataAdapter и DataReader служат для чтения и записи данных в виде объектов DataSet. Остальные классы используются для определения соединений, организации транзакций, определения и выполнения SQL-команд по чтению или изменению данных.
Ниже приводится простой пример работы с данными с помощью библиотек ADO.NET.
DbConnection connection = new SqlConnection("Data Source=localhost;" +
"Integrated Security=SSPI;Initial Catalog=DBCatalog");
DbCommand command = new SqlCommand("SELECT ID, Title, ISBN FROM Book",
connection);
DataAdapter adapter = new SqlDataAdapter();
Adapter.SelectCommand = command;
connection.Open();
DataSet dataset = new DataSet();
adapter.Fill(dataset, "Book");
connection.Close();
Прежде чем перейти к построению интерфейса пользователя в Web-приложениях на основе J2EE и .NET, стоит рассмотреть основные элементы
HTTP (Hypertext Transfer Protocol, протокол передачи гипертекста) представляет собой протокол прикладного уровня, использующий для пересылки данных протокол транспортного уровня. Достаточно подробное описание его можно найти в [5,6].
Сообщения HTTP бывают двух видов: запросы клиента и ответы сервера.
Запрос HTTP состоит из идентификации метода запроса, универсального идентификатора запрашиваемого ресурса (Universal Resource Identifier, URI), указания версии протокола и, возможно, набора заголовков с дополнительной информацией, а также поля данных общего вида.
<Request> ::= GET <URI> CrLf
| <Method> <URI> <HTTP-Version> CrLf
<Req-Header>* ( <Data> )?
<Req-Header> ::= <Field> : <Value> CrLf
CrLf ::= '\r''\n'
Основные методы
GETСлужит для получения любой информации по URI запроса, обычно — документа, хранящегося по указанному адресу или генерируемого по запросу с таким URI. Может иметь заголовок If-Modified-Since, который предписывает не посылать тело запрашиваемого ресурса, если он не изменялся с указанной даты.
POSTСлужит для создания нового ресурса, связанного с указанным по URI. Чаще всего используется для аннотации ресурсов, добавления сообщений в группы новостей, дистанционной работы с базами данных. Реальная обработка такого запроса зависит от содержащегося в нем URI.
Остальные методы — HEAD, PUT, DELETE, LINK, UNLINK — используются гораздо реже.
Заголовки запроса служат для передачи дополнительной информации об этом запросе или о клиенте. Заголовок состоит из идентификатора поля и его значения, разделенных двоеточием, и бывает одного из следующих типов.
FromСодержит e-mail адрес пользователя, под чьим именем работает клиент.
Пример: From:
Accept, Accept-Encoding, Accept-Charset и Accept-LanguageВ таком заголовке через запятую перечисляются возможные форматы (соответственно, кодировки, используемые таблицы символов и языки) ответов на данный запрос.
Пример: Accept: text/
User-AgentСодержит название используемой клиентской программы.
RefererИспользуется для указания адреса ресурса, с которого был получен данный запрос.
If-Modified-SinceИспользуется для отмены ответной пересылки документов, модифицированных не позднее указанной даты, с целью снижения нагрузки на сеть.
AuthorizationСодержит авторизационную информацию, специфичную для используемых сервером протоколов авторизации.
ChargeToСодержит информацию о том, куда выставить счет за обработку запроса.
PragmaСодержит дополнительные директивы для промежуточных серверов, например, прокси-серверов.
Пример запроса.
GET /locate?keywords=HTTP+description HTTP/1.1 Date: Mon, 15 Dec 2004 12:18:15 GMT Accept: image/gif, image/jpg, */* Accept-Charset: iso-8859-1, *, utf-8 Accept-Language: en Connection: keep-Alive User-Agent: Mozilla/4.7 [en] (Win98; u)
| Группа кодов | Код | Фраза-объяснение, следующая за кодом | Значение кода |
|---|---|---|---|
| 1xx | Информационное сообщение | ||
| 2xx | Успешная обработка | ||
| 200 | OK | Вcе нормально | |
| 201 | Created | Документ создан | |
| 3xx | Перенаправление запроса | ||
| 301 | Moved Permanently | Ресурс перемещен | |
| 302 | Moved |
Ресурс перемещен временно | |
| 4xx | Ошибка клиента | ||
| 400 | Bad Request | Некорректно составленный запрос | |
| 401 | Нужна аутентификация клиента | ||
| 403 | Forbidden | Доступ к ресурсу запрещен | |
| 404 | Not Found | Запрашиваемый ресурс отсутствует | |
| 5xx | Ошибка сервера | ||
| 500 | Internal |
Внутренняя ошибка сервера |
Ответ сервера на HTTP-запрос состоит либо только из запрашиваемого клиентом документа, либо в дополнение к нему содержит код статуса ответа и, возможно, несколько заголовков ответа.
<Response> ::= ( <Content> )?
| <HTTP-Version> <Code> <Explanation> CrLf
<Resp-Header>* ( <Content> )?
<Resp-Header> ::= <Field> : <Value> CrLf
CrLf ::= '\r''\n'
Некоторые коды статуса ответа поясняются в табл. 12.
Возможны следующие заголовки ответа:
AllowedПеречисляются через пробел доступные для пользователя методы запросов по данному URI.
PublicПеречисляет доступные всем методы запросов.
Content-Length, Content-Type, Content-Encoding и Content-LanguageЗадают размер содержимого в байтах (подразумевается, что содержимое имеет бинарный формат и не должно разбиваться на строки при чтении), его формат или MIME-тип, кодировку и язык.
DateДата создания содержащегося документа или объекта.
Last-ModifiedДата последнего изменения содержащегося объекта.
ExpiresДата, после которой содержащийся объект считается устаревшим.
URIURI содержащегося объекта.
TitleЗаголовок содержащегося документа.
ServerОписывает серверную программу.
Retry-AfterОпределяет промежуток времени на обработку запроса, до прохождения которого не надо направлять запрос повторно, если ответа на него еще нет.
Пример HTTP-ответа.
HTTP/1.0 200 OK Content-Length: 2109 Content-Type: text/html Expires: 0 Last-Modified: Thu, 08 Feb 2001 09:23:17 GMT Server: Apache/1.3.12 <HTML> <HEAD> <TITLE> … </TITLE> </HEAD> <BODY> … </BODY> </HTML>
Компоненты пользовательского интерфейса в Web-приложениях, построенных как по технологии J2EE, так и по .NET, реализуют обработку HTTP-запросов, приходящих от браузера, и выдают в качестве результатов HTTP-ответы, содержащие сгенерированные HTML-документы с запрашиваемыми данными. Сами запросы автоматически строятся браузером на основе действий пользователя — в основном, переходов по ссылкам и действий с элементами управления в HTML-формах.
Если стандартных
В рамках J2EE версии 1.4 два основных вида компонентов WebUI —
Интерфейс Java- javax. и javax., являющихся частью J2EE SDK. Первый пакет содержит классы, описывающие независимые от протокола
Основные классы и интерфейсы пакета javax. следующие.
HttpServletПредназначен для реализации void doGet(HttpServletRequest, HttpServletResponse), определяющий обработку GET-запросов, и void doPost(HttpServletRequest, HttpServletResponse), обрабатывающий POST-запросы. В обоих методах первый параметр содержит всю информацию о запросе, а второй — о генерируемом ответе.
HttpServletRequest и HttpServletResponse — интерфейсы, содержащие методы для получения и установки (второй) заголовков и других атрибутов HTTP-запросов и ответов. Второй интерфейс также содержит метод, возвращающий поток вывода для построения содержимого ответа.CookieКласс, представляющий закладки сервера, которые хранятся на клиентской машине для запоминания информации о данном пользователе.
HTTPSessionИнтерфейс, предоставляющий методы для управления сеансом обмена HTTP-сообщениями. Информация о сеансе используется в том случае, если она должна быть доступна нескольким
При развертывании J2EE-приложения, помимо самих классов
Web-приложение поставляется в виде архива .war, содержащего все его файлы. На самом деле это zip-архив, расширение .war нужно для того, чтобы Web-контейнер узнавал архивы развертываемых на нем Web-приложений. Содержащаяся в этом архиве структура директорий Web-приложения должна включать директорию WEB-INF, вложенную непосредственно в корневую директорию приложения. Директория WEB-INF содержит две поддиректории — classes для .class-файлов
Заголовок
<!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc...ВЕВ Web Application 2.2.. EN" http://java.sun.com/j2ee/dtds/web-app_2_2.dtd>
Содержимое <web-app>. В нем указывается список
<servlet>
<servlet-name>ServletName</servlet-name>
<servlet-class>com.company.deprtment.app.ServletClassName</servlet-class>
<description>…</description>
<init-param>
<param-name>ParameterName</param-name>
<param-value>ParameterValue</param-value>
<description>…</description>
</init-param>
</servlet>
Значения параметров инициализации String getInitParameter(String) и Enumeration getInitParametersNames() связанных с ServletContext.
Отображение
<servlet-mapping> <servlet-name>ServletName</servlet-name> <url-pattern>URL</url-pattern> </servlet-mapping>
При работе Web-приложения doGet(), в котором HTML-элементы записываются в поток содержимого ответа в неизменном виде, а элементы Java-кода преобразуются в код, записывающий некоторые данные в тот же поток на основании параметров запроса или данных приложения.
Для развертывания
Основные интерфейсы и базовые классы javax..
Элементами
Директивы имеют следующий общий синтаксис.
<%@ directive attribute1="value1" ... attributeN="valueN" %>.
Основные директивы
import = "имена включаемых классов и пакетов через запятую"Порождает соответствующую Java-директиву import в сгенерированном коде
contentType = "MIME-тип[;charset=таблица символов]"Задает тип MIME для генерируемого документа. По умолчанию используется text/html. Эквивалентен скриплету
<% response.setContentType(MIME-тип); %> (см. далее).
isThreadSafe = "true|false"Значение true позволяет использовать один экземпляр
session = "true|false"Значение true предписывает привязать
autoFlush = "true|false"Определяет необходимость сбрасывать буфер вывода при заполнении.
buffer = "размер в KB|none"Задает размер буфера для выходного потока
extends = "наследуемый класс"Определяет класс, наследуемый сгенерированным из данной
errorPage = "url странички с информацией об ошибках"Определяет страницу, которая используется для обработки исключений, не обрабатываемых в рамках данной.
isErrorPage = "true|false"Допускает или запрещает использование данной страницы в качестве страницы обработки ошибок.
language = "java"Определяет язык программирования, применяемый в скриптовых элементах данной страницы. Пока есть возможность использовать только Java. Впоследствии предполагается (аналогично .NET) разрешить использование других языков, код которых будет также транслироваться в байт-код, интерпретируемый JVM.
include обеспечивает статическое (в ходе трансляции file, значением которого должна быть строка, задающая URL taglib указывает используемую в данной странице библиотеку пользовательских тегов. Она имеет два атрибута — uri, значением которого является URI библиотеки, и prefix, определяющий префикс тегов из данной библиотеки. Префикс употребляется в дальнейшем с тегами только данной библиотеки. Он не может быть пустым и не должен совпадать с одним из зарезервированных префиксов jsp , jspx, java, javax, servlet , sun, sunw.Теги или действия определяют основные действия, выполняемые при обработке данных и построении результирующего документа.
Теги могут быть стандартными, использование которых возможно в любой странице без дополнительных объявлений, или пользовательскими, которые могут употребляться, только если предварительно с помощью директивы taglib была подключена содержащая их библиотека. Любой тег имеет следующий синтаксис.
<tagprefix:tag attribute1="value1" … attributeN="valueN" />
Теги могут содержать вложенные теги, такие как . В этом случае они выглядят следующим образом.
<tagprefix:tag attribute1="value1" … attributeN="valueN"> … (вложенные теги) </tagprefix:tag>
Стандартные теги имеют префикс , а префикс пользовательских тегов определяется в директиве taglib, подключающей содержащую их библиотеку.
Имеется довольно много стандартных тегов. Основные из них следующие.
jsp :includeОпределяет динамическое включение некоторой страницы или файла в данную страницу при обработке запроса. С помощью вложенных тегов может указывать один или несколько пар параметр-значение в качестве параметров включаемой страницы.
Имеет атрибуты page, определяющий URL включаемой страницы, и flush, имеющий значения true или false в зависимости от того, нужно ли сразу после включения сбросить буфер выходного потока в генерируемом ответе или нет.
jsp :useBeanОпределяет используемый объект или компонент. Фактически такой тег эквивалентен декларации переменной определенного типа, инициализируемой определенным объектом и доступной в рамках некоторого контекста.
Имеет следующие атрибуты.
id = "имя объекта"Задает имя объекта, которое будет использоваться в коде
class = "класс объекта"Задает класс этого объекта.
scope = "page|request|session|application"Задает область видимости декларируемого объекта.
type = "тип используемой ссылки на объект"Указанный тип должен быть предком класса объекта. Это тип декларируемой переменной, а класс объекта определяет истинный тип объекта, хранящегося в ней.
jsp :setProperty, jsp :getPropertyУстанавливает или получает значение свойства объекта.
Атрибут name определяет имя объекта, чье свойство используется, а атрибут property — имя свойства.
Тег записывает полученное значение свойства в результирующий документ в виде строки (результата вызова toString() для этого значения).
Тег имеет также дополнительный атрибут — либо value, значение которого присваивается свойству, либо param, который указывает имя параметра запроса, значение которого записывается в свойство. Если в теге вместо имени свойства в атрибуте property указан символ *, то всем свойствам указанного объекта с именами, совпадающими с именами параметров запроса, будут присвоены значения соответствующих параметров.
jsp :forwardЭтот тег употребляется для перенаправления запроса на обработку другой странице. URL этой страницы указывается в качестве значения атрибута page. В качестве этого URL может использоваться
С помощью вложенных тегов можно передать одно или несколько значений параметров странице, на которую переключается управление.
jsp :pluginЭтот тег вставляет аплет или компонент . Кроме того, имеет следующие атрибуты.
type = "bean|applet"Задает вид вставляемого компонента.
code = "имя файла класса компонента (включая расширение .class)"codebase = "имя директории, в которой находится файл класса компонента"Если этот атрибут отсутствует, используется директория, содержащая данную
name = "имя используемого экземпляра компонента"archive = "список разделенных запятыми путей архивных файлов, которые будут загружены перед загрузкой компонента"Эти архивы содержат дополнительные классы и библиотеки, необходимые для работы компонента.
align = "bottom|top|middle|left|right"Задает положение экземпляра компонента относительно базовой строки текста содержащего его HTML-документа.
height = "высота изображения объекта в точках"width = "ширина изображения объекта в точках"hspace = "ширина пустой рамки вокруг объекта в точках"vspace = "высота пустой рамки вокруг объекта в точках"jreversion = "версия JRE , необходимая для работы компонента"По умолчанию используется версия 1.1.
Пользовательские теги могут быть определены для выполнения самых разнообразных действий. Одна из наиболее широко используемых библиотек тегов core (подключаемая с помощью директивы <%@ taglib uri="http://java.sun.com/ ), содержит теги, представляющие все конструкции языка Java.
Например, с помощью тега <c:set var="variable" value="value" /> можно присвоить значение value в переменную variable, с помощью тега <c:if test="expression">…</c:if> можно выполнить код expression имеет значение true, с помощью тега <c:forEach var="variable" items="collection">…</c:forEach> можно выполнить содержащийся в нем код для всех элементов коллекции collection, используя для обращения к текущему элементу переменную variable.
Таким образом, весь код, который может быть записан в виде скриптовых элементов (см. далее), можно записать и в виде тегов. Применение тегов при этом вносит некоторые неудобства для Java-программиста. Но оно же делает код
Скриптовые элементы могут иметь один из следующих трех видов.
<%! код на Java %>
<% код на Java %>
<% = выражение на Java %>
${выражение на Java}
#{выражение на Java}
Различий между первым и вторым способом представления выражений практически нет. Выражение третьего типа вычисляется отлаженно — вычисление его значения происходит только тогда, когда это значение действительно понадобится.
Комментарии в коде <%-- … --%>. Встречающийся в них код не обрабатывается во время трансляции и не участвует в работе полученного <!-- … --> обрабатываются так же, как и в других местах — они генерируют содержимое комментариев в результирующем HTML-документе.
Помимо объявленных в объявлениях и тегах переменных в скриптовых элементах могут использоваться неявно доступные объекты, связанные с результирующим
request — запрос клиента (тип ServletRequest ).param — параметры запроса (тип Map ).response — ответ сервера (тип ServletResponse ).out — выходной поток PrintWriter ).session — сеанс (тип HttpSession ).application —приложение ( ServletContext ).config — конфигурация ServletConfig ).pageContext — javax.servlet .jsp .PageContext ).exception — произошедшее исключение.Ниже приведен пример
<%@ page import="java.util.Date, java.util.Iterator,
com.company.Client" %>
<jsp:useBean id="clients" class="com.company.ClientList"
scope="page" />
<jsp:useBean id="convertor" class="com.company.ExchangeRate"
scope="page" />
<html>
<head>
<title>Table of clients</title>
</head>
<body>
<h3 align="center">Table of clients</h3>
Created on <%= new Date() %> <br><br>
<table width="98%" border="1" cellspacing="1" cellpadding="1">
<tr>
<%!
private double dollarsToRubles(double m)
{
return m*convertor.getDollarToRubleRate(new Date());
}
%>
<th width="50%" scope="col">Client</th>
<th width="25%" scope="col">Balance, dollars</th>
<th width="25%" scope="col">Balance, rubles</th>
</tr>
<%
Iterator it = clients.getNumberOfClients().iterator();
while(it.hasNext())
{
Client сlient = (Client)it.next();
%>
<tr>
<td> ${client.getFullName()} </td>
<td> ${client.getBalance()} </td>
<td> ${dollarsToRubles(client.getBalance())} </td>
</tr>
<%
}
%>
</table> <br><br>
<jsp: include page="footer.txt" flush= "true" />
</body>
</html>
Разработка компонентов пользовательского интерфейса Web-приложений в рамках .NET выделена в виде отдельной технологии ASP.NET [9,10] и в целом очень похожа на разработку тех же компонентов в J2EE. В .NET имеются те же виды компонентов: элементы управления, представленные серверными элементами управления HTML (HTML server controls) и просто серверными элементами управления (Web Server Controls), обработчики http-запросов (аналог IHttpHandler и IHttpAsyncHandler, и так называемые Web-формы (Web-forms), аналог
Элементы управления WebUI в .NET могут быть размещены на HTML-страницах, но выполняются на сервере. Библиотеки таких компонентов находятся в сборке System.Web и в пространстве имен System.Web.UI, вместе с его подпространствами. Их употребление в рамках HTML-документа оформляется в виде специальных тегов с атрибутом runat, имеющим значение server. Ниже приведен пример использования компонента System.Web.UI.WebControls.Button в коде Web-формы:
<%@ Page Language="C#" AutoEventWireup="True" %>
<html>
<head>
<script language="C#" runat=server>
void OnButtonClick(object sender, EventArgs e)
{
Message.Text="Hello World!!";
}
</script>
</head>
<body>
<form runat="server">
<h3>Button Example</h3>
Click on the submit button.<br><br>
<asp:Button id="MyButton"
Text="Submit"
OnClick="OnButtonClick"
runat="server"/>
<p>
<asp:label id="Message" runat="server"/>
</form>
</body>
</html>
Аналогом System.Web.IHttpHandler и System.Web.IHttpAsyncHandler. Оба они являются частью программного интерфейса Web-сервера Microsoft (Internet Server Application Program Interface, ISAPI). Первый интерфейс предназначен для синхронной обработки запросов, с блокированием на время обработки вызвавшего ее потока Web-сервера. Второй интерфейс позволяет реализовывать такую обработку в отдельном потоке.
Единственный метод первого интерфейса — void ProcessRequest (System.Web.HttpContext context). Все данные, связанные с запросом, ответом на него, приложением и контекстом, в котором работает данный обработчик, можно получить, используя различные свойства параметра этого метода.
Интерфейс IHttpAsyncHandler имеет два метода — IAsyncResult BeginProcessRequest( HttpContext context, AsyncCallback cb, object extraData) и void EndProcessRequest( IAsyncResult result). Первый вызывается при передаче запроса данному обработчику, второй — для прекращения обработки.
Специальные конструкции
Директивы <%@ directive attribute1="value1" ... attributeN="valueN" %>. Список директив шире, чем в Import, аналог include, директива Control для описания пользовательских элементов управления, директива Register для определения синонимов (алиасов), и пр.
Объявления полей данных и методов в Web-формах обрамляются в тег <script> … </script>. Такой тег должен иметь атрибут runat со значением server и атрибут language, который определяет язык кода, написанного внутри тега. Он может также иметь атрибут src для указания URL файла, код из которого должен быть вставлен перед содержимым тега.
Конструкции встроенного кода обрамляются в тег <% … %>. Как и в <%=… %>. Комментарии тоже оформляются, как и в <%-- … --%>.
Конструкции привязки к данным имеют синтаксис <%# expression %> и работают примерно так же, как и выражения встроенного кода. Они могут использоваться и в значениях атрибутов элементов управления.
Конфигурационные файлы компонентов .NET, являющиеся аналогами configuration. Он может содержать теги location, которые определяют конфигурацию для ресурсов, путь к которым указывается в атрибуте path таких тегов. Теги location для компонентов ASP.NET содержат тег system.web, который, в свою очередь, может содержать следующие теги (перечислены не все возможные, более полную информацию см. в [11]).
authenticationОпределяет используемый вид аутентификации — атрибут mode задает используемый механизм (Windows, Forms, forms описывают свойства отдельных форм, используемых для аутентификации.
authorizationОпределяет права доступа для пользователей, ролей и отдельных методов HTTP-запросов. Разрешения на доступ указываются в атрибутах вложенного теги allow, запреты — в атрибутах вложенного тега deny.
compilationОпределяет параметры компиляции компонента ASP.NET.
customErrorsОпределяет специфические для данного приложения ошибки и URL, на которые переходит управление при возникновении этих ошибок.
globalizationОпределяет кодировки и локализацию запросов и ответов.
httpHandlersОпределяет отображение адресов и методов запросов на обрабатывающие их объекты типа IHttpHandelr или IHttpHandlerFactory.
pagesОпределяет настройки для отдельных страниц.
sessionStateОписывает настройки для поддержки
Для получения официальных документов о завершении программы дополнительного профессионального образования (удостоверения о повышении квалификации, дипломов о профессиональной переподготовке и MBA) необходимо предоставить:
Внимание! Вы можете не заказывать доставку бумажной версии официального документы, а скачать его в электронном виде и распечатать самостоятельно. Информация о выданном документе в течение 1 месяца загружается в Федеральную информационную систему «Федеральный реестр сведений о документах об образовании и (или) о квалификации, документах об обучении» - ФИС ФРДО.
Доступ на новый сайт осуществляется с использованием адреса электронной почты, который был указан вами при регистрации на "старом". Мы постарались перенести все ваши данные с прежнего ресурса, однако не исключена вероятность потери части информации.
При возникновении проблемы со входом, воспользуйтесь функцией сброса пароля
Если вы обнаружите несоответствия, пожалуйста, сообщите нам.