当前位置: 首页 > news >正文

HandlerMethodArgumentResolver :深入spring mvc参数解析机制

❃博主首页 : <码到三十五>
☠博主专栏 : <mysql高手> <elasticsearch高手> <源码解读> <java核心> <面试攻关>
♝博主的话 : 搬的每块砖,皆为峰峦之基;公众号搜索(码到三十五)关注这个爱发技术干货的coder,一起筑基 !

HandlerMethodArgumentResolver 是 Spring MVC 框架中的一个关键组件,用于解析控制器(Controller)方法的参数。在 Spring MVC 中,当一个请求到达时,DispatcherServlet 会负责找到对应的处理器(即控制器中的方法)来处理这个请求。在处理之前,需要解析方法的参数,这就是 HandlerMethodArgumentResolver 的作用

导读

      • 一、HandlerMethodArgumentResolver简介
      • 二、工作原理和流程
        • 1. 接口定义与功能
        • 2. 工作流程
          • 2.1 确定解析器
          • 2.2 解析参数
          • 2.3 异常处理
      • 三、内置解析器
      • 四、自定义解析器
        • 实现步骤
        • 常用场景
        • 用法方法
      • 五、结语

一、HandlerMethodArgumentResolver简介

HandlerMethodArgumentResolver 是 Spring MVC 提供的一个接口,用于将 HTTP 请求中的数据解析并绑定到控制器方法的参数上。它定义了两个主要的方法:supportsParameterresolveArgumentsupportsParameter 方法用于判断当前解析器是否支持给定的方法参数,而 resolveArgument 方法则用于实际解析请求中的数据,并将其作为参数值返回。

下图是mvc处理流程:
在这里插入图片描述

HandlerMethodArgumentResolver 的主要职责是解析控制器方法的参数。这意味着当 Spring MVC 调用一个控制器方法时(上图第6步),它使用这个解析器来将请求中的数据(如请求参数、路径变量、请求体等)转换为方法参数的具体值

HandlerMethodArgumentResolver 是 Spring MVC 框架中的一个核心接口,其工作原理主要围绕如何将 HTTP 请求中的数据解析并绑定到控制器(Controller)方法的参数上。以下是该接口工作原理的详细介绍:

二、工作原理和流程

1. 接口定义与功能

HandlerMethodArgumentResolver 接口定义了两个主要方法:

  • boolean supportsParameter(MethodParameter parameter): 用于判断当前解析器是否支持给定的方法参数。这通常基于参数的注解或类型来决定。
  • Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer, NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception: 用于实际解析请求中的数据,并将其作为参数值返回。如果在解析过程中遇到错误,该方法可能会抛出异常。

在这里插入图片描述

2. 工作流程

当 Spring MVC 接收到一个 HTTP 请求并确定要调用的控制器方法后,它会按照以下步骤使用 HandlerMethodArgumentResolver 来解析方法的参数:

2.1 确定解析器

Spring MVC 会遍历所有已注册的 HandlerMethodArgumentResolver 实现,并调用每个解析器的 supportsParameter 方法来检查是否有解析器支持当前方法的参数。一旦找到支持的解析器,就会使用该解析器来解析参数。

2.2 解析参数

一旦确定了合适的解析器,Spring MVC 就会调用该解析器的 resolveArgument 方法来实际解析请求中的数据。这个过程可能涉及从请求头、请求体、路径变量、查询参数等不同来源提取数据,并将其转换为方法参数所需的类型。

2.3 异常处理

如果在解析过程中发生异常,解析器通常会抛出一个异常,该异常随后会被 Spring MVC 的异常处理机制捕获并处理。这允许开发者为不同的异常类型提供自定义的错误响应。

三、内置解析器

Spring MVC 提供了多种内置的 HandlerMethodArgumentResolver 实现,用于处理不同类型的请求参数,如:

  • ServletRequestParamMethodArgumentResolver:解析请求参数中的查询参数。
    在这里插入图片描述

  • PathVariableMethodArgumentResolver:解析请求参数中的路径变量。

  • RequestHeaderMethodArgumentResolver:解析请求头中的参数。

  • RequestBodyMethodArgumentResolver:解析请求体中的参数,通常用于处理 JSON 或 XML 数据。

  • ServletModelAttributeMethodProcessor:处理带有 @ModelAttribute 注解的参数,用于将请求参数绑定到模型对象上。

四、自定义解析器

除了内置解析器外,Spring MVC 还允许开发者自定义 HandlerMethodArgumentResolver 实现类,以处理特殊的参数类型或实现自定义的解析逻辑。自定义解析器需要实现 HandlerMethodArgumentResolver 接口,并覆盖 supportsParameterresolveArgument 方法。然后,通过注册自定义解析器到 Spring MVC 的配置中,使其能够参与到参数解析的过程中。

实现步骤

自定义HandlerMethodArgumentResolver一般包含以下步骤:

  1. 创建自定义解析器类,实现 HandlerMethodArgumentResolver 接口。
  2. 覆盖 supportsParameter 方法,定义该解析器支持的参数类型或注解。
  3. 覆盖 resolveArgument 方法,实现自定义的参数解析逻辑。
  4. 在 Spring MVC 配置中注册自定义解析器。
常用场景

自定义HandlerMethodArgumentResolver通常在以下情况下使用:

  • 当需要解析的请求参数类型不是 Spring MVC 默认支持的。
  • 当需要在参数解析过程中添加特定的逻辑,如权限检查、数据验证等
用法方法

下面代码中,创建一个自定义解析器来解析一个自定义的注解 @CurrentUser,该注解用于将当前用户的信息注入到控制器方法的参数中。

首先,定义 @CurrentUser 注解:

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;@Target(ElementType.PARAMETER)
@Retention(RetentionPolicy.RUNTIME)
public @interface CurrentUser {
}

然后,创建自定义的 HandlerMethodArgumentResolver

import org.springframework.core.MethodParameter;
import org.springframework.web.bind.support.WebDataBinderFactory;
import org.springframework.web.context.request.NativeWebRequest;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.method.support.ModelAndViewContainer;
import org.springframework.stereotype.Component;@Component
public class CurrentUserArgumentResolver implements HandlerMethodArgumentResolver {@Overridepublic boolean supportsParameter(MethodParameter parameter) {return parameter.hasParameterAnnotation(CurrentUser.class) && parameter.getParameterType().equals(User.class);}@Overridepublic Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer,NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception {// 假设已经有获取当前用户的方法User currentUser = getCurrentUser(webRequest);return currentUser;}private User getCurrentUser(NativeWebRequest webRequest) {// 这里是你的逻辑来获取当前用户,例如从Session或Security Context中// 返回一个新的User实例return new User(); }
}

最后,在控制器中使用这个注解:

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;@RestController
public class UserController {@GetMapping("/user/info")public String getUserInfo(@CurrentUser User currentUser) {// 这里可以使用currentUser对象,它已经被解析器填充了return "User info for: " + currentUser.getName(); }
}

别忘了在Spring配置中注册这个解析器,如果使用的是Java配置,可以在配置类中添加:

import org.springframework.context.annotation.Configuration;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;import java.util.List;@Configuration
public class WebConfig implements WebMvcConfigurer {@Autowiredprivate CurrentUserArgumentResolver currentUserArgumentResolver;@Overridepublic void addArgumentResolvers(List<HandlerMethodArgumentResolver> resolvers) {resolvers.add(currentUserArgumentResolver);}
}

这样,当访问 /user/info 端点时,CurrentUserArgumentResolver 将会被调用,并将当前用户的信息注入到 getUserInfo 方法的 currentUser 参数中。

五、结语

HandlerMethodArgumentResolver 是 Spring MVC 框架中用于解析请求参数的关键接口。通过内置解析器和自定义解析器,Spring MVC 提供了灵活而强大的参数解析能力,使得开发者可以轻松处理各种复杂的请求参数场景。深入理解 HandlerMethodArgumentResolver 的工作原理对于掌握 Spring MVC 框架的请求处理流程和提高开发效率具有重要意义。


关注公众号获取更多技术干货 !

相关文章:

  • JAVA:文件防重设计指南
  • 商用全面提速,5G新通话进入普及阶段!
  • Matplotlib 文本
  • Spring学习03-[Spring容器核心技术IOC学习进阶]
  • 大数据开发中的数据生命周期管理
  • WebRtc实现1V1音视频通话
  • docker私有仓库harbor部署
  • 从零开始学习网络安全渗透测试之Linux基础篇——(四)Linux基本命令
  • 华为云交付模式和技术支持
  • Selenium 监视数据收发
  • k8s-第八节-Helm
  • SpringCloud Feign 报错 Request method ‘POST‘ not supported 的解决办法
  • 【CT】LeetCode手撕—148. 排序链表
  • 2024亚太杯中文赛数学建模B题【洪水灾害的数据分析与预测】思路详解
  • 利用Python破解隔壁家的WiFi密码
  • django开发-定时任务的使用
  • React的组件模式
  • SegmentFault 社区上线小程序开发频道,助力小程序开发者生态
  • Spark VS Hadoop:两大大数据分析系统深度解读
  • spring-boot List转Page
  • webgl (原生)基础入门指南【一】
  • 阿里云爬虫风险管理产品商业化,为云端流量保驾护航
  • 对话:中国为什么有前途/ 写给中国的经济学
  • 基于Android乐音识别(2)
  • 使用 Node.js 的 nodemailer 模块发送邮件(支持 QQ、163 等、支持附件)
  • 微信小程序设置上一页数据
  • 异步
  • [地铁译]使用SSD缓存应用数据——Moneta项目: 低成本优化的下一代EVCache ...
  • ​Linux Ubuntu环境下使用docker构建spark运行环境(超级详细)
  • #include到底该写在哪
  • #我与Java虚拟机的故事#连载02:“小蓝”陪伴的日日夜夜
  • (CVPRW,2024)可学习的提示:遥感领域小样本语义分割
  • (附表设计)不是我吹!超级全面的权限系统设计方案面世了
  • (附源码)ssm考生评分系统 毕业设计 071114
  • (附源码)ssm旅游企业财务管理系统 毕业设计 102100
  • (七)glDrawArry绘制
  • (一)【Jmeter】JDK及Jmeter的安装部署及简单配置
  • (一)Thymeleaf用法——Thymeleaf简介
  • (转)Google的Objective-C编码规范
  • .bat批处理(十):从路径字符串中截取盘符、文件名、后缀名等信息
  • .gitignore文件设置了忽略但不生效
  • .htaccess配置重写url引擎
  • .Net 4.0并行库实用性演练
  • .NET 8 中引入新的 IHostedLifecycleService 接口 实现定时任务
  • .NET Core使用NPOI导出复杂,美观的Excel详解
  • .Net多线程总结
  • .NET企业级应用架构设计系列之结尾篇
  • .net中应用SQL缓存(实例使用)
  • .sh文件怎么运行_创建优化的Go镜像文件以及踩过的坑
  • //TODO 注释的作用
  • @Autowired自动装配
  • @PreAuthorize与@Secured注解的区别是什么?
  • @Responsebody与@RequestBody
  • @SuppressLint(NewApi)和@TargetApi()的区别
  • [ vulhub漏洞复现篇 ] Celery <4.0 Redis未授权访问+Pickle反序列化利用