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

在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日

悬赏问题

  • ¥100 嵌入式系统基于PIC16F882和热敏电阻的数字温度计
  • ¥15 cmd cl 0x000007b
  • ¥20 BAPI_PR_CHANGE how to add account assignment information for service line
  • ¥500 火焰左右视图、视差(基于双目相机)
  • ¥100 set_link_state
  • ¥15 虚幻5 UE美术毛发渲染
  • ¥15 CVRP 图论 物流运输优化
  • ¥15 Tableau online 嵌入ppt失败
  • ¥100 支付宝网页转账系统不识别账号
  • ¥15 基于单片机的靶位控制系统