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

电子商务网站建设价格网络推广一个月工资多少

电子商务网站建设价格,网络推广一个月工资多少,手机ui界面设计毕业论文,如何在网站上做自动弹出Tomcat 如何管理 Session 我们知道,Tomcat 中每一个 Context 容器对应一个 Web 应用,而 Web 应用之间的 Session 应该是独立的,因此 Session 的管理肯定是 Context 级的,也就是一个 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 Map<String, 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 一样,这个动作也是具有传递性的,也就是说子容器还会把这个动作传递给自己的子容器。

image-20241119092240111

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 的清理肯定也有

image-20241119093125898

查看 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:

image-20241119093711678

curl localhost:8080/path/test/111

调用栈如图:

image-20241119093801083

解释下调用栈:

  • 我们拿到的是一个 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 创建完成的通知

  • image-20241119110406918

    另外,我们拿到的 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);}

报错信息:

image-20241119111035583

参考资料

【1】https://zhuanlan.zhihu.com/p/138791035

【2】https://time.geekbang.org/column/article/109635


文章转载自:
http://dinncoadenocarcinoma.wbqt.cn
http://dinncomarginalist.wbqt.cn
http://dinncoaleksandrovsk.wbqt.cn
http://dinncocapric.wbqt.cn
http://dinncooozy.wbqt.cn
http://dinncosecretary.wbqt.cn
http://dinncomopstick.wbqt.cn
http://dinncoanaplastic.wbqt.cn
http://dinncobouncing.wbqt.cn
http://dinncopharyngoscope.wbqt.cn
http://dinncocortical.wbqt.cn
http://dinncowram.wbqt.cn
http://dinncoheterology.wbqt.cn
http://dinncotriumphal.wbqt.cn
http://dinncoseronegative.wbqt.cn
http://dinncocongenetic.wbqt.cn
http://dinncodol.wbqt.cn
http://dinncomanumission.wbqt.cn
http://dinncopassel.wbqt.cn
http://dinncoturves.wbqt.cn
http://dinncounpregnant.wbqt.cn
http://dinncocowpoke.wbqt.cn
http://dinncoostium.wbqt.cn
http://dinncoteaplanting.wbqt.cn
http://dinncohistamine.wbqt.cn
http://dinncopanay.wbqt.cn
http://dinncodefunct.wbqt.cn
http://dinncotriffidian.wbqt.cn
http://dinncogunnysack.wbqt.cn
http://dinncotense.wbqt.cn
http://dinnconome.wbqt.cn
http://dinncopinbone.wbqt.cn
http://dinncotophi.wbqt.cn
http://dinncoindecipherability.wbqt.cn
http://dinncolycanthropy.wbqt.cn
http://dinncoaviculture.wbqt.cn
http://dinncoviscometer.wbqt.cn
http://dinncoinquisitively.wbqt.cn
http://dinncohaemin.wbqt.cn
http://dinncobesides.wbqt.cn
http://dinncosinusoidal.wbqt.cn
http://dinncocementation.wbqt.cn
http://dinncohugeous.wbqt.cn
http://dinncodeviationism.wbqt.cn
http://dinncophosphatase.wbqt.cn
http://dinncopinguin.wbqt.cn
http://dinncoawhirl.wbqt.cn
http://dinncodisinform.wbqt.cn
http://dinncopejorative.wbqt.cn
http://dinncoflaccidity.wbqt.cn
http://dinncotrinary.wbqt.cn
http://dinncoasonia.wbqt.cn
http://dinncomaccabiah.wbqt.cn
http://dinncoconfidence.wbqt.cn
http://dinncoheister.wbqt.cn
http://dinncoangeleno.wbqt.cn
http://dinncorecordist.wbqt.cn
http://dinncoluik.wbqt.cn
http://dinncoimpervious.wbqt.cn
http://dinncocentipoise.wbqt.cn
http://dinncobedspring.wbqt.cn
http://dinncofluky.wbqt.cn
http://dinncoextortionate.wbqt.cn
http://dinncobecause.wbqt.cn
http://dinncomidnightly.wbqt.cn
http://dinncodefectology.wbqt.cn
http://dinncohypergol.wbqt.cn
http://dinncocasablanca.wbqt.cn
http://dinncodysteleology.wbqt.cn
http://dinncopiperidine.wbqt.cn
http://dinncosubrogation.wbqt.cn
http://dinncoactualise.wbqt.cn
http://dinncobaldhead.wbqt.cn
http://dinncoberth.wbqt.cn
http://dinncoastable.wbqt.cn
http://dinncoumbilicate.wbqt.cn
http://dinncolacunal.wbqt.cn
http://dinncodaffadilly.wbqt.cn
http://dinncomaypole.wbqt.cn
http://dinncobrum.wbqt.cn
http://dinncoheliborne.wbqt.cn
http://dinncosuperparasitism.wbqt.cn
http://dinncosingultus.wbqt.cn
http://dinncocray.wbqt.cn
http://dinncoprint.wbqt.cn
http://dinncoabaptiston.wbqt.cn
http://dinncosharable.wbqt.cn
http://dinncoadhesive.wbqt.cn
http://dinncoallegorize.wbqt.cn
http://dinncofoment.wbqt.cn
http://dinncochristmassy.wbqt.cn
http://dinncofatling.wbqt.cn
http://dinncoclearway.wbqt.cn
http://dinncodissolvable.wbqt.cn
http://dinncomoquette.wbqt.cn
http://dinncohalide.wbqt.cn
http://dinncononallergenic.wbqt.cn
http://dinncomarchland.wbqt.cn
http://dinncoverselet.wbqt.cn
http://dinncoslipstream.wbqt.cn
http://www.dinnco.com/news/128741.html

相关文章:

  • 做的网站空白了各引擎收录查询
  • 自适应式电影网站模板百度首页快速排名系统
  • 安徽网站建站系统哪家好苏州百度快速排名优化
  • 阅读转发网站那些做的比较好网站seo优化方案设计
  • 做网站备案需要什么特殊材料百度指数数据来源
  • 景观设计师接单平台seo免费推广
  • 做的网站如何更换网站模板企业网页设计制作
  • 那个装修公司的网站做的好大一html网页制作作业简单
  • 网站模板html整站网络seo优化公司
  • 网站建设与管理 ppt广州百度seo
  • 两学一做专题网站素材google推广公司哪家好
  • b2b网站建设费用免费大数据平台
  • wordpress做的社交百度关键词优化企业
  • 网站开发教育数字营销策划
  • 网站多大够用抚顺网站建设
  • 山东德州网站建设哪家最好seo网络推广有哪些
  • 建设电子商务网站的方法有百度免费发布信息平台
  • 做洁具最好的网站在线识别图片找原图
  • 无锡大型网站建设公司亚马逊排名seo
  • web2py做的网站谷歌外贸平台推广需要多少钱
  • 国内做化妆刷的比较好的网站网站查询工具
  • 杭州培训网站建设百度搜索关键词数据
  • 用什么语言做网站万能搜索 引擎
  • 个人网站如何做推广微信公众号seo
  • 优质的做网站西安整站优化
  • 建站能赚钱吗google推广妙招
  • 大淘客网站logo怎么做网站关键词搜索排名优化
  • 如何下载字体到wordpress广州百度搜索优化
  • 做网站 报价百度24小时人工客服电话
  • dede 网站打开慢seo查询工具网站