当前位置: 首页> 科技> 名企 > 北京网站排名优化公司_seo线下培训课程_长沙全网覆盖的网络推广_营销软件培训

北京网站排名优化公司_seo线下培训课程_长沙全网覆盖的网络推广_营销软件培训

时间:2025/7/29 5:39:03来源:https://blog.csdn.net/m0_50149847/article/details/142905899 浏览次数:0次
北京网站排名优化公司_seo线下培训课程_长沙全网覆盖的网络推广_营销软件培训

SpringBoot的启动、处理请求整体流程(二)

  • 1、tomcat服务
    • 1.1、tomcat引入
    • 1.2、系统结构图与执行流程
    • 1.3、tomcat使用的classLoader
  • 2、客户端发一次请求的调用流程

本篇文章若有侵权,请联系,谢谢~ 。同时,如果文章有错误,也欢迎批评指正。

本篇文章继SpringBoot的启动、处理请求整体流程(一)之后,可以先阅读第一篇文章

1、tomcat服务

1.1、tomcat引入

之前(servlet)都是把自己写的程序打包成war包,然后扔给tomcat容器进行执行。现在(spring应用 其实也是对servlet的封装)都是和tomcat进行一起打包成jar包,可以直接执行。
如何创建一个Servlet项目(Maven)
在这里插入图片描述
HTTP服务器和Servlet容器是两种不同的技术,它们各自有自己的功能和用途。

  1. HTTP服务器:HTTP服务器主要用于处理HTTP请求,返回静态的网页内容,如HTML、CSS、JavaScript文件或者图片等。它可以直接与客户端(通常是Web浏览器)进行通信。当用户在浏览器中输入URL并发送请求时,HTTP服务器会找到对应的静态资源并返回给用户。常见的HTTP服务器有Apache HTTP Server、Nginx等。

  2. Servlet容器:Servlet容器是运行Servlet的地方,Servlet是用Java写的服务器端程序,其主要功能在于交互式地浏览和修改数据,生成动态Web内容。Servlet容器负责管理Servlet的生命周期,提供网络服务、请求分发、安全控制等。常见的Servlet容器有Tomcat、Jetty等。

在实际应用中,HTTP服务器和Servlet容器常常一起使用。例如,用户发送的请求首先到达HTTP服务器,如果请求的是静态资源,那么HTTP服务器直接返回;如果请求的是动态内容,那么HTTP服务器会将请求转发给Servlet容器,由Servlet容器处理后返回给HTTP服务器,再由HTTP服务器返回给用户。这样的组合可以充分利用各自的优势,提供高效、灵活的Web服务。

而Tomcat和Jetty就是一个Servlet容器。为了方便使用,它们也具有HTTP服务器的功能,因此Tomcat或者Jetty就是一个“HTTP服务器 + Servlet容器”,我们也叫它们Web容器。所以我们写的代码程序都是基于servlet的spring程序,和http服务没关系
在这里插入图片描述

1.2、系统结构图与执行流程

在这里插入图片描述
这里就很明显看到第一篇文章在Spring启动的时候,启动tomcat创建server的时候,会创建连接器、容器等。

为了提高性能,在连接器中会有三个线程:main线程、监听线程和线程池:

  1. main线程启动ServerSocket,并创建一个监听线程(Acceptor)+一个工作程线池(多个Worker);
  2. 监听线程只用来监听Socket,收到Socket后放入线程池的队列中(Queue);
  3. 每一个工作线程(Worker)处理各自的HTTP请求(Socket),Worker将解析/封装HTTP协议的事交由Handler处理(原来每一个请求对应一个线程,这个线程是tomcat的线程池)。
    在这里插入图片描述

请求定位servlet过程:
Tomcat是通过Mapper组件确定请求是由哪个Wrapper容器里的Servlet来处理的。Mapper组件的功能就是将用户请求的URL定位到一个Servlet,它的工作原理是:Mapper组件里保存了Web应用的配置信息,其实就是容器组件与访问路径的映射关系,比如Host容器里配置的域名、Context容器里的Web应用路径,以及Wrapper容器里Servlet映射的路径,你可以想象这些配置信息就是一个多层次的Map。当一个请求到来时,Mapper组件通过解析请求URL里的域名和路径,再到自己保存的Map里去查找,就能定位到一个Servlet。请你注意,一个请求URL最后只会定位到一个Wrapper容器,也就是一个Servlet。
在这里插入图片描述
无论是通过上述的请求定位servlet还是系统架构图,可以看出整个请求到达servlet/wrapper这一层经历了很多容器。而每个容器都会做一些事情,这个过程就使用了责任链模式:Pipeline和valve。
在这里插入图片描述

public interface Valve {public Valve getNext();public void setNext(Valve valve);public void invoke(Request request, Response response)
}
public interface Pipeline extends Contained {public void addValve(Valve valve);public Valve getBasic();public void setBasic(Valve valve);public Valve getFirst();
}

整个调用过程由连接器中的Adapter触发的,它会调用Engine的第一个Valve:

// Calling the container 
connector.getService().getContainer().getPipeline().getFirst().invoke(request, response);

Wrapper容器的最后一个Valve会创建一个Filter链,并调用doFilter方法,最终会调到Servlet的service方法。

在Wrapper的pipeline执行完之后以及在真正执行servlet之前还有一个应用的责任链,也就是servlet规范中的Filter过滤器接口。给程序员提供的扩展接口。
在这里插入图片描述

1.3、tomcat使用的classLoader

在这里插入图片描述
详细继承图:(appClassLoader是系统类加载器SystemClassLoader的一个实例)
在这里插入图片描述
CommonClassLoader类加载器:负责加载tomcat和各个web服务需要的公共类
CatalinaClassLoader类加载器:负责加载tomcat需要的类
ServerClassLoader类加载器:负责加载所有web服务需要的公共类
WebAppClassLoader类加载器:负责加载单个、自身服务的类。

2、客户端发一次请求的调用流程

到此,整个tomcat服务已经启动了,开始监听端口,响应请求。

客户端发起一次请求,经历参数解析器、处理器等流程:
可以参考文献:SpringBoot源码——请求全过程源码分析——一步一步详细分析。
这里只是粘贴一下servlet源码,整个调用过程中的类:
在这里插入图片描述
servlet接口定义:

public interface Servlet {// servlet放到tomcat容器的时候被调用public void init(ServletConfig config) throws ServletException;// 获取servlet的配置public ServletConfig getServletConfig();// tomcat就会根据请求url调用servicepublic void service(ServletRequest req, ServletResponse res) throws ServletException, IOException;public String getServletInfo();// servlet被移除tomcat的时候调用public void destroy();
}

GenericServlet抽象类:

public abstract class GenericServlet implements Servlet, ServletConfig, java.io.Serializable{public void destroy() {}public void init(ServletConfig config) throws ServletException {this.config = config;this.init();}public void init() throws ServletException {}// service方法仍然没实现,其他的空实现public abstract void service(ServletRequest req, ServletResponse res)throws ServletException, IOException;
}

HttpServlet抽象类:

public abstract class HttpServlet extends GenericServlet{private static final String METHOD_DELETE = "DELETE";private static final String METHOD_HEAD = "HEAD";private static final String METHOD_GET = "GET";private static final String METHOD_OPTIONS = "OPTIONS";private static final String METHOD_POST = "POST";private static final String METHOD_PUT = "PUT";private static final String METHOD_TRACE = "TRACE";@Overridepublic void service(ServletRequest req, ServletResponse res)throws ServletException, IOException{HttpServletRequest  request;HttpServletResponse response;if (!(req instanceof HttpServletRequest &&res instanceof HttpServletResponse)) {throw new ServletException("non-HTTP request or response");}request = (HttpServletRequest) req;response = (HttpServletResponse) res;service(request, response);}// doGet doPost doHead doDelete....这些方法在这个类中只是实现了简单的逻辑(返回错误) 需要其他进行实现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 logicdoGet(req, resp);} else {// 上次请求返回的响应时间 请求头参数:If-Modified-Sincelong ifModifiedSince = req.getDateHeader(HEADER_IFMODSINCE);// 如果自从上次返回之后又修改了,则进行返回if (ifModifiedSince < lastModified) {// 给响应头Last-Modified设置修改最后时间maybeSetLastModified(resp, lastModified);doGet(req, resp);} else {// 自从上次返回没有修改过 直接返回状态码304 告诉客户端使用缓存 节省带宽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);}}
}

FrameworkServlet类:

public abstract class FrameworkServlet extends HttpServletBean implements ApplicationContextAware {// doGet doPost doHead doDelete....这些方法在这个类中又调用同一个方法@Overrideprotected final void doGet(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {processRequest(request, response);}@Overrideprotected final void doPost(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {processRequest(request, response);}protected final void processRequest(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {long startTime = System.currentTimeMillis();Throwable failureCause = null;LocaleContext previousLocaleContext = LocaleContextHolder.getLocaleContext();LocaleContext localeContext = buildLocaleContext(request);RequestAttributes previousAttributes = RequestContextHolder.getRequestAttributes();ServletRequestAttributes requestAttributes = buildRequestAttributes(request, response, previousAttributes);WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);asyncManager.registerCallableInterceptor(FrameworkServlet.class.getName(), new RequestBindingInterceptor());initContextHolders(request, localeContext, requestAttributes);try {doService(request, response);}catch (ServletException | IOException ex) {failureCause = ex;throw ex;}catch (Throwable ex) {failureCause = ex;throw new NestedServletException("Request processing failed", ex);}finally {resetContextHolders(request, previousLocaleContext, previousAttributes);if (requestAttributes != null) {requestAttributes.requestCompleted();}if (logger.isDebugEnabled()) {if (failureCause != null) {this.logger.debug("Could not complete request", failureCause);}else {if (asyncManager.isConcurrentHandlingStarted()) {logger.debug("Leaving response open for concurrent processing");}else {this.logger.debug("Successfully completed request");}}}publishRequestHandledEvent(request, response, startTime, failureCause);}}protected abstract void doService(HttpServletRequest request, HttpServletResponse response)throws Exception;
}

DispatcherServlet类:

public class DispatcherServlet extends FrameworkServlet {@Overrideprotected void doService(HttpServletRequest request, HttpServletResponse response) throws Exception {if (logger.isDebugEnabled()) {String resumed = WebAsyncUtils.getAsyncManager(request).hasConcurrentResult() ? " resumed" : "";logger.debug("DispatcherServlet with name '" + getServletName() + "'" + resumed +" processing " + request.getMethod() + " request for [" + getRequestUri(request) + "]");}// Keep a snapshot of the request attributes in case of an include,// to be able to restore the original attributes after the include.Map<String, Object> attributesSnapshot = null;if (WebUtils.isIncludeRequest(request)) {attributesSnapshot = new HashMap<>();Enumeration<?> attrNames = request.getAttributeNames();while (attrNames.hasMoreElements()) {String attrName = (String) attrNames.nextElement();if (this.cleanupAfterInclude || attrName.startsWith(DEFAULT_STRATEGIES_PREFIX)) {attributesSnapshot.put(attrName, request.getAttribute(attrName));}}}// Make framework objects available to handlers and view objects.request.setAttribute(WEB_APPLICATION_CONTEXT_ATTRIBUTE, getWebApplicationContext());request.setAttribute(LOCALE_RESOLVER_ATTRIBUTE, this.localeResolver);request.setAttribute(THEME_RESOLVER_ATTRIBUTE, this.themeResolver);request.setAttribute(THEME_SOURCE_ATTRIBUTE, getThemeSource());if (this.flashMapManager != null) {FlashMap inputFlashMap = this.flashMapManager.retrieveAndUpdate(request, response);if (inputFlashMap != null) {request.setAttribute(INPUT_FLASH_MAP_ATTRIBUTE, Collections.unmodifiableMap(inputFlashMap));}request.setAttribute(OUTPUT_FLASH_MAP_ATTRIBUTE, new FlashMap());request.setAttribute(FLASH_MAP_MANAGER_ATTRIBUTE, this.flashMapManager);}try {doDispatch(request, response);}finally {if (!WebAsyncUtils.getAsyncManager(request).isConcurrentHandlingStarted()) {// Restore the original attribute snapshot, in case of an include.if (attributesSnapshot != null) {restoreAttributesAfterInclude(request, attributesSnapshot);}}}}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);// Determine handler for the current request.mappedHandler = getHandler(processedRequest);if (mappedHandler == null) {noHandlerFound(processedRequest, response);return;}// Determine handler adapter for the current request.HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());// Process last-modified header, if supported by the handler.String method = request.getMethod();boolean isGet = "GET".equals(method);if (isGet || "HEAD".equals(method)) {long lastModified = ha.getLastModified(request, mappedHandler.getHandler());if (logger.isDebugEnabled()) {logger.debug("Last-Modified value for [" + getRequestUri(request) + "] is: " + lastModified);}if (new ServletWebRequest(request, response).checkNotModified(lastModified) && isGet) {return;}}if (!mappedHandler.applyPreHandle(processedRequest, response)) {return;}// Actually invoke the handler.mv = ha.handle(processedRequest, response, mappedHandler.getHandler());if (asyncManager.isConcurrentHandlingStarted()) {return;}applyDefaultViewName(processedRequest, mv);mappedHandler.applyPostHandle(processedRequest, response, mv);}catch (Exception ex) {dispatchException = ex;}catch (Throwable err) {// As of 4.3, we're processing Errors thrown from handler methods as well,// making them available for @ExceptionHandler methods and other scenarios.dispatchException = new NestedServletException("Handler dispatch failed", err);}processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);}catch (Exception ex) {triggerAfterCompletion(processedRequest, response, mappedHandler, ex);}catch (Throwable err) {triggerAfterCompletion(processedRequest, response, mappedHandler,new NestedServletException("Handler processing failed", err));}finally {if (asyncManager.isConcurrentHandlingStarted()) {// Instead of postHandle and afterCompletionif (mappedHandler != null) {mappedHandler.applyAfterConcurrentHandlingStarted(processedRequest, response);}}else {// Clean up any resources used by a multipart request.if (multipartRequestParsed) {cleanupMultipart(processedRequest);}}}}
}
关键字:北京网站排名优化公司_seo线下培训课程_长沙全网覆盖的网络推广_营销软件培训

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

责任编辑: