SpringMVC-03

SpringMVC-03

10、Restful风格

10.1、Restful 风格的介绍

Restful 一种软件架构风格、设计风格,而不是标准,只是提供了一组设计原则和约束条件。它主要用于客户端和服务器交互类的软件。基于这个风格设计的软件可以更简洁,更有层次,更易于实现缓存等机制。

REST(英文:Representational State Transfer,简称REST)描述了一个架构样式的网络系统,比如 web 应用程序。它首次出现在 2000 年 Roy Fielding 的博士论文中,他是 HTTP 规范的主要编写者之一。在目前主流的三种Web服务交互方案中,REST相比于SOAP(Simple Object Access protocol,简单对象访问协议)以及XML-RPC更加简单明了,无论是对URL的处理还是对Payload的编码,REST都倾向于用更加简单轻量的方法设计和实现。值得注意的是REST并没有一个明确的标准,而更像是一种设计的风格。

####原则条件

REST 指的是一组架构约束条件和原则。满足这些约束条件和原则的应用程序或设计就是 RESTful。

Web 应用程序最重要的 REST 原则是,客户端和服务器之间的交互在请求之间是无状态的。从客户端到服务器的每个请求都必须包含理解请求所必需的信息。如果服务器在请求之间的任何时间点重启,客户端不会得到通知。此外,无状态请求可以由任何可用服务器回答,这十分适合云计算之类的环境。客户端可以缓存数据以改进性能。

在服务器端,应用程序状态和功能可以分为各种资源。资源是一个有趣的概念实体,它向客户端公开。资源的例子有:应用程序对象、数据库记录、算法等等。每个资源都使用 URI (Universal Resource Identifier) 得到一个唯一的地址。所有资源都共享统一的接口,以便在客户端和服务器之间传输状态。使用的是标准的 HTTP 方法,比如 GET、PUT、POST 和 DELETE。Hypermedia 是应用程序状态的引擎,资源表示通过超链接互联。

干货(简单明了):

Restful是一种设计风格。对于我们Web开发人员来说。就是使用一个url地址表示一个唯一的资源。然后把原来的请求参数加入到请求资源地址中。然后原来请求的增,删,改,查操作。改为使用HTTP协议中请求方式GET、POST、PUT、DELETE表示。

1、把请求参数加入到请求的资源地址中

2、原来的增,删,改,查。使用HTTP请求方式,POST、DELETE、PUT、GET分别一一对应。

10.2、如何学习restful风格,这里需要明确两点

10.2.1、就是把传统的请求参数加入到请求地址是什么样子?

传统的方式是:

比如:http://ip:port/工程名/资源名?请求参数

举例:http://127.0.0.1:8080/springmvc/book?action=delete&id=1

restful风格是:

比如:http://ip:port/工程名/资源名/请求参数/请求参数

举例:http://127.0.0.1:8080/springmvc/book/1

请求的动作删除由请求方式delete决定

10.2.2、restful风格中请求方式GET、POST、PUT、DELETE分别表示查、增、改、删

GET请求 对应 查询

​ http://ip:port/工程名/book/1 HTTP请求GET 表示要查询id为1的图书

​ http://ip:port/工程名/book HTTP请求GET 表示查询全部的图书

POST请求 对应 添加

​ http://ip:port/工程名/book HTTP请求POST 表示要添加一个图书

PUT请求 对应 修改

​ http://ip:port/工程名/book/1 HTTP请求PUT 表示要修改id为1的图书信息

DELETE请求 对应 删除

​ http://ip:port/工程名/book/1 HTTP请求DELETE 表示要删除id为1的图书信息

10.2.3、SpringMVC中如何发送GET请求、POST请求、PUT请求、DELETE请求。

我们知道发起GET请求和POST请求,只需要在表单的form标签中,设置method=”get” 就是GET请求。

设置form标签的method=”post”。就会发起POST请求。而PUT请求和DELETE请求。要如何发起呢。

1、要有post请求的form标签

2、在form表单中,添加一个额外的隐藏域_method=”PUT”或_method=”DELETE”

3、在web.xml中配置一个Filter过滤器org.springframework.web.filter.HiddenHttpMethodFilter(注意,这个Filter一定要在处理乱码的Filter后面)

10.3、Restful风格的crud如何实现

表单:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
<body>
<%-- 查id为1的图书 --%>
<a href="${pageContext.request.contextPath}/book/1">查询id为1的图书</a> <br>
<a href="${pageContext.request.contextPath}/book">查询全部图书</a> <br>
<form action="${pageContext.request.contextPath}/book" method="post">
<input type="submit" value="添加图书">
</form>

<%--
1 先有一个post表单
2 在表单中有一个隐藏域,name值是:_method,value是:PUT( put请求,值是put,delete请求,值是DELETE )
3 在服务器中,配置一个支持restful风格请求的Filter( 将请求参数_method=put改为put请求 )
--%>
<form action="${pageContext.request.contextPath}/book/1" method="post">
<input type="hidden" name="_method" value="PUT">
<input type="submit" value="修改图书">
</form>


<form action="${pageContext.request.contextPath}/book/1" method="post">
<input type="hidden" name="_method" value="DELETE">
<input type="submit" value="删除图书">
</form>

</body>

BookController代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
package com.atguigu.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

@Controller
public class BookController {

@RequestMapping(value = "/book/1", method = RequestMethod.GET)
public String queryBookById() {
System.out.println(" 查询id为1的图书 ");
return "redirect:/index.jsp";
}

@RequestMapping(value = "/book", method = RequestMethod.GET)
public String queryBooks() {
System.out.println(" 查询全部图书 ");
return "redirect:/index.jsp";
}

@RequestMapping(value = "/book", method = RequestMethod.POST)
public String addBook() {
System.out.println("添加图书");
return "redirect:/index.jsp";
}


@RequestMapping(value = "/book/1", method = RequestMethod.PUT)
public String updateBook() {
System.out.println("修改图书");
return "redirect:/index.jsp";
}

@RequestMapping(value = "/book/1", method = RequestMethod.DELETE)
public String deleteBookById() {
System.out.println("删除图书");
return "redirect:/index.jsp";
}


}

web.xml中的配置:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0">

<servlet>
<servlet-name>dipsatcher</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>dipsatcher</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>

<!-- 配置支持restful风格请求的Filter过滤器-->
<filter>
<filter-name>HiddenHttpMethodFilter</filter-name>
<filter-class>org.springframework.web.filter.HiddenHttpMethodFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>HiddenHttpMethodFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>


</web-app>

10.4、Restful风格在高版本Tomcat中无法转发到jsp页面

在Tomcat8之后的一些高版本,使用restful风格访问然后转发到jsp页面。就会有如下的错误提示:

JSPs only permit GET POST or HEAD

第一种解决方案: 换回低版本的Tomcat(影响性能)

第二种解决方案:isErrorPage=”true”

10.5、@PathVariable 路径参数获取

前面我们已经知道如何编写和配置restful风格的请求和控制器。

那么 现在的问题是。如何接收restful风格请求的参数。比如前面的id值。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
/**
* value = "/book/{id}"在请求地址中,{参数名} 这个参数叫路径参数 <br/>
* @PathVariable("id") 注解作用是把指定名称的路径参数值赋给方法参数id
*/
@RequestMapping(value = "/book/{id}/{abc}", method = RequestMethod.GET)
public String queryBookById(
@PathVariable("id") Integer id,
@PathVariable("abc") String abc) {

System.out.println(" 查询id为" + id + "的图书 ");
System.out.println(" abc 参数值为: " + abc);

return "redirect:/index.jsp";
}

11、Restful风格实现的CRUD图书

把前面的传统请求方式的图书的CRUD换成刚刚讲的Restful风格的图书模块的CRUD。只需要修改页面端的请求方式和地址,以及服务器端Controller的接收。

11.2、列表功能实现

记得删除BookController类上的@RequestMapping注解

Controller中的修改:

1
2
3
4
5
6
7
8
9
10
11
12
/**
* 查询全部图书
*/
@RequestMapping(value = "/book",method = RequestMethod.GET)
public String queryAll(Map<String, Object> map) {
// 调用xxxService.xxx()查询全部图书
List<Book> books = bookService.queryBooks();
// 保存到Request域中
map.put("books", books);
// 请求转发到,/book/bookList.jsp
return "bookList";
}

页面端的修改:

11.4、添加功能实现

Controller中的代码:

1
2
3
4
5
6
7
8
9
10
/**
* 添加图书restful
*/
@RequestMapping(value = "/book",method = RequestMethod.POST)
public String add(Book book) {
// 调用bookService.add()
bookService.addBook(book);
// 重定向 图书列表管理页面
return "redirect:/book";
}

bookEdit.jsp页面中的修改:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32

<form action="${pageContext.request.contextPath}/book"
method="post">
<input type="hidden" name="id" value="${requestScope.book.id}">
<table>
<tr>
<td>书名</td>
<td><input name="name" type="text" value="${requestScope.book.name}"/></td>
</tr>
<tr>
<td>作者</td>
<td><input name="author" type="text" value="${requestScope.book.author}"/></td>
</tr>
<tr>
<td>价格</td>
<td><input name="price" type="text" value="${requestScope.book.price}" /></td>
</tr>
<tr>
<td>销量</td>
<td><input name="sales" type="text" value="${requestScope.book.sales}"/></td>
</tr>
<tr>
<td>库存</td>
<td><input name="stock" type="text" value="${requestScope.book.stock}" /></td>
</tr>
<tr>
<td align="center" colspan="2">
<input type="submit" />
</td>
</tr>
</table>
</form>

11.3、删除功能实现

BookController中的修改:

1
2
3
4
5
6
@RequestMapping(value = "/book/{id}",method = RequestMethod.DELETE)
public String delete(@PathVariable("id") Integer id) {
bookService.deleteBookById(id);
// 重定向 图书列表管理页面
return "redirect:/book";
}

bookList.jsp页面中的修改:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<c:forEach items="${requestScope.books}" var="book">
<tr>
<td>${book.name}</td>
<td>${book.author}</td>
<td>${book.price}</td>
<td>${book.sales}</td>
<td>${book.stock}</td>
<td>
<form action="${pageContext.request.contextPath}/book/${book.id}" method="post">
<input type="hidden" name="_method" value="DELETE" />
</form>
<a class="deleteClass" href="${pageContext.request.contextPath}/book/delete?id=${book.id}">删除</a>、
<a href="${pageContext.request.contextPath}/book/queryBookById?id=${book.id}">修改</a>
</td>
</tr>
</c:forEach>

修改确认提示代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<script type="text/javascript" src="${pageContext.request.contextPath}/script/jquery-1.7.2.js"></script>
<script type="text/javascript">
$(function () {
// 给删除绑定单击事件
$("a.deleteClass").click(function () {
// 在事件响应的function函数中,有一个this对象。这个this对象是当前正在响应事件的dom对象
var name = $(this).parent().parent().find("td:first").text();
if (confirm("你确定要删除 【" + name + "】吗?")){
// prev()取前面一个兄弟元素
// submit()是表单提交
$(this).prev("form").submit();
}
return false;
});
});
</script>

11.5、更新功能实现

更新图书分为两个步骤:

1、查询需要更新的图书,填充到更新页面

2、提交请求,发送数据给服务器更新保存修改。

11.5.1、查询需要更新的图书,填充到更新页面

BookController中的代码:

1
2
3
4
5
6
@RequestMapping(value = "/book/{id}",method = RequestMethod.GET)
public String queryBookById(@PathVariable("id") Integer id, Map<String, Object> map) {
Book book = bookService.queryBookById(id);
map.put("book", book);
return "bookEdit";
}

修改bookList.jsp页面中【修改】的请求地址:

11.5.2、提交请求,发送数据给服务器更新保存修改。

BookController中的代码:

1
2
3
4
5
6
@RequestMapping(value = "/book/{id}",method = RequestMethod.PUT)
public String update(Book book) {
bookService.updateBook(book);
// 重定向 图书列表管理页面
return "redirect:/book";
}

bookEdit.jsp页面的修改:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>图书列表</title>
<%
String basePath = request.getScheme()
+ "://"
+ request.getServerName()
+ ":"
+ request.getServerPort()
+ request.getContextPath()
+ "/";
%>
<base href="<%=basePath %>" />
</head>
<body>
<center>
<h3>添加图书</h3>
<%-- 添加需要的表单 --%>
<c:if test="${empty requestScope.book}">
<form action="${pageContext.request.contextPath}/book"
method="post">
</c:if>
<%-- 修改操作 --%>
<c:if test="${not empty requestScope.book}">
<form action="${pageContext.request.contextPath}/book/${requestScope.book.id}"
method="post">
<input type="hidden" name="id" value="${requestScope.book.id}">
<input type="hidden" name="_method" value="PUT">
</c:if>
<table>
<tr>
<td>书名</td>
<td><input name="name" type="text" value="${requestScope.book.name}"/></td>
</tr>
<tr>
<td>作者</td>
<td><input name="author" type="text" value="${requestScope.book.author}"/></td>
</tr>
<tr>
<td>价格</td>
<td><input name="price" type="text" value="${requestScope.book.price}" /></td>
</tr>
<tr>
<td>销量</td>
<td><input name="sales" type="text" value="${requestScope.book.sales}"/></td>
</tr>
<tr>
<td>库存</td>
<td><input name="stock" type="text" value="${requestScope.book.stock}" /></td>
</tr>
<tr>
<td align="center" colspan="2">
<input type="submit" />
</td>
</tr>
</table>
</form>
</center>
</body>
</html>

12、HandlerInterceptor拦截器

12.1、HandlerInterceptor拦截器的介绍

SpringMVC中的拦截器,跟JavaWeb的Filter过滤器都非常接近。

都可以拦截资源的请求,调用。

SpringMVC中的拦截器,使用步骤:

1 编写一个类去实现接口

2 实现其中的方法

3 到springmvc中的配置文件中去配置

12.2、单个HandlerInterceptor拦截器的示例

1、编写一个类去实现HandlerInterceptor接口

2、到Spring的容器配置文件中去配置拦截器,让SpringMVC知道都拦截哪些目标方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
package com.atguigu.interceptor;

import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class FirstHandlerInterceptor implements HandlerInterceptor {
/**
* preHandle() 在目标方法之前执行
*/
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("FirstHandlerInterceptor preHandle() ");
/**
* 返回true表示允许执行目标方法
* 返回false表示阻止目标方法的执行
*/
return false;
}

/**
* postHandle() 在目标方法之后执行
*/
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
System.out.println("FirstHandlerInterceptor postHandle() ");
}

/**
* afterCompletion()在页面渲染完成之后
*/
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
System.out.println("FirstHandlerInterceptor afterCompletion() ");
}
}

springmvc.xml配置文件中的内容

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/mvc https://www.springframework.org/schema/mvc/spring-mvc.xsd">

<!-- 配置包扫描 -->
<context:component-scan base-package="com"></context:component-scan>

<!-- 视图解析器 -->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/pages/" />
<property name="suffix" value=".jsp" />
</bean>

<mvc:interceptors>
<!-- bean标签表示当前拦截器拦截所有请求
<bean class="com.atguigu.interceptor.FirstHandlerInterceptor" /> -->

<!-- 配置一个拦截器 -->
<mvc:interceptor>
<!-- 配置拦截的路径 -->
<mvc:mapping path="/hello"/>
<!-- 配置拦截器类 -->
<bean class="com.atguigu.interceptor.FirstHandlerInterceptor"/>
</mvc:interceptor>

</mvc:interceptors>

<!-- mvc标配 -->
<mvc:default-servlet-handler></mvc:default-servlet-handler>
<mvc:annotation-driven></mvc:annotation-driven>


</beans>

SpringMVC拦截器和JavaWeb过滤器的不同:

12.3、单个拦截器异常时的执行顺序

一:目标方法前返回false的情况:

1、目标方法前执行 返回false

2、这是目标方法 不执行

3、目标方法之后 不执行

4、这是渲染页面 不执行

5、页面渲染完成! 不执行

二:目标方法前返回true的情况,目标方法异常

1、目标方法前执行 返回true

2、这是目标方法 异常

3、目标方法之后 不执行

4、这是渲染页面 渲染异常页面

5、页面渲染完成! 执行

三:目标方法前返回true的情况,目标方法后异常

1、目标方法前执行 返回true

2、这是目标方法 执行

3、目标方法之后 异常

4、这是渲染页面 渲染异常页面

5、页面渲染完成! 执行

四:目标方法前返回true的情况,渲染页面异常

1、目标方法前执行 返回true

2、这是目标方法 执行

3、目标方法之后 执行

4、这是渲染页面 异常

5、页面渲染完成! 执行

多个拦截器的执行介绍:

FirstHandlerInterceptor 代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
package com.atguigu.interceptor;

import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class FirstHandlerInterceptor implements HandlerInterceptor {
/**
* preHandle() 在目标方法之前执行
*/
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("FirstHandlerInterceptor preHandle() ");
/**
* 返回true表示允许执行目标方法
* 返回false表示阻止目标方法的执行
*/
return true;
}

/**
* postHandle() 在目标方法之后执行
*/
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
System.out.println("FirstHandlerInterceptor postHandle() ");
}

/**
* afterCompletion()在页面渲染完成之后
*/
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
System.out.println("FirstHandlerInterceptor afterCompletion() ");
}
}

SecondHandlerInterceptor 代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
public class SecondHandlerInterceptor implements HandlerInterceptor {
/**
* preHandle() 在目标方法之前执行
*/
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("SecondHandlerInterceptor preHandle() ");
/**
* 返回true表示允许执行目标方法
* 返回false表示阻止目标方法的执行
*/
return true;
}

/**
* postHandle() 在目标方法之后执行
*/
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
System.out.println("SecondHandlerInterceptor postHandle() ");
}

/**
* afterCompletion()在页面渲染完成之后
*/
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
System.out.println("SecondHandlerInterceptor afterCompletion() ");
}
}

springmvc.xml配置文件配置:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<mvc:interceptors>
<!-- bean标签表示当前拦截器拦截所有请求
<bean class="com.atguigu.interceptor.FirstHandlerInterceptor" /> -->

<!-- 配置一个拦截器 -->
<mvc:interceptor>
<!-- 配置拦截的路径 -->
<mvc:mapping path="/hello"/>
<!-- 配置拦截器类 -->
<bean class="com.atguigu.interceptor.FirstHandlerInterceptor"/>
</mvc:interceptor>


<!-- 配置一个拦截器 -->
<mvc:interceptor>
<!-- 配置拦截的路径 -->
<mvc:mapping path="/hello"/>
<!-- 配置拦截器类 -->
<bean class="com.atguigu.interceptor.SecondHandlerInterceptor"/>
</mvc:interceptor>

</mvc:interceptors>

多个SpringMVC拦截器的细节说明:

1、当有多个拦截器的时候,他们的执行顺序是由他们在springmvc配置文件中从上到下的配置顺序决定

2、如果有异常的情况下。只要preHandler方法返回了true的拦截器,它的afterCompletion();

视图源码解析

什么是视图?

​ SpringMVC为了让整个程序的代码有更好的封装性,把最后程序执行完给用户的结果,封装成为一个View接口。这个接口就叫视图

​ 视图就是程序执行完之后用户收到的结果。

渲染视图是啥?

​ 执行用户收到的结果的代码。就叫渲染。

​ 执行页面的代码(大多数情况下,是请求转发,重定向。)

View 视图

​ 获取视图的类型

​ String getContentType();

​

​ 渲染视图页面

​ void render(Map<String, ?> model, HttpServletRequest request, HttpServletResponse response) throws Exception;

​ AbstractView 抽象类实现

​ 具体实现页面的渲染

​ protected abstract void renderMergedOutputModel(

​ Map<String, Object> model, HttpServletRequest request, HttpServletResponse response) throws Exception;

把隐含模型中的数据,同步到Reqeust域中

protected void exposeModelAsRequestAttributes(Map<String, Object> model, HttpServletRequest request)

​ ViewResolver 视图解析器

​ 根据给定的视图名解析得到相应的视图View对象

​ View resolveViewName(String viewName, Locale locale) throws Exception;


SpringMVC-03
http://www.kju147.com/2021/07/22/SpringMVC-03/
作者
个人学习
发布于
2021年7月22日
许可协议