视图和视图解析器
2023年11月15日大约 7 分钟约 1416 字
基本介绍
- 在 springMVC 中的目标方法最终返回都是一个视图(有各种视图)。
- 返回的视图都会由一个视图解析器来处理 (视图解析器有很多种)。
自定义视图
为什么需要自定义视图
在默认情况下,我们都是返回默认的视图, 然后这个返回的视图交由 SpringMVC 的 InternalResourceViewResolver 视图处理器来处理的。
在实际开发中,我们有时需要自定义视图,这样可以满足更多更复杂的需求。
代码实现
配置 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
package com.lzw.web.viewsolver;
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;
/**
* @author LiAng
* 1. MyView继承了AbstractView, 就可以作为一个视图使用
* 2. @Component(value = "lzwView"),该视图会注入到容器中, 名字/id是 lzwView
*/
@Component(value = "lzwView")
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);
}
}
创建 GoodsHandler.java
package com.lzw.web.viewsolver;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
/**
* @author LiAng
*/
@RequestMapping("/goods")
@Controller
public class GoodsHandler {
@RequestMapping(value = "/buy")
public String buy(){
System.out.println("-----buy()-----");
return "lzwView";
}
}
创建 web\view.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>my_view页面</title>
</head>
<body>
<h1>进入到my_view页面</h1>
<p>从自定义视图来的。。</p>
</body>
</html>
完成测试
自定义视图工作流程小结
- 自定义视图:创建一个 View 的 bean,该 bean 需要继承自 AbstractView,并实现 renderMergedOutputModel 方法。
- 并把自定义 View 加入到 IOC 容器中。
- 自定义视图的视图处理器,使用 BeanNameViewResolver, 这个视图处理器也需要配置 到 IOC 容器。
- BeanNameViewResolver 的调用优先级需要设置一下,设置 order 比 Integer.MAX_VAL 小的值,以确保其在 InternalResourceViewResolver 之前被调用。
自定义视图-工作流程
- SpringMVC 调用目标方法,返回自定义 View 在 IOC 容器中的 id 。
- SpringMVC 调用 BeanNameViewResolver 解析视图:从 IOC 容器中获取 返回 id 值对应的 bean,即自定义的 View 的对象。
- SpringMVC 调用自定义视图的 renderMergedOutputModel 方法渲染视图 。
- 如果在 SpringMVC 调用目标方法,返回自定义 View 在 IOC 容器中的 id,不存在,则仍然按照默认的视图处理器机制处理。
目标方法直接指定转发或重定向
使用实例
目标方法中指定转发或者重定向。
- 默认返回的方式是请求转发,然后用视图处理器进行处理,比如在目标方法中这样写:

- 也可以在目标方法直接指定重定向或转发的 url 地址。
- 如果指定重定向,不能定向到 /WEB-INF 目录中。
代码实现
修改 GoodsHandler.java
/**
* 演示直接指定要请求转发的或者是重定向的页面
*/
@RequestMapping(value = "/order")
public String order(){
System.out.println("-----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";
//return "forward:/aa/bb/ok.jsp";
//直接指定要重定向的页面
//1. 对于重定向来说,不能重定向到 /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";
}
修改 view.jsp
<a href="goods/order">测试在目标方法中指定请求转发或者重定向到页面</a>
完成测试
作业
完成一个简单的用户登录案例
- 编写登录页面 login.jsp
- LoginHandler [doLogin 方法],如果用户输入用户名是 lzw,密码 123 就可以登录成功
- 创建 JavaBean:User.java
- 表单提交数据到 doLogin 方法,以 User 对象形式接收
- 登录成功到页面 login_ok.jsp 并显示登录欢迎信息
- 登录失败,到页面 login_error.jsp, 并给出重新登录的超链接
代码实现
创建 login.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>登录</title>
</head>
<body>
<h3>登录页面</h3>
<form action="<%=request.getContextPath()%>/login/doLogin method="post">
u:<input name="username" type="text"> <br/>
p:<input name="password" type="password"><br/>
<input type="submit" value="登录">
</form>
</body>
</html>
创建 User.java
package com.lzw.web.homework.entity;
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;
}
@Override
public String toString() {
return "User{" +
"username='" + username + '\'' +
", password='" + password + '\'' +
'}';
}
}
创建 LoginHandler.java
package com.lzw.web.homework;
import com.lzw.web.homework.entity.User;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
@RequestMapping("/login")
@Controller
public class LoginHandler {
@RequestMapping("/doLogin")
public String doLogin(User user){
if("lzw".equals(user.getUsername()) && "123".equals(user.getPassword())){
return "forward:/WEB-INF/pages/homework/login_ok";
}else{
return "forward:/WEB-INF/pages/homework/login_ok";
}
}
}
创建 login_ok.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>登录成功</title>
</head>
<body>
<h1>恭喜 登录成功!</h1>
<h2>欢迎${requestScope.user.username}</h2>
</body>
</html>
创建 login_error.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>登录失败</title>
</head>
<body>
<h1>登录失败</h1>
<%--
1. 这里考察 web工程路径知识点
2. <%=request.getContextPath()%>/homework/login.jsp
解析成 /springmvc/homework/login.jsp
3. 浏览器会解析 第一个 / 为 http://localhost:8080/
--%>
<a href="<%=request.getContextPath()%>/homework/login.jsp">重新登录</a>
</body>
</html>