回顾一下DispatcherServlet中doDispatch的处理流程

/*** Process the actual dispatching to the handler.* <p>The handler will be obtained by applying the servlet's HandlerMappings in order.* The HandlerAdapter will be obtained by querying the servlet's installed HandlerAdapters* to find the first that supports the handler class.* <p>All HTTP methods are handled by this method. It's up to HandlerAdapters or handlers* themselves to decide which methods are acceptable.* @param request current HTTP request* @param response current HTTP response* @throws Exception in case of any kind of processing failure*/protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {HttpServletRequest processedRequest = request;HandlerExecutionChain mappedHandler = null;int interceptorIndex = -1;try {ModelAndView mv;boolean errorView = false;try {// 判断请求是否是多媒体请求processedRequest = checkMultipart(request);// 获取当前请求的处理器HandlerExecutionChainmappedHandler = getHandler(processedRequest, false);if (mappedHandler == null || mappedHandler.getHandler() == null) {//如果没有处理器,则返回一个404noHandlerFound(processedRequest, response);return;}// 获取当前请求的Handler适配器HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());// Process last-modified header, if supported by the handler.//获取当前请求的请求方法String method = request.getMethod();// 判断当前请求方法是否是GET请求boolean isGet = "GET".equals(method);// 如果是GET请求或者是HEADif (isGet || "HEAD".equals(method)) {//获取最后修改时间long lastModified = ha.getLastModified(request, mappedHandler.getHandler());if (logger.isDebugEnabled()) {String requestUri = urlPathHelper.getRequestUri(request);logger.debug("Last-Modified value for [" + requestUri + "] is: " + lastModified);}if (new ServletWebRequest(request, response).checkNotModified(lastModified) && isGet) {return;}}// 获取拦截器HandlerInterceptor[] interceptors = mappedHandler.getInterceptors();//如果拦截器不为空if (interceptors != null) {for (int i = 0; i < interceptors.length; i++) {HandlerInterceptor interceptor = interceptors[i];//如果处理请求被拦截,则结束请求,否则继续if (!interceptor.preHandle(processedRequest, response, mappedHandler.getHandler())) {triggerAfterCompletion(mappedHandler, interceptorIndex, processedRequest, response, null);return;}interceptorIndex = i;}}// 调用处理器获取一个视图mv = ha.handle(processedRequest, response, mappedHandler.getHandler());//如果视图不为空,且有view,则设置默认视图名称if (mv != null && !mv.hasView()) {mv.setViewName(getDefaultViewName(request));}// Apply postHandle methods of registered interceptors.if (interceptors != null) {for (int i = interceptors.length - 1; i >= 0; i--) {HandlerInterceptor interceptor = interceptors[i];interceptor.postHandle(processedRequest, response, mappedHandler.getHandler(), mv);}}}catch (ModelAndViewDefiningException ex) {logger.debug("ModelAndViewDefiningException encountered", ex);mv = ex.getModelAndView();}catch (Exception ex) {Object handler = (mappedHandler != null ? mappedHandler.getHandler() : null);mv = processHandlerException(processedRequest, response, handler, ex);errorView = (mv != null);}// 渲染视图if (mv != null && !mv.wasCleared()) {render(mv, processedRequest, response);if (errorView) {WebUtils.clearErrorRequestAttributes(request);}}else {if (logger.isDebugEnabled()) {logger.debug("Null ModelAndView returned to DispatcherServlet with name '" + getServletName() +"': assuming HandlerAdapter completed request handling");}}// Trigger after-completion for successful outcome.triggerAfterCompletion(mappedHandler, interceptorIndex, processedRequest, response, null);}catch (Exception ex) {// Trigger after-completion for thrown exception.triggerAfterCompletion(mappedHandler, interceptorIndex, processedRequest, response, ex);throw ex;}catch (Error err) {ServletException ex = new NestedServletException("Handler processing failed", err);// Trigger after-completion for thrown exception.triggerAfterCompletion(mappedHandler, interceptorIndex, processedRequest, response, ex);throw ex;}finally {// Clean up any resources used by a multipart request.if (processedRequest != request) {cleanupMultipart(processedRequest);}}}

可以发现对请求数据的处理是通过HandlerAdapter的handle()方法进行处理。下面将通过AnnotationMethodHandlerAdapter类来说明HandlerAdapter

public ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler)throws Exception {// 获取处理器的Class对象Class<?> clazz = ClassUtils.getUserClass(handler);Boolean annotatedWithSessionAttributes = this.sessionAnnotatedClassesCache.get(clazz);if (annotatedWithSessionAttributes == null) {// 如果有会话域的参数annotatedWithSessionAttributes = (AnnotationUtils.findAnnotation(clazz, SessionAttributes.class) != null);//将会话域的参数放入到缓存中this.sessionAnnotatedClassesCache.put(clazz, annotatedWithSessionAttributes);}if (annotatedWithSessionAttributes) {// 总是防止缓存的情况下会话属性管理。checkAndPrepare(request, response, this.cacheSecondsForSessionAttributeHandlers, true);//  准备缓存防止会话域参数名称}else {// Uses configured default cacheSeconds setting.checkAndPrepare(request, response, true);}// 如果有必要可以在synchronized同步代码块中执行ivokeHandlerMethod方法,默认是falseif (this.synchronizeOnSession) {// 获取当前请求的sessionHttpSession session = request.getSession(false);if (session != null) {//获取当前session的互斥锁对象Object mutex = WebUtils.getSessionMutex(session);//互斥调用处理器的方法synchronized (mutex) {return invokeHandlerMethod(request, response, handler);}}}return invokeHandlerMethod(request, response, handler);}protected ModelAndView invokeHandlerMethod(HttpServletRequest request, HttpServletResponse response, Object handler)throws Exception {// 获取指定处理器的ServeltHandlerMethodResovler对象ServletHandlerMethodResolver methodResolver = getMethodResolver(handler);// 获取请求的处理方法Method handlerMethod = methodResolver.resolveHandlerMethod(request);//ServletHandlerMethodInvoker methodInvoker = new ServletHandlerMethodInvoker(methodResolver);//构建一个ServletWebReqeustServletWebRequest webRequest = new ServletWebRequest(request, response);ExtendedModelMap implicitModel = new BindingAwareModelMap();//指定处理Object result = methodInvoker.invokeHandlerMethod(handlerMethod, handler, webRequest, implicitModel);// 获取处理后的ModleAndViewModelAndView mav =methodInvoker.getModelAndView(handlerMethod, handler.getClass(), result, implicitModel, webRequest);methodInvoker.updateModelAttributes(handler, (mav != null ? mav.getModel() : null), implicitModel, webRequest);// 返回ModelAndView对象return mav;}
  /*** 对给定的处理器类型创建一个ServeltHandlerMethodResolver*/private ServletHandlerMethodResolver getMethodResolver(Object handler) {// 获取用户定义的类Class handlerClass = ClassUtils.getUserClass(handler);// 从缓存中获取ServletHandlerMethodResolverServletHandlerMethodResolver resolver = this.methodResolverCache.get(handlerClass);//如果缓存中不存在if (resolver == null) {synchronized (this.methodResolverCache) {resolver = this.methodResolverCache.get(handlerClass);if (resolver == null) {// 创建一个ServletHandlerMethodResolver对象并存入缓存resolver = new ServletHandlerMethodResolver(handlerClass);this.methodResolverCache.put(handlerClass, resolver);}}}return resolver;}

转载于:https://www.cnblogs.com/wei-zw/p/8797777.html

Spring MVC之DispatcherServlet请求处理(二)相关推荐

  1. Spring MVC的DispatcherServlet – Java开发人员应该知道的10件事

    如果您使用过Spring MVC,那么您应该知道什么是DispatcherServlet? 它实际上是Spring MVC的心脏,确切地说是MVC设计模式或控制器的C语言. 应该由Spring MVC ...

  2. Spring MVC 学习总结(二)——控制器定义与@RequestMapping详解

    Spring MVC 学习总结(二)--控制器定义与@RequestMapping详解 目录 一.控制器定义 1.1.实现接口Controller定义控制器 1.2.使用注解@Controller定义 ...

  3. Spring MVC 使用介绍(二)—— DispatcherServlet

    一.Hello World示例 1.引入依赖 <dependency><groupId>javax.servlet</groupId><artifactId& ...

  4. spring mvc 入门DispatcherServlet转发

    目录 一,配置相关 二,java类测试 三,测试 一,配置相关 maven坐标依赖 <dependencies><!-- spring context --><depen ...

  5. Spring MVC 入门指南(二):@RequestMapping用法详解

    为什么80%的码农都做不了架构师?>>>    一.@RequestMapping 简介 在Spring MVC 中使用 @RequestMapping 来映射请求,也就是通过它来指 ...

  6. Spring mvc 中 DispatcherServlet 的学习和理解

    上图表示当客户请求来到时,spring架构作出响应的流程,可以从图中看到看到请求分发的中心就是 DispatcherServlet 类,DispatcherServlet的任务是将请求发送给Sprin ...

  7. Spring MVC 原理 - DispatcherServlet调用完整过程

    本篇主要讲解了Spring mvc的调用过程,通过这个过程来了解Spring的原理. 进入web.xml中配置的Spring拦截(调度)器: 调用堆栈信息: 开始拦截,这一步主要是根据request获 ...

  8. Spring MVC 之 DispatcherServlet之主题

    如何使用spring mvc 主题 主题是一组静态资源的集合,一般包括影响应用程序界面样式的资源,如样式表和图像文件.本文详细说明使用 Spring MVC 的主题实现不同风格切换. 配置Spring ...

  9. Spring MVC中DispatcherServlet理解总结(1)

    DispatcherServlet在web.xml中的配置 <context-param><!--默认配置文件为/WEB-INF/[servlet名字]-servlet.xml--& ...

最新文章

  1. android 输入法遮挡布局解决方案
  2. 测试站点写入文件权限代码下载
  3. MATLAB新手教程
  4. 什么是web标准??
  5. 拨盘Demo大赛,获奖公布-20170710
  6. 前端工程师面试问题归纳(三、代码类)
  7. 【SPOJ】2713 Can you answer these queries IV
  8. Java乔晓松-android中调用系统拍照功能并显示拍照的图片
  9. FinCEN就非托管加密钱包报告规则征集意见时间将截至今日12时59分
  10. 学习OpenCV——Gabor函数的应用
  11. Matlab绘图设置总结
  12. 使用 Capistrano 和写作 Ruby 迭代边缘部署
  13. 2018 最强“弱密码”排行榜新鲜出炉,123456 再登首
  14. js打开新窗口Window.open()方法
  15. RAM格式与JPG对比
  16. 梦幻西游鸿蒙石之鉴如何捡碎片,梦幻西游鸿蒙石之鉴任务攻略 鸿蒙石之鉴攻略...
  17. Optional使用示例
  18. 条形码控件TBarCode SDK系列教程一(TBarCode OCX篇)
  19. Nvidia TX2+rplidar+autolabor pro1实现自主导航机器人
  20. 云开发山楂岛留言小程序带审核实现教程及源码

热门文章

  1. axure文件如何加密_怎么样给PDF加密?PDF文件如何加密?
  2. python中f点flush是什么函数_Python文件操作及内置函数flush原理解析
  3. 有一种惨:人还在,数据没了...
  4. 技术盘点:2022年云原生架构趋势解读
  5. 阿里 10 年:一个普通技术人的成长之路
  6. 4 个场景揭秘,如何低成本让容器化应用 Serverless 化?
  7. 台式计算机属于,pc机属于什么型计算机
  8. mysql 逻辑型_17. 逻辑运算符
  9. linux访问文档根目录之外的网页_开发文档加载不再卡顿,亿点点提升
  10. python面试常用问题_Python面试中最常见的25个问题-结束