springboot获取请求,springboot请求过程
00-1010 1.背景2。Spring Boot请求处理流程设计3。servlet服务模式请求流程分析3.1 servlet服务应用上下文分析3.2 servlet服务模式请求流程具体分析4。反应式服务模式请求流程分析4.1 Reac对tivebserverapplicationcontext的分析4.2 web flux服务模式5的请求流程详细分析。摘要
在00-1010之前,我们研究并解释了Spring Boot。我们知道如何集成配置,如何启动配置,如何实现自动配置。那么,它是如何接收和处理外部请求的,具体原理是什么,又要经过哪些关键环节?过滤器、拦截器和视图在哪里调用,处理顺序是什么?Spring Boot、Spring MVC和内置容器是什么关系?这里我们做一个详细的分析和研究。
00-1010处理流程:
从流程图中我们可以看到,嵌入式服务器接收请求,处理Spring Web包,调用Spring MVC框架,最后到自定义控制器。经过层层处理,接下来我们将研究具体的处理机制。
UML图:
正如您在UML图中所看到的,层次结构很复杂,主要集中在两个层次上:
一是继承GenericWebApplicationContext类,具备上下文BEAN的管理能力;
此外,它实现了可配置的WebServerApplicationContext接口,该接口具有上下文配置的能力。
目录
00-1010当Spring Boot启动时,它将判断应用服务的类型。有两种类型,一种是Servlet服务,另一种是反应式响应服务。ServletWebServerApplicationContext是Servlet服务的核心实现类。
它实现可配置的WebServerApplicationContext接口,并继承GenericWebApplicationContext类:
接口可配置WebServerApplication Contexts可配置ApplicationContext,web server application Context {/* * *设置服务的命名空间*/void setserver namespace(string server namespace);}继承两个接口,ConfigurableApplicationContext和WebServerApplicationContext,定义setServerNamespace接口,设置服务的命名空间。
查看WebServerApplicationContext源代码:
接口WebServer应用程序上下文扩展应用程序上下文{/* * * Get Web Server管理对象*/Web Server Get Web Server();/* * *获取服务的命名空间*/String getserver namespace();}webServer是一个服务管理接口,包括启动和停止服务的功能。
ServletWebServerApplicationContext的构造方法:
/* * *默认构造方法*/PublicServletWebServerApplicationContext(){ }/* *指定bean factory */PublicServletWebServerApplicationContext(DefaultListableBeanfactory bean factory){ super(bean factory)的构造方法;}支持传递指定的beanFactory进行对象初始化。
servletwebserveapplicationcontext的刷新方法:
@ override public final void refresh()抛出BeansExcept
ion, IllegalStateException { try { // 由父类方法初始化Spring上下文 super.refresh(); } catch (RuntimeException ex) { // 如果异常, 停止WebServer启动并释放资源 stopAndReleaseWebServer(); throw ex; }}refresh()方法, 可以参考【Spring Boot启动流程】第一章的3.2.4章节第12点说明, 里面做了具体说明, 就不再赘述。
ServletWebServerApplicationContext 的createWebServer方法:
private void createWebServer() {WebServer webServer = this.webServer; // 获取ServletContext上下文ServletContext servletContext = getServletContext();if (webServer == null && servletContext == null) { // 如果为空, 则进行初始化创建ServletWebServerFactory factory = getWebServerFactory();this.webServer = factory.getWebServer(getSelfInitializer());}else if (servletContext != null) {try { // 如果不为空,则直接启动getSelfInitializer().onStartup(servletContext);}catch (ServletException ex) {throw new ApplicationContextException("Cannot initialize servlet context", ex);}} // 初始化属性资源配置信息initPropertySources();}
ServletWebServerApplicationContext 的selfInitialize方法:
private void selfInitialize(ServletContext servletContext) throws ServletException { // 将ServeltContext设置为WebApplicationContext相关属性prepareWebApplicationContext(servletContext); // 注册ApplicationScope作用域registerApplicationScope(servletContext); // 注册环境变量中的bean信息, 在BeanFactory中也可以获得servletContext上下文信息WebApplicationContextUtils.registerEnvironmentBeans(getBeanFactory(), servletContext);for (ServletContextInitializer beans : getServletContextInitializerBeans()) { // 设置Bean在ServletContext加载完毕后进行初始化beans.onStartup(servletContext);}}
ServletWebServerApplicationContext 的finishRefresh方法:
@Overrideprotected void finishRefresh() // 完成刷新逻辑处理, 比如清除缓存, 发布刷新事件等super.finishRefresh();// 启动WebServerWebServer webServer = startWebServer();if (webServer != null) // 发布WebServer初始化完成事件publishEvent(new ServletWebServerInitializedEvent(webServer, this));}}
以上是整个Servlet模式服务的启动流程, ServletWebServerApplicationContext作为核心处理类,介绍了主要方法的处理逻辑 。
3.2 Servlet服务模式之请求流程具体分析
Spring Boot 是基于MVC做的封装,先看下Spring MVC的处理流程:
Spring Boot 默认是采用Tomcat作为容器, WebServer的实现类为TomcatWebServer, start启动方法:
@Overridepublic void start() throws WebServerException { // 增加同步锁synchronized (this.monitor) {if (this.started) { // 如果启动, 则直接返回return;}try { //处理tomcat的Connectors连接配置信息, 就是tomcat得xml配置得Connector信息addPreviouslyRemovedConnectors();Connector connector = this.tomcat.getConnector();if (connector != null && this.autoStart) { // 如果存在Connector, 且为自动启动, 设置Tomcat的内置上下文延迟处理(服务成功启动后执行)performDeferredLoadOnStartup();} // 检查配置的Connectors是否已经启动, 避免冲突checkThatConnectorsHaveStarted();this.started = true;logger.info("Tomcat started on port(s): " + getPortsDescription(true) + " with context path "+ getContextPath() + "");}catch (ConnectorStartFailedException ex) { // 出现异常, 静默停止stopSilently();throw ex;}catch (Exception ex) {if (findBindException(ex) != null) {throw new PortInUseException(this.tomcat.getConnector().getPort());}throw new WebServerException("Unable to start embedded Tomcat server", ex);}finally { // 获取TOMCAT内置上下文Context context = findContext(); // 解除与classloader类加载器的绑定关系ContextBindings.unbindClassLoader(context, context.getNamingToken(), getClass().getClassLoader());}}}
Web接口调用栈关系:
我们编写一个测试的Web接口, 看下其调用栈结构:
调用栈关系可以看到, 从tomcat的httpServlet接收到请求, 交给Spring MVC的DispatchServlet处理, 再分到我们自定义的WEB接口, 我们经常定义的过滤器Filter, 在进入httpServlet之前已经被处理。
DispatcherServlet的doService方法
我们查看下核心的, 请求分发处理流程:
@Overrideprotected void doService(HttpServletRequest request, HttpServletResponse response) throws Exception // LOG日志记录请求信息logRequest(request);// 记录Request级别作用域的请求变量信息, 必须要开启INCLUDE_REQUEST_URI_ATTRIBUTE属性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));}}}// 设置context上下文信息request.setAttribute(WEB_APPLICATION_CONTEXT_ATTRIBUTE, getWebApplicationContext());// 设置locale区域信息request.setAttribute(LOCALE_RESOLVER_ATTRIBUTE, this.localeResolver);// 设置theme解析器request.setAttribute(THEME_RESOLVER_ATTRIBUTE, this.themeResolver);// 设置theme源信息request.setAttribute(THEME_SOURCE_ATTRIBUTE, getThemeSource());// 设置flashmap信息, FlashMap 是传递重定向参数的时候要用到的一个类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()) {// 上面初始化设置attributesSnapshot, 这里如果有记录, 做还原处理if (attributesSnapshot != null) {restoreAttributesAfterInclude(request, attributesSnapshot);}}}}
DispatcherServlet的doDispatch方法
doDispatch方法负责请求分发处理, 内部会找到我们定义的处理器, 负责处理具体的请求逻辑。
protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception { // 定义初始变量HttpServletRequest processedRequest = request;HandlerExecutionChain mappedHandler = null;boolean multipartRequestParsed = false;// 获取Web异步请求管理器WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);try {ModelAndView mv = null;Exception dispatchException = null;try { // 检查请求是否为form-multipart提交类型,我们常见的文件上传就是采用此类型processedRequest = checkMultipart(request); // 如果是multipart该类型, 通过MultipartResolver解析multipartRequestParsed = (processedRequest != request);// 获取当前请求的映射处理器, 也就是自定义的controller, 如果没有找到, 则返回, 不做下面逻辑处理mappedHandler = getHandler(processedRequest);if (mappedHandler == null) {noHandlerFound(processedRequest, response);return;}// 根据映射处理器, 获取处理适配器(实际为RequestMappingHandlerAdapter) HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());// 获取请求类型,包含GET,HEAD,POST,PUT,PATCH,DELETE,OPTIONS等String method = request.getMethod(); // 判断是否为GET类型 boolean isGet = "GET".equals(method);if (isGet "HEAD".equals(method)) { // 获取上次请求修改标记, 如果没有修改, 默认返回-1long lastModified = ha.getLastModified(request, mappedHandler.getHandler());if (new ServletWebRequest(request, response).checkNotModified(lastModified) && isGet) {return;}}// 在进入处理器之前, 先要判断有没设置拦截器, 如果有, 进入拦截器的前置处理逻辑, 默认有ResourceUrlProviderExposingInterceptor等拦截器if (!mappedHandler.applyPreHandle(processedRequest, response)) {return;}// 这里就是真正调用处理器, 也就是我们在controller中定义的方法mv = ha.handle(processedRequest, response, mappedHandler.getHandler());// 异步处理判断if (asyncManager.isConcurrentHandlingStarted()) {return;}// 判断有没采用ModelAndView返回, 并进行对应设置applyDefaultViewName(processedRequest, mv); // 这里是拦截器的后置处理逻辑, 如果有匹配设置, 则会进行调用处理mappedHandler.applyPostHandle(processedRequest, response, mv);}catch (Exception ex) {dispatchException = ex;}catch (Throwable err) {// As of 4.3, were 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 {//如果采用multipart类型提交, 会做一些清除工作, 比如上传文件缓存等if (multipartRequestParsed) {cleanupMultipart(processedRequest);}}}}
通过以上分析, 我们可以了解到Servlet模式服务的请求流程, 重点是DispatcherServlet的doDispatch方法,要了解一个请求进入之前所做的事情, 请求处理完成之后所做的事情, 以及对于filter, interceptor执行顺序这些都要清楚, 可以帮助我们更好的运用, 以及排查请求过程中出现的问题。
4. Reactive服务模式请求流程分析
4.1 ReactiveWebServerApplicationContext分析
ReactiveWebServerApplicationContext为响应式服务容器管理, 是提供Reactive Web环境的Spring 容器。 Spring WebFlux应用就采用ReactiveWebServerApplicationContext实现, ReactiveWebServerApplicationContext与ServletWebServerApplicationContext 的实现类似, 都是由SpringBoot统一封装设计, 总体处理流程基本一致。
ReactiveWebServerApplicationContext 构造方法
public class ReactiveWebServerApplicationContext extends GenericReactiveWebApplicationContextimplements ConfigurableWebServerApplicationContext {// 服务管理类, 包含服务启动与停止, 以及请求handler处理private volatile ServerManager serverManager;// 服务命名空间private String serverNamespace;/** * 默认构造方法 */public ReactiveWebServerApplicationContext() {}/** * 指定beanFactory的构造方法 */public ReactiveWebServerApplicationContext(DefaultListableBeanFactory beanFactory) {super(beanFactory);}
ReactiveWebServerApplicationContext#ServerManager内部类:
/** * 服务管理类 */static final class ServerManager implements HttpHandler {// WebServer服务private final WebServer server;// 是否懒加载private final boolean lazyInit;// Http Handler请求处理器private volatile HttpHandler handler;// 构造方法, 注入serverFactory与延迟加载标记private ServerManager(ReactiveWebServerFactory factory, boolean lazyInit) {this.handler = this::handleUninitialized;this.server = factory.getWebServer(this);this.lazyInit = lazyInit;}// 处理未初始化的请求, 暂未实现private Mono<Void> handleUninitialized(ServerHttpRequest request, ServerHttpResponse response) {throw new IllegalStateException("The HttpHandler has not yet been initialized");}// 重载方法, 处理Web请求@Overridepublic Mono<Void> handle(ServerHttpRequest request, ServerHttpResponse response) {return this.handler.handle(request, response);}public HttpHandler getHandler() {return this.handler;}// 获取ServerManager服务管理类public static ServerManager get(ReactiveWebServerFactory factory, boolean lazyInit) {return new ServerManager(factory, lazyInit);} // 获取WebServer服务public static WebServer getWebServer(ServerManager manager) {return (manager != null) ? manager.server : null;} // 通过serverManager启动服务public static void start(ServerManager manager, Supplier<HttpHandler> handlerSupplier) {if (manager != null && manager.server != null) {manager.handler = manager.lazyInit ? new LazyHttpHandler(Mono.fromSupplier(handlerSupplier)): handlerSupplier.get();manager.server.start();}}// 通过serverManager停止服务public static void stop(ServerManager manager) {if (manager != null && manager.server != null) {try {manager.server.stop();}catch (Exception ex) {throw new IllegalStateException(ex);}}}}
ReactiveWebServerApplicationContext#startReactiveWebServer方法:
private WebServer startReactiveWebServer() { ServerManager serverManager = this.serverManager; // 启动WebServer, 从BeanFactory中获取HttpHandlerServerManager.start(serverManager, this::getHttpHandler); // 获取返回WebServerreturn ServerManager.getWebServer(serverManager);}
查看getHttpHandler方法:
protected HttpHandler getHttpHandler() {// 获取所有实现HttpHandler接口的实现类String[] beanNames = getBeanFactory().getBeanNamesForType(HttpHandler.class); // HttpHandler实现类只能存在一个, 没有配置或多个都会抛出异常if (beanNames.length == 0) { // throw new ApplicationContextException("Unable to start ReactiveWebApplicationContext due to missing HttpHandler bean.");} // 存在多个, 抛出异常if (beanNames.length > 1) {throw new ApplicationContextException("Unable to start ReactiveWebApplicationContext due to multiple HttpHandler beans : "+ StringUtils.arrayToCommaDelimitedString(beanNames));} // 返回HttpHandlerreturn getBeanFactory().getBean(beanNames[0], HttpHandler.class);}
ReactiveWebServerApplicationContext#onClose方法:
@Overrideprotected void onClose() { // 先调用父类方法, 关闭逻辑处理, 目前是空实现 super.onClose(); // 通过ServerManager停止服务 stopAndReleaseReactiveWebServer();}
4.2 webflux服务模式之请求流程具体分析
上面讲解了ReactiveWebServerApplicationContext的代码实现流程, 我们看下webflux服务的请求处理流程。
定义HttpHandler
// 定义Reactive服务的HttpHandler, @Beanpublic HttpHandler httpHandler() { return WebHttpHandlerBuilder.applicationContext(this.applicationContext) .build();}
webflux使用的httpHandler类型是HttpWebHandlerAdapter, 创建的webserver为NettyWebServer类型
@Overridepublic WebServer getWebServer(HttpHandler httpHandler) { // 创建HTTP SERVER服务 HttpServer httpServer = createHttpServer(); // 定义HTTP HANDLER处理适配器 ReactorHttpHandlerAdapter handlerAdapter = new ReactorHttpHandlerAdapter( httpHandler); // 采用Netty作为WebServer实现 return new NettyWebServer(httpServer, handlerAdapter, this.lifecycleTimeout);}
创建ReactorHttpHandlerAdapter使用的httpHandler就是我们上面定义的WebHttpHandlerBuilder。
当一个请求进来的时候,就是通过ReactorHttpHandlerAdapter的apply()方法然后进入了了HttpWebHandlerAdapter类的handle方法, 再执行DispatcherHandler的handle方法:
public Mono<Void> handle(ServerWebExchange exchange) { // 校验handlerMappings是否存在if (this.handlerMappings == null) {return createNotFoundError();} // 响应式操作, 调用Handler实现类处理逻辑, handleResult处理执行结果return Flux.fromIterable(this.handlerMappings).concatMap(mapping -> mapping.getHandler(exchange)).next().switchIfEmpty(createNotFoundError()).flatMap(handler -> invokeHandler(exchange, handler)).flatMap(result -> handleResult(exchange, result));}
通过RequestMappingHandlerMapping找到对应的HandlerMethod(就是我们Controller中对应的方法),然后执行invokeHandler方法:
private Mono<HandlerResult> invokeHandler(ServerWebExchange exchange, Object handler) { // 校验Handler适配器是否存在if (this.handlerAdapters != null) { // 遍历handlerAdaptersfor (HandlerAdapter handlerAdapter : this.handlerAdapters) { // 判断是否支持的适配器类型if (handlerAdapter.supports(handler)) { // 处理Handler适配器具体逻辑return handlerAdapter.handle(exchange, handler);}}}return Mono.error(new IllegalStateException("No HandlerAdapter: " + handler));}
HandlerAdapter是RequestMappingHandlerAdapter,在RequestMappingHandlerAdapter方法中执行了InvocableHandlerMethod的invode方法,然后通过反射执行了Controller中的方法, 最后把Controller方法执行的结果,通过DispatcherHandler中的handlerResult方法,输出返回给调用客户端。
5. 总结
学习研究Spring Boot的请求流程, 理解其内置容器, Spring MVC和自定义controller之间是如何流转处理的, 各自所做的事情, 每个环节的作用, 相互之间的调用关系, 才算是理解和掌握Spring Boot的使用, 在实际工作当中, 可能更多的是停留在使用层面, 但是如果能够对实现原理有进一步认知, 我们才知道更合理的去使用, 以及更高效的去排查使用过程当中出现的各种问题。
到此这篇关于Spring Boot超详细讲解请求处理流程机制的文章就介绍到这了,更多相关Spring Boot请求处理内容请搜索盛行IT以前的文章或继续浏览下面的相关文章希望大家以后多多支持盛行IT!
郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。