资讯专栏INFORMATION COLUMN

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

fuchenxuan / 2013人阅读

摘要:源码仓库本文仓库三层结构表现层模型业务层持久层工作流程用户前端控制器用户发送请求前端控制器后端控制器根据用户请求查询具体控制器后端控制器前端控制器处理后结果前端控制器视图视图渲染视图前端控制器返回视图前端控制器用户响应结

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}

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

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/73641.html

相关文章

  • spring-MVC源码解读(一)

    摘要:处理器是继前端控制器的后端控制器,在的控制下对具体的用户请求进行处理。由于涉及到具体的用户业务请求,所以一般情况需要程序员根据业务需求开发。 1、mcv整体架构和流程 showImg(https://segmentfault.com/img/bV55Qq?w=860&h=406); 用户发送请求至前端控制器 DispatcherServlet DispatcherServlet 收到...

    I_Am 评论0 收藏0
  • SSM框架运行机制

    摘要:框架搭建首先下载相应的包,对于包有两种方式使用创建依赖从而导入所需的包。总结主要进行页面的请求接受与响应。组件包括前端控制器,处理器映射器,处理器适配器,视图解析器,处理器,视图。 我之前的文章介绍了如何搭建SSH框架以及如何利用这一框架来进行web应用开发,最近我又接触了SSM框架即Spring+SpringMVC+Mybatis三大框架的整合,而且目前该框架就SSH框架而言使用的较...

    winterdawn 评论0 收藏0
  • SSM框架运行机制

    摘要:框架搭建首先下载相应的包,对于包有两种方式使用创建依赖从而导入所需的包。总结主要进行页面的请求接受与响应。组件包括前端控制器,处理器映射器,处理器适配器,视图解析器,处理器,视图。 我之前的文章介绍了如何搭建SSH框架以及如何利用这一框架来进行web应用开发,最近我又接触了SSM框架即Spring+SpringMVC+Mybatis三大框架的整合,而且目前该框架就SSH框架而言使用的较...

    Batkid 评论0 收藏0
  • SpringMVC入门笔记

    摘要:入门笔记简介是一种基于的实现了设计模式的请求驱动类型的轻量级框架,是系开源项目中的一个,和配合使用。配置在中需要添加使用的和映射规则。入门较快,而掌握起来相对较难。 SpringMVC入门笔记 1. 简介 Spring MVC是一种基于Java的实现了Web MVC设计模式的请求驱动类型的轻量级Web框架 ,是Spring系开源项目中的一个,和IoC配合使用。通过策略接口,Spring...

    zhaochunqi 评论0 收藏0
  • spring-mvc注解

    摘要:关键注解的关键注解主要有其中主要是用于标记该类是一个控制器,用于指示的哪一个类或方法来处理请求动作,即用于标识具体的处理器。默认已经装配了作为组件的实现类,而由使用,将请求信息转换为对象。 关键注解 springmvc的关键注解主要有@Controller/@RequestMapping/@RequestParam/@PathVariable/@RequestHeader/@Cooki...

    EdwardUp 评论0 收藏0

发表评论

0条评论

fuchenxuan

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<