【问题标题】:Struts2 handle session timeout using InterceptorStruts2 使用 Interceptor 处理会话超时
【发布时间】:2013-01-21 16:36:39
【问题描述】:

我正在尝试使用拦截器在我的 struts2 应用程序中处理会话超时请求。以下是与此相关的文件:

Web.xml:

<filter-mapping>
    <filter-name>struts2</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>
<session-config>
    <session-timeout>1</session-timeout>
</session-config>

Struts.xml:

<package name="default" extends="struts-default">
<interceptors>
    <interceptor name="sessionInterceptor"
        class="com.platform.web.security.SessionInterceptor" />
</interceptors>
<action name="doLogin"
    class="com.platform.web.action.LoginAction">
    <result name="input">/login/login.jsp</result>
    <result name="error">/login/login.jsp</result>
    <result type="chain">menuAction</result>
</action>

<action name="menuAction"
    class="com.platform.web.action.MenuAction">
    <interceptor-ref name="sessionInterceptor"/> //Interceptor included here
    <result name="SUCCESS">/jsp/main.jsp</result>
    <result name="ERROR">/login/login.jsp</result>
    <result name="input">/jsp/myFavourite.jsp</result>
</action>

拦截器类:

public class SessionInterceptor extends AbstractInterceptor implements StrutsStatics {
/**
 * 
 */
private static final long serialVersionUID = 1L;

@Override
public String intercept(ActionInvocation invocation) throws Exception {

final ActionContext context = invocation.getInvocationContext();
HttpServletRequest request = (HttpServletRequest) context
    .get(HTTP_REQUEST);
HttpSession session = request.getSession(false);

// Is there a "user" object stored in the user's HttpSession?
//Object user = session.getAttribute("User");
if (session == null) {
    // The user has not logged in yet.

    // Is the user attempting to log in right now?
    //String loginAttempt = request.getParameter(LOGIN_ATTEMPT);

    /* The user is attempting to log in. */
    /*if (!StringUtils.isBlank(loginAttempt)) {
    return invocation.invoke();
    }*/
    return "timeout";
 } else {
    return invocation.invoke();
 }
 }
}

登录操作:

public class LoginAction extends MesActionSupport implements ServletRequestAware {
@Override
public String execute() throws Exception {
setActionNameForAudit("execute123");
FILE_LOGGER.debug("Entering into execute() ... ");
String strSessionId = "";

if (isValidUser == true) {
    user = getUser();

    strSessionId = request.getSession(true).getId();
    setServletRequest(request);
    session.put("SessionId", strSessionId);

    setSession(session, user);

    ServletActionContext.getRequest().getSession().setAttribute("User", user);

    FILE_LOGGER.debug("Exit from  LoginAction.execute() ... ");
    return SUCCESS;
} else {
    return ERROR;
}
 }

菜单操作:

public class MenuAction extends MesActionSupport implements SessionAware, ParameterAware, RequestAware {
@Override
public String execute() throws Exception {
setActionNameForAudit("execute ");
User user = null; // To store current user
Map<String, ArrayList<String>> category = null; // To store all Menu
// Categories.
StringBuffer menu = new StringBuffer(""); // To store Menu String
StringBuffer dashboardMenu = new StringBuffer("");

// user = (User)(request.getSession().getAttribute("User")==null ? null : request.getSession().getAttribute("User")); //Request object IS NULL HERE!!
user = (User) (mapSession.get("User") == null ? null : mapSession
    .get("User")); // mapSession object IS NULL HERE
FILE_LOGGER.debug("user is " + user == null);

if (user != null) {
    menu = menuView.getMenu(user);
    mapSession.put("Menu", menu.toString());
    mapSession.put("dbMenu", dashboardMenu.toString());
    ret = "SUCCESS";
} else if (user == null) {
    ret = ERROR;
} else {
    ret = SUCCESS;
}
return ret;
}

流程是这样的: 1.登录屏幕打开 2. 用户输入凭证并提交 3. LoginAction被调用,用户被认证 4. 如果有效用户 - MenuAction 被调用。否则重定向到 Login.jsp

根据上面的代码,会话在 LoginAction 中创建,控制到达检查会话对象的拦截器。如果会话存在,则控件到达 MenuAction。

但是当这种情况发生时,request 对象被重置为 NULL!早些时候,当我不使用拦截器时,LoginAction 和 MenuAction 之间的流程工作得很好。

拦截器是否会重置 HTTPRequest?因此会议?结果我无法继续。

有什么帮助吗?

【问题讨论】:

    标签: session struts2 httprequest session-timeout interceptor


    【解决方案1】:

    我有很多关于此代码/配置的 cmets,有些微不足道,有些则不然。

    1. 创建自己的会话的理由为零;不要。

    2. 在操作配置中声明拦截器时,必须声明所有拦截器。按照配置,只有会话拦截器正在为menuAction 运行。

    3. 这意味着不会填充任何参数,因为没有其他拦截器在运行。

    4. 一般情况下,只能使用SessionAware 来访问会话。 非常很少需要直接访问请求。

    5. 显然拦截器没有“将请求设置为空”,这甚至没有意义。

    6. 我不知道你的LoginAction 应该做什么。 setServletRequest(request);setSession(session, user); 这样的行的意图是什么?这两行看起来不正确。

    7. 如果您要使用ActionSupport.SUCCESSActionSupport.ERROR 常量,请将您的成功和错误结果命名为"success""error"(小写)。如果您在此代码中使用这些常量,我建议为它们使用其他名称,因为它会使以前实际使用过 Struts 2 的任何人感到困惑。

    8. 发布代码示例时,请删除不相关的内容。特别是当您没有明确设置语法突出显示时,它会使内容更加难以阅读。

    9. 不要使用if (isValidUser == true)之类的代码,使用if (isValidUser)

    10. 注意你的条件:像if (user == null) ... else if (user != null) ... else ... 这样的东西是零意义的。用户为空,或者不是:没有第三个选项。

    11. 避免不必要的、令人困惑的逻辑,例如 User currentUser = (User) (mapSession.get("User") == null ? null : mapSession.get("User"));,它的基本意思是“如果它为 null,则使用 null,否则返回刚刚获得的值,但再次获取它。”为什么???

    12. User user = null; // To store current user 之类的评论完全没有价值。 显而易见User user 是什么?一个用户。不够明显? User currentUser????

    13. 将复数形式(例如,集合)命名为复数形式。类别名称到列表的映射不是单一类别。

    14. 不要在远离它们使用的地方声明变量;这很混乱。

    15. 将您的 JSP 页面放在 WEB-INF 下的某处,以禁止客户端直接访问。

    16. 避免不必要的语言结构,例如当 if 分支返回时,else 不是绝对必要的,而且 IMO 会增加噪音。同样,一旦您知道要返回,请考虑立即返回。后者更具争议性,但我认为人们开始意识到在短方法中有多个返回点是可以的,而且 IMO 更容易考虑。

    17. 用更少的代码来表达。创建小的实用方法来包装琐碎的功能,以免污染主线代码。

    18. 几乎从不使用动作链接。

    还有更多,但现在已经足够了。这是清理后的实际相关代码。其中一些实际上并不相关,但我还是把它留下了。


    <filter-mapping>
      <filter-name>struts2</filter-name>
      <url-pattern>/*</url-pattern>
    </filter-mapping>
    
    <session-config>
      <session-timeout>1</session-timeout>
    </session-config>
    
    <package name="default" extends="struts-default">
      <interceptors>
        <interceptor name="sessionInterceptor" class="com.platform.web.security.SessionInterceptor" />
      </interceptors>
    
      <action name="doLogin" class="com.platform.web.action.LoginAction">
        <result name="input">/WEB-INF/jsp/login/login.jsp</result>
        <result name="error">/WEB-INF/jsp/login/login.jsp</result>
        <result type="redirectAction">menuAction</result>
      </action>
    
      <action name="menuAction" class="com.platform.web.action.MenuAction">
        <interceptor-ref name="sessionInterceptor"/>
        <result name="success">/WEB-INF/jsp/main.jsp</result>
        <result name="input">/WEB-INF/jsp/myFavourite.jsp</result>
      </action>
    
     public class SessionInterceptor extends AbstractInterceptor implements StrutsStatics {
        @Override
        public String intercept(ActionInvocation invocation) throws Exception {
            ActionContext context = invocation.getInvocationContext();
            HttpServletRequest request = (HttpServletRequest) context.get(HTTP_REQUEST);
            HttpSession session = request.getSession(false);
    
            // session will almost *never* be null. Check for a valid user object.
            if (session == null) {
                return "timeout";
            }
    
            return invocation.invoke();
        }
    }
    
    public class LoginAction extends MesActionSupport implements ServletRequestAware {
        @Override
        public String execute() throws Exception {
            if (!isValidUser) {
                return ERROR;
            }
    
            user = getUser();
    
            String strSessionId = request.getSession(true).getId();
            setServletRequest(request);
            session.put("SessionId", strSessionId);
    
            setSession(session, user);
    
            ServletActionContext.getRequest().getSession().setAttribute("User", user);
    
            return SUCCESS;
        }
    }
    
    public class MenuAction extends MesActionSupport implements SessionAware, ParameterAware, RequestAware {
        @Override
        public String execute() throws Exception {
            User currentUser = (User) mapSession.get("User");
            if (currentUser == null) {
                return ERROR;
            }
    
            Map<String, List<String>> categories; // Left in for naming.
    
            StringBuffer menu = menuView.getMenu(user);
            mapSession.put("Menu", menu.toString());
    
            StringBuffer dashboardMenu = new StringBuffer("");
            mapSession.put("dbMenu", dashboardMenu.toString());
    
            return SUCCESS;
        }
    }
    

    【讨论】:

    • +1 如果可以的话,我会再给它一个赞,因为它也很有趣。去表现出很多动力可以来自一个恼火的程序员!加入黑暗面。
    【解决方案2】:

    没有办法您可以分辨会话是超时还是尚未在拦截器中创建,除非您在前端添加一些跟踪,在原始情况下它可能只是一个请求参数。

    HttpSessionListenerServlet3 + AJAX Push notifications 的组合将是正确的方法。

    【讨论】:

    • 没创建或者超时没关系;无论哪种方式,用户都是无效的。我不明白把相对简单的事情过度复杂化。
    • 他说他想处理会话超时请求 - 这应该不同于检查用户是否有效,但谁知道
    • 我当然不会——我认为 OP 的意思是“我提出了请求,但我的会话已超时”基于代码,但 m 也很难理解代码:/无论如何+1 :)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-09-16
    • 2014-03-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多