Springboot自定义方法参数解析器

将request请求的参数解析后绑定到对应的Controller参数上,可以参考SpringMVC的RequestParamMethodArgumentResolver,自定义一个参数解析器。

1 . 实现一个既可接收基本类型,又可接收JavaBean对象类型的参数解析器

(类似@RequestBody)

① pom.xml中添加依赖

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <optional>true</optional>
</dependency>
<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>fastjson</artifactId>
    <version>1.2.49</version>
</dependency>

② 自定义一个参数注解

@Target(ElementType.PARAMETER)
@Retention(RetentionPolicy.RUNTIME)
public @interface TkParam {

    /**
     * 参数别名
     */
    @AliasFor("name")
    String value() default "";
    /**
     * 参数别名
     */
    @AliasFor("value")
    String name() default "";
    /**
     * 是否必填
     */
    boolean required() default true;
}

③ 自定义参数解析器
可参考: SpringMVC内置实现的RequestParamMethodArgumentResolver

public class TkRequestParamArgumentResolver extends AbstractNamedValueMethodArgumentResolver {

    @Override
    protected NamedValueInfo createNamedValueInfo(MethodParameter parameter) {
        TkParam anno = parameter.getParameterAnnotation(TkParam.class);
        return anno == null ? new NamedValueInfo("", false, ValueConstants.DEFAULT_NONE) :
                new NamedValueInfo(anno.name(), anno.required(), ValueConstants.DEFAULT_NONE);
    }

    @Override
    protected Object resolveName(String key, MethodParameter parameter, NativeWebRequest request) throws Exception {
       //获取参数类型
       Type paramType = parameter.getGenericParameterType();
       if (paramType == null) {
           throw new IllegalArgumentException("undefined parameter type!");
       }

       Object result = request.getParameter(key);
       //判断参数是否是JavaBean对象类型
       if (ParserConfig.global.getDeserializer(paramType) instanceof JavaBeanDeserializer) {
           Map<String, String> map = new HashMap();
           Map<String, String[]> paramMap = request.getParameterMap();
           for (Map.Entry<String, String[]> entry : paramMap.entrySet()) {
               String name = entry.getKey();
               String value = URLDecoder.decode(entry.getValue()[0], "UTF-8");
               map.put(name, value);
           }
           result = JSON.parseObject(JSON.toJSONString(map), paramType);
       }
       return result;
    }

    /**
     * 判断是否支持解析当前参数
     */
    @Override
    public boolean supportsParameter(MethodParameter parameter) {
        return parameter.hasParameterAnnotation(TkParam.class);
    }

}

④ 实现WebMvcConfigurer接口,添加web相关配置

注:WebMvcConfigurerAdapter在Spring Boot 2.0时已被废弃,官方推荐使用WebMvcConfigurer接口实现。

@Configuration
public class ApiMvcConfigure implements WebMvcConfigurer {

    /**
     * 添加参数解析器
     * @param resolvers
     */
    @Override
    public void addArgumentResolvers(List<HandlerMethodArgumentResolver> resolvers) {
        resolvers.add(new TkRequestParamArgumentResolver());
    }
}

⑤ 测试一下

定义一个UserModel的类:

@Setter
@Getter
@NoArgsConstructor
@AllArgsConstructor
public class UserModel {
    /**
     * 用户名
     */
    private String username;
    /**
     * 密码(MD5)
     */
    private String password;
}

创建控制器:

@RestController
@RequestMapping
public class TestController {

    @RequestMapping("test")
    public String testSession(@TkParam String username) throws Exception {
        return username;
    }

    @RequestMapping("login")
    public String userLogin(@TkParam UserModel model) throws Exception {
        return String.format("用户名:%s,密码:%s", model.getUsername(), model.getPassword());
    }

}

浏览器中输入:
http://localhost:8080/login?username=Tom&password=e10adc3949ba59abbe56e057f20f883e
,回车后页面显示:

用户名:Tom,密码:e10adc3949ba59abbe56e057f20f883e
Comments
Write a Comment