spring-模型数据和视图---视图解析器的说明以及大量代码演示
目录
spring-模型数据
● 说明
应用实例需求
创建后面所有代码执行成功之后跳转的vote_ok.jsp页面
方式 1: 通过 HttpServletRequest放入 request 域
创建 Master类
创建Pet类
创建model_data.jsp
修改 VoteHandler增加方法
创建vote_ok.jsp, 显示数据
完成测试(Postman 测试)
方式 2: 通过请求的方法参数 Map放入 request,object>
修改 model_data.jsp, 增加代码
修改 VoteHandler.java增加方法
完成测试(Postman 测试)
方式 3: 通过返回 ModelAndView 对象 实现 request 域数据
修改 model_data.jsp, 增加代码
修改 VoteHandler.java 增加方法
完成测试(Postman 测试)
使用注意事项
模型数据处理-数据放入 session
● 说明
修改 model_data.jsp, 增加代码
修改 VoteHandler.java 增加方法
修改vote_ok.jsp增加代码
完成测试(Postman 测试)
@ModelAttribute 实现 prepare 方法
● 基本说明
修改 VoteHandler 增加方法 并测试
@ModelAttribute 最佳实践
视图和视图解析器
基本介绍
自定义视图
为什么需要自定义视图
自定义视图实例-代码实现
配置 springDispatcherServlet-servlet.xml , 增加自定义视图解析器
创建MyView.java -自定义视图类
解读
注意
创建GoodsHandler.java类
创建view.jsp类
创建/WEB-INF/pages/my_view.jsp类
完成测试(Postman 测试)
自定义视图-小结
自定义视图-工作流程
目标方法直接指定转发或重定向
目标方法中指定转发或者重定向
● 应用实例-代码实现
修改 GoodsHandler.java, 增加方法 order()
请求转发到
直接指定要重定向的页面
修改view.jsp
完成测试(页面测试)
编辑
完成测试(Postman 测试)
综合代码演示
完成一个简单的用户登录案例
login.jsp
login_ok.jsp
login_error.jsp
User.java
LoginHandler.java
spring-模型数据
● 说明
模型数据处理-数据放入 request
开发中, 控制器/处理器中获取的数据如何放入 request 域,然后在前端(VUE/JSP/...) 取出显示
应用实例需求
创建后面所有代码执行成功之后跳转的vote_ok.jsp页面
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>vote_ok </title>
</head>
<body>
<h1>获取的的数据显示页面</h1>
<hr>
取出 request域的数据-通过前面讲解的el表达式来获取即可
<br>
address: ${requestScope.address}<br>
主人名字= ${requestScope.master.name}
主人id= ${requestScope.master.id}
宠物名字= ${requestScope.master.pet.name}
</body>
</html>
方式 1: 通过 HttpServletRequest放入 request 域
创建 Master类
public class Master {
private Integer id;
private String name;
private Pet pet;//对象的属性是另外一个对象[涉及级联]
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Pet getPet() {
return pet;
}
public void setPet(Pet pet) {
this.pet = pet;
}
@Override
public String toString() {
return "Master{" +
"id=" + id +
", name='" + name + '\'' +
", pet=" + pet +
'}';
}
}
创建Pet类
public class Pet {
private Integer id;
private String name;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "Pet{" +
"id=" + id +
", name='" + name + '\'' +
'}';
}
}
创建model_data.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>测试 模型数据</title>
</head>
<body>
<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>
</body>
</html>
修改 VoteHandler增加方法
解读
1. 演示将提交的数据->springmvc封装到java对象->springmvc 会自动的将其放入到request域
2. 这样我们就可以在跳转到的页面取出数据.
@RequestMapping("/vote")
@Controller
public class VoteHandler {
@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";
}
}
创建vote_ok.jsp, 显示数据
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>vote_ok </title>
</head>
<body>
<h1>获取的的数据显示页面</h1>
<hr>
取出 request域的数据-通过前面讲解的el表达式来获取即可
<br>
address: ${requestScope.address}<br>
主人名字= ${requestScope.master.name}
主人id= ${requestScope.master.id}
宠物名字= ${requestScope.master.pet.name}
</body>
</html>
完成测试(Postman 测试)
方式 2: 通过请求的方法参数 Map<String,Object>放入 request
修改 model_data.jsp, 增加代码
<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>
修改 VoteHandler.java增加方法
解读
1. 需求是通过map对象,添加属性到request中
2. 原理分析:springmvc会遍历map,然后将map的k-v, 存放到request域
@RequestMapping("/vote")
@Controller
public class VoteHandler {
//演示通过Map<String,Object> 设置数据到request域
@RequestMapping(value = "/vote06")
public String test06(Master master, Map<String, Object> map) {
System.out.println("------test06-----");
//解读
//1. 需求是通过map对象,添加属性到request中
//2. 原理分析:springmvc会遍历map,然后将map的k-v, 存放到request域
map.put("address", "beijing...");
//map.put("master", null);
//返回到一个结果
return "vote_ok";
}
}
完成测试(Postman 测试)
方式 3: 通过返回 ModelAndView 对象 实现 request 域数据
修改 model_data.jsp, 增加代码
<br/><hr/>
<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>
修改 VoteHandler.java 增加方法
@RequestMapping("/vote")
@Controller
public class VoteHandler {
// 演示通过返回ModelAndView对象,将数据放入到request域
@RequestMapping(value = "/vote07")
public ModelAndView test07(Master master) {
System.out.println("----test07----");
ModelAndView modelAndView = new ModelAndView();
//放入属性到modelAndView对象
modelAndView.addObject("address", "shanghai");
//modelAndView.addObject("master", null);
//可以把从数据库得到的数据->对象-》放入modelAndView[Service-dao-db]
//这里指定跳转的视图名称
modelAndView.setViewName("vote_ok");
//返回结果
return modelAndView;
}
}
完成测试(Postman 测试)
使用注意事项
1) 从本质看
请求响应的方法 return "xx", 是返回了一个字符串,其实本质是返回了一个ModelAndView 对象,只是默认被封装起来的.
2) ModelAndView 即可以包含 model 数据,也可以包含视图信息
3) ModelAndView 对象的 addObject 方法可以添加 key-val 数据,默认在 request 域中
4) ModelAndView 对象 setView 方法可以指定视图名称
模型数据处理-数据放入 session
● 说明
开发中, 控制器/处理器中获取的数据如何放入 session 域,然后在前端(VUE/JSP/...)取出显示
修改 model_data.jsp, 增加代码
<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>
修改 VoteHandler.java 增加方法
@RequestMapping("/vote")
@Controller
public class VoteHandler {
@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";//请求转发
}
}
修改vote_ok.jsp增加代码
<hr>
取出 session域的数据 <br>
address: ${sessionScope.address}<br>
主人名字= ${sessionScope.master.name}
主人信息= ${sessionScope.master}
完成测试(Postman 测试)
@ModelAttribute 实现 prepare 方法
● 基本说明
开发中,有时需要使用某个前置方法(比如 prepareXxx(), 方法名由程序员定)给目标方法准备一个模型对象
1. @ModelAttribute 注解可以实现 这样的需求
2. 在某个方法上,增加了@ModelAttribute 注解后
3. 那么在调用该 Handler 的任何一个方法时,都会先调用这个方法
修改 VoteHandler 增加方法 并测试
@RequestMapping("/vote")
@Controller
public class VoteHandler {
@ModelAttribute
public void prepareModel(){
System.out.println("prepareModel()-----完成准备工作-----");
}
}
@ModelAttribute 最佳实践
● 修改用户信息(就是经典的使用这种机制的应用),流程如下:
1. 在修改前,在前置方法中从数据库查出这个用户
2. 在修改方法(目标方法)中,可以使用前置方法从数据库查询的用户
3. 如果表单中对用户的某个属性修改了,则以新的数据为准,如果没有修改,则以数据库的信息为准,比如,用户的某个属性不能修改,就保持原来的值
视图和视图解析器
基本介绍
1. 在 springMVC 中的目标方法最终返回都是一个视图(有各种视图)
2. 返回的视图都会由一个视图解析器来处理 (视图解析器有很多种)
自定义视图
为什么需要自定义视图
1. 在默认情况下,我们都是返回默认的视图, 然后这个返回的视图交由 SpringMVC 的InternalResourceViewResolver 视图处理器来处理的
2. 在实际开发中,我们有时需要自定义视图,这样可以满足更多更复杂的需求
自定义视图实例-代码实现
配置 springDispatcherServlet-servlet.xml , 增加自定义视图解析器
解读
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>
创建MyView.java -自定义视图类
解读
1. MyView继承了AbstractView, 就可以作为一个视图使用
2. @Component(value = "myView"),该视图会注入到容器中, 名字/id是 myView
@Component(value = "hspView")
public class MyView extends AbstractView {
@Override
protected void renderMergedOutputModel(Map<String, Object> model,
HttpServletRequest request,
HttpServletResponse response) throws Exception {
//完成视图渲染
//并且可以确定我们要跳转的页面 [请求转发] /WEB-INF/pages/my_view.jsp
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);
}
}
注意
1. 下面就是进行请求转发到 /WEB-INF/pages/my_view.jsp
2. /WEB-INF/pages/my_view.jsp 会被springmvc解析 /springmvc/WEB-INF/pages/my_view.jsp
3.最后浏览器解析成http://localhost:8080 /springmvc/WEB-INF/pages/my_view.jsp
创建GoodsHandler.java类
@RequestMapping("/goods")
@Controller
public class GoodsHandler {
@RequestMapping(value = "/buy")
public String buy() {
System.out.println("------buy()-----");
return "myView";
}
}
创建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/>
</body>
</html>
创建/WEB-INF/pages/my_view.jsp类
<%@ 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>
完成测试(Postman 测试)
自定义视图-小结
1. 自定义视图: 创建一个 View 的 bean, 该 bean 需要继承自 AbstractView, 并实现renderMergedOutputModel 方法。
2. 并把自定义 View 加入到 IOC 容器中
3. 自定义视图的视图处理器,使用 BeanNameViewResolver, 这个视图处理器也需要配置到 ioc 容器
4. BeanNameViewResolver 的调用优先级需要设置一下,设置 order 比 Integer.MAX_VAL小的值. 以确保其在 InternalResourceViewResolver 之前被调用
自定义视图-工作流程
1. SpringMVC 调用目标方法, 返回自定义 View 在 IOC 容器中的 id
2. SpringMVC 调用 BeanNameViewResolver 解析视图: 从 IOC 容器中获取 返回 id 值对应的 bean, 即自定义的 View 的对象
3. SpringMVC 调用自定义视图的 renderMergedOutputModel 方法渲染视图
4. 说明: 如果在 SpringMVC 调用目标方法, 返回自定义 View 在 IOC 容器中的 id,不存在, 则仍然按照默认的视图处理器机制处理
目标方法直接指定转发或重定向
目标方法中指定转发或者重定向
1. 默认返回的方式是请求转发,然后用视图处理器进行处理,比如在目标方法中这样写:
2. 也可以在目标方法直接指定重定向或转发的 url 地址
3. 如果指定重定向,不能定向到 /WEB-INF 目录中
● 应用实例-代码实现
修改 GoodsHandler.java, 增加方法 order()
请求转发到
/WEB-INF/pages/my_view.jsp
下面的 /WEB-INF/pages/my_view.jsp 被解析成 /springmvc/WEB-INF/pages/my_view.jsp
return "forward:/WEB-INF/pages/my_view.jsp";
直接指定要重定向的页面
1. 对于重定向来说,不能重定向到 /WEB-INF/ 目录下
2. redirect 关键字,表示进行重定向
3. /login.jsp 在服务器解析 /springmvc/login.jsp
@RequestMapping("/goods")
@Controller
public class GoodsHandler {
/**
* 演示直接指定要请求转发的或者是重定向的页面
* @return
*/
@RequestMapping(value = "/order")
public String order() {
System.out.println("=======order()=====");
// return "forward:/WEB-INF/pages/my_view.jsp";
// return "forward:/aaa/bbb/ok.jsp";
return "redirect:/login.jsp";
}
}
修改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>
完成测试(页面测试)
完成测试(Postman 测试)
综合代码演示
完成一个简单的用户登录案例
1) 编写登录页面 login.jsp
2) LoginHandler [doLogin 方法], 如果用户输入用户名是 wyx, 密码 123 就可以登录成功.
3) 创建 JavaBean : User.java
4) 表单提交数据到 doLogin 方法, 以 User 对象形式接收.
5) 登录成功到, 页面 login_ok.jsp 并显示登录欢迎信息
6) 登录失败, 到页面 login_error.jsp
login.jsp
<form action="login">
u:<input name="username" type="text"> <br/>
p:<input name="password" type="password"><br/>
<input type="submit" value="登录">
</form>
</body>
</html>
login_ok.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>登录成功</title>
</head>
<h1>登录成功</h1>
欢迎你: ${requestScope.user.username}
<body>
</body>
</html>
login_error.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>登录失败</title>
</head>
<body>
<h1>登录失败</h1>
<a href="<%=request.getContextPath()%>/homework/login.jsp">返回重新登录</a>
</body>
</html>
1. 这里考察web工程路径的知识点 如果忘记了 可以去看我的博客 链接
2. <%=request.getContextPath()%>/homework/login.jsp
服务器解析 /springmvc/homework/login.jsp
3. 浏览器会解析 为 http://localhost:8080/springmvc/homework/login.jsp
User.java
public class User {
//属性..
private String username;
private String password;
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}
LoginHandler.java
@RequestMapping("/user")
@Controller
public class LoginHandler {
//处理登录
@RequestMapping(value = "/login")
public String doLogin(User user) {
//判断
if("wyx".equals(user.getUsername())
&& "123".equals(user.getPassword())){
//验证OK
return "forward:/WEB-INF/pages/homework/login_ok.jsp";
} else {
return "forward:/WEB-INF/pages/homework/login_error.jsp";
}
}
}