一、背景

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

二、分析

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

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

分别是类RequestParamMethodArgumentResolver和RequestParamMapMethodArgumentResolver


类关系图

RequestParamMethodArgumentResolver

可以看到两个类都最终实现了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. String name() default "ip"; 


  10. boolean required() default true; 


  11. 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. @Nullable 

  10. @Override 

  11. protected Object resolveName(String name, MethodParameter parameter, NativeWebRequest request) throws Exception { 

  12. HttpServletRequest servletRequest = request.getNativeRequest(HttpServletRequest.class); 

  13. String ip = servletRequest.getRemoteAddr(); 

  14. return ip == null ? "127.0.0.1":ip; 




  15. @Override 

  16. public boolean supportsParameter(MethodParameter parameter) { 

  17. return parameter.hasParameterAnnotation(IP.class) && !Map.class.isAssignableFrom(parameter.nestedIfOptional().getNestedParameterType()); 




  18. private static class RequestIPNamedValueInfo extends NamedValueInfo{ 


  19. private RequestIPNamedValueInfo(IP annotation) { 

  20. super(annotation.name(), annotation.required(), annotation.defaultValue()); 








这三个方法是必须实现的,还有一个可选重写的handleMissingValue。

3.添加配置

  1. @Configuration 

  2. @EnableWebMvc 

  3. public class MvcConfig implements WebMvcConfigurer { 



  4. @Override 

  5. public void addArgumentResolvers(List<HandlerMethodArgumentResolver> resolvers) { 

  6. resolvers.add(new IPAddressArgumentResolver()); 





4.controller

  1. @Slf4j 

  2. @RestController 

  3. public class VOTestController { 


  4. @GetMapping("vo/test") 

  5. public BaseVo test(@IP String ip){ 


  6. log.info("请求的ip地址为:{}",ip); 

  7. BaseVo baseVo = new BaseVo(); 

  8. //设置为Null 

  9. baseVo.setResult(null); 

  10. 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实现原理感兴趣的童鞋可以自己看看源码。

SpringBoot自定义参数解析器的更多相关文章

  1. SpringBoot系列教程web篇之如何自定义参数解析器

    title: 190831-SpringBoot系列教程web篇之如何自定义参数解析器 banner: /spring-blog/imgs/190831/logo.jpg tags: 请求参数 cat ...

  2. springmvc 源码分析(三) -- 自定义处理器映射器和自定义处理器适配器,以及自定义参数解析器 和错误跳转自定页面

    测试环境搭建: 本次搭建是基于springboot来实现的,代码在码云的链接:https://gitee.com/yangxioahui/thymeleaf.git DispatcherServlet ...

  3. SpringMVC 自定义参数解析器.

    一.简述 有没有想过像 @RequestParam.@RequestBody 这些注解的工作原理呢?为什么 form 表单.application/json 的参数能够直接封装进 Bean 对象中呢? ...

  4. Spring自定义参数解析器

    结合redis编写User自定义参数解析器UserArgumentResolver import javax.servlet.http.Cookie; import javax.servlet.htt ...

  5. SpringMVC自动封装List对象 —— 自定义参数解析器

    前台传递的参数为集合对象时,后台Controller希望用一个List集合接收数据. 原生SpringMVC是不支持,Controller参数定义为List类型时,接收参数会报如下错误: org.sp ...

  6. SpringBoot自定义参数验证器

    前要 之前我们介绍了JSR-303验证方式,十分的方便Spring都帮我们封装好了,但是对一些复杂的验证,还是需要更加灵活的验证器的. JSR-303验证器传送门:https://www.jiansh ...

  7. 自定义springmvc参数解析器

    实现spring HandlerMethodArgumentResolver接口 通过使用@JsonArg自定义注解来解析json数据(通过fastjson的jsonPath),支持多个参数(@Req ...

  8. 一步一步自定义SpringMVC参数解析器

    随心所欲,自定义参数解析器绑定数据. 题图:from Zoommy 干货 SpringMVC解析器用于解析request请求参数并绑定数据到Controller的入参上. 自定义一个参数解析器需要实现 ...

  9. 自定义HandlerMethodArgumentResolver参数解析器和源码分析

    在初学springmvc框架时,我就一直有一个疑问,为什么controller方法上竟然可以放这么多的参数,而且都能得到想要的对象,比如HttpServletRequest或HttpServletRe ...

随机推荐

  1. UVA 11246 - K-Multiple Free set(数论推理)

    UVA 11246 - K-Multiple Free set 题目链接 题意:一个{1..n}的集合.求一个子集合.使得元素个数最多,而且不存在有两个元素x1 * k = x2,求出最多的元素个数是 ...

  2. Android自己定义圆角ImageView

    我们常常看到一些app中能够显示圆角图片.比方qq的联系人图标等等,实现圆角图片一种办法是直接使用圆角图片资源,当然假设没有圆角图片资源.我们也能够自己通过程序实现的,以下介绍一个自己定义圆角Imag ...

  3. 用WaveX实现音频文件的录音

    原文地址:https://blog.csdn.net/gongluck93/article/details/53096013 1.WaveInOpen waveInOpen MMRESULT wave ...

  4. ERROR: cannot start Android Studio. No JDK found. Please validate either ANDROID_STUDIO_JDK, JDK_HOME + Unrecognized VM option '+UseCodeCacheFlushing

    想学下android,在本来想用myeclipse安装下sdk和adt,谁知在官网看到http://developer.android.com/sdk/index.html Google I/O 20 ...

  5. spring cloud config 属性加解密

    首先需要(Java Cryptography Extension (JCE))的支持,下载路径: https://www.oracle.com/technetwork/java/javase/down ...

  6. css3中animation的应用

    1.css3 的相关属性: 相关代码: div { animation-name: myfirst; //动画的名称 animation-duration: 5s; //动画一个周期需要5秒 anim ...

  7. linux下lk和kernel层通信方式[2]

    U-Boot与Linux内核的交互 说明:本文所使用的U-Boot的版本是1.1.6,平台是S3C2440. 目录 一.简介 1.1标记列表二.设置标记存放的地址 2.1相关的结构体定义 2.2标记存 ...

  8. SideBar---fixed定位

      <style> /*外层fixed*/ body{ width:2000px; height:2000px; background:#000; } .wrap { position: ...

  9. CodeForces242D:Connected Components (不错的并查集)

    We already know of the large corporation where Polycarpus works as a system administrator. The compu ...

  10. [Selenium] Android HTML5 中 Application Cache

    HTML5 中引入了 Application Cache,这意味着 Web 应用程序可以被缓存到本地,且可在没有网络的情况下也能访问该 Web 应用程序 Application Cache 在以下3个 ...