首页 > 编程语言 >阿里Java二面:说说Spring MVC执行流程及原理?这样聊能吊打面试官

阿里Java二面:说说Spring MVC执行流程及原理?这样聊能吊打面试官

时间:2023-07-05 21:35:21浏览次数:50  
标签:聊能 面试官 拦截器 请求 视图 吊打 controller ModelAndView 执行

面试找虐

博主之前每次去面试必问的问题:“讲一下spring mvc的执行流程以及常用组件的作用”;
记得第一次和面试官说了大概的流程是这样的:“服务器收到一个请求后会先去HandlerMapping中匹配url,找到url之后用HandlerAdapter 适配器去执行这个控制器(controller层),执行完之后返回一个modelAndView,然后通过视图解析器ViewResolver解析后得到一个view对象,这个view就是渲染好的jsp页面,返回给前端页面”;
(等了一会看着我)面试官:“   就这样。。。没啦?”;
懵逼的我:“嗯,没了”;
面试官:“那你回家等消息吧!”;

其实吧,博主说得没错,只是说少了,不够详细,如果是面试初级java开发,这样讲是没问题的,妥妥地给过了,但我是谁啊,我可是要成为架构师的人啊! 回答出这种答案,老板怎么放心把项目交给我呢。于是啊,吸取了教训,我就在家潜心研究,经过七七四十九天的研究、九九八十一次的练习,终于让我掌握了这门核心技术;

什么是Spring mvc

SpringMVC是一种web层mvc框架;是spring的一个模块,拥有spring的特性,通过策略接口,Spring框架是高度可配置的,而且包含多种视图技术,例如 JavaServer Pages(JSP)技术、Velocity、Tiles、iText 和 POI。Spring MVC 框架并不知道使用的视图,所以不会强迫您只使用 JSP 技术。Spring的MVC框架主要由DispatcherServlet、处理器映射、处理器(控制器)、视图解析器、视图组成。

都知道叫做spring mvc,mvc是什么东东呢?其实就是三层架构, 在过去架构都是两层的,就是浏览器通过servlet后直接访问JSP页面,也就是说所有的java代码都是在jsp页面里面写的,就连访问数据库也是在jsp页面,小型项目这样开发没什么问题,因为快嘛,但是大型项目是需要迭代的,是需要增加功能和模块的,你这么写的话,我后期维护起来很麻烦啊;而且java代码和html标签混搭,这样代码的可读性也不高;所以就衍生出了MVC三层架构

 

  • M : 表示mode,翻译成中文叫做模型,对应数据库;
  • V : 表示View,翻译为中文叫做视图,对应前端的页面,比如jsp
  • C : 表示 Controller,翻译是控制层,对应servlet的请求映射;

Spring MVC执行原理

终于到重点了,其实我在开头的时候已经答对了一半了,只是呢,少了一个叫做拦截器的东东,还有一些其他的细节,看下面这张图就明白了

 

Spring mvc 执行流程

  1. 服务器收到请求后,servlet 会将所有的请求都交给前端控制器(DispatcherServlet)处理;
  1. 前端控制器(DispatcherServlet)先调用HandlerMapping(处理器映射器),handlerMapping 根据请求url查找控制器(handler),返回一个 HandlerExecutionChain(处理器执行链) ,HandlerExecutionChain中除了控制器的信息之外,还有拦截器的信息;
  1. 接着将HandlerExecutionChain(处理器执行链)返回给 前端控制器(DispatcherServlet),调用适配器之前会先执行前置拦截器的代码,接着 DispatcherServlet 调用 HandlerAdapter(适配器)执行controller 层的代码内容,也就是带@Controller注解的类里面的代码,返回一个ModelAndView (逻辑视图);注意,这里的逻辑视图还不是真正的jsp页面;因为它还没经过渲染;再一次执行后置拦截器;
  2. 到这一步,DispatcherServlet就会调用ViewResolver(视图解析器)来解析ModelAndView 对象,得到一个View(视图),这个视图就是已经渲染好了的jsp页面了,然后把页面返回给前端之前再执行一次拦截器;

在mvc里面,最重要的无非就这几样 DispatcherServlet 、 HandlerMapping 、 HandlerExecutionChain 、 HandlerInterceptor拦截器、 HandlerAdapter、 ModelAndView、ViewResolver 、 View;别着急,我们一个个讲解它们的作用是什么;

DispatcherServlet

DispatcherServlet 的中文叫做前端控制器 ,也就叫中央调度器,用户发送的所有请求都会经过这个接口,由Servlet调用,是用来拦截所有请求的url的入口,并根据url地址分发到不同的controller ;在web.xml中配置后即可使用


<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" version="3.0">
  <display-name>SpringMVC_01</display-name>
  <!-- 注册中央调度器 -->
  <servlet>
    <servlet-name>springmvc</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <!-- tomcat启动时自动创建servlet,数字越小优先级越高(>0) -->
    <load-on-startup>1</load-on-startup>
  </servlet>
  
  <servlet-mapping>
    <servlet-name>springmvc</servlet-name>
    <!-- 拦截所有请求 -->
    <url-pattern>/</url-pattern>
  </servlet-mapping>

</web-app>

HandlerMapping

HandlerMapping的作用就是解析请求链接,然后根据请求链接找到执行这个请求的类(HandlerMapping所说的handler,也就是我们写的Controller或是Action),也叫做控制器映射器,如果未匹配到控制器,则返回404错误;

HandlerExecutionChain

HandlerExecutionChain 是Handler的执行链,我叫它控制器执行链,包含控制器对象handler、拦截器 interceptor。所以HandlerExecutionChain 提供了getHandler、getInterceptors方法,配置文件中配置的interceptor都会加入到HandlerExecutionChain;需要注意的是,拦截器的列表里面除了我们配置的拦截器之外,还有一个springmvc自己维护的拦截器;

HandlerInterceptor

控制器的拦截器,一般都是作为扩展使用,一共有三个方法:

  • preHandle() :在业务处理器处理请求之前被调用。预处理,可以进行编码、安全控制、权限校验等处理;preHandle有一个boolen类型的返回值,返回 true 表示正常执行,返回 false 表示拦截请求.如果返回 false ,postHandle() 和 afterCompletion() 方法都不会执行;
  • postHandle() :在业务处理器处理请求执行完成后调用,生成视图之前执行。后处理(调用了Service并返回ModelAndView,但未进行页面渲染),有机会修改ModelAndView ;当controller层抛出异常后不会执行postHandle方法,
  • afterCompletion() :在DispatcherServlet完全处理完请求后被调用,可用于清理资源等。返回处理(已经渲染了页面);当controller层抛出异常后依然会执行afterCompletion方法

代码示例

package com.Spring.Boot.controller.Interceptor;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
 
/**
 * springmvc拦截器
 *
 */
@Component
public class MvcInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        System.out.println("处理器处理请求之前被调用");
        // 返回true正常执行,返回false 表示拦截请求,
        return true;
    }
 
    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        // preHandle方法返回false则不会执行到这里
        System.out.println("处理器处理请求执行完成后调用");
    }
 
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        // preHandle方法返回false则不会执行到这里
        System.out.println("DispatcherServlet完全处理完请求后被调用");
 
    }

}

打印结果

 

HandlerAdapter

HandlerAdapter字面上的意思就是处理适配器,它的作用用一句话概括就是调用具体的方法对用户发来的请求来进行处理。当handlerMapping获取到执行请求的controller时,DispatcherServlte会根据controller对应的controller类型来调用相应的HandlerAdapter来进行处理。

执行过程 : DispatcherServlte会根据handlerMapping传过来的controller与已经注册好了的HandlerAdapter一一匹配,看哪一种HandlerAdapter是支持该controller类型的,如果找到了其中一种HandlerAdapter是支持传过来的controller类型,那么该HandlerAdapter会调用自己的handle方法

ModelAndView

从名字上看ModelAndView中的Model代表模型,View代表视图,这里的模型就是在controller层中ModelMap中添加的值;

ModelAndView对象有两个作用:

作用一

设置转向地址,如下所示(这也是ModelAndView和ModelMap的主要区别)

ModelAndView mv = new ModelAndView();
mv.setViewName("statisticalform/popStatistics/onloadPopStatisticsList");

作用二

用于传递控制方法处理结果数据到结果页面,也就是说我们把需要在结果页面上需要的数据放到ModelAndView对象中即可,

他的作用类似于 request对象的setAttribute方法的作用,用来在一个请求过程中传递处理的数据。

通过以下方法向页面传递参数:

addObject(String key,Object value);   
mv.addObject("list", list);

在页面上可以通过el变量方式$key或者bboss的一系列数据展示标签获取并展示ModelAndView中的数据。

ViewResolver

视图解析器,ViewResolver的主要作用是把一个逻辑上的视图 ModelAndView 解析为一个真正的view视图;

View

视图的作用是渲染模型数据,将模型里的数据以某种形式呈现给客户端。视图对象可以是常见的JSP,还可以是Excel或PDF等形式不一的媒体。为了实现视图模型和具体实现技术的解耦;

标签:聊能,面试官,拦截器,请求,视图,吊打,controller,ModelAndView,执行
From: https://www.cnblogs.com/fcjedorfjoeij/p/17529833.html

相关文章

  • 阿里Java二面:说说Spring MVC执行流程及原理?这样聊能吊打面试官
    面试找虐博主之前每次去面试必问的问题:“讲一下springmvc的执行流程以及常用组件的作用”;记得第一次和面试官说了大概的流程是这样的:“服务器收到一个请求后会先去HandlerMapping中匹配url,找到url之后用HandlerAdapter适配器去执行这个控制器(controller层),执行完之后返回一个mode......
  • 【从优秀到卓越】听一位面试官这样…
    文/浙大PGClub 今天的面试,我给每个人的时间,不会超过5分钟。 有一个人我只和他谈了3分钟,留下他的简历,他后面的同学用一种没有希望的眼神看着他,说:"这么快?" 我说:"你会更快。如果你不假思索地用两句话描述你的优点,我就招你,1分钟。"可惜他断断续续地说了一大堆——显然他心理的......
  • FullGC调优100倍,掌握这3招,吊打JVM调优
    文章很长,且持续更新,建议收藏起来,慢慢读!疯狂创客圈总目录博客园版为您奉上珍贵的学习资源:免费赠送:《尼恩Java面试宝典》持续更新+史上最全+面试必备2000页+面试必备+大厂必备+涨薪必备免费赠送:《尼恩技术圣经+高并发系列PDF》,帮你实现技术自由,完成职业升级,薪......
  • 字节跳动面试官问什么是Zookeeper
    什么是Zookeeper? 简单来说,Zookeeper是一个开源的分布式协同服务系统,Zookeeper的设计目标就是把复杂并且容易出错的分布式协同服务进行封装,并抽象出一个高效可靠的原语接口,并对外提供一系列简单的接口为其他服务调用。其他应用只要使用Zookeeper提供的接口,就可以实现各种分布......
  • 面试官问我知不知道 MySQL 的锁,5分钟让他刮目相看是什么?一篇理解
    锁的概念锁机制是用于管理对共享资源的并发访问。InnoDB存储引擎会在行级别上对数据上锁。数据库使用锁是为了支持对共享资源进行并发访问,提供数据的完整性和一致性。lock与latchlatch一般称为闩锁(轻量级的锁),因为其要求锁定的时间必须要非常短。在innoDB存储引擎中,latch可以分为......
  • 面试官问我知不知道 MySQL 的锁,5分钟让他刮目相看
    锁的概念锁机制是用于管理对共享资源的并发访问。InnoDB存储引擎会在行级别上对数据上锁。数据库使用锁是为了支持对共享资源进行并发访问,提供数据的完整性和一致性。lock与latchlatch一般称为闩锁(轻量级的锁),因为其要求锁定的时间必须要非常短。在innoDB存储引擎中,latch可以......
  • 为什么面试官这么爱问性能优化?
     笔者是一个六年前端,没有大厂经历,也没有什么出彩的项目,所以今年以来,前端现在这种行情下并没有收到多少面试,但是为数不多的面试中,百分之九十都问到了性能优化的问题,而且问题都出奇的一致:平时的工作中你有做过什么性能优化?对于这个问题其实我的内心os是(各位轻喷~):你们怎么都这么爱问......
  • 面试官问:ZooKeeper是强一致的吗?怎么实现的?
    Zookeeper通过ZAB保证分布式事务的最终一致性。 ZAB全称ZookeeperAtomicBroadcast(ZAB,Zookeeper原子消息广播协议)ZAB是一种专门为Zookeeper设计的一种支持崩溃恢复的原子广播协议,是Zookeeper保证数据一致性的核心算法。ZAB借鉴了Paxos算法,但它不是通用的一致性算法,是特......
  • 如果面试官问你:Redis 内存满了怎么办?
    Redis占用内存大小Redis的内存淘汰LRU算法LRU在Redis中的实现LFU算法问题Redis占用内存大小我们知道Redis是基于内存的key-value数据库,因为系统的内存大小有限,所以我们在使用Redis的时候可以配置Redis能使用的最大的内存大小。1、通过配置文件配置通过在Redis安装目录下面的redis.c......
  • 关于Java类加问题我竟让面试官哑口无言
    学习类加载之前我们先看看从面试官的角度会问哪些问题?毕竟带着问题学习会比较高效。直击面试看你简历写得熟悉JVM,那你说说类的加载过程吧?我们可以自定义一个String类来使用吗?什么是类加载器,类加载器有哪些?这些类加载器都加载哪些文件?多线程的情况下,类的加载为什么不会......