实现思路,使用一个拦截器实现session的处理:
- 获取sessionId,查找sessionAttribute(自定义hashmap)
- 设置session attribute到webwork
- 监控session attribute,一旦发现修改,则持久化到cache中
使用方法:
1、配置拦截器
<interceptor class="com.comwave.sna.interceptor.SNAInterceptor" name="snaInterceptor"></interceptor>
<interceptor-ref name="snaInterceptor"></interceptor-ref>
2、配置spring
<bean class="com.comwave.sna.cache.provider.MemcachedCacheManager" id="cacheManager" destroy-method="close"></bean>
??<constructor-arg value="127.0.0.1:11212"></constructor-arg>
?
如果使用struct2,则需要修改相应的接口,并增加setCacheManager方法
1 楼
balaschen
2007-05-28
代码非常简单,cookieId的值并没有自己实现,简单借用应用服务器的sessionId,当然你以可以实现自己的sessionId算法。
2 楼
pupi
2007-05-29
看了楼主的代码。
楼主是用memcached实现了ActionContext的session。
挺棒 !!
有几个问题:
<1> 只要serverlist一样,是不是memcached server就是同一个实例?
<2> 是否代码中要约定大家不能使用HttpSession了
楼主是用memcached实现了ActionContext的session。
挺棒 !!
有几个问题:
<1> 只要serverlist一样,是不是memcached server就是同一个实例?
<2> 是否代码中要约定大家不能使用HttpSession了
3 楼
balaschen
2007-05-29
pupi 写道
看了楼主的代码。
楼主是用memcached实现了ActionContext的session。
挺棒 !!
有几个问题:
<1> 只要serverlist一样,是不是memcached server就是同一个实例?
<2> 是否代码中要约定大家不能使用HttpSession了
楼主是用memcached实现了ActionContext的session。
挺棒 !!
有几个问题:
<1> 只要serverlist一样,是不是memcached server就是同一个实例?
<2> 是否代码中要约定大家不能使用HttpSession了
1、是,只要serverList一样
2、是,不能直接使用httpSession,应该使用ActionContext的session,不过webwork或struct直接使用httpsession的情况应该不多
4 楼
balaschen
2007-05-29
和其他方案相比最大的特点就是简单,并且能支持webwork或struct支持的任何应用服务器而无需修改代码,可以方便的切换到其他cache实现。缺点就是不支持其他web framework。我们公司的项目都是用webwork或struct,所以这样就够用了。
5 楼
pupi
2007-05-29
balaschen 写道
和其他方案相比最大的特点就是简单,并且能支持webwork或struct支持的任何应用服务器而无需修改代码,可以方便的切换到其他cache实现。缺点就是不支持其他web framework。我们公司的项目都是用webwork或struct,所以这样就够用了。
是struts2.0吧。
6 楼
balaschen
2007-05-29
是struct2.0
7 楼
pupi
2007-05-30
这种方案有一个小问题:
如果项目用到的包自己用到了httpsession,failover就会出问题。
如果项目用到的包自己用到了httpsession,failover就会出问题。
8 楼
balaschen
2007-06-01
pupi 写道
这种方案有一个小问题:
如果项目用到的包自己用到了httpsession,failover就会出问题。
如果项目用到的包自己用到了httpsession,failover就会出问题。
如果使用了Acegi之类直接使用httpsession的话,解决方法也不会太复杂,不过需要使用filter,可以这么搞:
/**
* $Revision: 1.0 $
* Created: 2007-6-1
* $Date: 2007-6-1 $
*
* Author: Keven Chen
*/
package com.comwave.sna.filter;
import java.io.IOException;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.Enumeration;
import java.util.Iterator;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import com.comwave.sna.SessionMap;
import com.comwave.sna.cache.provider.MemcachedCacheManager;
/**
* @author Keven Chen
* @version $Revision 1.0 $
*
*/
public class SNAFilter implements Filter {
private static final String REMOVE_ATTRIBUTE_METHOD = "removeAttribute";
private static final String SET_ATTRIBUTE_METHOD = "setAttribute";
private static final String GET_SESSION_METHOD = "getSession";
private static final String SERVER_LIST = "serverList";
private static final String SESSION_NAME = "cookie-session-id";
private MemcachedCacheManager cacheManager;
public void init(FilterConfig config) throws ServletException {
String serverList = config.getInitParameter(SERVER_LIST);
if(serverList == null || serverList.trim().length() ==0){
throw new ServletException("SNAFilter missing serverList parameter.");
}
cacheManager = new MemcachedCacheManager(serverList);
}
public void destroy() {
if (cacheManager != null) {
cacheManager.close();
}
}
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
final HttpServletRequest hrequest = (HttpServletRequest) request;
final HttpServletResponse hresponse = (HttpServletResponse) response;
String sessionId = getSessionId(hrequest,hresponse);
SessionMap session = getSession(sessionId);
initialHttpSession(session,hrequest.getSession());
try {
chain.doFilter(proxyRequest(hrequest,session), hresponse);
} finally {
if(session.isClear() || session.isEmpty()){
boolean result = cacheManager.flushCache(sessionId);
}
else if(session.isModified()){
session.setModified(false);
boolean result = cacheManager.putToCache(sessionId, session);
}
}
}
private HttpServletRequest proxyRequest(final HttpServletRequest request,final SessionMap session){
final HttpSession hSession = request.getSession();
return (HttpServletRequest) Proxy.newProxyInstance(HttpServletRequest.class.getClassLoader(),
new Class[] { HttpServletRequest.class }, new InvocationHandler() {
private HttpSession proxySession = null;
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
if(method.getName().equalsIgnoreCase(GET_SESSION_METHOD)){
if(proxySession == null){
proxySession = proxySession(hSession,session);
}
return proxySession;
}
return method.invoke(request, args);
}
});
}
private HttpSession proxySession(final HttpSession hsession,final SessionMap session){
return (HttpSession) Proxy.newProxyInstance(HttpSession.class.getClassLoader(), new Class[] {HttpSession.class}, new InvocationHandler() {
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
String methodName = method.getName();
if(methodName.equalsIgnoreCase(SET_ATTRIBUTE_METHOD)){
System.out.println("name:"+args[0]+",value:"+args[1]);
session.put(args[0], args[1]);
}
else if(methodName.equalsIgnoreCase(REMOVE_ATTRIBUTE_METHOD)){
System.out.println("remove:"+args[0]);
session.remove(args[0]);
}
return method.invoke(hsession, args);
}
});
}
private void initialHttpSession(SessionMap session, HttpSession hsession){
Enumeration oldAttributes = hsession.getAttributeNames();
while(oldAttributes.hasMoreElements()){
hsession.removeAttribute((String)oldAttributes.nextElement());
}
Iterator newAttributes = session.keySet().iterator();
while(newAttributes.hasNext()){
String attribute = (String) newAttributes.next();
hsession.setAttribute(attribute, session.get(attribute));
}
}
private String getSessionId(HttpServletRequest request,HttpServletResponse hresponse){
Cookie[] cookies = request.getCookies();
String sessionId = null ;
if (cookies != null) {
for (int i = 0; cookies != null && i < cookies.length; i++) {
if (SESSION_NAME.equals(cookies[i].getName())) {
sessionId = cookies[i].getValue();
break;
}
}
}
if(sessionId == null || sessionId.trim().length() == 0){
sessionId = buildSessionId(request);
createCookie(sessionId,hresponse);
}
return sessionId;
}
private void createCookie(String sessionId,HttpServletResponse response) {
Cookie cookie = new Cookie(SESSION_NAME,sessionId);
cookie.setPath("/");
response.addCookie(cookie);
}
private String buildSessionId(HttpServletRequest request) {
return request.getSession().getId();
}
protected SessionMap getSession(String Id){
Object value = cacheManager.getFromCache(Id);
if(value == null){
return new SessionMap();
}
return (SessionMap) value;
}
}
当然你得在web.xml配置filter
9 楼
balaschen
2007-06-01
不过,如果有第三方lib直接调用HttpSession.getId()这个方法,估计会有问题,没有测试过,推测而已。
10 楼
davexin
2007-08-30
搂住能不能讲得更详细一点,希望能借鉴一下,现在正需要这样的设计。还希望搂主能够讲得更详细一点,比如client和主服务器的通信等等。先谢谢了。