演示
自定义@Ip注解,获取请求的ip
原理
DispatcherServlet初始化的时候会初始组件RequestMappingHandlerMapping与RequestMappingHandlerAdapter
1、RequestMappingHandlerMapping组件
RequestMappingHandlerMapping 初始化时,会收集所有 @RequestMapping 映射信息,封装为 Map,其中
key 是 RequestMappingInfo 类型,包括请求路径、请求方法等信息
value 是 HandlerMethod 类型,包括控制器方法对象、控制器对象
有了这个 Map,就可以在请求到达时,快速完成映射,找到 HandlerMethod 并与匹配的拦截器一起返回给 DispatcherServlet
2、RequestMappingHandlerAdapter组件
RequestMappingHandlerAdapter 初始化时,会准备 HandlerMethod 调用时需要的各个组件,如:
HandlerMethodArgumentResolver 解析控制器方法参数
HandlerMethodReturnValueHandler 处理控制器方法返回值
RequestMappingHandlerAdapter组件就是调用映射方法的,也就是上面的test01,调用方法前自然要解析参数,自然就有解析参数的组件–>HandlerMethodArgumentResolver 解析控制器方法参数
步骤
1、定义注解
/* * 功能:获取请求时的ip * */ @Target(ElementType.PARAMETER)//作用范围(方法) @Retention(RetentionPolicy.RUNTIME)//作用时间(运行时) public @interface Ip { }
2、自定义参数解析器
实现HandlerMethodArgumentResolver接口
public class IpArgumentResolver implements HandlerMethodArgumentResolver { // 这个方法是否标有这个注解 @Override public boolean supportsParameter(MethodParameter methodParameter) { Ip ip = methodParameter.getParameterAnnotation(Ip.class); return ip != null; } //具体业务操作,获取HttpServletRequest请求,获取ip并返回 @Override public Object resolveArgument(MethodParameter methodParameter, ModelAndViewContainer modelAndViewContainer, NativeWebRequest nativeWebRequest, WebDataBinderFactory webDataBinderFactory) throws Exception { HttpServletRequest request = nativeWebRequest.getNativeRequest(HttpServletRequest.class); String remoteAddr = request.getRemoteAddr(); return remoteAddr; } }
3、将自定义的参数解析器注册进容器
RequestMappingHandlerAdapter调用映射方法的时候会初始化
HandlerMethodArgumentResolver也就是我们自定义的参数解析器与一些它自己的参数解析器到时候就会解析@Ip注解了
@Configuration public class MyConfig implements WebMvcConfigurer { @Override public void addArgumentResolvers(List<HandlerMethodArgumentResolver> resolvers) { resolvers.add(new IpArgumentResolver()); } }