目的
session存储在缓存服务器上(各种缓存服务器上均可,本文以memcached为例),但对开发者来说,他不用关注,只需要调用request.getSession()方法即可获取到session,然后对session的属性进行操作。
面临的问题
1. session获取,不是从application的服务器上获取,要从memcached上获取。
2. session属性的获取及设置,不是设置到application服务器上,而是操作memcached获取或者设置。
解决问题的方法
1. 使用一个HttpServletRequestWrapper的实现类,重写getSession()方法,然后使用filter,来过滤每个请求,使request变为requestWrapper。
2. 使用一个HttpSessionAttributeListener的实现类,重写attributeAdded()、attributeRemoved()、attributeReplaced()方法,当属性发生改变时需要通知memcached中的session发生改变
另外:为解决各个异构系统因语言不通可能发生的兼容问题,session以json字符串存储。
具体代码如下:
wrapper类
import java.io.IOException; import java.util.Map; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequestWrapper; import javax.servlet.http.HttpSession; import com.fasterxml.jackson.core.JsonParseException; import com.fasterxml.jackson.databind.JsonMappingException; import com.javacodegeeks.util.JacksonMapUtil; import com.javacodegeeks.util.MemcachedUtil; public class GetSessionWrapper extends HttpServletRequestWrapper{ public GetSessionWrapper(HttpServletRequest request) { super(request); } @Override public HttpSession getSession() { HttpSession httpSession=super.getSession(); //String sessionId=httpSession.getId(); String sessionId="davidwang456"; String json=MemcachedUtil.getValue(sessionId); // 读取JSON数据 Map<String, Object> userData; try { userData = JacksonMapUtil.getMapper().readValue(json, Map.class); for(Map.Entry<String, Object> entry:userData.entrySet()){ httpSession.setAttribute(entry.getKey(), entry.getValue()); } } catch (JsonParseException e) { e.printStackTrace(); } catch (JsonMappingException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } return httpSession; } @Override public HttpSession getSession(boolean create) { HttpSession httpSession=super.getSession(create); return httpSession; } public static void main(String[] args) { String sessionId="davidwang456"; String json=MemcachedUtil.getValue(sessionId); System.out.println(json); } }
filter类
import java.io.IOException; import javax.servlet.FilterChain; import javax.servlet.FilterConfig; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpSession; public class FetchSession implements javax.servlet.Filter{ @Override public void init(FilterConfig filterConfig) throws ServletException { } @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { HttpServletRequest httpRequest=(HttpServletRequest)request; GetSessionWrapper wrapperRequest=new GetSessionWrapper(httpRequest); //HttpSession httpSession=wrapperRequest.getSession(); chain.doFilter(wrapperRequest, response); } @Override public void destroy() { } }
属性监听器
public class MySessionAttributeListener implements HttpSessionAttributeListener { @Override public void attributeAdded(HttpSessionBindingEvent event) { HttpSession session=event.getSession(); String sessionId="davidwang456"; String attributeName = event.getName(); Object attributeValue = event.getValue(); System.out.println("Attribute add or update: " + attributeName + " : " + attributeValue); session.setAttribute(attributeName, attributeName); String json=MemcachedUtil.getValue(sessionId); String json_new; try { json_new = attributeAddOrUpdate(json,attributeName,attributeValue); MemcachedUtil.setValue(sessionId, json_new); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } } private String attributeAddOrUpdate(String json,String key,Object value) throws JsonParseException, JsonMappingException, IOException{ ObjectMapper mapper=JacksonMapUtil.getMapper(); @SuppressWarnings("unchecked") Map<String,Object> userData = mapper.readValue(json, Map.class); userData.put(key, value); return mapper.writeValueAsString(userData); } private String attributeDel(String json, String key) throws JsonParseException, JsonMappingException, IOException { ObjectMapper mapper = JacksonMapUtil.getMapper(); @SuppressWarnings("unchecked") Map<String, Object> userData = mapper.readValue(json, Map.class); userData.remove(key); return mapper.writeValueAsString(userData); } @Override public void attributeRemoved(HttpSessionBindingEvent event) { HttpSession session=event.getSession(); String sessionId="davidwang456"; String attributeName = event.getName(); System.out.println("Attribute del : " + attributeName); session.removeAttribute(attributeName); String json=MemcachedUtil.getValue(sessionId); String json_new; try { json_new = attributeDel(json,attributeName); MemcachedUtil.setValue(sessionId, json_new); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } } @Override public void attributeReplaced(HttpSessionBindingEvent se) { attributeAdded(se); }
pom.xml依赖:
<dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> <version>2.4.3</version> </dependency> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-annotations</artifactId> <version>2.4.3</version> </dependency> <dependency> <groupId>com.fasterxml.jackson.datatype</groupId> <artifactId>jackson-datatype-guava</artifactId> <version>2.4.3</version> </dependency> <dependency> <groupId>com.fasterxml.jackson.datatype</groupId> <artifactId>jackson-datatype-joda</artifactId> <version>2.4.3</version> </dependency> <dependency> <groupId>com.fasterxml.jackson.datatype</groupId> <artifactId>jackson-datatype-jsr310</artifactId> <version>2.4.3</version> </dependency> <dependency> <groupId>net.spy</groupId> <artifactId>spymemcached</artifactId> <version>2.12.0</version> </dependency>
注意:上面代码仅为demo代码,实际应用需重构代码。
原文:http://www.cnblogs.com/davidwang456/p/5256874.html