Сессии в приложении 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");
}
%>
Я где-то читал, что объем сеанса действия класса ограничен одной страницей - как я могу решить эту проблему?
Любой пример будет очень полезен для меня.
Ответы
Ответ 1
Есть несколько проблем с кодом, который у вас есть.
- Вы должны использовать 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>
Ответ 2
Чтобы поддерживать сеанс, используйте SessionAware интерфейс в своем классе действий и реализуйте int
public void setSession (Карта m), он примет атрибут как пару ключевых значений в карте
к которому можно получить доступ из любого места, где можно просто купить ключ.
например Класс действия
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/
Ответ 3
Я не нахожу причины использовать этот тип Map
для авторизации пользователя. Если ваше требование только проверяет пользователя на сеанс, я бы рекомендовал использовать Filter
, чем какую-либо карту в каком-то классе, проблема с этим видом карты заключается в удалении объектов сеанса, когда сеанс недействителен, конечно, вы можете использовать HttpSessionListener
, чтобы он работал, но я думаю, что лучше всего проверить с помощью Filter
, чем Map
.
Помимо этого вы можете взглянуть на многие рамки безопасности (например, Apache Shiro), чтобы сделать вашу задачу более простой и надежной.
Ответ 4
Разве ваш класс Action уже реализовал интерфейс SessionAware
?
EDIT:
Попробуйте это (это решение стиля 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:
BTW, такая проверка входа может быть выполнена легко и элегантно с помощью "Interceptor", предоставляемого Struts2 Framework.
Ответ 5
Выполнение 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();
}
}
Ответ 6
Следующая статья journaldev содержит более подробную информацию в той же строке ответа Стивена выше http://www.journaldev.com/2210/struts-2-interceptor-tutorial-with-custom-authentication-interceptor-example