微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

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. 解析参数依赖的就是各种参数解析器,它们都有两个重要方法
  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

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。

相关推荐