其他分享
首页 > 其他分享> > spring 20 参数解析器

spring 20 参数解析器

作者:互联网

  1. 初步了解 RequestMappingHandlerAdapter 的调用过程
    1. 控制器方法被封装为 HandlerMethod
    2. 准备对象绑定与类型转换
    3. 准备 ModelAndViewContainer 用来存储中间 Model 结果
    4. 解析每个参数值
点击查看代码
private static void test1() throws NoSuchMethodException {
        //初步了解 RequestMappingHandlerAdapter 的调用过程
        //设置控制器对象
        S20Controller controller = new S20Controller();
        //设置控制器方法,控制器方法被封装为 HandlerMethod 对象
        HandlerMethod method = new HandlerMethod(controller, controller.getClass().getMethod("testParamsResolver", 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));
        //准备对象绑定与参数的类型转换
        for (MethodParameter methodParameter : method.getMethodParameters()) {
            //设置参数名解析
            methodParameter.initParameterNameDiscovery(new DefaultParameterNameDiscoverer());
            Annotation[] parameterAnnotations = methodParameter.getParameterAnnotations();
            String annotation = parameterAnnotations.length > 0 ? Arrays.stream(parameterAnnotations).map(a -> a.annotationType().getSimpleName()).collect(Collectors.joining()) : null;
            System.out.println("[" + methodParameter.getParameterIndex() + "] " + annotation + " " + methodParameter.getParameterType().getSimpleName() + " " + methodParameter.getParameterName());
        }
        //ModelAndViewContainer ,用来存储中间生成的 Model 结果
//        new ModelAndView();
  1. 解析参数依赖的就是各种参数解析器,它们都有两个重要方法
    • supportsParameter 判断是否支持方法参数
    • resolveArgument 解析方法参数
  2. 常见参数的解析
    • @RequestParam
    • 省略 @RequestParam
    • @RequestParam(defaultValue)
点击查看代码
//解析 @RequestParam 注解的参数,增加 context ,为了解析环境变量。${JAVA_HOME}
    private static void test2(AnnotationConfigApplicationContext context, HttpServletRequest request) throws Exception {
        //创建解析 @RequestParam 注解的参数解析器
        RequestParamMethodArgumentResolver requestParamMethodArgumentResolver = new RequestParamMethodArgumentResolver(context.getDefaultListableBeanFactory(),true);
        //设置控制器方法,控制器方法被封装为 HandlerMethod 对象
        HandlerMethod method = new HandlerMethod(new S20Controller(), S20Controller.class.getMethod("testParamsResolver", 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));
        //准备对象绑定与参数的类型转换
        DefaultDataBinderFactory factory = new DefaultDataBinderFactory(null);
        //ModelAndViewContainer ,用来存储中间生成的 Model 结果
        ModelAndViewContainer modelAndViewContainer = new ModelAndViewContainer();

        for (MethodParameter methodParameter : method.getMethodParameters()) {
            //设置解析参数名字解析器
            methodParameter.initParameterNameDiscovery(new DefaultParameterNameDiscoverer());
            //判断是否可以解析此参数
            if (requestParamMethodArgumentResolver.supportsParameter(methodParameter)) {
                //可以,获得解析得到的参数
                Object resolveArgument = requestParamMethodArgumentResolver.resolveArgument(methodParameter, modelAndViewContainer, new ServletWebRequest(request), factory);
                System.out.println(methodParameter.getParameterName() + "参数值是:" + resolveArgument + "类型是:" + resolveArgument.getClass().getSimpleName());
            }

        }
    }
* MultipartFile * @PathVariable * @RequestHeader * @CookieValue * @Value
点击查看代码
 //组合器  将所以参数解析器组合,统一调用
        HandlerMethodArgumentResolverComposite composite = new HandlerMethodArgumentResolverComposite();
        composite.addResolvers(
                //@RequestParam
                requestParamMethodArgumentResolver,
                //@PathVariable
                new PathVariableMethodArgumentResolver(),
                //@RequestHeader
                new RequestHeaderMethodArgumentResolver(context.getDefaultListableBeanFactory()),
                //@CookieValue
                new ServletCookieValueMethodArgumentResolver(context.getDefaultListableBeanFactory()),
                //@Value
                new ExpressionValueMethodArgumentResolver(context.getDefaultListableBeanFactory())
        );
        for (MethodParameter methodParameter : method.getMethodParameters()) {
            //设置解析参数名字解析器
            methodParameter.initParameterNameDiscovery(new DefaultParameterNameDiscoverer());
            //判断是否可以解析此参数
            if (composite.supportsParameter(methodParameter)) {
                //可以,获得解析得到的参数
                Object resolveArgument = composite.resolveArgument(methodParameter, modelAndViewContainer, new ServletWebRequest(request), factory);
                System.out.println(methodParameter.getParameterName() + "参数值是:" + resolveArgument + "类型是:" + resolveArgument.getClass().getSimpleName());
            }
点击查看代码
 private static void test5(AnnotationConfigApplicationContext context, HttpServletRequest request) {
        //设置控制器方法,控制器方法被封装为 HandlerMethod 对象
        HandlerMethod method = new HandlerMethod(new S20Controller(), S20Controller.class.getMethod("testParamsResolver", 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));
        //准备对象绑定与参数的类型转换
        ServletRequestDataBinderFactory factory = new ServletRequestDataBinderFactory(null,null);
        //ModelAndViewContainer ,用来存储中间生成的 Model 结果
        ModelAndViewContainer modelAndViewContainer = new ModelAndViewContainer();
        //组合器  将所以参数解析器组合,统一调用
        HandlerMethodArgumentResolverComposite composite = new HandlerMethodArgumentResolverComposite();
        composite.addResolvers(
                //@RequestParam                                                            false 必须要有 @RequestParam 注解
                new RequestParamMethodArgumentResolver(context.getDefaultListableBeanFactory(), false),
                //@PathVariable
                new PathVariableMethodArgumentResolver(),
                //@RequestHeader
                new RequestHeaderMethodArgumentResolver(context.getDefaultListableBeanFactory()),
                //@CookieValue
                new ServletCookieValueMethodArgumentResolver(context.getDefaultListableBeanFactory()),
                //@Value spring 获取数据  ${} #{}
                new ExpressionValueMethodArgumentResolver(context.getDefaultListableBeanFactory()),
                // request, response, session ...
                new ServletRequestMethodArgumentResolver(),
                // @ModelAttribute
                new ServletModelAttributeMethodProcessor(false),
                // @RequestBody
                new RequestResponseBodyMethodProcessor(Collections.singletonList(new MappingJackson2HttpMessageConverter())),
                // 无 @ModelAttribute 修饰的
                new RequestParamMethodArgumentResolver(context.getDefaultListableBeanFactory(),true),
                //无 @RequestParam 修饰的
                new RequestParamMethodArgumentResolver(context.getDefaultListableBeanFactory(),true)
        );
        for (MethodParameter methodParameter : method.getMethodParameters()) {
            //设置解析参数名字解析器
            methodParameter.initParameterNameDiscovery(new DefaultParameterNameDiscoverer());
            //判断是否可以解析此参数
            if (composite.supportsParameter(methodParameter)) {
                //可以,获得解析得到的参数
                Object resolveArgument = composite.resolveArgument(methodParameter, modelAndViewContainer, new ServletWebRequest(request), factory);
                System.out.println(methodParameter.getParameterName() + "参数值是:" + resolveArgument + "类型是:" + resolveArgument.getClass().getSimpleName());
                //模型数据
                System.out.println(modelAndViewContainer.getModel());
            }

        }
    }
  1. 组合模式在 Spring 中的体现
  2. @RequestParam, @CookieValue 等注解中的参数名、默认值, 都可以写成活的, 即从 ${ } #{ }中获取
  3. 此处 @RequestBody 解析 类型转换报错 java.lang.IllegalArgumentException: not support type

标签:解析器,context,20,String,spring,methodParameter,resolveArgument,new,class
来源: https://www.cnblogs.com/xy7112/p/16436066.html