一、背景

平常经常用 @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. snip_opencv环境配置和测试程序

    opencv2.4.9环境变量配置的记录. 2014年8月10日 Microsoft Windows XP [版本 5.1.2600](C) 版权所有 1985-2001 Microsoft Corp ...

  2. C系列语言终极校对宝典【第一、第二部分】

    第一部分:基本概念及其它问答题 1.关键字static的作用是什么? 这个简单的问题很少有人能回答完全.在C语言中,关键字static有三个明显的作用: 1). 在函数体,一个被声明为静态的变量在这一 ...

  3. Hadoop 0.20.2+Ubuntu13.04配置和WordCount測试

    事实上这篇博客写的有些晚了.之前做过一些总结后来学校的事给忘了,这几天想又一次拿来玩玩发现有的东西记不住了.翻博客发现居然没有.好吧,所以赶紧写一份留着自己用吧.这东西网上有非常多,只是也不是全然适用 ...

  4. Reveal查看任意app的高级技巧

    本文转载至 http://blog.csdn.net/wbdwsqwwn/article/details/40476139 Reveal是一个很强大的UI分析工具,与其他几个功能相近的工具(比如Pon ...

  5. (25) java web的struts2框架的使用-基于表单的文件上传

    一,首先创建一个表单页面 <body> <form action="uploads" method="post" enctype=" ...

  6. java 获取项目根目录

    代码入下: request.getSession().getServletContext().getRealPath(); 这里的getRealPath()括号里面可以输入你想得到的具体目录. 需要注 ...

  7. spin_lock、spin_lock_irq、spin_lock_irqsave区别

    void spin_lock(spinlock_t *lock); void spin_lock_irq(spinlock_t *lock); void spin_lock_irqsave(spinl ...

  8. YTU 2429: C语言习题 学生成绩输入和输出

    2429: C语言习题 学生成绩输入和输出 时间限制: 1 Sec  内存限制: 128 MB 提交: 1897  解决: 812 题目描述 编写一个函数print,打印一个学生的成绩数组,该数组中有 ...

  9. 3种方法判断手机浏览器跳转WAP手机网站

    随着移动设备的普及,企业的网络宣传已经不能局限在PC端,而需要同时在移动端有所建树.对于公司网站来说,以前都是做的PC端的,当然手机等移动端也可以访问,但是用户体验肯定不如完全适合的手机端来的方便.我 ...

  10. 网站建设中用JS判断时间并显示不同内容

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...