Spring MVC策略模式之MethodArgumentResolver源码解析

Spring MVC 策略模式之 MethodArgumentResolver 源码解析

在 Spring MVC 中,MethodArgumentResolver 是一个非常重要的组件,它用于将请求参数转换为控制器方法的参数。MethodArgumentResolver 是 Spring MVC 策略模式的一部分,它通过实现 resolveArgument 方法来实现参数解析。本文将详细讲解 Spring MVC 策略模式之 MethodArgumentResolver 的源码解析,包括 MethodArgumentResolver 的定义、MethodArgumentResolver 的使用方法、MethodArgumentResolver 的实现原理等。

MethodArgumentResolver 的定义

MethodArgumentResolver 是一个接口,它定义了一个 resolveArgument 方法,用于将请求参数转换为控制器方法的参数。下面是 MethodArgumentResolver 接口的定义:

public interface MethodArgumentResolver {
  boolean supportsParameter(MethodParameter parameter);
  Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer, NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception;
}

在上面的代码中,MethodArgumentResolver 接口包含了两个方法:

  • supportsParameter:用于判断该 MethodArgumentResolver 是否支持当前参数类型。
  • resolveArgument:用于将请求参数转换为控制器方法的参数。

MethodArgumentResolver 的使用方法

在 Spring MVC 中,我们可以通过实现 MethodArgumentResolver 接口来自定义参数解析器。下面是一个简单的示例,演示了如何自定义参数解析器:

public class UserArgumentResolver implements MethodArgumentResolver {
  @Override
  public boolean supportsParameter(MethodParameter parameter) {
    return parameter.getParameterType().equals(User.class);
  }

  @Override
  public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer, NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception {
    User user = new User();
    user.setName(webRequest.getParameter("name"));
    user.setAge(Integer.parseInt(webRequest.getParameter("age")));
    return user;
  }
}

在上面的代码中,我们创建了一个 UserArgumentResolver 类,并实现了 MethodArgumentResolver 接口。在 supportsParameter 方法中,我们判断该参数解析器是否支持 User 类型的参数。在 resolveArgument 方法中,我们将请求参数转换为 User 对象,并返回该对象。

在使用自定义参数解析器时,我们需要将其注册到 RequestMappingHandlerAdapter 中。下面是一个简单的示例,演示了如何注册自定义参数解析器:

@Configuration
public class WebMvcConfig implements WebMvcConfigurer {
  @Override
  public void addArgumentResolvers(List<MethodArgumentResolver> resolvers) {
    resolvers.add(new UserArgumentResolver());
  }
}

在上面的代码中,我们创建了一个 WebMvcConfig 类,并实现了 WebMvcConfigurer 接口。在 addArgumentResolvers 方法中,我们将自定义参数解析器 UserArgumentResolver 添加到 resolvers 列表中。

MethodArgumentResolver 的实现原理

在 Spring MVC 中,参数解析器是通过 RequestMappingHandlerAdapter 来调用的。RequestMappingHandlerAdapter 会遍历所有的参数解析器,找到支持当前参数类型的参数解析器,并调用其 resolveArgument 方法来解析参数。下面是 RequestMappingHandlerAdapter 的源码片段:

public class RequestMappingHandlerAdapter extends AbstractHandlerMethodAdapter {
  private List<HandlerMethodArgumentResolver> argumentResolvers = new ArrayList<>();

  public RequestMappingHandlerAdapter() {
    this.argumentResolvers.add(new RequestParamMethodArgumentResolver());
    this.argumentResolvers.add(new RequestResponseBodyMethodProcessor());
    // ...
  }

  @Override
  public ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
    // ...
    for (HandlerMethodArgumentResolver resolver : this.argumentResolvers) {
      if (resolver.supportsParameter(parameter)) {
        Object arg = resolver.resolveArgument(parameter, mavContainer, webRequest, binderFactory);
        args[i] = arg;
        break;
      }
    }
    // ...
  }
}

在上面的代码中,我们可以看到 RequestMappingHandlerAdapter 中包含了一个 argumentResolvers 列表,该列表包含了所有的参数解析器。在 handle 方法中,RequestMappingHandlerAdapter 会遍历所有的参数解析器,找到支持当前参数类型的参数解析器,并调用其 resolveArgument 方法来解析参数。

示例说明

下面是两个示例,演示了如何使用 MethodArgumentResolver 自定义参数解析器:

示例一:使用 MethodArgumentResolver 解析自定义参数类型

public class UserArgumentResolver implements MethodArgumentResolver {
  @Override
  public boolean supportsParameter(MethodParameter parameter) {
    return parameter.getParameterType().equals(User.class);
  }

  @Override
  public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer, NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception {
    User user = new User();
    user.setName(webRequest.getParameter("name"));
    user.setAge(Integer.parseInt(webRequest.getParameter("age")));
    return user;
  }
}

@Controller
@RequestMapping("/user")
public class UserController {
  @RequestMapping(value = "/add", method = RequestMethod.POST)
  public String addUser(User user) {
    // 处理用户添加逻辑
    return "success";
  }
}

@Configuration
public class WebMvcConfig implements WebMvcConfigurer {
  @Override
  public void addArgumentResolvers(List<MethodArgumentResolver> resolvers) {
    resolvers.add(new UserArgumentResolver());
  }
}

在上面的代码中,我们创建了一个 UserArgumentResolver 类,并实现了 MethodArgumentResolver 接口。在 supportsParameter 方法中,我们判断该参数解析器是否支持 User 类型的参数。在 resolveArgument 方法中,我们将请求参数转换为 User 对象,并返回该对象。在 UserController 中,我们使用 User 类型的参数来接收请求参数。在 WebMvcConfig 中,我们将自定义参数解析器 UserArgumentResolver 添加到 resolvers 列表中。

示例二:使用 MethodArgumentResolver 解析 JSON 数据

public class JsonArgumentResolver implements MethodArgumentResolver {
  @Override
  public boolean supportsParameter(MethodParameter parameter) {
    return parameter.hasParameterAnnotation(RequestBody.class);
  }

  @Override
  public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer, NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception {
    String json = webRequest.getNativeRequest(HttpServletRequest.class).getReader().lines().collect(Collectors.joining(System.lineSeparator()));
    ObjectMapper objectMapper = new ObjectMapper();
    return objectMapper.readValue(json, parameter.getParameterType());
  }
}

@RestController
@RequestMapping("/user")
public class UserController {
  @PostMapping("/add")
  public String addUser(@RequestBody User user) {
    // 处理用户添加逻辑
    return "success";
  }
}

@Configuration
public class WebMvcConfig implements WebMvcConfigurer {
  @Override
  public void addArgumentResolvers(List<MethodArgumentResolver> resolvers) {
    resolvers.add(new JsonArgumentResolver());
  }
}

在上面的代码中,我们创建了一个 JsonArgumentResolver 类,并实现了 MethodArgumentResolver 接口。在 supportsParameter 方法中,我们判断该参数解析器是否支持 RequestBody 注解的参数。在 resolveArgument 方法中,我们将 JSON 数据转换为参数类型的对象,并返回该对象。在 UserController 中,我们使用 @RequestBody 注解来接收 JSON 数据。在 WebMvcConfig 中,我们将自定义参数解析器 JsonArgumentResolver 添加到 resolvers 列表中。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Spring MVC策略模式之MethodArgumentResolver源码解析 - Python技术站

(0)
上一篇 2023年5月18日
下一篇 2023年5月18日

相关文章

  • 带你入门java雪花算法原理

    带你入门java雪花算法原理 概述 雪花算法(Snowflake)是 Twitter 开源的分布式 id 生成算法,以其独特的 id 生成方式,广泛用于分布式系统中唯一 id 的生成,保证了分布式系统中数据的唯一性。 原理 雪花算法生成的 id 是一个 64 位的 long 型整数,其中: 1 bit:表示不可用,Java long 类型的高位是符号位,正数…

    Java 2023年5月19日
    00
  • Java日常练习题,每天进步一点点(40)

    下面是Java日常练习题的完整攻略: 1. 确定目标 我们的目标是通过做Java练习题来提高自己的编程能力,每天进步一点点。 2. 获取练习题 可以通过互联网上的Java编程练习网站,如Java编程练习网站等获取练习题。 3. 分析题目 在开始解题之前,请认真阅读题目并分析,确定题目的输入、输出、边界条件和算法思路。 4. 用Java代码实现 在分析完题目后…

    Java 2023年6月15日
    00
  • CentOS 7.9服务器Java部署环境配置的过程详解

    CentOS 7.9 服务器 Java 部署环境配置的过程详解 简介 在 CentOS 7.9 服务器上配置 Java 是一个常见的操作,本文将介绍在 CentOS 7.9 上配置 Java 的详细步骤,同时提供两个示例。 步骤 步骤一:安装 Java 环境 首先需要安装 Java 环境。可以通过 yum 命令进行安装: bash sudo yum inst…

    Java 2023年6月2日
    00
  • SpringBoot去除内嵌tomcat的实现

    以SpringBoot 2.x版本为例,要去除内嵌的Tomcat,可以按照以下步骤进行操作: 1.排除tomcat依赖 在pom.xml文件中,通过在spring-boot-starter-web依赖中排除Tomcat,可以去除内嵌的Tomcat。 示例: <dependencies> <dependency> <groupId…

    Java 2023年6月2日
    00
  • SpringBoot如何访问html和js等静态资源配置

    在Spring Boot中,我们可以使用静态资源来为我们的Web应用程序提供样式表、脚本、图像和其他静态内容。在本文中,我们将详细讲解如何在Spring Boot中访问静态资源。 静态资源目录 在Spring Boot中,我们可以将静态资源放置在以下目录中: /static /public /resources /META-INF/resources 这些目…

    Java 2023年5月18日
    00
  • spring mvc实现文件上传与下载功能

    Spring MVC实现文件上传与下载功能 Spring MVC是一个非常流行的Java Web框架,它提供了很多方便的功能,其中包括文件上传和下载。本文将详细讲解如何使用Spring MVC实现文件上传和下载功能,并提供两个示例来说明如何实现这一过程。 文件上传 文件上传是Web应用程序中常见的功能之一。Spring MVC提供了很多方便的类和注解来处理文…

    Java 2023年5月17日
    00
  • 详解JAVA生成将图片存入数据库的sql语句实现方法

    下面我将详细讲解“详解JAVA生成将图片存入数据库的 SQL 语句实现方法”的完整攻略。 1. 前置条件 在进行本攻略中的操作前,需要具备以下前置条件: 已安装 Java 开发环境并配置好环境变量 已安装 MySQL 数据库并配置好数据库信息 已导入 JDBC 驱动包,可以连接 MySQL 数据库 2. JAVA 代码实现 以下是将图片存入数据库的 JAVA…

    Java 2023年5月19日
    00
  • mybatis-plus主键生成策略

    mybatis-plus主键生成策略可以通过注解或配置文件进行设置,下面将详细讲解。 1. 注解方式设置主键生成策略 在实体类中使用@TableId注解可以设置主键生成方式。其属性type表示主键生成类型,取值范围为枚举类IdType中的枚举值,包括AUTO、NONE、INPUT、ID_WORKER、UUID、ID_WORKER_STR。其中,ID_WORK…

    Java 2023年5月19日
    00
合作推广
合作推广
分享本页
返回顶部