SpringMVC之注解替换SpringMVC配置文件(结业篇)

前面已经学习过了SpringMVC系列内容,接下来学习我的SpringMvc配置文件篇,本篇也是学习SpringMVC框架的最后一篇。学习资源

一、第一部分

1、web.xml替代介绍

(1)大概介绍

使用配置类和注解代替web.xml和SpringMVC配置文件的功能
在这里插入图片描述

(2)AbstractAnnotationConfigDispatcherServletInitializer类介绍

继承了这个类的类和web.xml是一样的道理,是在服务器启动之前加载,这样不影响性能。
在这里插入图片描述

比如这里的过滤器就可以在里面写了

(3)配置过滤器

在这里插入图片描述

2、SpringMVC的配置文件

(1)配合视图解析器

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

(2)配合访问

在这里插入图片描述
其他的controller就和其他的差不多了。

(3)设置默认servlet、拦截器、view-controller

  • 首先实现一个接口
    在这里插入图片描述
    在这里插入图片描述
  • 实现defaultServlet
    在这里插入图片描述
  • 实现拦截器
    在这里插入图片描述
  • 配合view-controller
    在这里插入图片描述
  • 文件上传解析啊
    在这里插入图片描述
  • 配置异常处理器
    在这里插入图片描述

二、复习和总结部分

(一)SpringMVC执行流程

1、SpringMVC常用组件

在这里插入图片描述

(1)DispatcherServlet前端控制器

在这里插入图片描述

(2)HandlerMapping处理器映射器(就是controller)

在这里插入图片描述

(3)Handler处理器,我们开发

在这里插入图片描述
它去找到对应的处理器,交给HandlerAdapter调用。

(4)HandlerAdapter处理器适配器

在这里插入图片描述
就是调用相对应的控制器方法的

(5)ViewResolver视图解析器

在这里插入图片描述
根据不同的请求,创建不同的视图解析器。

(6)View视图

在这里插入图片描述
就是展示数据

2、DispatcherServlet初始化过程

  • 首先了解DispatcherServlet就是个servlet,它肯定遵守servlet的声明周期的
    在这里插入图片描述
  • 初始hau过程
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
  • 执行完了上面过程后,把我们的IOC容器,共享到了我们的共享数据域。
    在这里插入图片描述
    在这里插入图片描述
  • init的初始化过程
    在这里插入图片描述
    在这里插入图片描述

3、DispatcherServlet服务过程

(1)首先看跳转过程

调用组件处理请求
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
因为父类写了个abstract方法,所以这方法就要去看我们的子类写的了
在这里插入图片描述
在这里插入图片描述
所以重点要来看的doDispatcher

(2)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);

            // Determine handler for the current request.
            /*
            	mappedHandler:调用链
                包含handler、interceptorList、interceptorIndex
            	handler:浏览器发送的请求所匹配的控制器方法
            	interceptorList:处理控制器方法的所有拦截器集合
            	interceptorIndex:拦截器索引,控制拦截器afterCompletion()的执行
            */
            mappedHandler = getHandler(processedRequest);
            if (mappedHandler == null) {
                noHandlerFound(processedRequest, response);
                return;
            }

            // Determine handler adapter for the current request.
           	// 通过控制器方法创建相应的处理器适配器,调用所对应的控制器方法
            HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());

            // Process last-modified header, if supported by the handler.
            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()
            if (!mappedHandler.applyPreHandle(processedRequest, response)) {
                return;
            }

            // Actually invoke the handler.
            // 由处理器适配器调用具体的控制器方法,最终获得ModelAndView对象
            mv = ha.handle(processedRequest, response, mappedHandler.getHandler());

            if (asyncManager.isConcurrentHandlingStarted()) {
                return;
            }

            applyDefaultViewName(processedRequest, mv);
            // 调用拦截器的postHandle()
            mappedHandler.applyPostHandle(processedRequest, response, mv);
        }
        catch (Exception ex) {
            dispatchException = ex;
        }
        catch (Throwable err) {
            // As of 4.3, we're processing Errors thrown from handler methods as well,
            // making them available for @ExceptionHandler methods and other scenarios.
            dispatchException = new NestedServletException("Handler dispatch failed", err);
        }
        // 后续处理:处理模型数据和渲染视图
        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()) {
            // Instead of postHandle and afterCompletion
            if (mappedHandler != null) {
                mappedHandler.applyAfterConcurrentHandlingStarted(processedRequest, response);
            }
        }
        else {
            // Clean up any resources used by a multipart request.
            if (multipartRequestParsed) {
                cleanupMultipart(processedRequest);
            }
        }
    }
}
d>processDispatchResult()
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) {
            logger.debug("ModelAndViewDefiningException encountered", exception);
            mv = ((ModelAndViewDefiningException) exception).getModelAndView();
        }
        else {
            Object handler = (mappedHandler != null ? mappedHandler.getHandler() : null);
            mv = processHandlerException(request, response, handler, exception);
            errorView = (mv != null);
        }
    }

    // Did the handler return a view to render?
    if (mv != null && !mv.wasCleared()) {
        // 处理模型数据和渲染视图
        render(mv, request, response);
        if (errorView) {
            WebUtils.clearErrorRequestAttributes(request);
        }
    }
    else {
        if (logger.isTraceEnabled()) {
            logger.trace("No view rendering, null ModelAndView returned.");
        }
    }

    if (WebAsyncUtils.getAsyncManager(request).isConcurrentHandlingStarted()) {
        // Concurrent handling started during a forward
        return;
    }

    if (mappedHandler != null) {
        // Exception (if any) is already handled..
        // 调用拦截器的afterCompletion()
        mappedHandler.triggerAfterCompletion(request, response, null);
    }
}

(3)执行流程

  • 用户向服务器发送请求,请求被SpringMVC 前端控制器 DispatcherServlet捕获。

  • DispatcherServlet对请求URL进行解析,得到请求资源标识符(URI),判断请求URI对应的映射:

    • 不存在

      • 再判断是否配置了mvc:default-servlet-handler
      • 如果没配置,则控制台报映射查找不到,客户端展示404错误
      • 如果有配置,则访问目标资源(一般为静态资源,如:JS,CSS,HTML),找不到客户端也会展示404错误
    • 存在则执行下面的流程

      • 根据该URI,调用HandlerMapping获得该Handler配置的所有相关的对象(包括Handler对象以及Handler对象对应的拦截器),最后以HandlerExecutionChain执行链对象的形式返回。
      • DispatcherServlet 根据获得的Handler,选择一个合适的HandlerAdapter。
      • 如果成功获得HandlerAdapter,此时将开始执行拦截器的preHandler(…)方法【正向】
      • 提取Request中的模型数据,填充Handler入参,开始执行Handler(Controller)方法,处理请求。在填充Handler的入参过程中,根据你的配置,Spring将帮你做一些额外的工作:
        • HttpMessageConveter: 将请求消息(如Json、xml等数据)转换成一个对象,将对象转换为指定的响应信息
        • 数据转换:对请求消息进行数据转换。如String转换成Integer、Double等
        • 数据格式化:对请求消息进行数据格式化。 如将字符串转换成格式化数字或格式化日期等
        • 数据验证: 验证数据的有效性(长度、格式等),验证结果存储到BindingResult或Error中
      • Handler执行完成后,向DispatcherServlet 返回一个ModelAndView对象。
      • 此时将开始执行拦截器的postHandle(…)方法【逆向】。
      • 根据返回的ModelAndView(此时会判断是否存在异常:如果存在异常,则执行HandlerExceptionResolver进行异常处理)选择一个适合的ViewResolver进行视图解析,根据Model和View,来渲染视图。
      • 渲染视图完毕执行拦截器的afterCompletion(…)方法【逆向】。
      • 将渲染结果返回给客户端。
  • 最后再来看一下狂神大哥画的一个流程图理解一下吧。
    在这里插入图片描述

  • 2
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值