- •Оглавление
- •Предисловие
- •Введение
- •Часть I Обзор Глава 1 "Расслоение" системы
- •Развитие модели слоев в корпоративных программных приложениях
- •Три основных слоя
- •Где должны функционировать слои
- •Глава 2 Организация бизнес-логики
- •Выбор типового решения
- •Глава 3 Объектные модели и реляционные базы данных
- •Архитектурные решения
- •Функциональные проблемы
- •Считывание данных
- •Взаимное отображение объектов и реляционных структур
- •Отображение связей
- •Наследование
- •Реализация отображения
- •Двойное отображение
- •Использование метаданных
- •Соединение с базой данных
- •Другие проблемы
- •Дополнительные источники информации
- •Глава 4 Представление данных в Web
- •Типовые решения представлений
- •Типовые решения входных контроллеров
- •Дополнительные источники информации
- •Глава 5 Управление параллельными заданиями
- •Проблемы параллелизма
- •Контексты выполнения
- •Изолированность и устойчивость данных
- •Стратегии блокирования
- •Предотвращение возможности несогласованного чтения данных
- •Разрешение взаимоблокировок
- •Транзакции
- •Типовые решения задачи обеспечения автономного параллелизма
- •Параллельные операции и серверы приложений
- •Дополнительные источники информации
- •Глава 6 Сеансы и состояния
- •В чем преимущество отсутствия "состояния"
- •Состояние сеанса
- •Глава 7 Стратегии распределенных вычислений
- •Соблазны модели распределенных объектов
- •Интерфейсы локального и удаленного вызова
- •Когда без распределения не обойтись
- •Сужение границ распределения
- •Интерфейсы распределения
- •Глава 8 Общая картина
- •Предметная область
- •Источник данных
- •Платформы и инструменты
- •Другие модели слоев
- •Часть II Типовые решения Глава 9 Представление бизнес-логики Сценарий транзакции (Transaction Script)
- •Модель предметной области (Domain Model)
- •Модуль таблицы (Table Module)
- •Слой служб (Service Layer)
- •Глава 10 Архитектурные типовые решения источников данных Шлюз таблицы данных (Table Data Gateway)
- •Шлюз записи данных (Row Data Gateway)
- •Активная запись (Active Record)
- •Преобразователь данных (Data Mapper)
- •Глава 11 Объектно-реляционные типовые решения, предназначенные для моделирования поведения Единица работы (Unit of Work)
- •Коллекция объектов (Identity Map)
- •Загрузка по требованию (Lazy Load)
- •Глава 12 Объектно-реляционные типовые решения, предназначенные для моделирования структуры Поле идентификации (Identity Field)
- •Отображение внешних ключей (Foreign Key Mapping)
- •Отображение с помощью таблицы ассоциаций (Association Table Mapping)
- •Отображение зависимых объектов (Dependent Mapping)
- •Внедренное значение (Embedded Value)
- •Сериализованный крупный объект (Serialized lob)
- •Наследование с одной таблицей (Single Table Inheritance)
- •Наследование с таблицами для каждого класса (Class Table Inheritance)
- •Наследование с таблицами для каждого конкретного класса (Concrete Table Inheritance)
- •Преобразователи наследования (Inheritance Mappers)
- •Глава 13 Типовые решения объектно-реляционного отображения с использованием метаданных Отображение метаданных (Metadata Mapping)
- •Объект запроса (Query Object)
- •Хранилище (Repository)
- •Глава 14 Типовые решения, предназначенные для представления данных в Web Модель-представление-контроллер (Model View Controller)
- •Контроллер страниц (Page Controller)
- •Контроллер запросов (Front Controller)
- •Представление по шаблону (Template View)
- •Представление с преобразованием (Transform View)
- •Двухэтапное представление (Two Step View)
- •Контроллер приложения (Application Controller)
- •Глава 15 Типовые решения распределенной обработки данных Интерфейс удаленного доступа (Remote Facade)
- •Объект переноса данных (Data Transfer Object)
- •Глава 16 Типовые решения для обработки задач автономного параллелизма Оптимистическая автономная блокировка (Optimistic Offline Lock)
- •Пессимистическая автономная блокировка (Pessimistic Offline Lock)
- •Блокировка с низкой степенью детализации (Coarse-Grained Lock)
- •Неявная блокировка (Implicit Lock)
- •Глава 17 Типовые решения для хранения состояния сеанса Сохранение состояния сеанса на стороне клиента (Client Session State)
- •Сохранение состояния сеанса на стороне сервера (Server Session State)
- •Сохранение состояния сеанса в базе данных (Database Session State)
- •Глава 18 Базовые типовые решения Шлюз (Gateway)
- •Преобразователь (Mapper)
- •Супертип слоя (Layer Supertype)
- •Отделенный интерфейс (Separated Interface)
- •Реестр (Registry)
- •Объект-значение (Value Object)
- •Деньги (Money)
- •Частный случай (Special Case)
- •Дополнительный модуль (Plugin)
- •Фиктивная служба (Service Stub)
- •Множество записей (Record Set)
- •Список типовых решений
- •Шпаргалка
- •Как управлять сложным потоком функций приложения?
- •Как взаимодействовать с базой данных?
- •Как избежать загрузки в оперативную память всего содержимого базы данных?
- •Как сохранить структуры наследования в реляционной базе данных?
Глава 17 Типовые решения для хранения состояния сеанса Сохранение состояния сеанса на стороне клиента (Client Session State)
Сохраняет состояние сеанса на стороне клиента
Принцип действия
Даже если дизайн корпоративной системы полностью ориентирован на использование серверных средств, часть сведений о сеансе (будь то его идентификатор или еще что-нибудь) приходится располагать на стороне клиента. В некоторых приложениях на сторону клиента помещают всю информацию о состоянии сеанса. В этом случае клиент передает серверу все сведения о сеансе вместе с каждым запросом, а сервер возвращает все сведения о сеансе вместе с каждым ответом. Подобная схема позволяет серверу полностью отказаться от сохранения состояний сеанса.
В большинстве случаев для перемещения данных между клиентом и сервером используется объект переноса данных (Data Transfer Object). Он может сериализовать свое содержимое для передачи по сети, тем самым позволяя перемещать весьма сложные структуры данных.
Клиент также нуждается в способе хранения данных. Если речь идет о толстом клиенте, хранение данных может осуществляться за счет собственных структур приложения, например полей его интерфейса (хотя я бы предпочел застрелиться, чем поступать таким образом). Гораздо более удачным решением является хранение состояний сеансов в совокупности невизуализированных объектов, например в модели домена или в самом объекте переноса данных. В любом случае, это не такая уж серьезная проблема.
С HTML-интерфейсами дело обстоит немного сложнее. Существует три основных способа сохранения состояния сеанса на стороне клиента: параметры адреса URL, скрытые поля и файлы cookie.
Использование параметров адреса URL хорошо подходит для работы с небольшим количеством данных. Вообще говоря, для отображения Web-страницы с результатами выполнения запроса все адреса URL принимают то или иное количество параметров сеанса. Разумеется, объем сохраняемой информации существенно ограничен размерами адресов. Тем не менее данный метод прекрасно справляется с двумя-тремя параметрами, поэтому он весьма популярен для хранения на стороне клиента небольших значений наподобие идентификаторов сеансов. Некоторые платформы автоматически перезаписывают адреса URL, добавляя к ним идентификаторы сеансов. Изменение адреса Web-страницы может повлиять на работу закладок, поэтому данную схему хранения не рекомендуется использовать на коммерческих сайтах, связанных с обслуживанием потребителей.
Скрытое поле — это поле, значение которого передается обозревателю, но не отображается на Web-странице. Наличие скрытого поля задается дескриптором вида <input type = "hidden">. Чтобы сохранить данные на стороне клиента, сервер сериализует состояние сеанса, помещает его в скрытое поле при отправке ответа и вновь считывает при получении следующего запроса. Как только что отмечалось, помещаемые в скрытое поле данные должны быть сериализованы. Обычно в качестве формата сериализации применяют XML, хотя, как известно, он слишком "многословен". Вместо этого данные можно сериализовать и в какой-нибудь другой текстовый формат. Не забывайте, однако, что значение скрытого поля скрыто только во время отображения; чтобы добраться к этому значению, достаточно просмотреть исходный код страницы.
Остерегайтесь сайтов, содержащих старые Web-страницы или страницы с фиксированными адресами. Переместившись на них, вы потеряете всю информацию о состоянии сеанса.
Последний, пожалуй наиболее спорный, метод хранения состояний сеанса — это использование файлов cookie, которые автоматически передаются от сервера к клиенту и наоборот. Как и при работе со скрытыми полями, помещаемые в файл cookie данные нужно сериализовать. Объем сохраняемой информации ограничивается размерами файлов — они не должны быть слишком большими. Кроме того, многим пользователям не нравится присутствие файлов cookie, поэтому их отключают, в результате чего сайт перестанет функционировать. Тем не менее в наше время все больше и больше сайтов основаны на использовании файлов cookie, поэтому подобные неприятности случаются нечасто. И конечно, наличие этих файлов не представляет никакой опасности для чисто "домашних" систем.
Не забывайте: файлы cookie безопасны не более чем другие способы хранения информации, а значит, несанкционированное использование данных возможно и здесь. Кроме того, файлы cookie работают только в пределах одного имени домена, поэтому, если ваш сайт разнесен по нескольким доменам, файлы cookie не смогут перемещаться между его частями.
Некоторые платформы автоматически определяют, разрешено ли на стороне клиента использование файлов cookie; если это не так, они применяют перезаписывание адресов URL. Данная схема позволяет легко сохранять на стороне клиента небольшие объемы сведений о сеансе.
Назначение
Типовое решение сохранение состояния сеанса на стороне клиента обладает массой преимуществ. В частности, оно поддерживает использование серверных объектов без состояний, обеспечивая максимальную степень кластеризации и устойчивости к отказам.
Разумеется, при отказе системы клиента все данные будут утеряны, однако в подобных ситуациях большинство клиентов ожидают именно такого исхода.
Количество аргументов против сохранения состояния сеанса на стороне клиента стремительно возрастает с увеличением объема сохраняемой информации. Все перечисленные схемы прекрасно подходят для хранения нескольких полей, однако при наличии больших объемов данных вопросы их размещения и временные расходы, вызванные передачей вместе с каждым запросом большого количества информации, становятся весьма критичны. Это особенно верно для HTTP-клиентов.
Применение данного типового решения связано и с проблемами безопасности. Сведения, отсылаемые клиенту, могут быть перехвачены и изменены. Единственный способ предотвратить подобные поползновения — воспользоваться шифрованием, однако шифрование и дешифровка каждого запроса может нанести большой урон производительности приложения. С другой стороны, все, что не было зашифровано, является потенциальной мишенью для любознательных глаз. Как правило, их хозяева обладают к тому же "пронырливыми" пальцами, поэтому не ожидайте, что сведения о состоянии сеанса вернутся в том же виде, в каком они были отосланы. Все данные, возвращаемые клиентом, должны быть подвергнуты тщательной проверке на правильность.
Без сохранения состояния сеанса на стороне клиента не обойтись при необходимости хранить идентификаторы сеансов. К счастью, идентификатор — это всего лишь число, поэтому проблем с его обработкой в перечисленных выше схемах быть не должно. Тем не менее попытки перехвата данных случаются и здесь, например если злоумышленник изменит идентификатор своего сеанса, чтобы перехватить сеанс другого пользователя. Для снижения подобного риска большинство платформ генерируют идентификаторы сеансов методом случайных чисел; если же такая возможность отсутствует, попробуйте воспользоваться хэшированием.
