Java Web(七)__Tomcat(二)
Tomcat工作模式
Tomcat作为Servlet容器,有以下三种工作模式。
1)独立的Servlet容器,由Java虚拟机进程来运行
Tomcat作为独立的Web服务器来单独运行,Servlet容器组件作为Web服务器中的一部分而存在。这是Tomcat的默认工作模式。
在这种模式下,Tomcat是一个独立运行的Java程序。和运行其他Java程序一样,运行Tomcat需要启动一个Java虚拟机(JVM,Java Virtual Machine)进程,由该进程来运行Tomcat,如下图:

2)其他Web服务器进程内的Servlet容器
Tomcat分为Web服务器插件和Servlet容器组件两部分。
Web服务器插件在其他Web服务器进程的内部地址空间启动一个JVM(Java Virtual Machine),使Servlet容器组件在此虚拟机中运行。若客户机调用Servlet的请求,web服务器插件将取得对此请求的控制并将它传递(使用JNI)给Servlet容器组件。
注:JNI是Java Native Interface的简写,它是Java本地调用接口。通过这个接口,Java程序可以和其他语言编写的本地程序进行通信。

进程内的Servlet容器对于单进程、多线程的Web服务器非常合适,可以提供较高的运行速度,但缺乏伸缩性。
3)其他Web服务器进程外的Servlet容器
Tomcat分为Web服务器插件和Servlet容器组件两部分。
Web服务器插件在其他Web服务器的外部地址空间启动一个Java虚拟机进程,Servlet容器组件在此Java虚拟机中运行。如有客户端发出调用Servlet的请求,Web服务器插件获得对此请求的控制并将它转发(采用IPC通信机制)给Servlet容器。
注:IPC(Inter-Process Communication,进程间通信)是两个进程之间进行通信的一种机制。

进程外Servlet容器对客户请求的响应速度不如进程内Servlet容器,但进程外容器具有更好的伸缩性和稳定性。
从Tomcat的三种工作模式可以看出,当Tomcat作为独立的Servlet容器来运行时,此时Tomcat是能运行Java Servlet的独立Web服务器。
此外,Tomcat还可作为其他Web服务器进程内或者进程外的Servlet容器,从而与其他Web服务器集成(如Apache和IIS服务器等)。
集成的意义在于:对于不支持运行Java Servlet的其他Web服务器,可通过集成Tomcat来提供运行Servlet的功能。
Tomcat整体架构

Connector(连接器)

1)EndPoint
-
EndPoint : Coyote 通信端点,即通信监听的接口,是具体Socket接收和发送处理器,是对传输层的抽象,因此EndPoint用来实现TCP/IP协议的。
-
Tomcat 并没有EndPoint 接口,而是提供了一个抽象类AbstractEndpoint , 里面定义了两个内部类:Acceptor和SocketProcessor。
-
Acceptor用于监听Socket连接请求。
-
SocketProcessor用于处理接收到的Socket请求,它实现Runnable接口,在Run方法里调用协议处理组件Processor进行处理。为了提高处理能力,SocketProcessor被提交到线程池来执行。而这个线程池叫作执行器(Executor).
-
2) Processor
Processor : Coyote 协议处理接口 ,如果说EndPoint是用来实现TCP/IP协议的,那么Processor用来实现HTTP协议,Processor接收来自EndPoint的Socket,读取字节流解析成Tomcat Request和Response对象,并通过Adapter将其提交到容器处理,Processor是对应用层协议的抽象。
3)ProtocolHandler
ProtocolHandler: Coyote 协议接口, 通过Endpoint 和 Processor , 实现针对具体协议的处理能力。
- Tomcat 按照协议和I/O 提供了6个实现类 : AjpNioProtocol , AjpAprProtocol, AjpNio2Protocol , Http11NioProtocol ,Http11Nio2Protocol ,Http11AprProtocol。
- 我们在配置tomcat/conf/server.xml 时 , 至少要指定具体的ProtocolHandler ; 当然也可以指定协议名称 , 如 : HTTP/1.1 ,如果安装APR,那么将使用Http11AprProtocol , 否则使用 Http11NioProtocol 。
4)Adapter
由于协议不同,客户端发过来的请求信息也不尽相同,Tomcat定义了自己的Request类来“存放”这些请求信息。
- ProtocolHandler接口负责解析请求并生成Tomcat Request类。但是这个Request对象不是标准的ServletRequest,也就意味着,不能用Tomcat Request作为参数来调用容器。
- Tomcat设计者的解决方案是引入CoyoteAdapter,这是适配器模式的经典运用,连接器调用CoyoteAdapter的Sevice方法,传入的是Tomcat Request对象,CoyoteAdapter负责将Tomcat Request转成ServletRequest,再调用容器的Service方法。
Container(容器)
架构

4个子容器的作用分别是:
【1】Engine:表示整个Catalina的Servlet引擎,用来管理多个虚拟站点,一个Service最多只能有一个Engine,但是一个引擎可包含多个Host。
【2】Host:代表一个站点,也可以叫虚拟主机,可以给Tomcat配置多个虚拟主机地址,而一个虚拟主机下可包含多个Context;【整个webapps】
【3】Context:代表一个应用程序,对应着平时开发的一套程序,或者一个 WEB-INF目录以及下面的 web.xml文件;
【4】Wrapper:每一 Wrapper封装着一个 Servlet,Wrapper 作为容器中的最底层,不能包含子容器。
处理请求
使用 Pipeline-Valve 管道来处理的!(Valve是阀门之意)Pipeline-Valve 是责任链模式,责任链模式是指在一个请求处理的过程中有很多处理者依次对请求进行处理,每个处理者负责做自己相应的处理,处理完之后将处理后的请求返回,再让下一个处理着继续处理。

【1】Connector 在接收到请求后会首先调用最顶层容器的Pipeline来处理,这里的最顶层容器的 Pipeline就是EnginePipeline(Engine的管道);
【2】在 Engine的管道中依次会执行 EngineValve1、EngineValve2 等等,最后会执行 StandardEngineValve,在StandardEngineValve 中会调用 Host管道,然后再依次执行 Host 的 HostValve1、HostValve2 等,最后在执行StandardHostValve,然后再依次调用 Context的管道和 Wrapper的管道,最后执行到 StandardWrapperValve。
【3】当执行到 StandardWrapperValve 的时候,会在 StandardWrapperValve中创建 FilterChain,并调用其 doFilter方法来处理请求,这个 FilterChain包含着我们配置的与请求相匹配的 Filter和Servlet,其 doFilter方法会依次调用所有的 Filter的 doFilter方法和 Servlet的 service方法,这样请求就得到了处理!
【4】当所有的 Pipeline-Valve都执行完之后,并且处理完了具体的请求,这个时候就可以将返回的结果交给 Connector了,Connector 在通过 Socket的方式将结果返回给客户端。
service.xml文件
server.xml 是 Tomcat 中最重要的配置文件,server.xml 的每个元素都对应了 Tomcat中的一个组件;通过对xml文件中元素的配置,可以实现对 Tomcat 中各个组件的控制。
<?xml version="1.0" encoding="UTF-8"?>
<Server port="8005" shutdown="SHUTDOWN"><Listener className="org.apache.catalina.startup.VersionLoggerListener"/><Listener SSLEngine="on" className="org.apache.catalina.core.AprLifecycleListener"/><Listener className="org.apache.catalina.core.JasperListener"/><Listener className="org.apache.catalina.core.JreMemoryLeakPreventionListener"/><Listener className="org.apache.catalina.mbeans.GlobalResourcesLifecycleListener"/><Listener className="org.apache.catalina.core.ThreadLocalLeakPreventionListener"/><GlobalNamingResources><Resource auth="Container" description="User database that can be updated and saved" factory="org.apache.catalina.users.MemoryUserDatabaseFactory" name="UserDatabase" pathname="conf/tomcat-users.xml" type="org.apache.catalina.UserDatabase"/></GlobalNamingResources><Service name="Catalina"><Connector port="8080" protocol="HTTP/1.1" connectionTimeOut="20000" redirectPort="8443"/><Connector port="8009" protocol="AJP/1.3" redirectPort="8443"/><Engine defaultHost="localhost" name="Catalina"><Realm className="org.apache.catalina.realm.LockOutRealm"><Realm className="org.apache.catalina.realm.UserDatabaseRealm" resourceName="UserDatabase"/></Realm><Host appBase="webapps" autoDeploy="true" name="localhost" unpackWARs="true"><Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs" pattern="%h %l %u %t "%r" %s %b" prefix="localhost_access_log." suffix=".txt"/><Context docBase="cas-server-webapp" path="/cas" reloadable="true" source="org.eclipse.jst.j2ee.server:cas-server-webapp"/><Context docBase="portal" path="/portal" reloadable="true" source="org.eclipse.jst.jee.server:portal"/></Host></Engine></Service>
</Server>
整体架构简洁版
<Server><Service><Connector /><Connector /><Engine><Host><Value /><Context /><!-- 现在常常使用自动部署,不推荐配置Context元素--></Host></Engine></Service>
</Server>
核心组件
【1】Server
Server元素在最顶层,代表整个 Tomcat容器,因此他必须是 server.xml中唯一一个最外层的元素。一个 Server元素可以有一个或多个 Service元素。
Server 的主要任务,就是提供一个接口让客户端能够访问到这个 Service集合,同时维护它所包含的所有的 Service的生命周期,包含如何初始化,如何结束服务,如何找到客户端要访问的 Service。
<Server port="8005" shutdown="SHUTDOWN">
</Server>
说明:
- shutdown :发往此Server用于实现关闭tomcat实例的命令字符串,默认为SHUTDOWN;
- port 属性表示 Server接收 shutdown指令的端口号,设置为-1可以禁掉该端口。默认仅允许通过本机访问,默认为8005;
- address:服务器等待关机命令的TCP / IP地址。如果没有指定地址,则使用localhost。
- className: 用于实现此Server容器的完全限定类的名称,默认为org.apache.catalina.core.StandardServer;
【2】Service
在 Connector 和 Engine外面包一层,把它们组合在一起,对外提供服务。一个Service可以包含多个Connector,但是只能包含一个Engine;其中 Connector 的作用是从客户端接收请求,Engine 的作用是处理接收进来的请求。
<Server port="8005" shutdown="SHUTDOWN"><Service name="Catalina"></Service>
</Server>
属性说明:
- className: 用于实现service的类名,一般都是org.apache.catalina.core.StandardService。
- name:此服务的名称,默认为Catalina;
如上图,Server 中包含一个名称为 “Catalina” 的Service,此名字也会在产生相关的日志信息时记录在日志文件当中。
实际上,Tomcat 可以提供多个 Service,不同的 Service监听不同的端口。
【3】Connector
接收连接请求,创建 Request 和 Response对象用于和请求端交换数据;然后分配线程让 Engine来处理这个请求,并把产生的 Request 和 Response对象传给 Engine。通过配置 Connector,可以控制请求 Service的协议及端口号。【连接器类型通常包括:1) HTTP连接器;2) SSL连接器;3)AJP 1.3连接器;4) proxy连接器】
<Server port="8005" shutdown="SHUTDOWN"><Service name="Catalina"><Connector port="8080" protocol="HTTP/1.1" connectionTimeout="20000" redirectPort="8443" maxParameterCount="1000"/><Connector port="8009" protocol="AJP/1.3" redirectPort="8443" /></Service>
</Server>
常用属性的说明:
- 1) address:指定连接器监听的地址,默认为所有地址,即0.0.0.0;
- 2) maxThreads:支持的最大并发连接数,默认为200;
- 3) port:监听的端口,默认为8080;
- 4) protocol:连接器使用的协议,默认为HTTP/1.1,定义AJP协议时通常为AJP/1.3;
- 5) redirectPort:如果某连接器支持的协议是HTTP,当接收客户端发来的HTTPS请求时,则转发至此属性定义的端口;
- 6) connectionTimeout:等待客户端发送请求的超时时间,单位为毫秒,默认为60000,即1分钟;
- 7) enableLookups:是否通过request.getRemoteHost()进行DNS查询以获取客户端的主机名;默认为true;
- 8) acceptCount:设置等待队列的最大长度;通常在tomcat所有处理线程均处于繁忙状态时,新发来的请求将被放置于等待队列中;
配置说明:
- 通过配置第一个 Connector,客户端可以通过 8080端口号协议访问 Tomcat。其中,protocol 属性规定了请求的协议,port 规定了请求的端口号,redirectPort 表示当强制要求 https而请求是 http时,重定向至端口号为 8443的Connector,connectionTimeout表示连接的超时时间。
- 在这个例子中,Tomcat 监听 Http请求,使用的是 8080端口,而不是正式的 80端口;实际上,在正式的生产环境中,Tomcat也常常监听8080端口。而不是80端口。这是因为在生产环境中,很少讲 Tomcat直接对外开放接收请求,而是在 Tomcat和客户端之间加一层代理服务器(如Nginx),用于请求的转发、负载均衡、处理静态文件等;通过代理服务器访问 Tomcat时,是在局域网中,因为一般仍使用8080端口。
- 第二个配置 Connector,客户端可以通过 8009端口使用 AJP协议访问 Tomcat。AJP协议负责和其他的Http服务器(如Apache)建立连接;在把 Tomcat与其他服务器集成时,就需要用到这个连接器,之所以使用 Tomcat和其他服务器集成,是因为 Tomcat可以用作 Servlet/JSP容器,但是对静态资源处理速度较慢,不如 Apache和 IIS等 HTTP服务器;因此常常将 Tomcat和 Apache等集成,前者做 Servlet容器,后者处理静态资源,而 AJP协议便负责 Tomcat与 Apache的连接。Tomcat 和 Apache等集成的原理如下图:

【4】Engine
Engine 组件在 Service 组件有且只有一个;
- Engine是Servlet处理器的一个实例,即servlet引擎,默认为定义在server.xml中的Catalina。
- Engine组件从一个或多个Connector 中接收并处理,并将完成的响应返回给 Connector,最终传递给客户端。
- Engine、Host 和 Context都是容器,但是它们不是平行关系,而是父子关系:Engine 包含 Host,Host 包含 Context。
<Server port="8005" shutdown="SHUTDOWN"><Service name="Catalina"><Connector port="8080" protocol="HTTP/1.1" connectionTimeout="20000" redirectPort="8443" /><Connector port="8009" protocol="AJP/1.3" redirectPort="8443" /><Engine name="Catalina" defaultHost="localhost"></Engine></Service>
</Server>
参数说明:
- name:Engine组件的名称,用于日志和错误信息记录时区别不同的引擎;
- defalutHost :指定了默认的 host名称【接收所有发往非明确定义虚拟主机的请求的host组件,即当发往本机的请求指定的 host名称不存在时,一律使用 defaultHost指定的 host进行处理;】
- 因此 defaulthost的值,必须与 Engine中的一个Host组件的 name属性值匹配。
Engine 和 Host的关系:
- Host 是 Engine的子容器。
- Engine 组件中可以内嵌1个或者多个 Host组件;
- 每个 Host组件代表 Engine中的一个虚拟主机。
- Host组件至少有一个,且其中一个的 name必须与 Engine组件中的 defaultHost属性相匹配。
<Server port="8005" shutdown="SHUTDOWN"><Service name="Catalina"><Connector port="8080" protocol="HTTP/1.1" connectionTimeout="20000" redirectPort="8443" /><Connector port="8009" protocol="AJP/1.3" redirectPort="8443" /><Engine name="Catalina" defaultHost="localhost"><Host name="localhost" appBase="webapps" unpackWARs="true" autoDeploy="true"></Host></Engine></Service>
</Server>
【5】Host
位于Engine容器中用于接收请求并进行相应处理的主机或虚拟主机。作用是运行多个 Web应用(一个 Context 代表一个 Web应用),并负责安装、展开、启动、结束每个 Web应用。
- Host 组件代表的虚拟主机,对应服务器中一个网络名实体(如"www.test.com"或IP地址"116.25.25.25");为了使用户可以通过网络名连接Tomcat服务器,这个名字应该在DNS服务器上注册。
- 客户端通常使用主机名来标识它们希望连接的服务器,该主机名也会包含在 HTTP请求头中,Tomcat 从 HTTP头中提取出主机名,寻找名字匹配的主机。
- 如果没有匹配,请求会发送至默认的主机。因此默认主机不需要在 DNS服务器中注册网络名,因为任何与所有 Host名称不匹配的请求,都会路由至默认主机。
参数说明:
- 1) appBase:此Host的webapps目录,即存放非归档的web应用程序的目录或归档后的WAR文件的目录路径;可以使用基于$CATALINA_HOME的相对路径;
- 2) autoDeploy:在Tomcat处于运行状态时放置于appBase目录中的应用程序文件是否自动进行deploy;默认为true;
- 3) unpackWars:在启用此webapps时是否对WAR格式的归档文件先进行展开;默认为 true,通过解压后的文件结构运行该 Web应用;如果是false,直接使用 WAR文件运行 Web应用。
- 4)name 属性指定虚拟主机的主机名,一个 Engine有且只有一个 Host组件的 name属性和 Engine组件的 defaultHost属性相匹配;一般情况下,主机名需要是在 DNS服务器中注册网络名,但是 Engine指定的 defaultHost不需要。
<Context docBase="D:\Program Files\app1.war" reloadable="true"></Context>
【6】Context(静态部署)
Context元素代表在虚拟主机上运行的一个Web应用。
- 每个 Web应用基于 WAR文件,或 WAR文件解压后对应的目录(这里称为应用目录)。
- Context 是 Host 的子容器,每个 Host 都可以定义任意多的 Context元素。
属性说明:
- docBase :指定Web应用程序的存放位置;也可以使用相对路径,起始路径为此Context所属Host中appBase定义的路径;切记,docBase的路径名不能与相应的Host中appBase中定义的路径名有包含关系,比如,如果appBase为deploy,而docBase绝不能为deploy-bbs类的名字;
- path 指定了访问该Web应用上下文路径,当请求到来时,Tomcat 根据 Web应用的 path属性与 URL匹配程度来选择 Web应用处理相应请求。
- reloadable属性指示tomcat是否在运行时监控在 WEB-INF/classes和WEB-INF/lib目录下class文件的改动。默认值为false;当值为 true,在 class文件改动时会重新 web应用的重新加载。在开发环境下,reloadable 设置为 ture便于调试;
- 若是自动部署(即 autoDeploy=“true”),那么 server.xml配置文件中没有 Context元素的配置。这是因为 Tomcat开启了自动部署,Web应用没有在 server.xml中配置静态部署,而是由 Tomcat通过特定的规则自动部署。
注:目前往往server.xml配置文件中看不到Context元素的出现,因为Tomcat开启了
自动部署,Web应用没有在server.xml中配置静态部署,而是由Tomcat通过特定的规则自动部署。静态部署与自动部署是可以共存的。在实际应用中,并不推荐使用静态部署,因为server.xml 是不可动态重加载的资源,服务器一旦启动了以后,要修改这个文件,就得重启服务器才能重新加载。而自动部署可以在Tomcat运行时通过定期的扫描来实现,不需要重启服务器。
注意的是:在自动部署场景下(配置文件位于 xmlBase中)
- docBase 不在 appBase目录中,才需要指定;如果 docBase指定的 war包或应用目录就在 appBase中,则不需要指定。因为 Tomcat会自动扫描 appBase中的 war包和应用目录,制定了反而造成问题。
- 不能指定path属性,path属性由配置的文件的文件名,WAR文件的文件名或应用目录的名称自动推导出来。
appBase 和 docBase的区别
【1】appBase:这个目录下面的子目录将自动被部署为应用,且 war文件将被自动解压缩并部署为应用,默认为 Tomcat根目录下的 webapps文件夹。
【2】docBase:指定需要关联的项目自动解压并部署到 appBase目录下。项目的名称由 path属性决定。
- docBase 所在的文件或者 war包必须存在,否则项目启动找不到对应的目录。此时文件解压到 appBase目录下,根据 path属性,决定解压后的文件名。
- 若采用了 配置,那么 appBase目录下的应用目录将会再次部署。此时项目是部署两遍。解决办法,设置 autoDeploy=“false”。
【7】Valve组件
Valve类似于过滤器,它可以工作于Engine和Host/Context之间、Host和Context之间以及Context和Web应用程序的某资源之间。
不同的Valve有不同的特性,AccessLogValve记录的日志就是访问日志,每天的请求会写到一个日志文件里。AccessLogValve可以与Engine、Host或Context关联;
注:一个容器内可以建立多个Valve,而且Valve定义的次序也决定了它们生效的次序。
相关属性定义有:
-
className:规定了Valve的类型,是最重要的属性;本例中,通过该属性规定了这是一个AccessLogValve。
-
directory:指定日志存储的位置,本例中,日志存储在$TOMCAT_HOME/logs目录下。
-
prefix:指定了日志文件的前缀。
-
suffix:指定了日志文件的后缀。通过directory、prefix和suffix的配置,在$TOMCAT_HOME/logs目录下,可以看到如下所示的日志文件。
-
pattern:指定记录日志的格式。
pattern中一些值:
- %h:远程主机名或IP地址;如果有nginx等反向代理服务器进行请求分发,该主机名/IP地址代表的是nginx,否则代表的是客户端。后面远程的含义与之类似,不再解释。
- %l:远程逻辑用户名,一律是”-”,可以忽略。
- %u:授权的远程用户名,如果没有,则是”-”。
- %t:访问的时间。
- %r:请求的第一行,即请求方法(get/post等)、uri、及协议。
- %s:响应状态,200,404等等。
- %b:响应的数据量,不包括请求头,如果为0,则是””-。
- %D:请求处理的时间(单位是毫秒)
【8】Listener
Listener(即监听器)定义的组件,可以在特定事件发生时执行特定的操作;
- 被监听的事件通常是Tomcat的启动和停止。
- 监听器需要配置的最重要的属性是className,该属性规定了监听器的具体实现类,该类必须实现了org.apache.catalina.LifecycleListener接口。
<Listener className="org.apache.catalina.startup.VersionLoggerListener" /><!-- Security listener. Documentation at /docs/config/listeners.html<Listener className="org.apache.catalina.security.SecurityListener" />--><!-- APR library loader. Documentation at /docs/apr.html --><Listener className="org.apache.catalina.core.AprLifecycleListener" SSLEngine="on" /><!-- Prevent memory leaks due to use of particular java/javax APIs--><Listener className="org.apache.catalina.core.JreMemoryLeakPreventionListener" /><Listener className="org.apache.catalina.mbeans.GlobalResourcesLifecycleListener" /><Listener className="org.apache.catalina.core.ThreadLocalLeakPreventionListener" />
例如:
-
VersionLoggerListener:当Tomcat启动时,该监听器记录Tomcat、Java和操作系统的信息。该监听器必须是配置的第一个监听器。
-
AprLifecycleListener:Tomcat启动时,检查APR库,如果存在则加载。APR,即Apache Portable Runtime,是Apache可移植运行库,可以实现高可扩展性、高性能,以及与本地服务器技术更好的集成。
-
JasperListener:在Web应用启动之前初始化Jasper,Jasper是JSP引擎,把JVM不认识的JSP文件解析成java文件,然后编译成class文件供JVM使用。
-
JreMemoryLeakPreventionListener:与类加载器导致的内存泄露有关。
-
GlobalResourcesLifecycleListener:通过该监听器,初始化< GlobalNamingResources>标签中定义的全局JNDI资源;如果没有该监听器,任何全局资源都不能使用。
-
ThreadLocalLeakPreventionListener:当Web应用因thread-local导致的内存泄露而要停止时,该监听器会触发线程池中线程的更新。当线程执行完任务被收回线程池时,活跃线程会一个一个的更新。只有当Web应用(即Context元素)的renewThreadsWhenStoppingContext属性设置为true时,该监听器才有效。
其他
Tomcat 还有其它重要的组件,如安全组件 Security、Logger、Session、Mbeans、Naming 等其它组件。这些组件共同为 Connector 和 Container 提供必要的服务。
Tomcat调优
1.Tomcat 的自身调优:
- 采用动静分离节约 Tomcat 的性能;【采用:Nginx+Tomcat 实现动静分离】
- 禁用 AJP 连接器【使用 Nginx+Tomcat的架构,所以用不着 AJP 协议,所以把AJP连接器禁用。】
- 调整 Tomcat 的线程池
- 调整 Tomcat 的连接器
- 修改 Tomcat 的运行模式
- 关闭 Manager管理页面;(默认已经关闭)
- 关闭 host-mangent管理页面;(默认已经关闭)
- 对 Tomcat 日志进行分割;
- 定义 Tomcat 404 错误返回的页面;
2.JVM的调优:
- 调优Jvm内存
参考文档:tomcat优化(五)tomcat调优-腾讯云开发者社区-腾讯云
相关文章:
Java Web(七)__Tomcat(二)
Tomcat工作模式 Tomcat作为Servlet容器,有以下三种工作模式。 1)独立的Servlet容器,由Java虚拟机进程来运行 Tomcat作为独立的Web服务器来单独运行,Servlet容器组件作为Web服务器中的一部分而存在。这是Tomcat的默认工作模式。…...
【项目实战】帮美女老师做一个点名小程序(Python tkinter)
前言 博主有一个非常漂亮的老师朋友😍。最近,她急需一个能够实现随机点名的小程序,而博主正好擅长这方面的技术🤏。所以,今天博主决定为她制作一个专门用于点名的小程序💪。 博主在美女老师面前吹完牛皮之…...
Elasticsearch 去重后求和
标题的要求可以用如下 SQL 表示 select sum(column2) from (select distinct(column1),column2 from table)t 要如何用 DSL 实现呢,先准备下索引和数据 PUT test_index {"mappings": {"properties": {"column1": {"type"…...
考研数学——高数:函数与极限(3)
函数的连续性与间断点 函数的连续性 左连续 右连续 区间上的连续性 在xo处连续 函数的间断点 第一类间断点(左右极限都存在) 可去间断点: f(xo-0)= f(xo+0) 跳跃间断点: f(xo-0)≠ f(xo+0) 第二类间断点(震荡间断点、无穷间断点)...
LeetCode49 字母异位词分组
LeetCode49 字母异位词分组 在这篇博客中,我们将探讨 LeetCode 上的一道经典算法问题:字母异位词分组。这个问题要求将给定的字符串数组中的字母异位词组合在一起,并以任意顺序返回结果列表。 问题描述 给定一个字符串数组 strs࿰…...
【Python】Windows本地映射远程Linux服务器上的端口(解决jupyter notebook无法启动问题)
创作日志: 学习深度学习不想在本地破电脑上再安装各种软件,我就用实验室的服务器配置环境,启动jupyter notebook时脑子又瓦特了,在自己Windows电脑上打开服务器提供的网址,那肯定打不开啊,以前在其它电脑上…...
C++面试:用户态和内核态的基本概念、区别
目录 一、基本概念 概念: 区别: 二、Windows示例 基础介绍 用户态到内核态的切换过程: 程序实例 三、Linux示例 特权级别: 用户态到内核态的切换过程: 调度和中断处理: 程序实例 总结 在操作系…...
Vue计算属性computed()
1. 计算属性定义 获取计算属性值 <div>{{ 计算属性名称}}</div>创建计算属性 let 定义的属性ref/reactive....let 计算属性名称 computed(() > {//这里写函数式,函数式里面包含定义属性//只有这个包含的定义属性被修改时才出发此函数式//通过计算属性名称co…...
JWT学习笔记
了解 JWT Token 释义及使用 | Authing 文档 JSON Web Token Introduction - jwt.io JSON Web Token (JWT,RFC 7519 (opens new window)),是为了在网络应用环境间传递声明而执行的一种基于 JSON 的开放标准((RFC 7519)。该 token 被设计为紧凑…...
WSL里的Ubuntu 登录密码忘了怎么更改
环境: Win10 专业版 WSL2 如何 Ubuntu22.04 问题描述: WSL里的Ubuntu 登录密码忘了怎么更改 解决方案: 在WSL中的Ubuntu系统中,忘记了密码,可以通过以下步骤重置密码: 1.打开命令提示符或PowerShel…...
【软件测试面试】要你介绍项目-如何说?完美面试攻略...
目录:导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结(尾部小惊喜) 前言 1、测试面试时&am…...
【Crypto | CTF】RSA打法 集合
天命:我发现题题不一样,已知跟求知的需求都不一样 题目一:已知 p q E ,计算T,最后求D 已知两个质数p q 和 公钥E ,通过p和q计算出欧拉函数T,最后求私钥D 【密码学 | CTF】BUUCTF RSA-CSDN…...
在springboot中调用openai Api并实现流式响应
之前在《在springboot项目中调用openai API及我遇到的问题》这篇博客中,我实现了在springboot中调用openai接口,但是在这里的返回的信息是一次性全部返回的,如果返回的文字比较多,我们可能需要等很久。 所以需要考虑将请求接口响应…...
C++构造函数重难点解析
一、C构造函数是什么 C的构造函数是一种特殊的成员函数,用于初始化类的对象。它具有与类相同的名称,并且没有返回类型。构造函数在创建对象时自动调用,并且可以执行必要的初始化操作。 二、C构造函数特点 类的构造函数不能被继承,…...
QT day3 作业2.22
思维导图: 作业: 完善对话框,点击登录对话框,如果账号和密码匹配,则弹出信息对话框,给出提示”登录成功“,提供一个Ok按钮,用户点击Ok后,关闭登录界面,跳转到…...
AR汽车行业解决方案系列之2-远程汽修
在汽车行业中,AR技术的应用正悄然改变着整个产业链的运作方式,应用涵盖培训、汽修、汽车售后、PDI交付、质检以及汽车装配等,AR技术为多个环节都带来了前所未有的便利与效率提升。 安宝特AR将以系列推文的形式为读者逐一介绍在汽车行业中安宝…...
每日五道java面试题之spring篇(五)
目录: 第一题. 使用 Spring 有哪些方式?第二题. 什么是Spring IOC 容器?第三题. 控制反转(IoC)有什么作用?第四题. IOC的优点是什么?第五题. BeanFactory 和 ApplicationContext有什么区别? 第一题. 使用 Spring 有哪…...
挑战杯 基于YOLO实现的口罩佩戴检测 - python opemcv 深度学习
文章目录 0 前言1 课题介绍2 算法原理2.1 算法简介2.2 网络架构 3 关键代码4 数据集4.1 安装4.2 打开4.3 选择yolo标注格式4.4 打标签4.5 保存 5 训练6 实现效果6.1 pyqt实现简单GUI6.3 视频识别效果6.4 摄像头实时识别 7 最后 0 前言 🔥 优质竞赛项目系列…...
12. Springboot集成Dubbo3(三)Dubbo-Admin
目录 1、前言 2、安装 2.1、下载Dubbo-admin 2.2、修改配置 2.3、编译前端 2.4、访问 2.5、加载自己的服务 2.6、服务测试 2.7、其他 3、小结 1、前言 Dubbo Admin是用于管理Dubbo服务的基于Web的管理工具。Dubbo Admin提供了一个用户友好的界面,用于在分…...
c语言的数据结构:找环状链表入口处
一起<( ̄︶ ̄)↗[GO!] 1.如何判断一个链表是否有环 思路:设定两个快慢指针fast和slow,fast每次走两个结点,slow每次走一个节点 如果fast指针遇到了Null,那么这个链表没有环,如果fast和slow可以相遇,则代表这个链表有环 代码如下 N:fast先进环,slow后…...
业务系统对接大模型的基础方案:架构设计与关键步骤
业务系统对接大模型:架构设计与关键步骤 在当今数字化转型的浪潮中,大语言模型(LLM)已成为企业提升业务效率和创新能力的关键技术之一。将大模型集成到业务系统中,不仅可以优化用户体验,还能为业务决策提供…...
基于uniapp+WebSocket实现聊天对话、消息监听、消息推送、聊天室等功能,多端兼容
基于 UniApp + WebSocket实现多端兼容的实时通讯系统,涵盖WebSocket连接建立、消息收发机制、多端兼容性配置、消息实时监听等功能,适配微信小程序、H5、Android、iOS等终端 目录 技术选型分析WebSocket协议优势UniApp跨平台特性WebSocket 基础实现连接管理消息收发连接…...
linux 错误码总结
1,错误码的概念与作用 在Linux系统中,错误码是系统调用或库函数在执行失败时返回的特定数值,用于指示具体的错误类型。这些错误码通过全局变量errno来存储和传递,errno由操作系统维护,保存最近一次发生的错误信息。值得注意的是,errno的值在每次系统调用或函数调用失败时…...
ffmpeg(四):滤镜命令
FFmpeg 的滤镜命令是用于音视频处理中的强大工具,可以完成剪裁、缩放、加水印、调色、合成、旋转、模糊、叠加字幕等复杂的操作。其核心语法格式一般如下: ffmpeg -i input.mp4 -vf "滤镜参数" output.mp4或者带音频滤镜: ffmpeg…...
Caliper 配置文件解析:config.yaml
Caliper 是一个区块链性能基准测试工具,用于评估不同区块链平台的性能。下面我将详细解释你提供的 fisco-bcos.json 文件结构,并说明它与 config.yaml 文件的关系。 fisco-bcos.json 文件解析 这个文件是针对 FISCO-BCOS 区块链网络的 Caliper 配置文件,主要包含以下几个部…...
自然语言处理——循环神经网络
自然语言处理——循环神经网络 循环神经网络应用到基于机器学习的自然语言处理任务序列到类别同步的序列到序列模式异步的序列到序列模式 参数学习和长程依赖问题基于门控的循环神经网络门控循环单元(GRU)长短期记忆神经网络(LSTM)…...
Maven 概述、安装、配置、仓库、私服详解
目录 1、Maven 概述 1.1 Maven 的定义 1.2 Maven 解决的问题 1.3 Maven 的核心特性与优势 2、Maven 安装 2.1 下载 Maven 2.2 安装配置 Maven 2.3 测试安装 2.4 修改 Maven 本地仓库的默认路径 3、Maven 配置 3.1 配置本地仓库 3.2 配置 JDK 3.3 IDEA 配置本地 Ma…...
使用 SymPy 进行向量和矩阵的高级操作
在科学计算和工程领域,向量和矩阵操作是解决问题的核心技能之一。Python 的 SymPy 库提供了强大的符号计算功能,能够高效地处理向量和矩阵的各种操作。本文将深入探讨如何使用 SymPy 进行向量和矩阵的创建、合并以及维度拓展等操作,并通过具体…...
代理篇12|深入理解 Vite中的Proxy接口代理配置
在前端开发中,常常会遇到 跨域请求接口 的情况。为了解决这个问题,Vite 和 Webpack 都提供了 proxy 代理功能,用于将本地开发请求转发到后端服务器。 什么是代理(proxy)? 代理是在开发过程中,前端项目通过开发服务器,将指定的请求“转发”到真实的后端服务器,从而绕…...
安卓基础(aar)
重新设置java21的环境,临时设置 $env:JAVA_HOME "D:\Android Studio\jbr" 查看当前环境变量 JAVA_HOME 的值 echo $env:JAVA_HOME 构建ARR文件 ./gradlew :private-lib:assembleRelease 目录是这样的: MyApp/ ├── app/ …...
