标签:
由于集群下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);
}
}
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进行共享、复制处理。
标签:
原文地址:http://blog.csdn.net/wangdi_ao/article/details/42062921