每次请求都通过NoSql数据库查询,如果存在,则获取值;反之存放值。
我是通过redis来实现session的共享,其主要有一下两种方法:
1、通过tomcat服务器的拓展功能实现
这种方式比较简单,主要是通过继承session的ManagerBase类,实现重写session相关的方法,这种比较简单,
参考源码链接(http://download.csdn.net/detail/fengshizty/9417242)。
2、通过filter拦截request请求实现
下面主要介绍这样实现方式:
(1)写HttpSessionWrapper实现HttpSession接口,实现里面session相关的方法。
(2)写HttpServletRequestWrapper继承javax.servlet.http.HttpServletRequestWrapper类,重写对于session 相关的方法。
(3)写SessionFilter拦截配置的请求url,过去cookie中
的sessionId,如果为空,对此次请求重写生成一个新的sessionId,在sessionId构造新的HttpServletRequestWrapper对象。
(4)写SessionService实现session到redis的保存和过去,其key为sessionId,value为session对于的Map。
3、代码实现
/**
* 创建时间:2016年1月21日 下午7:55:41
*
* @author andy
* @version 2.2
*/
public class HttpSessionWrapper implements HttpSession {
private String sid = "";
private HttpSession session;
private HttpServletRequest request;
private HttpServletResponse response;
private Map<String, Object> map = null;
private SessionService sessionService = (SessionService) SpringContextHolder.getBean("sessionService");
public HttpSessionWrapper() {
}
public HttpSessionWrapper(HttpSession session) {
this.session = session;
}
public HttpSessionWrapper(String sid, HttpSession session) {
this(session);
this.sid = sid;
}
public HttpSessionWrapper(String sid, HttpSession session,
HttpServletRequest request, HttpServletResponse response) {
this(sid, session);
this.request = request;
this.response = response;
}
private Map<String, Object> getSessionMap() {
if (this.map == null) {
this.map = sessionService.getSession(this.sid);
}
return this.map;
}
@Override
public Object getAttribute(String name) {
if (this.getSessionMap() != null) {
Object value = this.getSessionMap().get(name);
return value;
}
return null;
}
@Override
public void setAttribute(String name, Object value) {
this.getSessionMap().put(name, value);
sessionService.saveSession(this.sid, this.getSessionMap());
}
@Override
public void invalidate() {
this.getSessionMap().clear();
sessionService.removeSession(this.sid);
CookieUtil.removeCookieValue(this.request,this.response, GlobalConstant.JSESSIONID);
}
@Override
public void removeAttribute(String name) {
this.getSessionMap().remove(name);
sessionService.saveSession(this.sid, this.getSessionMap());
}
@Override
public Object getValue(String name) {
return this.session.getValue(name);
}
@SuppressWarnings("unchecked")
@Override
public Enumeration getAttributeNames() {
return (new Enumerator(this.getSessionMap().keySet(), true));
}
@Override
public String[] getValueNames() {
return this.session.getValueNames();
}
@Override
public void putValue(String name, Object value) {
this.session.putValue(name, value);
}
@Override
public void removeValue(String name) {
this.session.removeValue(name);
}
@Override
public long getCreationTime() {
return this.session.getCreationTime();
}
@Override
public String getId() {
return this.sid;
}
@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 boolean isNew() {
return this.session.isNew();
}
}
(2)HttpServletRequestWrapper实现
/**
* 创建时间:2016年1月22日 下午7:52:29
*
* @author andy
* @version 2.2
*/
public class HttpServletRequestWrapper extends
javax.servlet.http.HttpServletRequestWrapper {
private HttpSession session;
private HttpServletRequest request;
private HttpServletResponse response;
private String sid = "";
public HttpServletRequestWrapper(HttpServletRequest request) {
super(request);
}
public HttpServletRequestWrapper(String sid, HttpServletRequest request) {
super(request);
this.sid = sid;
}
public HttpServletRequestWrapper(String sid, HttpServletRequest request,
HttpServletResponse response) {
super(request);
this.request = request;
this.response = response;
this.sid = sid;
if (this.session == null) {
this.session = new HttpSessionWrapper(sid, super.getSession(false),
request, response);
}
}
@Override
public HttpSession getSession(boolean create) {
if (this.session == null) {
if (create) {
this.session = new HttpSessionWrapper(this.sid,
super.getSession(create), this.request, this.response);
return this.session;
} else {
return null;
}
}
return this.session;
}
@Override
public HttpSession getSession() {
if (this.session == null) {
this.session = new HttpSessionWrapper(this.sid, super.getSession(),
this.request, this.response);
}
return this.session;
}
}
(3)SessionFilter拦截器的实现
public class SessionFilter extends OncePerRequestFilter implements Filter {
private static final Logger LOG = Logger.getLogger(SessionFilter.class);
@Override
protected void doFilterInternal(HttpServletRequest request,
HttpServletResponse response, FilterChain filterChain)
throws ServletException, IOException {
//从cookie中获取sessionId,如果此次请求没有sessionId,重写为这次请求设置一个sessionId
String sid = CookieUtil.getCookieValue(request, GlobalConstant.JSESSIONID);
if(StringUtils.isEmpty(sid) || sid.length() != 36){
sid = StringUtil.getUuid();
CookieUtil.setCookie(request, response, GlobalConstant.JSESSIONID, sid, 60 * 60);
}
//交给自定义的HttpServletRequestWrapper处理
filterChain.doFilter(new HttpServletRequestWrapper(sid, request, response), response);
}
}
(4)SessionService实现session从redis的读写存储
public class SessionService {
private final static Logger LOG = Logger.getLogger(SessionService.class);
private JdkSerializationRedisSerializer jdkSerializer = new JdkSerializationRedisSerializer();
@Autowired
private RedisTemplate<Serializable, Serializable> redisTemplate;
@SuppressWarnings("unchecked")
public Map<String, Object> getSession(String sid) {
Map<String, Object> session = new HashMap<String, Object>();
try {
Object obj = redisTemplate.opsForValue()
.get(RedisKeyUtil.SESSION_DISTRIBUTED_SESSIONID + sid);
if(obj != null){
obj = jdkSerializer.deserialize((byte[])obj);
session = (Map<String, Object>) obj;
}
} catch (Exception e) {
LOG.error("Redis获取session异常" + e.getMessage(), e.getCause());
}
return session;
}
public void saveSession(String sid, Map<String, Object> session) {
try {
redisTemplates.opsForValue()
.set(RedisKeyUtil.SESSION_DISTRIBUTED_SESSIONID + sid,
jdkSerializer.serialize(session), RedisKeyUtil.SESSION_TIMEOUT,
TimeUnit.MINUTES);
} catch (Exception e) {
LOG.error("Redis保存session异常" + e.getMessage(), e.getCause());
}
}
public void removeSession(String sid) {
try {
redisTemplates.delete(
RedisKeyUtil.SESSION_DISTRIBUTED_SESSIONID + sid);
} catch (Exception e) {
LOG.error("Redis删除session异常" + e.getMessage(), e.getCause());
}
}
}
(5)Session的拦截配置,一般的我们只需要拦截我们定义的拦截请求拦截,而不需要所有的都需要拦截。在web.xml中配置SessionFilter
<filter>
<filter-name>sessionFilter</filter-name>
<filter-class>org.andy.shop.session.SessionFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>sessionFilter</filter-name>
<url-pattern>*.do</url-pattern>
</filter-mapping>