在负载均衡情况下,如果用户访问不同的机器,如果没有做session同步,用户就会被提出,这样用户体验非常不好,所以我们很远必要做session同步,把session放到reids缓存服务器就能很好的解决问题。下面是代码简单的实现。
一、配置web.xml过滤器:
[html] view plain copy
- <filter>
- <filter-name>sessionFilter</filter-name>
- <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
- </filter>
- <filter-mapping>
- <filter-name>sessionFilter</filter-name>
- <url-pattern>/*</url-pattern>
- </filter-mapping>
二、配置对应的过滤器名字:
[html] view plain copy
- <bean id="sessionFilter" class="com.plateno.interceptor.SessionFilter">
- <property name="redisTemplate" ref="redisTemplate"/>
- </bean>
三、SessionFilter的实现:
[java] view plain copy
- public class SessionFilter extends GenericFilterBean {
- private RedisTemplate redisTemplate;
- @Override
- public void doFilter(ServletRequest request, ServletResponse response,
- FilterChain chain) throws IOException, ServletException {
- System.out.println("filter");
- HttpServletRequest re = (HttpServletRequest)request;
- HttpServletResponse res = (HttpServletResponse)response;
- TerryHttpServletRequestWrapper wrapper = new TerryHttpServletRequestWrapper(re,res,redisTemplate);
- chain.doFilter(wrapper, response);
- }
- public RedisTemplate getRedisTemplate() {
- return redisTemplate;
- }
- public void setRedisTemplate(RedisTemplate redisTemplate) {
- this.redisTemplate = redisTemplate;
- }
- }
四、TerryHttpServletRequestWrapper的实现:
[java] view plain copy
- public class TerryHttpServletRequestWrapper extends HttpServletRequestWrapper {
- private CacheHttpSession session;
- private HttpServletResponse response;
- private RedisTemplate redisTemplate;
- public TerryHttpServletRequestWrapper(HttpServletRequest request, HttpServletResponse response,RedisTemplate redisTemplate) {
- super(request);
- this.response = response;
- this.redisTemplate = redisTemplate;
- }
- @Override
- public HttpSession getSession(boolean create) {
- if(session != null) {
- return session;
- }
- String sid = "terry" + System.currentTimeMillis();
- writeSidToCookie(sid);
- session = new CacheHttpSession(null,sid,redisTemplate);
- return session;
- }
- @Override
- public HttpSession getSession() {
- return getSession(false);
- }
- protected void writeSidToCookie(String sid) {
- Cookie mycookies = new Cookie("terry", sid);
- mycookies.setMaxAge(-1);
- mycookies.setDomain("locahost");
- mycookies.setPath("/");
- response.addCookie(mycookies);
- }
- }
五、CacheHttpSession的实现:
[java] view plain copy
- public class CacheHttpSession extends HttpSessionWrapper {
- private String sid;
- private RedisTemplate redisTemplate;
- private StringRedisSerializer stringSerializer = new StringRedisSerializer();
- public CacheHttpSession(HttpSession session,String sid,RedisTemplate redisTemplate) {
- super(session);
- this.sid = sid;
- this.redisTemplate = redisTemplate;
- }
- @SuppressWarnings("unchecked")
- @Override
- public Enumeration<String> getAttributeNames() {
- final byte[] key = stringSerializer.serialize(sid);
- Object result = redisTemplate.execute(new RedisCallback<Object>() {
- @Override
- public Object doInRedis(RedisConnection connection)
- throws DataAccessException {
- Set<byte[]> set = connection.keys(key);
- return set;
- }
- });
- if(result != null) {
- Set<byte[]> s = (Set<byte[]>)result;
- Set<String> ss = new HashSet<String>();
- for(byte[] b : s) {
- ss.add(stringSerializer.deserialize(b));
- }
- Enumeration<String> en = new Vector(ss).elements();
- return en;
- }
- return null;
- }
- @SuppressWarnings("unchecked")
- @Override
- public void setAttribute(String name, Object value) {
- final byte[] key = stringSerializer.serialize(name);
- final byte[] v = stringSerializer.serialize((String)value);
- redisTemplate.execute(new RedisCallback<Object>() {
- @Override
- public Object doInRedis(RedisConnection connection)
- throws DataAccessException {
- connection.set(key, v);
- return null;
- }
- });
- }
- @Override
- public Object getAttribute(String name) {
- final byte[] key = stringSerializer.serialize(name);
- @SuppressWarnings("unchecked")
- Object value = redisTemplate.execute(new RedisCallback<Object>() {
- @Override
- public Object doInRedis(RedisConnection connection)
- throws DataAccessException {
- return connection.get(key);
- }
- });
- return value;
- }
- @Override
- public String getId() {
- return sid;
- }
- }
六、HttpSessionWrapper的实现:
[java] view plain copy
- public class HttpSessionWrapper implements HttpSession {
- private HttpSession session;
- public HttpSessionWrapper(HttpSession session) {
- this.session = session;
- }
- @Override
- public long getCreationTime() {
- return this.session.getCreationTime();
- }
- @Override
- public String getId() {
- return this.session.getId();
- }
- @Override
- public long getLastAccessedTime() {
- return this.session.getLastAccessedTime();
- }
- @Override
- public ServletContext getServletContext() {
- return this.session.getServletContext();
- }
- @Override
- public void setMaxInactiveInterval(int interval) {
- this.session.setMaxInactiveInterval(interval);
- }
- @Override
- public int getMaxInactiveInterval() {
- return this.session.getMaxInactiveInterval();
- }
- @Override
- public HttpSessionContext getSessionContext() {
- return this.session.getSessionContext();
- }
- @Override
- public Object getAttribute(String name) {
- return this.session.getAttribute(name);
- }
- @Override
- public Object getValue(String name) {
- return this.session.getValue(name);
- }
- @Override
- public Enumeration<String> getAttributeNames() {
- return this.session.getAttributeNames();
- }
- @Override
- public String[] getValueNames() {
- return this.session.getValueNames();
- }
- @Override
- public void setAttribute(String name, Object value) {
- this.session.setAttribute(name,value);
- }
- @Override
- public void putValue(String name, Object value) {
- this.session.putValue(name,value);
- }
- @Override
- public void removeAttribute(String name) {
- this.session.removeAttribute(name);
- }
- @Override
- public void removeValue(String name) {
- this.session.removeValue(name);
- }
- @Override
- public void invalidate() {
- this.session.invalidate();
- }
- @Override
- public boolean isNew() {
- return this.session.isNew();
- }
- }
以上代码就能把session保存到redis,当然这其中还有很多问题,比如sessionId的生成,session过去,对象序列化(测试为了方便统一用了string),等等很多问题。以后有时间再完善。