【SpringBoot3】Spring 请求处理流程,自定义返回类型处理(HttpMessageConverter)

一、Spring Boot 请求处理

1、请求处理流程

Spring Boot 的接口请求处理流程主要基于 Spring MVC 架构,以下是详细的请求处理流程:

  1. 客户端发送请求:客户端发送HTTP请求到Spring Boot应用的URL。

  2. DispatcherServlet 接收请求:Spring Boot应用中的DispatcherServlet拦截所有的请求。

  3. HandlerMapping 进行映射:DispatcherServlet 通过 HandlerMapping 找到处理请求的 Controller。

  4. Controller 方法处理请求:Controller 中的相应方法处理请求,并调用适当的业务逻辑,返回数据或者视图名。

  5. 数据绑定与验证:如果请求中包含数据,Spring Boot 将数据绑定到相应的参数上,并执行验证(如果有的话),验证失败会产生相应的错误。

  6. 调用 Service 层:Controller 方法通常会调用 Service 层的方法来执行业务逻辑。

  7. 返回数据或视图:Controller 方法处理完请求后,返回数据或者视图名给 DispatcherServlet。

  8. ViewResolver 解析视图:如果返回的是视图名,DispatcherServlet 会使用 ViewResolver 来解析视图名,得到具体的视图对象。

  9. 视图渲染:视图对象将模型数据填充到视图中,生成最终的响应结果。

  10. 响应返回给客户端:DispatcherServlet 将最终的响应返回给客户端,请求处理完成。

需要注意的是,Spring Boot 的自动配置大大简化了这个流程,大部分情况下,开发者只需要专注于编写 Controller 和相应的业务逻辑,其他的请求处理流程由 Spring Boot 自动完成。

2、处理请求的相关注解

在Spring Boot中,用于处理请求的相关注解包括但不限于以下几种:

  1. @Controller:用于标识控制器类,处理HTTP请求。

  2. @RestController:类似于@Controller,但是其方法默认返回JSON格式的数据,常用于构建RESTful风格的服务。

  3. @RequestMapping:用于映射HTTP请求到控制器的处理方法,并可以定义请求的URL路径、HTTP方法等。

  4. @GetMapping@PostMapping@PutMapping@DeleteMapping:这些注解分别用于标识处理GET、POST、PUT、DELETE请求的方法,并可以指定URL路径。

  5. @RequestParam:用于从请求中获取参数值,常用于处理HTTP请求中的查询参数。

  6. @PathVariable:用于从URL路径中获取参数值,常用于RESTful风格的请求。

  7. @RequestBody:用于将请求体中的数据绑定到方法的参数上,常用于处理POST请求中的请求体数据。

  8. @ResponseBody:用于将方法的返回值直接作为HTTP响应体返回给客户端。

  9. @ModelAttribute:用于将请求参数绑定到一个对象上,并将该对象添加到模型中传递给视图。

  10. @Valid@Validated:用于执行Bean验证,通常与JSR-303/JSR-380规范的验证注解一起使用。

  11. @ExceptionHandler:用于捕获处理方法中抛出的异常,可以定义全局异常处理方法或特定异常的处理方法。

  12. @ControllerAdvice:用于定义全局控制器的建言(增强)类,可以在其中定义全局异常处理方法、全局数据绑定等。

这些注解是Spring Boot中处理请求时最常用的注解,通过它们可以方便地定义控制器类和处理方法,并实现与请求相关的业务逻辑。

3、序列化与反序列化

Http请求处理流程实际上就是数据的序列化与反序列化的过程,如下图所示:

在这里插入图片描述

二、自定义返回类型处理(HttpMessageConverter)

下面以自定Excel文件下载为例,自定义请求处理类 XlsHttpMessageConverter

1、新建返回类型 XlsResult

@Data
public class XlsResult<T> {// 文件名称private String filename;// 表格 sheet名称private String sheetName;// 数据列表private List<T> data;// 数据类型private Class<T> type;
}

1、新建自定义返回类型处理器 XlsHttpMessageConverter

1)XlsHttpMessageConverter 继承 AbstractHttpMessageConverter,并传入返回值泛型 XlsResult
2)实现构造函数,传入Excel媒体类型
3)实现supports方法,判断返回类型
4)实现writeInternal写入数据方法,使用EasyExcel写入数据到输出流
5)添加注解@Component,会在AbstractMessageConverterMethodProcessor#messageConverters列表的第一个位置添加该自定义处理类XlsHttpMessageConverter

@Component
public class XlsHttpMessageConverter extends AbstractHttpMessageConverter<XlsResult<Object>> {private static final MediaType mediaType = MediaType.valueOf("application/vnd.ms-excel;charset=UTF-8");public XlsHttpMessageConverter() {super(mediaType);}@Overrideprotected boolean supports(Class<?> clazz) {return clazz == XlsResult.class;}@Overrideprotected XlsResult<Object> readInternal(Class<? extends XlsResult<Object>> clazz, HttpInputMessage inputMessage) throws IOException, HttpMessageNotReadableException {return null;}@Overrideprotected void writeInternal(XlsResult<Object> objectXlsResult, HttpOutputMessage outputMessage) throws IOException, HttpMessageNotWritableException {EasyExcel.write(outputMessage.getBody(), objectXlsResult.getType()).autoCloseStream(false) // 不要自动关闭,交给 Servlet 自己处理.registerWriteHandler(new LongestMatchColumnWidthStyleStrategy()) // 基于 column 长度,自动适配。最大 255 宽度.registerConverter(new LongStringConverter()) // 避免 Long 类型丢失精度.sheet(objectXlsResult.getSheetName()).doWrite(objectXlsResult.getData());}
}

2、添加Controller 请求方法,并注明 produces

这里以导出用户数据为例。

1)从数据库中查询用户数据列表
2)返回类型 XlsResult<UserRespVO>
3)设置 produces = {"application/vnd.ms-excel"}

在请求返回时,AbstractHttpMessageConverter.canWrite 同时判断了 supportsmediaType

public boolean canWrite(Class<?> clazz, @Nullable MediaType mediaType) {return supports(clazz) && canWrite(mediaType);
}
@GetMapping(value = "/exportList", produces = {"application/vnd.ms-excel"})
@Operation(summary = "导出用户")
public XlsResult<UserRespVO> exportList(@Validated UserPageReqVO exportReqVO,HttpServletResponse response) {XlsResult<UserRespVO> xlsResult = new XlsResult<>();xlsResult.setFilename("用户数据.xls");xlsResult.setSheetName("用户列表");xlsResult.setType(UserRespVO.class);exportReqVO.setPageSize(PageParam.PAGE_SIZE_NONE);// 从数据库查询用户列表List<UserRespVO> list = userService.getUserPage(exportReqVO).getList();xlsResult.setData(UserConvert.INSTANCE.convertList(list, deptMap));return xlsResult;
}

3、发送测试请求

打开 Postman,点击 Send and Download

如果出现文件下载框,说明处理正常!

在这里插入图片描述

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

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

相关文章

stm32--simulink开发之--timer的学习,硬件输入中断,触发事件,STM32通用定时器之输出比较模式与PWM模式(重要理解)

下面三个模块&#xff0c;一个比一个高级&#xff0c;当然使用是越来越简单 1&#xff0c;第一个模块&#xff1a;Timer Starts timer counter and provides current counter value Timer Starts Timer Counter and Provides Current Counter Value: 这个模块启动定时器计数器…

架构师应知必会的缩写大全

架构师应知必会的缩写大全 本文转自 公众号 ByteByteGo&#xff0c;如有侵权&#xff0c;请联系&#xff0c;立即删除 CAP、BASE、SOLID、KISS&#xff0c;这些缩写词是什么意思&#xff1f; 下图解释了系统设计中常见的缩写词。 CAP CAP 定理指出&#xff0c;任何分布式数据…

代码随想录Day37 | 738.单调递增的数字 968.监控二叉树

代码随想录Day37 | 738.单调递增的数字 968.监控二叉树 738.单调递增的数字968.监控二叉树 738.单调递增的数字 文档讲解&#xff1a;代码随想录 视频讲解&#xff1a; 贪心算法&#xff0c;思路不难想&#xff0c;但代码不好写&#xff01;LeetCode:738.单调自增的数字 状态 本…

QWT开源库使用

源代码地址&#xff1a;Qwt Users Guide: Qwt - Qt Widgets for Technical Applications Qwt库包含GUI组件和实用程序类&#xff0c;它们主要用于具有技术背景的程序。除了2D图的框架外&#xff0c;它还提供刻度&#xff0c;滑块&#xff0c;刻度盘&#xff0c;指南针&#xf…

oracle数据回滚导致业务性能问题排查

问题描述 数据库出现性能问题&#xff0c;应用响应超时持续长达10多分钟。由于每秒有大量insert&#xff0c;业务实时敏感性较高&#xff0c;而且每天凌晨会对前一天的数据进行归档也就是insert进历史表格&#xff0c;原表数据会进行delete清理&#xff08;数据量每天300W左右…

C语言指针学习(1)

前言 指针是C语言中一个重要概念&#xff0c;也是C语言的一个重要特色&#xff0c;正确而灵活地运用指针可以使程序简洁、紧凑、高效。每一个学习和使用C语言的人都应当深入的学习和掌握指针&#xff0c;也可以说不掌握指针就没有掌握C语言的精华。 一、什么是指针 想弄清楚什…

11. UE5 RPG使用GameplayEffect修改角色属性(二)

上一篇写了一下GameplayEffect的基础操作&#xff0c;这一篇进阶一下&#xff0c;讲解一下GameplayEffect堆叠功能&#xff0c;以及能够基于这个堆叠能够实现一些怎样的效果。 经过几天的查看&#xff0c;发现新版的更新的真不错&#xff0c;而且最上面竟然直接显示编译的错误…

【SpringBoot】SpringBoot的自动配置原理

&#x1f4dd;个人主页&#xff1a;五敷有你 &#x1f525;系列专栏&#xff1a;SpringBoot ⛺️稳重求进&#xff0c;晒太阳 自动配置 啥叫自动配置呢&#xff1f;简单说就是springboot根据我们开发者的行为猜测你要做什么事情&#xff0c;然后把你要用的bean都给你准备…

vue3使用is动态切换组件报错Vue received a Component which was made a reactive object.

vue3使用is动态切换组件&#xff0c;activeComponent用ref定义报错 Vue received a Component which was made a reactive object. This can lead to unnecessary performance overhead, and should be avoided by marking the component with markRaw or using shallowRef ins…

【Linux】初始进程地址空间

最近&#xff0c;我发现了一个超级强大的人工智能学习网站。它以通俗易懂的方式呈现复杂的概念&#xff0c;而且内容风趣幽默。我觉得它对大家可能会有所帮助&#xff0c;所以我在此分享。点击这里跳转到网站。 目录 一、再谈fork二、程序地址空间2.1代码验证 三、虚拟地址&am…

数据结构+算法(第05篇):数组和链表

作者简介&#xff1a;大家好&#xff0c;我是smart哥&#xff0c;前中兴通讯、美团架构师&#xff0c;现某互联网公司CTO 联系qq&#xff1a;184480602&#xff0c;加我进群&#xff0c;大家一起学习&#xff0c;一起进步&#xff0c;一起对抗互联网寒冬 学习必须往深处挖&…

前端工程化之:webpack1-8(loader)

一、loader webpack 做的事情&#xff0c;仅仅是分析出各种模块的依赖关系&#xff0c;然后形成资源列表&#xff0c;最终打包生成到指定的文件中。 更多的功能需要借助 webpack loaders (加载器)和 webpack plugins (插件)完成。 webpack loader &#xff1a; loader 本质上是…