【读书笔记/源码】How Tomcat Works 笔记- c11~c13
- chapter11:
standardwrapper
- chapter12: 无程序
第十章 安全性
servlet容器是通过一个名为验证器的阀来支持安全限制的。当servlet容器启动时,验证器阀会被添加到Context容器的管道中。
验证器阀会调用Context容器的领域对象的authenticate()方法,传入用户输入的用户名和密码,来对用户进行身份验证。领域对象可以访问有效用户的用户名和密码的集合。
servlet编程中安全性功能的概念包括主题、角色、领域和登陆配置等。可以阅读《Java for the Web with Senlets, JSP, and EJB》一书
10.1 领域
- 领域对象用来对用户进行身份验证的组件。领域对象通常都会与一个Context容器相关联,而一个Context容器也只能有一个领域对象。
- 领域对象如何验证用户身份呢?它保存了所有有效用户的用户名和密码对,或者它会访问存储这些数据的存储器。在Tomcat中,有效信息默认存储在tomcat-user.xml文件中。但是也可以使用其他领域对象来实现。
- 在Catalina中,领域对象是org.apache.catalina.Realm接口的实例。
10.2 GenericPrincipal类
- 主体对象是java.seurity.Principal接口的实例。该接口在Catalina中的实现是org.apache.catalina.realm.GenericPrincipal类。GenericPrincipal实例必须始终与一个领域对象相关联。
10.3 LoginConfig类
登录配置是final型的org.apache.catalina.deploy.LoginConfig类的实例,其中包含一个领域对象的名字。LoginConfig实例封装了领域对象名和所要使用的身份验证方法。
在实际部署中,Tomcat在启动时需要读取web.xml文件的内容。如果web.xml文件包含login-config元素的配置,则Tomcat会创建一个LoginConfig对象。
10.4 Authenticator
验证器是Authenticator接口的实例。Authenticator接口本身并没有声明方法。只是起到了一个标记作用,这样其他组件就可以使用instanceof
关键字检查某个组件是不是一个验证器。
Catalina提供了Authenticator接口的一个基本实现,AuthenticatorBase类。除了实现Authenticator接口外,AuthenticatorBase类还扩展了org.apache.catalina.values.ValveBase类。这就是说AuthenticatorBase类也是一个阀。
10.5 安装验证器阀
在部署描述器中,login-config元素仅能出现一次。login-config元素包含一个auth-method元素来指定身份验证方法。也就是说,一个Context实例只能有一个LoginConfig实例和利用一个验证类的实现。
由于使用的验证器类是在运行时才确定的,因此该类是动态载入的。StandardContext类使用org.apache.catalina.startup.ContextConfig类来对StandardContext实例的属性进行设置。这些设置包括实例化一个验证器类,并将该实例与Context实例相关联。本章示例中SimpleContextConfig类的实例负责动态载入BasicAuthenticator类,实例化其对象,并将其作为一个阀安装到StandardContext实例中。
10.6 应用程序
simple-realm
com.lab.tomcat.Bootstrap#main
- …
- org.apache.catalina.core.StandardContext#start
- …
- org.apache.catalina.core.ContainerBase#start
- …
- com.lab.tomcat.core.SimpleContextConfig#lifecycleEvent
- com.lab.tomcat.core.SimpleContextConfig#authenticatorConfig
- 检查是否有安全限制
context.findConstraints();
- 如果有安全限制,检查是否有LoginConfig对象
context.getLoginConfig();
- 一个Context实例只能有一个验证器,当发现某个阀是验证器后,直接返回
- 检查当前Context实例是否有关联的领域对象
context.getRealm()
- 若找到了领域对象,则动态载入
BasicAuthenticator
类,创建该类的一个实例,并作为阀添加到StandardContext中。
- 检查是否有安全限制
- com.lab.tomcat.core.SimpleContextConfig#authenticatorConfig
simple-user-database-realm
com.lab.tomcat.realm.SimpleUserDatabaseRealm#authenticate
- …
浏览器请求后
org.apache.catalina.connector.http.HttpProcessor#run
- org.apache.catalina.connector.http.HttpProcessor#process
- org.apache.catalina.connector.http.HttpProcessor#parseHeaders
- 获取header上的
authorization
参数 - org.apache.catalina.connector.RequestBase#setAuthorization
- 获取header上的
- org.apache.catalina.core.StandardContext#invoke
- org.apache.catalina.core.StandardPipeline#invoke
- org.apache.catalina.core.StandardPipeline#invokeNext
- org.apache.catalina.authenticator.AuthenticatorBase#invoke
- org.apache.catalina.authenticator.BasicAuthenticator#authenticate
- 从request中取出
authorization
参数 org.apache.catalina.Request#getAuthorization - com.lab.tomcat.realm.SimpleUserDatabaseRealm#authenticate
- 从request中取出
- org.apache.catalina.authenticator.BasicAuthenticator#authenticate
- org.apache.catalina.authenticator.AuthenticatorBase#invoke
- org.apache.catalina.core.StandardPipeline#invokeNext
- org.apache.catalina.core.StandardPipeline#invoke
- org.apache.catalina.connector.http.HttpProcessor#parseHeaders
第十一章 StandardWrapper
11.1 方法调用序列
对于每个引入的HTTP请求,连接器都会调用与其关联的servlet容器的invoke()方法。然后servlet容器会调用其所有子容器的invoke()方法。
回忆下第五章内容,servlet容器包含一条管道和一个或多个阀。
具体过程如下
- 连接器创建请求和响应对象
- 连接器调用 StandardContext 的 invoke 方法
- StandardContext 实例的 invoke 方法调用其pipeline的 invoke 方法,即调用其基础阀 StandardContextValve 的 invoke 方法
- StandardContextValve 的 invoke 方法得到合适的Wrapper实例处理HTTP请求,调用Wrapper实例的 invoke 方法
- StandardWrapper 是Wrapper接口的标准实现,StandardWrapper 实例的 invoke 方法其pipeline对象的 invoke 方法
- StandardWrapper的pipeline对象的基础阀是StandardWrapperValve类的实例。 因此,会调用StandardWrapperValve 的 invoke 方法,StandardWrapperValve 的 invoke 方法会调用Wrapper实例的 allocate 方法获得一个 servlet 的实例。
- allocate 方法调用 load 方法来加载一个 servlet类,若已经载入则无需重复
- load 方法调用 servlet 的 init 方法
- StandardWrapperValve调用servlet实例的service()方法
StandardContext的构造函数中会设置StandardContextValue做基础阀
StandardWrapper的构造函数中会设置StandardWrapperValve做基础阀
本章着重说明servlet实例时如何调用的。 先对SingleThreadModel接口进行介绍,该接口是理解Wrapper如何载入servlet类的关键。
11.2 SingleThreadModel
servlet类可以实现javax.servlet.SingleThreadModel接口,这样的servlet类也称作SingleThreadModel(STM)类。根据Servlet规范,实现此接口的目的是保证servlet实例一次只处理一个请求。
实现SingleThreadModel接口的servlet类只能保证在同一时刻,只有一个线程在执行该servlet实例的service()方法,但为了提高性能,servlet容器会创建多个STM servlet实例。也就是说,STM servlet实例的service()方法会在多个STM servlet实例中并发执行。如果servlet实例需要访问静态类变量或类外的某些资源的话,就有可能引起同步问题。
(在Servlet2.4规范中,SingleThreadModel接口已经弃用了)
11.3 StandardWrapper
StandardWrapper对象的主要任务是载入它所代表的servlet类,并进行实例化。但是,StandardWrapper类并不调用servlet的service方法,而由StandardWrapperValue对象(StandardWrapper实例的pipeline基础阀)完成。StandardWrapperValue对象调用allocate()方法从StandardWrapper实例中获取servlet实例。之后调用servlet实例的service方法。
至于当StandardWrapperValue实例请求servlet实例时,StandardWrapper实例必须考虑到该servlet类是否实现了SingleThreadModel(STM)接口。
对于那些没有实现STM接口的servlet类,只会被StandardWrapper载入一次。之后的请求都访问该类的同一实例。StandardWrapper类不需要多个servlet实例,因为它假设该servlet类的service()方法在多线程环境中是线程安全的。如果必要的话,由servlet程序员来负责同步对共享资源的访问。
而对于一个STM servlet类。StandardWrapper实例必须保证每个时刻只能有一个线程在执行STM servlet类的service()方法。
但是为了更好的性能,StandardWrapper实例会维护一个STM servlet实例池。
Wrapper实例负责准备一个javax.servlet.servletConfig实例,后者在servlet实例内部可以获取到。
- 分配servlet实例
- 载入servlet类
StandardWrapper类不仅实现了Wrapper接口,还实现了javax.servlet.ServletConfig接口
StandardWrapper类并不将自身传递给servlet实例的init()方法。相反,它会在一个StandardWrapperFacade实例中包装自身,将其大部分的公共方法对servlet程序员隐藏起来。
无法单独使用一个Wrapper实例来表示一个servlet类的定义。Wrapper实例必须驻留在某个Context容器中,这样当调用其父容器的getServletContext()方法时才能返回ServletContext类的一个实例。
Wrapper的父容器只能是Context类的实现。
11.4 StandardWrapperFacade类
StandardWrapper实例会调用其所载入的servlet实例的init()方法。init()方法需要一个javax.servlet.ServletConfig实例,而StandardWrapper类本身实现了javax.servlet.ServletConfig接口,所以,理论上StandardWrapper对象可以将自己传入init()方法。但是StandardWrapper需要将大部分公共方法对servlet程序员隐藏起来。为了实现该目的,StandardWrapper类将自身实例包装成StandardWrapperFacade类的一个实例。
当创建StandardWrapper对象调用servlet实例的init()方法时,它会传入StandardWrapperFacade类的一个实例。这样,在servlet实例内调用ServletConfig类的getServletName()、getInitParameter()和getInitParameterNames()方法会直接传递给StandardWrapper类实现的相应方法。
11.5 StandardWrapperValue类
StandardWrapperValue类是StandardWrapper实例中的基础阀,要完成:
- 执行与该servlet实例关联的全部过滤器
- 调用servlet实例的service()方法
11.6 FilterConfig类
过滤器定义
11.7 ApplicationFilterConfig类
ApplicationFilterConfig类用于管理Web应用程序第一次启动时创建的所有过滤器实例。
11.8 ApplicationFilterChain类
StandardWrapperValue类的invoke()方法会创建ApplicationFilterChain类的一个实例,并调用其doFilter()方法。
11.9 应用程序
org.apache.catalina.core.StandardWrapper#allocate
- 对于非STM类,定义了
instance
属性。instance
为null则- org.apache.catalina.core.StandardWrapper#loadServlet 载入相关servlet类
++this.countAllocated;
- 若StandardWrapper表示的servlet类是STM servlet类,则试图从对象池
instancePool
中返回一个servlet实例。- 只要STM servlet实例数不超过指定的最大值,返回一个STM servlet实例。
...
synchronized(this.instancePool) {while(this.countAllocated >= this.nInstances) {if (this.nInstances < this.maxInstances) {try {this.instancePool.push(this.loadServlet());++this.nInstances;} catch (ServletException var6) {throw var6;} catch (Throwable var7) {throw new ServletException(ContainerBase.sm.getString("standardWrapper.allocate"), var7);}} else {try {this.instancePool.wait();} catch (InterruptedException var8) {}}}if (this.debug >= 2) {this.log(" Returning allocated STM instance");}++this.countAllocated;return (Servlet)this.instancePool.pop();
}
(StandardWrapperValve的方法挺一目了然的)
org.apache.catalina.core.StandardWrapperValve#invoke
- 调用StandardWrapper实例的allocate()方法获取该StandardWrapper实例所表示的servlet实例
- 调用私有方法createFilterChain(),创建过滤器链
- 调用过滤器链的doFilter()方法,其中包括调用servlet实例的service()方法。
- 释放过滤器链
- 调用Wrapper实例的deallocate()方法
- 若该servlet类再也不会被使用到,则调用Wrapper实例的unload()方法。
第十二章 StandardContext类
本章无程序
12.1 StandardContext的配置
- 正确设置后,StandardContext对象才能读取并解析默认的web.xml文件,该文件位于%CATALINA_HOME%目录下,该文件的内容会应用到所有部署到Tomcat中的应用程序。
- start()方法要做的一件事,是触发一个生命周期事件。该事件调用监听器。
- 用生命周期监听器配置StandardContext实例,当配置成功后,监听器会将其configured属性置为true。
tomcat5中start()方法与Tomcat4相似,但包含了一些与JMX相关的代码。
- start()方法需要完成
- 触发 BEFORE_START 事件
- 设置 availability 属性为 false
- 设置 configured 属性为 false
- 设置资源
- 设置载入器
- 设置Session管理器
- 初始化字符集映射器
- 启动与该Context容器相关联的组件
- 启动子容器
- 启动管道对象
- 启动Session管理器
- 触发 START 事件,在这里监听器(ContextConfig实例)会进行一系列配置操作,配置成功后,ContextConfig实例会将 StandardContext 实例的 configured 属性设置 为 true
- 检查 configured 属性的值,如果为 true,调用 postWelcomPages方法,加载需要在启动时就载入的子容器,即Wrapper实例,并将available属性设置为true。如果 configured 属性为 false,调用 stop 方法
- 触发 AFTER_START 事件
12.2 StandardContextWrapper类
- 对于每个引入的HTTP请求,都会调用StandardContext实例的管道对象的基础阀的invoke()方法来处理。
- 对于每个引入的HTTP请求,StandardContextValue实例调用Context容器的map()方法,并传入一个org.apache.catalina.Request对象。map()方法(实际上是定义在父类ContainerBase中的)会针对某个特定的协议调用findMapper()方法返回一个映射器对象,然后调用映射器对象的map()方法获取Wrapper实例。
- 在Tomcat4中用Mapper映射servlet
- Tomcat5中,Mapper接口以及其相关类已经移除了。事实上,StandardContextValue类的invoke()方法会从request对象中获取适合的Wrapper实例。
Wrapper wrapper = request.getWrapper();
- 该Wrapper实例指明了封装在request对象中的映射信息。
12.3 对重载的支持
- StandardContext类是通过其载入器实现应用程序重载的。在Tomcat4中,StandardContext对象中的WebappLoader类实现了Loader接口,并使用另一个线程检查WEB-INF目录中的所有类和JAR文件的时间戳。只需要调用其setContainer()方法将WebappLoader对象与StandardContext对象相关联就可以启动该检查线程。
12.4 backgroundProcess()方法
- 这个共享线程在ContainerBase对象中创建。ContainerBase类在其Start()方法中(即,当该容器启动时)嗲用其threadStart()方法启动该后台线程。
- ContainerBackgroundProcessor类时间上是ContainerBase类的内部类。在其run()方法中是一个while循环,周期性地调用其processChildren方法。而processChildred方法会调用自身对象地backgroundProcess()方法和其每个子容器地processChildren()方法。通过实现backgroundProcess()方法,ContainerBase类的子类可以使用一个专用线程来执行周期性任务,例如检查类的时间戳或检查session对象的超过时间。
第十三章 Host和Engine
如果想在同一个Tomcat上部署运行多个Context容器的话,你就需要使用Host容器。当只有一个Context容器时,理论上不需要使用Host容器。在Context接口的描述中有一段话。
Context容器的父容器通常是Host容器,也有可能是其他实现,或者如果不必要,就可以不使用父容器。
13.1 Host接口
- 比较重要的是map方法,该方法返回一个用来处理引入的HTTP请求的Context容器的实例。
13.2 StandardHost类
- 每引入一个HTTP请求,都会调用Host实例的invoke方法。由于StandardHost没有提供invoke方法实现,其会调用父类ContainerBase类的invoke方法,父类方法进而调用StandardHost实例的基础阀StandardHostValue实例的invoke方法。此外,StandardHostValue类的invoke方法会调用StandardHost类的map()方法来获取相应的Context实例来处理HTTP请求。
13.3 StandardHostMapper类
- 在Tomcat4中,ContainerBase类(也就是StandardHost的父类)会调用其addDefaultMapper()方法创建一个默认映射器。默认映射器的类型由mapperClass属性的值决定。
- 此外,StandardHost类的start()方法会在方法末尾调用父类的start()方法,确保默认映射器的创建完成。
Tomcat4中StandardContext类创建默认映射器的方法略有不同。其start()方法不会调用父类的start()方法。相反,StandardContext类的start()方法会调用addDefaultMapper()方法,并传入mapperClass变量来创建默认映射器。
13.4 StandardHostValue类
- 在Tomcat4中,invoke方法调用StandardHost实例的map()方法来获取一个相应Context实例
- 然后,invoke方法会获取与该request对象相关联的session的对象,并调用其access()方法。access()方法会修改session对象的最后访问时间。
13.5 为什么必须要有一个Host容器
- 在Tomcat4和5的实际部署中,若一个Context实例使用ContextConfig对象进行设置,就必须使用一个Host对象。原因:
- 使用ContextConfig对象需要知道应用程序web.xml文件的位置。在其applicationConfig()方法中它会试图打开web.xml文件。
- 其中,Constants.ApplicationWebXml的值为"/WEB-INF/web.xml",web.xml文件的相对路径,servletContext是一个ApplicationContext类型(实现了servletContext接口)的对象。
- ApplicationContext的getResource()代码中限制了如果要使用ContextConfig实例来进行配置的话,Context实例必须有一个Host实例作为父容器。即,除非自己实现ContextConfig类,否则必须使用一个Host容器。
13.7 Engine接口
- 在Engine容器中,可以设置一个默认Host或一个默认Context容器。注意,Engine容器可以与一个服务实例相关联。
13.8 StandardEngine类
- 相比于StandardContext类和StandardHost类,StandardEngine类相对小一些。
- Engine容器可以有子容器,只能是Host容器。
13.9 StandardEngineValue类
- 验证了request和response类型后,invoke()方法得到Host实例,用于处理请求。invoke方法会通过调用Engine实例的map()方法获取Host对象
感觉链路模式差不多,不进行代码调试记录了
第十四章 服务器组件和服务组件
暂略
第十五章 Digester库
暂略
第十六章 关键钩子
例如,在 Tomcat 部署通过实例化一个Server并调用它的 start 方法来启动一个 servlet 容器,该方法又调用其他组件的 start 方法。正常的情况下,可以通过一个关闭命令来让服务器关闭所有组件(如 14 章中介绍)。如果突然地关闭程序,如关闭运行中程序的控制台可能会发生意想不到的事情。
Java提供了方法可以在关闭过程中执行一些代码。
在 Java 中,虚拟机遇到两种事件的时候会关闭虚拟机:
- 应用程序正常退出如System.exit方法被调用,或者最后一个非守护进程线程退出。
- 用户突然强制终止虚拟机,例如键入 CTRL+C 或者在未关闭 Java程序的情况下从系统退出。
幸运的是,虚拟机在执行关闭操作的时候,会有经过以下两个阶段:
- 虚拟机启动所有注册的关闭钩子。关闭钩子是实现在 Runtime 上面注册的线程。所有的关闭钩子会并发执行直到完成任务。
- 虚拟机根据情况调用所有的未调用的终结器(finalizers)
本章重点说明第一个阶段,它允许虚拟机在应用程序中执行一些清理代码。关闭钩子是 java.lang.Thread 类的子类实例,可以如下创建一个关闭钩子:
- 写一个类继承 Thread 类
- 提供你的实现类中的 run 方法。该方法是应用程序被关闭的时候会执行的代码,无论是正常退出还是非正常退出。
- 在应用程序中,实例化关闭钩子类
- 使用当前的 Runtime 类的 addShutdownHook 方法来注册该关闭钩子。
你可能已经注意到,不需要像启动其他线程一样调用关闭钩子的start方法。虚拟机会在它运行其关闭序列时启动并执行关闭钩子。
第十七章 启动Tomcat
windows和linux脚本编写
暂略
第十八章 部署器
暂略
第十九章 Manager应用程序的servlet类
暂略
第二十章 基于JMX的管理
暂略
相关文章:
【读书笔记/源码】How Tomcat Works 笔记- c11~c13
chapter11: standardwrapperchapter12: 无程序 第十章 安全性 servlet容器是通过一个名为验证器的阀来支持安全限制的。当servlet容器启动时,验证器阀会被添加到Context容器的管道中。 验证器阀会调用Context容器的领域对象的authenticate()方法,传入…...
Electron快速入门——跨平台桌面端应用开发框架
个人简介 👀个人主页: 前端杂货铺 🙋♂️学习方向: 主攻前端方向,正逐渐往全干发展 📃个人状态: 研发工程师,现效力于中国工业软件事业 🚀人生格言: 积跬步…...
Vision Transformer模型详解(附pytorch实现)
写在前面 最近,我在学习Transformer模型在图像领域的应用。图像处理任务一直以来都是深度学习领域的重要研究方向,而传统的卷积神经网络已在许多任务中取得了显著的成绩。然而,近年来,Transformer模型由于其在自然语言处理中的成…...
中国区域创新创业指数IRIEC数据(省级、地市级)1990-2020年-社科数据
中国区域创新创业指数IRIEC数据(省级、地市级)1990-2020年-社科数据https://download.csdn.net/download/paofuluolijiang/90028728 https://download.csdn.net/download/paofuluolijiang/90028728 中国区域创新创业指数(IRIEC)…...
Elasticsearch:减少 Elastic 容器镜像中的 CVE(常见的漏洞和暴露)
作者:来自 Elastic Maxime Greau 在这篇博文中,我们将讨论如何通过在 Elastic 产品中切换到最小基础镜像并优化可扩展漏洞管理程序的工作流程来显著减少 Elastic 容器镜像中的常见漏洞和暴露 (Common Vulnerabilities and Exposures - CVEs)。 基于 Chai…...
webpack02
webpack中常用loader postcss-loader 在css-loader之前,对css进行一些操作,,,比如统一加前缀,,或者是重置样式,,, 这个postcss-loader会自己去找 postcss工具࿰…...
腾讯云更改用户为root
最近买了台99元一年的2核的云服务器,方便学习一些java开发中间件,以及部署一些项目。 1.设置root用户密码 sudo passwd root 2.修改配置文件 ll /etc | grep ssh cd /etc/ssh/ ls vim sshd_config 输入/PasswordAuthentication 寻找 输入:set nu 再按下…...
Excel导入导出-若依版本
最终效果 1、导出 1、在实体类上加注解 Excel(name “客户类型名称”) ToString AllArgsConstructor NoArgsConstructor public class UserType extends BaseEntity2 implements Serializable {Excel(name "客户类型ID", cellType Excel.ColumnType.NUMERIC…...
【Qt】快速添加对应类所需的头文件包含
快速添加对应类所需的头文件包含 一,简介二,操作步骤 一,简介 本文介绍一下,如何快速添加对应类所需要包含的头文件,可以提高开发效率,供参考。 二,操作步骤 以QTime类为例: 选中…...
基于服务器部署的综合视频安防系统的智慧快消开源了。
智慧快消视频监控平台是一款功能强大且简单易用的实时算法视频监控系统。它的愿景是最底层打通各大芯片厂商相互间的壁垒,省去繁琐重复的适配流程,实现芯片、算法、应用的全流程组合,从而大大减少企业级应用约95%的开发成本。国产化人工智能“…...
浅谈棋牌游戏开发流程七:反外挂与安全体系——守护游戏公平与玩家体验
一、前言:为什么反外挂与安全这么重要? 对于任何一款线上棋牌游戏而言,公平性和玩家安全都是最重要的核心要素之一。如果游戏环境充斥着各式各样的外挂、作弊方式,不仅会毁坏玩家体验,更会导致游戏生态崩塌、口碑下滑…...
Laravel操作ElasticSearch
在Laravel项目中操作ElasticSearch可以通过以下步骤来实现,通常会借助相应的ElasticSearch客户端扩展包。 ### 安装ElasticSearch客户端包 在Laravel项目中,常用的是 elasticsearch/elasticsearch 这个PHP客户端库来与ElasticSearch进行交互,…...
缓存-文章目录
关于缓存系列文章: 缓存学习总结1(缓存分类) 缓存学习总结2(服务器本地缓存) 缓存学习总结3(服务器内存缓存)推荐使用 缓存学习总结4(分布式缓存) 关于redis系列文章…...
安装教程:慧集通集成平台(DataLinkX)智能体客户端安装操作(Linux/windows/mac)
1.下载客户端 使用提供的账号登录集成平台后台(https://www.datalinkx.cn/),点击左侧菜单栏【智能体】→【智能体】进入到智能体列表界面,在该界面我们找到功能栏中的下载按钮点击则会弹出下载界面,在该界面我们可以选择不同的系统操作系统来下载对应版…...
解决vmware虚拟机和宿主机之间不能复制粘贴
在虚拟机内执行一下命令 /usr/bin/vmware-user 更多解决方案 https://www.cnblogs.com/wutou/p/17629408.html...
由源程序到运行
由源程序到运行 第一步:编写源程序 assume cs:codesg codesg segmentmov ax,0123Hmov bx,0456Hadd ax,bxadd ax,axmov ax,4c00hint 21h codesg ends end第二步:进行编译 进入到编译目录 编译 .asm文件生成目标文件(.obj) m…...
Java-JDBC的使用
目录 一、JDBC(java数据库连接):java database connector 二、使用JDBC的步骤 三、加条件查询 四、预处理(防止SQL注入) 五、Statement和PreparedStatement的优略 六、将数据中的数据查询出来后需要保存在一个集合中,方便前端…...
如何优化亚马逊广告以提高ROI?
在竞争激烈的亚马逊市场中,优化广告以提高投资回报率(ROI)是卖家的关键任务。以下是一些实用的策略: 一、精准的关键词研究与选择 深入了解产品特性和目标受众 详细分析产品的功能、用途、优势和适用人群。例如,如果你…...
身是菩提树,心如明镜台;时时勤拂拭,莫使惹尘埃。
神秀: 身是菩提树,心如明镜台;时时勤拂拭,莫使惹尘埃。 第一个毛病1: 在神秀看来,修行就是要保持我们本来干净的心, 跟外部世界的灰尘之间的隔绝状态,始终保持这种隔绝, 尘世是什么? 尘就是烦恼,人世间无处不是烦恼&a…...
如何修复富士相机卡错误并恢复卡数据
富士相机以其卓越的图像质量而闻名,但不幸的是,其 SD 卡错误可能会意外发生,导致数据丢失和摄影会话中断。 在本指南中,我们将引导您了解常见的富士相机 SD 卡错误、如何修复这些错误,以及如何有效地从损坏的卡中恢复…...
呼叫中心中间件实现IVR进入排队,判断排队超时播放提示音
文章目录 [TOC](文章目录) 前言需求排队结束原因 联系我们实现步骤1. 调用http接口返回动作2. 启用拨号方案 前言 需求 呼叫中心需要实现调用IVR接口进入排队,如果是因为等待超时导致退出排队的,那就播放一段提示音再挂断通话;其他的情况就…...
数据分析思维(八):分析方法——RFM分析方法
数据分析并非只是简单的数据分析工具三板斧——Excel、SQL、Python,更重要的是数据分析思维。没有数据分析思维和业务知识,就算拿到一堆数据,也不知道如何下手。 推荐书本《数据分析思维——分析方法和业务知识》,本文内容就是提取…...
SpringBoot3动态切换数据源
背景 随着公司业务战略的发展,相关的软件服务也逐步的向多元化转变,之前是单纯的拿项目,赚人工钱,现在开始向产品化\服务化转变。最近雷袭又接到一项新的挑战:了解SAAS模型,考虑怎么将公司的产品转换成多租…...
Java虚拟机面试题:内存管理(上)
🧑 博主简介:CSDN博客专家,历代文学网(PC端可以访问:https://literature.sinhy.com/#/?__c1000,移动端可微信小程序搜索“历代文学”)总架构师,15年工作经验,精通Java编…...
WPF通过反射机制动态加载控件
Activator.CreateInstance 是 .NET 提供的一个静态方法,它属于 System 命名空间。此方法通过反射机制根据提供的类型信息。 写一个小demo演示一下 要求:在用户反馈界面点击建议或者评分按钮 弹出相应界面 编写MainWindow.xmal 主窗体 <Window x:C…...
前端学习-操作元素属性(二十三)
前言 假期快乐,大家加油 操作元素属性 操作元素常用属性 还可以通过 JS 设置/修改标签元素属性,比如通过 src更换 图片最常见的属性 比如:href、title、src等语法:对象.属性 值 const pic document.querySelector(img);pic.src ./images/b0.jpgp…...
Javascript 编写的一个红、黄、绿灯交替变亮
为了创建一个简单但功能完整的交通灯程序,我们将使用 HTML、CSS 和 JavaScript 来实现红、黄、绿三种颜色按照规定的顺序循环显示。这个例子将确保灯光按照红 -> 绿 -> 黄的顺序循环,并且可以调整每个灯光的持续时间以模拟真实的交通灯行为。 效果…...
基于64QAM的载波同步和定时同步性能仿真,包括Costas环和gardner环
目录 1.算法仿真效果 2.算法涉及理论知识概要 3.MATLAB核心程序 4.完整算法代码文件获得 1.算法仿真效果 matlab2022a仿真结果如下(完整代码运行后无水印): 仿真操作步骤可参考程序配套的操作视频。 2.算法涉及理论知识概要 载波同步是…...
小于n的最大数 - 贪心算法 - C++
字节经典面试题 给定一个整数n,并从1~9中给定若干个可以使用的数字,根据上述两个条件,得到每一位都为给定可使用数字的、最大的小于整数n的数,例如,给定可以使用的数字为 {2,3,8} 三个数:给定 n3589&#x…...
leetcode(hot100)4
解题思路:双指针思想 利用两个for循环,第一个for循环把所有非0的全部移到前面,第二个for循环将指针放在非0的末尾全部加上0。 还有一种解法就是利用while循环双指针条件,当不为0就两个指针一起移动 ,为0就只移动右指针…...
【Pandas】pandas Series xs
Pandas2.2 Series Indexing, iteration 方法描述Series.get()用于根据键(索引标签)从 Series 中获取值Series.at用于快速访问标量值(单个元素)的访问器Series.iat用于快速访问标量值(单个元素)的访问器Se…...
【linux内核分析-存储】EXT4源码分析之“文件删除”原理【七万字超长合并版】(源码+关键细节分析)
EXT4源码分析之“文件删除”原理【七万字超长合并版】(源码关键细节分析),详细的跟踪了ext4文件删除的核心调用链,分析关键函数的细节,解答了开篇中提出的三个核心疑问。 文章目录 提示前言全文重点索引1.源码解析1.1 …...
一个在ios当中采用ObjectC和opencv来显示图片的实例
前言 在ios中采用ObjectC编程利用opencv来显示一张图片,并简单绘图。听上去似乎不难,但是实际操作下来,却不是非常的容易的。本文较为详细的描述了这个过程,供后续参考。 一、创建ios工程 1.1、选择ios工程类型 1.2、选择接口模…...
使用Python实现基于强化学习的游戏AI:打造智能化游戏体验
友友们好! 我的新专栏《Python进阶》正式启动啦!这是一个专为那些渴望提升Python技能的朋友们量身打造的专栏,无论你是已经有一定基础的开发者,还是希望深入挖掘Python潜力的爱好者,这里都将是你不可错过的宝藏。 在这个专栏中,你将会找到: ● 深入解析:每一篇文章都将…...
STM32G0B1 can Error_Handler 解决方法
问题现象 MCU上电,发送0x13帧数据固定进入 Error_Handler 硬件介绍 MCU :STM32G0B1 can:NSI1042 tx 接TX RX 接RX 折腾了一下午,无解,问题依旧; 对比测试 STM32G431 手头有块G431 官方评估版CAN 模块; 同样的…...
洛谷 P2511 [HAOI2008] 木棍分割
第一问很简单,第二问 d p dp dp。 (真是哪都能混个 d p dp dp) 参考题解 #include <bits/stdc.h>using namespace std;int read() {int x 0, f 1; char c getchar();while (c < 0 || c > 9) {if (c -) f -1; c getcha…...
二极管钳位电路分享
二极管钳位(I/O的过压/浪涌保护等) 如果我们的电路环境接收外部输入信号容易受到噪声影响,那我们必须采取过压和浪涌保护措施,其中一个方式就是二极管钳位保护。 像上图,从INPUT输入的电压被钳位在-Vf与VCCVf之间&…...
guestfish/libguestfs镜像管理工具简介
文章目录 简介guestfishlibguestfs项目 例子原理代码libguestfs架构参考 简介 guestfish Guestfish 是libguestfs项目中的一个工具软件,提供修改虚机镜像内部配置的功能。它不需要把虚机镜像挂接到本地,而是为你提供一个shell接口,你可以查…...
AutoSar架构学习笔记
1.AUTOSAR(Automotive Open System Architecture,汽车开放系统架构)是一个针对汽车行业的软件架构标准,旨在提升汽车电子系统的模块化、可扩展性、可重用性和互操作性。AUTOSAR的目标是为汽车电子控制单元(ECU…...
Scade pragma: separate_io
概述 在 Scade 语言中,支持对用户自定义算子使用 separate_io pragma 进行修饰。其形式如: function #pragma kcg separate_io #end N(x: int8) returns (y,z: int8) let y x;z x; tel在上例中,算子N 就被 pragma #pragma kcg separate_i…...
三天速成微服务
微服务技术栈 总结 微服务技术对比 技术栈 SpringCloud SpringCloud是目前国内使用最广泛的微服务框架。官网地址:https://spring.io/projects/spring-cloud Springboot和SpringCould兼容性 代码目录结构如下 用于远程调用Bean 代码 package cn.itcast.order.config;//import …...
【MySQL】九、表的内外连接
文章目录 前言Ⅰ. 内连接案例:显示SMITH的名字和部门名称 Ⅱ. 外连接1、左外连接案例:查询所有学生的成绩,如果这个学生没有成绩,也要将学生的个人信息显示出来 2、右外连接案例:对stu表和exam表联合查询,把…...
GitLab 创建项目、删除项目
1、创建项目 点击左上角图标,回到首页 点击 Create a project 点击 Create blank project 输入项目名称,点击Create Project 创建成功 2、删除项目 进入项目列表 点击对应项目,进入项目 进入Settings页面 拖到页面底部,展开Adva…...
python学opencv|读取图像(二十六)使用cv2.putText()绘制文字进阶-在图像上写文字
【1】引言 前序已经学会了在画布上绘制文字的大部分技巧,相关文章链接为: python学opencv|读取图像(二十三)使用cv2.putText()绘制文字-CSDN博客 python学opencv|读取图像(二十四)使用cv2.putText()绘制…...
Apache HTTPD 多后缀解析漏洞
目录 漏洞简介 漏洞环境 漏洞复现 漏洞防御 漏洞简介 Apache HTTPD 支持一个文件拥有多个后缀,并为不同后缀执行不同的指令。比如,如下配置文件: AddType text/html .html AddLanguage zh-CN .cn 以上就是Apache多后缀的特性。如果运维…...
(二)当人工智能是一个函数,函数形式怎么选择?ChatGPT的函数又是什么?
在上一篇文章中,我们通过二次函数的例子,讲解了如何训练人工智能。今天,让我们进一步探讨:面对不同的实际问题,应该如何选择合适的函数形式? 一、广告推荐系统中的函数选择 1. 业务目标 想象一下&#x…...
JavaScript学习-入门篇
JavaScript的运行环境 开发环境就是开发JavaScript代码所需的环境,一般建议新手刚刚开始使用一些记事本工具(如sublime、editPlus、VScode),锻炼代码的手感。等学习到一定阶段,就可以使用集成开发工具IDE࿰…...
今日头条ip属地根据什么显示?不准确怎么办
在今日头条这样的社交媒体平台上,用户的IP属地信息对于维护网络环境的健康与秩序至关重要。然而,不少用户发现自己的IP属地显示与实际位置不符,这引发了广泛的关注和讨论。本文将深入探讨今日头条IP属地的显示依据,并提供解决IP属…...
python之移动端测试---appium
Appium Appium介绍环境准备新版本appium的用法介绍元素定位函数被封装,统一使用By.xxx(定位方式):通过文本定位的写法 一个简单的请求示例APP操作api基础apk安装卸载发送,拉取文件uiautomatorviewer工具使用获取页面元素及属性模拟事件操作模…...
【网络安全实验室】基础关实战详情
须知少时凌云志,曾许人间第一流 1.key在哪里 url:http://rdyx0/base1_4a4d993ed7bd7d467b27af52d2aaa800/index.php 查看网页源代码的方式有4种,分别是:1、鼠标右击会看到”查看源代码“,这个网页的源代码就出现在你眼前了&…...