【金九银十秋招Java岗】大厂BAT核心面试课之Spring MVC面试解析

JAVA大厂BAT核心面试课

Spring MVC面试解析

目录

一,SpringMVC简介
二,Spring MVC 的工作流程是什么?

典型回答 3
详细流程 4
DisptacherServlet代码分析 5

三,知识拓展 9
1. Spring MVC的主要组件? 9
2. SpringMVC常用的注解有哪些? 11

@Controller 11
@RequestMapping 11
@PathVariable 12
@RequestParam 12
@ResponseBody 12
@RequestBody 12

3. 如何通过SpringMVC实现跨域请求 12

方案一:@CrossOrigin 13
方案二:全局配置 14

四,巩固练习 14

一,SpringMVC简介

SpringMVC是一种基于Spring实现了Web MVC设计模式的请求驱动类型的轻量级Web框架,使用了MVC架构模式的思想,将web层进行职责解耦,并管理应用所需对象的生命周期,为简化日常开发,提供了很大便利。
  SpringMVC提供了总开关——前端控制器(DispatcherServlet);请求处理映射器(Handler Mapping)和处理适配器(Handler Adapter),视图解析器(View Resolver)进行视图管理;动作处理器Controller接口(包含ModelAndView,以及处理请求响应对象request和response),配置灵活,支持文件上传,数据简单转化等强大功能。

二,Spring MVC 的工作流程是什么?

典型回答

用户发送请求到后端,后端前端控制器接收后根据请求URL到映射器查找处理器和执行链并返回,前端控制器通过适配器执行处理器,然后接收处理器返回的ModelAndView对象,前端控制器调用视图解析器解析ModelAndView,根据返回的结果去响应用户请求或渲染视图。

在这里插入图片描述

详细流程

首先:加载springmvc.xml配置

  1. 用户向服务器发送请求,请求被Spring 前端控制器(DispatcherServlet)捕获;

  2. DispatcherServlet对请求URL进行解析,得到请求资源标识符(URI)。然后根据该URI,调用处理器映射器(HandlerMapping)获得该Handler配置的所有相关的对象(包括Handler对象以及Handler对象对应的拦截器),最后以HandlerExecutionChain对象的形式返回;

  3. DispatcherServlet 根据获得的处理器(Handler),选择一个合适的HandlerAdapter(处理器适配器) [适配器模式]。(附注:如果成功获得HandlerAdapter后,此时将开始执行拦截器的preHandler(…)方法)

  4. 提取Request中的模型数据,填充Handler入参,开始执行Handler(Controller)。 在填充Handler的入参过程中,根据你的配置,Spring将帮你做一些额外的工作:

    HttpMessageConveter: 将请求消息(如Json、xml等数据)转换成一个对象,将对象转换为指定的响应信息
    
    数据转换:对请求消息进行数据转换。如String转换成Integer、Double等
    
    数据格式化:对请求消息进行数据格式化。 如将字符串转换成格式化数字或格式化日期等
    
    数据验证(如果有): 验证数据的有效性(长度、格式等),验证结果存储到BindingResult或Error中
    
  5. 处理器(Handler)执行完成后,向 前端控制器(DispatcherServlet)返回一个ModelAndView对象;

  6. 根据返回的ModelAndView,选择一个适合的视图解析器(ViewResolver)(必须是已经注册到Spring容器中的ViewResolver)返回给DispatcherServlet ;

  7. 视图解析器(ViewResolver) 结合 Model 和 View,来渲染视图(View)

  8. 将渲染结果返回给客户端。

DisptacherServlet代码分析

DisptacherServlet 实现了 Servlet 接口。
在这里插入图片描述

下面展示了HttpServlet定义的一下方法
在这里插入图片描述
当然,父类 HttpServlet 只是给出了定义,直接调用父类这些方法将会报错,所以 FrameworkServlet 将它们覆盖重写了处理逻辑:

protected final void doGet(HttpServletRequest request, HttpServletResponse response) {
// 注解 10. 具体调用的是 processRequest 方法 processRequest(request, response);
}
protected final void doPost(HttpServletRequest request, HttpServletResponse response) {
processRequest(request, response);
}

可以看到 doGet 、doPost 这些方法,底层调用的都是 processRequest 方法进行处理,关键方法是委托给子类 DispatcherServlet 的 doServie() 方法

DispatcherServlet#doService
protected void doService(HttpServletRequest request, HttpServletResponse response) throws Exception {
logRequest(request);
// 暂存请求参数
Map<String, Object> attributesSnapshot = null;

// 经过前面的准备(属性、辅助变量),进入请求处理过程 doDispatch(request, response);
}
请求分发和处理逻辑的核心是在 doDispatch(request, response) 方法中。

DispatcherServlet#doDispatch
protected void doDispatch(HttpServletRequest request, HttpServletResponse response) {
HttpServletRequest processedRequest = request; HandlerExecutionChain mappedHandler = null;
// 注释 10. 检查是否 MultipartContent 类型
processedRequest = checkMultipart(request);
// 根据 request 信息寻找对应的
Handler mappedHandler = getHandler(processedRequest); if (mappedHandler == null) {
// 没有找到 handler,通过 response 向用户返回错误信息 noHandlerFound(processedRequest, response);
return;
}
// 根据当前的 handler 找到对应的 HandlerAdapter 适配器 HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());
// 如果当前 handler 支持 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;
}
}
// 拦截器的 preHandler 方法的调用
if (!mappedHandler.applyPreHandle(processedRequest, response)) { return; }
// 真正激活 handler 进行处理,并返回视图
mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
if (asyncManager.isConcurrentHandlingStarted()) { return; } // 视图名称转换(有可能需要加上前后缀) applyDefaultViewName(processedRequest, mv);
// 应用所有拦截器的 postHandle 方法 mappedHandler.applyPostHandle(processedRequest, response, mv);
// 处理分发的结果(如果有 mv,进行视图渲染和跳转) processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);
}

三,知识拓展

1. Spring MVC的主要组件?

(1)DispatcherServlet(前端控制器):从图中我们可以看出DispatcherServlet是整个流程的核心,用来控制其他组件的执行,统一调度,降低组件之间的耦合度,方便后期扩展。

(2)Handler(处理器): 直接对应着MVC中的C也就是Controller层,它的具体表现形式有很多,可以是类,也可以是方法,也可以是其他表现形式,它的类型是Object。例如我们可以将@RequestMapping的所有方法都看成是一个Handler。总的来说只要可以实际处理请求就可以是Handler。

(3)HandleMapping(处理器映射器):对于每一个请求都需要一个Handler来处理,那么我们怎么知道需要通过哪个Handler来处理呢?这就是HandleMapping的工作,它会根据request请求来找到具体处理请求的Handler。

(4)HandlerAdapter(处理器适配器): 上面说过Handler可以是任意的形式,只要能处理请求就OK,但是Servlet需要的处理方法的结构确实固定的,都是以request和response为参数的方法(如doservic方法)。怎么让固定的servlet处理方法调用灵活的Handler来进行处理,这就是HandlerAdaper要做的事情。通过HandlerAdapter对处理器进行执行,这是适配器模式的应用,通过扩展适配器可以对更多类型的处理器进行执行。(DispatcherServlte会根据HandlerMapping传过来的controller与已经注册好了的HandlerAdapter一一匹配,看哪一种HandlerAdapter是支持该controller类型的,如果找到了其中一种HandlerAdapter是支持传过来的controller类型,那么该HandlerAdapter会调用自己的handle方法,handle方法运用Java的反射机制执行controller的具体方法来获得ModelAndView)
通俗的讲就是Handler是用来干活的工具,HandlerMapping则是用于需要干的活找到相应的工具,HandlerAdapter是使用工具干活的人。

(5)View(视图):View是一个接口,实现类支持不同的View类型(jsp、freemarker、pdf…)

(6)ViewResolver(视图解析器):作用:进行视图解析,根据逻辑视图名解析成真正的视图(view) 。
ViewResolver负责将处理结果生成View视图,View Resolver首先根据逻辑视图名解析成物理视图名即具体的页面地址,再生成View视图对象,最后对View进行渲染将处理结果通过页面展示给用户。 springmvc框架提供了很多的View视图类型,包括:jstlView、freemarkerView、pdfView等。
一般情况下需要通过页面标签或页面模版技术将模型数据通过页面展示给用户,需要由工程师根据业务需求开发具体的页面。(View和View Resolver的原理与Handler和HandlerMapping的原理类似,View是用来展示数据的,而View Resolver是用来查找View的)

2. SpringMVC常用的注解有哪些?

@Controller
使用它标记的类就是一个SpringMVC Controller 对象,也可以使用@RestController,@RestController注解相当于@ResponseBody + @Controller。

@RequestMapping
用于处理请求 url 映射的注解,可用于类或方法上。用于类上,则表示类中的所有响应请求的方法都是以该地址作为父路径。
@RequestMapping(value="/new", method = RequestMethod.GET)
// 简写
@GetMapping(value="/new")
// 其他请求方法
@PostMapping
@PutMapping
@DeleteMapping
@PatchMapping

@PathVariable
用于对应 RESTful 风格 url 中的参数
// url:/happy/1 @RequestMapping(value="/happy/{dayid}") findPet(@PathVariable String dayid) // dayid == 1

@RequestParam
将请求的参数绑定到方法中的参数上
// Url:/xxx?name=steven @RequestParam(value = “name”, required = false) String name

@ResponseBody
将返回类型直接输入到HTTP response body中。
一般在异步获取数据时使用,在使用@RequestMapping后,返回值通常解析为跳转路径,加上@ResponseBody后返回结果不会被解析为跳转路径,而是通过适当的 HttpMessageConverter 转换为指定格式后, 直接写入HTTP response body中。比如异步获取json数据,加上@ResponseBody后,会直接返回json数据。

@RequestBody
方法参数直接被绑定到http request body中

3. 如何通过SpringMVC实现跨域请求
方案一:@CrossOrigin

@RestController
@RequestMapping("/account")
public class AccountController {
@CrossOrigin
@GetMapping("/{id}")
public Account retrieve(@PathVariable Long id) {
// …
}
@DeleteMapping("/{id}")
public void remove(@PathVariable Long id) {
// …
}
}
默认情况下,@CrossOrigin允许:
 所有起源。
 所有标题。
 控制器方法映射到的所有HTTP方法。
参数:
allowedCredentials 默认情况下不启用,因为它建立了一个信任级别,用于公开敏感的用户特定信息(例如cookie和CSRF令牌),并且只应在适当的地方使用。
maxAge 设定为30分钟。

方案二:全局配置

@Configuration @EnableWebMvc public class WebConfig implements WebMvcConfigurer {
@Override public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/api/**")
.allowedOrigins(“https://domain2.com”)
.allowedMethods(“PUT”, “DELETE”)
.allowedHeaders(“header1”, “header2”, “header3”)
.exposedHeaders(“header1”, “header2”)
.allowCredentials(true).maxAge(3600); // Add more mappings…
}
}

默认情况下,全局配置启用以下内容:
 所有起源。
 所有标题。
 GET,HEAD和POST方法。
参数:
allowedCredentials 默认情况下不启用,因为它建立了一个信任级别,用于公开敏感的用户特定信息(例如cookie和CSRF令牌),并且只应在适当的地方使用。
maxAge 设定为30分钟。

四,巩固练习

  1. 在Spring MVC中,哪个类是负责处理HTTP请求和响应的?( A )
    A,DispatcherServlet
    B,RequestHandler
    C,HttpServlet
    D,SpringController

  2. 下面关于Spring MVC 描述正确的是?( C )
    A,DispatcherServlet在 Spring MVC 中是核心servlet , 它负责接收请求并将请求分发给适合的控制器
    B,在Spring MVC 中,可以配置多个DispatcherServlet
    C,全部选项
    D,要使Spring MVC可用,DispatcherServlet需要在web.xml中配置

拓展学习

【实训邦·Java】 Spring Boot+Vue/前后端分离/高并发/秒杀实战
https://ke.qq.com/course/447591?flowToken=1013910

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
东南亚位于我国倡导推进的“一带一路”海陆交汇地带,作为当今全球发展最为迅速的地区之一,近年来区域内生产总值实现了显著且稳定的增长。根据东盟主要经济体公布的最新数据,印度尼西亚2023年国内生产总值(GDP)增长5.05%;越南2023年经济增长5.05%;马来西亚2023年经济增速为3.7%;泰国2023年经济增长1.9%;新加坡2023年经济增长1.1%;柬埔寨2023年经济增速预计为5.6%。 东盟国家在“一带一路”沿线国家中的总体GDP经济规模、贸易总额与国外直接投资均为最大,因此有着举足轻重的地位和作用。当前,东盟与中国已互相成为双方最大的交易伙伴。中国-东盟贸易总额已从2013年的443亿元增长至 2023年合计超逾6.4万亿元,占中国外贸总值的15.4%。在过去20余年中,东盟国家不断在全球多变的格局里面临挑战并寻求机遇。2023东盟国家主要经济体受到国内消费、国外投资、货币政策、旅游业复苏、和大宗商品出口价企稳等方面的提振,经济显现出稳步增长态势和强韧性的潜能。 本调研报告旨在深度挖掘东南亚市场的增长潜力与发展机会,分析东南亚市场竞争态势、销售模式、客户偏好、整体市场营商环境,为国内企业出海开展业务提供客观参考意见。 本文核心内容: 市场空间:全球行业市场空间、东南亚市场发展空间。 竞争态势:全球份额,东南亚市场企业份额。 销售模式:东南亚市场销售模式、本地代理商 客户情况:东南亚本地客户及偏好分析 营商环境:东南亚营商环境分析 本文纳入的企业包括国外及印尼本土企业,以及相关上下游企业等,部分名单 QYResearch是全球知名的大型咨询公司,行业涵盖各高科技行业产业链细分市场,横跨如半导体产业链(半导体设备及零部件、半导体材料、集成电路、制造、封测、分立器件、传感器、光电器件)、光伏产业链(设备、硅料/硅片、电池片、组件、辅料支架、逆变器、电站终端)、新能源汽车产业链(动力电池及材料、电驱电控、汽车半导体/电子、整车、充电桩)、通信产业链(通信系统设备、终端设备、电子元器件、射频前端、光模块、4G/5G/6G、宽带、IoT、数字经济、AI)、先进材料产业链(金属材料、高分子材料、陶瓷材料、纳米材料等)、机械制造产业链(数控机床、工程机械、电气机械、3C自动化、工业机器人、激光、工控、无人机)、食品药品、医疗器械、农业等。邮箱:market@qyresearch.com
完整版:https://download.csdn.net/download/qq_27595745/89522468 【程大纲】 1-1 什么是java 1-2 认识java语言 1-3 java平台的体系结构 1-4 java SE环境安装和配置 2-1 java程序简介 2-2 计算机中的程序 2-3 java程序 2-4 java类库组织结构和文档 2-5 java虚拟机简介 2-6 java的垃圾回收器 2-7 java上机练习 3-1 java语言基础入门 3-2 数据的分类 3-3 标识符、关键字和常量 3-4 运算符 3-5 表达式 3-6 顺序结构和选择结构 3-7 循环语句 3-8 跳转语句 3-9 MyEclipse工具介绍 3-10 java基础知识章节练习 4-1 一维数组 4-2 数组应用 4-3 多维数组 4-4 排序算法 4-5 增强for循环 4-6 数组和排序算法章节练习 5-0 抽象和封装 5-1 面向过程的设计思想 5-2 面向对象的设计思想 5-3 抽象 5-4 封装 5-5 属性 5-6 方法的定义 5-7 this关键字 5-8 javaBean 5-9 包 package 5-10 抽象和封装章节练习 6-0 继承和多态 6-1 继承 6-2 object类 6-3 多态 6-4 访问修饰符 6-5 static修饰符 6-6 final修饰符 6-7 abstract修饰符 6-8 接口 6-9 继承和多态 章节练习 7-1 面向对象的分析与设计简介 7-2 对象模型建立 7-3 类之间的关系 7-4 软件的可维护与复用设计原则 7-5 面向对象的设计与分析 章节练习 8-1 内部类与包装器 8-2 对象包装器 8-3 装箱和拆箱 8-4 练习题 9-1 常用类介绍 9-2 StringBuffer和String Builder类 9-3 Rintime类的使用 9-4 日期类简介 9-5 java程序国际化的实现 9-6 Random类和Math类 9-7 枚举 9-8 练习题 10-1 java异常处理 10-2 认识异常 10-3 使用try和catch捕获异常 10-4 使用throw和throws引发异常 10-5 finally关键字 10-6 getMessage和printStackTrace方法 10-7 异常分类 10-8 自定义异常类 10-9 练习题 11-1 Java集合框架和泛型机制 11-2 Collection接口 11-3 Set接口实现类 11-4 List接口实现类 11-5 Map接口 11-6 Collections类 11-7 泛型概述 11-8 练习题 12-1 多线程 12-2 线程的生命周期 12-3 线程的调度和优先级 12-4 线程的同步 12-5 集合类的同步问题 12-6 用Timer类调度任务 12-7 练习题 13-1 Java IO 13-2 Java IO原理 13-3 流类的结构 13-4 文件流 13-5 缓冲流 13-6 转换流 13-7 数据流 13-8 打印流 13-9 对象流 13-10 随机存取文件流 13-11 zip文件流 13-12 练习题 14-1 图形用户界面设计 14-2 事件处理机制 14-3 AWT常用组件 14-4 swing简介 14-5 可视化开发swing组件 14-6 声音的播放和处理 14-7 2D图形的绘制 14-8 练习题 15-1 反射 15-2 使用Java反射机制 15-3 反射与动态代理 15-4 练习题 16-1 Java标注 16-2 JDK内置的基本标注类型 16-3 自定义标注类型 16-4 对标注进行标注 16-5 利用反射获取标注信息 16-6 练习题 17-1 顶目实战1-单机版五子棋游戏 17-2 总体设计 17-3 代码实现 17-4 程序的运行与发布 17-5 手动生成可执行JAR文件 17-6 练习题 18-1 Java数据库编程 18-2 JDBC类和接口 18-3 JDBC操作SQL 18-4 JDBC基本示例 18-5 JDBC应用示例 18-6 练习题 19-1 。。。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值