• SpringBoot自定义参数解析器


    一、背景

    平常经常用 @RequestParam注解来获取参数,然后想到我能不能写个自己注解获取请求的ip地址呢?就像这样 @IP String ip

    二、分析

    于是开始分析 @RequestParam是如何实现的。

    从@RequestParam注解开始入手,搜索该注解在源码中使用的地方
    分别是类RequestParamMethodArgumentResolverRequestParamMapMethodArgumentResolver

    类关系图
    类关系图

    RequestParamMethodArgumentResolver
    RequestParamMethodArgumentResolver

    可以看到两个类都最终实现了HandlerMethodArgumentResolver这个接口。

    HandlerMethodArgumentResolver结构
    HandlerMethodArgumentResolver结构

    里面就两个方法,supportsParameter方法是检测该参数是否支持这个参数解析器,
    如果supportsParameter方法返回true,则调用resolveArgument来进行参数解析工作。

    三、代码编写

    现在就可以写自己的参数解析器了,但是推荐继承AbstractNamedValueMethodArgumentResolver而不是直接实现HandlerMethodArgumentResolver接口。
    1.注解@IP

    1. /** 
    2. * 获取参数 
    3. * Created by 2YSP on 2019/1/6. 
    4. */ 
    5. @Documented 
    6. @Retention(value = RetentionPolicy.RUNTIME) 
    7. @Target(ElementType.PARAMETER) 
    8. public @interface IP { 
    9.  
    10. String name() default "ip"
    11.  
    12. boolean required() default true
    13.  
    14. String defaultValue() default "0"

    2.参数解析器IPAddressArgumentResolver

    1. /** 
    2. * Created by 2YSP on 2019/1/6. 
    3. */ 
    4. public class IPAddressArgumentResolver extends AbstractNamedValueMethodArgumentResolver
    5. @Override 
    6. protected NamedValueInfo createNamedValueInfo(MethodParameter parameter)
    7. IP annotation = parameter.getParameterAnnotation(IP.class); 
    8. return new IPAddressArgumentResolver.RequestIPNamedValueInfo(annotation); 
    9.  
    10. @Nullable 
    11. @Override 
    12. protected Object resolveName(String name, MethodParameter parameter, NativeWebRequest request) throws Exception
    13. HttpServletRequest servletRequest = request.getNativeRequest(HttpServletRequest.class); 
    14. String ip = servletRequest.getRemoteAddr(); 
    15. return ip == null ? "127.0.0.1":ip; 
    16.  
    17. @Override 
    18. public boolean supportsParameter(MethodParameter parameter)
    19. return parameter.hasParameterAnnotation(IP.class) && !Map.class.isAssignableFrom(parameter.nestedIfOptional().getNestedParameterType()); 
    20.  
    21. private static class RequestIPNamedValueInfo extends NamedValueInfo
    22.  
    23. private RequestIPNamedValueInfo(IP annotation)
    24. super(annotation.name(), annotation.required(), annotation.defaultValue()); 
    25.  

    这三个方法是必须实现的,还有一个可选重写的handleMissingValue。
    3.添加配置

    1. @Configuration 
    2. @EnableWebMvc 
    3. public class MvcConfig implements WebMvcConfigurer
    4.  
    5.  
    6. @Override 
    7. public void addArgumentResolvers(List<HandlerMethodArgumentResolver> resolvers)
    8. resolvers.add(new IPAddressArgumentResolver()); 

    4.controller

    1. @Slf4j 
    2. @RestController 
    3. public class VOTestController
    4.  
    5. @GetMapping("vo/test"
    6. public BaseVo test(@IP String ip)
    7.  
    8. log.info("请求的ip地址为:{}",ip); 
    9. BaseVo baseVo = new BaseVo(); 
    10. //设置为Null 
    11. baseVo.setResult(null); 
    12. return baseVo; 

    四、测试总结

    启动项目,游览器请求http://localhost/vo/test可以看到日志显示:

    2019-01-11 10:30:24.284 [http-nio-80-exec-3] INFO  cn.sp.controller.VOTestController - 请求的ip地址为:0:0:0:0:0:0:0:1
    

    代码已托管到我的github,点击访问,对@RequestParam实现原理感兴趣的童鞋可以自己看看源码。

  • 相关阅读:
    正则表达式的贪婪匹配(.*)和非贪婪匹配(.*?)
    jQuery + css 公告从左往右滚动
    C# process 使用方法
    存储过程与SQL的结合使用
    img标签的方方面面
    kibana 5.0.0-alpha5 安装
    es5.0 v5.0.0-alpha 编译安装
    奇怪的hosts文件
    阿里云 api 的文档拼写错误
    centos 7 systemd docker http proxy
  • 原文地址:https://www.cnblogs.com/2YSP/p/10253927.html
Copyright © 2020-2023  润新知