前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >SpringMVC 自定义参数解析器.

SpringMVC 自定义参数解析器.

作者头像
JMCui
发布2019-11-22 22:04:09
1.4K0
发布2019-11-22 22:04:09
举报
文章被收录于专栏:JMCui

一、简述

有没有想过像 @RequestParam、@RequestBody 这些注解的工作原理呢?为什么 form 表单、application/json 的参数能够直接封装进 Bean 对象中呢?这就要说到 HandlerMethodArgumentResolver — 方法参数解析器,该接口有两个方法:

代码语言:javascript
复制
public interface HandlerMethodArgumentResolver {

    boolean supportsParameter(MethodParameter parameter);


    Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer,
            NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception;

}

supportsParameter 方法返回 boolean 值,表示是否启用该解析器,true 表示启用,false 表示不启用;resolveArgument 方法表示方法参数的解析过程,就是你把 HTTP 的请求参数转换为方法参数的过程,返回 Object 对象,即参数的转换结果。

@RequestParam 对应的参数解析器是 RequestParamMethodArgumentResolver;@RequestBody 对应的参数解析器是 RequestResponseBodyMethodProcessor;诸如此类的解析器,读者可自行阅读。

二、自定义参数解析器

我想在控制器方法参数中得到当前用户的登陆信息,大概是如下这个效果,只要添加了 @CurrentUser 注解,那么 UserParam 参数中就会有当前用户的登陆信息。

代码语言:javascript
复制
    @RequestMapping(value = "/list", method = RequestMethod.POST)
    public ResponseData<List<SysWayDto>> list(@CurrentUser UserParam userParam) {
        Map<String, Object> objectMap = MapUtils.convertObjToMap(userParam);
        return sysWayService.findWithOriginDest(objectMap);
    }

怎么实现呢?首先我们需要有一个 @CurrentUser 注解:

代码语言:javascript
复制
@Target(ElementType.PARAMETER)
@Retention(RetentionPolicy.RUNTIME)
public @interface CurrentUser {
}

那么剩下来的工作就是 HandlerMethodArgumentResolver 的事情了:

代码语言:javascript
复制
@Slf4j
public class CurrentUserHandlerMethodArgumentResolver implements HandlerMethodArgumentResolver {

    /**
     * 用于判定是否需要处理该参数分解,返回 true 为需要,并会去调用下面的方法resolveArgument。
     */
    @Override
    public boolean supportsParameter(MethodParameter methodParameter) {
        return methodParameter.getParameterType().isAssignableFrom(UserParam.class)
                && methodParameter.hasParameterAnnotation(CurrentUser.class);
    }

    /**
     * 真正用于处理参数分解的方法,返回的 Object 就是 controller 方法上的形参对象。
     */
    @Override
    public Object resolveArgument(MethodParameter methodParameter, ModelAndViewContainer modelAndViewContainer, NativeWebRequest nativeWebRequest, WebDataBinderFactory webDataBinderFactory) throws Exception {
        String accessToken = nativeWebRequest.getHeader(GatewayHeader.accessToken);
        try {
            UserParam userParam = JsonUtils.readValue(JwtHelper.parseJWT(accessToken), UserParam.class);
            return userParam ;
        } catch (IOException e) {
            log.error("CurrentUserHandlerMethodArgumentResolver resolveArgument readValue error.accessToken:{}", accessToken, e);
        } catch (Exception e) {
            log.error("CurrentUserHandlerMethodArgumentResolver resolveArgument error.accessToken:{}", accessToken, e);
        }
        return null;
    }
}

最后,别忘了注册上自定义的参数解析器哦!

代码语言:javascript
复制
@Configuration
public class WebConfig extends WebMvcConfigurerAdapter {

    @Override
    public void addArgumentResolvers(List<HandlerMethodArgumentResolver> argumentResolvers) {
        argumentResolvers.add(new CurrentUserHandlerMethodArgumentResolver());
    }
}
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2019-11-22 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一、简述
  • 二、自定义参数解析器
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档