我正在尝试使用Interceptor处理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;
}
Flow就像这样: 1.登录屏幕打开 2.用户输入凭据并提交 3.调用LoginAction,对用户进行身份验证 4.如果调用了有效的用户 - MenuAction。否则重定向到Login.jsp
根据上面的代码,会话在LoginAction中创建,控件到达检查会话对象的Interceptor。如果会话存在,则控件到达MenuAction。
但是当发生这种情况时,request
对象会重置为NULL!早些时候,当我没有使用拦截器时,流程在LoginAction和MenuAction之间完全正常。
拦截器会重置HTTPRequest吗?会议?结果我无法继续。
任何帮助?
答案 0 :(得分:15)
我对这段代码/配置有很多评论,有些是微不足道的,有些则不是。
创建自己的会话是没有理由的;不。
在动作配置中声明拦截器时,必须声明所有拦截器。根据配置,仅会话拦截器正在为menuAction
运行。
这意味着不会填充任何参数,因为没有其他拦截器正在运行。
通常,只能使用SessionAware
来访问会话。 very 很少需要直接访问请求。
显然,拦截器没有“将请求设置为空”,这甚至没有意义。
我不知道你LoginAction
应该做什么。什么是setServletRequest(request);
或setSession(session, user);
等行的意图?这两行看起来没什么。
如果您要使用"success"
和"error"
,请将您的成功和错误结果命名为ActionSupport.SUCCESS
和ActionSupport.ERROR
(小写)常量。如果你不在这段代码中使用这些常量,我建议使用其他名称,因为它会让任何以前实际使用过Struts 2的人感到困惑。
发布代码示例时,请删除不相关的内容。特别是当您没有明确设置语法突出显示时,它会使很多更难以阅读。
请勿使用if (isValidUser == true)
之类的代码,请使用if (isValidUser)
。
注意你的条件:像if (user == null) ... else if (user != null) ... else ...
这样的东西没有意义。用户为空,或者不是:没有第三个选项。
避免使用不必要的,令人困惑的逻辑,例如User currentUser = (User) (mapSession.get("User") == null ? null : mapSession.get("User"));
基本上说“如果它为null,则使用null,否则返回刚刚获得的值,但再次获取它。” WHY ???
像User user = null; // To store current user
这样的评论完全没有价值。是不是明显 User user
是什么?一个用户。不够明显? User currentUser
???
将复数(例如,集合)命名为复数。列表中的类别名称映射不是单一类别。
不要将变量声明远离它们使用的地方;这很令人困惑。
将您的JSP页面放在WEB-INF
某处,以禁止直接访问客户端。
避免使用不必要的语言结构,例如if
分支返回时,else
并非绝对必要,而IMO则会增加噪音。同样,一旦你知道你正在回来,就考虑回来。后者有点争议,但我认为人们正在意识到在短方法中有多个回归点是可以的,IMO更容易思考。
使用较少的代码来表达事物。创建一些小实用工具方法来包含琐碎的功能,这样就不会污染主线代码。
几乎从不使用动作链接。
还有更多,但现在已经够了。这是清理过的实际相关代码。其中一些实际上并不相关,但无论如何我都把它留下了。
<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)
没有办法你可以判断会话是否超时或者你的拦截器中是否还没有创建它,除非你在前端添加一些跟踪,原始情况下它可能只是一个请求参数。
HttpSessionListener和Servlet3 + AJAX Push notifications的组合将是正确的方式。