墨海文章集

SpringBoot:构建自定义的HandlerMethodAr

2022-02-07  本文已影响0人  花花大脸猫

前一篇博客使用TypeConvert实现类型String到LocalDate/LocalDateTime转换,使用TypeConvert对于创建简单的值类型并且将其注入到Controller对应的方法,是一个不错的选择。

但是,有时候我们注入的对象需要满足如下这些要求:

如果我们需要满足上述说的这些要求,就需要创建一个自定义的HandlerMethodArgumentResolver,那这篇博客就是为了描述我们如何做到这一点。

创建一个自定义的HandlerMethodArgumentResolver

新建一个FooBar类,包含两个final修饰的字段:bar 和 foo

 private final String foo;
    private final String bar;

    public FooBar(String foo, String bar) {
        this.foo = foo;
        this.bar = bar;
    }

    public String getFoo() {
        return foo;
    }

    public String getBar() {
        return bar;
    }

    @Override
    public String toString() {
        return "FooBar{" +
                "foo='" + foo + '\'' +
                ", bar='" + bar + '\'' +
                '}';
    }

通过如下步骤,创建自定义的HandlerMethodArgumentResolver,用于创建FooBar对象:

  1. 实现HandlerMethodArgumentResolver 接口
  2. 实现supportsParameter(MethodParameter methodParameter)方法,如果方法参数是FooBar类型返回true,其余返回false
  3. 实现resolveArgument() 方法,逻辑如下:
    (1)从请求参数获bar的值
    (2)从请求参数获foo的值
    (3)如果请求参数中不存在bar的值,使用默认值
    (4)如果请求参数中不存在foo的值,使用默认值
    (5)创建一个新的FooBar对象并返回

具体代码如下:

public class CustomMethodArgumentResolver implements HandlerMethodArgumentResolver {
    @Override
    public boolean supportsParameter(MethodParameter parameter) {
        if(parameter.getParameterType().equals(FooBar.class)){
            return true;
        }

        return false;
    }

    @Override
    public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer, NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception {
        String bar = webRequest.getParameter("bar");
        String foo = webRequest.getParameter("foo");

        if(null == bar){
            bar = "defaultBar";
        }

        if(null == foo){
            bar = "defaultFoo";
        }
        return new FooBar(foo, bar);
    }
}

配置web应用上下文信息

在我们注入FooBar 对象到Controller方法之前,我们需要注册CustomMethodArgumentResolver 作为方法参数的解析器,下面我们将介绍如何在springboot中进行注册

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

测试功能

@SpringBootApplication(exclude = DataSourceAutoConfiguration.class)
@EnableWebMvc
@RestController
public class DemoApplication {

    public static void main(String[] args) {
        SpringApplication.run(DemoApplication.class, args);
    }

    @RequestMapping(value = "/foobar", method = RequestMethod.POST)
    public String processFooBar(FooBar fooBar){
        System.out.println(fooBar);
        return "test is ok";
    }

}

测试结果请求输出如下:


image.png
2022-02-07 23:08:07.633  INFO 19876 --- [nio-8080-exec-2] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring DispatcherServlet 'dispatcherServlet'
2022-02-07 23:08:07.634  INFO 19876 --- [nio-8080-exec-2] o.s.web.servlet.DispatcherServlet        : Initializing Servlet 'dispatcherServlet'
2022-02-07 23:08:07.634  INFO 19876 --- [nio-8080-exec-2] o.s.web.servlet.DispatcherServlet        : Completed initialization in 0 ms
FooBar{foo='2021-12-13', bar='defaultBar'}

总结:

  1. 如果我们想要注入复杂类型的对象进入Controller方法,这些对象既不是表单对象也不是来自于request body中,这时候我们就需要创建一个自定义的HandlerMethodArgumentResolver 接口实现类

  2. 在自定义的HandlerMethodArgumentResolver 接口实现类生效之前,我们需要将其注册到上下文环境的resolvers列表内。

参考链接:https://www.petrikainulainen.net/programming/spring-framework/spring-from-the-trenches-creating-a-custom-handlermethodargumentresolver/

上一篇 下一篇

猜你喜欢

热点阅读