Zhiqim Httpd即知启蒙WEB容器,是Zhiqim Framework面向WEB开发的多例服务,提供更简洁配置、积木式组件模块和天然的模型模板设计。
HttpSessionAbs.java14KB
/*
* 版权所有 (C) 2015 知启蒙(ZHIQIM) 保留所有权利。[遇见知启蒙,邂逅框架梦]
*
* https://zhiqim.org/project/zhiqim_framework/zhiqim_httpd.htm
*
* Zhiqim Httpd is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
package org.zhiqim.httpd;
import java.util.List;
import org.zhiqim.kernel.model.maps.HashMapSO;
import org.zhiqim.kernel.model.maps.HashMapSS;
import org.zhiqim.kernel.model.maps.MapSV;
import org.zhiqim.kernel.json.Jsons;
import org.zhiqim.kernel.util.Asserts;
import org.zhiqim.kernel.util.DateTimes;
import org.zhiqim.kernel.util.Ints;
import org.zhiqim.kernel.util.Longs;
import org.zhiqim.kernel.util.Strings;
/**
* HttpSession抽象类,公共属性
* 1.sessionId 会话唯一标识,用于SessionManager管理
* 2.created 会话创建时间
* 3.accessed 会话访问时间
* 4.sessionName 会话名称,用于业务上作为唯一标识
* 5.sessionUser 会话对象,用于业务对象模型,作为存储
* 6.attributes 属性列表
* 持久化时,6个值都将保存到持久化层
*
* @version v1.0.0 @author zouzhigang 2020-5-14 新建与整理
*/
public abstract class HttpSessionAbs implements HttpSession
{
//会话管理器
protected transient HttpContext context;
protected transient HttpSessionManager sessionManager;
//定义浸入式更换sessionId的保留老编号,在HttpResponse时清理,因此是临时保存
protected transient String oldSessionId;
//会话标准六属性,编号、两个时间、两个客户端属性
protected String sessionId;
protected long created;
protected long accessed;
protected String userIp;
protected String userAgent;
//会话业务属性表,由业务侧设置和管理
protected HashMapSO attributeMap;
protected HashMapSS attributeGenerics;
//会话用户属性,从业务属性表中独立出来,特指登录用户属性,简化开发
protected HttpSessionUser sessionUser;
/******************************************************************************************/
//构造函数
/******************************************************************************************/
/** 空构造函数用于远程时创建再解析 */
public HttpSessionAbs()
{
}
/** 参数构造函数用于本地创建传到远程 */
public HttpSessionAbs(String sessionId, String userIp, String userAgent, HttpSessionManager sessionManager)
{
this.sessionManager = sessionManager;
this.context = sessionManager.getContext();
this.sessionId = sessionId;
this.created = System.currentTimeMillis();
this.accessed = created;
this.userIp = userIp;
this.userAgent = userAgent;
this.attributeMap = new HashMapSO();
this.attributeGenerics = new HashMapSS();
}
@Override /** 子类必须使用的同步到远程的方法 */
public abstract void flush();
/******************************************************************************************/
//用于业务浸入式更改sessionId(注:谨慎使用),HttpResponse会oldSessionId进行处理
/******************************************************************************************/
@Override /** 用于业务修改ID值,请谨慎使用 */
public void setNewSessionId(String newSessionId)
{
if (newSessionId.equals(this.sessionId))
return;
this.oldSessionId = this.sessionId;
this.sessionId = newSessionId;
}
@Override /** 获取老会话编号,用于响应时查出来从管理器中删除 */
public String getOldSessionId()
{
return oldSessionId;
}
@Override /** 清除老会话编号,在响应时从管理器中删除老会话后,清除新会话中的老会话标志 */
public void clearOldSessionId()
{
this.oldSessionId = null;
}
/******************************************************************************************/
//使会话失效
/******************************************************************************************/
@Override /** 会话主动失效 */
public void invalidate()
{
if (sessionUser != null)
{//解除绑定
sessionUser.setSession(null);
sessionUser = null;
}
if (attributeMap != null)
{//清除属性
attributeMap.clear();
attributeMap = null;
}
if (oldSessionId != null)
{//清除旧会话
sessionManager.invalidateSession(oldSessionId);
oldSessionId = null;
}
if (sessionId != null)
{//清除当前会话
sessionManager.invalidateSession(sessionId);
sessionId = null;
}
}
/******************************************************************************************/
//获取参数判断值
/******************************************************************************************/
@Override
public HttpContext getContext()
{
return context;
}
@Override
public String getId()
{
return sessionId;
}
@Override
public boolean isNew()
{
return created == accessed;
}
@Override
public String getUserIp()
{
return userIp;
}
@Override
public String getUserAgent()
{
return this.userAgent;
}
@Override
public int getMaxInactiveInterval()
{
return sessionManager.getSessionTimeout();
}
@Override
public long getCreated()
{
return created;
}
@Override
public String getCreateTime()
{
return DateTimes.toDateTimeString(created);
}
@Override
public long getLastAccessed()
{
return accessed;
}
@Override
public String getLastAccessTime()
{
return DateTimes.toDateTimeString(accessed);
}
@Override
public long getRemainSecond()
{
long remain = System.currentTimeMillis() - getLastAccessed();
return getMaxInactiveInterval() - remain / 1000;
}
@Override
public long getRemainMinute()
{
return getRemainSecond() / 60;
}
@Override
public long[] getRemainTime()
{
long time = getRemainSecond();
long day = time / 86400;
long hour = time % 86400 / 3600;
long minute = time % 3600 / 60;
long second = time % 60;
return new long[]{day, hour, minute, second};
}
@Override
public String getRemainTimeDesc()
{
long[] times = getRemainTime();
StringBuilder strb = new StringBuilder();
if (times[0] > 0)
strb.append(times[0]).append("天");
if (times[1] > 0)
strb.append(times[1]).append("小时");
if (times[2] > 0)
strb.append(times[2]).append("分");
strb.append(times[3]).append("秒");
return strb.toString();
}
/**********************************************/
//SessionUser相关
/**********************************************/
@Override /** 绑定会话用户信息 */
public boolean bindSessionUser(HttpSessionUser sessionUser)
{
boolean binded = false;
if (this.sessionUser != null && !this.sessionUser.equals(sessionUser))
{//清理原关系
this.sessionUser.setSession(null);
this.sessionUser = null;
binded = true;
}
if (sessionUser != null)
{//增加新关系
this.sessionUser = sessionUser;
this.sessionUser.setSession(this);
binded = true;
}
return binded;
}
@Override /** 解绑会话用户信息 */
public boolean unbindSessionUser()
{
if (this.sessionUser == null)
return false;
this.sessionUser.setSession(null);
this.sessionUser = null;
return true;
}
/** 子类会话在远程重建时回调设置会话和会话用户的关联 */
protected void bindSessionUser(HttpSession session)
{
if (sessionUser == null)
return;
sessionUser.setSession(session);
}
/**********************************************/
//获取或判断SessionUser相关
/**********************************************/
@Override /** 判断会话中是否有用户信息 */
public boolean hasSessionUser()
{
return sessionUser != null;
}
@Override /** 获取会话用户信息中用户类,多个时抛异常,多会话用户时请谨慎调用 */
public HttpSessionUser getSessionUser()
{
return sessionUser;
}
@Override /** 判断会话中是否有用户信息且指定的用户类 */
public <T extends HttpSessionUser> boolean hasSessionUser(Class<T> clazz)
{
return sessionUser != null && sessionUser.getClass() == clazz;
}
@Override /** 获取会话用户信息且指定的用户类 */
@SuppressWarnings("unchecked")
public <T extends HttpSessionUser> T getSessionUser(Class<T> clazz)
{
return sessionUser == null?null:sessionUser.getClass() == clazz?(T)sessionUser:null;
}
@Override /** 获取会话用户名称,多个时抛异常,多会话用户时请谨慎调用 */
public String getSessionName()
{
return sessionUser == null?null:sessionUser.getSessionName();
}
/**********************************************/
//写入关联到session中attribute列表
/**********************************************/
@Override
public Object removeAttribute(String name)
{
attributeGenerics.remove(name);
return attributeMap.remove(name);
}
@Override
public void setAttribute(String name, Object value)
{
Asserts.as(!(value instanceof List || value instanceof MapSV)?null:"本方法不支持List<T>和MapSV<V>,请使用有泛型参数的setAttribute方法");
attributeMap.put(name, value);
}
@Override
public void setAttribute(String name, Object value, Class<?> genericClass)
{
Asserts.as((value instanceof List || value instanceof MapSV)?null:"本方法仅支持List<T>和MapSV<V>,请使用无泛型参数的setAttribute方法");
attributeMap.put(name, value);
attributeGenerics.put(name, genericClass.getName());
}
/**********************************************/
//获取关联到session中attribute列表
/**********************************************/
@Override
public HashMapSO getAttributes()
{
return attributeMap;
}
@Override
public boolean hasAttribute(String name)
{
return attributeMap.containsKey(name);
}
@Override
public Object getAttribute(String name)
{
return attributeMap.get(name);
}
@Override
public Object getAttribute(String name, Object defaultValue)
{
Object value = attributeMap.get(name);
return (value == null)?defaultValue:value;
}
@Override
public String getAttributeString(String name)
{
return getAttributeString(name, null);
}
@Override
public String getAttributeString(String name, String defaultValue)
{
Object value = getAttribute(name);
return (value == null)?defaultValue:Strings.trim(String.valueOf(value));
}
@Override
public int getAttributeInt(String name)
{
return getAttributeInt(name, -1);
}
@Override
public int getAttributeInt(String name, int defaultValue)
{
return Ints.toInt(attributeMap.get(name), defaultValue);
}
@Override
public long getAttributeLong(String name)
{
return getAttributeLong(name, -1);
}
@Override
public long getAttributeLong(String name, long defaultValue)
{
return Longs.toLong(attributeMap.get(name), defaultValue);
}
@Override
public boolean getAttributeBoolean(String name, boolean defaultValue)
{
Object value = attributeMap.get(name);
if (value == null)
return defaultValue;
else if (value instanceof Boolean)
return (Boolean)value;
else if (value instanceof String)
return Boolean.parseBoolean((String)value);
else
return defaultValue;
}
/*******************************************************************/
//会话用户不公开的moreMap方法,通过透传让RmiSession可访问
/*******************************************************************/
protected void removeSessionUserMore(String name)
{
sessionUser.removeMore(name);
}
protected void addSessionUserMore(String name, String value)
{
sessionUser.addMore(name, value);
}
protected HashMapSS getSessionUserMoreMap()
{
return sessionUser.getMoreMap();
}
protected void setSessionUserValueGeneric(String key, Object value, String genericClassName)
{
sessionUser.setValueGeneric(key, value, genericClassName);
}
protected String getSessionUserValueGeneric(String key)
{
return sessionUser.getValueGeneric(key);
}
/**********************************************/
//清理和转换成字符串
/**********************************************/
@Override
public String toString()
{
return Jsons.toString(this);
}
}