Java源码分析SpringMVC执行流程 您所在的位置:网站首页 javaspringmvc流程 Java源码分析SpringMVC执行流程

Java源码分析SpringMVC执行流程

#Java源码分析SpringMVC执行流程| 来源: 网络整理| 查看: 265

Java源码分析SpringMVC执行流程 发布时间:2023-04-20 16:13:04 来源:亿速云 阅读:58 作者:iii 栏目:开发技术

本篇内容介绍了“Java源码分析SpringMVC执行流程”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!

先看流程

先看一下SpringMVC执行流程再看源码,有助理解:

⽤户发送请求⾄前端控制器DispatcherServlet。

DispatcherServlet 收到请求调⽤ HandlerMapping 处理器映射器。

处理器映射器找到具体的处理器(可以根据xml配置、注解进⾏查找),⽣成处理器及处理器拦截器(如果有则⽣成)⼀并返回给DispatcherServlet。

DispatcherServlet调⽤HandlerAdapter处理器适配器。

HandlerAdapter经过适配调⽤具体的处理器(Controller,也叫后端控制器)

Controller执⾏完成返回ModelAndView。

HandlerAdapter 将 Controller 执⾏结果 ModelAndView 返回给DispatcherServlet。

DispatcherServlet将ModelAndView传给ViewReslover视图解析器。

ViewReslover解析后返回具体View。

DispatcherServlet根据View进⾏渲染视图(即将模型数据填充⾄视图中)。

DispatcherServlet 响应⽤户。

Java源码分析SpringMVC执行流程

再看源码

我们都知道当从用户发起请求到后端是,首先走的就是DispatcherServlet,接着就会调用doService()方法执行业务逻辑,doService()方法也只是一个中转站,实际执行逻辑的是doDispatch()方法,且看源码:

@Override protected void doService(HttpServletRequest request, HttpServletResponse response) throws Exception {     logRequest(request);     // 省略部分源码     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);             }         }         ServletRequestPathUtils.setParsedRequestPath(previousRequestPath, request);     } }

doDispatch 方法:

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);             // 为当前请求获取映射处理器             mappedHandler = getHandler(processedRequest);             if (mappedHandler == null) {                 noHandlerFound(processedRequest, response);                 return;             }             // 获取映射处理器适配器             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 (new ServletWebRequest(request, response).checkNotModified(lastModified) && isGet) {                     return;                 }             }             if (!mappedHandler.applyPreHandle(processedRequest, response)) {                 return;             }             // 实际调用的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 afterCompletion             if (mappedHandler != null) {                 mappedHandler.applyAfterConcurrentHandlingStarted(processedRequest, response);             }         }         else {             // Clean up any resources used by a multipart request.             if (multipartRequestParsed) {                 cleanupMultipart(processedRequest);             }         }     } }

下面来看一下其中几个重要的方法:

1.getHandler(HttpServletRequest request)方法:该方法是处理当前请求找到合适的HandlerMapping,并返回一个HandlerExecutionChain,HandlerExecutionChain,HandlerExecutionChain包含了具体的处理器(handler)和拦截器列表。

HandlerMapping 默认的实现有org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping 和 org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping。

@Nullable 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; }

2.getHandlerAdapter(Object handler) 根据HandlerExecutionChain中的handler来获取处理器适配器(HandlerAdapter),

protected HandlerAdapter getHandlerAdapter(Object handler) throws ServletException {     if (this.handlerAdapters != null) {         for (HandlerAdapter adapter : this.handlerAdapters) {             if (adapter.supports(handler)) {                 return adapter;             }         }     }     throw new ServletException("No adapter for handler [" + handler +             "]: The DispatcherServlet configuration needs to include a HandlerAdapter that supports this handler"); }

HandlerAdapter有两个默认实现类,分别是 org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter和 org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter,前者用于没有使用模板引擎的请求,后者用于使用了模板引擎的接口。

实际处理请求的是HandlerAdapter的handle方法,如果是没有使用例如JSP等的模板引擎,handle方法就会返回null,如果使用了模板引擎就会返回一个ModelAndView对象。

ModelAndView mv = ha.handle(processedRequest, response, mappedHandler.getHandler());

handle方法最终调用的是Controller接口的 handleRequest(HttpServletRequest request, HttpServletResponse response) 方法来处理请求。

以SimpleControllerHandlerAdapter#handle方法源码为例:

@Override @Nullable public ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler)         throws Exception {     return ((Controller) handler).handleRequest(request, response); }

3.processDispatchResult方法用于处理转发结果,该结果要么是一个ModelAndView,要么抛异常。

private void processDispatchResult(HttpServletRequest request, HttpServletResponse response, @Nullable HandlerExecutionChain mappedHandler, @Nullable ModelAndView mv, @Nullable Exception exception) throws Exception {     boolean errorView = false;     if (exception != null) {         if (exception instanceof ModelAndViewDefiningException) {             logger.debug("ModelAndViewDefiningException encountered", exception);             mv = ((ModelAndViewDefiningException) exception).getModelAndView();         }         else {             Object handler = (mappedHandler != null ? mappedHandler.getHandler() : null);             //处理异常             mv = processHandlerException(request, response, handler, exception);             errorView = (mv != null);         }     }     // Did the handler return a view to render?     if (mv != null && !mv.wasCleared()) {         //加载视图         render(mv, request, response);         if (errorView) {             WebUtils.clearErrorRequestAttributes(request);         }     } else {         if (logger.isTraceEnabled()) {             logger.trace("No view rendering, null ModelAndView returned.");         }     }     if (WebAsyncUtils.getAsyncManager(request).isConcurrentHandlingStarted()) {         // Concurrent handling started during a forward         return;     }     if (mappedHandler != null) {         // Exception (if any) is already handled..         mappedHandler.triggerAfterCompletion(request, response, null);     } }

processDispatchResult方法中在正常情况下会调用render方法。

4.render方法用来通过名称呈现视图,它也是请求处理的最后一步。

protected void render(ModelAndView mv, HttpServletRequest request, HttpServletResponse response) throws Exception {     // Determine locale for request and apply it to the response.     Locale locale =             (this.localeResolver != null ? this.localeResolver.resolveLocale(request) : request.getLocale());     response.setLocale(locale);     View view;     String viewName = mv.getViewName();     if (viewName != null) {         // 通过视图名称获取视图         view = resolveViewName(viewName, mv.getModelInternal(), locale, request);         if (view == null) {             throw new ServletException("Could not resolve view with name '" + mv.getViewName() +                     "' in servlet with name '" + getServletName() + "'");         }     }     else {         // No need to lookup: the ModelAndView object contains the actual View object.         view = mv.getView();         if (view == null) {             throw new ServletException("ModelAndView [" + mv + "] neither contains a view name nor a " +                     "View object in servlet with name '" + getServletName() + "'");         }     }     // Delegate to the View object for rendering.     if (logger.isTraceEnabled()) {         logger.trace("Rendering view [" + view + "] ");     }     try {         if (mv.getStatus() != null) {             response.setStatus(mv.getStatus().value());         }         //渲染视图         view.render(mv.getModelInternal(), request, response);     }     catch (Exception ex) {         if (logger.isDebugEnabled()) {             logger.debug("Error rendering view [" + view + "]", ex);         }         throw ex;     } }

DispatcherServlet的render方法是对视图View的封装,最后调用的还是View的render方法。

resolveViewName方法用于解析视图名称,它会通过视图解析器ViewResolver的resolveViewName方法解析视图并返回一个视图View,然后再通过View的render方法渲染视图,至于是怎么渲染视图的这里就不介绍了,感兴趣的可以自行查看源码。

protected View resolveViewName(String viewName, @Nullable Map model, Locale locale, HttpServletRequest request) throws Exception {     if (this.viewResolvers != null) {         for (ViewResolver viewResolver : this.viewResolvers) {             View view = viewResolver.resolveViewName(viewName, locale);             if (view != null) {                 return view;             }         }     }     return null; }

“Java源码分析SpringMVC执行流程”的内容就介绍到这里了,感谢大家的阅读。如果想了解更多行业相关的知识可以关注亿速云网站,小编将为大家输出更多高质量的实用文章!

推荐阅读: java中如何实现生成器和迭代器 从零开始,搭建网络管理系统-前期准备

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:[email protected]进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

java springmvc 上一篇新闻:Vue怎么实现轮播图组件封装 下一篇新闻:Vue表格首列相同数据合并怎么实现 猜你喜欢 springBoot启动时让方法自动执行的方法 python 如何提取PPT中所有文字的方法 JavaWeb中怎么使用Filter和Listener python 如何自动监控新邮件并读取 MySQL和Python怎么交互 spring-boot-maven-plugin引入出现爆红问题怎么回事 Mybatis-Plus select如何不显示全部字段 mysql字符集相关知识大全 Python中删除文件的几种方法介绍 如何解决mybatis-plus实体类中出现非数据库映射字段的问题


【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有