session 共享

在多个tomcat集群中,session共享就是必须,不然前端nginx转发过来不知道之前请求在哪台,就找不到session,导致请求失败。

几种实现方案

1.粘性session

使用Nginx的ip_hash特性做粘性会话,可以让用户每次访问都转发到该用户第一次访问的web容器上,但是当该web容器上的应用挂了,nginx不会将该用户的请求转发到别的web容器,体验不好。

2.服务器session复制

即每次session发生变化时,创建或者修改,就广播给所有集群中的服务器,使所有的服务器上的session相同。

3.session共享

缓存session,使用redis, memcached。

4.session持久化

将session存储至数据库中,如mysql。

基于redis的实现方式

自定义Request与Session,并使用过滤器过滤对应路径的请求,引入自定义Request

  1. 封装自定义Request,主要目的重写getSession方法返回自定义的session对象。
package com.liabc.poc.server.config;

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

public class HttpServletRequestWrapper extends javax.servlet.http.HttpServletRequestWrapper {

    private String sid;

    public HttpServletRequestWrapper(HttpServletRequest request, String sid) {
        super(request);
        this.sid = sid;
    }

    @Override
    public HttpSession getSession(boolean create) {
        return new HttpSessionSidWrapper(null, sid);
    }

    @Override
    public HttpSession getSession() {
        return new HttpSessionSidWrapper(null, sid);
    }
}

  1. 封装自定义Session
package com.liabc.poc.server.config;

import javax.servlet.ServletContext;
import javax.servlet.http.HttpSession;
import javax.servlet.http.HttpSessionContext;
import java.util.Enumeration;

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 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();
    }
}
  1. 继承并重写getAttribute,setAttribute等方法。(主要实现从redis读取数据封装session信息,暂未实现。)
package com.liabc.poc.server.config;


import javax.servlet.http.HttpSession;
import java.util.HashMap;
import java.util.Map;

public class HttpSessionSidWrapper extends HttpSessionWrapper {

    private String sid;
    private Map map = new HashMap();

    public HttpSessionSidWrapper(HttpSession session, String sid) {
        super(session);
        this.sid = sid;
    }

    @Override
    public Object getAttribute(String name) {
        map.put("test","Hello Session!");
        return this.map.get(name);
    }

    @Override
    public void setAttribute(String name, Object value) {
        this.map.put(name, value);
    }

    @Override
    public String getId() {
        return this.sid;
    }
}
  1. 在过滤器里引入自定义Request和Session
package com.liabc.poc.server.config;


import javax.servlet.*;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

public class SessionFilter implements Filter {

    private static final long serialVersionUID = 8928219999641126613L;
    private String cookieDomain = "";
    private String cookiePath = "/";


    @Override
    public void init(FilterConfig filterConfig) throws ServletException {

        this.cookiePath = filterConfig.getInitParameter("cookiePath");
        if (this.cookiePath == null || this.cookiePath.length() == 0) {
            this.cookiePath = "/";
        }

    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        String sessionId = "XmlBeanDefinitionReaderSid";
        HttpServletRequest request = (HttpServletRequest) servletRequest;
        HttpServletResponse response = (HttpServletResponse) servletResponse;
        Cookie cookies[] = request.getCookies();
        Cookie sCookie = null;
        String sid = "";
        if (cookies != null && cookies.length > 0) {
            for (int i = 0; i < cookies.length; i++) {
                sCookie = cookies[i];
                if (sCookie.getName().equals(sessionId)) {
                    sid = sCookie.getValue();
                }
            }
        }

        if (sid == null || sid.length() == 0) {
            sid = java.util.UUID.randomUUID().toString();
            Cookie mycookies = new Cookie(sessionId, sid);
            mycookies.setMaxAge(-1);
            mycookies.setPath("/");
            mycookies.setHttpOnly(true);
            response.addCookie(mycookies);
        }

        HttpServletRequestWrapper requestWrapper = new HttpServletRequestWrapper(request, sid);

        filterChain.doFilter(requestWrapper, response);

    }


}
  1. web.xml 配置过滤器

    
        mySessionFilter
        com.liabc.poc.server.config.SessionFilter
    
    
        mySessionFilter
        /*
    

你可能感兴趣的:(session 共享)