新西兰服务器

Tomcat9如何实现请求处理


Tomcat9如何实现请求处理

发布时间:2021-12-11 15:05:09 来源:高防服务器网 阅读:93 作者:小新 栏目:编程语言

这篇文章给大家分享的是有关Tomcat9如何实现请求处理的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。

请求处理

Tomcat对于HTTP请求,会由Connector监听的端口,通过线程池的处理进行多线程的处理。
此线程池默认的最小线程数minSpareThreads等于10,最大线程数maxThreads等于200,我们可以在server.xml的Connector配置中调整它们的大小。
之后,采用责任链模式,通过容器的管道对请求进行处理,最终调用用户开发的Filter和Servlet。

源码分析

org.apache.catalina.connector.Connector
 public Connector(String protocol) {          boolean aprConnector = AprLifecycleListener.isAprAvailable() &&                  AprLifecycleListener.getUseAprConnector();          if ("HTTP/1.1".equals(protocol) || protocol == null) {              if (aprConnector) {                  protocolHandlerClassName = "org.apache.coyote.http11.Http11AprProtocol";              } else {                  protocolHandlerClassName = "org.apache.coyote.http11.Http11NioProtocol";              }          } else if ("AJP/1.3".equals(protocol)) {              if (aprConnector) {                  protocolHandlerClassName = "org.apache.coyote.ajp.AjpAprProtocol";              } else {                  protocolHandlerClassName = "org.apache.coyote.ajp.AjpNioProtocol";              }          } else {              protocolHandlerClassName = protocol;          }          // Instantiate protocol handler          ProtocolHandler p = null;          try {              Class<?> clazz = Class.forName(protocolHandlerClassName);              p = (ProtocolHandler) clazz.getConstructor().newInstance();          } catch (Exception e) {              log.error(sm.getString(                      "coyoteConnector.protocolHandlerInstantiationFailed"), e);          } finally {              this.protocolHandler = p;          }          // Default for Connector depends on this system property          setThrowOnFailure(Boolean.getBoolean("org.apache.catalina.startup.EXIT_ON_INIT_FAILURE"));      }

在Connector的构造方法中,会根据配置的不同协议,创建不同协议处理类,Tomcat9中默认的配置为protocol=”HTTP/1.1”,对应的类为Http11NioProtocol

org.apache.coyote.http11.Http11NioProtocol
public Http11NioProtocol() {          super(new NioEndpoint());      }

Http11NioProtocol的构造方中,会创建NioEndpoint,NioEndpoint会处理socket的接口以及请求的调用。

org.apache.tomcat.util.net.NioEndpoint
@Override      public void startInternal() throws Exception {          if (!running) {              running = true;              paused = false;              if (socketProperties.getProcessorCache() != 0) {                  processorCache = new SynchronizedStack<>(SynchronizedStack.DEFAULT_SIZE,                          socketProperties.getProcessorCache());              }              if (socketProperties.getEventCache() != 0) {                  eventCache = new SynchronizedStack<>(SynchronizedStack.DEFAULT_SIZE,                          socketProperties.getEventCache());              }              if (socketProperties.getBufferPool() != 0) {                  nioChannels = new SynchronizedStack<>(SynchronizedStack.DEFAULT_SIZE,                          socketProperties.getBufferPool());              }              // Create worker collection              if (getExecutor() == null) {                  createExecutor();              }              initializeConnectionLatch();              // Start poller thread              poller = new Poller();              Thread pollerThread = new Thread(poller, getName() + "-ClientPoller");              pollerThread.setPriority(threadPriority);              pollerThread.setDaemon(true);              pollerThread.start();              startAcceptorThread();          }      }      protected void startAcceptorThread() {          acceptor = new Acceptor<>(this);          String threadName = getName() + "-Acceptor";          acceptor.setThreadName(threadName);          Thread t = new Thread(acceptor, threadName);          t.setPriority(getAcceptorThreadPriority());          t.setDaemon(getDaemon());          t.start();      }

NioEndpoint的startInternal方法中会启动Poller线程和Acceptor线程

org.apache.tomcat.util.net.Acceptor
@Override      public void run() {          int errorDelay = 0;          // Loop until we receive a shutdown command          while (endpoint.isRunning()) {              // Loop if endpoint is paused              while (endpoint.isPaused() && endpoint.isRunning()) {                  state = AcceptorState.PAUSED;                  try {                      Thread.sleep(50);                  } catch (InterruptedException e) {                      // Ignore                  }              }              if (!endpoint.isRunning()) {                  break;              }              state = AcceptorState.RUNNING;              try {                  //if we have reached max connections, wait                  endpoint.countUpOrAwaitConnection();                  // Endpoint might have been paused while waiting for latch                  // If that is the case, don't accept new connections                  if (endpoint.isPaused()) {                      continue;                  }                  U socket = null;                  try {                      // Accept the next incoming connection from the server                      // socket                      socket = endpoint.serverSocketAccept();                  } catch (Exception ioe) {                      // We didn't get a socket                      endpoint.countDownConnection();                      if (endpoint.isRunning()) {                          // Introduce delay if necessary                          errorDelay = handleExceptionWithDelay(errorDelay);                          // re-throw                          throw ioe;                      } else {                          break;                      }                  }                  // Successful accept, reset the error delay                  errorDelay = 0;                  // Configure the socket                  if (endpoint.isRunning() && !endpoint.isPaused()) {                      // setSocketOptions() will hand the socket off to                      // an appropriate processor if successful                      if (!endpoint.setSocketOptions(socket)) {                          endpoint.closeSocket(socket);                      }                  } else {                      endpoint.destroySocket(socket);                  }              } catch (Throwable t) {                  ExceptionUtils.handleThrowable(t);                  String msg = sm.getString("endpoint.accept.fail");                  // APR specific.                  // Could push this down but not sure it is worth the trouble.                  if (t instanceof Error) {                      Error e = (Error) t;                      if (e.getError() == 233) {                          // Not an error on HP-UX so log as a warning                          // so it can be filtered out on that platform                          // See bug 50273                          log.warn(msg, t);                      } else {                          log.error(msg, t);                      }                  } else {                          log.error(msg, t);                  }              }          }          state = AcceptorState.ENDED;      }

Acceptor的run方法中,endpoint.serverSocketAccept()会调用NioEndpoint的具体实现来开启对应端口的TCP监听,当端口有请求时,则endpoint.setSocketOptions(socket)进行具体处理

org.apache.tomcat.util.net.NioEndpoint.setSocketOptions
protected boolean setSocketOptions(SocketChannel socket) {          // Process the connection          try {              // Disable blocking, polling will be used              socket.configureBlocking(false);              Socket sock = socket.socket();              socketProperties.setProperties(sock);              NioChannel channel = null;              if (nioChannels != null) {                  channel = nioChannels.pop();              }              if (channel == null) {                  SocketBufferHandler bufhandler = new SocketBufferHandler(                          socketProperties.getAppReadBufSize(),                          socketProperties.getAppWriteBufSize(),                          socketProperties.getDirectBuffer());                  if (isSSLEnabled()) {                      channel = new SecureNioChannel(socket, bufhandler, selectorPool, this);                  } else {                      channel = new NioChannel(socket, bufhandler);                  }              } else {                  channel.setIOChannel(socket);                  channel.reset();              }              NioSocketWrapper socketWrapper = new NioSocketWrapper(channel, this);              channel.setSocketWrapper(socketWrapper);              socketWrapper.setReadTimeout(getConnectionTimeout());              socketWrapper.setWriteTimeout(getConnectionTimeout());              socketWrapper.setKeepAliveLeft(NioEndpoint.this.getMaxKeepAliveRequests());              socketWrapper.setSecure(isSSLEnabled());              poller.register(channel, socketWrapper);              return true;          } catch (Throwable t) {              ExceptionUtils.handleThrowable(t);              try {                  log.error(sm.getString("endpoint.socketOptionsError"), t);              } catch (Throwable tt) {                  ExceptionUtils.handleThrowable(tt);              }          }          // Tell to close the socket          return false;      }

在setSocketOptions方法中,主要逻辑为将socket请求放入Poller的队列中,在之前启动的Poller线程会不断的从队列中获取请求。

org.apache.tomcat.util.net.NioEndpoint$Poller
@Override          public void run() {              // Loop until destroy() is called              while (true) {                  boolean hasEvents = false;                  try {                      if (!close) {                          hasEvents = events();                          if (wakeupCounter.getAndSet(-1) > 0) {                              // If we are here, means we have other stuff to do                              // Do a non blocking select                              keyCount = selector.selectNow();                          } else {                              keyCount = selector.select(selectorTimeout);                          }                          wakeupCounter.set(0);                      }                      if (close) {                          events();                          timeout(0, false);                          try {                              selector.close();                          } catch (IOException ioe) {                              log.error(sm.getString("endpoint.nio.selectorCloseFail"), ioe);                          }                          break;                      }                  } catch (Throwable x) {                      ExceptionUtils.handleThrowable(x);                      log.error(sm.getString("endpoint.nio.selectorLoopError"), x);                      continue;                  }                  // Either we timed out or we woke up, process events first                  if (keyCount == 0) {                      hasEvents = (hasEvents | events());                  }                  Iterator<SelectionKey> iterator =                      keyCount > 0 ? selector.selectedKeys().iterator() : null;                  // Walk through the collection of ready keys and dispatch                  // any active event.                  while (iterator != null && iterator.hasNext()) {                      SelectionKey sk = iterator.next();                      NioSocketWrapper socketWrapper = (NioSocketWrapper) sk.attachment();                      // Attachment may be null if another thread has called                      // cancelledKey()                      if (socketWrapper == null) {                          iterator.remove();                      } else {                          iterator.remove();                          processKey(sk, socketWrapper);                      }                  }                  // Process timeouts                  timeout(keyCount,hasEvents);              }              getStopLatch().countDown();          }          protected void processKey(SelectionKey sk, NioSocketWrapper socketWrapper) {              try {                  if (close) {                      cancelledKey(sk, socketWrapper);                  } else if (sk.isValid() && socketWrapper != null) {                      if (sk.isReadable() || sk.isWritable()) {                          if (socketWrapper.getSendfileData() != null) {                              processSendfile(sk, socketWrapper, false);                          } else {                              unreg(sk, socketWrapper, sk.readyOps());                              boolean closeSocket = false;                              // Read goes before write                              if (sk.isReadable()) {                                  if (socketWrapper.readOperation != null) {                                      if (!socketWrapper.readOperation.process()) {                                          closeSocket = true;                                      }                                  } else if (!processSocket(socketWrapper, SocketEvent.OPEN_READ, true)) {                                      closeSocket = true;                                  }                              }                              if (!closeSocket && sk.isWritable()) {                                  if (socketWrapper.writeOperation != null) {                                      if (!socketWrapper.writeOperation.process()) {                                          closeSocket = true;                                      }                                  } else if (!processSocket(socketWrapper, SocketEvent.OPEN_WRITE, true)) {                                      closeSocket = true;                                  }                              }                              if (closeSocket) {                                  cancelledKey(sk, socketWrapper);                              }                          }                      }                  } else {                      // Invalid key                      cancelledKey(sk, socketWrapper);                  }              } catch (CancelledKeyException ckx) {                  cancelledKey(sk, socketWrapper);              } catch (Throwable t) {                  ExceptionUtils.handleThrowable(t);                  log.error(sm.getString("endpoint.nio.keyProcessingError"), t);              }          }      protected void processKey(SelectionKey sk, NioSocketWrapper socketWrapper) {              try {                  if (close) {                      cancelledKey(sk, socketWrapper);                  } else if (sk.isValid() && socketWrapper != null) {                      if (sk.isReadable() || sk.isWritable()) {                          if (socketWrapper.getSendfileData() != null) {                              processSendfile(sk, socketWrapper, false);                          } else {                              unreg(sk, socketWrapper, sk.readyOps());                              boolean closeSocket = false;                              // Read goes before write                              if (sk.isReadable()) {                                  if (socketWrapper.readOperation != null) {                                      if (!socketWrapper.readOperation.process()) {                                          closeSocket = true;                                      }                                  } else if (!processSocket(socketWrapper, SocketEvent.OPEN_READ, true)) {                                      closeSocket = true;                                  }                              }                              if (!closeSocket && sk.isWritable()) {                                  if (socketWrapper.writeOperation != null) {                                      if (!socketWrapper.writeOperation.process()) {                                          closeSocket = true;                                      }                                  } else if (!processSocket(socketWrapper, SocketEvent.OPEN_WRITE, true)) {                                      closeSocket = true;                                  }                              }                              if (closeSocket) {                                  cancelledKey(sk, socketWrapper);                              }                          }                      }                  } else {                      // Invalid key                      cancelledKey(sk, socketWrapper);                  }              } catch (CancelledKeyException ckx) {                  cancelledKey(sk, socketWrapper);              } catch (Throwable t) {                  ExceptionUtils.handleThrowable(t);                  log.error(sm.getString("endpoint.nio.keyProcessingError"), t);              }          }

在run方法中,会轮询Poller队列中的请求,并调用processKey方法进行处理,并最终调用processSocket方法

public boolean processSocket(SocketWrapperBase<S> socketWrapper,              SocketEvent event, boolean dispatch) {          try {              if (socketWrapper == null) {                  return false;              }              SocketProcessorBase<S> sc = null;              if (processorCache != null) {                  sc = processorCache.pop();              }              if (sc == null) {                  sc = createSocketProcessor(socketWrapper, event);              } else {                  sc.reset(socketWrapper, event);              }              Executor executor = getExecutor();              if (dispatch && executor != null) {                  executor.execute(sc);              } else {                  sc.run();              }          } catch (RejectedExecutionException ree) {              getLog().warn(sm.getString("endpoint.executor.fail", socketWrapper) , ree);              return false;          } catch (Throwable t) {              ExceptionUtils.handleThrowable(t);              // This means we got an OOM or similar creating a thread, or that              // the pool and its queue are full              getLog().error(sm.getString("endpoint.process.fail"), t);              return false;          }          return true;      }

在processSocket会将请求封装为SocketProcessor对象,并多线程进行处理。

SocketProcessor
protected class SocketProcessor extends SocketProcessorBase<NioChannel> {          public SocketProcessor(SocketWrapperBase<NioChannel> socketWrapper, SocketEvent event) {              super(socketWrapper, event);          }          @Override          protected void doRun() {              NioChannel socket = socketWrapper.getSocket();              SelectionKey key = socket.getIOChannel().keyFor(socket.getSocketWrapper().getPoller().getSelector());              Poller poller = NioEndpoint.this.poller;              if (poller == null) {                  socketWrapper.close();                  return;              }              try {                  int handshake = -1;                  try {                      if (key != null) {                          if (socket.isHandshakeComplete()) {                              // No TLS handshaking required. Let the handler                              // process this socket / event combination.                              handshake = 0;                          } else if (event == SocketEvent.STOP || event == SocketEvent.DISCONNECT ||                                  event == SocketEvent.ERROR) {                              // Unable to complete the TLS handshake. Treat it as                              // if the handshake failed.                              handshake = -1;                          } else {                              handshake = socket.handshake(key.isReadable(), key.isWritable());                              // The handshake process reads/writes from/to the                              // socket. status may therefore be OPEN_WRITE once                              // the handshake completes. However, the handshake                              // happens when the socket is opened so the status                              // must always be OPEN_READ after it completes. It                              // is OK to always set this as it is only used if                              // the handshake completes.                              event = SocketEvent.OPEN_READ;                          }                      }                  } catch (IOException x) {                      handshake = -1;                      if (log.isDebugEnabled()) log.debug("Error during SSL handshake",x);                  } catch (CancelledKeyException ckx) {                      handshake = -1;                  }                  if (handshake == 0) {                      SocketState state = SocketState.OPEN;                      // Process the request from this socket                      if (event == null) {                          state = getHandler().process(socketWrapper, SocketEvent.OPEN_READ);                      } else {                          state = getHandler().process(socketWrapper, event);                      }                      if (state == SocketState.CLOSED) {                          poller.cancelledKey(key, socketWrapper);                      }                  } else if (handshake == -1 ) {                      getHandler().process(socketWrapper, SocketEvent.CONNECT_FAIL);                      poller.cancelledKey(key, socketWrapper);                  } else if (handshake == SelectionKey.OP_READ){                      socketWrapper.registerReadInterest();                  } else if (handshake == SelectionKey.OP_WRITE){                      socketWrapper.registerWriteInterest();                  }              } catch (CancelledKeyException cx) {                  poller.cancelledKey(key, socketWrapper);              } catch (VirtualMachineError vme) {                  ExceptionUtils.handleThrowable(vme);              } catch (Throwable t) {                  log.error(sm.getString("endpoint.processing.fail"), t);                  poller.cancelledKey(key, socketWrapper);              } finally {                  socketWrapper = null;                  event = null;                  //return to cache                  if (running && !paused && processorCache != null) {                      processorCache.push(this);                  }              }          }      }  public SocketState process(SocketWrapperBase<S> wrapper, SocketEvent status) {  ...省略其他代码...  if (processor == null) {                      processor = getProtocol().createProcessor();                      register(processor);                  }  ...省略其他代码...  state = processor.process(wrapper, status);  }   protected Processor createProcessor() {          Http11Processor processor = new Http11Processor(this, adapter);          return processor;      }

在SocketProcessor中,多线程run方法会调用dorun方法,其中会调用getHandler().process()方法来进行后续处理,在process方法中会实例化processor,并调用processor.process,HTTP/1.1协议对应的processor为Http11Processor
在Http11Processor中,会对HTTP请求的头部信息进行解析,此处代码较多,读者可自行查看Http11Processor.service方法。
解析完请求头后,调用CoyoteAdapter.service方法

CoyoteAdapter
 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);          if (request == null) {              // Create objects              request = connector.createRequest();              request.setCoyoteRequest(req);              response = connector.createResponse();              response.setCoyoteResponse(res);              // Link objects              request.setResponse(response);              response.setRequest(request);              // Set as notes              req.setNote(ADAPTER_NOTES, request);              res.setNote(ADAPTER_NOTES, response);              // Set query string encoding              req.getParameters().setQueryStringCharset(connector.getURICharset());          }          if (connector.getXpoweredBy()) {              response.addHeader("X-Powered-By", POWERED_BY);          }          boolean async = false;          boolean postParseSuccess = false;          req.getRequestProcessor().setWorkerThreadName(THREAD_NAME.get());          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());                  // Calling the container                  connector.getService().getContainer().getPipeline().getFirst().invoke(                          request, response); //责任链模式,调用处理管道              }  ...省略其他代码...      }

在CoyoteAdapter的service方法中

  • postParseRequest:生成request和response对象,其中会请求头信息匹配出相应的

  • connector.getService().getContainer().getPipeline().getFirst().invoke(request, response)会调用Service下的容器的管道,即从StandardEngine开始之后所有的所有容器,以责任链设计模式进行调用,具体参照第二章节的模块图。

org.apache.catalina.core.StandardWrapperValve
public final void invoke(Request request, Response response)          throws IOException, ServletException {  ...省略其他代码...                  servlet = wrapper.allocate(); //生成servlet          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()); //调用filter,在filter结束后调用servlet                          }                      } finally {                          String log = SystemLogHandler.stopCapture();                          if (log != null && log.length() > 0) {                              context.getLogger().info(log);                          }                      }                  } else {                      if (request.isAsyncDispatching()) {                          request.getAsyncContextInternal().doInternalDispatch();                      } else {                          filterChain.doFilter                              (request.getRequest(), response.getResponse());                      }                  }              }          }  ...省略其他代码...

在管道最后的处理 StandardWrapperValve中,invoke方法会对匹配到的Servlet进行初始化和调用,其中servlet的调用会在过滤器链的最后进行调用

org.apache.catalina.core.ApplicationFilterChain
public void doFilter(ServletRequest request, ServletResponse response)          throws IOException, ServletException {          if( Globals.IS_SECURITY_ENABLED ) {              final ServletRequest req = request;              final ServletResponse res = response;              try {                  java.security.AccessController.doPrivileged(                      new java.security.PrivilegedExceptionAction<Void>() {                          @Override                          public Void run()                              throws ServletException, IOException {                              internalDoFilter(req,res);                              return null;                          }                      }                  );              } catch( PrivilegedActionException pe) {                  Exception e = pe.getException();                  if (e instanceof ServletException)                      throw (ServletException) e;                  else if (e instanceof IOException)                      throw (IOException) e;                  else if (e instanceof RuntimeException)                      throw (RuntimeException) e;                  else                      throw new ServletException(e.getMessage(), e);              }          } else {              internalDoFilter(request,response);          }      }      private void internalDoFilter(ServletRequest request,                                    ServletResponse response)          throws IOException, ServletException {          // Call the next filter if there is one          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);                  }              } catch (IOException | ServletException | RuntimeException e) {                  throw e;              } catch (Throwable e) {                  e = ExceptionUtils.unwrapInvocationTargetException(e);                  ExceptionUtils.handleThrowable(e);                  throw new ServletException(sm.getString("filterChain.filter"), e);              }              return;          }          // We fell off the end of the chain -- call the servlet instance          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(request, response);              }          } catch (IOException | ServletException | RuntimeException e) {              throw e;          } catch (Throwable e) {              e = ExceptionUtils.unwrapInvocationTargetException(e);              ExceptionUtils.handleThrowable(e);              throw new ServletException(sm.getString("filterChain.servlet"), e);          } finally {              if (ApplicationDispatcher.WRAP_SAME_OBJECT) {                  lastServicedRequest.set(null);                  lastServicedResponse.set(null);              }          }      }

可以看到ApplicationFilterChain.doFilter方法中会递归过滤链,在调用完所有的filter之后,调用servlet.servce方法

javax.servlet.http.HttpServlet
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);          }      }

在HttpServlet中,service方法会根据请求的不同方法相应的调用doPost、doGet等方法。

时序图

感谢各位的阅读!关于“Tomcat9如何实现请求处理”这篇文章就分享到这里了,希望以上内容可以对大家有一定的帮助,让大家可以学到更多知识,如果觉得文章不错,可以把它分享出去让更多的人看到吧!

[微信提示:高防服务器能助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。

[图文来源于网络,不代表本站立场,如有侵权,请联系高防服务器网删除]
[