在连接器对请求信息进行解析, 封装为Request和Response, 然后通过适配器CoyoteAdapter的service()方法调用引擎中管道pipeline的第一个Valve, 开始对请求进行处理;
CoyoteAdapter#service实现:
@Override
public void service(org.apache.coyote.Request req, org.apache.coyote.Response res) throws Exception {
Request request = (Request) req.getNote(ADAPTER_NOTES);
Response response = (Response) res.getNote(ADAPTER_NOTES);
...
try {
// Parse and set Catalina and configuration specific
// request parameters
postParseSuccess = postParseRequest(req, request, res, response);
if (postParseSuccess) {
//check valves if we support async
request.setAsyncSupported(
connector.getService().getContainer().getPipeline().isAsyncSupported());
/**
* 调用StandardHost的pipeline对Request,Response进行处理
* StandardHostValve保存在pipeline的first属性中
* {@link org.apache.catalina.core.StandardEngineValve#invoke(Request, Response)}
*/
connector.getService().getContainer().getPipeline().getFirst().invoke(
request, response);
}
...
}
...
}
分析:
connector.getService() ==> StandardService实例
connector.getService().getContainer() ==> StandardEngine实例
connector.getService().getContainer().getPipeline() ==> StandardEngine.StandardPipeline实例
connector.getService().getContainer().getPipeline().getFirst() ==> StandardEngineValve实例
connector.getService().getContainer().getPipeline().getFirst().invoke( request, response)实现:
@Override
public final void invoke(Request request, Response response)
throws IOException, ServletException {
//选择用于此请求的Host
Host host = request.getHost();
if (host == null) {
response.sendError(HttpServletResponse.SC_BAD_REQUEST,sm.getString("standardEngine.noHost",request.getServerName()));
return;
}
if (request.isAsyncSupported()) {
request.setAsyncSupported(host.getPipeline().isAsyncSupported());
}
/**
* 要求Host处理此请求
* {@link AbstractAccessLogValve#invoke(org.apache.catalina.connector.Request, org.apache.catalina.connector.Response)}
*/
host.getPipeline().getFirst().invoke(request, response);
}
分析:
- 获取请求的主机实例
- 获取Host的管道信息, 对请求进行处理
AbstractAccessLogValve#invoke实现:
@Override
public void invoke(Request request, Response response) throws IOException,
ServletException {
if (tlsAttributeRequired) {
request.getAttribute(Globals.CERTIFICATES_ATTR);
}
/**
* 执行下一个Valve
* {@link ErrorReportValve#invoke(org.apache.catalina.connector.Request, org.apache.catalina.connector.Response)}
*/
getNext().invoke(request, response);
}
分析:
- 权限日志信息配置
- 执行下一个Valve
ErrorReportValve#invoke实现:
@Override
public void invoke(Request request, Response response) throws IOException, ServletException {
/**
* 执行下一个Valve
* {@link org.apache.catalina.core.StandardHostValve#invoke(Request, Response)}
*/
getNext().invoke(request, response);
if (response.isCommitted()) {
if (response.setErrorReported()) {
try {
response.flushBuffer();
} catch (Throwable t) {
ExceptionUtils.handleThrowable(t);
}
response.getCoyoteResponse().action(ActionCode.CLOSE_NOW,
request.getAttribute(RequestDispatcher.ERROR_EXCEPTION));
}
return;
}
Throwable throwable = (Throwable) request.getAttribute(RequestDispatcher.ERROR_EXCEPTION);
if (request.isAsync() && !request.isAsyncCompleting()) {
return;
}
if (throwable != null && !response.isError()) {
response.reset();
response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
}
response.setSuspended(false);
try {
report(request, response, throwable);
} catch (Throwable tt) {
ExceptionUtils.handleThrowable(tt);
}
}
分析:
- 执行下一个Valve
- 错误信息输出设置
StandardHostValve#invoke实现:
@Override
public final void invoke(Request request, Response response)throws IOException, ServletException {
Context context = request.getContext();
if (context == null) {
return;
}
if (request.isAsyncSupported()) {
request.setAsyncSupported(context.getPipeline().isAsyncSupported());
}
boolean asyncAtStart = request.isAsync();
try {
context.bind(Globals.IS_SECURITY_ENABLED, MY_CLASSLOADER);
if (!asyncAtStart && !context.fireRequestInitEvent(request.getRequest())) {
return;
}
try {
if (!response.isErrorReportRequired()) {
/**
* 调用StandardContext的pipeline对Request,Response进行处理
* StandardContextValve保存在pipeline的first属性中
* {@link StandardContextValve#invoke(Request, Response)}
*/
context.getPipeline().getFirst().invoke(request, response);
}
} catch (Throwable t) {
ExceptionUtils.handleThrowable(t);
container.getLogger().error("Exception Processing " + request.getRequestURI(), t);
if (!response.isErrorReportRequired()) {
request.setAttribute(RequestDispatcher.ERROR_EXCEPTION, t);
throwable(request, response, t);
}
}
response.setSuspended(false);
Throwable t = (Throwable) request.getAttribute(RequestDispatcher.ERROR_EXCEPTION);
if (!context.getState().isAvailable()) {
return;
}
if (response.isErrorReportRequired()) {
AtomicBoolean result = new AtomicBoolean(false);
response.getCoyoteResponse().action(ActionCode.IS_IO_ALLOWED, result);
if (result.get()) {
if (t != null) {
throwable(request, response, t);
} else {
status(request, response);
}
}
}
if (!request.isAsync() && !asyncAtStart) {
context.fireRequestDestroyEvent(request.getRequest());
}
} finally {
if (ACCESS_SESSION) {
request.getSession(false);
}
context.unbind(Globals.IS_SECURITY_ENABLED, MY_CLASSLOADER);
}
}
分析:
- 获取Context实例, 以及相关配置信息设置
- 获取Context的管道信息,对请求进行处理
StandardContextValve#invoke实现:
@Override
public final void invoke(Request request, Response response) throws IOException, ServletException {
// 禁止直接访问WEB-INF或META-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);
return;
}
// 选择用于此请求的包装器
Wrapper wrapper = request.getWrapper();
if (wrapper == null || wrapper.isUnavailable()) {
response.sendError(HttpServletResponse.SC_NOT_FOUND);
return;
}
// 确认请求
try {
response.sendAcknowledgement();
} catch (IOException ioe) {
container.getLogger().error(sm.getString(
"standardContextValve.acknowledgeException"), ioe);
request.setAttribute(RequestDispatcher.ERROR_EXCEPTION, ioe);
response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
return;
}
if (request.isAsyncSupported()) {
request.setAsyncSupported(wrapper.getPipeline().isAsyncSupported());
}
/**
* 调用StandardWrapper的pipeline对Request,Response进行处理
* StandardWrapperValve保存在pipeline的first属性中
* {@link StandardWrapperValve#invoke(Request, Response)}
*/
wrapper.getPipeline().getFirst().invoke(request, response);
}
分析:
- 禁止直接访问WEB-INF或META-INF下的资源
- 选择用于此请求的包装器Wrapper
- 确认请求
- 获取wrapper的管道信息, 对请求进行处理
StandardWrapperValve#invoke实现:
@Override
public final void invoke(Request request, Response response) throws IOException, ServletException {
...
/**
* 1.分配一个servlet实例以处理此请求
*/
try {
if (!unavailable) {
/**
* 获取一个Servlet实例
*/
servlet = wrapper.allocate();
}
} catch (UnavailableException e) {
...
}
MessageBytes requestPathMB = request.getRequestPathMB();
DispatcherType dispatcherType = DispatcherType.REQUEST;
if (request.getDispatcherType()==DispatcherType.ASYNC) dispatcherType = DispatcherType.ASYNC;
request.setAttribute(Globals.DISPATCHER_TYPE_ATTR,dispatcherType);
request.setAttribute(Globals.DISPATCHER_REQUEST_PATH_ATTR,requestPathMB);
/**
* 2.给当前请求创建一个Filter链
*/
ApplicationFilterChain filterChain = ApplicationFilterFactory.createFilterChain(request, wrapper, servlet);
/**
* 3.调用过滤器链, 在过滤器链的最后会调用servlet的service()方法
*/
try {
if ((servlet != null) && (filterChain != null)) {
// Swallow output if needed
if (context.getSwallowOutput()) {
try {
SystemLogHandler.startCapture();
if (request.isAsyncDispatching()) { //如果是异步请求
request.getAsyncContextInternal().doInternalDispatch();
} else {
filterChain.doFilter(request.getRequest(),response.getResponse());
}
} finally {
String log = SystemLogHandler.stopCapture();
if (log != null && log.length() > 0) {
context.getLogger().info(log);
}
}
} else {
if (request.isAsyncDispatching()) {
request.getAsyncContextInternal().doInternalDispatch();
} else {
/**
* 3.1 调用这个Filter链,Filter链中的最后一个Filter会调用Servlet
*/
filterChain.doFilter(request.getRequest(), response.getResponse());
}
}
}
}
...
}
// 如果存在过滤器链,则释放此请求的过滤器链
if (filterChain != null) {
filterChain.release();
}
// 取消分配已分配的servlet实例
try {
if (servlet != null) {
wrapper.deallocate(servlet);
}
} catch (Throwable e) {
ExceptionUtils.handleThrowable(e);
container.getLogger().error(sm.getString("standardWrapper.deallocateException",
wrapper.getName()), e);
if (throwable == null) {
throwable = e;
exception(request, response, e);
}
}
...
}
分析:
- 分配一个servlet实例以处理此请求
- 给当前请求创建一个Filter链
- 调用过滤器链, 在过滤器链的最后会调用servlet的service()方法
_1.StandardWrapper#allocate实现
@Override
public Servlet allocate() throws ServletException {
//如果此时正在卸载servlet,则抛出异常
if (unloading) {
throw new ServletException(sm.getString("standardWrapper.unloading", getName()));
}
boolean newInstance = false;
// If not SingleThreadedModel, return the same instance every time
if (!singleThreadModel) {
/**
* 如果实例未null或者还没有初始化完成, 则创建,以及初始化
*/
if (instance == null || !instanceInitialized) {
synchronized (this) {
if (instance == null) {
try {
if (log.isDebugEnabled()) {
log.debug("Allocating non-STM instance");
}
/**
* 加载Servlet
* 注意:(1)我们不知道Servlet是否实现SingleThreadModel,直到我们加载它。
* (2)此处调用loadServlet()方法加载Servlet是在接受到请求后,分配servlet处理请求时没有从缓存中获取到, 创建新的servlet实例后调用的
* 此处要与StandardContext中监听事件中的调用的loadServlet()方法区分
*/
instance = loadServlet();
newInstance = true;
if (!singleThreadModel) {
// For non-STM, increment here to prevent a race
// condition with unload. Bug 43683, test case
// #3
countAllocated.incrementAndGet();
}
} catch (ServletException e) {
throw e;
} catch (Throwable e) {
ExceptionUtils.handleThrowable(e);
throw new ServletException(sm.getString("standardWrapper.allocate"), e);
}
}
if (!instanceInitialized) {
initServlet(instance);
}
}
}
/**
* 将新创建的servlet实例放入实例池中
*/
if (singleThreadModel) {
if (newInstance) {
// Have to do this outside of the sync above to prevent a
// possible deadlock
synchronized (instancePool) {
instancePool.push(instance);
nInstances++;
}
}
} else {
/**
* 如果没有创建新servlet实例, 则直接返回获取到的实例
*/
if (log.isTraceEnabled()) {
log.trace(" Returning non-STM instance");
}
// For new instances, count will have been incremented at the
// time of creation
if (!newInstance) {
countAllocated.incrementAndGet();
}
return instance;
}
}
synchronized (instancePool) {
while (countAllocated.get() >= nInstances) {
// Allocate a new instance if possible, or else wait
if (nInstances < maxInstances) {
try {
instancePool.push(loadServlet());
nInstances++;
} catch (ServletException e) {
throw e;
} catch (Throwable e) {
ExceptionUtils.handleThrowable(e);
throw new ServletException(sm.getString("standardWrapper.allocate"), e);
}
} else {
try {
instancePool.wait();
} catch (InterruptedException e) {
// Ignore
}
}
}
if (log.isTraceEnabled()) {
log.trace(" Returning allocated STM instance");
}
countAllocated.incrementAndGet();
/**
* 从实例池中返回一个servlet实例
*/
return instancePool.pop();
}
}
_3. ApplicationFilterChain#doFilter实现:
@Override
public void doFilter(ServletRequest request, ServletResponse response)throws IOException, ServletException {
if( Globals.IS_SECURITY_ENABLED ) {
...
} else {
/**
* 执行过滤器链
*/
internalDoFilter(request,response);
}
}
private void internalDoFilter(ServletRequest request,.ServletResponse response)throws IOException, ServletException {
/**
* 1. 如果存在过滤器, 则执行该过滤器
*/
if (pos < n) {
ApplicationFilterConfig filterConfig = filters[pos++];
try {
Filter filter = filterConfig.getFilter();
if (request.isAsyncSupported() && "false".equalsIgnoreCase(filterConfig.getFilterDef().getAsyncSupported())) {
request.setAttribute(Globals.ASYNC_SUPPORTED_ATTR, Boolean.FALSE);
}
if( Globals.IS_SECURITY_ENABLED ) {
final ServletRequest req = request;
final ServletResponse res = response;
Principal principal =
((HttpServletRequest) req).getUserPrincipal();
Object[] args = new Object[]{req, res, this};
SecurityUtil.doAsPrivilege ("doFilter", filter, classType, args, principal);
} else {
filter.doFilter(request, response, this);
}
}
...
return;
}
/**
* 2. 调用链执行完成之后, 调用servlet的service()方法
*/
try {
if (ApplicationDispatcher.WRAP_SAME_OBJECT) {
lastServicedRequest.set(request);
lastServicedResponse.set(response);
}
if (request.isAsyncSupported() && !servletSupportsAsync) {
request.setAttribute(Globals.ASYNC_SUPPORTED_ATTR,Boolean.FALSE);
}
// Use potentially wrapped request from this point
if ((request instanceof HttpServletRequest) && (response instanceof HttpServletResponse) && Globals.IS_SECURITY_ENABLED ) {
final ServletRequest req = request;
final ServletResponse res = response;
Principal principal =((HttpServletRequest) req).getUserPrincipal();
Object[] args = new Object[]{req, res};
SecurityUtil.doAsPrivilege("service",servlet,classTypeUsedInService,args,principal);
} else {
/**
* 调用servlet的service方法;
*/
servlet.service(request, response);
}
}
...
}
分析:
- 如果存在过滤器, 则执行该过滤器
- 调用链执行完成之后, 调用servlet的service()方法
HttpServlet#service(javax.servlet.ServletRequest, javax.servlet.ServletResponse)实现:
@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) {
doGet(req, resp);
} else {
long ifModifiedSince;
try {
ifModifiedSince = req.getDateHeader(HEADER_IFMODSINCE);
} catch (IllegalArgumentException iae) {
ifModifiedSince = -1;
}
if (ifModifiedSince < (lastModified / 1000 * 1000)) {
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 {
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);
}
}
至此, Http请求过程解析中容器的解析过程分析完成;
NIO模型下Tomcat中Http请求解析流程图: