我们在IIS7.5后面使用Tomcat6.29,并带有spring,hibernate和struts2框架。我们现在开始注意到服务器会话变得混乱起来,尤其是在Ajax请求中。
有关该问题的更多详细信息
任何指向问题根源的指针都将有所帮助,代码可以在用户数量较少的情况下正常运行,并且不会报告此类实例。
编辑
web.xml
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID" version="2.5">
<display-name>bm</display-name>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring/*Context.xml</param-value>
</context-param>
<filter>
<filter-name>encodingFilter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
<init-param>
<param-name>forceEncoding</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter>
<filter-name>struts2</filter-name>
<filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>encodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name>struts2</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<listener>
<listener-class>org.apache.struts2.tiles.StrutsTilesListener</listener-class>
</listener>
struts.xml
<result-types>
<result-type name="jasper" class="org.apache.struts2.views.jasperreports.JasperReportsResult"/>
<result-type name="tiles" class="org.apache.struts2.views.tiles.TilesResult" />
</result-types>
<interceptors>
<interceptor name="sessionLoggin" class="com.inrev.bm.interceptor.IRLoggingInterceptor" />
<interceptor name="appAccess" class="appAccessInterceptor" />
<interceptor-stack name="newStack">
<interceptor-ref name="exception"/>
<interceptor-ref name="alias"/>
<interceptor-ref name="servletConfig"/>
<interceptor-ref name="i18n"/>
<interceptor-ref name="prepare"/>
<interceptor-ref name="chain"/>
<interceptor-ref name="debugging"/>
<interceptor-ref name="scopedModelDriven"/>
<interceptor-ref name="modelDriven"/>
<interceptor-ref name="fileUpload"/>
<interceptor-ref name="checkbox"/>
<interceptor-ref name="multiselect"/>
<interceptor-ref name="staticParams"/>
<interceptor-ref name="params">
<param name="excludeParams"> dojo\..*,^struts\..*</param>
</interceptor-ref>
<interceptor-ref name="actionMappingParams"/>
<interceptor-ref name="sessionLoggin"/>
<interceptor-ref name="appAccess"/>
</interceptor-stack>
</interceptors>
<default-interceptor-ref name="newStack"/>
其他资讯
1)用户通过提交表单登录,登录后我们将执行以下操作:
public class xxxAction extends ActionSupport implements SessionAware
{
public String execute()
{
session.clear();
if (session instanceof org.apache.struts2.dispatcher.SessionMap)
{
try
{
((org.apache.struts2.dispatcher.SessionMap) session).invalidate();
}
catch (IllegalStateException e) {
log.error("Session Invalidate Failed ", e);
}
//Authorization code happens here
session.put("orgs", orgs);
session.put("currentOrg", org);
session.put("permission", adminDAO.getRolePermission(orgs.get(0).getRoleId()));
session.put("simplyApp", simplyApp);
session.put("user", user);
return "login"
}
}
2)正在使用的操作系统是Windows 2008 RC2
EDIT2 接收者代码
侦听器1
public String intercept(ActionInvocation invocation) throws Exception
{
String result = null;
String className = invocation.getAction().getClass().getName();
Map session = invocation.getInvocationContext().getSession();
IRUser user = (IRUser) session.get("user");
IROrgname org = (IROrgname)session.get("currentOrg");
IRAppDetails simplyApp = (IRAppDetails)session.get("simplyApp");
String sessionId = (String)session.get("sessionId");
boolean switchUser =session.get("switchUser")!=null ? (Boolean)session.get("switchUser") : false;
if(className.indexOf("IRLoginAction")!=-1 || className.indexOf("IRContactUsAction")!=-1
|| className.indexOf("IRIPNAction")!=-1 || className.indexOf("IRPaymentAction")!=-1
|| className.indexOf("IRServiceAction")!=-1 || className.indexOf("IRAppBossAction") !=-1)
{
result= invocation.invoke();
session.put("PREV_CLASS_NAME", className);
}
else if(!(className.indexOf("IRLoginAction")!=-1) && (user !=null && org!=null))
{
if(!IRSessionManager.getInstance().compareSession(user.getUserId(), sessionId) && !switchUser)
{
session.clear();
if (session instanceof org.apache.struts2.dispatcher.SessionMap)
{
try
{
((org.apache.struts2.dispatcher.SessionMap) session).invalidate();
}
catch (IllegalStateException e)
{
log.error("Session Invalidate Failed ", e);
}
}
result = "sessionDuplicated";
}
else
{
result= invocation.invoke();
session.put("PREV_CLASS_NAME", className);
}
}
else if(className.indexOf("widgets") !=-1)
{
result= invocation.invoke();
}
else if(className.indexOf("ActionSupport") !=-1)
{
result= invocation.invoke();
}
else if (!(className.indexOf("IRLoginAction")!=-1) && (user ==null || org==null || simplyApp==null))
{
result = "sessionExpired";
}
return result;
}
侦听器2
public String intercept(ActionInvocation invocation) throws Exception
{
String result = null;
HttpServletRequest request = ServletActionContext.getRequest();
String className = invocation.getAction().getClass().getName();
try
{
Map session = invocation.getInvocationContext().getSession();
IRUser user = (IRUser) session.get("user");
IROrgname org = (IROrgname)session.get("currentOrg");
IRAppDetails application = (IRAppDetails)session.get("simplyApp");
if(( user!= null && user.getAppType()!=0) && !(className.indexOf("IRLoginAction")!=-1))
{
if(hasAccess(user.getAppType(), className))
{
result= invocation.invoke();
}
else
{
result = "checkURL";
}
}
else
{
result= invocation.invoke();
}
}
catch (Exception e)
{
e.printStackTrace();
}
return result;
}
两天前,我在一个旧项目(不是我的)上调试了类似的东西。
原来这是自定义拦截器的错误。
检查我可以在您的堆栈中看到的自定义拦截器,
<interceptor-ref name="sessionLoggin"/>
<interceptor-ref name="appAccess"/>
并确保其代码是线程安全的(避免使用拦截器上的字段,而不是同步所有内容,仅使用局部变量)。
例如,考虑以下代码:
public abstract class ThreadUnsafeInterceptor extends AbstractInterceptor {
private Map<String, Object> session; // <!-- Thread Unsafe
public final String intercept(ActionInvocation invocation) throws Exception {
session = invocation.getInvocationContext().getSession();
/* Do stuff */
System.out.println(session.get("myObject"));
return invocation.invoke();
}
}
这样,当User1进入方法时,它会设置共享session
对象及其会话。如果在User1尚未完成的情况下User2进入该方法,则User2将立即session
用其会话覆盖该对象,而User1将引用User2会话而不是它自己的会话。
要使其线程安全,应如下所示:
public abstract class ThreadSafeInterceptor extends AbstractInterceptor {
public final String intercept(ActionInvocation invocation) throws Exception {
Map<String, Object> session; // <!-- Thread Safe
session = invocation.getInvocationContext().getSession();
/* Do stuff */
System.out.println(session.get("myObject"));
return invocation.invoke();
}
}
编辑:
您的拦截器存在一些问题:
1)请求不能被访问这种方式(如描述这里):
HttpServletRequest request = ServletActionContext.getRequest();
从Struts2拦截器内部访问请求的正确方法是:
// Constants are from StrutsStatics interface
HttpServletRequest request = (HttpServletRequest) context.get(HTTP_REQUEST);
2)如果您不想invocation.invoke();
立即返回立即数,请注意,将其分配给result
String将触发“流”,并且invoke()
将在Action执行之后执行后面的行,如下所述:
public String intercept(ActionInvocation invocation) throws Exception {
String className = invocation.getAction().getClass().getName();
long startTime = System.currentTimeMillis();
System.out.println("Before calling action: " + className);
String result = invocation.invoke();
long endTime = System.currentTimeMillis();
System.out.println("After calling action: " + className
+ " Time taken: " + (endTime - startTime) + " ms");
return result;
}
我有一个Spring MVC Web应用程序,用户可以在该应用程序上登录和注册帐户。一旦用户登录并且用户注销会话结束,我将尝试保留会话。 实现这一点的最佳方式是什么? 以下是我的登录控制器。
将感谢任何关于我们应该如何处理这一点的提示!
因此,我尝试使用JSF托管bean上的方法访问HttpSession的属性 但是我得到了一个 为什么啊? 在我的一个会话bean被销毁之前,我需要访问该会话打开的外部服务的连接列表,它们当然存储在会话属性对象上。 我该怎么做?
我在Tomcat7中有一个web应用程序,它将会话中的用户信息作为DTO对象保存。我还为我的项目启用了Spring Security性,如果用户没有会话,它会自动将用户重定向到登录页面。 如果我登录到应用程序一次,然后在Eclipse中重新启动Tomcat,会发生的情况是,我的会话被冲出,但cookie没有运行。 Edit:尽管Firefox说,但如果关闭并重新启动Firefox,cookie仍然
我有一个cordova应用程序,我有一个登录页面和一个登录用户的内页。每当用户会话消失时,它就会请求登录信息。如何防止ths cordova应用程序在重启移动应用程序时删除会话uppon重启或恢复cookie和会话信息?所以登录屏幕不会每次都出现?
问题内容: 我刚刚完成了在PHP中创建整个登录和注册systsem的操作,但是我的问题是我还没有使用任何会话。我是PHP的新手,以前从未使用过会话。我想做的是,在用户注册并填写登录表单后,他们仍将停留在同一页面上。因此,其中一部分将是会话已登录,另一部分将是其他(用户未登录,请显示登录表单)。谁能告诉我如何开始? 问题答案: 希望这可以帮助 :) 开始会话,您需要在页面顶部或在调用会话代码之前说出