SpringMVC笔记三:处理模型数据

本文介绍了Spring MVC处理模型数据的几种途径,包括返回值为ModelAndView时添加数据、Handler方法接受Map类型参数、控制类上使用@SessionAttributes注解暂存数据到HttpSession,以及@ModelAttribute注解的作用和工作流程,还阐述了SpringMVC确定目标方法POJO入参的过程。

处理模型数据

Spring MVC 提供了以下几种途径输出模型数据:

1.1.ModelAndView: 处理方法返回值类型为 ModelAndView时, 方法体即可通过该对象添加模型数据

    /*
     * 处理方法的返回值可以是ModelAndView类型,其中可包含视图和模型信息
     * SpringMVC会把ModelAndView的model中的数据放到request域对象
     */
    @RequestMapping("/ModelAndView")
    public ModelAndView testModelAndView() {
        ModelAndView modelAndView = new ModelAndView("hello");
        modelAndView.addObject("time",new Date());
        return modelAndView;
    }

如果想要在JSP页面上获取对应的值可以通过如下的方法:

    time now: ${requestScope.time}<br>
  • @ModelAttribute: 方法入参标注该注解后, 入参的对象就会放到数据模型中

1.2.Handler 方法可以接受Map类型的参数

Map 及 Model: 入参为org.springframework.ui.Model、org.springframework.ui. ModelMap 或 java.uti.Map 时,处理方法返回时,Map 中的数据会自动添加到模型中。

Spring MVC 在调用方法前会创建一个隐含的模型对象作为模型数据的存储容器。
如果方法的入参为 Map 或 Model 类型,Spring MVC 会将隐含模型的引用传递给这些入参。在方法体内,开发者可以通过这个入参对象访问到模型中的所有数据,也可以向模型中添加新的属性数据。

/*
 * 目标方法可以添加Map类型(也可以是Model/ModelMap类型)
 */
 @RequestMapping("/testMap")
    public String  testMap(Map<String,Object> map) throws IOException {
        map.put("names", Arrays.asList("Tom","Lisa","Allen"));
        return "hello";
    }

jsp页面中添加:

names list: ${requestScope.names}

1.3. 控制类上的@SessionAttributes

该注解只能标识在类上面
若希望在多个请求之间共用某个模型属性数据,则可以在控制器类上标注一个 @SessionAttributes, Spring MVC 将在模型中对应的属性暂存到 HttpSession 中。

/*
 * @SessionAttributes 除了可以通过属性名指定需要放到会话中的属性外,(value)
 * value={"user"}含义是把模型中属性为"user"的,(map中的键值)
 * 还可以通过模型属性的对象类型指定哪些模型属性需要放到会话中(types)
 * types指定的是map中的值类型符合就保存在session中
 * (requestScope一样含有这些模型属性)
 */
@SessionAttributes(value={"user"},types ={String.class})
@RequestMapping("/TestRequest")
@Controller
public class HelloWorld {
    @RequestMapping("/Session")
    public String testSessionAttribute(Map<String,Object> map){
        User user = new User("kaixin","123456",new Address("nanchang","AlongRiver"),19);
        map.put("user",user);
        map.put("school","hust");
        return "hello";
    }
}
 request user:${requestScope.user}<br>
 session user:${sessionScope.user}<br>
 request school:${requestScope.school}<br>
 session school:${sessionScope.school}<br>

localhost:8080/SpringMVC01/TestRequest/Session上显示

request user:User{username='kaixin', password='123456', address=Address{city='nanchang', street='AlongRiver'}, age=19}
session user:User{username='kaixin', password='123456', address=Address{city='nanchang', street='AlongRiver'}, age=19}
request school:hust
session school:hust

注:
传入数据到Map中时,一般情况下对于键的名称没有做特别的要求,但如果是在@ModelAttribute中,因为map的数据是作为参数传给处理器方法的,所以要求键的名称对应bean类的首字母小写。

1.4.@ModelAttribute

参考
https://blog.youkuaiyun.com/xiangwanpeng/article/details/53069533

讨论@ModelAttribute的作用及工作流程。即:有一个Graduate类,有id、studentname、email、password四个属性。现在要完成一个更新操作,但是其中有一项属性不能被修改,例如id,那么只能修改三项属性,password、studentname和email,所以从form表单传递的信息就只能有这三项,我们是通过@ModelAttribute注解标记方法来实现的:(其中数据库相关的操作仅采用模拟的方式)

1.4.1 注:

若目标方法的 POJO 类型的参数没有使用 @ModelAttribute 作为修饰, 则 key 为 POJO 类名第一个字母的小写;
若目标方法的 POJO 类型的参数使用了@ModelAttribute 来修饰, 则 key 为 @ModelAttribute 注解的 value 属性值。

1.4.2
SpringMVC确定目标方法POJO入参的全过程

在这个例子中,SpringMVC通过映射请求调用目标处理方法testModelAttribute方法之前,做了下面三件事情:
  第1步: 执行 @ModelAttribute 注解修饰的方法: 从数据库中取出对象,把对象放入到了 Graduate中,键为:undergraduate。(见1.4.1)
  第2步: SpringMVC 从 Map 中取出 Graduate 对象 graduate1, 并把表单的请求参数赋给 graduate1的对应属性。
  第3步: SpringMVC 把上述对象作为参数传入目标方法testModelAttribute(Graduate id1)。

     /*
     * 源码分析:
     * 1.调用@ModelAttribute修饰的方法,实际上@ModelAttribute修饰的方法中的Map的数据放到implicitModel
     * (这是一个BindingAwareModelMap类型的对象,BindingAwareModelMap类型实现了Map接口)中
     * 2.解析请求处理器的目标参数,实际上该目标参数来源于WebDataBinder的target属性
     *  1)创建WebDataBinder对象
     *      ①确定Attribute属性:(确定key)
     *      若传入的属性值为"",则ObjectName为类名首字母小写
     *      注:若目标方法的POJO属性使用了@ModelAttribute修饰,则ObjectName值即为
     *      @ModelAttribute的value值
     *      ②确定target属性:(确定value)
     *      Ⅰ 在implicitModel中查找attributeName对应的属性值.找到ok;
     *      Ⅱ 若 implicitModel 中不存在 key 对应的对象,
     *      则检查当前的控制器类是否被@SessionAttributes注解修饰 ,如果使用了@SessionAttributes注解修饰,
     *      且@SessionAttributes注解的value属性值中包含了key,则尝试从HttpSession中获取key所对应的value值,
     *      如果value值存在则获取到,若存在则直接传入到目标方法的入参中。
     *      如果value值不存在则抛出异常。
     *     如果没有使用@SessionAttributes注解修饰该控制器类,或者使用了,
     *      但是@SessionAttributes注解中的value值不包含key,
     *      则SpringMVC会通过反射来创建一个POJO类型的对象。
     *  2)SpringMVC将表单参数赋给WebDataBinder对象的target属性
     *  3)SpringMVC将WebDataBinder的Attribute 、target属性给implicitModel
     *  4)把target作为参数传给目标方法的入参
     */
    @ModelAttribute
    public void getStudentInfo(@RequestParam(value = "id",required = false)Integer id,
                    Map<String,Object> map){
        if(id!=null){
            //模拟从数据库中获取对象
            Graduate graduate1 =new Graduate("Tom","123456789",1,"hust@edu.cn");
            System.out.println("从数据库中获取一个对象");
            //把对象放入到map中
            map.put("undergraduate", graduate1);//map中的键和目标方法的入参类型的名首字母小写
        }
    }
    @RequestMapping("/testModelAttribute")
    //在传入目标对象前,SpringMVC会从Map中取出Graduate对象,并把表单请求参数赋给对应的属性值
    public String testModelAttribute(@ModelAttribute("undergraduate") Graduate id1){
        System.out.println("修改:"+id1);
        return "hello";
    }
}

源码分析有一丢丢复杂,总之就是到处找key,找完key找对应的value,可以没有key(也就没有value),但不可以有key没value(抛异常)。

### 光流法C++源代码解析与应用 #### 光流法原理 光流法是一种在计算机视觉领域中用于追踪视频序列中运动物体的方法。它基于亮度不变性假设,即场景中的点在时间上保持相同的灰度值,从而通过分析连续帧之间的像素变化来估计运动方向和速度。在数学上,光流场可以表示为像素位置和时间的一阶导数,即Ex、Ey(空间梯度)和Et(时间梯度),它们共同构成光流方程的基础。 #### C++实现细节 在给定的C++源代码片段中,`calculate`函数负责计算光流场。该函数接收一个图像缓冲区`buf`作为输入,并初始化了几个关键变量:`Ex`、`Ey`和`Et`分别代表沿x轴、y轴和时间轴的像素强度变化;`gray1`和`gray2`用于存储当前帧和前一帧的平均灰度值;`u`则表示计算出的光流矢量大小。 #### 图像处理流程 1. **初始化和预处理**:`memset`函数被用来清零`opticalflow`数组,它将保存计算出的光流数据。同时,`output`数组被填充为白色,这通常用于可视化结果。 2. **灰度计算**:对每一像素点进行处理,计算其灰度值。这里采用的是RGB通道平均值的计算方法,将每个像素的R、G、B值相加后除以3,得到一个近似灰度值。此步骤确保了计算过程的鲁棒性和效率。 3. **光流向量计算**:通过比较当前帧和前一帧的灰度值,计算出每个像素点的Ex、Ey和Et值。这里值得注意的是,光流向量的大小`u`是通过`Et`除以`sqrt(Ex^2 + Ey^2)`得到的,再乘以10进行量化处理,以减少计算复杂度。 4. **结果存储与阈值处理**:计算出的光流值被存储在`opticalflow`数组中。如果`u`的绝对值超过10,则认为该点存在显著运动,因此在`output`数组中将对应位置标记为黑色,形成运动区域的可视化效果。 5. **状态更新**:通过`memcpy`函数将当前帧复制到`prevframe`中,为下一次迭代做准备。 #### 扩展应用:Lukas-Kanade算法 除了上述基础的光流计算外,代码还提到了Lukas-Kanade算法的应用。这是一种更高级的光流计算方法,能够提供更精确的运动估计。在`ImgOpticalFlow`函数中,通过调用`cvCalcOpticalFlowLK`函数实现了这一算法,该函数接受前一帧和当前帧的灰度图,以及窗口大小等参数,返回像素级别的光流场信息。 在实际应用中,光流法常用于目标跟踪、运动检测、视频压缩等领域。通过深入理解和优化光流算法,可以进一步提升视频分析的准确性和实时性能。 光流法及其C++实现是计算机视觉领域的一个重要组成部分,通过对连续帧间像素变化的精细分析,能够有效捕捉和理解动态场景中的运动信息
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值