zoukankan      html  css  js  c++  java
  • SpringMVC 自定义参数解析器.

    一、简述

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

    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 参数中就会有当前用户的登陆信息。

        @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 注解:

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

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

    @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;
        }
    }
    

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

    @Configuration
    public class WebConfig extends WebMvcConfigurerAdapter {
    
        @Override
        public void addArgumentResolvers(List<HandlerMethodArgumentResolver> argumentResolvers) {
            argumentResolvers.add(new CurrentUserHandlerMethodArgumentResolver());
        }
    }
    
  • 相关阅读:
    AMR转换MP3 linuxCentOS 版(不管任何语言可以使用shell命令在linux执行转换语句)
    MySql 入门——日期计算
    javascript深度剖析之 【 var 关键字】。
    javascript动画浅析。
    javascript之this关键字浅析。
    javascript【AMD模块加载器】浅析V3(添加CSS加载功能,重构内部流程)
    html5 canvas 自制小游戏系列之 【贪吃蛇】。
    javascript设计模式简单介绍之【工厂模式】
    javascript【AMD模块加载器】浅析
    javascript【AMD模块加载器】浅析V2(整合DOM ready)
  • 原文地址:https://www.cnblogs.com/jmcui/p/11909524.html
Copyright © 2011-2022 走看看