传统的Servlet容器 Apache Tomcat
这里只记录了部分重要场景
包含核心组件
静态资源处理
类加载
连接器
JDBC数据源
HttpServletResponse
javax.servlet.http.HttpServletResponse
public static void main(String[] args) {
ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader();
while (true) {
System.out.println(contextClassLoader.getClass().getName());
ClassLoader parent = contextClassLoader.getParent();
if (parent == null) {
break;
}
}
ClassLoader systemClassLoader = ClassLoader.getSystemClassLoader();
System.out.println(systemClassLoader.getClass().getName());
}
除了其中的状态码之外,结合最近的测试其中的实现可具体参考
addHeader方法,getHeader方法等等
BootStrap--system---common---webapp
静态资源处理类org.apache.catalina.servlets.DefaultServlet
注意下包名
大多数情况下我们关注的更多是server.xml中Tomcat的配置,而在web.xml中除了路径映射等配置外
<!-- The mapping for the default servlet -->
<servlet-mapping>
<servlet-name>default</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<!-- The mappings for the JSP servlet -->
<servlet-mapping>
<servlet-name>jsp</servlet-name>
<url-pattern>*.jsp</url-pattern>
<url-pattern>*.jspx</url-pattern>
</servlet-mapping>
关于是否是开发模式
<!-- development Is Jasper used in development mode? If true, -->
<!-- the frequency at which JSPs are checked for -->
<!-- modification may be specified via the -->
<!-- modificationTestInterval parameter. [true] -->
由于DefaultServlet是HttpServlet的子类,所以在此不展开讨论
而在server.xml中标签与后台接口是一一绑定的
<Connector port="8080" protocol="HTTP/1.1" connectionTimeout="20000" redirectPort="8443" />
而在JDBC中的大多数类中也遵循此规则,那么就上面这段分析标签Connector则对应
org.apache.catalina.connector.Connector,验证一下标签中对应protocol,connectionTimeout,redirectPort
其中标签对应部分
/**
* Defaults to using HTTP/1.1 NIO implementation.
*/
public Connector() {
this("org.apache.coyote.http11.Http11NioProtocol");
}
而在tomcat8.0+中getProtocol对应protocol
redirectPort对应属性默认值
/**
* The redirect port for non-SSL to SSL redirects.
*/
protected int redirectPort = 443;
关于标签中connector中这个Http11NioProtocol则在tomcat官方文档中可见其中一句话
When using HTTP connectors (based on APR or NIO/NIO2), Tomcat supports using sendfile to send large static files. These writes, as soon as the system load increases, will be performed asynchronously in the most efficient way. Instead of sending a large response using blocking writes, it is possible to write content to a static file, and write it using a sendfile code. A caching valve could take advantage of this to cache the response data in a file rather than store it in memory. Sendfile support is available if the request attribute org.apache.tomcat.sendfile.support is set to Boolean.TRUE
也可在server.xml中搜索
<!-- Define an AJP 1.3 Connector on port 8009 -->
<!--
<Connector protocol="AJP/1.3"
address="::1"
port="8009"
redirectPort="8443" />
-->
server.port在文件中的位置
<!-- {
"name": "server.port",
"type": "java.lang.Integer",
"description": "Server HTTP port.",
"sourceType": "org.springframework.boot.autoconfigure.web.ServerProperties",
"defaultValue": 8080
}, -->
重点来了 ServerProperties包含了tomcat,Jetty,Undertow,而在Springboot2.2.6中则存在Netty
那么理所当然,在tomcat中的一些配置也存在于此
/**
* Maximum amount of worker threads.
*/
private int maxThreads = 200;
/**
* Minimum amount of worker threads.
*/
private int minSpareThreads = 10;
那么为什么Tomcat被称之为嵌入式容器呢?
在启动时无需自启动容器,在Bootstrap中调用tomcat,另外tomcat中TomcatEmbeddedContext,Embedded即直译为嵌入式
这里记忆有些混乱了,有点找不过来哪里是入口了,但先从TomcatServletWebServerFactoryCustomizer的customize()方法调用找,
private Stream<Wrapper> getLoadOnStartupWrappers(Container[] children) {
Map<Integer, List<Wrapper>> grouped = new TreeMap<>();
for (Container child : children) {
Wrapper wrapper = (Wrapper) child;
int order = wrapper.getLoadOnStartup();
if (order >= 0) {
grouped.computeIfAbsent(order, ArrayList::new);
grouped.get(order).add(wrapper);
}
}
return grouped.values().stream().flatMap(List::stream);
}
因为要看下Netty,所以还是重新看下server.properties
我将Spring Boot AutoConfigure升级到了2.6.2,内置的Tomcat就升级到9.0了
为了方便查看才升级的,之前的2.1.x就不截图了
server.properties的位置在configuration的下面的json文件
spring-configuration-metadata.json
{
"name": "server",
"type": "org.springframework.boot.autoconfigure.web.ServerProperties",
"sourceType": "org.springframework.boot.autoconfigure.web.ServerProperties"
}
那既然为了看Netty在这个json文件中同样存在
{
"name": "server.netty",
"type": "org.springframework.boot.autoconfigure.web.ServerProperties$Netty",
"sourceType": "org.springframework.boot.autoconfigure.web.ServerProperties",
"sourceMethod": "getNetty()"
}
既然在json中存在getNetty等方法,猜测那么对应的ServerProperties也存在对应的方法,
因为存在实例么,tomcat搭配server.xml和web.xml简单看了一下,当然Tomcat还是主要和Servlet的关联关系更为重要,
本身tomcat知识点也最够庞大的,包含类加载器,双拼委派,打破双亲委派、jvm调优等等,可以顺带看下这里的专题
当一次请求发起都发生了什么?
用户通过浏览器进行了一个操作,这个操作可以是输入url地址并回车,或者是点击超链接,或者是在搜索框中输入关键字进行搜索,接着浏览器就捕获到了这个事件
由于 HTTP 协议底层具体的数据传输使用的是 TCP/IP 协议,因此浏览器需要向服务端发出 TCP 连接请求
服务器接受浏览器的连接请求,并经过 TCP 三次握手建立连接
浏览器将请求数据打包成一个 HTTP 协议格式的数据包
浏览器将打包好的数据包推入网络,经过网络传输最终到达服务器指定程序
服务端程序拿到数据包后,根据 HTTP 协议格式进行解包,获取到客户端的意图
得知客户端意图后进行处理,比如提供静态文件或者调用服务端程序获得动态结果
服务器将响应结果按照 HTTP 协议格式打包
服务器将响应数据包推入网络,数据包经过网络传输最终达到到浏览器
浏览器拿到数据包后,按照 HTTP 协议的格式解包,然后对数据进行解析
浏览器将解析后的静态数据(如html、图片)展示给用户
Tomcat 作为一个 HTTP 服务器,主要需要完成的功能是接受连接、解析请求数据、处理请求和发送响应这几个步骤。
作者:若兮缘
链接:https://www.jianshu.com/p/7c9401b85704
来源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
关于tomcat的架构就取自这篇文章,图文都很喜欢~
导入过程Running With JRE 7 Or Later
启动tomcat所需环境
else
eval $_NOHUP "\"$_RUNJAVA\"" "\"$CATALINA_LOGGING_CONFIG\"" $LOGGING_MANAGER "$JAVA_OPTS" "$CATALINA_OPTS" \
-D$ENDORSED_PROP="\"$JAVA_ENDORSED_DIRS\"" \
-classpath "\"$CLASSPATH\"" \
-Dcatalina.base="\"$CATALINA_BASE\"" \
-Dcatalina.home="\"$CATALINA_HOME\"" \
-Djava.io.tmpdir="\"$CATALINA_TMPDIR\"" \
org.apache.catalina.startup.Bootstrap "$@" start \
后续不在赘述。重点在Server.properties中版本区别是否包含Netty的这个类,
本来我是想跟着dei一下bug的,实际是我没起来,版本又不兼容,中间穿插了需求,就不dei了skr~