自定义session,实现session共享

原创
2016/11/29 15:55
阅读数 719

使用filter自定义Session的操作

1、过滤器
package com.wenjie.ssm.session;
import java.io.IOException;
import java.util.UUID;
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;

public class RedisSessionFilter implements Filter {
	private String sessionName =null;
	private String domain=null;
	private String path =null;
	private int expir =30;

	[@Override](https://my.oschina.net/u/1162528)
	public void init(FilterConfig filterConfig) throws ServletException {
		sessionName = filterConfig.getInitParameter("sessionName");
		domain = filterConfig.getInitParameter("domain");
		path = filterConfig.getInitParameter("path");
		expir=Integer.parseInt(filterConfig.getInitParameter("expir"));
	}

	[@Override](https://my.oschina.net/u/1162528)
	public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
		HttpServletRequest request = (HttpServletRequest) req;
		HttpServletResponse response = (HttpServletResponse) res;
		String sesssionId = null;
		Cookie[] cookies = request.getCookies();
		if (null != cookies) {
			for (Cookie cookie : cookies) {
				if (cookie.getName().equals(sessionName)) {
					sesssionId = cookie.getValue();
					break;
				}
			}
		}
		if (null == sesssionId || "".equals(sesssionId)) {
			sesssionId = UUID.randomUUID().toString();
			Cookie cookie = new Cookie(sessionName, sesssionId.replaceAll("-", ""));
			if(domain!=null && !"".equals(domain)){
				cookie.setDomain(domain);
			}
			cookie.setPath(path);
			response.addCookie(cookie);
		}
		chain.doFilter(new RedisHttpServletRequestWrapper(request, sesssionId,expir), response);
	}

	[@Override](https://my.oschina.net/u/1162528)
	public void destroy() {}
}
2、包装request
package com.wenjie.ssm.session;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import javax.servlet.http.HttpSession;

public class RedisHttpServletRequestWrapper extends HttpServletRequestWrapper {
	private RedisSeSSion redisSeSSion = null;
	private String sesssionId = null;
	private int expir = 30;

	public RedisHttpServletRequestWrapper(HttpServletRequest request, String sesssionId,int expir) {
		super(request);
		this.sesssionId = sesssionId;
		this.expir = expir;
		getSession();//刷新session
	}

	[@Override](https://my.oschina.net/u/1162528)
	public HttpSession getSession() {
		redisSeSSion= new RedisSeSSion(super.getSession(),sesssionId,expir);
		redisSeSSion.refresh();
		return redisSeSSion;
	}

}
3、定制Session
package com.wenjie.ssm.session;

import java.util.Enumeration;

import javax.servlet.ServletContext;
import javax.servlet.http.HttpSession;
import javax.servlet.http.HttpSessionContext;

public class RedisHttpSessionWrapper implements HttpSession {

	private HttpSession session;

	public RedisHttpSessionWrapper(HttpSession session) {
		this.session = session;
	}

	[@Override](https://my.oschina.net/u/1162528)
	public Object getAttribute(String arg0) {
		return this.session.getAttribute(arg0);
	}

	@Override
	public Enumeration getAttributeNames() {
		return this.session.getAttributeNames();
	}

	@Override
	public long getCreationTime() {
		return session.getCreationTime();
	}

	@Override
	public String getId() {
		return session.getId();
	}

	@Override
	public long getLastAccessedTime() {
		return session.getLastAccessedTime();
	}

	@Override
	public int getMaxInactiveInterval() {
		return session.getMaxInactiveInterval();
	}

	@Override
	public ServletContext getServletContext() {
		return session.getServletContext();
	}

	@Override
	public HttpSessionContext getSessionContext() {
		return session.getSessionContext();
	}

	@Override
	public Object getValue(String arg0) {
		return session.getValue(arg0);
	}

	@Override
	public String[] getValueNames() {
		return session.getValueNames();
	}

	@Override
	public void invalidate() {
		this.session.invalidate();
	}

	@Override
	public boolean isNew() {
		return session.isNew();
	}

	@Override
	public void putValue(String arg0, Object arg1) {
		session.putValue(arg0, arg1);
	}

	@Override
	public void removeAttribute(String arg0) {
		this.session.removeAttribute(arg0);
	}

	@Override
	public void removeValue(String arg0) {
		session.removeValue(arg0);
	}

	@Override
	public void setAttribute(String arg0, Object arg1) {
		this.session.setAttribute(arg0, arg1);
	}

	@Override
	public void setMaxInactiveInterval(int arg0) {
		session.setMaxInactiveInterval(arg0);
	}

}


package com.wenjie.ssm.session;

import java.util.Enumeration;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

import javax.servlet.http.HttpSession;

import org.springframework.dao.DataAccessException;
import org.springframework.data.redis.connection.RedisConnection;
import org.springframework.data.redis.core.RedisCallback;
import org.springframework.data.redis.core.RedisTemplate;

import com.wenjie.ssm.utils.SerializeUtil;

public class RedisSeSSion extends RedisHttpSessionWrapper {
	private String sesssionId = null;
	private Integer redisSeSSionExpireTime = 1800;//过期时间秒
	// 操作和jedis基本一致。只能接收 byte[]的key-value 接下来熟悉jedis即可。
	private static RedisTemplate<?, ?> redisTemplate;
	public static void setRedisTemplate(RedisTemplate<?, ?> redisTemplate) {
		RedisSeSSion.redisTemplate = redisTemplate;
	}

	public RedisSeSSion(HttpSession session, final String sesssionId,int expir) {
		super(session);
		this.sesssionId = sesssionId;
		this.redisSeSSionExpireTime =expir*60;
	}
	@Override
	public void setAttribute(final String arg0, final Object arg1) {
		redisTemplate.execute(new RedisCallback<Object>() {
			public Object doInRedis(RedisConnection connection) throws DataAccessException {
				connection.hSet(SerializeUtil.serialize(sesssionId),SerializeUtil.serialize(arg0), SerializeUtil.serialize(arg1));
				connection.expire(SerializeUtil.serialize(sesssionId),redisSeSSionExpireTime);
				return null;
			}
		});
	}
	
	@Override
	public Object getAttribute(final String arg0) {
		return redisTemplate.execute(new RedisCallback<Object>() {
			public Object doInRedis(RedisConnection connection) throws DataAccessException {
				if (connection.exists(SerializeUtil.serialize(sesssionId))) {
					byte[] value = connection.hGet(SerializeUtil.serialize(sesssionId),SerializeUtil.serialize(arg0));
					connection.expire(SerializeUtil.serialize(sesssionId),redisSeSSionExpireTime);
					return (Object) SerializeUtil.unserialize(value);
				}
				return null;
			}
		});
	}

	@Override
	public void removeAttribute(final String arg0) {
		redisTemplate.execute(new RedisCallback<Object>() {
			public Object doInRedis(RedisConnection connection) throws DataAccessException {
				if (connection.exists(SerializeUtil.serialize(sesssionId))) {
					connection.expire(SerializeUtil.serialize(sesssionId),redisSeSSionExpireTime);
					return connection.hDel(SerializeUtil.serialize(sesssionId),SerializeUtil.serialize(arg0));
				}else{
					return null;
				}
			}
		});
	}
	
	@Override
	public void invalidate() {
		redisTemplate.execute(new RedisCallback<Object>() {
			public Object doInRedis(RedisConnection connection) throws DataAccessException {
				return connection.hDel(SerializeUtil.serialize(sesssionId));
			}
		});
	}

	
	@Override
	public Enumeration getAttributeNames() {
		Map<byte[], byte[]> result=redisTemplate.execute(new RedisCallback<Map<byte[], byte[]>>() {
			public Map<byte[], byte[]> doInRedis(RedisConnection connection) throws DataAccessException {
				if (connection.exists(SerializeUtil.serialize(sesssionId))) {
					connection.expire(SerializeUtil.serialize(sesssionId),redisSeSSionExpireTime);
					return connection.hGetAll(SerializeUtil.serialize(sesssionId));
				}else {
					return null;
				}
			}
		});
		
		if(result!=null && result.size()>0){
			Set<Object> set=new HashSet<Object>();
			for(byte[] keySet:result.keySet()){ set.add(SerializeUtil.unserialize(keySet));}
			return (new Enumerator(set, true));
		}else{
			return (new Enumerator(new HashSet<Object>(), true));
		}
	}
	
	public void refresh() {
		redisTemplate.execute(new RedisCallback<Map<byte[], byte[]>>() {
			public Map<byte[], byte[]> doInRedis(RedisConnection connection) throws DataAccessException {
				if (connection.exists(SerializeUtil.serialize(sesssionId))) {
					connection.expire(SerializeUtil.serialize(sesssionId),redisSeSSionExpireTime);
				}
				return null;
			}
		});
	}
}
4、注册过滤器
<filter>
	<filter-name>MySession</filter-name>
	<filter-class>com.wenjie.ssm.session.RedisSessionFilter</filter-class>
	<init-param>
		<param-name>sessionName</param-name>
		<param-value>MySessionId</param-value>
	</init-param>
	
	<init-param>
		<param-name>path</param-name>
		<param-value>/</param-value>
	</init-param>
	
	<init-param>
		<param-name>domian</param-name>
		<param-value>.xiaodingwangplatform.com</param-value>
	</init-param>
	
	<init-param>
		<param-name>expir</param-name>
		<param-value>60</param-value>
	</init-param>
</filter>
<filter-mapping>
	<filter-name>MySession</filter-name>
	<url-pattern>/*</url-pattern>
</filter-mapping>
5、使用静态注入redisTemplate
package com.wenjie.ssm.utils;

import org.springframework.data.redis.core.RedisTemplate;

import com.wenjie.ssm.session.RedisSeSSion;

public class StaticInjection {
	public void setRedisTemplate(RedisTemplate redisTemplate) {
		RedisCache.setRedisTemplate(redisTemplate);
		RedisSeSSion.setRedisTemplate(redisTemplate);
	}
}

<!-- 使用中间类解决RedisTemplate的静态注入-->
<bean class="com.wenjie.ssm.utils.StaticInjection">
	<property name="redisTemplate" ref="redisTemplate" />
</bean>

序列化与反序列就不贴了,redis缓存也不贴了,暂时记录到这里。 Spring-data-redis 实现redis缓存以及session共享。纯属学习希望大神们指导改正错误。

展开阅读全文
打赏
0
1 收藏
分享
加载中

引用来自“554330833a”的评论

引用来自“哎呦-又忘了”的评论

引用来自“554330833a”的评论

这个的作用是?
session共享 redis的整合还没弄。 这里只是好奇自己弄着玩 😄

回复@哎呦-又忘了 : 是把session放到redies里面吗?redies只开一个的是吧
是的 redis也可以配置成集群
2016/11/29 16:57
回复
举报

引用来自“哎呦-又忘了”的评论

引用来自“554330833a”的评论

这个的作用是?
session共享 redis的整合还没弄。 这里只是好奇自己弄着玩 😄

回复@哎呦-又忘了 : 是把session放到redies里面吗?redies只开一个的是吧
2016/11/29 16:31
回复
举报

引用来自“554330833a”的评论

这个的作用是?
session共享 redis的整合还没弄。 这里只是好奇自己弄着玩 😄
2016/11/29 16:08
回复
举报
这个的作用是?
2016/11/29 16:04
回复
举报
更多评论
打赏
4 评论
1 收藏
0
分享
返回顶部
顶部