千家信息网

SpringBoot如何自定义参数解析器

发表于:2025-02-02 作者:千家信息网编辑
千家信息网最后更新 2025年02月02日,本篇内容主要讲解"SpringBoot如何自定义参数解析器",感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习"SpringBoot如何自定义参数解析器"吧!Sp
千家信息网最后更新 2025年02月02日SpringBoot如何自定义参数解析器

本篇内容主要讲解"SpringBoot如何自定义参数解析器",感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习"SpringBoot如何自定义参数解析器"吧!

SpringMVC提供了各种姿势的http参数解析支持,从前面的GET/POST参数解析篇也可以看到,加一个@RequsetParam注解就可以将方法参数与http参数绑定,看到这时自然就会好奇这是怎么做到的,我们能不能自己定义一种参数解析规则呢?

本文将介绍如何实现自定义的参数解析,并让其生效

I. 环境搭建

首先得搭建一个web应用才有可能继续后续的测试,借助SpringBoot搭建一个web应用属于比较简单的活;

创建一个maven项目,pom文件如下

    org.springframework.boot    spring-boot-starter-parent    2.1.7         UTF-8    UTF-8    Finchley.RELEASE    1.8            org.springframework.boot        spring-boot-starter-web                                            org.springframework.boot                spring-boot-maven-plugin                                    spring-milestones        Spring Milestones        https://repo.spring.io/milestone                    false            

II. 自定义参数解析器

对于如何自定义参数解析器,一个较推荐的方法是,先搞清楚springmvc接收到一个请求之后完整的处理链路,然后再来看在什么地方,什么时机,来插入自定义参数解析器,无论是从理解还是实现都会简单很多。遗憾的是,本篇主要目标放在的是使用角度,所以这里只会简单的提一下参数解析的链路,具体的深入留待后续的源码解析

1. 参数解析链路

http请求流程图,来自 SpringBoot是如何解析HTTP参数的

既然是参数解析,所以肯定是在方法调用之前就会被触发,在Spring中,负责将http参数与目标方法参数进行关联的,主要是借助org.springframework.web.method.support.HandlerMethodArgumentResolver类来实现

/** * Iterate over registered {@link HandlerMethodArgumentResolver}s and invoke the one that supports it. * @throws IllegalStateException if no suitable {@link HandlerMethodArgumentResolver} is found. */@Override@Nullablepublic Object resolveArgument(MethodParameter parameter, @Nullable ModelAndViewContainer mavContainer,                NativeWebRequest webRequest, @Nullable WebDataBinderFactory binderFactory) throws Exception {        HandlerMethodArgumentResolver resolver = getArgumentResolver(parameter);        if (resolver == null) {                throw new IllegalArgumentException("Unknown parameter type [" + parameter.getParameterType().getName() + "]");        }        return resolver.resolveArgument(parameter, mavContainer, webRequest, binderFactory);}

上面这段核心代码来自org.springframework.web.method.support.HandlerMethodArgumentResolverComposite#resolveArgument,主要作用就是获取一个合适的HandlerMethodArgumentResolver,实现将http参数(webRequest)映射到目标方法的参数上(parameter)

所以说,实现自定义参数解析器的核心就是实现一个自己的HandlerMethodArgumentResolver

2. HandlerMethodArgumentResolver

实现一个自定义的参数解析器,首先得有个目标,我们在get参数解析篇里面,当时遇到了一个问题,当传参为数组时,定义的方法参数需要为数组,而不能是List,否则无法正常解析;现在我们则希望能实现这样一个参数解析,以支持上面的场景

为了实现上面这个小目标,我们可以如下操作

a. 自定义注解ListParam

定义这个注解,主要就是用于表明,带有这个注解的参数,希望可以使用我们自定义的参数解析器来解析;

@Target(ElementType.PARAMETER)@Retention(RetentionPolicy.RUNTIME)@Documentedpublic @interface ListParam {    /**     * Alias for {@link #name}.     */    @AliasFor("name") String value() default "";    /**     * The name of the request parameter to bind to.     *     * @since 4.2     */    @AliasFor("value") String name() default "";}
b. 参数解析器ListHandlerMethodArgumentResolver

接下来就是自定义的参数解析器了,需要实现接口HandlerMethodArgumentResolver

public class ListHandlerMethodArgumentResolver implements HandlerMethodArgumentResolver {    @Override    public boolean supportsParameter(MethodParameter parameter) {        return parameter.hasParameterAnnotation(ListParam.class);    }    @Override    public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer,            NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception {        ListParam param = parameter.getParameterAnnotation(ListParam.class);        if (param == null) {            throw new IllegalArgumentException(                    "Unknown parameter type [" + parameter.getParameterType().getName() + "]");        }        String name = "".equalsIgnoreCase(param.name()) ? param.value() : param.name();        if ("".equalsIgnoreCase(name)) {            name = parameter.getParameter().getName();        }        String ans = webRequest.getParameter(name);        if (ans == null) {            return null;        }        String[] cells = StringUtils.split(ans, ",");        return Arrays.asList(cells);    }}

上面有两个方法:

  • supportsParameter就是用来表明这个参数解析器适不适用

    • 实现也比较简单,就是看参数上有没有前面定义的ListParam注解

  • resolveArgument 这个方法就是实现将http参数粗转换为目标方法参数的具体逻辑

    • 上面主要是为了演示自定义参数解析器的过程,实现比较简单,默认只支持List

3. 注册

上面虽然实现了自定义的参数解析器,但是我们需要把它注册到HandlerMethodArgumentResolver才能生效,一个简单的方法如下

@SpringBootApplicationpublic class Application extends WebMvcConfigurationSupport {    @Override    protected void addArgumentResolvers(List argumentResolvers) {        argumentResolvers.add(new ListHandlerMethodArgumentResolver());    }    public static void main(String[] args) {        SpringApplication.run(Application.class);    }}

4. 测试

为了验证我们的自定义参数解析器ok,我们开两个对比的rest服务

@RestController@RequestMapping(path = "get")public class ParamGetRest {    /**     * 自定义参数解析器     *     * @param names     * @param age     * @return     */    @GetMapping(path = "self")    public String selfParam(@ListParam(name = "names") List names, Integer age) {        return names + " | age=" + age;    }    @GetMapping(path = "self2")    public String selfParam2(List names, Integer age) {        return names + " | age=" + age;    }}

演示demo如下,添加了ListParam注解的可以正常解析,没有添加注解的会抛异常

到此,相信大家对"SpringBoot如何自定义参数解析器"有了更深的了解,不妨来实际操作一番吧!这里是网站,更多相关内容可以进入相关频道进行查询,关注我们,继续学习!

0