上一篇:《修炼SpringMVC-注解开发-处理器方法的返回值》
如果文中有纰漏,请多多指正!!!
一、介绍
当处理器对请求处理完成后,向其他资源进行跳转时,有两种跳转方式:请求转发与重定向。
根据跳转资源类型的不同,可分为跳转至页面和跳转到其它处理器两种。
请求转发与重定向其它小知识:
1.请求转发一定在一个请求域中。 请求转发只能是把本系统的资源发送给本系统的其它资源、不能从本系统访问其它系统,可以访问本系统的WEB-INF下的所有资源。2. 请求重定向一定是两次请求过程。 请求重定向一定要注意数据的发送问题:如果想在重定向中发送数据,可以在重定向请求路径中拼接发送数据,也可以借助session域发送数据。 请求重定向不能访问本系统WEB-INF下的资源,但是请求重定向是可以从本系统访问其它系统资源。
上节讲到使用@Controller注解,注解的处理器,其内部方法常用返回值大致总结为以下4种类型:
- 返回ModelAndView类型
- 返回String类型
- 无返回值void
- 返回自定义类型对象(Object)
针对返回自定义类型对象(Object)不是作为逻辑视图出现的,而是作为直接在页面显示的数据出现的,所以本章节不做讨论。
二、返回ModelAndView时的请求转发与重定向
1.请求转发
1.在默认情况下,当处理器返回ModelAndView时,跳转到指定View,使用的就是请求转发。当然我们也可以在代码中显式地进行指出。此时,需要在setViewName()方法中指定的视图前添加forward:,写出相对于项目根的路径,并且此时的视图不会再与视图解析器中配置的前后缀拼接。2.由于此种写法是相对于项目根路径的,所以请求转发可以,请求转发到页面,也可以请求转发到其他处理器(Controller)。3.当通过请求转发跳转到目标资源(页面/Controller)时,如果需要携带数据,除了使用request、session外 ,还可以将数据放到ModelAndView中的Model中,页面通过EL表达式可直接访问该数据。
下面我们进行简单的案例演示。
- web.xml配置
SpringMVCDemoorg.springframework.web.servlet.DispatcherServletcontextConfigLocationclasspath:mySringMVC.xml1SpringMVCDemo*.docharacterEncodingFilterorg.springframework.web.filter.CharacterEncodingFilterencodingutf-8farceEncodingtruecharacterEncodingFilter/*
- mySringMVC.xml 配置
- jsp页面(/WEB-INF/inner.jsp)
请求转发与重定向(数据显示) ${show }
1.1) 请求转发到页面
- 定义处理器
@Controller@RequestMapping("/ResourceDeal")public class ResourceDealController { /** * 请求转发:跳转到页面 */ @RequestMapping("/inner.do") public ModelAndView toInner() throws Exception { ModelAndView mv = new ModelAndView(); mv.addObject("show","请求转发:跳转到页面"); mv.setViewName("forward:/WEB-INF/inner.jsp"); return mv; }}
- 访问路径
http://localhost:8080/SpringMVCPrimary/ResourceDeal/inner.do
1.2) 请求转发到其它Controller
请求转发到其它Controller,如需携带参数可利用request、session等,也可直接将参数名带入但必须保证前后名称一致(如下案例)。
- 定义处理器
@Controller@RequestMapping("/ResourceDeal")public class ResourceDealController { /** * 请求转发:转发到其它Controller */ @RequestMapping("/toInner.do") public ModelAndView toInner_1(String param) throws Exception { ModelAndView mv = new ModelAndView("forward:toInnerJsp.do"); return mv; } /** * 请求转发:转发到其它Controller */ @RequestMapping("/toInnerJsp.do") public ModelAndView toInnerJsp(String param) throws Exception { System.out.println(param); ModelAndView mv = new ModelAndView(); mv.addObject("show",param+"toInnerJsp"); mv.setViewName("forward:/WEB-INF/inner.jsp"); return mv; }}
- 访问路径
http://localhost:8080/SpringMVCPrimary/ResourceDeal/toInner.do?param=888
2.重定向
1.当处理器返回ModelAndView时,使用的是重定向。此时,需要在setViewName()方法中指定的视图前添加redirect:,写出相对于项目根的路径,并且此时的视图不会再与视图解析器中配置的前后缀拼接。2.重定向的目标资源中,将无法访问用户提交请求的request中的数据。3.当通过重定向跳转到目标资源(页面/Controller)时,如果需要携带数据,除了使用session外 ,还可以将数据放到ModelAndView中的Model中,页面通过EL表达式可直接访问该数据。
1.1) 重定向到页面
A.通过ModelAndView中的Model携带数据
当通过ModelAndView中的Model携带数据时,视图解析器会将map中的key、value以请求参数的形式拼接到请求URL后。此时需要注意
1.由于视图解析器会将map中的key、value以请求参数的形式拼接到请求URL后,所以无论什么类型的value都会转变成String。因此**放入到Model中的value,只能是基本数据类型与String,不能是自定义类型的对象数据。**2.重定向无法从request中读取数据,但由于会将Model中的数据拼接到URL中,所以页面可以通过EL表达式获取请求参数param中读取携带的参数。3.重定向无法获取/WEB-INF中的资源。
- 将inner.jsp更名outer.jsp页面放到项目根路径下(/outer.jsp)
${param.show }
- 定义处理器
@Controller@RequestMapping("/ResourceDeal")public class ResourceDealController { /** * 重定向:跳转到页面 * 通过ModelAndView中的Model携带数据 */ @RequestMapping(value="/outer.do",produces="text/html; charset=UTF-8") public ModelAndView toOuter() throws Exception { ModelAndView mv = new ModelAndView("redirect:/outer.jsp") .addObject("show","重定向跳转到页面,通过ModelAndView中的Model携带数据."); return mv; }}
- 访问路径
http://localhost:8080/SpringMVCPrimary/ResourceDeal/outer.do
- 注意事项(页面显示中文乱码解决)
使用tomcat测试,出现中文乱码问题:经过分析,应该是Tomcat在解析参数的时候没有使用正确的编码格式(UTF-8)去解码。查看$TOMCAT_HOME/webapps/docs/config/http.html这个说明文档,有如下说明:URIEncoding:This specifies the character encoding used to decode the URI bytes, after %xx decoding the URL. If not specified, ISO-8859-1 will be used.也就是说,如果没有设置URIEncoding, Tomcat默认是按ISO-8859-1进行URL解码,ISO-8859-1并未包括中文字符,这样的话中文字符肯定就不能被正确解析了。 解决办法:修改Tomcat的Server.xml,在Connector标签中加上URLEncoding参数:
B.通过HttpSession携带数据
- 将inner.jsp更名outer.jsp页面放到项目根路径下(/outer.jsp)
${show }
- 定义处理器
@Controller@RequestMapping("/ResourceDeal")public class ResourceDealController { /** * 重定向:跳转到页面 * 通过ModelAndView中的Model携带数据 */ @RequestMapping(value="/outer.do",produces="text/html; charset=UTF-8") public ModelAndView toOuter() throws Exception { ModelAndView mv = new ModelAndView("redirect:/outer.jsp") .addObject("show","重定向跳转到页面,通过ModelAndView中的Model携带数据."); return mv; }}
- 访问路径
http://localhost:8080/SpringMVCPrimary/ResourceDeal/session.do
1.2) 重定向到其它Controller
关于重定向到其它Controller时,携带参数可以采用前面的方式。而对于接受这些参数可以逐个接收也可以整体接收。
A.通过ModelAndView中的Model携带数据
目标Controller接收参数时
逐个接收:要保证目标Controller的方法形参名称与发送Controller发送的参数名称保持相同即可。整体接收:要保证参数名称与目标Controller接收参数类型的属性名相同即可。
- 将inner.jsp更名outer.jsp页面放到项目根路径下(/outer.jsp)
${show }
- 定义实体类(整体接收参数用)
//教育程度public class Educational { private String schoolName;//学校名称 //setter and getter and toString}
- 定义处理器
/** * 重定向到其它Controller * 通过ModelAndView中的Model携带数据 */@RequestMapping(value="/redirectModel.do")public ModelAndView redirectModel() throws Exception { ModelAndView mv = new ModelAndView("redirect:/ResourceDeal/redirectModelOuter.do") .addObject("schoolName", "大学"); return mv;}//单个参数接收@RequestMapping(value="/redirectModelOuter.do")public ModelAndView redirectModelOuter(String schoolName) throws Exception { ModelAndView mv = new ModelAndView("forward:/outer.jsp") .addObject("show", "schoolName:"+schoolName); return mv;}//整体参数接收/*@RequestMapping(value="/redirectModelOuter.do")public ModelAndView redirectModelOuter(Educational educational) throws Exception { ModelAndView mv = new ModelAndView("forward:/outer.jsp") .addObject("show", "schoolName:"+educational.getSchoolName()); return mv;}*/
- 访问路径
http://localhost:8080/SpringMVCPrimary/ResourceDeal/redirectModel.do
B.通过HttpSession携带数据
- 将inner.jsp更名outer.jsp页面放到项目根路径下(/outer.jsp)
${show }
- 定义处理器
@Controller@RequestMapping("/ResourceDeal")public class ResourceDealController { /** * 重定向到其它Controller * 通过HttpSession携带数据 */ @RequestMapping(value="/redirectHttpSession.do") public ModelAndView redirectHttpSession(HttpSession session) throws Exception { session.setAttribute("school", "清华大学"); ModelAndView mv = new ModelAndView("redirect:/ResourceDeal/redirectHttpSessionOuter.do"); return mv; } @RequestMapping(value="/redirectHttpSessionOuter.do") public ModelAndView redirectModelOuter(HttpSession session) throws Exception { ModelAndView mv = new ModelAndView("forward:/outer.jsp") .addObject("show", "schoolName:"+session.getAttribute("school")); return mv; }}
- 访问路径
http://localhost:8080/SpringMVCPrimary/ResourceDeal/redirectHttpSession.do