Spring MVC之DispatcherServlet请求处理(二)
回顾一下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请求处理(二)相关推荐
- Spring MVC的DispatcherServlet – Java开发人员应该知道的10件事
如果您使用过Spring MVC,那么您应该知道什么是DispatcherServlet? 它实际上是Spring MVC的心脏,确切地说是MVC设计模式或控制器的C语言. 应该由Spring MVC ...
- Spring MVC 学习总结(二)——控制器定义与@RequestMapping详解
Spring MVC 学习总结(二)--控制器定义与@RequestMapping详解 目录 一.控制器定义 1.1.实现接口Controller定义控制器 1.2.使用注解@Controller定义 ...
- Spring MVC 使用介绍(二)—— DispatcherServlet
一.Hello World示例 1.引入依赖 <dependency><groupId>javax.servlet</groupId><artifactId& ...
- spring mvc 入门DispatcherServlet转发
目录 一,配置相关 二,java类测试 三,测试 一,配置相关 maven坐标依赖 <dependencies><!-- spring context --><depen ...
- Spring MVC 入门指南(二):@RequestMapping用法详解
为什么80%的码农都做不了架构师?>>> 一.@RequestMapping 简介 在Spring MVC 中使用 @RequestMapping 来映射请求,也就是通过它来指 ...
- Spring mvc 中 DispatcherServlet 的学习和理解
上图表示当客户请求来到时,spring架构作出响应的流程,可以从图中看到看到请求分发的中心就是 DispatcherServlet 类,DispatcherServlet的任务是将请求发送给Sprin ...
- Spring MVC 原理 - DispatcherServlet调用完整过程
本篇主要讲解了Spring mvc的调用过程,通过这个过程来了解Spring的原理. 进入web.xml中配置的Spring拦截(调度)器: 调用堆栈信息: 开始拦截,这一步主要是根据request获 ...
- Spring MVC 之 DispatcherServlet之主题
如何使用spring mvc 主题 主题是一组静态资源的集合,一般包括影响应用程序界面样式的资源,如样式表和图像文件.本文详细说明使用 Spring MVC 的主题实现不同风格切换. 配置Spring ...
- Spring MVC中DispatcherServlet理解总结(1)
DispatcherServlet在web.xml中的配置 <context-param><!--默认配置文件为/WEB-INF/[servlet名字]-servlet.xml--& ...
最新文章
- android 输入法遮挡布局解决方案
- 测试站点写入文件权限代码下载
- MATLAB新手教程
- 什么是web标准??
- 拨盘Demo大赛,获奖公布-20170710
- 前端工程师面试问题归纳(三、代码类)
- 【SPOJ】2713 Can you answer these queries IV
- Java乔晓松-android中调用系统拍照功能并显示拍照的图片
- FinCEN就非托管加密钱包报告规则征集意见时间将截至今日12时59分
- 学习OpenCV——Gabor函数的应用
- Matlab绘图设置总结
- 使用 Capistrano 和写作 Ruby 迭代边缘部署
- 2018 最强“弱密码”排行榜新鲜出炉,123456 再登首
- js打开新窗口Window.open()方法
- RAM格式与JPG对比
- 梦幻西游鸿蒙石之鉴如何捡碎片,梦幻西游鸿蒙石之鉴任务攻略 鸿蒙石之鉴攻略...
- Optional使用示例
- 条形码控件TBarCode SDK系列教程一(TBarCode OCX篇)
- Nvidia TX2+rplidar+autolabor pro1实现自主导航机器人
- 云开发山楂岛留言小程序带审核实现教程及源码
热门文章
- axure文件如何加密_怎么样给PDF加密?PDF文件如何加密?
- python中f点flush是什么函数_Python文件操作及内置函数flush原理解析
- 有一种惨:人还在,数据没了...
- 技术盘点:2022年云原生架构趋势解读
- 阿里 10 年:一个普通技术人的成长之路
- 4 个场景揭秘,如何低成本让容器化应用 Serverless 化?
- 台式计算机属于,pc机属于什么型计算机
- mysql 逻辑型_17. 逻辑运算符
- linux访问文档根目录之外的网页_开发文档加载不再卡顿,亿点点提升
- python面试常用问题_Python面试中最常见的25个问题-结束