a_wing啊 2021-10-07 18:50 采纳率: 50%
浏览 328
已结题

在SpringBoot中,Controller的参数中有Map接口类型的,请问他的实现类是什么?

突发奇想,在SpringBoot中,Controller的参数中有Map接口类型的

    @GetMapping("/common")
    public HttpResult testCommonGet(Map<String,String> map){

        return  HttpResult.success("common测试get");
    }

像这里的map,声明是Map接口,那他的实现类是什么?
如果改为HashMap类型,有什么优缺点吗?

  • 写回答

1条回答 默认 最新

  • 大鹏cool Java领域优质创作者 2021-10-07 19:32
    关注

    先说结论,分两种情况。

    情况1:不带注解的 Controller 方法 Map 参数类型,Map 的实现类是 Spring 提供的 BindingAwareModelMap,HashMap 完全可以替换 Map。需要注意的是此时 Map 不是用来接收请求参数的,而是作为 view 中使用的一个 model,用来填充 view ,如将 jsp 页面中的变量替换为具体的值。

    情况2:带 @RequestBody 注解将 Map 作为请求体,Map 的实现类是 LinkedHashMap,HashMap 可以替换 Map。

    情况1分析:Spring Controller 中的方法参数类型多种多样,Spring 调用 Controller 方法时必须保证能够为每个参数提供对应的值,Spring 的解决方案是提供一个通用的接口 HandlerMethodArgumentResolver,不同的参数类型由不同的实现处理。

    HandlerMethodArgumentResolver 接口定义如下。

    public interface HandlerMethodArgumentResolver {
    
        boolean supportsParameter(MethodParameter parameter);
    
        @Nullable
        Object resolveArgument(MethodParameter parameter, @Nullable ModelAndViewContainer mavContainer,
                               NativeWebRequest webRequest, @Nullable WebDataBinderFactory binderFactory) throws Exception;
    
    }
    

    如果 HandlerMethodArgumentResolver 的实现支持给定的参数类型,就会将参数类型解析为值,Spring 解析不带注解的 Map 参数类型使用的是 MapMethodProcessor。源码如下。

    public class MapMethodProcessor implements HandlerMethodArgumentResolver, HandlerMethodReturnValueHandler {
        public MapMethodProcessor() {
        }
    
        public boolean supportsParameter(MethodParameter parameter) {
            return Map.class.isAssignableFrom(parameter.getParameterType()) && parameter.getParameterAnnotations().length == 0;
        }
    
        @Nullable
        public Object resolveArgument(MethodParameter parameter, @Nullable ModelAndViewContainer mavContainer, NativeWebRequest webRequest, @Nullable WebDataBinderFactory binderFactory) throws Exception {
            Assert.state(mavContainer != null, "ModelAndViewContainer is required for model exposure");
            return mavContainer.getModel();
        }
    
        public boolean supportsReturnType(MethodParameter returnType) {
            return Map.class.isAssignableFrom(returnType.getParameterType());
        }
    
        public void handleReturnValue(@Nullable Object returnValue, MethodParameter returnType, ModelAndViewContainer mavContainer, NativeWebRequest webRequest) throws Exception {
            if (returnValue instanceof Map) {
                mavContainer.addAllAttributes((Map)returnValue);
            } else if (returnValue != null) {
                throw new UnsupportedOperationException("Unexpected return type [" + returnType.getParameterType().getName() + "] in method: " + returnType.getMethod());
            }
    
        }
    }
    

    可以看到,只要是 Map 类型参数,Spring 就会调用 ModelAndViewContainer#getModel 获取值,相关源码如下。

    public class ModelAndViewContainer {
        private final ModelMap defaultModel = new BindingAwareModelMap();
    
        public ModelMap getModel() {
            if (this.useDefaultModel()) {
                return this.defaultModel;
            } else {
                if (this.redirectModel == null) {
                    this.redirectModel = new ModelMap();
                }
    
                return this.redirectModel;
            }
        }
    
    }
    

    最终使用的就是 ModelAndViewContainer 内部的 BindingAwareModelMap 实例,这个类实现了 LinkedHashMap,这也意味着如果你使用 TreeMap 作为参数,由于类型不匹配将会导致程序报错。

    情况2分析:带 @RequestBody 的参数,由 RequestResponseBodyMethodProcessor 解析,默认情况下交由 MappingJackson2HttpMessageConverter 实例化参数,如果是 Map 实例化出来的是 HashMap 类型,这块源码内容较多,可自己尝试分析。

    最后如果你对 Spring 实现感兴趣,也可以看我的博客或者和我私聊讨论,有帮助麻烦采纳哦!

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

问题事件

  • 系统已结题 10月17日
  • 已采纳回答 10月9日
  • 修改了问题 10月7日
  • 创建了问题 10月7日

悬赏问题

  • ¥15 python安卓开发
  • ¥15 使用R语言GD包一直不出结果
  • ¥15 计算机微处理器与接口技术相关问题,求解答图片的这个问题,有多少个端口,端口地址和解答问题的方法和思路,不要AI作答
  • ¥15 如何根据一个截图编写对应的HTML代码
  • ¥15 stm32标准库的PID角度环
  • ¥15 ADS已经下载好了,但是DAS下载不了,一直显示这两种情况,有什么办法吗,非常急!
  • ¥100 Excel 点击发送自动跳转outlook邮件
  • ¥15 gis中用栅格计算器或加权总和后图层不显示,值也明显不对
  • ¥15 python使用python-pptx如何给幻灯片添加只读密码。
  • ¥15 深度神经网络传递自变量损失