探索SpringMVC-HandlerAdapter之RequestMappingHandlerAdapter-返回值处理

news2024/11/20 2:33:43

前言

上回我们回答了ReqeustMappingHandlerAdapter调用目标方法的参数解析问题,今天我们再来回答第二个问题:怎么处理方法调用的返回值。

深入分析返回值处理需求

@RequestMapping处理器的返回值类型
相信很多同学对于这个返回值的第一个反应就是返回一个自定义的对象了,或许还有部分同学想到返回String类型的viewName。没错,对于SpringMVC而言,最重要的返回值就是这两种。

返回值类型描述
@ResponseBody + 自定义类型通常会被HttpMessageConverter序列化后,通过response写回给客户端,从而完成请求的处理。通常是接口请求。
与视图相关的对象视图相关对象包括:viewName,View,Model,ModelAndView,@ModelAttribute。通常是页面请求,不过具体的视图响应内容由视图解析器负责和View。

这里提醒一下大家,在阅读源码时,一定要时刻注意自己关注的点在哪里。因为一款优秀的框架总是考虑很多很全面的,对于很多功能进行支持。就像这里,有接口请求的支持,也有视图请求的支持。实在不行就自己打断点。

Spring的设计

为了支持上述的两种类型的返回值,抽象出来两个概念

  1. ModelAndViewContainer
    用于收集各种与视图相关的返回值。这也是他叫Container的原因。他才是HandlerAdatper封装ModelAndView的数据来源
  2. HandlerMethodReturnValueHandler
    SpringMVC默认注册的返回值处理器
    负责处理返回值。这里就可以通过不同的实现来对上述的两种情况进行支持。
    • 视图相关的返回值:实现对应的返回值处理器,将其设置到ModelAndViewContainer中,以便后续HandlerAdapter封装ModelAndView
    • @ResponseBody返回值,专门实现了RequestResponseBodyMethodProcessor。基于HttpMessageConverter,将数据通过Response写出。

如果不需要深入探究json序列化的内容,RequestResponseBodyMethodProcessor的逻辑基本就是这样。当然,还有设置必要的请求头,例如Content-Type。接下来我们更多的分析视图相关的。

视图数据

还记得使用jsp的时候,会使用${attributeName}获取的数据吗?这就是视图数据,除了jsp还常见于各种视图技术,例如:FreeMarker和Thymeleaf等。

值得一提的是,除了模板技术,spring还支持@JsonView,用于同一个对象,不同接口返回要求返回的字段不同的场景。

视图数据赋值/填充最简单的方式,就是在@RequestMapping方法中声明一个Model或者ModelMap,在方法的处理逻辑中手动添加到Model中。不过Spring还提供了另一个利器@ModelAttribute

@ModelAttribute

他可以注解在方法上,只要是Controller/ControllerAdvice里面的public方法都可以。
也可以注解在@RequestMapping的参数上。

  • 注解在@RequestMapping方法参数上,则会自动将该参数作为视图数据。
  • 如果方法同时是@RequestMapping方法,那么则是ModelAttributeMethodProcessor处理。
  • 其他的则是由HandlerAdapter封装进ModelFactory里面,HandlerAdapter在调用@RequestMapping方法之前,会执行ModelFactory的initModel方法被调用时会执行这些@ModelAttribute注解的方法。产生的视图数据会被设置到ModelAndViewContainer里面。

这些方法是有先后顺序的,在@ControllerAdvice中的会先执行,@Controller中的后执行。因此对于同一个属性名的会被@Controller中的方法覆盖。意味着以最靠近@RequestMapping方法的为准,也就是说,@RequestMapping方法的才是最终返回的。

@InitBinder

@InitBinder方法基于WebDataBinder的能力,可以对视图数据做两个事情

  1. 类型转换,例如通过注册Formater/PropertyEditor将Date转为String。当然他也可以将入参的String类型转为Date

    @InitBinder
    public void initBinder(WebDataBinder binder) {
    	SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
        dateFormat.setLenient(false);
        binder.registerCustomEditor(Date.class, new CustomDateEditor(dateFormat, false));
        
        // 或者像这样
        // 注意这个DateFormat是spring包的:org.springframework.format.datetime.DateFormatter
    	// binder.addCustomFormatter(new DateFormatter("yyyy-MM-dd"));
    }
    
  2. 限制返回的视图数据字段:binder.setAllowedFields

总结

  1. 处理器返回值常用的可以被分为两类:@ResponseBody和视图相关的数据。除此之外,还有响应式的异步请求的数据。这里没有做分析,感兴趣的同学:这里
  2. @ResponseBody和@RequsetBody都是由RequestResponseBodyMethodProcessor(既是参数解析器,也是返回值处理器)处理,都是基于HttpMessageConverter。
  3. HandlerAdapter在调用目标处理器后,更多的支持都是为了后续的视图做准备。体现在更多的视图数据相关的返回值处理器、ModelAndViewContainer、调用目标处理器后的ModelAndView的封装。

后记

终于梳理完了入参解析和返回值的处理,下一步就到我们的正菜:RequestMappingHandlerAdapter了。

上一篇:
探索SpringMVC-HandlerAdapter之RequestMappingHandlerAdapter-参数解析
第一篇:
探索SpringMVC-web上下文

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

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

相关文章

图解JDK1.7中HashMap头插法扩容造成的死循环问题

JDK1.7中HashMap头插法扩容造成的死循环问题 文章目录JDK1.7中HashMap头插法扩容造成的死循环问题一、背景二、源码解读三、图解单线程环境中扩容多线程环境中扩容四.总结一、背景 HashMap是线程不安全的,在并发使用HashMap时很容易出现一些问题,其中最…

ArcGIS基础实验操作100例--实验66符号图层的保存与加载

本实验专栏参考自汤国安教授《地理信息系统基础实验操作100例》一书 实验平台:ArcGIS 10.6 实验数据:请访问实验1(传送门) 高级编辑篇--实验66 符号图层的保存与加载 目录 一、实验背景 二、实验数据 三、实验步骤 &#xff0…

【OpenGL】基础光照

介绍 现实世界中的光照是极其复杂,难以计算的,因此OpenGL的光照使用的是简化的模型,其中一个模型被称为冯氏光照模型(Phong Lighting Model)。 冯氏光照模型的主要结构由三个分量组成: 环境(Ambient)光照漫反射(Diffuse)光照镜…

blender学习笔记2023.01.05

文章目录why基操why 想画条大黄鱼 想画一下渔网 网箱 写笔记预防忘记 基操 1.语言改为中文 不过后续可能改回英文去 2.顶部导航栏—编辑—偏好设置—界面—翻译—(关掉)新建数据 目的是预防插件导致奇奇怪怪的报错 这里左下角位置处点击 保存修改 3…

初识LCD1602及编程实现字符显示

一、LCD1602基础知识及接线方法LCD1602是一种工业字符型液晶,能够同时显示16x02即32字符(16列两行)引脚说明第 1 脚: VSS 为电源地 第 2 脚: VDD 接 5V 正电源 第 3 脚: VL 为液晶显示器对比度调整端,接正电源时对比度最弱,接地时…

【Neo4j构建知识图谱】:官方服务图谱大型数据集下载与可视化方法【数据集包括:食谱数据、足球、权力的游戏、美国宇航局、英国公司注册、财产所有权、政治捐款】

目录 1、服务端口免费查看知识图谱2、关于 Neo4j 示例数据集的实现3、下载离线数据集4、项目概览与实现案例还可以看到解析python源码还可以看到解析cypher源码各种数据集实现案例参考1、服务端口免费查看知识图谱 此服务器托管许多具有只读访问权限的数据集,供公众使用。 该…

2022尚硅谷SSM框架跟学(三)MyBatis基础三

2022尚硅谷SSM框架跟学 三 MyBatis基础三9.动态SQL9.1if9.2where方法一:加入恒成立的条件方法二:使用where标签9.3trim9.4choose、when、otherwise9.5foreach9.51批量添加9.52批量删除批量删除方式1批量删除方式2批量删除方式39.6SQL片段10.MyBatis的缓存10.1MyBatis的一级缓存…

JS基础(一)——认识JS及其基础语法

网页的三个组成部分 HTML:用于控制网页的内容CSS:用于控制网页的样式JavaScript:用于控制网页的行为 网页的行为指用户与浏览器的行为交互、浏览器与浏览器与服务器的数据交互。 ECMAScriptS(ES) ECMAScriptS是Java…

OpenCV入门

OpenCV入门图像金字塔高斯金字塔(cv2.pyrUp、cv.pyrDown)拉普拉斯金字塔边缘检测图像轮廓 (cv2.findContours)轮廓特征(cv2.contourArea、cv2.arcLength)轮廓近似(cv2.approxPolyDP)边界矩形、外接圆(cv2.boundingRect、cv2.minEnclosingCircle)模板匹配…

C库函数:time.h

time.h C 标准库 – <time.h> | 菜鸟教程 (runoob.com) 库变量 下面是头文件 time.h 中定义的变量类型&#xff1a; 序号变量 & 描述1size_t 是无符号整数类型&#xff0c;它是 sizeof 关键字的结果。2clock_t 这是一个适合存储处理器时间的类型。3time_t is 这是一…

C库函数:math.h

math.h C 标准库 – <math.h> | 菜鸟教程 (runoob.com) 16double pow(double x, double y) 返回 x 的 y 次幂。17double sqrt(double x) 返回 x 的平方根。18double ceil(double x) 返回大于或等于 x 的最小的整数值。19double fabs(double x) 返回 x 的绝对值。20doubl…

矩阵分析:QR分解

Householder变换 Householder变换是一种简洁而有意思的线性变换&#xff0c;也可称为镜面反射变换&#xff0c;Householder变换矩阵为HI−wTwHI-w^TwHI−wTw 考虑向量α\alphaα和一个单位向量w:wTw1w:w^{T}w1w:wTw1 α\alphaα在www 方向上的分量是 αw//(wTα)wwwTα\alpha _…

Python快速制作自动填写脚本:100%准确率

嗨害大家好鸭&#xff01;我是小熊猫~ 环境使用 Python 3.8Pycharm 模块使用 import requests —> 数据请求模块 pip install requestsimport parsel —> 数据解析模块 pip install parselfrom selenium import webdriver —> 自动测试模块 pip install selenium3.…

#H. Linear Approximation

Description给你一个数列A&#xff0c;希望你找出一个数字B。使得下面这个式子的值最小Abs(A1-(B1))Abs(A2-(B2))Abs(A3-(B3))..........Abs(An-(Bn))FormatInput第一行给出输入n第二行给出数列A,数字的值在[1,1e9]N<2e5Output如题Samples输入数据 152 2 3 5 5输出数据 12思…

WQS二分

本博客以一种较为少见的方式来解释WQS二分。 题目 首先&#xff0c;WQS二分用于解决什么问题&#xff1f; 我们先看一个伞兵题目&#xff1a; 有一个 nnn 个数的数组 aaa。 求在 aaa 中恰好选择 mmm 个数的情况下&#xff0c;选择的数的和的最大值。 你现在看到了这个题目&a…

Jenkins基于Blue Ocean UI构建流水线

目录 一、Blue Ocean 简介 二、Blue Ocean 安装 2.1 安装 Blue Ocean 插件 2.2 安装 Blue Ocean 版本的 Jenkins 3. 构建流水线 4. 创建流水线 5. 选择代码仓库 6. 连接Git仓库 7. 创建流水线 详细信息可以参考官网&#xff1a;Blue Ocean 入门 一、Blue Ocean 简介…

牛客竞赛每日俩题 - Day13

目录 洪泛法BFS 26进制计数字符串 洪泛法BFS 红与黑__牛客网 循环接收每组用例&#xff0c;对于每组用例进行如下操作&#xff1a; 找到‘’所在的位置&#xff0c;即起始搜索的点 使用DFS搜索地板中的每块瓷砖&#xff0c;如果是黑色&#xff0c;给计数1&#xff0c;然后像…

JavaSE学习day2_01, 数据类型

1. 数据类型 1.1 Java中数据类型的分类,重点 基本数据类型 引用数据类型 1.2 基本数据类型的四类八种 整数类型&#xff1a;byte、short、int、long 浮点类型&#xff1a;float、double 字符类型&#xff1a;char 布尔类型&#xff1a;boolean,只有两个取值,true和false…

HW13 Network Compression网络压缩

文章目录一、任务描述1、介绍知识蒸馏2、介绍架构设计二、实验1、simple baselineconfigs结构设计训练2、medium baselineconfigs3、strong baselineconfigsReLu和leakyRelu知识蒸馏一、任务描述 ●网络压缩&#xff1a;使您的模型更小而不损失性能。 ●在这个任务中&#xff…

初级算法之深度搜索

目录 ​编辑 概述&#xff1a; 个人对深搜的理解&#xff1a; 深搜模板&#xff1a; 例题&#xff1a; 题目描述 输入格式 输出格式 输入输出样例 说明/提示 代码图示&#xff1a; 概述&#xff1a; 在我们刷算法的过程中肯定会想到暴力通过&#xff0c;暴力是不需要…