当前位置: 代码迷 >> VC/MFC >> Spring4MVC之处置模型数据
  详细解决方案

Spring4MVC之处置模型数据

热度:171   发布时间:2016-05-02 03:47:06.0
Spring4MVC之处理模型数据

?

处理模型数据

?

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

?

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

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

3. @SessionAttributes: 将模型中的某个属性暂存到HttpSession 中,以便多个请求之间可以共享这个属性

4. @ModelAttribute: 方法入参标注该注解后, 入参的对象就会放到数据模型中

?

ModelAndView

?

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

添加模型数据:

MoelAndView addObject(String attributeName, Object attributeValue)

ModelAndView addAllObject(Map<String, ?> modelMap)

设置视图:

void setView(View view)

void setViewName(String viewName)?

?

示例

?

1. 编辑JSP页面

?

        <li>处理模型数据            <ul>                <li><a href="user/testModelAndView">ModelAndView处理方式</a></li>            </ul>        </li>

?

<%@ 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><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><title>SUCCESS</title></head><body>    <hr/>        <h1>LOGIN</h1>    <table>        <tr>            <td>时间:</td><td>${requestScope.time}</td>        </tr>        <tr>            <td>信息:</td><td>${requestScope.message}</td>        </tr>    </table>        <hr/>    <a href="/org.rabbitx.web.spring4mvc/index.jsp">返回首页</a></body></html>

?

<%@ 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><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><title>SUCCESS</title></head><body>    <hr/>        <h1>LOGOUT</h1>    <table>        <tr>            <td>时间:</td><td>${requestScope.time}</td>        </tr>        <tr>            <td>信息:</td><td>${requestScope.message}</td>        </tr>    </table>    <hr/>    <a href="/org.rabbitx.web.spring4mvc/index.jsp">返回首页</a></body></html>

?

2. 编辑处理类

?

	/**	 * 目标方法的返回值可以是ModelAndView类型,此类型中包含了(封装了)视图和模型信息	 * 	 * SpringMVC会把ModelAndView的model中的数据放入到request域对象中	 * 	 */	@RequestMapping("/testModelAndView")	public ModelAndView testModelAndView()	{		String viewName = null;		ModelAndView modelAndView = new ModelAndView();		if(System.currentTimeMillis()%2 == 0)		{			viewName = LOGIN;			modelAndView.addObject("message", "success");		}		else		{			viewName = LOGOUT;			modelAndView.addObject("message", "failure");		}		modelAndView.addObject("time", new Date());		modelAndView.setViewName(viewName);		return modelAndView;	}

?

3. 测试



?

原理分析

?

1. 在方法testModelAndView中添加断点并使用调试模式启动服务器;




2. 在浏览器中点击相应连接启动调试;

3. 在调试栈中选择DispatcherServlet.doDispatch(HttpServletRequest, HttpServletResponse) line: 945;




此处的mv就是ModelAndView实例;

?

4. 进入此类的processDispatchResult方法;

5. 进入方法processDispatchResult中的render(mv, request, response);方法;

6. 在方法render中的view.render(mv.getModelInternal(), request, response);方法上使用Ctrl+T快捷键;



?

7. 选择AbstractView并进入;

8. 在AbstractView类中方法render中的方法renderMergedOutputModel上使用快捷键Ctrl+T进入“InternalResourceView”;



?

9. 查看类InternalResourceView中的renderMergedOutputModel方法中的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 [email protected] 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() + "'");				}			}		}	}

?

总结:

?

SpringMVC使用ModelAndView处理数据回传的本质是在ModelAndView中维护了一个ModelMap(这个类继承至LinkedHashMap<String, Object>),在服务器端,用户通过ModelAndView的addObject方法把数据添加到ModelAndView的map中。ModelAndView会在响应阶段通过遍历此map把数据添加到request域对中。

?

Map 及 Model

?

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

?

具体步骤:

1. Spring MVC 在调用方法前会创建一个隐含的模型对象作为模型数据的存储容器。

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

?



?

?

示例

?

1. 添加处理类

?

	/**	 * 目标方法可以添加Map类型的(实际上也可以是Model类型或者ModelMap类型)参数 	 * 	 * 实际map的类型是BindingAwareModelMap	 * 	 * 处理本质是把此处map中的数据放入到ModelAndView对象中了	 */	@RequestMapping("/testMap")	public String testMap(Map<String,Object> map)	{		map.put("time", new Date());		map.put("message", "testMap-success");		System.out.println("----------testMap----------");		System.out.println("Map type: " + map.getClass());		return LOGIN;	}

??

@SessionAttributes

?

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

@SessionAttributes 除了可以通过属性名指定需要放到会话中的属性外,还可以通过模型属性的对象类型指定哪些模型属性需要放到会话中

@SessionAttributes(types=User.class) 会将隐含模型中所有类型为 User.class 的属性添加到会话中。

@SessionAttributes(value={“user1”, “user2”})

@SessionAttributes(types={User.class, Dept.class})

@SessionAttributes(value={“user1”, “user2”},

types={Dept.class})?

?

示例

?

1. 在处理类中添加处理方法;

?

	/**	 * @SessionAttributes 除了可以通过属性名指定需要放到会话中的属性外(实际上使用的是 value 属性值),	 * 还可以通过模型属性的对象类型指定哪些模型属性需要放到会话中(实际上使用的是 types 属性值)	 * 	 * 注意: 该注解只能放在类的上面. 而不能修饰放方法. 	 */	@RequestMapping("/testSessionAttributes")	public String testSessionAttributes(Map<String,Object> map)	{		User user = new User();		user.setUsername("tom");		user.setPassword("123456");		map.put("user", user);		map.put("time", new Date());		map.put("message", "testMap-success");		System.out.println("----------testMap----------");		System.out.println("Map type: " + map.getClass());		return LOGIN;	}

?

2. 在处理类中添加Session域配置;

?

@Controller@SessionAttributes(value={"user","time"},types={String.class})@RequestMapping("/user")public class UserController {	private final static String LOGIN = "login";		private final static String LOGOUT = "logout";        。。。}

?

3. 编辑JSP页面

?

        <li>处理模型数据            <ul>                <li><a href="user/testModelAndView">ModelAndView处理方式</a></li>                <li><a href="user/testMap">Map及 Model处理方式</a></li>                <li><a href="user/testSessionAttributes">@SessionAttributes处理方式</a></li>            </ul>        </li>

?

<%@ 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><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><title>SUCCESS</title></head><body>    <hr/>        <h1>LOGIN</h1>    <table>        <tr>            <td>request域中时间:</td><td>${requestScope.time}</td>        </tr>        <tr>            <td>request域中信息:</td><td>${requestScope.message}</td>        </tr>        <tr>            <td>request域中user</td><td>${requestScope.user}</td>        </tr>        <tr>            <td>session域中时间:</td><td>${sessionScope.time}</td>        </tr>        <tr>            <td>session域中信息:</td><td>${sessionScope.message}</td>        </tr>        <tr>            <td>session域中user</td><td>${sessionScope.user}</td>        </tr>    </table>        <hr/>    <a href="/org.rabbitx.web.spring4mvc/index.jsp">返回首页</a></body></html>

?

测试结果



?

?

?

?

?

?

?

?

?

?

?

?

  相关解决方案