首先上一张图片了解一下整体的流程:
1.Tomcat启动后会有后台会有一个线程 一直监听对应的启动窗口(默认8080)。
2.请求到达Tomcat后 监听线程捕获到请求;
请求首先被Acceptor监听到。Acceptor实现了Runnable接口,在Tomcat启动后就一直在后台运行run方法。run方法中会调用endpoint.setSocketOptions()方法。
NioEndpoint.setSocketOptions(SocketChannel socket)
protected boolean setSocketOptions(SocketChannel socket) {
NioSocketWrapper socketWrapper = null;
try {
// 根据 socket 封装处理生成 socketWrapper
...
// 会把 调用poller的 register 方法,把 socketWrapper 交给 poller
poller.register(socketWrapper);
return true;
} catch (Throwable t) {
// ...异常处理
}
// 返回 boolean 类型,如果为 false 则通知accept关闭,关闭socket
return false;
}
接下来查看 Poller.register()方法(Poller是NioEndpoint的内部类)
// 向Poller注册一个新创建的套接字(socketWrapper)
public void register(final NioSocketWrapper socketWrapper) {
socketWrapper.interestOps(SelectionKey.OP_READ);//this is what OP_REGISTER turns into.
PollerEvent event = null;
if (eventCache != null) {
// 先从缓存中取
event = eventCache.pop();
}
if (event == null) {
// 如果为空,根据socketWrapper创建一个新的事件,实际上new方法 也是调用了reset方法
event = new PollerEvent(socketWrapper, OP_REGISTER);
} else {
// 如果不为空,则将event重置,并将socketWrapper设置进去
event.reset(socketWrapper, OP_REGISTER);
}
// 注意这一句,将创建好的event事件添加到当前队列中
addEvent(event);
}
上面可以看到,每个请求进来之后,会通过 register 方法创建一个 PollerEvent 对象并添加到当前的 SynchronizedQueue events 队列中。
接下来看 Poller的run()方法,Poller 在Tomcat启动时在startInternal()方法调用的时候创建并一直在后台启动着。
public void run() {
// 一直循环直到调用destroy()方法
while (true) {
boolean hasEvents = false;
try {
if (!close) {
hasEvents = events();
...
}
...
} catch (Throwable x) {
...
}
Iterator<SelectionKey> iterator =
keyCount > 0 ? selector.selectedKeys().iterator() : null;
// 遍历所有的键,找到key之后调用processKey
while (iterator != null && iterator.hasNext()) {
SelectionKey sk = iterator.next();
iterator.remove();
NioSocketWrapper socketWrapper = (NioSocketWrapper) sk.attachment();
// 如果另一个线程调用了 cancelledKey(),则attachment可能为空
if (socketWrapper != null) {
processKey(sk, socketWrapper);
}
}
...
}
getStopLatch().countDown();
}
processKey() 会根据配置的Executer调用SocketProcessorBase的 run() 方法。
接下来看SocketProcessorBase的run()方法最终会调用doRun()方法,SocketProcessorBase是一个抽象类,doRun()是一个抽象方法,所以实际调用的是SocketProcessor的doRun()方法。SocketProcessor是SocketProcessorBase的子类,SocketProcessor是NioEndpoint的内部类。在doRun()方法中会有调用 getHandler().process() ,接下来就是进入到AbstractProtocol.ConnectionHandler.process()
调用链:
Acceptor.run() -> endpoint.setSocketOptions() -> NioEndpoint.setSocketOptions() -> poller.register() -> addEvent () 将PollerEvent 对象并添加到Poller的events 队列中,Poller的run方法会判断队列中是否有event然后调用processKey()
Poller.run() -> processKey() -> SocketProcessorBase.run() -> doRun() ->NioEndpoint.SocketProcessor.doRun() -> getHandler() ->
AbstractProtocol.ConnectionHandler.process()
SocketProcessorBase 实现了Runnable接口
Connector 里面有一个属性:ProtocolHandler(是一个接口)
AbstractProtocol实现了 ProtocolHandler 接口
AbstractEndpoint 里面有一个属性: Handler(是一个内部接口)
AbstractProtocol有一个内部类:ConnectionHandler 实现了 Handler接口
SocketProcessorBase是一个抽象类,并且有一个抽象方法 doRun()
NioEndpoint中有一个内部类 SocketProcessor并且继承了SocketProcessorBase,实现了doRun()方法。
NioEndpoint继承了AbstractEndpoint,AbstractEndpoint有getHandler()方法并且返回的是Handler类型的,但是NioEndpoint没有getHandler()方法。
所以在NioEndpoint.SocketProcessor.doRun() 中调用getHandler()实际调用的父类的方法,同时返回的是实现了父类中Handle接口的对象。
因此getHandle()方法返回的就是AbstractProtocol.ConnectionHandler
ConnectionHandler.process()
protected static class ConnectionHandler<S> implements AbstractEndpoint.Handler<S> {
...
@Override
public SocketState process(SocketWrapperBase<S> wrapper, SocketEvent status) {
//找到对应的processor
...
processor.setSslSupport(wrapper.getSslSupport(getProtocol().getClientCertProvider()));
// Associate the processor with the connection
wrapper.setCurrentProcessor(processor);
SocketState state = SocketState.CLOSED;
do {
state = processor.process(wrapper, status);
// 后续是对处理结果的一些处理
...
} while ( state == SocketState.UPGRADING);
...
}
...
}
从上图可以看到最后处理socket的processor是 Http11Processor
继续往下走,我们发现代码是进入到AbstractProcessorLight.process() ,这应该是一个模板方法,Http11Processor是没有process这个方法的,但是Http11Processor继承了AbstractProcessorLight,所以直接进入了AbstractProcessorLight的process方法。
AbstractProcessorLight.process(SocketWrapperBase<?> socketWrapper, SocketEvent status)
public SocketState process(SocketWrapperBase<?> socketWrapper, SocketEvent status)
throws IOException {
// socket状态
SocketState state = SocketState.CLOSED;
// 调度类型
Iterator<DispatchType> dispatches = null;
do {
// 根据不同的socket状态进行的一些操作
if (dispatches != null) {
..
} else if (status == SocketEvent.OPEN_READ) {
// 正常情况请求会进到这一步,调用了service方法,但是AbstractProcessorLight没有service方法,所以实际调用的是子类的service方法
state = service(socketWrapper);
} else if (status == SocketEvent.CONNECT_FAIL) {
// 如果失败,则添加日志
logAccess(socketWrapper);
} else {
// 如果传入的 SocketEvent 与 Processor 当前状态不一致,则默认关闭套接字
state = SocketState.CLOSED;
}
...
} while (state == SocketState.ASYNC_END || dispatches != null && state != SocketState.CLOSED);
return state;
}
处理之前经过一个AuthenticatorBase
实际是调用进入到DispatcherServlet,先看下一下DispatcherServlet的UML图:
DispatcherServlet、FrameworkServlet、HttpServletBean没有service(ServletRequest req, ServletResponse res)方法,注意req、res的参数类型。
FrameworkServlet的service方法是:service(HttpServletRequest request, HttpServletResponse response),所以进入到 HttpServlet.service(ServletRequest req, ServletResponse res)方法。
HttpServlet.service(ServletRequest req, ServletResponse res)
@Override
public void service(ServletRequest req, ServletResponse res)
throws ServletException, IOException
{
HttpServletRequest request;
HttpServletResponse response;
// 判断 req 和 res 是否是 HttpServletRequest 、HttpServletResponse 类型的对象
if (!(req instanceof HttpServletRequest &&
res instanceof HttpServletResponse)) {
throw new ServletException("non-HTTP request or response");
}
// 类型转换 HttpServletRequest和HttpServletResponse是两个接口,分别继承了ServletRequest、ServletResponse
request = (HttpServletRequest) req;
response = (HttpServletResponse) res;
// 调用本类的service方法,而且上面对req、res进行了类型转换,所以下一步进入到的是FrameworkServlet.service(HttpServletRequest request, HttpServletResponse response)
service(request, response);
}
FrameworkServlet.service(HttpServletRequest request, HttpServletResponse response)
protected void service(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// 获取方法类型: GTE、POST、PUT......
HttpMethod httpMethod = HttpMethod.resolve(request.getMethod());
if (httpMethod == HttpMethod.PATCH || httpMethod == null) {
processRequest(request, response);
} else {
// 调用父类的service(HttpServletRequest request, HttpServletResponse response),HttpServletBean没有该方法,故进入到HttpServlet.service(HttpServletRequest req, HttpServletResponse resp)
super.service(request, response);
}
}
HttpServlet.service(HttpServletRequest req, HttpServletResponse resp)
protected void service(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException
{
// 获得方法类型: GET、POST...
String method = req.getMethod();
if (method.equals(METHOD_GET)) {
// ???
long lastModified = getLastModified(req);
if (lastModified == -1) {
// 执行doGet方法,代码执行到这里实际上当前对象this一直是DispatcherServlet的类型,所以doGet还是优先去找DispatcherServlet中的方法,找不到再一级一级向上找,这里实际会进入到FrameworkServlet.doGet(HttpServletRequest request, HttpServletResponse response)
doGet(req, resp);
} else {
...
}
} else if (method.equals(METHOD_POST)) {
doPost(req, resp);
}
//根据同的方法类型做执行对应的逻辑
...
}
FrameworkServlet.doGet(HttpServletRequest request, HttpServletResponse response)
protected final void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
processRequest(request, response);
}
protected final void processRequest(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
...
try {
// 主要就这一行代码,此时才是真正执行到 DispatcherServlet.doService(HttpServletRequest request, HttpServletResponse response)
doService(request, response);
} catch (ServletException | IOException ex) {
...
}
}
DispatcherServlet.doService(HttpServletRequest request, HttpServletResponse response)
protected void doService(HttpServletRequest request, HttpServletResponse response) throws Exception {
...
try {
// 核心代码就这一行
doDispatch(request, response);
}
...
}
protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
HttpServletRequest processedRequest = request;
HandlerExecutionChain mappedHandler = null;
boolean multipartRequestParsed = false;
WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);
try {
ModelAndView mv = null;
Exception dispatchException = null;
try {
processedRequest = checkMultipart(request);
multipartRequestParsed = (processedRequest != request);
// 确定当前请求的Handler
mappedHandler = getHandler(processedRequest);
...
// 实际上调用handler
mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
if (asyncManager.isConcurrentHandlingStarted()) {
return;
}
applyDefaultViewName(processedRequest, mv);
mappedHandler.applyPostHandle(processedRequest, response, mv);
}
...
processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);
}
...
}
// 返回此请求的 HandlerExecutionChain。 按顺序尝试所有处理程序映射
protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
if (this.handlerMappings != null) {
for (HandlerMapping mapping : this.handlerMappings) {
HandlerExecutionChain handler = mapping.getHandler(request);
if (handler != null) {
return handler;
}
}
}
return null;
}
找到对应的handler后,handler负责处理请求,最终实际就是使用反射调用业务代码的方法,将请求交由业务逻辑处理,adapter根据请求返回确定对应的视图或者页面。
ServletInvocableHandlerMethod.invokeAndHandle()
public void invokeAndHandle(ServletWebRequest webRequest, ModelAndViewContainer mavContainer,
Object... providedArgs) throws Exception {
// 拿到返回值
Object returnValue = invokeForRequest(webRequest, mavContainer, providedArgs);
setResponseStatus(webRequest);
...
try {
// 根据返回值,继续处理接下来的流程
this.returnValueHandlers.handleReturnValue(
returnValue, getReturnValueType(returnValue), mavContainer, webRequest);
}...
}
InvocableHandlerMethod.invokeForRequest()
public Object invokeForRequest(NativeWebRequest request, @Nullable ModelAndViewContainer mavContainer, Object... providedArgs) throws Exception {
...
return doInvoke(args);
}
protected Object doInvoke(Object... args) throws Exception {
ReflectionUtils.makeAccessible(getBridgedMethod());
try {
// 主要就是一行,getBean通过反射获得对象,并执行反射执行对应的方法,最后进入到业务代码
return getBridgedMethod().invoke(getBean(), args);
}
...
}