欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 汽车 > 维修 > spring原理(第十四天)

spring原理(第十四天)

2024/10/25 2:31:10 来源:https://blog.csdn.net/GD2604279407/article/details/141154993  浏览:    关键词:spring原理(第十四天)

参数解析器

  1. 初步了解 RequestMappingHandlerAdapter 的调用过程

    1. 控制器方法被封装为 HandlerMethod

    2. 准备对象绑定与类型转换

    3. 准备 ModelAndViewContainer 用来存储中间 Model 结果

    4. 解析每个参数值

  2. 解析参数依赖的就是各种参数解析器,它们都有两个重要方法

    • supportsParameter 判断是否支持方法参数

    • resolveArgument 解析方法参数

  3. 常见参数的解析

    • @RequestParam

    • 省略 @RequestParam

    • @RequestParam(defaultValue)

    • MultipartFile

    • @PathVariable

    • @RequestHeader

    • @CookieValue

    • @Value

    • HttpServletRequest 等

    • @ModelAttribute

    • 省略 @ModelAttribute

    • @RequestBody

  4. 组合模式在 Spring 中的体现

  5. @RequestParam, @CookieValue 等注解中的参数名、默认值, 都可以写成活的, 即从 ${ } #{ }中获取

 AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(WebConfig.class);DefaultListableBeanFactory beanFactory = context.getDefaultListableBeanFactory();// 准备测试 RequestHttpServletRequest request = mockRequest();// 要点1. 控制器方法被封装为 HandlerMethodHandlerMethod handlerMethod = new HandlerMethod(new Controller(), Controller.class.getMethod("test", String.class, String.class, int.class, String.class, MultipartFile.class, int.class, String.class, String.class, String.class, HttpServletRequest.class, User.class, User.class, User.class));// 要点2. 准备对象绑定与类型转换ServletRequestDataBinderFactory factory = new ServletRequestDataBinderFactory(null, null);// 要点3. 准备 ModelAndViewContainer 用来存储中间 Model 结果ModelAndViewContainer container = new ModelAndViewContainer();// 要点4. 解析每个参数值for (MethodParameter parameter : handlerMethod.getMethodParameters()) {// 多个解析器组合HandlerMethodArgumentResolverComposite composite = new HandlerMethodArgumentResolverComposite();composite.addResolvers(//                                          false 表示必须有 @RequestParamnew RequestParamMethodArgumentResolver(beanFactory, false),new PathVariableMethodArgumentResolver(),new RequestHeaderMethodArgumentResolver(beanFactory),new ServletCookieValueMethodArgumentResolver(beanFactory),new ExpressionValueMethodArgumentResolver(beanFactory),new ServletRequestMethodArgumentResolver(),new ServletModelAttributeMethodProcessor(false), // 必须有 @ModelAttributenew RequestResponseBodyMethodProcessor(List.of(new MappingJackson2HttpMessageConverter())),new ServletModelAttributeMethodProcessor(true), // 省略了 @ModelAttributenew RequestParamMethodArgumentResolver(beanFactory, true) // 省略 @RequestParam);String annotations = Arrays.stream(parameter.getParameterAnnotations()).map(a -> a.annotationType().getSimpleName()).collect(Collectors.joining());String str = annotations.length() > 0 ? " @" + annotations + " " : " ";parameter.initParameterNameDiscovery(new DefaultParameterNameDiscoverer());if (composite.supportsParameter(parameter)) {// 支持此参数Object v = composite.resolveArgument(parameter, container, new ServletWebRequest(request), factory);
//                System.out.println(v.getClass());System.out.println("[" + parameter.getParameterIndex() + "] " + str + parameter.getParameterType().getSimpleName() + " " + parameter.getParameterName() + "->" + v);System.out.println("模型数据为:" + container.getModel());} else {System.out.println("[" + parameter.getParameterIndex() + "] " + str + parameter.getParameterType().getSimpleName() + " " + parameter.getParameterName());}}

参数解析器的先后顺序也有要求,先解析需要带注解的参数,后解析不需要带注解的,不需要带注解的解析器也有顺序,先解析是对象不带注解的,后解析普通参数不带注解的 

参数名的获取

javac命令

  1. 如果编译时添加了 -parameters 可以生成参数表, 反射时就可以拿到参数名
  2. 如果编译时添加了 -g 可以生成调试信息, 但分为两种情况

  • 普通类, 会包含局部变量表, 用 asm 可以拿到参数名
  • 接口, 不会包含局部变量表, 无法获得参数名,这也是 MyBatis 在实现 Mapper 接口时为何要提供 @Param 注解来辅助获得参数名
public static void main(String[] args) throws NoSuchMethodException, ClassNotFoundException {// 1. 反射获取参数名Method foo = Bean2.class.getMethod("foo", String.class, int.class);/*for (Parameter parameter : foo.getParameters()) {System.out.println(parameter.getName());}*/// 2. 基于 LocalVariableTable 本地变量表LocalVariableTableParameterNameDiscoverer discoverer = new LocalVariableTableParameterNameDiscoverer();String[] parameterNames = discoverer.getParameterNames(foo);System.out.println(Arrays.toString(parameterNames));}

spring中组合了这两种方法获取参数,类名:DefaltParameterNameDiscover 

本地变量表的局限性:对于接口里的方法获取不到方法的参数

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com