【springMVC】springMVC学习系列一:springMVC的组件

系列文章目录

前言

spring mvc 它解决了什么问题呢?
1.URL映射
2. 表单参数映射
3. 调用目标Control
4. 数据模型映射
5. 视图解析
6. 异常处理
上述解决在spring mvc 中都体现在如下组件当中
HandlerMapping: url与控制器的映谢
HandlerAdapter: 控制器执行适配器
ViewResolver:视图仓库
view:具体解析视图
HandlerExceptionResolver:异常捕捕捉器
HandlerInterceptor:拦截器

各组件调用关系流程图如下:
在这里插入图片描述

一、handler

真正处理请求的对象,有4种
1)实现了Controller接口的Bean对象
2)实现了HttpRequestHandler接口的Bean对象
3)@Controller注解的类中添加了@RequestMapping注解的方法(HandlerMethod)
4)HandlerFunction对象

其实handler是一个逻辑概念,并没有一个统一的接口,上面4中对象都可以成为handler,代码中是用Object来引用的,后面一篇会具体介绍

二、handlerMapping

有3种
1)BeanNameUrlHandlerMapping:负责Controller接口和HttpRequestHandler接口
2)RequestMappingHandlerMapping:负责@RequestMapping的方法
3)RouterFunctionMapping:负责RouterFunction以及其中的HandlerFunction

1.handlerMapping的重要结构

1)存储请求和handler的映射关系
例如RequestMappingHandlerMapping存储了2个map

a. mappingLookup:key:RequestMappingInfo value:HandlerMethod
RequestMappingInfo 是对@RequestMapping注解中元数据的封装
HandlerMethod 是对method和目标对象的封装,是处理器真正执行的地方

b. urlLookup:key:url value:List
url和RequestMappingInfo是多对多的关系,比如@RequestMapping 注解可以配置多个URL路径来映射到同一个控制器方法

@Controller
public class MyController {@RequestMapping(value = {"/path1", "/path2", "/path3"})public String handleMultiplePaths() {return "viewName";}
}

一个URL可以通过请求方式映射多个控制器方法

@Controller
public class MyController {@RequestMapping(value = "/path",method = "GET")public String getResource() {return "viewName";}@RequestMapping(value = "/path",method = "POST")public String postResource() {return "viewName";}
}

至于具体怎么通过这2个map找到对应的处理器,下一篇再讲

2)存储拦截器
在处理请求时,与handler一起组成执行链executionChain

2.如何获取handlerMapping

 protected HandlerExecutionChain getHandler(HttpServletRequest request) throws 
Exception {if (this.handlerMappings != null) {for (HandlerMapping mapping : this.handlerMappings) {HandlerExecutionChain handler = mapping.getHandler(request);if (handler != null) {return handler;}}}return null;

三、handlerAdapter

不同种类的Handler处理请求的方法不一样,那么需要一个能将他们统一调用的东西,那就是适配器
针对不同的Handler,会有不同的适配器:
HttpRequestHandlerAdapter:对应实现了HttpRequestHandler的处理器
SimpleControllerHandlerAdapter:对应实现了Controller接口的处理器
RequestMappingHandlerAdapter:对应@RequestMapping注解方法的处理器
HandlerFunctionAdapter:对应实现了 HandlerFunction接口的处理器

寻找适配器的逻辑如下,也是策略模式

rotected HandlerAdapter getHandlerAdapter(Object handler) throws ServletException { if (this.handlerAdapters != null) { for (HandlerAdapter adapter : this.handlerAdapters) { if (adapter.supports(handler)) { return adapter; } } } 。。。}

四、HandlerMethodArgumentResolver

SpringMVC要去解析方法参数,那么该如何解析呢,是通过HandlerMethodArgumentResolver来进行的,比如对于@RequestMapping方法
RequestParamMethodArgumentResolver:负责处理@RequestParam
RequestHeaderMethodArgumentResolver:负责处理@RequestHeader
SessionAttributeMethodArgumentResolver:负责处理@SessionAttribute
RequestAttributeMethodArgumentResolver:负责处理@RequestAttribute
RequestResponseBodyMethodProcessor:负责处理@RequestBody

而在判断某个参数该由哪个HandlerMethodArgumentResolver处理时,也是用的策略模式:

private HandlerMethodArgumentResolver getArgumentResolver(MethodParameter parameter) { HandlerMethodArgumentResolver result = this.argumentResolverCache.get(parameter); if (result == null) { for (HandlerMethodArgumentResolver resolver : this.argumentResolvers) { if (resolver.supportsParameter(parameter)) { result = resolver; this.argumentResolverCache.put(parameter, result); break; } } } return result; }

五、HandlerMethodReturnValueHandler

方法返回值如何解析呢,比如返回一个String,加了@ResponseBody注解直接将这个String返回给浏览器,没有加就根据这个String找到对应的页面,把页面返回给浏览器。这些处理是通过HandlerMethodReturnValueHandler来进行的,比如下面的实现:
1)RequestResponseBodyMethodProcessor:处理加了@ResponseBody注解的情况
2)ViewNameMethodReturnValueHandler:处理没有加@ResponseBody注解并且返回值类型为String的情况
3)ModelMethodProcessor:处理返回值是Model类型的情况

如何判断使用哪个来解析呢,还是策略模式:

private HandlerMethodReturnValueHandler selectHandler(@Nullable Object value, MethodParameter returnType) {boolean isAsyncValue = isAsyncReturnValue(value, returnType);for (HandlerMethodReturnValueHandler handler : this.returnValueHandlers) {if (isAsyncValue && !(handler instanceof AsyncHandlerMethodReturnValueHandler)) {continue;}if (handler.supportsReturnType(returnType)) {return handler;}}return null;}

六、HttpMessageConverter

RequestResponseBodyMethodProcessor,因为它会处理加了@ResponseBody注解的情况,也是目前我们用得最多的情况。如果@ResponseBody注解的方法返回的不是String,而是Map、User对象呢,该怎么解析呢?
SpringMVC会利用HttpMessageConverter来处理,默认情况下有4种:
1)ByteArrayHttpMessageConverter:处理返回值为字节数组的情况,把字节数组返回给浏览器
2)StringHttpMessageConverter:处理返回值为字符串的情况,把字符串按指定的编码序列号后返回给浏览器
3)SourceHttpMessageConverter:处理返回值为XML对象的情况,比如把DOMSource对象返回给浏览器
4)AllEncompassingFormHttpMessageConverter:处理返回值为MultiValueMap对象的情况

不过以上四个Converter是不能处理Map对象或User对象的,所以如果返回的是Map或User对象,那
么得单独配置一个Converter,比如MappingJackson2HttpMessageConverter,这个Converter比
较强大,能把String、Map、User对象等等都能转化成JSON格式。

public class AppConfig implements WebMvcConfigurer { @Override public void configureMessageConverters(List<HttpMessageConverter<?>> converters) { MappingJackson2HttpMessageConverter messageConverter = new 
MappingJackson2HttpMessageConverter();messageConverter.setDefaultCharset(StandardCharsets.UTF_8); converters.add(messageConverter); } }

另外,如果使用StringHttpMessageConverter,字符集默认为ISO-8859-1,所以默认情况下返
回中文会乱码,需要通过配置解决

ublic class AppConfig implements WebMvcConfigurer { @Override public void configureMessageConverters(List<HttpMessageConverter<?>> converters) { 7StringHttpMessageConverter messageConverter = new 
StringHttpMessageConverter();messageConverter.setDefaultCharset(StandardCharsets.UTF_8); converters.add(messageConverter); } }

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.pswp.cn/news/907175.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【Vue Vapor Mode :技术突破与性能优化的可能性】

Vue Vapor Mode &#xff1a;技术突破与性能优化的可能性 前言 作为一名有着Vue 2经验和Vue 3经验的开发者&#xff0c;你一定深刻体会过Vue从Options API到Composition API的演进&#xff0c;也感受过Vue 3在性能上相比Vue 2的显著提升。现在&#xff0c;Vue团队正在开发一个…

MySQL数据库零基础入门教程:从安装配置到数据查询全掌握【MySQL系列】

第1章&#xff1a;认识MySQL 1.1 什么是MySQL&#xff1f; MySQL是一种开源的关系型数据库管理系统&#xff08;RDBMS&#xff09;&#xff0c;由瑞典MySQL AB公司开发&#xff0c;现由Oracle公司维护。它使用结构化查询语言&#xff08;SQL&#xff09;进行数据库的管理和操…

AXI3、AXI4 和 AXI5 的详细差异对比

AXI3、AXI4 和 AXI5 的详细差异对比 摘要&#xff1a;AXI (Advanced eXtensible Interface) 是 ARM 公司提出的高性能片上总线协议&#xff0c;广泛用于 SoC (System on Chip) 设计中&#xff0c;以实现高效的数据传输和系统互连。AXI 协议随着版本的迭代不断演进&#xff0c;从…

向量数据库该如何选择?Milvus 、ES、OpenSearch 快速对比:向量搜索能力与智能检索引擎的应用前景

​ 1.milvus VS ES Milvus 的亮点 功能性&#xff1a;Milvus 不仅支持基本的向量相似性搜索&#xff0c;还支持稀疏向量、批量向量、过滤搜索和混合搜索功能等高级功能。 灵活性&#xff1a;Milvus 支持多种部署模式和多个 SDK&#xff0c;所有这些都在一个强大的集成生态系…

SQL进阶之旅 Day 4:子查询与临时表优化

文章标题 【SQL进阶之旅 Day 4】子查询与临时表优化 文章内容 开篇&#xff1a;SQL进阶之旅的第4天 在“SQL进阶之旅”系列中&#xff0c;第4天的主题是子查询与临时表优化。这是SQL开发中不可或缺的一部分&#xff0c;尤其在处理复杂查询时&#xff0c;合理使用子查询和临…

Python学习(2) ----- Python的类型

在 Python 中&#xff0c;一切皆对象&#xff0c;每个对象都有类型。下面是 Python 中的常见内置类型分类和示例&#xff1a; &#x1f7e1; 1. 数字类型&#xff08;Numeric Types&#xff09; 类型说明示例int整数5, -42float浮点数3.14, -0.5complex复数1 2j a 10 …

跨协议协同智造新实践:DeviceNet-EtherCAT网关驱动汽车焊接装配效能跃迁

在汽车制造领域&#xff0c;机器人协作对于提升生产效率与产品质量至关重要。焊接、装配等关键环节&#xff0c;需要机器人与各类设备紧密配合。JH-DVN-ECT疆鸿智能的devicenet从站转ethercat主站协议网关&#xff0c;成为实现这一高效协作的得力助手&#xff0c;尤其是在连接欧…

nginx之proxy_buffering的作用

Nginx 的缓冲机制是为了让后端能更快释放资源&#xff0c;而不是卡在慢客户端上&#xff0c;从而提升整体性能和并发能力。 现实中客户端和后端服务器之间的传输速率可能差异很大。Nginx 的缓冲机制正是为了解决这个不匹配问题。 假设没有缓冲&#xff08;即 proxy_buffering…

数据库相关问题

1.保留字 1.1错误案例&#xff08;2025/5/27&#xff09; 报错&#xff1a; java.sql.SQLSyntaxErrorException: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near condition, sell…

GO 语言进阶之 进程 OS与 编码,数据格式转换

更多个人笔记见&#xff1a; github个人笔记仓库 gitee 个人笔记仓库 个人学习&#xff0c;学习过程中还会不断补充&#xff5e; &#xff08;后续会更新在github上&#xff09; 文章目录 进程信息OS操作基本例子 编码相关HASH 哈希Base64 encoding 基础64编码 数据格式转换和处…

如何用Spring Cache实现对Redis的抽象

我们在进行Java项目开发时候&#xff0c;经常会用到Redis缓存例如数据库里的一些信息、手机验证码之类的&#xff0c;正常写法就会像去连mysql一样&#xff0c;这种硬编码的方式肯定是非常不合适的。 Autowireprivate UserMapper userMapper;Autowireprivate StringCommand str…

CMake指令:file()

目录 1.简介 2.常用子命令&#xff08;COMMAND&#xff09; 2.1.COPY - 复制文件或目录 2.2.RENAME - 重命名文件或目录 2.3.REMOVE - 删除文件或目录 2.4.MAKE_DIRECTORY - 创建目录 2.5.READ - 读取文件内容 2.6.WRITE - 写入文件内容 2.7.GLOB - 按模式匹配文件 2…

使用VuePress开发日志

结合官方教程&#xff0c;补充一些细节。 快速上手 | VuePress中文文档 | VuePress中文网 VuePress使用步骤 创建并进入一个新目录 mkdir vuepress-starter && cd vuepress-starter使用你喜欢的包管理器进行初始化 yarn init # npm init将 VuePress 安装为本地依赖 …

随手记录7

2025年5月26日~2025年6月01日 周一&#xff1a;没做 周二&#xff1a;芹菜炒鸡蛋香肠 周三&#xff1a; 周四&#xff1a; 周五&#xff1a; 周六&#xff1a; 周日&#xff1a;

【无标题】使用JEasyOpc开发OPCDA采集中间件

使用JEasyOpc开发OPCDA采集中间件 1.JEasyOpc下载2.修改JEasyOpc源码及打包安装3.Pom 引入jeasy2.3.2.jar4.maven pom 配置打包5.cmd执行&#xff08;手动指定 main主程序入口&#xff09;6.EXE4J打包jar包&#xff0c;生成exe可执行文件 1.JEasyOpc下载 jeasyopc源码下载&…

5 WPF中的Page页面的使用

以下是一个简单的WPF示例&#xff0c;演示如何在三个Page之间进行导航切换&#xff0c;使用Frame控件作为导航容器&#xff0c;并包含基本的导航按钮&#xff08;前进/后退/主页&#xff09; Page类更简单&#xff0c;比Window更精简。 代码见下文以及资源文件&#xff1a; htt…

基于51单片机的音乐盒点阵屏proteus仿真

地址&#xff1a; https://pan.baidu.com/s/1hYzg2icjHV8jWJdltJkKxw 提取码&#xff1a;1234 仿真图&#xff1a; 芯片/模块的特点&#xff1a; AT89C52/AT89C51简介&#xff1a; AT89C51 是一款常用的 8 位单片机&#xff0c;由 Atmel 公司&#xff08;现已被 Microchip 收…

图论:floyed算法

Floyd 算法是一种用于寻找加权图中所有顶点对之间最短路径的经典算法&#xff0c;它能够处理负权边&#xff0c;但不能处理负权环。即如果边权有负数&#xff0c;切负权边与其他边构成了环就不能用该算法。该算法的时间复杂度为 \(O(V^3)\)&#xff0c;其中 V 是图中顶点的数量…

STM32之看门狗(IWDG)

一、看门狗外设的原理与应用 背景说明 随着单片机的发展&#xff0c;单片机在家用电器、工业自动化、生产过程控制、智能仪器仪表等领域的应用越来越广泛。然而处于同一电力系统中的各种电气设备通过电或磁的联系彼此紧密相连&#xff0c;相互影响&#xff0c;由于运行方式的…

#RabbitMQ# 消息队列进阶

目录 消息可靠性 一 生产者的可靠性 1 生产者的重连 2 生产者的确认 (1 Confirm* (2 Return 二 MQ的可靠性 1 数据持久化 2 Lazy Queue* 三 消费者的可靠性 1 消费者确认机制 2 消费失败处理 3 业务幂等性 四 延迟消息 消息可靠性 在消息队列中&#xff0c;可靠性…