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日

相关文章

  • Spring Boot之FilterRegistrationBean-自定义Filter详解

    下面是对于“Spring Boot之FilterRegistrationBean-自定义Filter详解”的完整攻略。 什么是FilterRegistrationBean? FilterRegistrationBean是Spring提供的一个Bean,用于将Filter(过滤器)注册到Servlet容器中的过程中进行拦截,进而实现自定义Filter。 如何使…

    Java 2023年5月31日
    00
  • Java8之Lambda表达式使用解读

    Java8之Lambda表达式使用解读 什么是Lambda表达式? Lambda表达式是一种匿名函数,它没有名称,但它有参数列表、函数体和可能存在的返回类型,可以在需要函数类型的上下文中使用。 举个例子,我们可以使用Lambda表达式来实现简化的Runnable接口: Runnable r = () -> System.out.println(&quo…

    Java 2023年5月26日
    00
  • Java编程发展历史(动力节点Java学院整理)

    Java编程发展历史 Java前身 Java语言是由Sun Microsystems公司(后被Oracle公司收购)于1995年推出的一门计算机编程语言。起初,该语言被称为Oak语言,因为Oak是Sun Microsystems的办公室门外长了一棵橡树,而这个项目在设计之初的代号就是Oak。 Java语言推出 后来,强调语言应该与因特网紧密结合,适应网络环境…

    Java 2023年5月20日
    00
  • Java高级面试题小结

    让我给大家详细讲解“Java高级面试题小结”的完整攻略。 简介 “Java高级面试题小结”是一篇系统总结Java面试中常出现的高级难点问题以及解决方案的文章。该文主要分为以下几个部分: Java高级面试题分类 Java高级面试题解析及解决方案 Java高级面试题分类 Java高级面试题主要分为以下几个类别: 多线程 并发集合 垃圾回收算法 反射机制 设计模式…

    Java 2023年5月26日
    00
  • idea连接SQL Server数据库的详细图文教程

    下面我来详细讲解“idea连接SQL Server数据库的详细图文教程”的攻略。 准备工作 安装idea 下载安装SQL Server JDBC驱动程序,例如Microsoft官方提供的sqljdbc驱动 连接SQL Server 打开idea,选择菜单栏“File” -> “Data Sources” 在新弹出的窗口中,点击右上角的“+”按钮,选择“…

    Java 2023年6月16日
    00
  • 详解Spring AOP 实现“切面式”valid校验

    关于“详解Spring AOP 实现‘切面式’valid校验”的完整攻略,这是一个相对比较复杂的话题,需要我们详细来讲解一下。下面是我的分享: 什么是AOP AOP,Aspect Oriented Programming,面向切面编程,是OOP(Object Oriented Programming,面向对象编程)的一种补充。其实现是基于代理模式的基础之上的…

    Java 2023年5月20日
    00
  • 从原理聊JVM(一):染色标记和垃圾回收算法

    作者:京东科技 康志兴 1 JVM运行时内存划分 1.1 运行时数据区域 • 方法区 属于共享内存区域,存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据。运行时常量池,属于方法区的一部分,用于存放编译期生成的各种字面量和符号引用。 JDK1.8之前,Hotspot虚拟机对方法区的实现叫做永久代,1.8之后改为元空间。二者区别主要在于永…

    Java 2023年4月22日
    00
  • hibernate-validator如何使用校验框架

    下面是详细讲解“hibernate-validator如何使用校验框架”的完整攻略。 简介 hibernate-validator是一款基于Java Bean Validation标准的校验框架,能够轻松地将校验逻辑应用到JavaBean中,大大提高开发效率,减少出错几率。 使用步骤 1. 引入依赖 在项目的pom.xml文件中添加如下依赖配置: <d…

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