Java面试——Tomcat

优质博文:IT_BLOG_CN

一、Tomcat 顶层架构

img

Tomcat中最顶层的容器是Server,代表着整个服务器,从上图中可以看出,一个Server可以包含至少一个Service,用于具体提供服务。Service主要包含两个部分:ConnectorContainer。从上图中可以看出Tomcat的心脏就是这两个组件,他们的作用如下:
【1】Connector用于处理连接相关的事情,并提供SocketRequestResponse相关的转化;
【2】Container用于封装和管理Servlet,以及具体处理Request请求;

一个Tomcat中只有一个Server,一个Server可以包含多个Service,一个 Service只有一个Container,但是可以有多个Connectors,这是因为一个服务可以有多个连接,如同时提供HttpHttps链接,也可以提供向相同协议不同端口的连接,示意图如下(EngineHostContext下边会说到):
img

多个Connector和一个Container就形成了一个Service,有了Service就可以对外提供服务了,但是Service还要一个生存的环境,必须要有人能够给她生命、掌握其生死大权,那就非Server莫属了!所以整个Tomcat的生命周期由 Server控制。另外,上述的包含关系或者说是父子关系,都可以在tomcatconf目录下的 server.xml 配置文件中看出。

二、简要解释下 server.xml 配置文件的信息

server.xmlTomcat中最重要的配置文件,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 &quot;%r&quot; %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.xml的整体架构(简洁版):

<Server><Service><Connector /><Connector /><Engine><Host><Context /><!-- 现在常常使用自动部署,不推荐配置Context元素,Context小节有详细说明 --></Host></Engine></Service>
</Server>

【1】顶层元素:元素是整个配置文件的根元素,元素代表一个Engine元素以及一组与之相连的Connector元素。
【2】连接器: 代表了外部客户端发送请求到特定Service的接口;同时也是外部客户端从特定Service接收响应的接口。
【3】容器:容器的功能是处理Connector接收进来的请求,并产生对应的响应。Engine包含HostHost包含Context。一个 Engine组件可以处理Service中的所有请求,一个Host组件可以处理发向一个特定虚拟主机的所有请求,一个Context组件可以处理一个特定Web应用的所有请求。

三、Tomcat 都有哪些核心组件

【1】ServerServer元素在最顶层,代表整个 Tomcat容器,因此他必须是server.xml中唯一一个最外层的元素。一个Server元素可以有一个或多个Service元素。

<Server port="8005" shutdown="SHUTDOWN">
</Server>

可以看到,最外层有一个 元素,shutdown属性表示关闭Server的指令;port属性表示Server接收shutdown指令的端口号,设置为-1可以禁掉该端口。Server 的主要任务,就是提供一个接口让客户端能够访问到这个 Service集合,同时维护它所包含的所有的 Service的生命周期,包含如何初始化,如何结束服务,如何找到客户端要访问的 Service。
【2】ServiceConnectorEngine外面包一层,把它们组合在一起,对外提供服务。一个Service可以包含多个Connector,但是只能包含一个Engine;其中Connector的作用是从客户端接收请求,Engine的作用是处理接收进来的请求。

<Server port="8005" shutdown="SHUTDOWN"><Service name="Catalina"></Service>
</Server>

如上图,Server中包含一个名称为CatalinaService。实际上,Tomcat可以提供多个Service,不同的Service监听不同的端口。
【3】Connector接收连接请求,创建RequestResponse对象用于和请求端交换数据;然后分配线程让Engine来处理这个请求,并把产生的RequestResponse对象传给Engine。通过配置 Connector,可以控制请求 Service的协议及端口号。

<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" /></Service>
</Server>

通过配置第一个Connector,客户端可以通过8080端口号协议访问Tomcat。其中,protocol属性规定了请求的协议,port规定了请求的端口号,redirectPort表示当强制要求https而请求是 http时,重定向至端口号为8443ConnectorconnectionTimeout表示连接的超时时间。

在这个例子中,Tomcat监听Http请求,使用的是8080端口,而不是正式的 80端口;实际上,在正式的生产环境中,Tomcat也常常监听8080端口。而不是80端口。这是因为在生产环境中,很少讲Tomcat直接对外开放接收请求,而是在Tomcat和客户端之间加一层代理服务器(如Nginx),用于请求的转发、负载均衡、处理静态文件等;通过代理服务器访问Tomcat时,是在局域网中,因为一般仍使用8080端口。

第二个配置Connector,客户端可以通过8009端口使用AJP协议访问 TomcatAJP协议负责和其他的Http服务器(如Apache)建立连接;在把 Tomcat与其他服务器集成时,就需要用到这个连接器,之所以使用 Tomcat和其他服务器集成,是因为Tomcat可以用作Servlet/JSP容器,但是对静态资源处理速度较慢,不如ApacheIISHTTP服务器;因此常常将 TomcatApache等集成,前者做Servlet容器,后者处理静态资源,而AJP协议便负责TomcatApache的连接。TomcatApache等集成的原理如下图:
img
【4】EngineEngine 组件在Service组件有且只有一个;EngineService组件中的请求处理组件。Engine组件从一个或多个Connector中接收并处理,并将完成的响应返回给Connector,最终传递给客户端。前面说到,EngineHostContext都是容器,但是它们不是平行关系,而是父子关系:Engine包含HostHost包含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属性用于日志和错误信息,在整个Server中应该是唯一的。defalutHost属性指定了默认的host名称,当发往本机的请求指定的host名称不存在时,一律使用defaultHost指定的host进行处理;因此defaulthost的值,必须与Engine中的一个Host组件的name属性值匹配。
【5】EngineHostHostEngine的子容器。Engine组件中可以内嵌1个或者多个Host组件,每个Host组件代表Engine中的一个虚拟主机。Host组件至少有一个,且其中一个的name必须与 Engine组件中的defaultHost属性相匹配。
【6】Host的作用:Host虚拟主机的作用,是运行多个Web应用(一个Context代表一个Web应用),并负责安装、展开、启动、结束每个Web应用。Host组件代表的虚拟主机,对应服务器中一个网络名实体(如www.test.com](https://links.jianshu.com/go?to=http%3A%2F%2Fwww.test.com)"或IP地址"116.25.25.25);为了使用户可以通过网络名连接Tomcat服务器,这个名字应该在DNS服务器上注册。

客户端通常使用主机名来标识它们希望连接的服务器,该主机名也会包含在 HTTP请求头中,TomcatHTTP头中提取出主机名,寻找名字匹配的主机。如果没有匹配,请求会发送至默认的主机。因此默认主机不需要再DNS服务器中注册网络名,因为任何与所有Host名称不匹配的请求,都会路由至默认主机。
【7】Host的配置:name属性指定虚拟主机的主机名,一个Engine有且只有一个Host组件的name属性和Engine组件的 defaultHost属性相匹配;一般情况下,主机名需要是在DNS服务器中注册网络名,但是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>

unpackWARs指定了是否将代表Web应用的WAR文件解压;如果是true,通过解压后的文件结构运行该Web应用,如果是false,直接使用WAR文件运行Web应用。
【8】ContextContext元素代表在虚拟主机上运行的一个Web应用。在后文中,提到Context、应用或Web应用,他们都代指Web应用,每个Web应用基于WAR文件,或WAR文件解压后对应的目录(这里称为应用目录)ContextHost的子容器,每个Host都可以定义任意多的Context元素。元素的配置:Context元素最重要的属性是 docBasepath,此外reloadable属性也比较常用。

docBase指定了该Web应用使用war包路径,或应用目录。需要注意的是:在自动部署场景下(配置文件位于xmlBase中),docBase不在appBase目录中,才需要指定;如果docBase指定的war包或应用目录就在appBase中,则不需要指定。因为Tomcat会自动扫描appBase中的war包和应用目录,制定了反而造成问题。

path指定了访问该Web应用上下文路径,当请求到来时,Tomcat根据Web应用的path属性与 URL匹配程度来选择Web应用处理相应请求。例如:Web 应用app1path属性是/app1Web应用app2path属性是"/app2",那么请求/app1/index.html会交由app1来处理;而请求/app2/index.html会交由 app2来处理。如果一个Context元素的path属性为"",那么这个Context是虚拟主机的默认的Web应用;当请求的uri与所有的path都不匹配时,使用该默认Web应用来处理。

但是,需要注意的是,在自动部署场景(配置文件位于xmlBase中),不能指定path属性,path属性由配置的文件的文件名,WAR文件的文件名或应用目录的名称自动推导出来。如扫描Web应该时,发现xmlBase目录下的app1.xml,或appBase目录下的app1.WARapp1应用目录,则该Web用于的path属性是app1。如果名称不是app1而是ROOT,则该Web应用时虚拟主机默认的Web应用,此时path属性推导为""。

reloadable属性指示tomcat是否在运行时监控在WEB-INF/classesWEB-INF/lib目录下class文件的改动。如果值为true,那么当class文件改动时,会重新web应用的重新加载。在开发环境下,reloadable设置为ture便于调试;但是在生产环境中设置为true会给服务器带来性能压力,因此reloadable参数的默认值为false。在该例子中,docBase位于HostappBase目录之外;path属性没有指定,而是根据app1.xml自动推导为app1

<Context docBase="D:\Program Files\app1.war" reloadable="true"></Context>

若是自动部署(即autoDeploy="true"),那么server.xml配置文件中没有Context元素的配置。这是因为Tomcat开启了自动部署,Web应用没有在 server.xml中配置静态部署,而是由Tomcat通过特定的规则自动部署。

四、Web 的自动部署

要开启Web应用的自动部署,需要配置所在的虚拟主机;配置的方式就是在配置Host元素的 deployOnStartupautoDeploy属性。如果deployOnStartupautoDeploy设置为true,则tomcat启动自动部署:当检测到新的Web应用或Web应用更新时,会触发应用的部署(或重新部署)。

二者的主要区别在于
【1】deployeOnStartuptrue时,Tomcat在启动时检查Web应用,且检测到所有的Web应用都试做新应用;
【2】autoDeploytrue时,Tomcat在运行时定期检查新的Web应用或Web应用的更新;

通过配置deployOnStartupautoDeploy可以开启虚拟主机自动部署Web应用;实际上,自动部署依赖于检查是否有新的或更改过的Web应用,而Host元素中的appBasexml配置设置了检查Web应用更新的目录。

其中,appBase属性指定Web应用所在的目录,默认值是webapps,这是一个相对路径,代表 Tomcat根目录下的webapps文件夹。xmlBase属性指定Web应用的XML配置文件所在的目录,默认值为conf/<engine_name><engine_name>,例如上面例子中,主机localhostxmlBase的默认值是$TOMCAT_HOME/conf/Catalina/localhost

五、appBase 和 docBase的区别

【1】appBase这个目录下面的子目录将自动被部署为应用,且war文件将被自动解压缩并部署为应用,默认为tomcatwebapps目录。
【2】docBase指定需要关联的项目自动解压并部署到appBase目录下。项目的名称由path属性决定。
先部署 需要注意,docBase所在的文件或者war包必须存在。否则项目启动找不到对应的目录。此时文件解压到appBase目录下,根据path属性,决定解压后的文件名。
若采用了<Host name="localhost" appBase="webapp" autoDeploy="true"> 配置,那么appBase目录下的应用目录将会再次部署。此时项目是部署了两遍。解决办法,设置autoDeploy="false"

六、Tomcat 顶层架构小结

【1】Tomcat中只有一个Server,一个Server可以有多个Service,一个Service可以有多个 Connector和一个Container
【2】Server掌管着整个Tomcat的生死大权;
【3】Service是对外提供服务的;
【4】Connector用于接受请求并将请求封装成RequestResponse来具体处理;
【5】Container用于封装和管理Servlet,以及具体处理Request请求;

知道了整个Tomcat顶层的分层架构和各个组件之间的关系以及作用,对于绝大多数的开发人员来说 ServerService对我们来说确实很远,而我们开发中绝大部分进行配置的内容是属于ConnectorContainer的,所以接下来介绍一下ConnectorContainer

七、Connector 和 Container的微妙关系

由上述内容我们大致可以知道一个请求发送到Tomcat之后,首先经过Service然后会交给我们的 ConnectorConnector用于接收请求并将接收的请求封装为RequestResponse来具体处理,RequestResponse封装完之后再交由Container进行处理,Container处理完请求之后再返回给 Connector,最后在由Connector通过Socket将处理的结果返回给客户端,这样整个请求的就处理完了!

Connector最底层使用的是Socket来进行连接的,RequestResponse是按照HTTP协议来封装的,所以Connector同时需要实现TCP/IP协议和HTTP协议。Tomcat既然处理请求,那么肯定需要先接收到这个请求,接收请求这个东西我们首先就需要看一下Connector

八、Container 架构分析

Container用于封装和管理Servlet,以及具体处理Request请求,在Connector内部包含了4个子容器,结构图如下:
img
4个子容器的作用分别是:
【1】Engine:引擎,用来管理多个站点,一个Service最多只能有一个Engine
【2】Host:代表一个站点,也可以叫虚拟主机,通过配置Host就可以添加站点;
【3】Context:代表一个应用程序,对应着平时开发的一套程序,或者一个WEB-INF目录以及下面的web.xml文件;
【4】Wrapper:每一Wrapper封装着一个Servlet

下面找一个Tomcat的文件目录对照一下,如下图所示:
img

ContextHost的区别是Context表示一个应用,我们的Tomcat中默认的配置下webapps下的每一个文件夹目录都是一个Context,其中ROOT目录中存放着主应用,其他目录存放着子应用,而整个 webapps就是一个 Host站点。我们访问应用Context的时候,如果是ROOT下的则直接使用域名就可以访问,例如:www.ledouit.com,如果是Host(webapps)下的其他应用,则可以使用 www.ledouit.com/docs 进行访问,当然默认指定的根应用ROOT是可以进行设定的,只不过Host站点下默认的主营用是ROOT目录下的。

看到这里我们知道Container是什么,但是还是不知道Container是如何进行处理的以及处理完之后是如何将处理完的结果返回给Connector的。

十、Container 如何处理请求的

Container处理请求是使用Pipeline-Valve管道来处理的!(Valve是阀门之意)Pipeline-Valve是责任链模式,责任链模式是指在一个请求处理的过程中有很多处理者依次对请求进行处理,每个处理者负责做自己相应的处理,处理完之后将处理后的请求返回,再让下一个处理着继续处理。
img

但是!Pipeline-Valve使用的责任链模式和普通的责任链模式有些不同!区别主要有以下两点:
【1】每个Pipeline都有特定的Valve,而且是在管道的最后一个执行,这个Valve叫做BaseValveBaseValve是不可删除的;
【2】在上层容器的管道的BaseValve中会调用下层容器的管道。

我们知道Container包含四个子容器,而这四个子容器对应的BaseValve分别在:StandardEngineValveStandardHostValveStandardContextValveStandardWrapperValvePipeline的处理流程图如下:
img

【1】Connector在接收到请求后会首先调用最顶层容器的Pipeline来处理,这里的最顶层容器的 Pipeline就是EnginePipelineEngine的管道);
【2】在Engine的管道中依次会执行EngineValve1EngineValve2等等,最后会执行 StandardEngineValve,在StandardEngineValve中会调用Host管道,然后再依次执行HostHostValve1HostValve2等,最后在执行StandardHostValve,然后再依次调用Context的管道和 Wrapper的管道,最后执行到StandardWrapperValve
【3】当执行到StandardWrapperValve的时候,会在StandardWrapperValve中创建FilterChain,并调用其 doFilter方法来处理请求,这个FilterChain包含着我们配置的与请求相匹配的FilterServlet,其 doFilter方法会依次调用所有的FilterdoFilter方法和Servletservice方法,这样请求就得到了处理!
【4】当所有的Pipeline-Valve都执行完之后,并且处理完了具体的请求,这个时候就可以将返回的结果交给Connector了,Connector在通过Socket的方式将结果返回给客户端。

十一、tomcat 容器是如何创建 servlet类实例?用到了什么原理?

当容器启动时,会读取在webapps目录下所有的web应用中的web.xml文件,然后对xml文件进行解析,并读取servlet注册信息。然后,将每个应用中注册的servlet类都进行加载,并通过反射的方式实例化。(有时候也是在第一次请求时实例化)在servlet注册时加上如果为正数,则在一开始就实例化,如果不写或为负数,则第一次请求实例化。

十二、共享 session处理

目前的处理方式有如下几种:
【1】使用Tomcat本身的Session复制功能。参考http://ajita.iteye.com/blog/1715312Session复制的配置)方案的有点是配置简单,缺点是当集群数量较多时,Session复制的时间会比较长,影响响应的效率;
【2】使用第三方来存放共享Session:目前用的较多的是使用memcached来管理共享Session,借助于memcached-sesson-manager来进行TomcatSession管理。参考http://ajita.iteye.com/blog/1716320(使用MSM管理Tomcat集群session
【3】使用黏性session的策略:对于会话要求不太强(不涉及到计费,失败了允许重新请求下等)的场合,同一个用户的session可以由nginx或者apache交给同一个Tomcat来处理,这就是所谓的 session sticky策略,目前应用也比较多。参考:http://ajita.iteye.com/blog/1848665(tomcat session sticky)Nginx默认不包含session sticky模块,需要重新编译才行(windows下我也不知道怎么重新编译)优点是处理效率高多了,缺点是强会话要求的场合不合适。

十三、关于 Tomcat 的 session数目

这个可以直接从Tomcatweb管理界面去查看即可,或者借助于第三方工具Lambda Probe来查看,它相对于Tomcat自带的管理稍微多了点功能,但也不多 ;

十四、Tomcat 一个请求的完整过程

首先DNS解析机器,一般是ng服务器ip地址,然后ng根据server的配置,寻找路径为yy/的机器列表,ip和端口。最后 选择其中一台机器进行访问。下面为详细过程:
【1】请求被发送到本机端口8080,被在那里侦听的Coyote HTTP/1.1 Connector获得;
【2】Connector把该请求交给它所在的ServiceEngine来处理,并等待来自Engine的回应;
【3】Engine获得请求localhost/yy/index.jsp,匹配它所拥有的所有虚拟主机Host
【4】Engine匹配到名为 localhost 的 Host(即使匹配不到也把请求交给该 Host处理,因为该Host被定义为该 Engine的默认主机);
【5】localhost Host获得请求/yy/index.jsp,匹配它所拥有的所有Context
【6】Host匹配到路径为/yyContext(如果匹配不到就把该请求交给路径名为”“的Context去处理);
【7】path=”/yy”Context获得请求/index.jsp,在它的mapping table中寻找对应的servlet
【8】Context匹配到URL PATTERN*.jspservlet,对应于JspServlet类;
【9】构造HttpServletRequest对象和HttpServletResponse对象,作为参数调用JspServletdoGetdoPost方法;
【10】Context把执行完了之后的HttpServletResponse对象返回给Host
【11】HostHttpServletResponse对象返回给Engine
【12】EngineHttpServletResponse对象返回给Connector
【13】ConnectorHttpServletResponse对象返回给客户browser

十五、Tomcat 工作模式

Tomcat是一个JSP/Servlet容器。其作为Servlet容器,有三种工作模式:独立的Servlet容器、进程内的Servlet容器和进程外的Servlet容器。进入Tomcat的请求可以根据Tomcat的工作模式分为如下两类:
【1】Tomcat作为应用程序服务器:请求来自于前端的web服务器,这可能是Apache, IIS, Nginx等;
【2】Tomcat作为独立服务器:请求来自于web浏览器;

Tomcat的工作一般分为三种:
【1】bio 传统的Java I/O操作,同步且阻塞I/O,一个线程处理一个请求,并发量高时,线程数较多,浪费资源;(已经很少有人在使用)
【2】nio JDK1.4开始支持,同步阻塞或同步非阻塞IO,可以通过少量的线程来处理大量的请求;(从Tomcat 8版本开始默认就是这种模式)
【3】aprJNI的形式调用Apache HTTP服务器的核心动态链接库来处理文件读取或网络传输操作,从而大大地提高Tomcat对静态文件的处理性能;(企业中使用较多)

十六、如何对 Tomcat 进行优化

【1】关闭Manager管理页面;(默认已经关闭)
【2】关闭host-mangent管理页面;(默认已经关闭)
【3】对Tomcat日志进行分割;
【4】定义Tomcat 404错误返回的页面;
【5】对JVM进行优化;
【6】对Tomcat线程池进行优化;

十七、如何对 Tomcat 进行优化

【1】关闭Manager管理页面;(默认已经关闭)
【2】关闭host-mangent管理页面;(默认已经关闭)
【3】对Tomcat日志进行分割;
【4】定义Tomcat 404错误返回的页面;
【5】对JVM进行优化;
【6】对Tomcat线程池进行优化;
【7】更改Tomcat的工作的模式;

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/388007.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

SQL labs-SQL注入(七,sqlmap对于post传参方式的注入,2)

本文仅作为学习参考使用&#xff0c;本文作者对任何使用本文进行渗透攻击破坏不负任何责任。参考&#xff1a;SQL注入之Header注入_sqlmap header注入-CSDN博客 序言&#xff1a; 本文主要讲解基于SQL labs靶场&#xff0c;sqlmap工具进行的post传参方式的SQL注入&#xff0c…

【Java版数据结构】初识泛型

看到这句话的时候证明&#xff1a;此刻你我都在努力 加油陌生人 br />个人主页&#xff1a;Gu Gu Study专栏&#xff1a;Java版数据结构 喜欢的一句话&#xff1a; 常常会回顾努力的自己&#xff0c;所以要为自己的努力留下足迹 喜欢的话可以点个赞谢谢了。 作者&#xff1…

【全国大学生电子设计竞赛】2024年E题

&#x1f970;&#x1f970;全国大学生电子设计大赛学习资料专栏已开启&#xff0c;限时免费&#xff0c;速速收藏~

快速查找WGS1984 坐标地理坐标系转UTM投影坐标的多种方法

在arcgis中如果是要计算长度或面积&#xff0c;则需要将矢量图层地理坐标系转为投影坐标系&#xff0c;下面总结了几种快速找到“WGS 1984”&#xff08;UTM ZONE&#xff09;投影带号的方法。 一、准备工作 软件&#xff1a;arcmap 示例数据&#xff1a;安微省shp矢量图 二…

删除链表的倒数第N个结点(LeetCode)

题目 给你一个链表&#xff0c;删除链表的倒数第个结点&#xff0c;并且返回链表的头结点。 示例1&#xff1a; 输入&#xff1a;&#xff0c; 输出&#xff1a; 示例2&#xff1a; 输入&#xff1a;&#xff0c; 输出&#xff1a; 示例3&#xff1a; 输入&#xff1a;&#x…

申瓯通信设备有限公司在线录音管理系统(复现过程)

漏洞简介 申瓯通信设备有限公司在线录音管理系统 index.php接口处存在任意文件读取漏洞&#xff0c;恶意攻击者可能利用该漏洞读取服务器上的敏感文件&#xff0c;例如客户记录、财务数据或源代码&#xff0c;导致数据泄露 一.复现过程 fofa搜索语句:title"在线录音管…

【Vue3】标签的 ref 属性

【Vue3】标签的 ref 属性 背景简介开发环境开发步骤及源码 背景 随着年龄的增长&#xff0c;很多曾经烂熟于心的技术原理已被岁月摩擦得愈发模糊起来&#xff0c;技术出身的人总是很难放下一些执念&#xff0c;遂将这些知识整理成文&#xff0c;以纪念曾经努力学习奋斗的日子。…

Ubuntu22.04手动安装fabric release-2.5版本

这个过程稍微有点复杂&#xff0c;但完整操作完成以后会对Fabric网络有更加深入的理解&#xff0c;方便后续自己手动搭建Fabric网络。这个过程需要手动逐个下载Fabric源代码、使用命令下载Fabric镜像和用Git下载例子程序。 Fabric源代码主要用途是用来编译cryptogen、configtx…

二叉搜索树(图解)

文章目录 二叉搜索树的概念插入查找二叉搜索树的删除操作删除单孩子和叶子节点。del节点有两个孩子用左子树的最大节点替代用右子树的最小节点替代 弊端 二叉搜索树的概念 对于每颗子树&#xff0c;左子树 < 根&#xff0c;右子树 > 根。 二叉搜索树有以下操作&#xff1…

代码随想录二刷(哈希表)

代码随想录二刷(哈希表) 三数之和思路反正对于我来说是真的难想出来。 若这道题还是采用哈希表的思路去做&#xff0c;非常麻烦&#xff0c;并且还要考虑去重的操作。所以这道题其实用双指针&#xff0c;是更方便的。 具体程序如下&#xff1a; class Solution:def threeSu…

Docker简介和Docker常见命令

目录 1. Docker 简介 1.1 Docker 的核心概念 1.2 Docker 的优势 1.3 Docker 工作流程 2. 常见命令 2.1 基本命令 2.2 镜像操作 2.3 容器操作 2.4 网络操作 2.5 卷操作 2.6 日志和监控 2.7 清理命令 3. 注意事项和最佳实践 3.1 镜像操作 3.2 容器操作 3.3 网络操…

2.1、matlab绘图汇总(图例、标题、坐标轴、线条格式、颜色和散点格式设置)

1、前言 在 MATLAB 中进行绘图是一种非常常见且实用的操作,可以用来可视化数据、结果展示、分析趋势等。通过 MATLAB 的绘图功能,用户可以创建各种类型的图形,包括线图、散点图、柱状图、曲线图等,以及三维图形、动画等复杂的可视化效果。 在绘图之前,通常需要先准备好要…

docker部署容器端口占用问题

docker部署容器端口占用问题 当我在使用 Windows 下使用 Docker Desktop 部署docker容器时经常性发生容器启动失败的提示&#xff0c;并且有的时候重启电脑后就能成功启动容器&#xff0c;这是因为 Hyper-V 引起的 保留端口&#xff0c;这部分端口将会被系统保留&#xff0c;无…

基于SpringBoot+Vue的企业客户信息反馈平台(带1w+文档)

基于SpringBootVue的企业客户信息反馈平台(带1w文档) 基于SpringBootVue的企业客户信息反馈平台(带1w文档) 企业客户信息反馈平台的开发运用java技术&#xff0c;MIS的总体思想&#xff0c;以及MYSQL等技术的支持下共同完成了该平台的开发&#xff0c;实现了企业客户信息反馈管…

【C++】哈希容器

unordered系列关联式容器 在之前的博文中介绍过关联式容器中的map与set&#xff0c;同map与set一样&#xff0c;unordered_set与unordered_set也是关联式容器。 在C98中&#xff0c;STL提供了底层为红黑树结构的一系列关联式容器&#xff0c;查询效率可以达到logN&#xff1b;在…

安装 Terraform for Tencent 使用

第一步 &#xff1a;下载安装包 前往 Terraform 官网&#xff0c;使用命令行直接安装 Terraform 或下载二进制安装文件。 解压并配置全局路径 Linux/MAC&#xff1a;export PATH$PATH:${可执行文件所在目录} 例如&#xff1a;export PATH$PATH:$/usr/bin/terraform Win…

vue2学习 -- 核心语法

文章目录 前置简介1. 模板语法2. 数据2.1 数据绑定2.2 el与data的两种写法2.3 MVVM模型2.4 Object.defineProperty2.5 Vue中的数据代理 3. 事件3.1 事件处理3.2 事件修饰符3.3 键盘事件 4. 计算属性5. 监视(侦听)属性5.1 书写形式5.2 深度监视5.3 简写形式5.4 计算属性和监听属…

Go语言生成excel、将excel保存到本地、将多个excel表格压缩为压缩包、在压缩文件上传OSS删除本地excel文件和压缩包

最近在公司了个需求&#xff0c;主要涉及到文件导出&#xff0c;需要根据特定表格文件生成excel文件导出&#xff0c;同时对导出的excel临时保存本地&#xff0c;生成压缩包&#xff0c;将压缩包上传至OSS&#xff08;Object Storage Service&#xff09;后删除本地临时文件。下…

Go+Redis零基础到用户管理系统API实战_20240730 课程笔记

概述 如果您没有Golang的基础&#xff0c;应该学习如下前置课程。 Golang零基础入门Golang面向对象编程Go Web 基础Go语言开发REST API接口_20240728Go语言操作MySQL开发用户管理系统API教程_20240729Redis零基础快速入门_20231227 基础不好的同学每节课的代码最好配合视频进…

AI绘画模型之:VAE、SD 与 SD-XL

重磅推荐专栏: 《大模型AIGC》 《课程大纲》 《知识星球》 本专栏致力于探索和讨论当今最前沿的技术趋势和应用领域,包括但不限于ChatGPT和Stable Diffusion等。我们将深入研究大型模型的开发和应用,以及与之相关的人工智能生成内容(AIGC)技术。通过深入的技术解析和实践经…