说明:开发中, 控制器/处理器中获取的数据如何放入 request 域,然后在前端(VUE/JSP/...)取出显 示
(1)前端发送请求
- <h1>添加主人信息</h1>
- <form action="vote/vote05" method="post">
- 主人号:<input type="text" name="id"><br>
- 主人名:<input type="text" name="name"><br>
- 宠物号:<input type="text" name="pet.id"><br>
- 宠物名:<input type="text" name="pet.name"><br>
- <input type="submit" value="添加主人和宠物">
- </form>
(2)后端接收请求
springmvc会自动把获取的model模型,放入到request域中
- /**
- * 1. 将提交的数据封装到java对象->springmvc 会自动的将其放入到request域
- * 2. 这样我们就可以在跳转到的页面取出数据.
- */
- @RequestMapping(value = "/vote05")
- public String test05(Master master, HttpServletRequest request) {
-
- //1. springmvc会自动把获取的model模型,放入到request域中,名字就是master
- //2. 也可以手动将master放入到request
- request.setAttribute("address", "beijing");
- //3. 如果我们希望修改master的属性值
- master.setName("nono");
- //4. 分析一下springmvc默认存放对象到request域中,属性名是
- // request域 ("master", master) 属性名是类名/类型名 首字母小写
- //返回到一个结果
- return "vote_ok";
- }
(3)跳转页面
- <h1>获取的的数据显示页面</h1>
- <hr>
- 取出 request域的数据-通过 el表达式来获取
- <br>
- address: ${requestScope.address}<br>
- 主人名字= ${requestScope.master.name}
- 主人id= ${requestScope.master.id}
- 宠物名字= ${requestScope.master.pet.name}
(4)页面显示结果
(1)前端发送请求
- <h1>添加主人信息[测试 Map ]</h1>
- <form action="vote/vote06" method="post">
- 主人号:<input type="text" name="id"><br>
- 主人名:<input type="text" name="name"><br>
- 宠物号:<input type="text" name="pet.id"><br>
- 宠物名:<input type="text" name="pet.name"><br>
- <input type="submit" value="添加主人和宠物">
- </form>
(2)后端接收请求
- /**
- * 通过Map
设置数据到request域 - */
- @RequestMapping(value = "/vote06")
- public String test06(Master master, Map<String, Object> map) {
- //1. 需求是通过map对象,添加属性到request中
- //2. 原理分析:springmvc会遍历map,然后将map的k-v, 存放到request域
- map.put("address", "beijing...");
- //返回到一个结果
- return "vote_ok";
- }
(3)跳转页面同方式1
(4)页面显示结果
(1)前端发送请求
- <h1>添加主人信息[测试ModelAndView]</h1>
- <form action="vote/vote07" method="post">
- 主人号:<input type="text" name="id"><br>
- 主人名:<input type="text" name="name"><br>
- 宠物号:<input type="text" name="pet.id"><br>
- 宠物名:<input type="text" name="pet.name"><br>
- <input type="submit" value="添加主人和宠物">
- </form>
(2)后端接收请求
说明:
- /**
- * 通过返回ModelAndView对象,将数据放入到request域
- */
- @RequestMapping(value = "/vote07")
- public ModelAndView test07(Master master) {
-
- System.out.println("----test07----");
- ModelAndView modelAndView = new ModelAndView();
- //放入属性到modelAndView对象
- modelAndView.addObject("address", "shanghai");
- //可以把从数据库得到的数据->对象,放入modelAndView
- //这里指定跳转的视图名称
- modelAndView.setViewName("vote_ok");
- //返回结果
- return modelAndView;
- }
(3)跳转页面同方式1
(4)页面显示结果
说明:开发中, 控制器/处理器中获取的数据如何放入 session 域,然后在前端(VUE/JSP/...)取出显 示
应用实例:
(1)前端发送请求
- <h1>添加主人信息[测试session]</h1>
- <form action="vote/vote08" method="post">
- 主人号:<input type="text" name="id"><br>
- 主人名:<input type="text" name="name"><br>
- 宠物号:<input type="text" name="pet.id"><br>
- 宠物名:<input type="text" name="pet.name"><br>
- <input type="submit" value="添加主人和宠物">
- </form>
(2)后端接收请求
- /**
- * 将数据设置到session域中
- */
- @RequestMapping(value = "/vote08")
- public String test08(Master master, HttpSession httpSession) {
- System.out.println("----test08----");
- //master对象是默认放在request域
- //这里将master对象放入到session域
- httpSession.setAttribute("master", master);
- httpSession.setAttribute("address", "guangzhou");
- return "vote_ok";//请求转发
- }
(3)跳转页面
- 取出 session域的数据 <br>
- address: ${sessionScope.address}<br>
- 主人名字= ${sessionScope.master.name}
- 主人信息= ${sessionScope.master}
(4)页面显示结果
说明:开发中,有时需要使用某个前置方法(比如 prepareXxx(), 方法名由程序员定)给目标方法准 备一个模型对象
@ModelAttribute 注解可以实现 这样的需求,在某个方法上,增加了@ModelAttribute 注解后 那么在调用该 Handler 的任何一个方法时,都会先调用这个方法
案例:
- /**
- * 1. 当Handler的方法被标识 @ModelAttribute,就视为一个前置方法
- * 2. 当调用该Handler的其它的方法时,都会先执行该前置方法
- * 3. 类似Spring中AOP的前置通知[底层是AOP机制]
- * 4. prepareModel前置方法,会切入到其它方法前执行
- */
- @ModelAttribute
- public void prepareModel(){
- System.out.println("prepareModel()-----完成准备工作-----");
- }
使用场景举例:
修改用户信息(就是经典的使用这种机制的应用),流程如下:
1. 在修改前,在前置方法中从数据库查出这个用户
2. 在修改方法(目标方法)中,可以使用前置方法从数据库查询的用户
3. 如果表单中对用户的某个属性修改了,则以新的数据为准,如果没有修改,则以数据库 的信息为准,比如,用户的某个属性不能修改,就保持原来的值
(1)在 springMVC 中的目标方法最终返回都是一个视图(有各种视图).
(2)返回的视图都会由一个视图解析器来处理 (视图解析器有很多种)
(1)在默认情况下,我们都是返回默认的视图, 然后这个返回的视图交由 SpringMVC 的 InternalResourceViewResolver 视图处理器来处理的
- <!--下面配置springMVC的视图解析器,如果我们的controller return 的是 login_ok
- 那么要跳转的页面页面就是 /WEB-INF/pages/login_ok-->
- <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
- <!--配置属性suffix(后缀) 和 prefix(前缀)-->
- <property name="prefix" value="/WEB-INF/pages/"/>
- <property name="suffix" value=".jsp"/>
- </bean>
(2)在实际开发中,我们有时需要自定义视图,这样可以满足更多更复杂的需求.
(1)配置 applicationContext-mvc, 增加自定义视图解析器
- <!--
- 1. 配置自定义视图解析器BeanNameViewResolver
- 2. BeanNameViewResolver可以去解析我们自定义的视图
- 3. 配置 属性 order, 表示视图解析器执行的顺序, 值越小, 优先级越高
- 4. 属性 order 的默认值是最低优先级 ,值为 Integer.MAX_VALUE
- int LOWEST_PRECEDENCE = 2147483647
- -->
- <bean class="org.springframework.web.servlet.view.BeanNameViewResolver">
- <property name="order" value="99"/>
- </bean>
(2)创建 MyView.java - 自定义视图类
- package com.web.viewresolver;
-
- import org.springframework.stereotype.Component;
- import org.springframework.web.servlet.view.AbstractView;
-
- import javax.servlet.http.HttpServletRequest;
- import javax.servlet.http.HttpServletResponse;
- import java.util.Map;
-
- /**
- * 1. MyView继承了AbstractView, 就可以作为一个视图使用
- * 2. @Component(value = "myView"),该视图会注入到容器中, 名字/id是 myView
- */
- @Component(value = "myView")
- public class MyView extends AbstractView {
- @Override
- protected void renderMergedOutputModel(Map<String, Object> model,
- HttpServletRequest request,
- HttpServletResponse response) throws Exception {
- //完成视图渲染
- //并且可以确定我们要跳转的页面 [请求转发]
- System.out.println("进入到自己的视图..");
-
- //1. 下面就是进行请求转发到 /WEB-INF/pages/my_view.jsp
- //2. /WEB-INF/pages/my_view.jsp 会被springmvc解析成 /springmvc/WEB-INF/pages/my_view.jsp
- request.getRequestDispatcher("/WEB-INF/pages/my_view.jsp")
- .forward(request, response);
-
- }
- }
(3)创建 GoodsHandler.java
- @RequestMapping("/goods")
- @Controller
- public class GoodsHandler {
-
- @RequestMapping(value = "/buy")
- public String buy() {
- System.out.println("------buy()-----");
- // 这里返回自定义视图类在容器中的名字/id
- return "myView";
- }
- }
(4)创建 web\view.jsp 和 /WEB-INF/pages/my_view.jsp
- <%@ page contentType="text/html;charset=UTF-8" language="java" %>
- <html>
- <head>
- <title>自定义视图测试</title>
- </head>
- <body>
- <h1>自定义视图测试</h1>
- <a href="goods/buy">点击到自定义视图-</a><br/>
- <a href="goods/order">测试在目标方法中指定请求转发或者重定向的页面-</a><br/>
- </body>
- </html>
- <%@ page contentType="text/html;charset=UTF-8" language="java" %>
- <html>
- <head>
- <title>my_view页面</title>
- </head>
- <h1>进入到my_view页面</h1>
- <p>是从自定义视图来的..</p>
- <body>
-
- </body>
- </html>
(5)效果如下
初始页面:
跳转页面:
自定义视图-小结
自定义视图-工作流程
(1)默认返回的方式是请求转发,然后用视图处理器进行处理,比如在目标方法中这样写:
- @RequestMapping(value = "/login")
- public String login(){
- System.out.println("login ok....");
- return "login_ok";
- }
(2)也可以在目标方法直接指定重定向或转发的 url 地址
(3)如果指定重定向,不能定向到 /WEB-INF 目录中,因为这个目录是tomcat的一个类路径
(1)修改 GoodsHandler.java, 增加方法 order()
- /**
- * 演示直接指定要请求转发的或者是重定向的页面
- */
- @RequestMapping(value = "/order")
- public String order() {
- System.out.println("=======order()=====");
- //请求转发到 /WEB-INF/pages/my_view.jsp
- //forward 关键字表示请求转发
- //请求转发可以到/WEB-INF/ 目录下,也可以转发到这个目录外面的页面
- //下面的 /WEB-INF/pages/my_view.jsp 会被解析成 /springmvc/WEB-INF/pages/my_view.jsp
- //return "forward:/WEB-INF/pages/my_view.jsp"; // 等价于 return "my_view.jsp"
- //请求转发到/WEB-INF/目录外面的页面
- //return "forward:/aaa/bbb/ok.jsp";
-
- //直接指定要重定向的页面
- //1. 对于重定向来说,可以重定向到web目录,不能重定向到 /WEB-INF/ 目录下
- //2. redirect 关键字,表示进行重定向
- //3. /login.jsp 在服务器解析 /springmvc/login.jsp
- return "redirect:/login.jsp";
-
- // /WEB-INF/pages/my_view.jsp 被解析 /springmvc/WEB-INF/pages/my_view.jsp 该路径是访问不到的
- //return "redirect:/WEB-INF/pages/my_view.jsp";//这样写会报错
- }
(2)前端发出请求
<a href="goods/order">测试在目标方法中指定请求转发或者重定向的页面-</a><br/>
(3)跳转页面
- <%@ page contentType="text/html;charset=UTF-8" language="java" %>
- <html>
- <head>
- <title>登录成功</title>
- </head>
- <body>
- <h1>恭喜 登录成功</h1>
- </body>
- </html>
(4)跳转成功