前言
在SpringMVC框架中,视图解析器可以将逻辑视图名称转换为实际的视图对象。除了直接渲染视图,你还可以通过SpringMVC提供的转发和重定向机制来跳转到另一个视图。在本篇博客中,我们将学习SpringMVC中的转发视图技术,以及如何使用它来构建更高效的Web应用程序。
一、前期准备
1、新建项目,结构如下
2、导入依赖
<dependencies>
<!-- springmvc 依赖,会将spring的核心包一并添加进来 -->
<!-- https://mvnrepository.com/artifact/org.springframework/spring-webmvc -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.3.23</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.30</version>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.4.5</version>
</dependency>
</dependencies>
3、配置 web.xml
<?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>dispatcher</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>dispatcher</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
用于配置 Servlet 的映射和加载。在 Spring MVC 中,它用于配置 DispatcherServlet 的初始化和请求映射。
具体来说,这段配置的作用如下:
- 定义了一个名为 "dispatcher" 的 Servlet,并指定了 org.springframework.web.servlet.DispatcherServlet 作为其处理类。
- 设置了 load-on-startup 属性为 1,表示在应用启动时就加载该 Servlet。
- 使用 <servlet-mapping> 元素将 "dispatcher" Servlet 映射到所有的请求路径上(即 <url-pattern>/</url-pattern>),意味着所有的请求都会经过该 Servlet 进行处理。
这段配置的作用是将所有的请求交给 DispatcherServlet 处理,并让它成为应用的核心控制器。DispatcherServlet 将根据请求的 URL 和其他配置信息,将请求分发给相应的处理器方法进行处理,然后返回响应结果。
4、配置 dispatcher-servlet.xml
<?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" xmlns:mcv="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="edu.nf.ch06"/>
<!-- mvc 注解驱动 -->
<mvc:annotation-driven/>
<!-- 默认 servlet 处理静态资源 -->
<mcv:default-servlet-handler/>
<!-- 内部资源视图解析器 -->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/jsp/"/>
<property name="suffix" value=".jsp"/>
</bean>
</beans>
主要作用是配置Spring MVC框架相关的组件和参数,以便在Web应用中使用Spring MVC框架进行开发。
具体来说,该配置文件包含以下几个部分:
命名空间声明:声明了XML文件所使用的命名空间,包括beans、context和mvc三个命名空间。
组件扫描:通过context:component-scan标签启用组件扫描机制,指定需要扫描的包路径,以便Spring MVC框架能够自动扫描和注册相关的组件。
注解驱动:通过mvc:annotation-driven标签启用注解驱动机制,使得Spring MVC框架能够自动识别和处理控制器中的注解,例如@RequestMapping、@ResponseBody等。
静态资源处理:通过mcv:default-servlet-handler标签配置默认的servlet处理静态资源,以便在Web应用中访问静态资源,例如图片、CSS、JavaScript等。
视图解析器:通过<bean>标签配置视图解析器,将JSP页面映射到对应的控制器方法上,以便返回相应的视图。
5、在 entity 包下新建一个 User 实体类
@Data
public class User {
private String userName;
}
二、转发视图
1、方式一
1)编写 controller
@Controller
@Slf4j
public class TestController {
/**
* 转发视图
* @return
*/
@GetMapping("/forward1")
public ModelAndView forward1(){
return new ModelAndView("index");
}
}
这段代码是一个Spring MVC框架中的控制器方法,使用了@GetMapping注解来处理HTTP GET请求。当访问"/forward1"路径时,该方法会被调用。
该方法返回一个ModelAndView对象,其中"index"是返回的视图名称。在这种情况下,它将返回名为"index"的视图页面。
2)编写 jsp 页面 index.jsp 页面
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>首页</title>
</head>
<body>
<h1>首页</h1>
</body>
</html>
3)运行效果
2、方式二
1)编写 controller
/**
* 转发视图 2
* @return
*/
@GetMapping("/forward2")
public String forward2(){
log.info("转发视图");
return "index";
}
在 SpringMVC 中,控制器可以使用多种方式来响应客户端请求。其中,转发视图是一种常用的方式之一。通过转发视图,控制器可以将请求转发给指定的视图进行处理,并返回处理结果给客户端。
在这个例子中,控制器的方法名为
forward2()
,使用GetMapping
注解标记了请求路径为 "/forward2"。方法体内,通过返回 "index" 字符串实现了转发视图的功能。具体来说,控制器将请求转发给名为 "index" 的视图进行处理,并将处理结果返回给客户端。
2)编写 jsp 页面 index.jsp 页面
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>首页</title>
</head>
<body>
<h1>首页</h1>
</body>
</html>
3)运行效果
3、方式三
1) 编写 controller
/**
* 转发的 url 必须使用 forward 前缀
* 注意:转发视图是通过 InternalResourceViewResolver
* 解析器来完成的,而转发请求的 url 是一个地址,并非视图
* 因此需要加上 forward:前缀,并且 url 的路径必须写完整
* @return
*/
@GetMapping("/forward3")
public String forward3(){
return "forward:forward2";
}
该方法使用
@GetMapping("/forward3")
注解将HTTP GET请求映射到"/forward3"路径。在方法内部,通过返回字符串"forward:forward2"来指定要转发的URL。这里使用了"forward:"前缀,告诉Spring框架将请求转发到"forward2"路径。
需要注意的是,这里使用的是转发而不是重定向。转发是服务器内部的操作,它会将请求直接转发给另一个控制器方法或视图,而不会改变浏览器的URL。因此,在浏览器地址栏中仍然会显示为"/forward3"。
通过转发将请求发送到另一个控制器方法或视图。这在某些场景下可以帮助我们组织和管理代码,并实现URL之间的跳转。
2)编写 jsp 页面 index.jsp 页面
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>首页</title>
</head>
<body>
<h1>首页</h1>
</body>
</html>
3)运行效果
三、重定向视图
1、方式一
1)编写 Controller
/**
* 如果需要 重定向一个视图或者请求地址
* 可以结合”redirect:“这个前缀
* 并且重定向的地址和视图名称 必须是完整的 url 路径
* 因为重定向是不会走内部资源视图解析器的
*
* 注意:重定向不能传递请求数据,需要通过其他方式传递参数
* @return
*/
@GetMapping("/redirect1")
public String redirect1(Model model){
model.addAttribute("name","qiu");
return "redirect:redirect.jsp";
}
在 Spring MVC 中,控制器可以使用重定向来将请求转发到另一个 URL 或视图。重定向使用了 "redirect:" 前缀来指示 Spring MVC 执行重定向。
控制器的方法名为
redirect1()
,使用GetMapping
注解标记了请求路径为 "/redirect1"。方法体内,通过将 "redirect.jsp" 字符串作为返回值,并添加了 "redirect:" 前缀,实现了重定向的功能。具体来说,控制器将请求重定向到名为 "redirect.jsp" 的视图或 URL。需要注意的是,重定向地址必须是完整的 URL 路径,而不是视图名称。因为重定向不会走内部资源视图解析器,所以不能使用简单的视图名称来指定重定向的目标。
另外,需要注意的是重定向无法直接传递请求数据,也就是无法通过 Model 或其他方式携带参数。如果需要传递参数,可以使用 URL 参数、路径参数、Session 等其他方式来实现。
2)编写 jsp 页面 redirect.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<h1>重定向</h1>
参数:${param.name}
</body>
</html>
3)运行效果
2、方式二
1)编写 controller
/**
* RedirectAttributes 是 spring MVC3.1 版本提供的一个类
* 主要用于在重定向时可以重写 url ,在重定向的 url 后面加入
* 参数,这样就可以变相在重定向的资源中获取相关的参数信息
* @param redirectAttributes
* @return
*/
@GetMapping("/redirect2")
public String redirect2(RedirectAttributes redirectAttributes){
redirectAttributes.addAttribute("name","qiu");
return "redirect:redirect.jsp";
}
在 Spring MVC 3.1 版本及以上,引入了 RedirectAttributes 类,它是用于在重定向时传递参数的一个工具类。通过使用 RedirectAttributes,可以将参数添加到重定向 URL 的查询参数中,从而在重定向的资源中获取相关的参数信息。
在控制器方法名为
redirect2()
,使用GetMapping
注解标记了请求路径为 "/redirect2"。方法的参数中使用了 RedirectAttributes 对象,通过调用其addAttribute()
方法,将名为 "name",值为 "qiu" 的参数添加到重定向 URL 的查询参数中。然后,控制器返回 "redirect:redirect.jsp" 字符串,实现了重定向的功能。这样,在重定向的资源(redirect.jsp)中就能够通过获取查询参数来获取传递的参数信息。
需要注意的是,RedirectAttributes 只能传递基本数据类型和字符串等简单类型的参数。如果需要传递复杂对象,可以通过其他方式(如 Session)进行传递。
2)编写 jsp 页面 redirect.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<h1>重定向</h1>
参数:${param.name}
</body>
</html>
3)运行效果
四、使用 @RestController 注解
1、 @RestController 注解的用途
@RestController注解是Spring框架中用于标识一个类为RESTful风格的控制器的注解。
使用@RestController注解的类会自动将返回的数据(对象、集合等)转换为指定格式的响应体,一般为JSON或XML格式。它结合了@Controller和@ResponseBody注解的功能。
具体用途包括:
处理HTTP请求:@RestController注解使得类中的方法能够处理HTTP请求,例如GET、POST、PUT、DELETE等。
自动序列化响应数据:通过@RestController注解,方法返回的对象会自动序列化为指定格式(如JSON)的响应体,简化了手动进行序列化的过程。
简化代码编写:使用@RestController注解可以减少开发者编写代码的工作量,不需要额外配置@ResponseBody注解来指示方法返回的结果需要作为响应体。
支持多种数据格式:@RestController注解支持多种数据格式,例如JSON、XML等,根据请求头中的Accept字段来决定返回的数据格式。
总而言之,@RestController注解的主要作用是将类标识为RESTful风格的控制器,并自动将方法返回的对象转换为指定格式的响应体。这样可以简化代码编写并提供灵活的数据格式支持。
2、编写 UserController 控制器
1)方式一:方法上
public class UserController {
@GetMapping("/user")
/**
* 使用 @ResponseBody 注解,表示将方法返回值
* 以输出流的方式写回客户端,这样 springmvc
* 就会将序列化好的 json 的数据放入响应体并写回
*/
@ResponseBody
public User getUSer(){
User user = new User();
user.setUserName("user1");
return user;
}
}
在
@GetMapping("/user")
注解中指定了该方法将处理HTTP GET请求,并映射到"/user"路径。接下来,在方法上方添加了
@ResponseBody
注解。这个注解的作用是告诉Spring MVC框架将方法的返回值作为响应的内容直接写回给客户端,而不是通过视图解析器进行解析和渲染。在这种情况下,返回的是一个User对象。在方法体内部,首先创建了一个User对象,并设置了它的属性值。然后,该User对象被作为方法的返回值返回。由于使用了
@ResponseBody
注解,Spring MVC框架会自动将User对象序列化为JSON格式的数据,并将其放入响应体中,最终返回给客户端。
2) 方式二:类上(推荐)
@RestController
public class UserController {
@GetMapping("/user")
/**
* 使用 @ResponseBody 注解,表示将方法返回值
* 以输出流的方式写回客户端,这样 springmvc
* 就会将序列化好的 json 的数据放入响应体并写回
*/
public User getUSer(){
User user = new User();
user.setUserName("user1");
return user;
}
}
@RestController
是一个组合注解,它将@Controller
和@ResponseBody
注解结合在一起,用于标识这个类是一个控制器,并且所有的方法都会以JSON或XML格式直接返回给客户端,而不需要使用@ResponseBody
注解来标识每个方法。
3、运行效果
五、使用 @RequestBody 注解
1、@RequestBody 注解的用途
@RequestBody
注解用于指示 Spring MVC 控制器方法参数应该从请求体中获取数据。在 Spring MVC 中,请求体是指 HTTP 请求中的消息主体部分,通常用于传递 JSON、XML 或其他结构化数据。默认情况下,Spring MVC 控制器方法的参数通过请求的 URL 参数进行绑定。但是,在某些情况下,我们希望直接将请求体中的数据绑定到方法的参数上,这时就可以使用
@RequestBody
注解。使用
@RequestBody
注解时,Spring MVC 会尝试将请求体的内容转换为指定的 Java 对象或其他数据类型。这个转换过程通常是通过消息转换器(MessageConverter)来实现的。根据请求的 Content-Type 头部信息,Spring MVC 会选择适合的消息转换器来解析请求体中的数据。总之,
@RequestBody
注解用于指示 Spring MVC 控制器方法参数应从请求体中获取数据,并通过消息转换器进行解析和转换。这样可以方便地处理请求体中的结构化数据,如 JSON 或 XML。
2、编写 UserController
/**
* 当前端提交的是一个 JSON 字符串时,
* 此时要使用 @RequestBody 注解来映射,
* 这样 springmvc 就会将 json 字符串
* 反序列化为实体对象
* @param user
* @return
*/
@PostMapping("/add")
public String add(@RequestBody User user){
log.info(user.getUserName());
return "success";
}
当前端发送一个包含 JSON 格式数据的 POST 请求到 "/add" 路径时,Spring MVC 将自动将请求体中的 JSON 字符串转换为
User
对象,并将其传递给add()
方法。你可以在方法内部访问User
对象的属性,如user.getUserName()
。最后,
add()
方法将返回 "success" 字符串作为响应。需要注意的是,在使用
@RequestBody
注解时,请求头中的 Content-Type 必须设置为 "application/json",以告诉 Spring MVC 请求体中的数据为 JSON 格式。此外,还需要确保请求体中的 JSON 字符串与User
类的属性对应,以便成功反序列化为User
对象。
3、编写一个 ajax2.html 页面
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="js/JQuery文件.txt.js"></script>
</head>
<body>
<script>
$(function () {
// 构建一个 js 对象
let user = {'userName':'user2'};
// 将 js 对象序列化为 json 字符串
user = JSON.stringify(user);
$.ajax({
url:'../add',
type:'post',
data:user,
// 以 json 字符串提交时,需要将请求 类型设置为 application/json
contentType:'application/json;charset=utf-8',
success:function (result) {
alert(result);
},error(e){
alert("错误信息:" + e)
}
})
})
</script>
</body>
</html>
注意:
// 以 json 字符串提交时,需要将请求 类型设置为 application/json
contentType:'application/json;charset=utf-8',不然的话会就会序列化失败。
4、运行效果
六、 转发视图和重定向视图的区别
转发(forward)和重定向(redirect)是在Web应用程序中常见的两种跳转方式。它们虽然都能实现页面跳转,但它们的原理和使用场景不同。
转发是指将请求传递给后端的另一个资源来处理,处理完毕后直接将结果返回给客户端,客户端并不知道是否经过了转发。在转发的过程中,客户端只发起了一次请求,请求的URL地址没有发生改变。在Spring MVC框架中,转发可以通过return "forward:/path"
语句实现。转发视图文件需要放置在WEB-INF目录下,客户端无法直接访问,只有服务器端能够访问。
重定向是指将请求重定向到另一个URL地址,重定向会向客户端发出一个新的请求,原来的请求已经结束。在重定向的过程中,客户端发起了两次请求,第一次请求的URL地址被重定向到了新的URL地址。在Spring MVC框架中,重定向可以通过return "redirect:/path"
语句实现。
转发和重定向的区别如下:
跳转方式不同:转发是在服务器端内部完成的,而重定向是在客户端发起的新的HTTP请求。
地址栏URL不同:转发时,客户端发起的URL地址和服务器端处理的URL地址是一致的,而重定向会将请求URL地址修改为新的地址。
请求参数不同:转发时,请求参数在整个请求过程中一直存在,而重定向只能将请求参数放在URL地址后面。
响应速度不同:转发速度快于重定向,因为重定向需要客户端发起新的HTTP请求,而转发只是在服务器内部进行了一次调用和处理。
运作环境不同:转发只适用于同一个Web应用程序内的资源跳转,而重定向可以跨域访问不同的Web应用程序。
总之,转发和重定向区别很大,使用时需要根据实际情况选择合适的跳转方式。如果需要在同一个Web应用程序内进行资源跳转,且请求对象、响应对象以及参数需要共享,则应该使用转发;如果需要跳转到另一个Web应用程序或新的URL地址,并且需要传递参数,则应该使用重定向。
七、gitee 案例
地址:ch06 · qiuqiu/SpringMVC - 码云 - 开源中国 (gitee.com)