SpringMVC_执行流程
Spring MVC框架简介
Spring MVC是什么呢,它是属于Spring FrameWork的后续产品,已经融合在Spring Web Flow里面。 Spring的MVC框架主要由DispatcherServlet、处理器映射、处理器(控制器)、视图解析器、视图组成。可以简单的把springMVC理解为是spring的一个模块(类似AOP,IOC这样的模块),网络上经常会说springMVC和spring无缝集成,其实springMVC就是spring的一个子模块,所以根本不需要同spring进行整合。
Spring MVC框架提供了构建web应用程序的全功能MVC模块,使用了Spring可插入架构,可以选择是使用内置的Spring web框架还是struts这样的web框架,通过接口,Spring 框架是高度可配置的,而且包含多种视图技术。Spring MVC 框架并不知道使用视图,Spring MVC 分离了控制器、模型对象、分派器以及处理程序对象的角色,这种分离让它们更容易进行定制。
Spring MVC原理图
DispatcherServlet:作为前端控制器,整个流程控制的中心,控制其它组件执行,统一调度,降低组件之间的耦合性,提高每个组件的扩展性。
ViewResolver:通过扩展视图解析器,支持更多类型的视图解析,例如:jsp、freemarker、pdf、excel等。
HandlerMapping:通过扩展处理器映射器实现不同的映射方式,例如:配置文件方式,实现接口方式,注解方式等。
HandlAdapter:通过扩展处理器适配器,支持更多类型的处理器。
SpringMVC运行原理
我们再来看看SpringMVC的流程:
- 用户发送请求至前端控制器DispatcherServlet。
- DispatcherServlet收到请求调用HandlerMapping处理器映射器。
- 处理器映射器找到具体的处理器,生成处理器对象及处理器拦截器一并返回给DispatcherServlet。
- DispatcherServlet调用HandlerAdapter处理器适配器。
- HandlerAdapter经过适配调用具体的处理器。
- Controller执行完成返回ModelAndView。
- HandlerAdapter将controller执行结果ModelAndView返回给DispatcherServlet。
- DispatcherServlet将ModelAndView传给ViewReslover视图解析器。
- ViewReslover解析后返回具体View。
- DispatcherServlet根据View进行渲染视图。
- DispatcherServlet响应用户,DispatcherServlet也是整个Spring MVC的核心,它负责接收HTTP请求组织协调Spring MVC的各个组成部分。
HandlerMapping
HandlerMapping(如:BeanNameUrlHandlerMapping)是请求映射处理器,也就是通过请求的url找到对应的逻辑处理单元(Controller),注意这里只是建立请求与Controller的映射关系,最终的处理是通过HandlerAdapter来进行处理的。
DispatcherServlet的初始化中会调用initStrategies()方法,实际上HandlerMapping的初始化是调用initStrategies()中的initHandlerMappings(context);
HandlerMapping的任务就是建立url与Bean(Controller)的对应关系,并将对应关系保存在handlerMap中;
对应关系在HandlerMapping初始化的时候就已经建立好了;
当请求到来时,会通过DispatcherServlet找到HandlerMapping,然后通过请求的url在handlerMap中找到对应的Controller,至此HandlerMapping的任务完成了,下一步就是HandlerAdapter出场了。
HandlerAdapter
HandlerMapping在初始化时就将@RequestMapping对应的url与Controller建立了对应关系,前端的Http请求通过对应关系找到Controller,这就是HandlerMapping的使命,接下来就是HandlerAdapter来进行处理了。在HandlerMapping中有讲到DispatcherServlet的初始化中会调用initStrategies()方法,这里面也包含了HanderAdapter的初始化initHandlerAdapters(context);
同HandlerMapping初始化一样,默认的HanderAdapter实现也是配置在DispatcherServlet.properties文件中。
org.springframework.web.servlet.HandlerAdapter=org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter,\ org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter,\ org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter
从配置可以看出,HandlerAdapter默认有三种类型的实现,分别是:HttpRequestHandlerAdapter、SimpleControllerHandlerAdapter、AnnotationMethodHandlerAdapter。
回到DispatcherServlet中来,看到请求处理的方法doDispatch()方法中有这么一段:
mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
这段就是通过HandlerMapping返回的Handler,来找到对应的Controller执行相应的逻辑,下面我们来具体看一下内部实现:
//重点看一下AnnotationMethodHandlerAdapter的handler方法 public ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { //获取class对象 Class<?> clazz = ClassUtils.getUserClass(handler); //检查class对象是否含有SessionAttributes注解 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 { checkAndPrepare(request, response, true); } // Execute invokeHandlerMethod in synchronized block if required. if (this.synchronizeOnSession) { HttpSession session = request.getSession(false); if (session != null) { Object mutex = WebUtils.getSessionMutex(session); synchronized (mutex) { return invokeHandlerMethod(request, response, handler); } } } //重点是invoke方法来做的调用 return invokeHandlerMethod(request, response, handler); } protected ModelAndView invokeHandlerMethod(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { //我们知道handler就是从上一步HandlerMapping拿到的Controller,这里通过handler拿到HandlerMethodResolver //那HandlerMethodResolver到底是个什么鬼?它里面主要是存储Controller中方法上@RequestMapping的url以及所有的方法 ServletHandlerMethodResolver methodResolver = getMethodResolver(handler); //通过methodResolver与当前的request进行匹配,通过请求的url找到需要调用的方法 Method handlerMethod = methodResolver.resolveHandlerMethod(request); ServletHandlerMethodInvoker methodInvoker = new ServletHandlerMethodInvoker(methodResolver); ServletWebRequest webRequest = new ServletWebRequest(request, response); ExtendedModelMap implicitModel = new BindingAwareModelMap(); //重点看该方法调用,看下面具体源码 Object result = methodInvoker.invokeHandlerMethod(handlerMethod, handler, webRequest, implicitModel); ModelAndView mav = methodInvoker.getModelAndView(handlerMethod, handler.getClass(), result, implicitModel, webRequest); methodInvoker.updateModelAttributes(handler, (mav != null ? mav.getModel() : null), implicitModel, webRequest); return mav; } public final Object invokeHandlerMethod(Method handlerMethod, Object handler, NativeWebRequest webRequest, ExtendedModelMap implicitModel) throws Exception { Method handlerMethodToInvoke = BridgeMethodResolver.findBridgedMethod(handlerMethod); try { boolean debug = logger.isDebugEnabled(); for (String attrName : this.methodResolver.getActualSessionAttributeNames()) { Object attrValue = this.sessionAttributeStore.retrieveAttribute(webRequest, attrName); if (attrValue != null) { implicitModel.addAttribute(attrName, attrValue); } } for (Method attributeMethod : this.methodResolver.getModelAttributeMethods()) { Method attributeMethodToInvoke = BridgeMethodResolver.findBridgedMethod(attributeMethod); Object[] args = resolveHandlerArguments(attributeMethodToInvoke, handler, webRequest, implicitModel); if (debug) { logger.debug("Invoking model attribute method: " + attributeMethodToInvoke); } String attrName = AnnotationUtils.findAnnotation(attributeMethod, ModelAttribute.class).value(); if (!"".equals(attrName) && implicitModel.containsAttribute(attrName)) { continue; } ReflectionUtils.makeAccessible(attributeMethodToInvoke); Object attrValue = attributeMethodToInvoke.invoke(handler, args); if ("".equals(attrName)) { Class<?> resolvedType = GenericTypeResolver.resolveReturnType(attributeMethodToInvoke, handler.getClass()); attrName = Conventions.getVariableNameForReturnType(attributeMethodToInvoke, resolvedType, attrValue); } if (!implicitModel.containsAttribute(attrName)) { implicitModel.addAttribute(attrName, attrValue); } } //这里即将调用方法的参数,对参数进行处理 Object[] args = resolveHandlerArguments(handlerMethodToInvoke, handler, webRequest, implicitModel); if (debug) { logger.debug("Invoking request handler method: " + handlerMethodToInvoke); } ReflectionUtils.makeAccessible(handlerMethodToInvoke); //将参数传入,利用反射来进行方法调用 return handlerMethodToInvoke.invoke(handler, args); } catch (IllegalStateException ex) { // Internal assertion failed (e.g. invalid signature): // throw exception with full handler method context... throw new HandlerMethodInvocationException(handlerMethodToInvoke, ex); } catch (InvocationTargetException ex) { // User-defined @ModelAttribute/@InitBinder/@RequestMapping method threw an exception... ReflectionUtils.rethrowException(ex.getTargetException()); return null; } }
进行到这里已经调用完了方法,再回到上一步看看返回值的情况:
//根据handler处理的结果,封装一个ModelAndView给前端 public ModelAndView getModelAndView(Method handlerMethod, Class<?> handlerType, Object returnValue, ExtendedModelMap implicitModel, ServletWebRequest webRequest) throws Exception { ResponseStatus responseStatus = AnnotatedElementUtils.findMergedAnnotation(handlerMethod, ResponseStatus.class); if (responseStatus != null) { HttpStatus statusCode = responseStatus.code(); String reason = responseStatus.reason(); if (!StringUtils.hasText(reason)) { webRequest.getResponse().setStatus(statusCode.value()); } else { webRequest.getResponse().sendError(statusCode.value(), reason); } // to be picked up by the RedirectView webRequest.getRequest().setAttribute(View.RESPONSE_STATUS_ATTRIBUTE, statusCode); this.responseArgumentUsed = true; } // Invoke custom resolvers if present... if (customModelAndViewResolvers != null) { for (ModelAndViewResolver mavResolver : customModelAndViewResolvers) { ModelAndView mav = mavResolver.resolveModelAndView( handlerMethod, handlerType, returnValue, implicitModel, webRequest); if (mav != ModelAndViewResolver.UNRESOLVED) { return mav; } } } //以下是判断返回值的各种类型,给出不同的处理 if (returnValue instanceof HttpEntity) { handleHttpEntityResponse((HttpEntity<?>) returnValue, webRequest); return null; } //@ResponseBody注解的处理 else if (AnnotationUtils.findAnnotation(handlerMethod, ResponseBody.class) != null) { handleResponseBody(returnValue, webRequest); return null; } //看这里,就是我们很熟悉的ModelAndView的处理 else if (returnValue instanceof ModelAndView) { ModelAndView mav = (ModelAndView) returnValue; mav.getModelMap().mergeAttributes(implicitModel); return mav; } //返回Model else if (returnValue instanceof Model) { return new ModelAndView().addAllObjects(implicitModel).addAllObjects(((Model) returnValue).asMap()); } //返回View else if (returnValue instanceof View) { return new ModelAndView((View) returnValue).addAllObjects(implicitModel); } //@ModelAttribute注解的处理 else if (AnnotationUtils.findAnnotation(handlerMethod, ModelAttribute.class) != null) { addReturnValueAsModelAttribute(handlerMethod, handlerType, returnValue, implicitModel); return new ModelAndView().addAllObjects(implicitModel); } //返回Map else if (returnValue instanceof Map) { return new ModelAndView().addAllObjects(implicitModel).addAllObjects((Map<String, ?>) returnValue); } //返回String else if (returnValue instanceof String) { return new ModelAndView((String) returnValue).addAllObjects(implicitModel); } //返回null的处理 else if (returnValue == null) { // Either returned null or was 'void' return. if (this.responseArgumentUsed || webRequest.isNotModified()) { return null; } else { // Assuming view name translation... return new ModelAndView().addAllObjects(implicitModel); } } else if (!BeanUtils.isSimpleProperty(returnValue.getClass())) { // Assume a single model attribute... addReturnValueAsModelAttribute(handlerMethod, handlerType, returnValue, implicitModel); return new ModelAndView().addAllObjects(implicitModel); } else { throw new IllegalArgumentException("Invalid handler method return value: " + returnValue); } }
下面来看一下ModelAndView是个什么?
//根据handler处理的结果,封装一个ModelAndView给前端 public ModelAndView getModelAndView(Method handlerMethod, Class<?> handlerType, Object returnValue, ExtendedModelMap implicitModel, ServletWebRequest webRequest) throws Exception { ResponseStatus responseStatus = AnnotatedElementUtils.findMergedAnnotation(handlerMethod, ResponseStatus.class); if (responseStatus != null) { HttpStatus statusCode = responseStatus.code(); String reason = responseStatus.reason(); if (!StringUtils.hasText(reason)) { webRequest.getResponse().setStatus(statusCode.value()); } else { webRequest.getResponse().sendError(statusCode.value(), reason); } // to be picked up by the RedirectView webRequest.getRequest().setAttribute(View.RESPONSE_STATUS_ATTRIBUTE, statusCode); this.responseArgumentUsed = true; } // Invoke custom resolvers if present... if (customModelAndViewResolvers != null) { for (ModelAndViewResolver mavResolver : customModelAndViewResolvers) { ModelAndView mav = mavResolver.resolveModelAndView( handlerMethod, handlerType, returnValue, implicitModel, webRequest); if (mav != ModelAndViewResolver.UNRESOLVED) { return mav; } } } //以下是判断返回值的各种类型,给出不同的处理 if (returnValue instanceof HttpEntity) { handleHttpEntityResponse((HttpEntity<?>) returnValue, webRequest); return null; } //@ResponseBody注解的处理 else if (AnnotationUtils.findAnnotation(handlerMethod, ResponseBody.class) != null) { handleResponseBody(returnValue, webRequest); return null; } //看这里,就是我们很熟悉的ModelAndView的处理 else if (returnValue instanceof ModelAndView) { ModelAndView mav = (ModelAndView) returnValue; mav.getModelMap().mergeAttributes(implicitModel); return mav; } //返回Model else if (returnValue instanceof Model) { return new ModelAndView().addAllObjects(implicitModel).addAllObjects(((Model) returnValue).asMap()); } //返回View else if (returnValue instanceof View) { return new ModelAndView((View) returnValue).addAllObjects(implicitModel); } //@ModelAttribute注解的处理 else if (AnnotationUtils.findAnnotation(handlerMethod, ModelAttribute.class) != null) { addReturnValueAsModelAttribute(handlerMethod, handlerType, returnValue, implicitModel); return new ModelAndView().addAllObjects(implicitModel); } //返回Map else if (returnValue instanceof Map) { return new ModelAndView().addAllObjects(implicitModel).addAllObjects((Map<String, ?>) returnValue); } //返回String else if (returnValue instanceof String) { return new ModelAndView((String) returnValue).addAllObjects(implicitModel); } //返回null的处理 else if (returnValue == null) { // Either returned null or was 'void' return. if (this.responseArgumentUsed || webRequest.isNotModified()) { return null; } else { // Assuming view name translation... return new ModelAndView().addAllObjects(implicitModel); } } else if (!BeanUtils.isSimpleProperty(returnValue.getClass())) { // Assume a single model attribute... addReturnValueAsModelAttribute(handlerMethod, handlerType, returnValue, implicitModel); return new ModelAndView().addAllObjects(implicitModel); } else { throw new IllegalArgumentException("Invalid handler method return value: " + returnValue); } }
- HanderAdapter从上一步HandlerMapping拿到Controller;
- 通过Controller,经过反射拿到Controller中@requestMapping上url与方法的对应关系,返回ServletHandlerMethodResolver;
- 通过request请中的url与ServletHandlerMethodResolver中的mappings匹配,可以找到需要调用的方法;
- 利用反射调用找到的方法,返回Object;
- 处理返回结果,根据不同的返回值类型(ModelAndView、String、Map、View等)进行处理后,封装成ModelAndView返回给前台。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· 使用C#创建一个MCP客户端
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 按钮权限的设计及实现