- 浏览: 842480 次
- 性别:
- 来自: 深圳
文章分类
最新评论
-
renzhengzhi:
请教一下楼主,公有云和私有云的开发,具体要做哪些工作呢?我拿到 ...
4,云的4 种模式 -
SangBillLee:
我用了solr5.5,用SolrQuery查询,没法高亮,不知 ...
solr5.x快速入门 -
lw900925:
这翻译读起来真是别扭。
solr in action翻译-第一章1.1 -
springjpa_springmvc:
spring mvc demo教程源代码下载,地址:http: ...
Spring MVC性能提升 -
h416373073:
正遇到了此问题不知如何解决, 多谢分享
solr错误
容器是一个处理用户servlet请求并返回对象给web用户的模块。
org.apache.catalina.Container接口定义了容器的形式,有四种容器:Engine(引擎), Host(主机), Context(上下文), 和 Wrapper(包装器)。
容器接口
一个容器必须实现org.apache.catalina.Container接口
传递一个Container实例给Connector对象的setContainer方法,然后Connector对象就可以使用container的invoke方法
HttpConnector connector = new HttpConnector();
SimpleContainer container = new SimpleContainer();
connector.setContainer(container);
对于Catalina的容器首先需要注意的是它一共有四种不同的容器:
Engine:表示整个Catalina的servlet引擎
Host:表示一个拥有数个上下文的虚拟主机
Context:表示一个Web应用,一个context包含一个或多个wrapper
Wrapper:表示一个独立的servlet
每一个概念之上是用org.apache.catalina包来表示的。
Engine、Host、Context和Wrapper接口都实现了Container即可。
它们的标准实现是StandardEngine, StandardHost, StandardContext, and StandardWrapper,它们都是org.apache.catalina.core包的一部分。
一个Catalina功能部署不一定需要所有的四种类型的容器。例如本章的第一个应用程序仅仅包括一个wrapper,而第二个应用程序是一个包含Context和wrapper的容器模块。
一个容器可以有一个或多个低层次上的子容器。例如,一个Context有一个或多个wrapper,而wrapper作为容器层次中的最底层,不能包含子容器。
Container接口被设计成Tomcat管理员可以通过server.xml文件配置来决定其工作方式的模式
Pipelining Tasks(流水线任务)
一个pipeline包含了改容器要唤醒的所有任务。每一个阀门表示了一个特定的任务。一个容器的流水线有一个基本的阀门,但是你可以添加任意你想要添加的阀门。
阀门的数目定义为添加的阀门的个数(不包括基本阀门)。有趣的是,阀门可以通过编辑Tomcat的配置文件server.xml来动态的添加。
理解了servlet过滤器,那么流水线和它的阀门的工作方式不难想象。
一个流水线就像一个过滤链,每一个阀门像一个过滤器。跟过滤器一样,一个阀门可以操作传递给它的request和response方法。
让一个阀门完成了处理,则进一步处理流水线中的下一个阀门,基本阀门总是在最后才被调用。
一个容器可以有一个流水线。当容器的invoke方法被调用的时候,容器将会处理流水线中的阀门,并一个接一个的处理,直到所有的阀门都被处理完毕
流水线的invoke方法的伪代码如下所示
// invoke each valve added to the pipeline
for (int n=0; n<valves.length; n++) {
valve[n].invoke( ... );
}
// then, invoke the basic valve
basicValve.invoke( ... );
Tomcat的设计者选择了一种通过org.apache.catalina.ValveContext定义的方式来处理,这里介绍它如何工作的:
容器的invoke方法在被connector调用的时候所作的工作不难进行编码。容器调用的是流水线的invoke方法。
流水线接口的invoke方法前面跟容器接口的invoke方法签名相同
public void invoke(Request request, Response response) throws IOException, ServletException;
这里是Container接口中invoke方法在org.apache.catalina.core.ContainerBase的实现:
public void invoke(Request request, Response response)throws IOException, ServletException {
pipeline.invoke(request, response);
}
Pipeline是容器中Pipeline接口的一个实例。
流水线必须保证说要添加给它的阀门必须被调用一次,流水线通过创建一个ValveContext接口的实例来实现它。
ValveContext是流水线的的内部类,这样ValveContext就可以访问流水线中所有的成员。ValveContext中最重要的方法是invokeNext方法
public void invokeNext(Request request, Response response) throws IOException, ServletException
在创建一个ValveContext实例之后,流水线调用ValveContext的invokeNext方法。ValveContext会先唤醒流水线的第一个阀门,然后第一个阀门会在完成它的任务之前唤醒下一个阀门。
ValveContext将它自己传递给每一个阀门,那么该阀门就可以调用ValveContext的invokeNext方法。Valve接口的invoke签名如下:
public void invoke(Request request, Response response, ValveContext ValveContext) throws IOException, ServletException
public void invoke(Request request, Response response, ValveContext valveContext) throws IOException, ServletException {
// Pass the request and response on to the next valve in our pipeline
valveContext.invokeNext(request, response);
// now perform what this valve is supposed to do ...
}
org.apache.catalina.core.StandardPipeline类是容器流水线的实现
InvokeNext方法使用下标(subscript)和级别(stage)记住哪个阀门被唤醒。当第一次唤醒的时候,下标的值是0,级的值是1。
以你次,第一个阀门被唤醒,流水线的阀门获得ValveContext实例调用它的invokeNext方法。这时下标的值是1所以下一个阀门被唤醒,然后一步步的进行。
The Pipeline Interface流水线接口
我们提到的流水线的第一个方法是它的Pipeline接口的invoke方法,该方法会开始唤醒流水线的阀门。流水线接口允许你添加一个新的阀门或者删除一个阀门。
最后,可以使用setBasic方法来分配一个基本阀门给流水线,getBasic方法会得到基本阀门。最后被唤醒的基本阀门,负责处理request和回复response。
public interface Pipeline {
public Valve getBasic();
public void setBasic(Valve valve);
public void addValve(Valve valve);
public Valve[] getValves();
public void invoke(Request request, Response response) throws IOException, ServletException;
public void removeValve(Valve valve);
}
The Valve Interface阀门接口
阀门接口表示一个阀门,该组件负责处理请求。该接口有两个方法,invoke和getInfo方法。
Invoke方法如上所述,getInfo方法返回阀门的信息
public interface Valve {
public String getInfo();
public void invoke(Request request, Response response, ValveContext context) throws IOException, ServletException;
}
The ValveContext Interface阀门上下文接口
阀门上下文接口有两个方法,invokeNext方法如上所述,getInfo方法会返回阀门上下文的信息。ValveContext接口如下:
public interface ValveContext {
public String getInfo();
public void invokeNext(Request request, Response response)throws IOException, ServletException;
}
The Contained Interface Contained接口
一个阀门可以选择性的实现org.apache.catalina.Contained接口。该接口定义了其实现类跟一个容器相关联
public interface Contained {
public Container getContainer();
public void setContainer(Container container);
}
the Wrapper Interface Wrapper接口
org.apache.catalina.Wrapper接口表示了一个包装器。一个包装器是表示一个独立servlet定义的容器。
包装器继承了Container接口,并且添加了几个方法。包装器的实现类负责管理其下层servlet的生命中期,包括servlet的init,service,和destroy方法。
由于包装器是最底层的容器,所以不可以将子容器添加给它。如果addChild方法被调用的时候会产生IllegalArgumantException异常。
包装器接口中重要方法有allocate和load方法。allocate方法负责定位该包装器表示的servlet的实例
Load方法负责load和初始化servlet的实例
The Context Interface上下文(Context)接口
一个context在容器中表示一个web应用。一个context通常含有一个或多个包装器作为其子容器。
重要的方法包括addWrapper, createWrapper等方法
The Wrapper Application(包装器应用程序)
这个应用程序展示了如何写一个简单的容器模型
核心类是SimpleWrapper,它实现了Wrapper接口。SimpleWrapper类包括一个Pipeline和一个Loader类来加载一个servlet。
流水线包括一个基本阀门SimpleWrapperValve和两个另外的阀门ClientIPLoggerValve,HeaderLoggerValve)
public static void main(String[] args) { /** * 初始化连接器 */ HttpConnector connector = new HttpConnector(); //创建一个包装器 Wrapper wrapper = new SimpleWrapper(); //告诉包装器要加载类的名字 wrapper.setServletClass("ModernServlet"); //创建了加载器 Loader loader = new SimpleLoader(); //两个阀门 Valve valve1 = new HeaderLoggerValve(); Valve valve2 = new ClientIPLoggerValve(); //把加载器给包装器 wrapper.setLoader(loader); //流水线添加俩个阀门 ((Pipeline) wrapper).addValve(valve1); ((Pipeline) wrapper).addValve(valve2); //连接器设置容器 //把包装器当做容器添加到连接器中,然后初始化并启动连接器 connector.setContainer(wrapper); try{ //连接器初始化,实现Lifecycle周期接口 connector.initialize(); //启动 connector.start(); System.in.read(); }catch(Exception e){ e.printStackTrace(); } }
SimpleWrapper
package com.tomcat.core; import java.beans.PropertyChangeListener; import java.io.IOException; import javax.naming.directory.DirContext; import javax.servlet.Servlet; import javax.servlet.ServletException; import javax.servlet.UnavailableException; import org.apache.catalina.AccessLog; import org.apache.catalina.Cluster; import org.apache.catalina.Container; import org.apache.catalina.ContainerListener; import org.apache.catalina.InstanceListener; import org.apache.catalina.Loader; import org.apache.catalina.Manager; import org.apache.catalina.Pipeline; import org.apache.catalina.Realm; import org.apache.catalina.Wrapper; import org.apache.catalina.connector.Request; import org.apache.catalina.connector.Response; /** * 代表一个容器 * @author Administrator * */ public class SimpleWrapper implements Wrapper { /** * loader变量用于加载一个servlet类 */ private Loader loader; /** * Parent变量表示该包装器的父容器 */ protected Container parent = null; /** * getLoader方法用于返回一个Loader对象用于加载一个servlet类。 * 如果一个包装器跟一个加载器相关联,会返回该加载器。 * 否则返回其父容器的加载器,如果没有父容器,则返回null。 */ public Loader getLoader() { if(loader!=null) return loader; if(parent!=null) return parent.getLoader(); return null; } public void addInitParameter(String arg0, String arg1) { // TODO Auto-generated method stub } public void addInstanceListener(InstanceListener arg0) { // TODO Auto-generated method stub } ....... }
SimpleLoader
package com.tomcat.core; import java.beans.PropertyChangeListener; import java.io.File; import java.io.IOException; import java.net.MalformedURLException; import java.net.URL; import java.net.URLClassLoader; import java.net.URLStreamHandler; import org.apache.catalina.Container; import org.apache.catalina.Loader; /** * 容器中加载servlet的任务被分配给了Loader实现 * impleLoader就是一个Loader实现。 * 它知道如何定位一个servlet,并且通过getClassLoader获得一个java.lang.ClassLoader实例用来查找servlet类位置 * @author Administrator * */ public class SimpleLoader implements Loader { ////////WEB_ROOT用来指明在哪里查找servlet类 public static final String WEB_ROOT = System.getProperty("user.dir") + File.separator + "webroot"; ClassLoader classLoader = null; Container container = null; /** * 初始化类加载器 */ public SimpleLoader(){ try { URL[] urls = new URL[1]; URLStreamHandler streamHandler = null; File classPath = new File(WEB_ROOT); String repository = (new URL("file", null, classPath.getCanonicalPath() + File.separator)).toString() ; urls[0] = new URL(null, repository, streamHandler); classLoader = new URLClassLoader(urls); } catch (MalformedURLException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } public void addPropertyChangeListener(PropertyChangeListener arg0) { // TODO Auto-generated method stub } ...................... }
HeaderLoggerValve
package com.tomcat.core; import java.io.IOException; import javax.servlet.ServletException; import org.apache.catalina.CometEvent; import org.apache.catalina.Contained; import org.apache.catalina.Container; import org.apache.catalina.Valve; import org.apache.catalina.connector.Request; import org.apache.catalina.connector.Response; /** * 是一个阀门 * 打印请求头部到控制台上 * @author Administrator * */ public class HeaderLoggerValve implements Valve, Contained { public void backgroundProcess() { // TODO Auto-generated method stub } public void event(Request arg0, Response arg1, CometEvent arg2) throws IOException, ServletException { // TODO Auto-generated method stub } public String getInfo() { // TODO Auto-generated method stub return null; } public Valve getNext() { // TODO Auto-generated method stub return null; } public void invoke(Request arg0, Response arg1) throws IOException, ServletException { // TODO Auto-generated method stub } ................... }
ClientIPLoggerValve
package com.tomcat.core; import java.io.IOException; import javax.servlet.ServletException; import org.apache.catalina.CometEvent; import org.apache.catalina.Contained; import org.apache.catalina.Container; import org.apache.catalina.Valve; import org.apache.catalina.connector.Request; import org.apache.catalina.connector.Response; /** * ClientIPLoggerValve是一个阀门,它打印出客户端的IP地址到控制台 * @author Administrator * */ public class ClientIPLoggerValve implements Valve,Contained{ protected Container container; ................................ }
SimplePipeline
package com.tomcat.core; import org.apache.catalina.Pipeline; import org.apache.catalina.Valve; /** * 流水线 * @author Administrator * */ public class SimplePipeline implements Pipeline { public void addValve(Valve arg0) { // TODO Auto-generated method stub } public Valve getBasic() { // TODO Auto-generated method stub return null; } public Valve getFirst() { // TODO Auto-generated method stub return null; } public Valve[] getValves() { // TODO Auto-generated method stub return null; } public void removeValve(Valve arg0) { // TODO Auto-generated method stub } public void setBasic(Valve arg0) { // TODO Auto-generated method stub } }
一个仅仅包括一个包装器的简单的web应用。该程序仅仅包括一个servlet
大多数的网络应用需要多个servlet。在这些应用中,需要一个跟包装器不同的容器:上下文。
如何使用一个包含两个包装器的上下文来包装两个servlet类。
当有多于一个得包装器的时候,需要一个map来处理这些子容器,对于特殊的请求可以使用特殊的子容器来处理。
在这个程序中,mapper是SimpleContextMapper类的一个实例,
它继承了Tomcat 4中的org.apache.catalina.Mapper接口。一个容器也可以有多个mapper来支持多协议。
例如容器可以用一个mapper来支持HTTP协议,而使用另一个mapper来支持HTTPS协议
public interface Mapper {
public Container getContainer();
public void setContainer(Container container);
public String getProtocol(); public void setProtocol(String protocol);
public Container map(Request request, boolean update);
}
getContainer返回该容器的mapper,
setContainer方法用于联系一个容器到mapper。
getProtocol返回该mapper负责处理的协议,
setProtocol用于分配该容器要处理的协议。
map方法返回处理一个特殊请求的子容器。
SimpleContext表示一个上下文,它使用SimpleContextMapper作为它的mapper,SimpleContextValve作为它的基本阀门。
该上下文包括两个阀门ClientIPLoggerValve和HeaderLoggerValve。
用SimpleWrapper表示的两个包装器作为该上下文的子容器被添加。
包装器吧SimpleWrapperValve作为它的基本阀门,但是没有其它的阀门了。
该上下文应用程序使用同一个加载器、两个阀门。但是加载器和阀门时跟该上下文关联的,而不是跟包装器关联。
这样,两个加载器就可以都使用该加载器。该上下文被当做连接器的容器
基本流程如下
1. 一个容器有一个流水线,容器的invoke方法会调用流水线的invoke方法。
2. 流水线的invoke方法会调用添加到容器中的阀门的invoke方法,然后调用基本阀门的invoke方法。
3. 在一个包装器中,基本阀门负责加载相关的servlet类并对请求作出相应。
4. 在一个有子容器的上下文中,基本法门使用mapper来查找负责处理请求的子容器。如果一个子容器被找到,子容器的invoke方法会被调用,然后返回步骤1。
package com.tomcat.startup; import org.apache.catalina.Context; import org.apache.catalina.Loader; import org.apache.catalina.Pipeline; import org.apache.catalina.Valve; import org.apache.catalina.Wrapper; import com.tomcat.core.ClientIPLoggerValve; import com.tomcat.core.HeaderLoggerValve; import com.tomcat.core.HttpConnector; import com.tomcat.core.Mapper; import com.tomcat.core.SimpleContext; import com.tomcat.core.SimpleContextMapper; import com.tomcat.core.SimpleLoader; import com.tomcat.core.SimpleWrapper; public final class Bootstrap2 { /** * @param args */ public static void main(String[] args) { HttpConnector connector = new HttpConnector(); Wrapper wrapper1 = new SimpleWrapper(); wrapper1.setName("Primitive"); wrapper1.setServletClass("PrimitiveServlet"); Wrapper wrapper2 = new SimpleWrapper(); wrapper2.setName("Modern"); wrapper2.setServletClass("ModernServlet"); Context context = new SimpleContext(); context.addChild(wrapper1); context.addChild(wrapper2); Valve valve1 = new HeaderLoggerValve(); Valve valve2 = new ClientIPLoggerValve(); ((Pipeline) context).addValve(valve1); ((Pipeline) context).addValve(valve2); Mapper mapper = new SimpleContextMapper(); mapper.setProtocol("http"); context.addMapper(mapper); Loader loader = new SimpleLoader(); context.setLoader(loader); // context.addServletMapping(pattern, name); context.addServletMapping("/Primitive", "Primitive"); context.addServletMapping("/Modern", "Modern"); connector.setContainer(context); try { connector.initialize(); connector.start(); // make the application wait until we press a key. System.in.read(); } catch (Exception e) { e.printStackTrace(); } } } }
发表评论
-
21,tomcat关闭钩子
2012-11-22 20:35 6647在很多环境下,在关闭应用程序的时候需要做一些清理工作。问题在于 ... -
20,tomcat的XML解析---digester
2012-11-22 20:07 1559tomcat使用server.xml配置属性信息Tomcat使 ... -
19tomcat的服务器和服务
2012-11-20 20:10 1077Server服务器 Server接口表示整个Catalina ... -
18,tomcat的主机(host)和引擎
2012-11-16 09:13 2351如果需要在一个Tomcat部署中部署多个上下文,需要使用一个主 ... -
附,listener、 filter、servlet 加载顺序及其详解
2012-11-15 09:10 985一、 1、启动一个WEB项 ... -
17,tomcat中StandardContext
2012-11-15 08:59 5043一个上下文容器(Context)代表一个web应用,每一个上下 ... -
16,tomcat中StandardWrapper实现
2012-11-14 18:28 3890Wrapper接口在Catalina中的标准实现Standar ... -
15,tomcat安全
2012-11-14 09:02 1201有些web应用程序的内容是有限制的,只允许有权限的用户在提供正 ... -
14,tomcat session管理
2012-11-14 09:01 1104Catalina通过一个叫管理器的组建来完成Session的管 ... -
13.tomcat加载器
2012-11-13 13:21 1376库(repository)和源(res ... -
12,tomcat日志处理
2012-11-13 13:15 1248日志系统是一个记录信息的组件。在Catalina中,日志系统是 ... -
附:JAVA事件处理--观察者模式
2012-11-12 10:33 1001简单地说,观察者模式 ... -
11.tomcat生命周期
2012-11-12 10:26 988Catalina由多个组件组成,当Catalina启动的 ... -
9.Tomcat的默认连接器
2012-11-12 08:52 1179Tomcat连接器是一个可以插入servlet容器的独立模块, ... -
8.连接器
2012-11-12 08:46 940一个可以创建更好的请 ... -
7,Facade外观模式
2012-11-08 11:28 950外观模式:为子系统中的一组接口提供了一个一致的界面,此模式定义 ... -
6,一个简单的servlet容器
2012-11-08 11:10 855总的来说,一个全功能的servlet容器会为servlet的每 ... -
5.javax.servlet.Servlet接口
2012-11-08 09:18 951javax.servlet.Servlet接口Servlet编 ... -
4,一个简单的tomcat
2012-11-07 18:10 946流程图如下 -
3.ServerSocket 与 Socket的区别
2012-11-07 16:56 11871.1 ServerSocket类创建 ...
相关推荐
10.分布式系统设计实战.pptx 11.系统实战需求物料.pptx 另还有企培专家课程:设计理念和开发,面向企业架构师和中层管理人员,详细描述了IT技术管理、敏捷开发流程、DDD实践、部门管理等内容。 更多,深度学习、...
Prometheus容器监控架构 ...10.容器监控:Prometheus容器监控架构鼓励在堆栈的每一层都采用高度详细的度量工具,容器的状态,通过的请求流,甚至是运行于其中的应用的深层信息都通过度量工具对外可见。
10. 容器的分级:按照设计压力大小,《容规》将压力容器划分为低压、中压、高压和超高压四级。对于易燃或毒性程度为中度危害介质的中压储存容器和反应容器,其PV乘积也会影响容器的分类。 11. 排放能力:安全阀和...
10. 容器分类:根据设计压力和工作压力,以及直径和长度,可以确定氧气储罐属于哪一类压力容器。 11. 判断题涉及的法规和规定:例如,特种设备安全监察条例的实施日期,以及多腔压力容器的设计和制造要求,这些都是...
10.洁净区容器具清洁消毒标准操作规程[定稿].pdf
3.2. docker exec 命令 10 3.3. docker commit 命令 11 3.4. docker build 命令 12 3.5. docker-compose 命令 13 4. Docker 容器使用 16 4.1. 查看所有的容器 16 4.2. 查看运行中的容器 16 4.3. 查看容器日志...
- **容器**:如Servlet容器和EJB容器,负责管理Java组件的生命周期和资源。 - **集群**:多个Apusic服务器可以组成一个集群,实现负载均衡和故障转移。 - **热部署**:允许在不中断服务的情况下更新应用程序。 - **...
描述:“10个精选的容器应用案例10个精选的容器应用案例10个精选的容器应用案例” 标签:“容器应用” 知识点: 1. 容器技术的发展与应用:自2013年Docker诞生以来,容器技术在业界迅速受到追捧,特别是在企业级...
10. 容器适配器:stack、queue和priority_queue是容器适配器,它们基于底层的容器(通常是vector或deque)提供栈、队列和优先级队列的行为。 11. 泛型编程:STL的一个核心特性是泛型编程,这意味着所有容器和算法都...
10. 容器对桌面的压强:考虑容器底面积和容器与液体的总重力,计算容器对桌面的压强。 11. 湖水对堤坝底部的压强:湖水深度直接决定了压强大小,计算方法同上。 12. 弯管内的液体压强:即使管子形状改变,液体在...
10. 容器的内存管理: 容器会自动管理内部对象的内存,但开发者需要了解内存分配和释放可能带来的性能影响,例如使用reserve方法预先分配空间以减少内存碎片。 在实际编程中,理解并熟练运用这些容器和操作,可以...
10. perf_event:增加了对每 group 的监测跟踪的能力。 Linux 容器虚拟技术(LXC)是指通过虚拟化操作系统的方式来管理代码和应用程序,实现轻量级虚拟化和资源isolated 分组。 容器技术之 Docker 是指使用 Docker...
本文件“运输和储存容器.pdf”可能涵盖了以下多个方面的重要知识点: 1. 容器种类:运输和储存容器有多种类型,如金属箱、塑料桶、木质托盘、集装箱、周转箱等。每种类型的容器都有其特定的适用场景和优缺点,例如...
10.标准GUI组件(下拉列表)。 11.标准GUI组件(列表)。12.标准GUI组件(滚动条)。13.鼠标事件。14.键盘事件。 15.菜单(下拉菜单)。16.菜单(多级菜单)。17.菜单(弹出式菜单)。18.对话框。 相信这些Jaa...
10. 容器类对象:页框(PageFrame)是容器类对象,可以包含其他控件,选项C正确。 11. 自由表索引:自由表不能创建主索引,选项A正确。 12. 继承性:继承性体现了面向对象编程的共享机制,允许子类继承父类的属性...
10 docker版本介绍mp4 11docker部署YUM源获取mp4 12 docker安装及服务启动,mp4 13容器镜像获取mp4 14运行个容器mp4 15 dockerdaemon配置远程及本地管理mp4 16 dockel命令行命令介绍.mp4 17docker获取镜像mp4 18...
10. 筒节(短节)检查记录 筒节(短节)检查记录是用于记录和管理压力容器制造过程中的筒节(短节)检查情况的记录。该记录用于跟踪和记录压力容器制造过程中的筒节(短节)检查情况,以确保压力容器的制造符合相关...
10. 容器底部受到的压力与压强:对于高度相等、底面积相等的容器,如果装有同种液体,尽管液体体积相同,但由于容器形状可能不同,液体深度可能会不同,因此容器底部的压强和压力可能也会有所不同。 11. 海水深潜...
10. 容器类型与平衡:恒压容器中,如果加入惰性气体,总压强不变,平衡不移动;恒容容器中,加入惰性气体,各组分的分压不变,平衡也不移动。 11. 固体对平衡的影响:固体对平衡移动无直接影响,因为其浓度视为常数...
10. 容器适配器:除了基本的容器外,STL还提供了一些适配器,如优先级队列(priority_queue)、反向列表(deque)等,它们是对现有容器功能的扩展。 《C++标准库》帮助文档是学习STL的重要资源,它详尽地介绍了每个...