Struts2 - сессия

Объект сессии ( session ) в WEB-приложении имеет немаловажное значение. При использовании Struts2 можно использовать сессию интерфейса ServletRequest, который расширяется интерфейсом HttpServletRequest. Метод getSession (boolean create) данного интерфейса возвращает объект типа HttpSession текущего сеанса клиента. Если параметр create равен true и объект HttpSession не существует, то создается новый объект HttpSession.

Интерфейс SessionAware

Несмотря на возможность использования сессии интерфейса HttpSession необходимо все же использовать объект сессии фреймворка. Для этого необходимо создать действие, которое наследует интерфейс SessionAware. Интерфейс SessionAware содержит метод setSession, который открывает нам доступ к сессии фреймворка. Параметром метода setSession является объект типа Map <String, Object>. Таким образом, определив в действии объект типа Map <String, Object>, мы можем связать его с сессией фреймворка. После этого, сессию можно использовать для обмена объектами между различными действиями.

Необходимо отметить, что перехватчики ( Interceptor ) наследуют интерфейс SessionAware, получая доступ к объекту сессии. Такая структура фреймворка позволяет использовать перехватчики для проверки авторизации (наличия пользователя в сессии) при попытке "незванного гостя" попасть в закрытые области (страницы) WEB-приложения.
Рассмотрим вопрос использования сессии на примере авторизации пользователя. Суть данного примера заключается в проверке наличия пользователя с определенным аккаунтом в нашем хранилище ( базе данных ). Если пользователь присутствует, то объект User добавляется к сессии и вызывается действие главной формы. В главной форме можно использовать сессию для получения доступа к объекту и отображения параметров его аккаунта.

Вызов Action-класса авторизации Authentication будем выполнять на странице Login.jsp.

Наследование ActionSupport

В листинге Authentication.java приведен исходный код действия авторизации пользователя. На что следует обратить внимание?
  1. import org.apache.struts2.interceptor.SessionAware - наследование интерцептором;

    сессия может быть использована в интерцепторах; В примере раздела о перехватчиках приводится код получения сессии для проверки авторизации пользователя, чтобы предотвратить недопустимый переход в закрытые области приложения;
  2. extends ActionSupport - наследование свойств и методов класса, который вызывает execute () и validate ();

    • в методе execute () выполняем авторизацию пользователя;
    • в методе validate () реализовываем логику проверки данных;
  3. implements SessionAware - включение свойств класса;

    наследование интерфейса SessionAware определяет необходимость включения в класс процедуры setSession, которая вызывается фреймворком и, в коде которой, мы определяем переменную сессии session;

Действие авторизации пользователя

Листинг действия Authentication.java
package examples.registration; import java.util.Map; import com.opensymphony.xwork2.Action; import com.opensymphony.xwork2.ActionSupport; import org.apache.struts2.interceptor.SessionAware; public class Authentication extends ActionSupport implements SessionAware { private String login; private String password; private Map session; public String execute() throws Exception { Store store = new Store(); if (( store != null ) && ( store.userExists ( getLogin (), getPassword ()))) { User user = store.getUser ( getLogin (), getPassword ()); session.put ( "user", user ); return Action.SUCCESS; } else return Action.INPUT; } public void setSession ( Map session ) { this.session = session; } public String getLogin { return login; } public void setLogin (String login) { this.login = login; } public String getPassword { return password; } public void setPassword (String password) { this.password = password; } private boolean isEmptyString ( String value ) { return value == null || "".equals ( value.trim ( ) ); } public void validate ( ) { if ( isEmptyString ( login )) addFieldError ( "login", "Не указан логин" ); if ( isEmptyString ( password )) addFieldError ( "password", "Не указан пароль" ); } }

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

Фреймворк вызывает метод setSession, в котором мы определяем нашу переменную session. Получив доступ к сессии, мы в методе execute () извлекаем объект User из хранилища и размещаем его в сессии. Структура объекта User приводится в следующем листинге.
Объект пользователя User.java
package examples.registration; public class User { private String name; private String login; private String password; public String getName { return name; } public void setName (String name) { this.name = name; } public String getLogin { return login; } public void setLogin (String login) { this.login = login; } public String getPassword { return password; } public void setPassword (String password) { this.password = password; } }

Подключение действия авторизации к приложению

Подключение действия к WEB-приложению осуществляется в файле конфигурации struts.xml.
Листинг файла конфигурации struts.xml
<package name="public" namespace="/Public" extends="struts-default"> <action name="Login"> <result>/Login.jsp</result> </action> <action name="Authentication" class="examples.registration.Authentication"> <result name="success" type="redirect">/Private/MainPage.action</result> <result name="input">/Login.jsp</result> </action> </package>

В данном файле конфигурации мы определили, что действие Authentication располагается в открытой области (namespace) Public. Для выполнения данного действия необходимо вызвать класс examples.registration.Authentication.class. Если результат выполнения действия будет success, то необходимо выполнить действие MainPage.action закрытой области Private. Если действие Authentication не авторизует пользователя, т.е. результат выполнения будет input, то остаемся на странице Login.jsp.

Вызов действия авторизации

Представим страницу Login.jsp, в которой оператор будет вводить данные и вызывать действие Authentication.
Листинг JSP-страницы Login.jsp
<%@ page language="java" contentType="text/html; charset=utf-8" pageEncoding="utf-8"%> <%@ taglib prefix="s" uri="/struts-tags" %> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html> <head> <title>Авторизация пользователя</title> </head> <body> <h1>Авторизация пользователя</h1> <s:form action="Authentication" method="post"> <s:textfield label="Логин" name="login" required="true" ><s:textfield /> <s:password label="Пароль" name="password" required="true" /> <s:submit value="Подключиться"></s:submit> </s:form> </body> </html>

В представленном листинге страницы Login.jsp следует обратить внимание на способы закрытия тегов. Теги Struts2 можно закрывать с объявлением (</s:textfield>) и без объявления (/>). Параметр required определяет установку символа * для представления поля как обязательного к заполнению.

Использование объектов сессии на странице JSP

После того, как пользователь авторизован, было бы неплохо отобразить параметры его аккаунта на странице JSP. В следующем листинге приводится фрагмент кода использования объекта User, который мы разместили в сессии.
Фрагмент листинга страницы JSP
<%@ page import="examples.registration.User" %> <% User user = (User) session.getAttribute ("user"); %> Добро пожаловать, <h3><%= user.getName() %></h3>