赞
踩
1、DispatcherServlet
前端控制器,SpringMVC里最核心的组件,是整个SpringMVC请求流程的中心,主要流程都是由DispatcherServlet来调用其他组件,而且看名字就知道,它是一个Servlet
2、HandlerMapping
处理器映射器,根据请求来查找对应的处理器Handler,其实就是Controller
3、Handler(Controller)
处理器,由软件工程师开发,其实就是Controller,用于具体处理用户的请求
4、HandlerAdapter
处理器适配器,因为SpringMVC中的Handler可以是任意的形式,只要能处理请求就可以了,但是Servlet需要的处理方法的结构却是固定的,都是以request和response为参数的方法,所以如何让固定的Servlet处理方法调用灵活的Handler来进行处理呢?这就要用到HandlerAdapter了
注:网上看到一个很有意思的形容:
Handler是用来干活的工具
HandlerMapping用来根据需要干的活找到对应的工具
HandlerAdapter是使用工具干活的人
5、ViewResolver
视图解析器,根据视图名称解析成View类型的视图,View是用来渲染页面的,也就是将程序返回的数据填入模板里,生成html或者其他类型的文件,具体使用哪个模板,用什么规则填入数据就是ViewResolver要做的事,然后具体的渲染交给View去做
流程梳理:
1、用户通过浏览器发送请求到前端控制器(DispatcherServlet)
2、前端控制器(DispatcherServlet)将用户请求交给处理器映射器(HandlerMapping)
3-4、处理器映射器(HandlerMapping)找到负责这个请求的处理器(Handler)并和拦截器链一起封装成处理器执行链(HandlerExecutionChain)交给前端控制器(DispatcherServlet)
5、前端控制器(DispatcherServlet)会根据处理器(Handler)找到对应的处理器适配器(HandlerAdaptor)
6-9、处理器适配器(HandlerAdaptor) 会去执行具体的Controller,Controller将处理结果及要跳转的视图封装到ModelAndView返回给处理器适配器(HandlerAdaptor),并在执行Controller前后调用拦截器链
10、处理器适配器(HandlerAdaptor) 将ModelAndView返回给前端控制器(DispatcherServlet)
11、前端控制器(DispatcherServlet)将ModelAndView交给视图解析器(ViewResolver)
12、视图解析器(ViewResolver)将ModelAndView解析为具体的视图(View)返回给前端控制器(DispatcherServlet)
13、前端控制器(DispatcherServlet)调用视图对象,让其自己 (View) 进行渲染(将模型数据填充至视图中) ,形成响应 (HttpResponse)
14、前端控制器(DispatcherServlet)将响应 (HttpResponse) 返回给浏览器
首先我们要先知道SpringMVC的Servlet分为三层HttpServletBean、FrameworkServlet和DispatcherServlet,我们知道Servlet的入口是service方法,FrameworkServlet重写了service方法,我们往里跟代码,最终会来到DispatcherServlet的核心方法doDispatch
- //DispatcherServlet
- 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里包含了handler和拦截器链
- mappedHandler = getHandler(processedRequest);
- if (mappedHandler == null) {
- //找不到处理器,报404
- noHandlerFound(processedRequest, response);
- return;
- }
-
- //根据处理器里的handler获取对应的适配器
- HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());
-
- //处理last-modified请求头
- 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;
- }
- }
-
- //在处理请求前先执行拦截器的preHandle方法,这个方法会返回一个boolean类型的值
- //如果是true,就交给后面的拦截器继续处理,
- //如果是false就表示处理完了,顺便也把response搞定
- if (!mappedHandler.applyPreHandle(processedRequest, response)) {
- return;
- }
-
- //用适配器处理请求,返回ModelAndView
- mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
-
- if (asyncManager.isConcurrentHandlingStarted()) {
- return;
- }
-
- //判断是否需要viewNameTranslator从request里获取view的名字
- applyDefaultViewName(processedRequest, mv);
- //执行拦截器的PostHandle方法
- mappedHandler.applyPostHandle(processedRequest, response, mv);
- }
- catch (Exception ex) {
- dispatchException = ex;
- }
- catch (Throwable err) {
- dispatchException = new NestedServletException("Handler dispatch failed", err);
- }
- //页面渲染,调用拦截器的afterCompletion方法等
- 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()) {
- if (mappedHandler != null) {
- mappedHandler.applyAfterConcurrentHandlingStarted(processedRequest, response);
- }
- }
- else {
- if (multipartRequestParsed) {
- cleanupMultipart(processedRequest);
- }
- }
- }
- }
- //获取处理器,注意这里的mappedHandler里包含了handler和拦截器链
- mappedHandler = getHandler(processedRequest);
首先我们看下18行的getHandler方法,对应流程图中的2-4步
- //DispatcherServlet
- @Nullable
- protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
- if (this.handlerMappings != null) {
- for (HandlerMapping mapping : this.handlerMappings) {
- //逐个使用HandlerMapping去获取Handler,如果获取到了就返回,没获取到就换下一个
- HandlerExecutionChain handler = mapping.getHandler(request);
- if (handler != null) {
- return handler;
- }
- }
- }
- return null;
- }
这里的handlerMappings是个List集合,HandlerMapper有很多实现类,最重要的就是RequestMappingHandlerMapping和BeanNameUrlHandlerMapping,我们记住这两个类,继续看第7行getHandler,进入到AbstractHandlerMapping类里
- //AbstractHandlerMapping
- @Override
- @Nullable
- public final HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
- //获取handler
- Object handler = getHandlerInternal(request);
- if (handler == null) {
- handler = getDefaultHandler();
- }
- if (handler == null) {
- return null;
- }
-
- if (handler instanceof String) {
- String handlerName = (String) handler;
- handler = obtainApplicationContext().getBean(handlerName);
- }
-
- //找到匹配的拦截器和handler一起封装成一个HandlerExecutionChain
- HandlerExecutionChain executionChain = getHandlerExecutionChain(handler, request);
-
- if (logger.isTraceEnabled()) {
- logger.trace("Mapped to " + handler);
- }
- else if (logger.isDebugEnabled() && !request.getDispatcherType().equals(DispatcherType.ASYNC)) {
- logger.debug("Mapped to " + executionChain.getHandler());
- }
-
- if (CorsUtils.isCorsRequest(request)) {
- CorsConfiguration globalConfig = this.corsConfigurationSource.getCorsConfiguration(request);
- CorsConfiguration handlerConfig = getCorsConfiguration(handler, request);
- CorsConfiguration config = (globalConfig != null ? globalConfig.combine(handlerConfig) : handlerConfig);
- executionChain = getCorsHandlerExecutionChain(request, executionChain, config);
- }
-
- return executionChain;
- }
核心逻辑是第6行的getHandlerInternal,getHandlerInternal是个模板方法,最终会调用子类实现,这里有两个重要的实现类,分别是AbstractHandlerMethodMapping和AbstractUrlHandlerMapping,上面我们提到HandlerMapper有两个非常主要的实现类:RequestMappingHandlerMapping和BeanNameUrlHandlerMapping,我们看看这两个类的类图
我们发现RequestMappingHandlerMapping是AbstractHandlerMethodMapping的子类,而BeanNameUrlHandlerMapping是AbstractUrlHandlerMapping的子类
RequestMappingHandlerMapping:主要用来存储RequestMapping注解相关的控制器和url的映射关系
BeanNameUrlHandlerMapping: 主要用来处理Bean name直接以 / 开头的控制器和url的映射关系。
我们最常用的其实还是RequestMappingHandlerMapping,所以我们进入AbstractHandlerMethodMapping的getHandlerInternal方法,继续看
- //AbstractHandlerMethodMapping
- @Override
- protected HandlerMethod getHandlerInternal(HttpServletRequest request) throws Exception {
- //获取requestMapping地址
- String lookupPath = getUrlPathHelper().getLookupPathForRequest(request);
- this.mappingRegistry.acquireReadLock();
- try {
- //查找Handler
- HandlerMethod handlerMethod = lookupHandlerMethod(lookupPath, request);
- return (handlerMethod != null ? handlerMethod.createWithResolvedBean() : null);
- }
- finally {
- this.mappingRegistry.releaseReadLock();
- }
- }
第9行核心方法进去
- //AbstractHandlerMethodMapping
- @Nullable
- protected HandlerMethod lookupHandlerMethod(String lookupPath, HttpServletRequest request) throws Exception {
- List<Match> matches = new ArrayList<>();
- //从mappingRegistry中获取命中的方法
- List<T> directPathMatches = this.mappingRegistry.getMappingsByUrl(lookupPath);
- if (directPathMatches != null) {
- //寻找合适的mapping,根据属性去精确查找,最终防到matches中
- addMatchingMappings(directPathMatches, matches, request);
- }
- if (matches.isEmpty()) {
- // No choice but to go through all mappings...
- addMatchingMappings(this.mappingRegistry.getMappings().keySet(), matches, request);
- }
-
- if (!matches.isEmpty()) {
- Comparator<Match> comparator = new MatchComparator(getMappingComparator(request));
- matches.sort(comparator);
- Match bestMatch = matches.get(0);
- if (matches.size() > 1) {
- if (logger.isTraceEnabled()) {
- logger.trace(matches.size() + " matching mappings: " + matches);
- }
- if (CorsUtils.isPreFlightRequest(request)) {
- return PREFLIGHT_AMBIGUOUS_MATCH;
- }
- Match secondBestMatch = matches.get(1);
- if (comparator.compare(bestMatch, secondBestMatch) == 0) {
- Method m1 = bestMatch.handlerMethod.getMethod();
- Method m2 = secondBestMatch.handlerMethod.getMethod();
- String uri = request.getRequestURI();
- throw new IllegalStateException(
- "Ambiguous handler methods mapped for '" + uri + "': {" + m1 + ", " + m2 + "}");
- }
- }
- request.setAttribute(BEST_MATCHING_HANDLER_ATTRIBUTE, bestMatch.handlerMethod);
- handleMatch(bestMatch.mapping, lookupPath, request);
- return bestMatch.handlerMethod;
- }
- else {
- return handleNoMatch(this.mappingRegistry.getMappings().keySet(), lookupPath, request);
- }
- }
具体看下第9行addMatchingMappings
- private void addMatchingMappings(Collection<T> mappings, List<Match> matches, HttpServletRequest request) {
- for (T mapping : mappings) {
- T match = getMatchingMapping(mapping, request);
- if (match != null) {
- matches.add(new Match(match, this.mappingRegistry.getMappings().get(mapping)));
- }
- }
- }
这里有个mappingRegistry很重要,mappingRegistry.getMappings,返回的是HandlerMethod的map,这一步相当于把匹配到的HandlerMethod封装到Match对象中,最后加到matches集合里,最后排序,取出第一个匹配的Handler返回
我们回到getHandler方法
- //AbstractHandlerMapping
- @Override
- @Nullable
- public final HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
- //获取handler
- Object handler = getHandlerInternal(request);
- if (handler == null) {
- handler = getDefaultHandler();
- }
- if (handler == null) {
- return null;
- }
-
- if (handler instanceof String) {
- String handlerName = (String) handler;
- handler = obtainApplicationContext().getBean(handlerName);
- }
-
- //找到匹配的拦截器和handler一起封装成一个HandlerExecutionChain
- HandlerExecutionChain executionChain = getHandlerExecutionChain(handler, request);
-
- if (logger.isTraceEnabled()) {
- logger.trace("Mapped to " + handler);
- }
- else if (logger.isDebugEnabled() && !request.getDispatcherType().equals(DispatcherType.ASYNC)) {
- logger.debug("Mapped to " + executionChain.getHandler());
- }
-
- if (CorsUtils.isCorsRequest(request)) {
- CorsConfiguration globalConfig = this.corsConfigurationSource.getCorsConfiguration(request);
- CorsConfiguration handlerConfig = getCorsConfiguration(handler, request);
- CorsConfiguration config = (globalConfig != null ? globalConfig.combine(handlerConfig) : handlerConfig);
- executionChain = getCorsHandlerExecutionChain(request, executionChain, config);
- }
-
- return executionChain;
- }
第6行返回的就是刚才的HandlerMethod对象,然后调用getHandlerExecutionChain方法,将HandlerMethod和拦截器链封装成HandlerExecutionChain对象返回
- //用适配器处理请求,返回ModelAndView
- mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
下面看第47行handle方法,点击进到实现类AbstractHandlerMethodAdapter的handle方法中
- @Override
- @Nullable
- public final ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler)
- throws Exception {
-
- return handleInternal(request, response, (HandlerMethod) handler);
- }
继续点击handleInternal进入子类RequestMappingHandlerAdapter的handleInternal方法中
- //RequestMappingHandlerAdapter
- @Override
- protected ModelAndView handleInternal(HttpServletRequest request,
- HttpServletResponse response, HandlerMethod handlerMethod) throws Exception {
-
- ModelAndView mav;
- //检查是否支持当前request的请求方式和session
- checkRequest(request);
-
- //如果需要,在同步块中执行invokeHandlerMethod。
- if (this.synchronizeOnSession) {
- HttpSession session = request.getSession(false);
- if (session != null) {
- Object mutex = WebUtils.getSessionMutex(session);
- synchronized (mutex) {
- mav = invokeHandlerMethod(request, response, handlerMethod);
- }
- }
- else {
- //无HttpSession可用->无需互斥
- mav = invokeHandlerMethod(request, response, handlerMethod);
- }
- }
- else {
- //不需要同步会话
- mav = invokeHandlerMethod(request, response, handlerMethod);
- }
-
- if (!response.containsHeader(HEADER_CACHE_CONTROL)) {
- if (getSessionAttributesHandler(handlerMethod).hasSessionAttributes()) {
- applyCacheSeconds(response, this.cacheSecondsForSessionAttributeHandlers);
- }
- else {
- prepareResponse(response);
- }
- }
-
- return mav;
- }
最终会调用invokeHandlerMethod方法,点击进去
- //RequestMappingHandlerAdapter
- @Nullable
- protected ModelAndView invokeHandlerMethod(HttpServletRequest request,
- HttpServletResponse response, HandlerMethod handlerMethod) throws Exception {
-
- ServletWebRequest webRequest = new ServletWebRequest(request, response);
- try {
- //省略...
-
- invocableMethod.invokeAndHandle(webRequest, mavContainer);
- if (asyncManager.isConcurrentHandlingStarted()) {
- return null;
- }
-
- return getModelAndView(mavContainer, modelFactory, webRequest);
- }
- finally {
- webRequest.requestCompleted();
- }
- }
继续点击10行invokeAndHandle进到类ServletInvocableHandlerMethod中
- public void invokeAndHandle(ServletWebRequest webRequest, ModelAndViewContainer mavContainer,
- Object... providedArgs) throws Exception {
-
- //重点
- Object returnValue = invokeForRequest(webRequest, mavContainer, providedArgs);
- setResponseStatus(webRequest);
-
- if (returnValue == null) {
- if (isRequestNotModified(webRequest) || getResponseStatus() != null || mavContainer.isRequestHandled()) {
- mavContainer.setRequestHandled(true);
- return;
- }
- }
- else if (StringUtils.hasText(getResponseStatusReason())) {
- mavContainer.setRequestHandled(true);
- return;
- }
-
- mavContainer.setRequestHandled(false);
- Assert.state(this.returnValueHandlers != null, "No return value handlers");
- try {
- this.returnValueHandlers.handleReturnValue(
- returnValue, getReturnValueType(returnValue), mavContainer, webRequest);
- }
- catch (Exception ex) {
- if (logger.isTraceEnabled()) {
- logger.trace(formatErrorForReturnValue(returnValue), ex);
- }
- throw ex;
- }
- }
点击5行invokeForRequest进入其父类InvocableHandlerMethod中
- @Nullable
- public Object invokeForRequest(NativeWebRequest request, @Nullable ModelAndViewContainer mavContainer,
- Object... providedArgs) throws Exception {
-
- //获取方法参数
- Object[] args = getMethodArgumentValues(request, mavContainer, providedArgs);
- if (logger.isTraceEnabled()) {
- logger.trace("Arguments: " + Arrays.toString(args));
- }
- //执行具体业务
- return doInvoke(args);
- }
其中doInvoke方法最终会通过反射调用到Controller上的方法,我们具体看看getMethodArgumentValues方法
- protected Object[] getMethodArgumentValues(NativeWebRequest request, @Nullable ModelAndViewContainer mavContainer,
- Object... providedArgs) throws Exception {
-
- //获取Controller对应的方法所有参数,该部分在程序启动时就已经解析好了
- if (ObjectUtils.isEmpty(getMethodParameters())) {
- return EMPTY_ARGS;
- }
- MethodParameter[] parameters = getMethodParameters();
- Object[] args = new Object[parameters.length];
- //遍历所有参数,进行赋值
- for (int i = 0; i < parameters.length; i++) {
- MethodParameter parameter = parameters[i];
- parameter.initParameterNameDiscovery(this.parameterNameDiscoverer);
- args[i] = findProvidedArgument(parameter, providedArgs);
- if (args[i] != null) {
- continue;
- }
- if (!this.resolvers.supportsParameter(parameter)) {
- throw new IllegalStateException(formatArgumentError(parameter, "No suitable resolver"));
- }
- try {
- //解析参数并赋值,这里会根据参数找到对应的解析器进行解析
- args[i] = this.resolvers.resolveArgument(parameter, mavContainer, request, this.dataBinderFactory);
- }
- catch (Exception ex) {
- if (logger.isDebugEnabled()) {
- String error = ex.getMessage();
- if (error != null && !error.contains(parameter.getExecutable().toGenericString())) {
- logger.debug(formatArgumentError(parameter, error));
- }
- }
- throw ex;
- }
- }
- return args;
- }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。