一、背景
平常经常用 @RequestParam注解来获取参数,然后想到我能不能写个自己注解获取请求的ip地址呢?就像这样 @IP String ip
二、分析
于是开始分析 @RequestParam是如何实现的。
从@RequestParam注解开始入手,搜索该注解在源码中使用的地方
分别是类RequestParamMethodArgumentResolver和RequestParamMapMethodArgumentResolver
可以看到两个类都最终实现了HandlerMethodArgumentResolver这个接口。
里面就两个方法,supportsParameter方法是检测该参数是否支持这个参数解析器,
如果supportsParameter方法返回true,则调用resolveArgument来进行参数解析工作。
三、代码编写
现在就可以写自己的参数解析器了,但是推荐继承AbstractNamedValueMethodArgumentResolver而不是直接实现HandlerMethodArgumentResolver接口。
1.注解@IP
@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
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
还没有评论,来说两句吧...