|
|
Интересные статьи
|
|
|
|
|
SessionMan решает проблему сохранения состояний в вебсервисах 
Обзор Вебсервисы уже давно стали настолько популярными, что их поддержка вошла в Java SE 6. Сейчас уже трудно удивить кого-то гетерогенной архитектурой приложения, в которой серверная часть реализована на Java, а клиентская на .Net или наоборот. Веб сервисы обладают огромным списком преимуществ и не меньшим списком недостатков, устранение одного из которых и является целью данной статьи. Проблема Варианты решения проблемы для Axis2 WSDL — каркас любого вебсервиса SessionMan выходит на арену LogOut и "чистка" сессий Заключительное слово Ресурсы Проблема
"By design, Web services are said to be stateless..." — эта фраза говорит о многом! Это значит, что используя веб сервисы, не составит труда передать на сервер код города и в ответ получить прогноз погоды на неделю. Но, для того чтобы организовать систему клиент-банк с использование Axis2*, придется потрудиться т.к. такая система предполагает процедуру авторизации и поддержку сессии в течении некоторого периода времени. Замечание * Axis2 — второе поколение наиболее популярного движка для веб сервисов, разрабатываемого под эгидой Apache Software Foundation. Варианты решения проблемы для Axis2
Мои поиски решения этой проблемы привели к одной статье [1], в которой ребята из IBM предлагают свое решение. Его смысл сводится к тому, что в сервис-класс, сгенерированный Axis2 добавляется статическое поле (HashMap), который и является хранилищем информации о сессии пользователя, а wsdl сервиса преобразуется таким образом, что появляется две дополнительных операции login и logout. Единственным недостатком или скорее ограничением в приведенном примере [1], является то, что клент должен явно выполнять операцию logout, в противном случае информация о сессии так и останется дожидаться перезагрузки сервера приложений, а HashMap станет источником утечки памяти и проблем в производительности.
Решением проблемы также может стать Open Source библиотека SessionMan, предоставляющая базовый набор функций для работы с сессиями в любом Java-приложении и выполняющая периодическую сборку мусора, состоящую в удалении устаревших сессий.
Для рассмотрения примера использования SessionMan, нам понадобятся TomCat и Axis2. Установите TomCat, Axis2 и проверьте их работоспособность, воспользовавшись документацией к каждому из продуктов и мы продолжим наше повествование. WSDL — каркас любого вебсервиса
Мы начнем нашу работу с того, что создадим wsdl-документ, описывающий наш будущий вебсервис: <portType name="SessionManExamplePort"> <operation name="login"> <input name="loginOpIn" message="tns:loginSoapMessage" /> <output name="loginOpOut" message="tns:sessionSoapMessage" /> </operation> <operation name="disconnect"> <input name="disconnectOpIn" message="tns:sessionSoapMessage"/> <output name="disconnectOpOut" message="tns:isOkSoapMessage" /> </operation> <operation name="ping"> <input name="pingOpIn" message="tns:sessionSoapMessage" /> <output name="pingOpOut" message="tns:pingSoapMessage" /> </operation> </portType>
Как видно из фрагмента wsdl — наш вебсервис будет содержать три операции: login, disconnect** и ping. Первая операция принимает SOAP конверт в который упакованы имя пользователя и его пароль: Замечание ** имя метода выбрано не случайно, т.к. в одной из версий Axis2 v.1.0 были ошибки, и операция logout обрабатывалась некорректно.
<xsd:element name="UserAuthElement"> <xsd:complexType> <xsd:sequence> <xsd:element name="login" type="xsd:string" minOccurs="1" maxOccurs="1"/> <xsd:element name="password" type="xsd:string" minOccurs="1" maxOccurs="1" /> </xsd:sequence> </xsd:complexType> </xsd:element>
Оставшиеся же две принимают только SOAP конверт содержащий идентификатор сессии, что с одной стороны, необходимо для проверки актуальности сессии перед выполнением любой операции, и с другой — вполне достаточно для объяснения работы с библиотекой SessionMan.
После того, как wsdl-документ создан, мы запускаем утилиту wsdl2java, прилагающуюся к Axis2 и дожидаемся окончания генерации всех необходимых классов.
Полнофукнциональный пример, использующий библиотеку SessionMan, совместно с Axis2, доступен из SVN репозитория: http://sessionman.googlecode.com/svn/trunk/sessionman-example.
Инструкция по сборке проекта для работы в среде Eclipse 3.2: http://sessionman.googlecode.com/svn/trunk/sessionman-example/readme.txt. SessionMan выходит на арену
Результатом работы wsdl2java является целый пакет классов, среди которых SessionManExampleServiceSkeleton — сердце нашего будущего сервиса. Для дальнейшей работы мы унаследуем этот класс и создадим свой SessionManExampleService.
Подключаем SessionMan: import com.webtair.session.*; import com.webtair.session.artifact.*; import com.webtair.sessionman.ws.types.*; Добавляем контроллер сессий к сервис классу: public class SessionManExampleService extends SessionManExampleServiceSkeleton { ... /** SessionMan instance — main goal of this example */ private static SessionMan<SimpleSessionInfo> sessions = new SessionMan<SimpleSessionInfo>();
Здесь необходимы пояснения: Класс com.webtair.session.SessionMan имеет два конструктора: public SessionMan(ConfigBean config) и public SessionMan() — второй создает конфигурацию по умолчанию со временем жизни сессии 30мин и периодичностью очистки устаревших сессий 10мин. С помощью первого конструктора пользователю предоставляется возможность управлять этими параметрами, а так же определить стартовую размерность таблицы для сессий, передав, соответствующим образом настроенный, com.webtair.session.config.ConfigBean В качестве хранилища вашей информации может использоваться любой класс, реализующий интерфейс com.webtair.session.artifact.SessionInfo, для базовых операций с сессией библиотека предоставляет класс SimpleSessionInfo.
Таким образом, если Вам необходимо создать хранилище для, скажем состояния корзины, достаточно будет реализовать интерфейс SessionInfo c сответствующей функциональностью.
Создаем сессию и возвращем ее кленту вебсервиса: /** * Method that allow for client to login under this ws * @return IdSessionDocument — soap envelope with session id; */ @Override public IdSessionDocument login (UserAuthElementDocument userAuthElementDocument) { /* default login and pass for examples only. At this place you * mast recieve real pass from the real storage like RDBMS or * config-file or somthing else. */ String defaultLogin = "sessionman"; String defaultpass = "example";
UserAuthElement userAuthElement = userAuthElementDocument.getUserAuthElement();
if (userAuthElement.getLogin().equals(defaultLogin) && userAuthElement.getPassword().equals(defaultpass)){
// request for id session from SessionMan lib idSession = sessions.putSessionInfo(userAuthElement.getLogin(), new SimpleSessionInfo()); } ... }
Ключевым выражением в процедуре получения идентификатора является метод putSessionInfo(), "вкладывающий" в HashMap контроллера SessionInfo и возвращающий уникальный идентификатор сессии.
Провереям актуальность сессии:
Вызов метода validateSession(String idSession), позволяет не только проверить "жива" ли сессия, но и автоматически обновляет время ее последнего использования, что приводит к ее автоматическому пролонгированию на время указанное в ConfigBean (30 мин по умолчанию).
Вызов метода isSessionExpired(String idSession), позволяет просто определить завершилось ли время жизни сессии, не обновляя ее последнего использования. LogOut и "чистка" сессий
Если пользователь не выполнил явной операции disconnect (logout), чисткой HashMap займется фоновый поток, который проснется через интервал времени, определенный в ConfigBean. Заключительное слово
Полнофукнциональный пример, использующий библиотеку SessionMan, совместно с Axis2, доступен из SVN репозитория: http://sessionman.googlecode.com/svn/trunk/sessionman-example. Источник: http://www.javaportal.ru
|
|
|
Работаем с JAR-архивами
Ну а теперь, имея список содержимого jar-архива, мы спокойно можем распаковывать его, не забывая создавать подкаталоги, содержащиеся в архиве |
|
|
|
|