文章目录
本篇示例基于第一个SpringMVC程序,主要介绍以下三个域对象中如何实现数据共享。
- request,仅在一次请求中有效。
- session,仅在一次会话中有效。生命周期从浏览器开启到浏览器关闭。浏览器开启,创建session;浏览器关闭,销毁session。
- application,即ServletContext,在一个应用中有效。生命周期从服务器开启到服务器关闭。服务器开启,创建ServletContext;服务器关闭,销毁ServletContext。
实现request域对象的数据共享
使用Servlet API
package com.example.mvc.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import javax.servlet.http.HttpServletRequest;
@Controller
public class TestController {
@RequestMapping("/")
public String index(HttpServletRequest request){
request.setAttribute("data","hello,servlet!");
return "index";
}
}
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>首页</title>
</head>
<body>
<p th:text="${data}"></p>
</body>
</html>
使用ModelAndView
package com.example.mvc.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;
@Controller
public class TestController {
@RequestMapping("/")
public ModelAndView index( ){
ModelAndView mav = new ModelAndView();
mav.addObject("data","hello,ModelAndView");
mav.setViewName("index");
return mav;
}
}
<!-- index.html -->
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>首页</title>
</head>
<body>
<p th:text="${data}"></p>
</body>
</html>
使用Model
package com.example.mvc.controller;
;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
public class TestController {
@RequestMapping("/")
public String test(Model model){
model.addAttribute("data","hello,model!");
return "index";
}
}
<!-- index.html -->
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>首页</title>
</head>
<body>
<p th:text="${data}"></p>
</body>
</html>
使用Map
package com.example.mvc.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import java.util.Map;
@Controller
public class TestController {
@RequestMapping("/")
public String test(Map<String,Object> map){
map.put("data","hello,Map");
return "index";
}
}
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>首页</title>
</head>
<body>
<p th:text="${data}"></p>
</body>
</html>
使用ModelMap
package com.example.mvc.controller;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
public class TestController {
@RequestMapping("/")
public String test(ModelMap modelMap){
modelMap.addAttribute("data","hello,ModelMap");
return "index";
}
}
<!-- index.html -->
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>首页</title>
</head>
<body>
<p th:text="${data}"></p>
</body>
</html>
Model、Map和 ModelMap三者的关系
Model、Map和ModelMap在实现request域对象的数据共享时很类似,都是作为控制器方法的形参,不妨放在一起对比下。
package com.example.mvc.controller;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import java.util.Map;
@Controller
public class TestController {
@RequestMapping("/")
public String test(){
return "index";
}
@RequestMapping("/testApi")
public String testApi(HttpServletRequest request){
request.setAttribute("data","hello,Api");
return "test";
}
@RequestMapping("/testModelAndView")
public ModelAndView testModelAndView(){
ModelAndView modelAndView = new ModelAndView();
modelAndView.addObject("data","hello,ModelAndView");
modelAndView.setViewName("test");
return modelAndView;
}
@RequestMapping("/testModel")
public String testModel(Model model){
model.addAttribute("data","hello,Model");
System.out.println(model.getClass().getName());
return "test";
}
@RequestMapping("/testMap")
public String testMap(Map<String,Object> map){
map.put("data", "hello,Map");
System.out.println(map.getClass().getName());
return "test";
}
@RequestMapping("/testModelMap")
public String testModelMap(ModelMap modelMap){
modelMap.addAttribute("data","hello,ModelMap");
System.out.println(modelMap.getClass().getName());
return "test";
}
}
<!-- index.html -->
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>首页</title>
</head>
<body>
<h1>首页</h1>
<a th:href="@{/testApi}">testApi</a><br/>
<a th:href="@{/testModelAndView}">testModelAndView</a><br/>
<a th:href="@{/testModel}">testModel</a><br/>
<a th:href="@{/testMap}">testMap</a><br/>
<a th:href="@{/testModelMap}">testModelMap</a>
</body>
</html>
<!-- test.html -->
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>test</title>
</head>
<body>
<p th:text="${data}"></p>
</body>
</html>
idea控制台打印的信息如下所示,model、map和modelMap实例调用getClass().getName()
的结果都是org.springframework.validation.support.BindingAwareModelMap
。
进入ModelMap类,并ctrl+H,可查看类所在的层次结构。
Map、Model、ModelMap的继承层次结构可用下图描述。
public interface Model
public interface Map<K,V>
public class HashMap<K,V> extends AbstractMap<K,V> implements Map<K,V>, Cloneable, Serializable
public class LinkedHashMap<K,V> extends HashMap<K,V> implements Map<K,V>
public class ModelMap extends LinkedHashMap<String, Object>
public class ExtendedModelMap extends ModelMap implements Model
public class BindingAwareModelMap extends ExtendedModelMap
落脚点ModelAndView
要实现request域对象的数据共享,不论是使用Servlet API、ModelAndView、Model、Map还是ModelMap,最终的落脚点其实还是在ModelAndView。
可以通过打断点调试来理解。
实现session域对象的数据共享
使用Servlet API
package com.example.mvc.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import javax.servlet.http.HttpSession;
@Controller
public class TestController {
@RequestMapping("/")
public String test(HttpSession session){
session.setAttribute("data","hello,session");
return "index";
}
}
<!-- index.html -->
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>首页</title>
</head>
<body>
<h1>首页</h1>
<p th:text="${session.data}"></p>
</body>
</html>
实现application域对象的数据共享
使用Servlet API
获取ServletContext有多种方式,比如
- 通过HttpSession获取ServletContext
- 通过HttpServletRequest获取ServletContext
通过HttpSession获取ServletContext
package com.example.mvc.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpSession;
@Controller
public class TestController {
@RequestMapping("/")
public String test(HttpSession session){
ServletContext application = session.getServletContext();
application.setAttribute("data","hello,application");
return "index";
}
}
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>首页</title>
</head>
<body>
<h1>首页</h1>
<p th:text="${application.data}"></p>
</body>
</html>
使用HttpServletRequest获取ServletContext
package com.example.mvc.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
@Controller
public class TestController {
@RequestMapping("/")
public String test(HttpServletRequest request){
ServletContext application = request.getServletContext();
application.setAttribute("data","hello,application");
return "index";
}
}