Сессии в приложении Struts2
Я создал веб-приложение, в котором мне нужно поддерживать сеанс, если там есть сеанс пользователя, и тогда и только тогда он позволит пользователю увидеть jsp.
Я работал с сервлетами JSP раньше, но я новичок в Struts2.
Здесь я устанавливаю имя пользователя в своем классе действий:
Пересмотренный код
private HttpSession session;
public void setSession(HttpSession session) {
// TODO Auto-generated method stub0
this.session = session;
}
public HttpSession getSession() {
return session;
}
public String getLoginStatus(){
session = request.getSession();
session.setAttribute("userName", loginBean.getUsername());
return SUCCESS;
}
Теперь, когда я перенаправлен на следующую страницу после действия, он показывает значение сеанса один раз. После этого на каждой странице я нахожу нулевые значения в сеансе.
<%
String userName = (String)session.getAttribute("userName");
System.out.println(userName);
if(userName == null || userName.equals("") ){
response.sendRedirect("login.jsp");
}
%>
Я где-то читал, что область действия класса действий ограничена одной страницей - как я могу решить эту проблему?
Любой пример будет очень полезным для меня.
6 ответов
Есть несколько проблем с кодом, который у вас сейчас есть.
- Вы должны использовать Interceptor для обеспечения того, чтобы пользователь вошел в систему, а не пытаться применять его в JSP. JSP должен быть только для представления, а не для управления потоком.
- Вам следует избегать скриплетов (блоков кода) в JSP. Это устарело очень давно и широко считается очень плохой практикой в приложении MVC.
- Вы можете получить доступ к значениям сеанса в вашем JSP напрямую. Вам не нужно реализовывать
SessionAware
интерфейс в вашем действии, если вам не нужен доступ к сеансу внутри самого действия. - Вы должны перенаправить пользователя к действию входа в систему, а не непосредственно к странице JSP, в противном случае вы обходите инфраструктуру Struts2 и теряете преимущества ее использования.
Пример входа
Ниже приведен пример кода для создания базовой системы входа в систему с использованием инфраструктуры Struts2.
Требуется логин
Эта часть является необязательной, но, как правило, не все страницы в веб-приложении требуют входа пользователя в систему. Поэтому давайте создадим интерфейс под названием LoginRequired
, Любое действие, которое реализует этот интерфейс маркера, будет перенаправлено на страницу входа, если пользователь еще не вошел в систему.
Примечание: вместо этого вы можете использовать аннотацию, но для этого примера я буду использовать интерфейс.
public interface LoginRequired {}
Перехватчик
Перехватчик будет обрабатывать, заставляя пользователя войти в систему для любого запрошенного действия, которое реализует LoginRequired
интерфейс.
public class LoginInterceptor extends AbstractInterceptor {
@Override
public String intercept(final ActionInvocation invocation) throws Exception {
Map<String, Object> session = ActionContext.getContext().getSession();
// sb: feel free to change this to some other type of an object which
// represents that the user is logged in. for this example, I am using
// an integer which would probably represent a primary key that I would
// look the user up by with Hibernate or some other mechanism.
Integer userId = (Integer) session.get("userId");
// sb: if the user is already signed-in, then let the request through.
if (userId != null) {
return invocation.invoke();
}
Object action = invocation.getAction();
// sb: if the action doesn't require sign-in, then let it through.
if (!(action instanceof LoginRequired)) {
return invocation.invoke();
}
// sb: if this request does require login and the current action is
// not the login action, then redirect the user
if (!(action instanceof LoginAction)) {
return "loginRedirect";
}
// sb: they either requested the login page or are submitting their
// login now, let it through
return invocation.invoke();
}
}
Вам также понадобится LoginAction
который отображает и обрабатывает страницу входа и LogoutAction
который делает недействительным или очищает сеанс.
Конфигурация
Вам нужно будет добавить перехватчик в ваш стек, а также создать глобальное отображение результатов для "loginRedirect".
<interceptors>
<interceptor name="login" class="your.package.LoginInterceptor"/>
<!-- sb: you need to configure all of your interceptors here. i'm only
listing the one we created for this example. -->
<interceptor-stack name="yourStack">
...
<interceptor-ref name="login"/>
...
</interceptor-stack>
</interceptors>
<global-results>
<!-- sb: make this the path to your login action.
this could also be a redirectAction type. -->
<result name="loginRedirect" type="redirect">/login</url>
</global-results>
Чтобы поддерживать сеанс, используйте интерфейс SessionAware в вашем классе действий и реализуйте int public void setSession (Map m), он будет принимать атрибут в качестве пары ключ-значение на карте, доступ к которой можно получить из любого места, где только можно получить ключ.
например Action класс
import org.apache.struts2.interceptor.SessionAware;
import com.opensymphony.xwork2.ActionSupport;
public class LogingEx extends ActionSupport implements SessionAware{
private static final long serialVersionUID = 1L;
private String stuname,stuage,country;
private int stumarks;
Map m;
public String getStuname() {
return stuname;
}
public void setStuname(String stuname) {
this.stuname = stuname;
}
public String getStuage() {
return stuage;
}
public void setStuage(String stuage) {
this.stuage = stuage;
}
public String getCountry() {
return country;
}
public void setCountry(String country) {
this.country = country;
}
public int getStumarks() {
return stumarks;
}
public void setStumarks(int stumarks) {
this.stumarks = stumarks;
}
public void setSession(Map m)
{
this.m=m;
}
public String execute()
{
m.put("a",stuname);
m.put("b", stuage);
m.put("c",stumarks);
m.put("d",country);
return SUCCESS;
}
}
ИСТОЧНИК: http://www.java4s.com/struts-tutorials/example-on-struts-2-sessionaware-interface/
Ваш класс Action уже реализовал SessionAware
интерфейс?
РЕДАКТИРОВАТЬ:
Попробуйте это (это решение в стиле struts2):
public class anAction implements SessionAware{
private Map<String, Object> session;
public Map<String, Object> getSession() {
return session;
}
public void setSession(Map<String, Object> session) {
this.session = session;
}
public String getLoginStatus(){
session.put("userName", "test"); //Hard code here for testing.
return SUCCESS;
}
}
Затем используйте свой код JSP, чтобы получить имя пользователя на странице. Я проверил этот подход на моей машине, и он работает.
EDIT2: Кстати, такую проверку входа в систему можно легко и элегантно выполнить с помощью "Перехватчика", предоставляемого Struts2 Framework.
Я не вижу причин использовать этот вид Map
авторизовать пользователя. Если ваше требование только проверяет пользователя по сеансу, то я бы рекомендовал использовать Filter
чем какая-то карта в каком-то классе, проблема с этим типом карты заключается в удалении объектов сеанса после того, как сеанс признан недействительным, конечно, вы можете использовать HttpSessionListener
чтобы заставить его работать, но я думаю, что лучше всего проверить через Filter
чем Map
,
Помимо этого, вы можете взглянуть на многие структуры безопасности (например, Apache Shiro), чтобы сделать вашу задачу проще и надежнее.
Реализация SessionAware не требуется.
public class LoginAction extends Actionsupport
{
private Map<String, Object> session;
//Getter and Setter method
public String execute() throws Exception {
session=ActionContext.getContext().getSession();
session.put("userName", "test");
return super.execute();
}
}
В следующей статье в журнале есть более подробная информация в той же строке ответа Стивена выше http://www.journaldev.com/2210/struts-2-interceptor-tutorial-with-custom-authentication-interceptor-example