SpringBoot自定义参数解析器
一、背景
平常经常用 @RequestParam注解来获取参数,然后想到我能不能写个自己注解获取请求的ip地址呢?就像这样 @IP String ip
二、分析
于是开始分析 @RequestParam是如何实现的。
从@RequestParam注解开始入手,搜索该注解在源码中使用的地方
分别是类RequestParamMethodArgumentResolver和RequestParamMapMethodArgumentResolver


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

里面就两个方法,supportsParameter方法是检测该参数是否支持这个参数解析器,
如果supportsParameter方法返回true,则调用resolveArgument来进行参数解析工作。
三、代码编写
现在就可以写自己的参数解析器了,但是推荐继承AbstractNamedValueMethodArgumentResolver而不是直接实现HandlerMethodArgumentResolver接口。
1.注解@IP
- /**
- * 获取参数
- * Created by 2YSP on 2019/1/6.
- */
- @Documented
- @Retention(value = RetentionPolicy.RUNTIME)
- @Target(ElementType.PARAMETER)
- public @interface IP {
- String name() default "ip";
- boolean required() default true;
- String defaultValue() default "0";
- }
2.参数解析器IPAddressArgumentResolver
- /**
- * Created by 2YSP on 2019/1/6.
- */
- public class IPAddressArgumentResolver extends AbstractNamedValueMethodArgumentResolver {
- @Override
- protected NamedValueInfo createNamedValueInfo(MethodParameter parameter) {
- IP annotation = parameter.getParameterAnnotation(IP.class);
- return new IPAddressArgumentResolver.RequestIPNamedValueInfo(annotation);
- }
- @Nullable
- @Override
- protected Object resolveName(String name, MethodParameter parameter, NativeWebRequest request) throws Exception {
- HttpServletRequest servletRequest = request.getNativeRequest(HttpServletRequest.class);
- String ip = servletRequest.getRemoteAddr();
- return ip == null ? "127.0.0.1":ip;
- }
- @Override
- public boolean supportsParameter(MethodParameter parameter) {
- return parameter.hasParameterAnnotation(IP.class) && !Map.class.isAssignableFrom(parameter.nestedIfOptional().getNestedParameterType());
- }
- private static class RequestIPNamedValueInfo extends NamedValueInfo{
- private RequestIPNamedValueInfo(IP annotation) {
- super(annotation.name(), annotation.required(), annotation.defaultValue());
- }
- }
- }
这三个方法是必须实现的,还有一个可选重写的handleMissingValue。
3.添加配置
- @Configuration
- @EnableWebMvc
- public class MvcConfig implements WebMvcConfigurer {
- @Override
- public void addArgumentResolvers(List<HandlerMethodArgumentResolver> resolvers) {
- resolvers.add(new IPAddressArgumentResolver());
- }
- }
4.controller
- @Slf4j
- @RestController
- public class VOTestController {
- @GetMapping("vo/test")
- public BaseVo test(@IP String ip){
- log.info("请求的ip地址为:{}",ip);
- BaseVo baseVo = new BaseVo();
- //设置为Null
- baseVo.setResult(null);
- 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自定义参数解析器的更多相关文章
- SpringBoot系列教程web篇之如何自定义参数解析器
title: 190831-SpringBoot系列教程web篇之如何自定义参数解析器 banner: /spring-blog/imgs/190831/logo.jpg tags: 请求参数 cat ...
- springmvc 源码分析(三) -- 自定义处理器映射器和自定义处理器适配器,以及自定义参数解析器 和错误跳转自定页面
测试环境搭建: 本次搭建是基于springboot来实现的,代码在码云的链接:https://gitee.com/yangxioahui/thymeleaf.git DispatcherServlet ...
- SpringMVC 自定义参数解析器.
一.简述 有没有想过像 @RequestParam.@RequestBody 这些注解的工作原理呢?为什么 form 表单.application/json 的参数能够直接封装进 Bean 对象中呢? ...
- Spring自定义参数解析器
结合redis编写User自定义参数解析器UserArgumentResolver import javax.servlet.http.Cookie; import javax.servlet.htt ...
- SpringMVC自动封装List对象 —— 自定义参数解析器
前台传递的参数为集合对象时,后台Controller希望用一个List集合接收数据. 原生SpringMVC是不支持,Controller参数定义为List类型时,接收参数会报如下错误: org.sp ...
- SpringBoot自定义参数验证器
前要 之前我们介绍了JSR-303验证方式,十分的方便Spring都帮我们封装好了,但是对一些复杂的验证,还是需要更加灵活的验证器的. JSR-303验证器传送门:https://www.jiansh ...
- 自定义springmvc参数解析器
实现spring HandlerMethodArgumentResolver接口 通过使用@JsonArg自定义注解来解析json数据(通过fastjson的jsonPath),支持多个参数(@Req ...
- 一步一步自定义SpringMVC参数解析器
随心所欲,自定义参数解析器绑定数据. 题图:from Zoommy 干货 SpringMVC解析器用于解析request请求参数并绑定数据到Controller的入参上. 自定义一个参数解析器需要实现 ...
- 自定义HandlerMethodArgumentResolver参数解析器和源码分析
在初学springmvc框架时,我就一直有一个疑问,为什么controller方法上竟然可以放这么多的参数,而且都能得到想要的对象,比如HttpServletRequest或HttpServletRe ...
随机推荐
- iOS应用崩溃日志分析 iOS应用崩溃日志揭秘
转自:http://www.raywenderlich.com/zh-hans/30818/ios%E5%BA%94%E7%94%A8%E5%B4%A9%E6%BA%83%E6%97%A5%E5%BF ...
- 不是技术牛人,如何拿到国内IT巨头的Offer--转
http://blog.csdn.net/lsldd/article/details/13506263 不久前,byvoid面阿里星计划的面试结果截图泄漏,引起无数IT屌丝的羡慕敬仰.看看这些牛人,N ...
- 中科燕园GIS外包---交通运输综合地理信息平台
集地图.服务.应用于一身交通运输综合性的GIS门户 交通运输综合地理信息平台,是集地图.服务.应用于一身交通运输综合性的GIS门户.无需复杂的设置和部署,就可以高速创建交互式地图和应用程序,并 ...
- 使用JavaScript获取浏览器Chrome版本信息
Navigator对象包含了有关浏览器的信息 可通过访问其属性appVersion或userAgent来获取浏览器Chrome版本 例如,我所使用的QQ浏览器的appVersion和userAgent ...
- Java中的final具体解释以及用途实战
浅析Java中的finalkeyword 谈到finalkeyword,想必非常多人都不陌生.在使用匿名内部类的时候可能会经经常使用到finalkeyword. 另外.Java中的String类就是一 ...
- Model drivern
<s:hidden name="id" value="%{role.id}"></s:hidden> 其中的value传到后台是有类型的 ...
- golang基础-WaitGroup、kafka消费者
kafka消费者 以下博客是通过生产者创建.发送消息至kafka 博客链接 现在我们站在消费者的角度,来进行收取消息 package main import ( "fmt" &qu ...
- js中数组遍历的几种方法及其区别
参考网站: http://www.cnblogs.com/lvmh/p/6104397.html 第一种最常用的:for循环 for(j = 0; j < arr.length; j++) { ...
- java 开发面试题小整理(二)
51.Anonymous Inner Class(匿名内部类)是否可以继承其它类?是否可以实现接口? 答:可以继承其他类或实现其他接口,在Swing编程和Android开发中常用此方式来实现事件监听和 ...
- 书写优雅的shell脚本(四) - kill命令的合理使用
Linux中的kill命令用来终止指定的进程(terminate a process)的运行,是Linux下进程管理的常用命令.通常,终止一个前台进程可以使用Ctrl+C键,但是,对于一个后台进程就须 ...