[闹着玩-2]spring-mvc 主要流程

SpringMvc

【源码仓库】
【本文仓库】

三层结构

  • 表现层

    • MVC模型
  • 业务层

    • service
  • 持久层

    • dao

工作流程

用户->前端控制器:用户发送请求
前端控制器-> 后端控制器:根据用户请求查询具体控制器
后端控制器-->前端控制器:处理后结果
前端控制器--> 视图:视图渲染
视图-->前端控制器:返回视图
前端控制器--> 用户:响应结果

简单案例

依赖



    4.0.0

    com.huifer
    mySpringMvcBook
    1.0-SNAPSHOT

    war

    
        UTF-8
        UTF-8
        1.8
        5.1.5.RELEASE
        4.12
    


    
        org.springframework
        spring-beans
        ${spring.version}
    
    
        org.springframework
        spring-core
        ${spring.version}
    
    
        org.springframework
        spring-context
        ${spring.version}
    
    
        org.springframework
        spring-expression
        ${spring.version}
    

    
        org.springframework
        spring-aspects
        ${spring.version}
    
    
        aopalliance
        aopalliance
        1.0
    

    
        org.springframework
        spring-webmvc
        ${spring.version}
    
    
        org.springframework
        spring-web
        ${spring.version}
    


    
    
        javax.servlet.jsp.jstl
        jstl
        1.2
    
    
        javax.servlet
        servlet-api
        2.5
    
    
        org.projectlombok
        lombok
        1.18.4
    
    
        com.fasterxml.jackson.core
        jackson-databind
        2.9.3
    
    
    
        com.fasterxml.jackson.core
        jackson-core
        2.9.3
    
    
    
        com.fasterxml.jackson.core
        jackson-annotations
        2.9.3
    


    
        
            
            
                src/main/java
                
                    **/*.xml
                
            
        
        
            
                org.apache.maven.plugins
                maven-compiler-plugin
                
                    1.8
                    1.8
                    UTF-8
                
            
        
    

spring-config




    


    
    


web.xml





    
        springmvc
        org.springframework.web.servlet.DispatcherServlet
        
            contextConfigLocation
            classpath:spring-mvc-config.xml
        
        
        2

    
    
        springmvc
        /
    

  • controller

    @Controller
    @RequestMapping("item")
    public class ItemController {
        @ResponseBody
        @GetMapping("/query")
        public ModelAndView query() throws Exception {
    
            List itemList = new ArrayList<>();
            itemList.add(new Item("吃的", 3.3, new Date()));
            itemList.add(new Item("玩的", 3.3, new Date()));
            ModelAndView modelAndView = new ModelAndView();
            modelAndView.addObject("itemList", itemList);
            modelAndView.setViewName("/WEB-INF/jsp/item.jsp");
            return modelAndView;
        }
    
    }
  • item.JSP

    <%--
      Created by IntelliJ IDEA.
      User: huifer
      Date: 2019/3/10
      Time: 11:26
      To change this template use File | Settings | File Templates.
    --%>
    <%@ page language="java" contentType="text/html; charset=UTF-8"
             pageEncoding="UTF-8" isELIgnored="false" %>
    
    
    
        ItemList
    
    
    

    ITEM

    ${itemList}

web.xml 中的加载顺序

context-param->listener->filter->servlet

url-parttern 匹配顺序

  1. 精确匹配 ,如/baidu
  2. 目录匹配,如/*
  3. 拓展名匹配,如*.jpg
  4. 默认匹配 ,如/

tomcat中的url-parttern

  • 文件在 ${tomcatHome}/conf/web.xml中
  • 发布到tomcat的web应用共享下面两个配置

       
        
            default
            /
        
    
        
        
            jsp
            *.jsp
            *.jspx
        

此处面试题

为什么在自己的项目中web.xml配置/* 报错。如图

  • 根据tomcat的web.xml配置可以看到 /jsp的拦截是分开的 ,而我们直接用一个/*来拦截那么tomcat将不知道用什么来处理

spring-mvc大致流程源码翻阅

  • 从配置文件中知道前端控制器DispatcherServlet

    springmvc
    org.springframework.web.servlet.DispatcherServlet
    
        contextConfigLocation
        classpath:spring-mvc-config.xml
    
    
    2

在org.springframework.web.servlet.DispatcherServlet 看下面两个方法

  • doService 将访问的数据接收到交给doDispatch
  • 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 {
            try {
                ModelAndView mv = null;
                Object dispatchException = null;

                try {
                    processedRequest = this.checkMultipart(request);
                    multipartRequestParsed = processedRequest != request;
                       // 加载handler
                    mappedHandler = this.getHandler(processedRequest);
                    if (mappedHandler == null) {
                        this.noHandlerFound(processedRequest, response);
                        return;
                    }
                    // handler适配器
                    HandlerAdapter ha = this.getHandlerAdapter(mappedHandler.getHandler());
                    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;
                    }
                    // 适配器执行操作
                    mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
                    if (asyncManager.isConcurrentHandlingStarted()) {
                        return;
                    }

                    this.applyDefaultViewName(processedRequest, mv);
                    mappedHandler.applyPostHandle(processedRequest, response, mv);
                } catch (Exception var20) {
                    dispatchException = var20;
                } catch (Throwable var21) {
                    dispatchException = new NestedServletException("Handler dispatch failed", var21);
                }
                // 操作结果返回
                this.processDispatchResult(processedRequest, response, mappedHandler, mv, (Exception)dispatchException);
            } catch (Exception var22) {
                this.triggerAfterCompletion(processedRequest, response, mappedHandler, var22);
            } catch (Throwable var23) {
                this.triggerAfterCompletion(processedRequest, response, mappedHandler, new NestedServletException("Handler processing failed", var23));
            }

        } finally {
            if (asyncManager.isConcurrentHandlingStarted()) {
                if (mappedHandler != null) {
                    mappedHandler.applyAfterConcurrentHandlingStarted(processedRequest, response);
                }
            } else if (multipartRequestParsed) {
                this.cleanupMultipart(processedRequest);
            }

        }
    }
  • handler怎么来

    • initHandlerMappings(context)
    protected void initStrategies(ApplicationContext context) {
            this.initMultipartResolver(context);
            this.initLocaleResolver(context);
            this.initThemeResolver(context);
            this.initHandlerMappings(context);
            this.initHandlerAdapters(context);
            this.initHandlerExceptionResolvers(context);
            this.initRequestToViewNameTranslator(context);
            this.initViewResolvers(context);
            this.initFlashMapManager(context);
        }
    private void initHandlerMappings(ApplicationContext context) {
        this.handlerMappings = null;
        if (this.detectAllHandlerMappings) {
            Map matchingBeans = BeanFactoryUtils.beansOfTypeIncludingAncestors(context, HandlerMapping.class, true, false);
            if (!matchingBeans.isEmpty()) {
                this.handlerMappings = new ArrayList(matchingBeans.values());
                AnnotationAwareOrderComparator.sort(this.handlerMappings);
            }
        } else {
            try {
                HandlerMapping hm = (HandlerMapping)context.getBean("handlerMapping", HandlerMapping.class);
                this.handlerMappings = Collections.singletonList(hm);
            } catch (NoSuchBeanDefinitionException var3) {
            }
        }

        if (this.handlerMappings == null) {
            // 读取默认配置文件
            this.handlerMappings = this.getDefaultStrategies(context, HandlerMapping.class);
            if (this.logger.isTraceEnabled()) {
                this.logger.trace("No HandlerMappings declared for servlet '" + this.getServletName() + "': using default strategies from DispatcherServlet.properties");
            }
        }

    }
  • 默认配置文件

  • handler适配器也在配置文件中

    
        protected HandlerAdapter getHandlerAdapter(Object handler) throws ServletException {
            if (this.handlerAdapters != null) {
                Iterator var2 = this.handlerAdapters.iterator();
    
                while(var2.hasNext()) {
                    HandlerAdapter adapter = (HandlerAdapter)var2.next();
                      // 是否能够适配
                    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");
        }

    • HttpRequestHandlerAdapter

      public class HttpRequestHandlerAdapter implements HandlerAdapter {
          public HttpRequestHandlerAdapter() {
          }
      // 判断是否是当前类支持的适配器
          public boolean supports(Object handler) {
              return handler instanceof HttpRequestHandler;
          }
      
      // 适配器执行操作
          @Nullable
          public ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
              ((HttpRequestHandler)handler).handleRequest(request, response);
              return null;
          }
      
          public long getLastModified(HttpServletRequest request, Object handler) {
              return handler instanceof LastModified ? ((LastModified)handler).getLastModified(request) : -1L;
          }
      }
      
  • 视图解析

     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) {
                    this.logger.debug("ModelAndViewDefiningException encountered", exception);
                    mv = ((ModelAndViewDefiningException)exception).getModelAndView();
                } else {
                    Object handler = mappedHandler != null ? mappedHandler.getHandler() : null;
                    mv = this.processHandlerException(request, response, handler, exception);
                    errorView = mv != null;
                }
            }
    
            if (mv != null && !mv.wasCleared()) {
                  // 这个地方在做渲染
                this.render(mv, request, response);
                if (errorView) {
                    WebUtils.clearErrorRequestAttributes(request);
                }
            } else if (this.logger.isTraceEnabled()) {
                this.logger.trace("No view rendering, null ModelAndView returned.");
            }
    
            if (!WebAsyncUtils.getAsyncManager(request).isConcurrentHandlingStarted()) {
                if (mappedHandler != null) {
                    mappedHandler.triggerAfterCompletion(request, response, (Exception)null);
                }
    
            }
        }
    protected void render(ModelAndView mv, HttpServletRequest request, HttpServletResponse response) throws Exception {
            Locale locale = this.localeResolver != null ? this.localeResolver.resolveLocale(request) : request.getLocale();
            response.setLocale(locale);
            String viewName = mv.getViewName();
            View view;
            if (viewName != null) {
                // 视图解析器
                view = this.resolveViewName(viewName, mv.getModelInternal(), locale, request);
                if (view == null) {
                    throw new ServletException("Could not resolve view with name '" + mv.getViewName() + "' in servlet with name '" + this.getServletName() + "'");
                }
            } else {
                view = mv.getView();
                if (view == null) {
                    throw new ServletException("ModelAndView [" + mv + "] neither contains a view name nor a View object in servlet with name '" + this.getServletName() + "'");
                }
            }
    
            if (this.logger.isTraceEnabled()) {
                this.logger.trace("Rendering view [" + view + "] ");
            }
    
            try {
                if (mv.getStatus() != null) {
                    response.setStatus(mv.getStatus().value());
                }
                // 视图的渲染函数渲染到页面上
                view.render(mv.getModelInternal(), request, response);
            } catch (Exception var8) {
                if (this.logger.isDebugEnabled()) {
                    this.logger.debug("Error rendering view [" + view + "]", var8);
                }
    
                throw var8;
            }
        }
    @Nullable
    protected View resolveViewName(String viewName, @Nullable Map model, Locale locale, HttpServletRequest request) throws Exception {
        if (this.viewResolvers != null) {
            Iterator var5 = this.viewResolvers.iterator();
    
            while(var5.hasNext()) {
                // 视图解析器
                ViewResolver viewResolver = (ViewResolver)var5.next();
                View view = viewResolver.resolveViewName(viewName, locale);
                if (view != null) {
                    return view;
                }
            }
        }
    
        return null;
    }

spring-mvc请求具体流程图

用户->前端控制器\n org.springframework.web.servlet.DispatcherServlet\n 用来接收响应以及返回响应结果:1.用户发送请求 
前端控制器\n org.springframework.web.servlet.DispatcherServlet\n 用来接收响应以及返回响应结果 -> HandlerMapper : 2.根据url进行处理
HandlerMapper -> 前端控制器\n org.springframework.web.servlet.DispatcherServlet\n 用来接收响应以及返回响应结果:3.将handlerMapper处理结果给前端控制器
前端控制器\n org.springframework.web.servlet.DispatcherServlet\n 用来接收响应以及返回响应结果-> HandlerAdapter:4.给适配器确认具体的适配器,比如我们这里给了HttpRequestHandlerAdapter
HandlerAdapter ->ModelAndView:5.用来执行业务操作
ModelAndView ->HandlerAdapter: 6.执行完成给HandlerAdapter返回
HandlerAdapter->前端控制器\n org.springframework.web.servlet.DispatcherServlet\n 用来接收响应以及返回响应结果:7.返回一个modelAndView
前端控制器\n org.springframework.web.servlet.DispatcherServlet\n 用来接收响应以及返回响应结果-> ViewResolver 视图解析器 :8.将第7步中的view进行解析
ViewResolver 视图解析器->前端控制器\n org.springframework.web.servlet.DispatcherServlet\n 用来接收响应以及返回响应结果:9.解析结果返回
前端控制器\n org.springframework.web.servlet.DispatcherServlet\n 用来接收响应以及返回响应结果 -> View : 9.将model渲染到view中
View->前端控制器\n org.springframework.web.servlet.DispatcherServlet\n 用来接收响应以及返回响应结果: 10.view 结果返回给前端控制器
前端控制器\n org.springframework.web.servlet.DispatcherServlet\n 用来接收响应以及返回响应结果 --> 用户:查看到完整的网页

你可能感兴趣的:(java,spring-mvc)