1

我正在尝试使用拦截器在我的 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?因此会议?结果我无法继续。

有什么帮助吗?

4

2 回答 2

16

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

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

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

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

  4. 一般来说,只用于SessionAware访问会话。很少需要直接访问请求

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

  6. 我不知道你LoginAction应该做什么。or之类的行的意图是什么?这两条看起来正确的线没有任何东西。setServletRequest(request);setSession(session, user);

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

  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分支返回时,anelse不是绝对必要的,而 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;
    }
}
于 2013-02-06T14:40:14.830 回答
2

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

HttpSessionListenerServlet3 + AJAX 推送通知的组合将是正确的方法。

于 2013-02-06T19:50:28.573 回答