ServletAPI 2-10复杂参数, 解析完的参数值都会放到 ModelAndViewContainer里面

news2024/11/15 17:36:07

总结:

找到解析器后,用解析器去解析参数,都使用了resolveArgument()中以下方法

mavContainer.getModel();

mavContainer:模型和视图容器

视图:页面请求要返回一个地方,这个地方的地址叫视图 。比如要到/sucess

模型:携带的数据称为模型

复杂参数

   Map Model  :会被放在request请求域中,相当于调用了request.setAttribute

  Errors/BindingRequest

RedirectAttributes   重定向携带数据

 ServletResponse

SessionStatus UriComponentBuilder 

ServletComponentBuilder

转发生效前提

    return  "forward:/success2";

该类必须标注  @Controller  而不是@RestController,标准后者只会输出原文

方法注解参数设定非必须

  value="msg2",required = false

@ResponseBody
@GetMapping("/success2")
public Map success2(@RequestAttribute(value="msg2",required = false) String msg2,
                    @RequestAttribute(value="code",required = false) Integer code,
                    HttpServletRequest request

                    ){

 给Request域中放数据 map   model  request   response

TestFuza(Map<String,Object> map,
                           Model model,
                           HttpServletRequest request,
                           HttpServletResponse response
                           )

@Controller
public class FuzaController {

@GetMapping("/fuza")
    public String TestFuza(Map<String,Object> map,
                           Model model,
                           HttpServletRequest request,
                           HttpServletResponse response
                           ) {
    map.put("hello","1234567");
   model.addAttribute("city","苏州");
   request.setAttribute("province","广东");
    Cookie cookie=new Cookie("cookie1","shanghai");
    cookie.setDomain("localhost");
   response.addCookie(cookie);
     return  "forward:/success2";

    }

    @ResponseBody
    @GetMapping("/success2")
    public Map success2(@RequestAttribute(value="msg2",required = false) String msg2,
                        @RequestAttribute(value="code",required = false) Integer code,
                        HttpServletRequest request

                        ){

    Object msg1=request.getAttribute("msg");
    Map<String,Object> map=new HashMap<>();
    Object hello=request.getAttribute("hello");
    Object city=request.getAttribute("city");
   Object province=request.getAttribute("province");
   map.put("请求注解",msg1);
   map.put("annotion注解2",msg2);
   map.put("hello",hello);
   map.put("city",city);
   map.put("province",province);
      return map;
    }
}

原理分析1-到获取所有4个请求参数值

Cookie cookie=new Cookie("cookie1","shanghai");设置断点,请求后

我们企图给浏览器设置cookie

 浏览器中就会保存这个cookie

 进入断点

一路到

 stepinto

 stepinto

 循环27个解析器

可以看到parameter里面包含请求的4个参数: Map,Model,

 也就是方法张的参数

public String TestFuza(Map<String,Object> map,
                       Model model,
                       HttpServletRequest request,
                       HttpServletResponse response
                       ) 

可以看到当前Receiver,进入下一循环

 因为第一个参数是map,所以一直到  MapMethodProcessor

进入,会查看当前请求参数是否为Map

放行到去解析

 进入

 放行到

 进入

 其中有mavContainer,全称 ModelAndViewContainer去getModel

 ctrl进入ModelAndViewContainer,看到defaultModel

private final ModelMap defaultModel = new BindingAwareModelMap();

下面还有ModelMap getModel(),返回 defaultModel

 也可以在本类中ctl+f12查看方法

 

 其中有一句

private final ModelMap defaultModel = new BindingAwareModelMap();

ctrl进入类 BindingAwareModelMap

ctrl进入父类 ExtendedModelMap

public class ExtendedModelMap extends ModelMap implements Model {

可以看出ExtendedModelMap 既是ModelMap 又是Model

一路返回

,这样就获取了第一个参数 

 第二个参数解析

第二个参数编号1,就是model

stepinto

 stepinto

stepinto进入遍历Resolvers

 一直循环到ModelMethodParameter

 stepinto,可以看到参数类型是Model即可支持

继续放行

 stepinto

在如下位置stepinto

可以看到调的是与解析参数0一样的方法    mavContainer.getModel();

 放行到

 发现已经获得的两个参数类型都是@7059,代表他们是同一个对象

 放行到获取全部参数

 

-------------------------------以上获取了全部4个参数---------------------------------------------------- 

原理分析2-

放行到

可以在controller里面打一个断点

 这样放行几步就会先来到上面controller文件

继续放行几步

 放行到发现returnValue已经获取  是 forward:/success2

 查看其mavContainer参数得到的default model

 如何将上文defaultmodel中的两个值放到请求域中

在如下位置this.setResponseStatus(webRequest);进入

 进入之后

 

    放行到this.returnValueHandlers.handleReturnValue

 

 其传入参数中包含了 mavContainer

,这是处理返回结果,controller里面返回结果是个string),

 stepinto   this.returnValueHandlers.handleReturnValue(returnValue, this.getReturnValueType(returnValue), mavContainer, webRequest); 获取返回结果类型

放行返回

   

再次 step into,进入handleReturnValue 方法,找到返回值处理器selectHandler

 

 放行到本方法下面一句 

handler.handleReturnValue(returnValue, returnType, mavContainer, webRequest);

 看到这个

 可以看出把返回值变成字符串放到了mavContainer

视图是要求的网址,模型是携带的数据

returnValue是forward:/success2  
public void handleReturnValue(@Nullable Object returnValue, MethodParameter returnType, ModelAndViewContainer mavContainer, NativeWebRequest webRequest) throws Exception {
        if (returnValue instanceof CharSequence) {
            String viewName = returnValue.toString();
            mavContainer.setViewName(viewName);
            if (this.isRedirectViewName(viewName)) {
                mavContainer.setRedirectModelScenario(true);
            }

现在mavContainer包含了 view和 default model

 继续放行,辛苦啊,终于找到   getModelAndView这个方法所在位置

 

 进入,注意这一句modelFactory.updateModel(webRequest, mavContainer);

从此之后都是modelFactory执行 更新Model,可以进入研究

 继续放行,回到DispatcherServlet

 放行到mappedHandler.applyPostHandle(processedRequest, response, mv);

它是mv = ha.handle()获取完参数并放到mavcontainer中之后怎么办的方法,进入

放行到

 

 一路放行到

this.processDispatchResult(processedRequest, response, mappedHandler, mv, (Exception)dispatchException);

 

 Step3  处理派发结果,就是要去哪些页面

this.processDispatchResult(processedRequest, response, mappedHandler, mv, (Exception)dispatchException);

stepinto 

 继续放行到,注意这里mv的值,mv是对model and view的再次封装

ModelAndView [view="forward:/success2"; model={hello=1234567, city=苏州}]

 放行

进入render()

 其中有拿到视图名 String viewName = mv.getViewName();

放行到

对  mv.getModelInternal() 评估一下

 

Stepinto   view = this.resolveViewName(viewName, mv.getModelInternal(), locale, request);

来到了视图解析器流程,了解即可

 继续放行进入  view.render(mv.getModelInternal(), request, response);

 渲染要去的页面

stepinto

 放行到核心    创建要去的页面   createMergedOutputModel

Map<String, Object> mergedModel = this.createMergedOutputModel(model, request, response);

 stepinto 

 放行到

mergedModel.putAll(this.staticAttributes);此时创建了mergedModel

 放行到,如果model不为空,那么就都放入 mergedModel

继续放行,返回mergedModel

 

放行,准备响应repareResponse

 放行,渲染合并输出的模型数据

this.renderMergedOutputModel(mergedModel, this.getRequestToExpose(request), response);

stepinto    getRequestToExpose拿到请求对象 

 

放行回到

 再次step into   renderMergedOutputModel,

 其中有一句暴露model作为请求域的属性,属于类InternalResourceView

this.exposeModelAsRequestAttributes(model, request);

 

 protected void renderMergedOutputModel(Map<String, Object> model, HttpServletRequest request, HttpServletResponse response) throws Exception {
        this.exposeModelAsRequestAttributes(model, request);
        this.exposeHelpers(request);
        String dispatcherPath = this.prepareForRendering(request, response);
        RequestDispatcher rd = this.getRequestDispatcher(request, dispatcherPath);
        if (rd == null) {
            throw new ServletException("Could not get RequestDispatcher for [" + this.getUrl() + "]: Check that the corresponding file exists within your web application archive!");
        } else {
            if (this.useInclude(request, response)) {
                response.setContentType(this.getContentType());
                if (this.logger.isDebugEnabled()) {
                    this.logger.debug("Including [" + this.getUrl() + "]");
                }

                rd.include(request, response);
            } else {
                if (this.logger.isDebugEnabled()) {
                    this.logger.debug("Forwarding to [" + this.getUrl() + "]");
                }

                rd.forward(request, response);
            }

        }
    }

以下方法循环遍历model,赋值给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);
            }

        });
    }

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/181573.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

CV——day70 零基础学YOLO:YOLOv1

YOLO系列1. 不同阶段算法优缺点分析2. IOU指标计算3. MAP指标计算**指标分析**如何计算MAP4 YOLOv14.1 YOLOv1核心思想4.2 YOLOv1网络架构那么&#xff0c;7 * 7 * 30的输出是怎么来呢&#xff1f;4.3 损失函数4.3.1 位置误差4.3.2 置信度误差(含object)4.3.3 置信度误差(不含o…

股票量化分析工具QTYX使用攻略——小市值轮动选股策略(更新2.5.9)

搭建自己的量化交易系统 如果要长期在市场中立于不败之地&#xff01;必须要形成一套自己的交易系统。 如何学会搭建自己的量化交易系统&#xff1f; 边学习边实战&#xff0c;在实战中学习才是最有效地方式。于是我们分享一个即可以用于学习&#xff0c;也可以用于实战炒股分析…

Springboot农产品特产销售网站maven mysql idea

摘 要 I 1 绪论 1 1.1研究背景 1 1.2研究现状 1 1.3研究内容 2 2 系统关键技术 3 2.1 JSP技术 3 2.2 JAVA简介 3 2.3 MYSQL数据库 4 2.4 B/S结构 4 3 系统分析 5 3.1 可行性分析 5 3.1.1 技术可行性 5 3.1.2经济可行性 5 3.1.3操作可…

[Android开发基础2] 七大常用界面控件(附综合案例)

文章目录 一、文本TextView 二、按钮Button 三、编辑输入框EditText 四、图片ImageView 五、单选按钮RadioButton 六、复选框CheckBox 七、系统消息框Toast 综合案例&#xff1a;账号注册界面 一、文本TextView TextView控件用于显示文本信息。 演示&#xff1a; <?…

kafka可视化web管理工具-KafkaMmap

kafka可视化web管理工具-KafkaMmap ​ 使用过kafka的小伙伴应该都知道kafka本身是没有管理界面的&#xff0c;所有操作都需要手动执行命令来完成。但有些命令又多又长&#xff0c;如果没有做笔记&#xff0c;别说是新手&#xff0c;就连老手也不一定能记得住&#xff0c;每次想…

blender绑定骨骼法 2 rig

image.pngimage.png生成一个body_temp add neck 脖子 add chin 下巴 image.pngadd shoulder肩膀 image.pngadd wrist手腕 add spline root .额那个位置 image.pngadd ankle脚踝 image.pngFACIAL setup是面部的骨骼绑定,这里没眼球啥的就不弄了直接 点go 就生成了骨骼. image.pn…

1、SPSS 25的安装

目录 一、简介 二、竞争优势 三、安装步骤 一、简介 SPSS 是一款用于Windows操作系统的数据和科学图形的数值分析软件&#xff0c;能够为用户提供多样的数据统计、处理、报告等功能&#xff0c;还能根据数据帮用户生成离散图、折线图等图形&#xff0c;以更加直观的方式向你…

【数据库增删查改基础版】本文将与大家一起去探索基础版本的数据库增删查改,图文讲解数据库增删查改

前言&#xff1a; 大家好&#xff0c;我是良辰丫&#xff0c;这篇文章我将带领大家进入基础版本增删查改数据库的学习&#xff0c;后面的文章会有数据库进阶版&#xff0c;更多的约束条件让你润享丝滑。增删查改是数据库操作中极其重要的内容&#xff0c;我们从简单入手&#x…

12.Java二维数组讲解

本篇文章重点需要掌握的内容如下: 后面附有Java二维数组的练习题 文章目录前言一、二维数组的应用场景二、二维数组的初始化1.静态初始化2.动态初始化三、二维数组的内存图1.特殊情况1的写法:特殊情况1的写法的好处:2.特殊情况2的写法四、二维数组的练习题总结前言 一、二维数…

三子棋游戏

前言 三子棋是一种民间传统游戏&#xff0c;又叫九宫棋、圈圈叉叉、一条龙、井字棋等。将正方形对角线连起来&#xff0c;相对两边依次摆上三个双方棋子&#xff0c;只要将自己的三个棋子走成一条线&#xff0c;对方就算输了。但是&#xff0c;有很多时候会出现和棋的情况。 文…

Hi3861鸿蒙物联网项目实战:倒车雷达

华清远见FS-Hi3861开发套件&#xff0c;支持HarmonyOS 3.0系统。开发板主控Hi3861芯片内置WiFi功能&#xff0c;开发板板载资源丰富&#xff0c;包括传感器、执行器、NFC、显示屏等&#xff0c;同时还配套丰富的拓展模块。开发板配套丰富的学习资料&#xff0c;包括全套开发教程…

Cadence PCB仿真 使用 Allegro PCB SI 敏感网络列表.lst文件的建立方法图文教程

🏡《Cadence 开发合集目录》   🏡《Cadence PCB 仿真宝典目录》 目录 1,概述2,基本方法3,建立技巧4,总结1,概述 敏感网络表(.lst文件)是一个在PCB设计阶段需要特别关注的网络列表。本文简单介绍其建立或导出方法。 2,基本方法 第1步:使用记事本新建1个文本文档…

vue2原理核心Object.defineProperty()的理解

Object.defineProperty(obj, prop, { configurable:false //默认false ,为true是可以属性修改,删除 enumerable:false //默认false ,为true是可以枚举对象 value:prop对应的值 // 初始为undefined writable:false //默认false ,为true是可以修改value的值 }) o…

python实现XML文件的内容变更

文章目录一、使用背景二、实现效果三、内置库的使用四、代码实现解析五、完整代码一、使用背景 我们在某些情况下需要对XML格式的文件进行内容处理&#xff0c;可以直接打开处理&#xff0c;但是对于一些需要自动化或者不方便手动处理的情况下我们的代码实现就比较关键啦&…

maxlength属性

<!DOCTYPE html> <html> <head> <meta charset"utf-8"> <title>maxlength属性</title> </head> <body> <form action"action_page.php"> <!--…

面试官问:生产环境遇到难题,你是如何解决的?

1、生产环境发生 cpu 飙高的问题&#xff1f;你是如何定位解决的呢&#xff1f; 我们的线程是运行在 cpu 上面 1. CAS 自旋一直重试导致 cpu 飙高 没有控制自旋次数&#xff1b;乐观锁 2. 死循环; 3. 阿里云 Redis 被注入挖矿程序,建议 Redis 端口不要能够被外网访问; 4. 服务…

Python 介绍和环境准备

文章目录一、概述二、Python 应用领域1&#xff09; Web应用开发2&#xff09;自动化运维3&#xff09;网路爬虫4&#xff09;人工智能领域5&#xff09;科学计算三、Python 环境准备1&#xff09;Linux 平台安装 Python2&#xff09;Window 平台安装 Python3&#xff09;安装 …

Windows WSL 启用 Systemd(使用 snap 安装应用)

背景 如今&#xff0c;WSL 已经能够支持 systemd。我们看一下怎么在 WSL 启用 systemd 来使用 snap。 准备工作 确保 WSL 版本在 0.67.6 及以上。可以通过如下命令查看。 wsl --version如果版本过低&#xff0c;可以下载最新版本的 WSL 并安装。 启用 Systemd 测试环境为…

SAP入门技术分享七:Field Symbol和数据引用

Field Symbol和数据引用1.概要2.定义Field Symbol&#xff08;1&#xff09;定义-Generic TYPE(泛型)&#xff08;2&#xff09;定义-Fully TYPE(全类型)3.分配Field Symbol&#xff08;1&#xff09;Assign语句的基本结构&#xff08;2&#xff09;将结构体字段分配到字段符号…

分布式链路追踪在数字化金融场景的最佳实践

作者 | 张冀 责编 | Carol 出品 | CSDN&#xff08;ID&#xff1a;CSDNnews&#xff09; 【CSDN 编者按】在以微服务和容器化为主导应用的现代化浪潮下&#xff0c;系统的可观测性变得越来越重要&#xff0c;而链路追踪技术就成为软件系统实现“无人驾驶”的关键手段。本文作者…