【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请求处理流程实际上就是数据的序列化与反序列化的过程,如下图所示:

【SpringBoot3】Spring 请求处理流程,自定义返回类型处理(HttpMessageConverter)_第1张图片

二、自定义返回类型处理(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);
    }

    @Override
    protected boolean supports(Class<?> clazz) {
        return clazz == XlsResult.class;
    }

    @Override
    protected XlsResult<Object> readInternal(Class<? extends XlsResult<Object>> clazz, HttpInputMessage inputMessage) throws IOException, HttpMessageNotReadableException {
        return null;
    }

    @Override
    protected 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
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

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

【SpringBoot3】Spring 请求处理流程,自定义返回类型处理(HttpMessageConverter)_第2张图片

你可能感兴趣的:(SpringBoot,3.0,从入门到精通,spring,后端,springboot,请求处理)