调用 Web 资源给域对象传值。

  • page
  • request
  • session
  • application

业务数据的绑定是指将业务数据绑定给 JSP 域对象,业务数据的绑定是由 ViewResolver 来完成的,开发时,我们先添加业务数据,再交给 ViewResolver 来绑定。
Spring MVC 提供了以下几种方式来添加业务数据:

  • Map
  • Model
  • ModelAndVIew
  • @SessionAttribute
  • @ModelAttributes
  • Servet API

一、业务数据绑定到 request 域对象

创建实体类 User

package com.southwind.pojo;

import lombok.Data;

@Data
public class User {
    private Integer id;
    private String name;
    private Address address;
}

1、Map

Spring MVC 在调用业务方法之前会创建一个隐含对象作为业务数据的存储容器,设置业务方法的入参为 Map 类型,Spring MVC 会将隐含对象的引用传递给入参。

Controller代码:
@RequestMapping("/map")
public String map(Map<String, Object> map){
    User user = new User();
    user.setId(1);
    user.setName("张三");
    map.put("user",user);
    return "show";
}
jsp
<%@page contentType="text/html; charset=UTF-8" language="java" %>
<%@page isELIgnored="false" %>
<html>
<body>
  ${user}
</body>
</html>

结果:
User(id=1, name=张三, address=null)

2、Model

Model 与 Map 类似,业务方法通过入参来完成业务数据的绑定。

Controller
@RequestMapping("/model")
public String model(Model model){
    User user = new User();
    user.setId(1);
    user.setName("王五");
    model.addAttribute("user", user);
    return "show";
}
jsp
<%@page contentType="text/html; charset=UTF-8" language="java" %>
<%@page isELIgnored="false" %>
<html>
<body>
  ${user}
</body>
</html>

结果
User(id=1, name=王五, address=null)

3、ModelAndView

与 Map 或者 Model 不同的是,ModelAndView 不但包含业务数据,同时也封装了视图信息,如果使用 ModelAndVIew 来处理业务数据,业务方法的返回值必须是 ModelAndVIew 对象。
业务方法中对 ModelAndVIew 进行两个操作:

  • 填充业务数据
  • 绑定视图信息
Controller
@RequestMapping("/mav1")
public ModelAndView mav1(){
    User user = new User();
    user.setId(1);
    user.setName("张三");
    ModelAndView mav = new ModelAndView();
    // 填充业务数据
    mav.addObject("user", user);
    // 绑定视图信息
    mav.setViewName("show");
    return mav;
}

@RequestMapping("/mav2")
public ModelAndView mav2(){
    User user = new User();
    user.setId(2);
    user.setName("李四");
    ModelAndView mav = new ModelAndView();
    mav.addObject("user", user);
    View view = new InternalResourceView("/show.jsp");
    mav.setView(view);
    return mav;
}

@RequestMapping("/mav3")
public ModelAndView mav3(){
    ModelAndView mav = new ModelAndView("show");
    User user = new User();
    user.setId(1);
    user.setName("张三");
    mav.addObject("user", user);
    return mav;
}

@RequestMapping("/mav4")
public ModelAndView mav4(){
    View view = new InternalResourceView("/show.jsp");
    ModelAndView mav = new ModelAndView(view);
    User user = new User();
    user.setId(2);
    user.setName("李四");
    mav.addObject("user", user);
    return mav;
}

@RequestMapping("/mav5")
public ModelAndView mav5(){
    User user = new User();
    user.setId(1);
    user.setName("张三");
    Map<String, Object> map = new HashMap<>();
    map.put("user", user);
    ModelAndView mav = new ModelAndView("show", map);
    return mav;
}

@RequestMapping("/mav6")
public ModelAndView mav6(){
    View view = new InternalResourceView("/show.jsp");
    User user = new User();
    user.setId(2);
    user.setName("李四");
    Map<String, Object> map = new HashMap<>();
    map.put("user", user);
    ModelAndView mav = new ModelAndView(view, map);
    return mav;
}

@RequestMapping("/mav7")
public ModelAndView mav7(){
    View view = new InternalResourceView("/show.jsp");
    User user = new User();
    user.setId(1);
    user.setName("张三");
    ModelAndView mav = new ModelAndView(view, "user", user);
    return mav;
}

@RequestMapping("/mav8")
public ModelAndView mav8(){
    User user = new User();
    user.setId(2);
    user.setName("李四");
    ModelAndView mav = new ModelAndView("show", "user", user);
    return mav;
}

4、HttpServletRequest

Spring MVC 可以在业务方法中直接获取 Servlet 原生 Web 资源,只需要在方法定义时添加 HttpServletRequest 入参即可,在方法中直接使用 request 对象。

@RequestMapping("/request")
public String request(HttpServletRequest request){
    User user = new User();
    user.setId(1);
    user.setName("张三");
    request.setAttribute("user", user);
    return "show";
}

5、@ModelAttribute

Spring MVC 还可以通过 @ModelAttribute 注解的方式添加业务数据,具体使用步骤如下:

  • 定义一个方法,该方法用来放好要填充到业务数据中的对象
  • 给该方法添加 @ModelAttribute 注解,不是响应请求的业务方法
@RequestMapping("/modelAttribute")
public String modelAttribute(){
     return "show";
 }

@ModelAttribute
public User getUser(){
    User user = new User();
    user.setId(10);
    user.setName("小明");
    return user;
}

@ModelAttribute 注解的作用是,当 Handler 接收到一个客户端请求之后,无论调用哪个业务方法,都会优先调用被 @ModelAttribute 注解修饰的方法,并将其返回值作为业务数据,再进入到业务方法,此时业务方法只需要返回视图信息即可,不需要返回业务数据,即使返回业务数据,也会被 @ModelAttribute 注解修饰的方法返回的数据所覆盖。
域对象中存值都是以 key-value 形式存储的,那么此时的 key 值是什么?默认值是业务数据对应的类的类名首字母小写之后的结果。

<%@page contentType="text/html; charset=UTF-8" language="java" %>
<%@page isELIgnored="false" %>
<html>
<body>
  ${user}
</body>
</html>

如果 getUser 没有返回值,则必须手动在该方法中填充业务数据,使用 Map 或者 Model 即可。

@ModelAttribute
public void getUser(Model model){
    User user = new User();
    user.setId(122);
    user.setName("小红");
    model.addAttribute("user", user);
}

如果同时存在两个 @ModelAttribute 注解方法

@ModelAttribute
public User getUser(){
    User user = new User();
    user.setId(10);
    user.setName("小明");
    return user;
}

@ModelAttribute
public void getUser(Model model){
    User user = new User();
    user.setId(122);
    user.setName("小红");
    model.addAttribute("user", user);
}

直接给 Model 对象进行装载的方法优先级更高。

二、业务数据绑定到 session 域对象

1、HttpSession

Controller
@RequestMapping("/session")
public String session(HttpSession session){
    User user = new User();
    user.setId(11);
    user.setName("王五");
    session.setAttribute("user", user);
    return "show";
}
jsp
<%@page contentType="text/html; charset=UTF-8" language="java" %>
<%@page isELIgnored="false" %>
<html>
<body>
${sessionScope.user}
</body>
</html>

2、@SessionAttributes

@SessionAttributes 注解不是给方法添加的,而是给类添加的。

Controller
@Controller
@RequestMapping("/view")
@SessionAttributes(value = "test")
public class ViewController {
	@RequestMapping("/test")
	public ModelAndView test(){
	    User user = new User();
	    user.setId(11);
	    user.setName("王五");
	    ModelAndView mav = new ModelAndView();
	    mav.addObject("test", user);
	    mav.setViewName("show");
	    return mav;
	}
}

jsp
<%@page contentType="text/html; charset=UTF-8" language="java" %>
<%@page isELIgnored="false" %>
<html>
<body>
${requestScope.test} <br>
${sessionScope.test}
</body>
</html>
结果
User(id=11, name=王五, address=null)
User(id=11, name=王五, address=null)

只要给类添加了 @SessionAttributes 注解之后,无论类中的哪个业务方法被访问,将业务数据绑定到 request 域对象的同时,也会将业务数据绑定到 session 域对象中,也就是说 request 和 session 对象会同时存在业务数据,前提是 request 域中的 key 值需要和 @SessionAttributes 注解中的 value 值一致。

@SessionAttributes 除了可以通过 key 值绑定,也可以通过业务数据的数据类型进行绑定。

@Controller
@SessionAttributes(type = User.class){
	...
}

@SessionAttributes 可以同时绑定多个业务数据

@Controller
@SessionAttributes(value = {"user", "address"}){
	...
}

或者

@Controller
@SessionAttributes(type = {User.class, Address.class}){
	...
}
Logo

CSDN联合极客时间,共同打造面向开发者的精品内容学习社区,助力成长!

更多推荐