Spring Boot HandlerMethodArgumentResolver 使用和场景

在 Spring Boot 中,HandlerMethodArgumentResolver 是一个非常有用的接口,它可以帮助我们在处理请求时将请求参数转换为方法参数。这对于简化代码和提高开发效率非常有帮助,特别是在处理复杂的 RESTful API 时。下面是使用方式和多个场景案例。

使用方式

要使用 HandlerMethodArgumentResolver,需要遵循以下步骤:

  1. 创建一个自定义的 HandlerMethodArgumentResolver 实现类。
  2. 在该类中实现 supportsParameter() 方法和 resolveArgument() 方法。
  3. 在 Spring Boot 应用程序中注册该类。

创建自定义的 HandlerMethodArgumentResolver 实现类

为了将 HTTP 请求参数转换为 Java 对象,我们需要创建一个自定义的 HandlerMethodArgumentResolver 实现类。在这个类中,我们需要实现 supportsParameter() 方法和 resolveArgument() 方法。

supportsParameter() 方法

supportsParameter() 方法中,我们需要检查方法参数是否与我们要转换的 Java 类型相同。如果是,返回 true,否则返回 false

resolveArgument() 方法

resolveArgument() 方法中,我们需要将 HTTP 请求参数转换为 Java 对象。为此,我们可以使用 NativeWebRequest 对象来获取请求参数,然后将其转换为 Java 对象。

注册自定义的 HandlerMethodArgumentResolver 实现类

要在 Spring Boot 应用程序中使用自定义的 HandlerMethodArgumentResolver 实现类,我们需要将其注册到应用程序上下文中。为此,我们可以创建一个 @Configuration 类,并实现 WebMvcConfigurer 接口。在这个类中,我们需要重写 addArgumentResolvers() 方法,并将自定义的 HandlerMethodArgumentResolver 实现类添加到参数解析器列表中。

@Configuration
public class AppConfig implements WebMvcConfigurer {
 
    @Override
    public void addArgumentResolvers(List<HandlerMethodArgumentResolver> resolvers) {
        resolvers.add(new CustomHandlerMethodArgumentResolver());
    }
}

多个场景案例

以下是一些场景案例,演示了如何使用 HandlerMethodArgumentResolver 解析不同类型的请求参数。

将 JSON 请求体转换为 Java 对象

假设有一个 POST 请求,其中包含以下 JSON 请求体:

{  "name": "John",  "age": 30}

我们可以创建一个自定义的 HandlerMethodArgumentResolver 实现类来将这些参数转换为 Java 对象。

public class JsonHandlerMethodArgumentResolver implements HandlerMethodArgumentResolver {
 
    @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 mapper = new ObjectMapper();
        return mapper.readValue(json, parameter.getParameterType());
    }
}

在这个示例中,我们创建了一个名为 JsonHandlerMethodArgumentResolver 的自定义 HandlerMethodArgumentResolver 实现类,并在其中解析 JSON 请求体。在 supportsParameter() 方法中,我们检查方法参数是否带有 @RequestBody 注解。在 resolveArgument() 方法中,我们从请求体中读取 JSON 数据,并使用 ObjectMapper 将其转换为 Java 对象。

将 XML 请求体转换为 Java 对象

假设有一个 POST 请求,其中包含以下 XML 请求体:

<user>  <name>John</name>  <age>30</age></user>

我们可以创建一个自定义的 HandlerMethodArgumentResolver 实现类来将这些参数转换为 Java 对象。

public class XmlHandlerMethodArgumentResolver implements HandlerMethodArgumentResolver {
 
    @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 xml = webRequest.getNativeRequest(HttpServletRequest.class).getReader().lines().collect(Collectors.joining(System.lineSeparator()));
        JAXBContext jaxbContext = JAXBContext.newInstance(parameter.getParameterType());
        Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
        StringReader reader = new StringReader(xml);
        return unmarshaller.unmarshal(reader);
    }
}

在这个示例中,我们创建了一个名为 XmlHandlerMethodArgumentResolver 的自定义 HandlerMethodArgumentResolver 实现类,并在其中解析 XML 请求体。在 supportsParameter() 方法中,我们检查方法参数是否带有 @RequestBody 注解。在 resolveArgument() 方法中,我们从请求体中读取 XML 数据,并使用 JAXBContextUnmarshaller 将其转换为 Java 对象。

将多个请求参数转换为 Java 对象

假设有一个 GET 请求,其中包含以下请求参数:

name=John&age=30

我们可以创建一个自定义的 HandlerMethodArgumentResolver 实现类来将这些参数转换为 Java 对象。

public class UserHandlerMethodArgumentResolver implements HandlerMethodArgumentResolver {
 
    @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 {
        String name = webRequest.getParameter("name");
        int age = Integer.parseInt(webRequest.getParameter("age"));
        User user = new User();
        user.setName(name);
        user.setAge(age);
        return user;
    }
}

在这个示例中,我们创建了一个名为 UserHandlerMethodArgumentResolver 的自定义 HandlerMethodArgumentResolver 实现类,并在其中解析多个请求参数。在 supportsParameter() 方法中,我们检查方法参数是否与 User 类型相同。在 resolveArgument() 方法中,我们从请求参数中获取数据,并将其转换为 User 对象。

注册自定义的 HandlerMethodArgumentResolver 实现类

要在 Spring Boot 应用程序中使用自定义的 HandlerMethodArgumentResolver 实现类,我们需要将其注册到应用程序上下文中。为此,我们可以创建一个 @Configuration 类,并实现 WebMvcConfigurer 接口。在这个类中,我们需要重写 addArgumentResolvers() 方法,并将自定义的 HandlerMethodArgumentResolver 实现类添加到参数解析器列表中。

@Configuration
public class AppConfig implements WebMvcConfigurer {
 
    @Override
    public void addArgumentResolvers(List<HandlerMethodArgumentResolver> resolvers) {
        resolvers.add(new JsonHandlerMethodArgumentResolver());
        resolvers.add(new XmlHandlerMethodArgumentResolver());
        resolvers.add(new UserHandlerMethodArgumentResolver());
    }
}

现在,我们已经成功地创建了多个自定义的 HandlerMethodArgumentResolver 实现类,并将它们注册到 Spring Boot 应用程序中。这样,我们就能够轻松地处理不同类型的请求参数,并将它们转换为 Java 对象。

自定义注解来简化参数赋值。

例如,假设您有一个 @UserParam 注解,您可以使用以下代码来解析它:

public class UserHandlerMethodArgumentResolver implements HandlerMethodArgumentResolver {
 
    @Override
    public boolean supportsParameter(MethodParameter parameter) {
        return parameter.getParameterAnnotation(UserParam.class) != null;
    }
 
    @Override
    public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer, NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception {
        UserParam userParam = parameter.getParameterAnnotation(UserParam.class);
        String name = webRequest.getParameter(userParam.name());
        int age = Integer.parseInt(webRequest.getParameter(userParam.age()));
        User user = new User();
        user.setName(name);
        user.setAge(age);
        return user;
    }
}

在这个示例中,我们创建了一个 @UserParam 注解,并将其应用于方法参数上。然后,我们可以在 supportsParameter() 方法中检查方法参数是否带有 @UserParam 注解。在 resolveArgument() 方法中,我们从注解中获取参数名,并从请求参数中获取相应的值,然后将其转换为 User 对象。

要在 Spring Boot 应用程序中使用自定义注解,您需要将您的注解类添加到 @Configuration 类中,并将其添加到 addArgumentResolvers() 方法中:

@Configuration
public class AppConfig implements WebMvcConfigurer {
 
    @Override
    public void addArgumentResolvers(List<HandlerMethodArgumentResolver> resolvers) {
        resolvers.add(new UserHandlerMethodArgumentResolver());
    }
 
    @Retention(RetentionPolicy.RUNTIME)
    @Target(ElementType.PARAMETER)
    public @interface UserParam {
        String name() default "name";
        String age() default "age";
    }
}

现在,您就可以在 Spring Boot 应用程序中使用 @UserParam 注解来简化

请登录后发表评论

    没有回复内容