我想在Tomcat中过期我的所有会话.我们在Fitnesse下测试我们的产品,一些会话保留,会话结束会导致测试之间的依赖关系.我用以下代码手工完成,但是有些会话仍然存在(我可以使用
http://localhost:8080/manager/html/list url查看它)
public static void expireAllSessions() { String[] applications = { "a","b","c","d","e" }; for (String application : applications) { try { expireAllSessions(application); } catch (Exception e) { logger.error(e); } } } private static void expireAllSessions(final String application) throws Exception { // cf doc http://hc.apache.org/httpclient-3.x/authentication.html HttpClient client = new HttpClient(); client.getParams().setAuthenticationPreemptive(true); Credentials userPassword = new UsernamePasswordCredentials("tomcat","tomcat"); client.getState().setCredentials(AuthScope.ANY,userPassword); String url = "http://localhost:8080/manager/html/expire"; NameValuePair[] parametres = new NameValuePair[] { new NameValuePair("path","/" + application),new NameValuePair("idle","0") }; HttpMethod method = new GetMethod(url); method.setQueryString(parametres); client.executeMethod(method); }
有没有办法更有效和更直接地执行,没有剩余的会话?
解决方法
我假设你的应用程序是真正独立的上下文.我已经做了类似于每个上下文使用HttpSessionListener所要求的内容.这里的棘手部分是,您需要具有由根类加载器加载的会话集合,而不是上下文类加载器.这是我怎么记得的:
创建一个类,该类保存每个上下文的活动会话.该类必须驻留在tomcat / lib目录中,以便每个上下文都可以访问它.它不能是任何上下文的一部分.
public class SessionMap { private static Map<ServletContext,Set<HttpSession>> map = new HashMap<ServletContext,Set<HttpSession>>(); private SessionMap() { } public static Map<ServletContext,Set<HttpSession>> getInstance() { return map; } public static void invalidate(String[] contexts) { synchronized (map) { List<String> l = Arrays.asList(contexts); for (Map.Entry<ServletContext,Set<HttpSession>> e : map.entrySet()) { // context name without the leading slash String c = e.getKey().getContextPath().substring(1); if (l.contains(c)) { for (HttpSession s : e.getValue()) s.invalidate(); } } } } }
为每个上下文创建一个监听器.
public class ApplicationContextListener implements HttpSessionListener { public void sessionCreated(HttpSessionEvent event) { ConcurrentMap<ServletContext,Set<HttpSession>> instance = SessionMap.getInstance(); synchronized (instance) { ServletContext c = event.getSession().getServletContext(); Set<HttpSession> set = instance.get(c); if (c == null) { set = new HashSet<HttpSession>(); instance.put(c,set); } set.add(event.getSession()); } } public void sessionDestroyed(HttpSessionEvent event) { ConcurrentMap<ServletContext,Set<HttpSession>> instance = SessionMap.getInstance(); synchronized (map) { ServletContext c = event.getSession().getServletContext(); Set<HttpSession> set = instance.get(c); if (c != null) { set.remove(event.getSession()); } } } }
在相应上下文的web.xml中注册每个监听器.
<listener> <listener-class>ApplicationContextListener</listener-class> </listener>
SessionMap.invalidate();
我在地图上进行同步,只是为了安全起见.