作者回复: 👍
作者回复: Wrapper -> Filter -> DispatcherServlet -> Controller
作者回复: 👍
作者回复: 好问题,Mapper组件在映射请求的时候,会在Request对象中存储相应的Host、Context等对象,这些选定的容器用来处理这个特定的请求,因此Engine中的Valve是从Request对象拿到Host容器的。
作者回复: <server port=“8005” shutdown=“SHUTDOWN”>
<service name=“Catalina”>
<engine defaulthost=“localhost” name=“Catalina”>
<host appbase=“webapps” autodeploy=“true” name=“localhost” unpackwars=“true”></host>
<host appbase=“webapps1” autodeploy=“true” name=“www.domain1.com” unpackwars=“true”></host>
<host appbase=“webapps2” autodeploy=“true” name=“www.domain2.com” unpackwars=“true”></host>
<host appbase=“webapps3” autodeploy=“true” name=“www.domain3.com” unpackwars=“true”></host>
</engine>
</service>
</server>
作者回复: 1,你说的对,在同一个Tomcat实例里部署多个Web应用是为了节省内存等资源,不过配置部署有点复杂,应用之间互相影响,加上现在硬件成本将低,多应用部署比较少见了。
2,Servlet接口中定义了service方法,没有doGet/doPost。HttpServlet是一个实现类,实现了service方法,同时留出了doGet/doPost方法让程序员来实现。
你可以通过web.xml配置一个或多个Filter,Servlet容器在调用Servlet的service之前,需要调用这些Filter,于是把这些Filter创建出来,形成链表,依次调用,这个Filter链中的最后一个Filter会负责调用Servlet的service方法。
通过一个调用栈来理解一下:
doGet:22, HelloServlet (servlet)
service:635, HttpServlet (javax.servlet.http)
service:742, HttpServlet (javax.servlet.http)
internalDoFilter:231, ApplicationFilterChain (org.apache.catalina.core)
doFilter:166, ApplicationFilterChain (org.apache.catalina.core)
invoke:199, StandardWrapperValve (org.apache.catalina.core)
invoke:96, StandardContextValve (org.apache.catalina.core)
invoke:493, AuthenticatorBase (org.apache.catalina.authenticator)
invoke:140, StandardHostValve (org.apache.catalina.core)
invoke:81, ErrorReportValve (org.apache.catalina.valves)
invoke:87, StandardEngineValve (org.apache.catalina.core)
service:342, CoyoteAdapter (org.apache.catalina.connector)
service:800, Http11Processor (org.apache.coyote.http11)
process:66, AbstractProcessorLight (org.apache.coyote)
process:806, AbstractProtocol$ConnectionHandler (org.apache.coyote)
doRun:1498, NioEndpoint$SocketProcessor (org.apache.tomcat.util.net)
run:49, SocketProcessorBase (org.apache.tomcat.util.net)
runWorker:1149, ThreadPoolExecutor (java.util.concurrent)
run:624, ThreadPoolExecutor$Worker (java.util.concurrent)
run:61, TaskThread$WrappingRunnable (org.apache.tomcat.util.threads)
run:748, Thread (java.lang)
作者回复: 如果你需要隔离访问域名,用第二种;如果要进一步隔离访问端口,用第三种。
作者回复: 是的,谢谢指出,已经在紧急修复了,正确的关系是这样的:
<Server>
<Service>
<Connector>
</Connector>
<Engine>
<Host>
<Context>
</Context>
</Host>
</Engine>
</Service>
</Server>
作者回复: 你理解对了,这段话的下面就有解释
作者回复: Tomca的容器架构是一步到位的,设计之初就考虑到了使用的灵活性,如果说将来有变化,应该会朝着“瘦身”的方向发展。
作者回复: 对的
作者回复: this泄露是指在构造函数里将this赋值给某个变量,而这个变量是外部可见的,这样当另一个线程通过这个变量访问this对象时,this对象还没构造完成,就有问题了。
这里的关键是,this赋值的变量一定是外部可以访问的,比如是个public static成员变量,又或者是外部的一个全局变量,又或者是另一个对象实例的成员变量(比如自己是个监听器,将自己注册到事件源对象中),但是上面代码将this赋值给了realHost,而realHost是一个私有成员变量,所以不会有问题。
作者回复: 1,DNS解析是在客户端完成的,你需要在客户端把两个域名指向同一个IP,可以通过hosts配置,因此只要你使用的端口相同,两个域名其实访问的是同一个Service组件。而Tomcat设计通过请求URL中Host来转发到不同Host组件的。
2. 不同的连接器代表一种通信的路径,比如同时支持HTTP和HTTPS,不是为了并发。
3. 对
4.域名相同指向不同的Web应用,默认情况下你只需要把你的Web应用全部扔到webapps目录下,Tomcat自动检测,创建相应的Context组件,各个web应用的访问路径就是web应用的目录名。
作者回复: 先看核心类,建议看第13答疑篇
作者回复: first valve—valve—valve—basic valve. 最后会调到basic valve
作者回复: 是的,初始化Filter时,Spring的容器已经初始化好了。
这个顺序是Tomcat的StandardContext组件的启动方法startInternal决定的,其中关键的三步是:
1. 调用启动事件监听器ServletContextListener:
listenerStart() ->这里创建了Spring容器
2.始化Filter:
filterStart()
3.初始化配置了"load on startup"的Servlet
loadOnStartup()