当前位置: 首页 > news >正文

门户和网站的区别宝安印刷网站建设

门户和网站的区别,宝安印刷网站建设,wordpress对接静态网页,2022拉人头最暴利的appTomcat 如何管理 Session 我们知道#xff0c;Tomcat 中每一个 Context 容器对应一个 Web 应用#xff0c;而 Web 应用之间的 Session 应该是独立的#xff0c;因此 Session 的管理肯定是 Context 级的#xff0c;也就是一个 Context 一定关联多个 Session。 Tomcat 中主…Tomcat 如何管理 Session 我们知道Tomcat 中每一个 Context 容器对应一个 Web 应用而 Web 应用之间的 Session 应该是独立的因此 Session 的管理肯定是 Context 级的也就是一个 Context 一定关联多个 Session。 Tomcat 中主要由每个 Context 容器内的一个 Manager 对象来管理 Session。抽象实现类是 ManagerBase默认实现类为 StandardManager。 查看 org.apache.catalina.Manager 的接口(省略部分): public interface Manager {public Context getContext();public void setContext(Context context);public void add(Session session);public void changeSessionId(Session session);public void changeSessionId(Session session, String newId);public Session createEmptySession();public Session createSession(String sessionId);public Session findSession(String id) throws IOException;public Session[] findSessions();public void load() throws ClassNotFoundException, IOException;public void remove(Session session);public void remove(Session session, boolean update);public void unload() throws IOException;public void backgroundProcess(); }其中就有创建和删除 Session 的接口其中的 load 和 reload 是将 session 在存储介质中 保存/卸载。 Session 的创建 查看 Manager 的抽象实现类 org.apache.catalina.session.ManagerBase public abstract class ManagerBase extends LifecycleMBeanBase implements Manager {/*** The Context with which this Manager is associated.*/private Context context;/*** The set of currently active Sessions for this Manager, keyed by* session identifier.*/protected MapString, Session sessions new ConcurrentHashMap();}其中有两个关键属性如上所示一个是与该对象关联的 Context 对象一个是存放 session 的一个 Map。 StandardManager 继承了 ManagerBase直接复用了它的创建方法 public Session createSession(String sessionId) {// 首先判断 Session 数量是不是到了最大值最大 Session 数可以通过参数设置if ((maxActiveSessions 0) (getActiveSessions() maxActiveSessions)) {rejectedSessions;throw new TooManyActiveSessionsException(sm.getString(managerBase.createSession.ise),maxActiveSessions);}// 复用或者创建一个 session 实例Session session createEmptySession();// 初始化空 session 的属性值session.setNew(true);session.setValid(true);session.setCreationTime(System.currentTimeMillis());session.setMaxInactiveInterval(getContext().getSessionTimeout() * 60);String id sessionId;if (id null) {id generateSessionId();}// setId 将 session 保存到了 map 中session.setId(id);// 计数器加 1sessionCounter;SessionTiming timing new SessionTiming(session.getCreationTime(), 0);synchronized (sessionCreationTiming) {sessionCreationTiming.add(timing);sessionCreationTiming.poll();}return session;}查看 setId() 方法 public void setId(String id, boolean notify) {if ((this.id ! null) (manager ! null)) {manager.remove(this);}this.id id;if (manager ! null) {// 实现类里把 session put 到了 map 里manager.add(this);}// 如果需要触发创建通知if (notify) {tellNew();}}/*** 通知监听器有关新会话的信息*/public void tellNew() {// Notify interested session event listenersfireSessionEvent(Session.SESSION_CREATED_EVENT, null);// 获取 context 对象和 listener 对象Context context manager.getContext();Object listeners[] context.getApplicationLifecycleListeners();if (listeners ! null listeners.length 0) {HttpSessionEvent event new HttpSessionEvent(getSession());for (Object o : listeners) {// 判断是否是 HttpSessionListener 的实例if (!(o instanceof HttpSessionListener)) {continue;}HttpSessionListener listener (HttpSessionListener) o;try {context.fireContainerEvent(beforeSessionCreated, listener);// 其实就是这个方法我们只需要实现 HttpSessionListener 并注册 bean 就可以listener.sessionCreated(event);context.fireContainerEvent(afterSessionCreated, listener);} catch (Throwable t) {ExceptionUtils.handleThrowable(t);try {context.fireContainerEvent(afterSessionCreated, listener);} catch (Exception e) {// Ignore}manager.getContext().getLogger().error (sm.getString(standardSession.sessionEvent), t);}}}}Session 的清理 容器组件会开启一个 ContainerBackgroundProcessor 后台线程调用自己以及子容器的 backgroundProcess 进行一些后台逻辑的处理和 Lifecycle 一样这个动作也是具有传递性的也就是说子容器还会把这个动作传递给自己的子容器。 StandardContext 重写了该方法它会调用 StandardManager 的 backgroundProcess 进而完成 Session 的清理工作下面是 StandardManager 的 backgroundProcess 方法的代码 public void backgroundProcess() {// processExpiresFrequency 默认值为 6而 backgroundProcess 默认每隔 10s 调用一次也就是说除了任务执行的耗时每隔 60s 执行一次count (count 1) % processExpiresFrequency;if (count 0) // 默认每隔 60s 执行一次 Session 清理processExpires(); }/*** 单线程处理不存在线程安全问题*/ public void processExpires() {// 获取所有的 SessionSession sessions[] findSessions(); int expireHere 0 ;for (int i 0; i sessions.length; i) {// Session 的过期是在 isValid() 方法里处理的if (sessions[i]!null !sessions[i].isValid()) {expireHere;}} }既然 session 的创建会有事件通知那么 session 的清理肯定也有 查看 HttpSessionListener public interface HttpSessionListener extends EventListener {/*** Notification that a session was created.* The default implementation is a NO-OP.** param se* the notification event*/public default void sessionCreated(HttpSessionEvent se) {}/*** Notification that a session is about to be invalidated.* The default implementation is a NO-OP.** param se* the notification event*/public default void sessionDestroyed(HttpSessionEvent se) {} }这两个方法分别在 session 创建和销毁时被调用 实践 RestController RequestMapping(/path) Slf4j public class PathController {GetMapping(/test/{strs})public void testPath(PathVariable(strs) String strs, HttpServletRequest request) {HttpSession session request.getSession();log.info(接收到的strs值为:{}, strs);}}Slf4j Configuration public class SessionListener implements HttpSessionListener {Overridepublic void sessionCreated(HttpSessionEvent se) {log.info(session created);}Overridepublic void sessionDestroyed(HttpSessionEvent se) {log.info(session destroyed);} }进行 Debug curl localhost:8080/path/test/111调用栈如图 解释下调用栈 我们拿到的是一个 RequestFacade 类的对象这个对象其实是真正 request 的包装类构造器如下 public RequestFacade(Request request) {this.request request;}在包装类里我们调用了内部的 getSession()省略非关键代码最后调用了内部 request 的 getSession public HttpSession getSession() {return getSession(true);}public HttpSession getSession(boolean create) {if (SecurityUtil.isPackageProtectionEnabled()){return AccessController.doPrivileged(new GetSessionPrivilegedAction(create));} else {// 调用了内部 request 的 getSessionreturn request.getSession(create);}}在 request 的 getSession 中取到了 context 和 manager 对象开始走目录1中 session 创建的逻辑 protected Session doGetSession(boolean create) {// There cannot be a session if no context has been assigned yetContext context getContext();// Return the requested session if it exists and is validManager manager context.getManager();// Create a new session if requested and the response is not committedif (!create) {return null;}// Re-use session IDs provided by the client in very limited// circumstances.String sessionId getRequestedSessionId();// 这个方法走到了 ManagerBase 的 createSession 也就是目录1中介绍过的函数session manager.createSession(sessionId);session.access();return session;}最终进行 session 创建完成的通知 另外我们拿到的 session 其实也是一个包装类包装类的好处是对外界封闭细节避免暴露过多的内部实现防止外界进行危险操作例如这里我们假如把 session 强转为 StandardSession就会出现类型转换的错误。如下 GetMapping(/test/{strs})public void testPath(PathVariable(strs) String strs, HttpServletRequest request) {HttpSession session request.getSession();// 强转为 StandardSessionStandardSession standardSession (StandardSession) session;// 拿到 manager 对象多造几个 sessionManager manager standardSession.getManager();manager.createSession(1111);manager.createSession(2222);log.info(接收到的strs值为:{}, strs);}报错信息 参考资料 【1】https://zhuanlan.zhihu.com/p/138791035 【2】https://time.geekbang.org/column/article/109635
http://www.dnsts.com.cn/news/9121.html

相关文章:

  • 网站 搜索引擎 提交免费浏览网站推广
  • 网站运营流程wordpress如何连接到数据库
  • 局域网内网站建设的步骤过程快速排名刷
  • 水泥公司网站建设综合型企业网站有哪些
  • 星夜智能建站平台山东兴润建设集团网站
  • 网站建设需要用到iis吗网站前端切图做多个页面
  • 烟台做网站多钱网站开发 asp.net 还要学什么
  • 常州西站建设规划小学网站建设情况
  • 外贸网站宗旨长链接怎么弄成短链接
  • 环保设备在那个网站做有限责任公司法人承担什么责任
  • jsp网站缓存在哪无锡网站建设工作
  • ui最好的网站上海风险等级最新
  • 上海最专业的网站设计制wordpress 504 gateway time-out
  • 网站做菠菜阿里云做网站可以吗
  • 北京营销型网站建设培训生物网站建设
  • 做商城网站怎么做cms网站建设
  • 网站开发工程师项目经验怎么写花都营销型网站
  • wordpress上线apache嘉兴优化公司
  • 东莞网站设计师简述seo的优化流程
  • 那个网站做二手买卖的黄龙云 加强网站建设
  • 网站架构制作wordpress主题mx
  • 淘宝联盟怎么新建网站比wordpress好的工具
  • 电子科技企业网站建设东莞建筑公司招聘信息
  • 做网站推广都有哪些行业扬中简介
  • 知乎网站建设入门书蚌埠做网站的公司
  • 网站建设自查自评做快消品看那些网站好
  • 杭州网站建设科技有限公司国内定机票网站建设
  • 广州网站建设 骏域网页小游戏的网站
  • 个人做网站怎样才能建一个网站
  • 免费ppt模板下载哪个网站好东莞互联网推广