ModelAndView使用

  • Post author:
  • Post category:其他




请求转发

<bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="viewClass"
                  value="org.springframework.web.servlet.view.JstlView" />
        <property name="prefix" value="/WEB-INF/jsp/" />
        <property name="suffix" value=".jsp" />
    </bean>
@RequestMapping(value = "view")
    public ModelAndView view(HttpServletRequest request) {
        ModelAndView mv = new ModelAndView();
        mv.setViewName("index"); //视图名
        mv.addObject("name", "ljh");
        return mv;
    }

根据配置可以转到/WEB-INF/jsp/index.jsp文件,通过请求转发(forward)的方式跳转,所带的参数其实是通过

request.setAttribute("name","ljh")

的方式带给index.jsp的。

@RequestMapping("view2")
public String view2(){
	return "index";
}

这也是通过forward方式转发到index.jsp页面。如果想转发到view.do这个url,可以这样写,

return "forward:view.do";


Springmvc维护了几个视图参数:(ModelAndView)视图+数据模型、(ModelMap、Model)数据模型,直接写成入参就可以使用,例如:

public String view3(Model model)

,实际上ModelMap和Model都是BindingAwareModelMap的实例,它们之间的关系图如下:

在这里插入图片描述

ModelAndView初始化后,model属性为空,当调用它增加数据模型的方法后,会自动创建一个ModelMap实例并给model属性赋值,用以保存数据模型。例如:

@RequestMapping("view6")
public ModelAndView view6(Model model){
	ModelAndView mv = new ModelAndView();
	mv.setViewName("index");
	model.addAttribute("age",18);
	return mv;
}

这种是

无法正常返回

数据模型的:

@RequestMapping("view4")
public String view4(){
	ModelAndView mv = new ModelAndView();
	mv.addObject("name", "ljh");
	return "index";
}

可以正常转发到index.jsp页面,但是无法获取其中的name数据属性。但是可以通过

request.getAttribute("modelAndView")

获取返回的数据模型。

下面这种就可以

正常返回

视图数据:

@RequestMapping("view5")
    public String view5(ModelMap mv) {
        mv.addAttribute("email", "@163");
        return "index";
    }

如果返回的ModelAndView视图数据模型对象没有设置view属性,或者返回的String对象为null,则将对应请求url的值作为视图名。

@RequestMapping("view10")
    public ModelAndView view10(){
        ModelAndView mv = new ModelAndView();
        mv.addObject("key", "value");
        return mv;
    }

或者

@RequestMapping("view10")
    public String view10(){
        return null;
    }

最终都是转发到

/WEB-INF/jsp/view10.jsp



重定向

转发是通过服务器内部进行的,浏览器地址栏不会改变,并且可以访问WEB-INF目录下的文件,但是通过请求重定向却不可以。原因很简单,就是因为它是浏览器的访问。重定向是通过在响应头中添加Location字段,告诉浏览器去请求Location这个地址,浏览器会通过get去请求,浏览器地址栏会改变,并且不能往请求中放对象。

@RequestMapping("view6")
    public String view6(ModelMap modelMap) {
        modelMap.addAttribute("param", "value");
        return "redirect:view5.do";
    }

地址栏最后的数据

/view5.do?param=value

,view5中可以通过

request.getParameter("param")

方式获取get请求中值。

@RequestMapping("view7")
    public ModelAndView view7(ModelMap modelMap) {
        ModelAndView mv = new ModelAndView();
        mv.setViewName("redirect:view5.do");
        modelMap.addAttribute("score", 98);
        return mv;
    }

地址栏最后的数据

/view5.do?score=98

那么重定向时怎么才能传递对象呢?SpringMVC提供了RedirectAttributes接口,它继承Model接口,唯一的实现类RedirectAttributesModelMap继承ModelMap。

主要用到两个方法:

RedirectAttributes addAttribute(String var1, Object var2);

会自动添加参数到url上,同样不能是对象,var2需要可以转换成String类型。

RedirectAttributes addFlashAttribute(String var1, Object var2);

可以添加对象并保存,给重定向的请求获取。

例如:

    @RequestMapping("view8")
    public ModelAndView view8(RedirectAttributes ra) {
        ra.addAttribute("param", "value");
        ra.addFlashAttribute("object", new Integer(3));
        ModelAndView mv = new ModelAndView();
        mv.setViewName("redirect:view5.do");
        return mv;
    }


ra.addFlashAttribute("object", new Integer(3));

实际存储的属性在flashmap,那么flashmap又是什么呢?

Flash 属性 和 RedirectAttributes:通过FlashMap存储一个请求的输出,当进入另一个请求时作为该请求的输入,典型场景如重定向(POST-REDIRECT-GET模式,1、POST时将下一次需要的数据放在FlashMap;2、重定向;3、通过GET访问重定向的地址,此时FlashMap会把1放到FlashMap的数据取出放到请求中,并从FlashMap中删除;从而支持在两次请求之间保存数据并防止了重复表单提交)。 SpringMVC提供FlashMapManager用于管理FlashMap,默认使用SessionFlashMapManager,即数据默认存储在session中,但是键值并不是我们add的,而是系统指定的。

在HandlerAdapter执行完getModelAndView(ModelAndViewContainer mavContainer,ModelFactory modelFactory, NativeWebRequest webRequest)方法后,会将RedirectAttributes的属性值放入request中,在之后的视图渲染时将这个数据从request中取出加入session中,在重定向的下一次请求中DispatcherServlet的doService方法往request中添加。

下面提供两个方法把addFlashAttribute中的数据提取出来。

public String test1(HttpServletRequest request) { 
	Map<String,?> map = RequestContextUtils.getInputFlashMap(request); 
	Object o = map.get("object"); 
	return ""; 
} 

public String test2(@ModelAttribute("object") Object o) { 
	return ""; 
} 

**注意:**要想使用RedirectAttributes,必须在servlet配置文件中配置:

xmlns:mvc="http://www.springframework.org/schema/mvc"
 xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd"
<mvc:annotation-driven/>


重定向的中文参数乱码问题:


重定向时如果需要在url之后传递参数,那么需要考虑编码的问题。默认情况下是按照”ISO-8859-1″的编码格式,也可以通过给请求设置编码格式设置,如

request.setCharacterEncoding("UTF-8")

发送重定向数据时编码:

URLEncoder.encode("中文",encode)



接受数据时解码:

URLDecoder.decode(param, encode)



视图和视图解析器

视图对象需要实现View接口:

public interface View {
	//响应状态属性
	String RESPONSE_STATUS_ATTRIBUTE = View.class.getName() + ".responseStatus";
	//定义数据模型下取出变量路径
	String PATH_VARIABLES = View.class.getName() + ".pathVariables";
	 //选择响应内容类型
	String SELECTED_CONTENT_TYPE = View.class.getName() + ".selectedContentType";
	//响应客户端的类型
	String getContentType();
	//渲染方法,model是数据模型
	void render(Map<String, ?> model, HttpServletRequest request, HttpServletResponse response) throws Exception;
}

当控制器返回ModelAndView的时候,视图解析器将数据模型传递给render方法并解析,以得到渲染视图。

SpringMVC的常用视图类:

SpringMVC的常用视图类

如果只想返回Json数据,可以使用Json视图,设置view属性。

@RequestMapping("view9")
    public ModelAndView view9(){
        ModelAndView mv = new ModelAndView();
        mv.setView(new MappingJackson2JsonView());
        mv.addObject("key", "value");
        return mv;
    }

在这里插入图片描述

视图解析器配置完成后,会加载到SpringMVC的视图解析器列表中,当返回ModelAndView的时候,就会去列表中查找对应的解析器解析视图。为什么返回一个字符串或者setViewName(“…”)的时候可以返回一个视图呢?因为配置了视图解析器InternalResourceViewResolver,通过分析字符串,forward:或者redirect:开头,确定返回的视图,然后结合数据模型渲染出页面。



版权声明:本文为qq_36744284原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。