2013-02-06 36 views
1

我想在使用拦截器的我的struts2应用程序中处理会话超时请求。下面是与此相关的文件: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(); 
} 
} 
} 

的LoginAction:

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; 
} 
} 

MenuAction:

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中创建,控件到达会话对象被检查的Interceptor。如果会话存在,控件到达MenuAction。

但是,当发生这种情况时,request对象被重置为NULL!之前当我没有使用拦截器时,流程在LoginAction和MenuAction之间完全正常工作。

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

任何帮助?

回答

14

我对这段代码/配置有很多评论,有些微不足道,有些则没有。

  1. 没有理由创建自己的会话;别。

  2. 当您在动作配置中声明拦截器时,您必须声明全部拦截器。根据配置,只有会话拦截器正在运行menuAction

  3. 这意味着没有参数将被填充,因为没有其他拦截器正在运行。

  4. 通常,只能使用SessionAware来访问会话。很少有需要直接访问请求的

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

  6. 我不知道你的LoginAction应该做什么。什么是意图线如setServletRequest(request);setSession(session, user);?这两条线看起来没有错。

  7. 名称您的成功和错误的结果只是,"success""error"(小写),如果你要使用ActionSupport.SUCCESSActionSupport.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"));基本上说“如果它是空的,使用空值,否则返回刚刚得到的值,但再次得到它。为什么???

  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; 
    } 
} 
+2

挖掘彻底! – chad

+0

@chad我生气了:/ –

+0

+1如果可以,我会给它另一个upvote,因为它也很有趣。显示出很多动机可以从恼人的程序员中走出来!加入黑暗的一面。 – Quaternion

2

没有办法可以之间的会话是否已经超时或只是尚未在你的拦截器创建出来,除非您在前端添加一些跟踪,但在原始情况下,它可能只是一个请求参数。

HttpSessionListenerServlet3 + AJAX Push notifications的组合将是正确的方式来做到这一点。

+0

它没有被创建或超时无关紧要;用户无论如何都无效。我不明白过于复杂的相对简单的事情。 –

+0

他说他想要处理会话超时请求 - 这应该与检查用户是否有效不同,但是谁知道 –

+0

我确定没有 - 我认为OP意味着“我提出了一个请求,但是我的会话已基于代码超时“,但m也很难理解代码:/ +无论如何:) –