Spring的Model 和 Map的原理源码解析

Model 和 Map

为什么在Model和Map中放值传入后会出现在request的上面。

9.1、源码解析

准备测试代码

@GetMapping("/goto")
public String go(HttpServletRequest request,
                 Map<String,Object> map,
                 Model model){
    request.setAttribute("msg","传过来....");
    map.put("map","map hello word!!");
    model.addAttribute("model","model hello word!!");
    return "forward:success";
}
@ResponseBody
@GetMapping("/success")
public Map success(@RequestAttribute(value = "msg",required = false) String msg,
                   HttpServletRequest request){
    Map<String,Object> hashMap = new HashMap<>();
    Object msg1 = request.getAttribute("msg");
    Object map = request.getAttribute("map");
    Object model = request.getAttribute("model");
    hashMap.put("map1",map);
    hashMap.put("model",model);
    hashMap.put("msg1",msg1);
    return hashMap;
}

第一步进入DispatchServlet 的 doDispatch中

主要的三步

DispatchServlet类中的
    doDispatch方法
        // Determine handler for the current request.
        mappedHandler = getHandler(processedRequest);//获取反射的方法处理器
        // Determine handler adapter for the current request.
		//获取参数处理器
        HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());
		// Actually invoke the handler.
		//反射执行方法和解析Model和Map
		mv = ha.handle(processedRequest, response, 	mappedHandler.getHandler());

在获取参数阶段,解Model和Map

  1. 获取Map 的 处理器器 MapMethodProcessor
  2. 处理Map这个参数
MapMethodProcessor类中的
@Override
@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();
}

然后进入ModelAndViewContainer类中的
    private final ModelMap defaultModel = new BindingAwareModelMap();
    public ModelMap getModel() {
    if (useDefaultModel()) {
        return this.defaultModel;//获取ModelMap
    }
    ......
  • 把这个ModelMap对象返回
  • 获取Model的 处理器器 ModelMethodProcessor
  • 处理Model这个参数
ModelMethodProcessor类中的
@Override
@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();
}
然后进入ModelAndViewContainer类中的
    private final ModelMap defaultModel = new BindingAwareModelMap();
    public ModelMap getModel() {
    if (useDefaultModel()) {
        return this.defaultModel;//获取ModelMap   这个和那个Map获取的是同一个
    }
    ......

把同一个ModelMap对象返回

反射调用方法

由于是同一个对象所有 map 和 model中的值都样,所以往map和Model放值都一样

把model和map的数据放入request

第一步

ServletInvocableHandlerMethod类中
    invokeAndHandle方法
    	//获取返回值的一个处理器
        try {
            this.returnValueHandlers.handleReturnValue(
                returnValue, getReturnValueType(returnValue),
                mavContainer, webRequest);
        }
HandlerMethodReturnValueHandlerComposite类中的
    HandlerMethodReturnValueHandler方法 进行获取

这里获取的ViewNameMethodReturnValueHandler这个处理器

第二步

把Map和 Model携带的参数和返回值(路径)进行整合为ModelAndView

RequestMappingHandlerAdapter类中
    handleInternal方法
    		...
    		ModelAndView mav;
			...
			mav = invokeHandlerMethod(request, response, handlerMethod);
			...

第三步

准备派发和放入参数

DispatchServlet类中的
    doDispatch方法
    	render(mv, request, response);
		view.render(mv.getModelInternal(), request, response);

AbstractView类中的
    render方法
    	//把BindingAwareModelMap的参数封装为Map
    	Map<String, Object> mergedModel = createMergedOutputModel(model,
                                                              request, response);
		prepareResponse(request, response);
		//准备方法和放入参数到reques中
		renderMergedOutputModel(mergedModel, getRequestToExpose(request),
                                							response);
InternalResourceView类中的
    renderMergedOutputModel
    	// Expose the model object as request attributes.
		exposeModelAsRequestAttributes(model, request);//把参数放入到request中
AbstractView类中的
    //把参数放入到原生的request域中
    protected void exposeModelAsRequestAttributes(Map<String, Object> model,
                                                  HttpServletRequest request) 														throws Exception {
        model.forEach((name, value) -> {
            if (value != null) {
                request.setAttribute(name, value);
            }
            else {
                request.removeAttribute(name);
            }
        });
}

到此这篇关于Spring的Model 和 Map的原理源码解析的文章就介绍到这了,更多相关Spring Model 和 Map内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • springBoot controller,service,dao,mapper,model层的作用说明

    目录 零.业务逻辑 一.Dao(Data Access Object):数据存储对象 二.Service:服务 三.Controller:控制器 四.model:模型 五.View层 六.它们之间的关系 DAO层.Service层和Controller层的区别 1.dao层:数据访问层 2.service层:服务层 3.controller层 关系 零.业务逻辑 Controller-->service接口-->serviceImpl-->dao接口-->daoImpl-->

  • jsp 显示springmvc modelmap传递的对象详细介绍

    jsp 显示springmvc modelmap传递的对象 最近在做一个小网站,功能非常基础,决定用springmvc搭建. 遇到一个问题,在controller向前端传值时,比如使用ModelMap传了一个字符串,modelmap.addattribute("msg", "hello"),那么在jsp端,直接使用${msg}就可以显示.接着,如果我传递了一个对象,依然可以使用${obj.name}这样的方法来显示该对象的各个属性.然而更多情况下,都需要显示列表,所

  • Spring的Model 和 Map的原理源码解析

    Model 和 Map 为什么在Model和Map中放值传入后会出现在request的上面. 9.1.源码解析 准备测试代码 @GetMapping("/goto") public String go(HttpServletRequest request, Map<String,Object> map, Model model){ request.setAttribute("msg","传过来...."); map.put("

  • MyBatis框架底层的执行原理源码解析

    目录 1.前言 2.案例项目源码 3.MyBatis源码解析底层执行原理 3.1 读取mybatis配置文件创建出SqlSeesionFactory对象 3.2 通过SqlSeesionFactory对象进而创建出SqlSession对象 3.3 通过SqlSession的getMapper获取到接口代理对象 3.4 通过mapper接口的代理对象执行CRUD 1.前言 MyBatis框架大家肯定都用过的,废话我就不再多说了,这篇文章就给大家分享一下有关MyBatis框架底层的执行原理吧(Deb

  • React Hydrate原理源码解析

    目录 引言 Demo ReactDOM.render ReactDOM.hydrate hydrate 过程 事件绑定 hydrate 源码剖析 beginWork HostRoot Fiber HostComponent HostText Fiber tryToClaimNextHydratableInstance completeUnitOfWork popHydrationState prepareToHydrateHostInstance prepareToHydrateHostText

  • go slice 扩容实现原理源码解析

    目录 正文 扩容的示例 实际扩容倍数 growslice 实现 growslice 实现步骤 growslice 源码剖析 总结 正文 基于 Go 1.19. go 的切片我们都知道可以自动地进行扩容,具体来说就是在切片的容量容纳不下新的元素的时候, 底层会帮我们为切片的底层数组分配更大的内存空间,然后把旧的切片的底层数组指针指向新的内存中: 目前网上一些关于扩容倍数的文章都是基于相对旧版本的 Go 的,新版本中,现在切片扩容的时候并不是那种准确的小于多少容量的时候就 2 倍扩容, 大于多少容量

  • axios拦截器工作方式及原理源码解析

    目录 axios 拦截器的配置方式 use() 方法的定义 拦截器如何执行 拦截器回调方法的添加顺序 同步执行请求拦截器(顺序执行) 异步执行请求拦截器(同时执行) Q&A 拦截器是如何工作的 拦截器的执行顺序 同步&异步 axios 拦截器的配置方式 本文所用 axios 版本号为:1.3.2. axios 中有两种拦截器: axios.interceptors.request.use(onFulfilled, onRejected, options):配置请求拦截器. onFulfil

  • async-validator实现原理源码解析

    目录 async-validator 介绍 async-validator 基本使用 async-validator 源码分析 async-validator 源码-构造函数 async-validator 源码-validate方法 async-validator 源码-register方法 总结 最后 async-validator 介绍 async-validator是异步的验证数据是否合法有效的工具, 内置了不同数据类型的常见验证规则. 在需要对数据进行验证的场景中,都可以考虑使用asy

  • spring-session简介及实现原理源码分析

    一:spring-session介绍 1.简介 session一直都是我们做集群时需要解决的一个难题,过去我们可以从serlvet容器上解决,比如开源servlet容器-tomcat提供的tomcat-redis-session-manager.memcached-session-manager. 或者通过nginx之类的负载均衡做ip_hash,路由到特定的服务器上.. 但是这两种办法都存在弊端. spring-session是spring旗下的一个项目,把servlet容器实现的httpSe

  • python装饰器原理源码示例分析

    目录 前言 一.什么是装饰器 二.为什么要用装饰器 三.简单的装饰器 四.装饰器的语法糖 五.装饰器传参 六.带参数的装饰器 七.类装饰器 八.带参数的类装饰器 九.装饰器的顺序 前言 最近有人问我装饰器是什么,我就跟他说,其实就是装饰器就是类似于女孩子的发卡.你喜欢的一个女孩子,她可以有很多个发卡,而当她戴上不同的发卡,她的头顶上就是装饰了不同的发卡.但是你喜欢的女孩子还是你喜欢的女孩子.如果还觉得不理解的话,装饰器就是咱们的手机壳,你尽管套上了手机壳,但并不影响你的手机功能,可你的手机还是该

  • Vue解读之响应式原理源码剖析

    目录 初始化 initState() initProps() initData() observe() Observer defineReactive() 依赖收集 Dep Watcher 依赖收集过程 移除订阅 派发更新 notify() update() queueWatcher() flushSchedulerQueue() updated() defineProperty 缺陷及处理 Vue.set() 重写数组方法 总结 先看张图,了解一下大体流程和要做的事 初始化 在 new Vue

  • Vue watch原理源码层深入讲解

    目录 添加依赖 触发依赖 总结 由于我在从源码看vue(v2.7.10)的computed的实现原理中详细的讲解过computed的实现,本篇跟computed的原理类似.我就带大家简单分析一下. 添加依赖 代码如下: <template> <div> {{a}} <button @click="addModule">新增</button> </div> </template> <script> exp

随机推荐