本章主要内容为在请求转交给Coyote
适配器后的流程分析
紧接上文中请求交由Processor
处理.
CoyoteAdapter.service()
此时在service方法中会调用CoyoteAdapter.service()
,至此请求就即将被发送给Engine
引擎.
//获取Coyote适配器,并调用其service方法
getAdapter().service(request, response);
CoyoteAdapter.service()
这里先将CoyoteRequest
转换为HttpServletRequest
, 然后HttpServletRequest
里设置CoyoteRequest
然后就是一系列的invoke
方法
请求被Connector
组件接收,创建Request
和Response
对象。
Connector
将Request
和Response
交给Container
,先通过Engine
的pipeline
组件流经内部的每个Valve
。
请求流转到Host
的pipeline
组件中,并且经过内部Valve
的过滤。
请求流转到Contex
t的pipeline
组件中,并且经过内部的Valve
的过滤。
请求流转到Wrapper
的pipeline
组件中,并且经过内部的Valve
的过滤。
Wrapper
内部的WrapperValve
创建FilterChain
实例,调用指定的Servlet
实例处理请求。
返回
得到Engine
的Pipeline
得到管道的阀门, 默认为basic
为StandardEngineValve
StandardEngineValve.invoke()
ErrorReportValve -> StandardHostValve
ErrorReportValve .invoke()
StandardHostValve.invoke()
AuthenticatorBase -> NonLoginAuthenticator -> StandardContextValue
StandardContextValve.invoke()
在这个方法中解释了为什么 /WEB-INF/
下的资源不可以直接请求的原因
MessageBytes requestPathMB = request.getRequestPathMB();
if ((requestPathMB.startsWithIgnoreCase("/META-INF/", 0))
|| (requestPathMB.equalsIgnoreCase("/META-INF"))
|| (requestPathMB.startsWithIgnoreCase("/WEB-INF/", 0))
|| (requestPathMB.equalsIgnoreCase("/WEB-INF"))) {
response.sendError(HttpServletResponse.SC_NOT_FOUND); //解释了 /WEB-INF/下的资源为什么不能直接请求
return;
}
Wrapper
封装了Servlet
的信息
StandardWrapperValve.invoke()
Servlet.service()
创建并初始化Servlet
准备了一个FIlterChain
执行FilterChain
所以Tomcat
在请求到达Servlet
之前会执行FilterChain
ApplicationFilterChain.doFilter()
ApplicationFilterChain.internalDoFilter()
最后执行了Servlet.service()
然后执行了HttpServlet.service()
@Override
public void service(ServletRequest req, ServletResponse res)
throws ServletException, IOException {
HttpServletRequest request;
HttpServletResponse response;
try {
request = (HttpServletRequest) req;
response = (HttpServletResponse) res;
} catch (ClassCastException e) {
throw new ServletException(lStrings.getString("http.non_http"));
}
service(request, response);
}
protected void service(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
String method = req.getMethod();
if (method.equals(METHOD_GET)) {
long lastModified = getLastModified(req);
if (lastModified == -1) {
// servlet doesn't support if-modified-since, no reason
// to go through further expensive logic
doGet(req, resp);
} else {
long ifModifiedSince;
try {
ifModifiedSince = req.getDateHeader(HEADER_IFMODSINCE);
} catch (IllegalArgumentException iae) {
// Invalid date header - proceed as if none was set
ifModifiedSince = -1;
}
if (ifModifiedSince < (lastModified / 1000 * 1000)) {
// If the servlet mod time is later, call doGet()
// Round down to the nearest second for a proper compare
// A ifModifiedSince of -1 will always be less
maybeSetLastModified(resp, lastModified);
doGet(req, resp);
} else {
resp.setStatus(HttpServletResponse.SC_NOT_MODIFIED);
}
}
} else if (method.equals(METHOD_HEAD)) {
long lastModified = getLastModified(req);
maybeSetLastModified(resp, lastModified);
doHead(req, resp);
} else if (method.equals(METHOD_POST)) {
doPost(req, resp);
} else if (method.equals(METHOD_PUT)) {
doPut(req, resp);
} else if (method.equals(METHOD_DELETE)) {
doDelete(req, resp);
} else if (method.equals(METHOD_OPTIONS)) {
doOptions(req,resp);
} else if (method.equals(METHOD_TRACE)) {
doTrace(req,resp);
} else {
//
// Note that this means NO servlet supports whatever
// method was requested, anywhere on this server.
//
String errMsg = lStrings.getString("http.method_not_implemented");
Object[] errArgs = new Object[1];
errArgs[0] = method;
errMsg = MessageFormat.format(errMsg, errArgs);
resp.sendError(HttpServletResponse.SC_NOT_IMPLEMENTED, errMsg);
}
}
在转换完Response和Request后,service会调用重载的service方法,此时则开始正式执行Get,Post等等.
为阀门, 为一个责任链模式
通过getNext()
获取到下一个阀门
实现类: