使用cookie管理Servlet的session

由于集群下session同步性能较差,可以选择使用cookie保存session。session处理遵照以下几点

1.选择map做session的存储,在更新时写入cookie,可以保证每次请求时能正常获取上次记录的session。

2.添加子类重写HttpSession的方法,将其修改的方法实现为对map的修改,在每次修改后更新response的cookie。

自定义HttpSession

public class CsmSession implements HttpSession {

	private ConcurrentHashMap<String, Object> session;
	private String uuid;
	private Kryo kryo = new Kryo();
	private HttpServletResponse response;
	private HttpServletRequest request;

	@SuppressWarnings("unchecked")
	public CsmSession(HttpServletRequest request, HttpServletResponse response,
			String data, String uuid) {
		this.request = request;
		this.response = response;
		this.uuid = uuid;
		DeflateSerializer deflateSerializer = new DeflateSerializer(
				kryo.getDefaultSerializer(ConcurrentHashMap.class));
		BlowfishSerializer blowfishSerializer = new BlowfishSerializer(
				deflateSerializer, Constants.BLOWFISH_KEY);
		kryo.register(ConcurrentHashMap.class, blowfishSerializer);
		if (data != null) {
			try {
				Input input = new Input(Base64.decodeBase64(data));
				this.session = this.kryo.readObject(input,
						ConcurrentHashMap.class);
				input.close();
			} catch (Exception e) {
			}
		}
		if (this.session == null) {
			this.session = new ConcurrentHashMap<String, Object>();
			this.change();
		}
	}

	@Deprecated
	@Override
	public long getCreationTime() {
		return 0;
	}

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

	@Deprecated
	@Override
	public long getLastAccessedTime() {
		return 0;
	}

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

	@Deprecated
	@Override
	public void setMaxInactiveInterval(int interval) {
	}

	@Deprecated
	@Override
	public int getMaxInactiveInterval() {
		return 0;
	}

	@SuppressWarnings("deprecation")
	@Override
	public HttpSessionContext getSessionContext() {
		return null;
	}

	@Override
	public Object getAttribute(String name) {
		return session.get(name);
	}

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

	@Override
	public Enumeration<String> getAttributeNames() {
		return session.keys();
	}

	@Override
	public String[] getValueNames() {
		return session.keySet().toArray(new String[0]);
	}

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

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

	@Override
	public void removeAttribute(String name) {
		session.remove(name);
		this.change();
	}

	@Override
	public void removeValue(String name) {
		session.remove(name);
		this.change();
	}

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

	@Deprecated
	@Override
	public boolean isNew() {
		return false;
	}

	public String toCookieString() {
		Output output = new Output(1024, Constants.SESSION_MAX);
		this.kryo.writeObject(output, this.session);
		byte[] bytes = output.toBytes();
		output.close();
		return Base64.encodeBase64URLSafeString(bytes);
	}

	public void addToCookie(HttpServletResponse response, String path) {
		String cookieStr = this.toCookieString();
		CookieUtil.setCookie(response, Constants.SESSION_DATA, cookieStr, path);
	}

	private void change() {
		addToCookie(response, "/");
	}

	private void put(String name, Object value) {
		if (name == null)
			return;
		if (value == null)
			this.session.remove(name);
		else
			this.session.put(name, value);
	}

}

更新cookie

public static void setCookie(HttpServletResponse response, final Cookie cookie) {
        if (response.isCommitted()) {
            return;
        }
        final String headername = "Set-Cookie";
        String header = generateCookieString(cookie);
        final String startsWith = cookie.getName() + "=";
        Collection<String> headers = response.getHeaders(headername);
        String replaceItem = null;
        for (String item : headers) {
			if(item.startsWith(startsWith)){
				replaceItem = item;
			}
		}
        if(replaceItem != null){
        	headers.remove(replaceItem);
        	response.setHeader(headername, header);
        	for (String item : headers) {
        		response.addHeader(headername, item);
			}
        }else{
        	response.addHeader(headername, header);
        }
    }

3.使用filter将request包装后再继续执行,在包装的request中重写获取session、sessionid等方法,转为自己实现的session

filter处理:

public void doFilter(ServletRequest request, ServletResponse response,
		FilterChain chain) throws IOException, ServletException {
	String uri = ((HttpServletRequest) request).getRequestURI();
	boolean isStatic = uri.matches(".*\\.(ico|png|gif|jpg|css|js)$"); //静态文件不需要session处理
	if (!isStatic) {
		logger.info("start session filter uri="+uri);

		CsmServletRequest req = new CsmServletRequest(
				(HttpServletRequest) request,
				(HttpServletResponse) response);
		chain.doFilter(req, response);
		logger.info("session filter finished");
	}else{
		chain.doFilter(request, response);
	}
}

request重写

public class CsmServletRequest extends HttpServletRequestWrapper {
	private HttpSession session;
	private HttpServletResponse response;

	public CsmServletRequest(HttpServletRequest request,
			HttpServletResponse response) {
		super(request);
		this.response = response;
	}

	@Override
	public HttpSession getSession() {
		return this.getSession(true);
	}

	@Override
	public HttpSession getSession(boolean create) {
		this.initSession(create);
		return this.session;
	}

	@Override
	public String getRequestedSessionId() {
		return this.getSession().getId();
	}

	private void initSession(boolean create) {
		if (this.session == null && create) {
			this.session = SessionBuilder.get(this, this.response).cookie()
					.build();
		}
	}
}

这样,每次对session的修改就能转为cookie的写入,集群中不再需要额外对session进行共享、复制处理。

时间: 2024-11-11 13:48:41

使用cookie管理Servlet的session的相关文章

玩转web之servlet(六)---session介绍及简单使用(登录验证中保存信息)

在浏览器与服务器进行交互时,往往需要把涉及到的一些数据保存下来,这时就需要使用cookie或session进行状态管理. 这篇文章先来说说session怎么用,首先在servlet中创建一个session来保存信息,举个例子,在做登陆验证时,如果登陆成功,需要将用户的信息保存到session中,怎么保存呢?下面给出代码: public class Login_Do extends HttpServlet { String order_name = ""; String order_pa

会话管理-2.1.Session介绍

1.Session是什么? 客户端浏览器访问服务器的时候,服务器把客户端信息以某种形式记录在服务器上.这就是Session. 客户端浏览器再次访问时只需要从该Session中查找该客户的状态就可以了,Session相当于程序在服务器上建立的一份客户档案,客户来访的时候只需要查询客户档案表就可以了. 2.Session的生命周期 Session在用户第一次访问服务器的时候自动创建.需要注意只有访问JSP.Servlet等程序时才会创建Session,只访问HTML.IMAGE等静态资源并不会创建S

JavaSe:Cookie 管理的API介绍

CookieManager 在使用HttpURLConnection中,并没有关于Cookie的管理.如果使用Java程序时,怎么管理cookie呢? Cookie案例 1. User Agent -> Server POST /acme/login HTTP/1.1 [form data] 2. Server -> User Agent HTTP/1.1 200 OK Set-Cookie2: Customer="WILE_E_COYOTE"; Version="

Servlet之Session处理

HttpSession 对象中可用的几个重要的方法: 1    public Object getAttribute(String name) 该方法返回在该 session 会话中具有指定名称的对象,如果没有指定名称的对象,则返回 null. 2    public Enumeration getAttributeNames() 该方法返回 String 对象的枚举,String 对象包含所有绑定到该session 会话的对象的名称. 3    public long getCreationT

jsp的Session 和Servlet的Session的区别

1.session机制    http是无状态的协议,客户每次读取web页面时,服务器都打开新的会话,而且服务器也不会自动维护客户的上下文信息,session就是一种保存上下文信息的机制,它是针对每一个用户的,变量的值保存在服务器端,通过SessionID来区分不同的客户,session是以cookie或URL重写为基础的,默认使用cookie来实现,系统会创造一个名为JSESSIONID的输出返回给客户端Cookie保存. 2.jsp和Servlet的关系    jsp是servlet的一种简

servlet的session的生命周期

谈到javaweb首先想到的就是servlet,说道servlet就会想到servlet的生命周期 说道servlet的生命周期 就绕不过servlet的三个方法init service destroy 当我们将web项目部署到服务器,服务器启动的时候,这个时候servlet还没创建,,服务器启动了  开始对外提供服务,客户端可以访问了, 当某一个客户端第一次访问时候此servlet时候------>服务器找不到servlet对象------->这个时候服务器就会创建servlet对象,并且调

JMeter——cookie管理

http请求默认值: 登录: 充值: 查看登录: 查看充值: ========================================================================================================= 方法一.添加http  cookie管理器 ===========================================================================================

PHP用COOKIE实现一套SESSION机制

PHP的 SESSION是根据访客浏览器传过来的SESSION ID(表现为一个COOKIE) 来找到服务器的会话文件(/tmp/SESS_ID),以便通过$_SESSION数组读取里面的内容(会话变量). 利用PHP的SESSION可以很方便地实现购物车,验证码,csrf_token的记录. 可以用一个会话变量存储经过serialize序列化成串的关联数组. 两种方式的比较 : COOKIE(PHPSESSID) -> /tmp/SESS_XXX -> $_SESSION数组 COOKIE(

jmeter cookie管理器 使用方法---新手学习记录1

首先得抓包: 我已post方法为例: POST /api/datasources/lemontest/jaql HTTP/1.1 Host: 192.168.1.107:8081 Content-Length: 916 Accept: application/json, text/plain, */* Origin: http://192.168.1.107:8081 User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.