SpringMVC实战(四)-处理模型数据

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

  • ModelAndView:处理方法返回值类型为 ModelAndView时, 方法体即可通过该对象添加模型数据
  • Map及Model:入参为org.springframework.ui.Model、org.springframework.ui.ModelMap或 java.uti.Map时,处理方法返回时,Map 中的数据会自动添加到模型中。
  • @SessionAttributes: 将模型中的某个属性暂存到 HttpSession 中,以便多个请求之间可以共享这个属性
  • @ModelAttribute: 方法入参标注该注解后, 入参的对象就会放到数据模型中

ModelAndView

概述

控制器处理方法的返回值如果为 ModelAndView, 则其既包含视图信息,也包含模型数据信息。

添加模型数据:

  • MoelAndView addObject(String attributeName, Object attributeValue)
  • ModelAndView addAllObject(Map< String, ?> modelMap )

设置视图:

  • void setView(View view )
  • void setViewName(String viewName)

示例

register_form.jsp

<!DOCTYPE HTML>
<html>
<head>
    <title>Getting Started: Serving Web Content</title>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
</head>
<body>
    <form action="model/register" method="post">
        username: <input type="text" name="username"/>
        <br>
        password: <input type="password" name="password"/>
        <br>
        email: <input type="text" name="email"/>
        <br>
        age: <input type="text" name="age"/>
        <br>
        province: <input type="text" name="address.province"/>
        <br>
        city: <input type="text" name="address.city"/>
        <br>
        <input type="submit" value="Submit"/>
    </form>
</body>
</html>

ModelController.java

package com.ricky.codelab.webapp.ch3;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;
import com.ricky.codelab.webapp.ch2.model.User;

@Controller
@RequestMapping("model")
public class ModelController {

    @RequestMapping("register")
    public ModelAndView register(User user){

        ModelAndView mv = new ModelAndView("home");
        mv.addObject("user", user);

        return mv;
    }
}

home.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<body>
<h2>Welcome ${requestScope.user.username }!</h2>
</body>
</html>

Map 及 Model

概述

Spring MVC 在内部使用了一个org.springframework.ui.Model 接口存储模型数据。

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

示例

1、Map

package com.ricky.codelab.webapp.ch3;

import java.util.Map;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import com.ricky.codelab.webapp.ch2.model.User;

@Controller
@RequestMapping("model")
public class ModelController {

    @RequestMapping("register")
    public String register(User user, Map<String, Object> map){

        map.put("user", user);

        return "home";
    }
}

2、Model

package com.ricky.codelab.webapp.ch3;

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;

import com.ricky.codelab.webapp.ch2.model.User;

@Controller
@RequestMapping("model")
public class ModelController {

    @RequestMapping("register")
    public String register(User user, Model model){

        model.addAttribute("user", user);

        return "home";
    }
}

内部实现细节

SpringMVC 是怎么将ModelAndView设置到request域中的呢?
我们可以通过debug看看它执行的流程:

SpringMVC实战(四)-处理模型数据_第1张图片

在 org.springframework.web.servlet.view.AbstractView 的exposeModelAsRequestAttributes方法中我们看到如下代码:

/** * Expose the model objects in the given map as request attributes. * Names will be taken from the model Map. * This method is suitable for all resources reachable by {@link javax.servlet.RequestDispatcher}. * @param model Map of model objects to expose * @param request current HTTP request */
    protected void exposeModelAsRequestAttributes(Map<String, Object> model, HttpServletRequest request) throws Exception {
        for (Map.Entry<String, Object> entry : model.entrySet()) {
            String modelName = entry.getKey();
            Object modelValue = entry.getValue();
            if (modelValue != null) {
                request.setAttribute(modelName, modelValue);
                if (logger.isDebugEnabled()) {
                    logger.debug("Added model object '" + modelName + "' of type [" + modelValue.getClass().getName() +
                            "] to request in view with name '" + getBeanName() + "'");
                }
            }
            else {
                request.removeAttribute(modelName);
                if (logger.isDebugEnabled()) {
                    logger.debug("Removed model object '" + modelName +
                            "' from request in view with name '" + getBeanName() + "'");
                }
            }
        }
    }

它遍历model的每一个key-value键值对,并调用request.setAttribute(modelName, modelValue);方法将它们设置到request域中。

你可能感兴趣的:(spring,mvc,Model)