SpringMVC 方法三种类型返回值总结
说明
关于springmvc就是没有系统的去整理返回值和参数类型
比如返回值有void,modelandview,string,json格式
参数用
1.直接使用基本类型或者String接受
2.使用@RequestBody+实体类接受前端传来的json数据
3.使用@PathVariable+{}接受
等
参考网址:
https://mp.weixin.qq.com/s?__biz=MzI1NDY0MTkzNQ==&mid=2247485420&idx=1&sn=aed911f6ba97b957668e42152db93dd0&scene=21#wechat_redirect
准备工作
新建springboot工程导入web和thmeleaf依赖
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.example</groupId>
<artifactId>demo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>demo</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<spring-boot.version>2.4.1</spring-boot.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.6</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.1</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>${spring-boot.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
<encoding>UTF-8</encoding>
</configuration>
</plugin>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>2.4.1</version>
<configuration>
<mainClass>com.example.demo.DemoApplication</mainClass>
</configuration>
<executions>
<execution>
<id>repackage</id>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
application.properties
# 应用名称
spring.application.name=demo
# 应用服务 WEB 访问端口
server.port=8080
# THYMELEAF (ThymeleafAutoConfiguration)
# 开启模板缓存(默认值: true )
#设置为false否则会有页面缓存
spring.thymeleaf.cache=false
# 检查模板是否存在,然后再呈现
spring.thymeleaf.check-template=true
# 检查模板位置是否正确(默认值 :true )
spring.thymeleaf.check-template-location=true
#Content-Type 的值(默认值: text/html )
spring.thymeleaf.content-type=text/html
# 开启 MVC Thymeleaf 视图解析(默认值: true )
spring.thymeleaf.enabled=true
# 模板编码
spring.thymeleaf.encoding=UTF-8
# 要被排除在解析之外的视图名称列表,⽤逗号分隔
spring.thymeleaf.excluded-view-names=
# 要运⽤于模板之上的模板模式。另⻅ StandardTemplate-ModeHandlers( 默认值: HTML5)
spring.thymeleaf.mode=HTML5
# 在构建 URL 时添加到视图名称前的前缀(默认值: classpath:/templates/ )
spring.thymeleaf.prefix=classpath:/templates/
# 在构建 URL 时添加到视图名称后的后缀(默认值: .html )
spring.thymeleaf.suffix=.html
1.ModelAndView
说明:
以前前后端不分的情况下,ModelAndView 应该是最最常见的返回值类型了,现在前后端分离后,后端都是以返回 JSON 数据为主了。后端返回 ModelAndView 这个比较容易理解,开发者可以在 ModelAndView 对象中指定视图名称,然后也可以绑定数据
新建实体类
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;
@Data
@AllArgsConstructor
@NoArgsConstructor
@Accessors(chain = true)
public class Book {
private Integer id;
private String name;
private String author;
}
controller的测试方法
@RequestMapping("book")
// @ResponseBody
public ModelAndView getAllBook() {
ModelAndView mv = new ModelAndView();
List<Book> books = new ArrayList<Book>();
Book b1 = new Book();
b1.setId(1).setAuthor("罗贯中").setName("三国演义");
Book b2 = new Book();
b2.setId(2).setAuthor("曹雪芹").setName("红楼梦");
books.add(b1);
books.add(b2);
mv.addObject("bs",books);
mv.setViewName("book");
return mv;
}
html页面
book.html
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Bootstrap 101 Template</title>
<!-- Bootstrap -->
<link
href="https://cdn.jsdelivr.net/npm/bootstrap@3.3.7/dist/css/bootstrap.min.css"
rel="stylesheet">
<script
src="https://cdn.jsdelivr.net/npm/jquery@1.12.4/dist/jquery.min.js"></script>
<script
src="https://cdn.jsdelivr.net/npm/bootstrap@3.3.7/dist/js/bootstrap.min.js"></script>
<style type="text/css">
#div2{
text-align: center;
border: 3px solid red;
}
a{
font-size: 25px;
}
</style>
</head>
<body>
<!-- 查询所有员工列表页面 -->
<h1 align="center">book列表信息</h1>
<!-- 这个表格示显示员工数据的 -->
<div id="div2">
<table class="table table-condensed">
<thead>
<tr>
<td>编号</td>
<td>ID</td>
<td>NAME</td>
<td>JOB</td>
</thead>
<tbody>
<tr th:each="book,varstatus:${bs}">
<td th:text="${varstatus.count}"></td>
<td th:text="${book.id}"></td>
<td th:text="${book.name}"></td>
<td th:text="${book.author}"></td>
</tr>
</tbody>
</table>
</div>
</body>
</html>
浏览器访问localhost:8080/book
返回 ModelAndView ,最常见的两个操作就是指定数据模型+指定视图名
2. Void
返回值为 void 时,可能是你真的没有值要返回,也可能是你有其他办法
2.1 没有值
如果确实没有返回值,那就返回 void ,但是一定要注意,此时,方法上需要添加 @ResponseBody 注解,像下面这样:
@RequestMapping("/test2")
@ResponseBody
public void test2() {
//你的代码
System.out.println("controller方法时没有返回值");
}
控制台打印
controller方法时没有返回值
2.2 重定向
由于 SpringMVC 中的方法默认都具备 HttpServletResponse 参数,因此可以重拾 Servlet/Jsp 中的技能,可以实现重定向,像下面这样手动设置响应头:
@RequestMapping("/test1")
@ResponseBody
public void test1(HttpServletResponse resp) {
resp.setStatus(302);
resp.addHeader("Location","/book");
}
也可以像下面这样直接调用重定向的方法:
@RequestMapping("/test11")
@ResponseBody
public void test11(HttpServletResponse resp) throws IOException {
resp.sendRedirect("/book");
}
当然,重定向无论你怎么写,都是 Servlet/Jsp 中的知识点,上面两种写法都相当于是重回远古时代。
浏览器访问localhost:8080/test1和localhost:8080/test11
重定向到localhost:8080/book的视图渲染页面
2.3 服务端跳转
既然可以重定向,当然也可以服务端跳转,像下面这样:
@RequestMapping("/test5")//get请求
@ResponseBody
public void test5(HttpServletRequest req,HttpServletResponse resp) throws IOException, ServletException {
req.getRequestDispatcher("/book").forward(req,resp);
}
浏览器访问localhost:8080/test5
转发到localhost:8080/book 但是url地址不变
补充知识(转发和重定向的区别)
请求转发是一种资源的跳转方式,此外重定向也是一种资源的跳转方式
请求转发的特点:
(1)请求转发是一次请求,一次响应
(2)请求转发前后,地址栏地址不会发生变化
(3)请求转发前后,request对象是同一个(域对象)
(4)进行转发的两个资源必须属于同一个Web应用(属于不同web应用的资源之间是不能进行转发的)
request.**getRequestDispatcher**(转发到资源的URL地址).**forward**( req, res);
重定向也是一种资源的跳转方式
重定向的特点:
(1)重定向是两次请求,两次响应
(2)重定向前后,地址栏地址会发生变化
(3)重定向前后,request对象不是同一个
(不能使用域对象)
(4)进行重定向的两个资源可以不是同一个Web应用(属于不同web应用的资源之间是可以进行重定向的)
实现重定向:
response.sendRedirect( 重定向到资源的地址 );
2.4 返回字符串
当然也可以利用 HttpServletResponse 返回其他字符串数据,包括但不局限于 JSON,像下面这样:
@RequestMapping("/test3")
@ResponseBody
public void test3( HttpServletResponse resp) throws IOException {
/**
* 设置响应的数据为json格式
*/
resp.setContentType("application/json;charset=utf8");
PrintWriter out = resp.getWriter();
List<Book> books = new ArrayList<Book>();
Book b1 = new Book();
b1.setId(1).setAuthor("罗贯中").setName("三国演义");
Book b2 = new Book();
b2.setId(2).setAuthor("曹雪芹").setName("红楼梦");
books.add(b1);
books.add(b2);
/**
* 通过jackson工具类把java对象转为json格式的字符窜
*/
String booksJson = new ObjectMapper().writeValueAsString(books);
out.write(booksJson);
out.flush();
out.close();
}
这是返回值为 void 时候的情况,方法返回值为 void ,不一定就真的不返回了,可能还有其他的方式给前端数据。
浏览器访问 localhost:8080/test3
3. String
当 SpringMVC 方法的返回值为 String 类型时,也有几种不同情况。
3.1 逻辑视图名
返回 String 最常见的是逻辑视图名,这种时候一般利用默认的参数 Model 来传递数据,像下面这样 :
controller中方法
@RequestMapping("/test4")
public String test4(Model model) {
Book b1 = new Book();
b1.setId(1).setAuthor("罗贯中").setName("三国演义");
model.addAttribute("book",b1);
model.addAttribute("username","张三");
return "bookinfo";
}
html页面
bookinfo.html
<!DOCTYPE HTML>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<title>Getting Started: Serving Web Content</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
</head>
<body>
<p th:text="'页面获取model的username的值为: , ' + ${username} + '!'" />
<hr>
<hr>
<p th:text="'页面获取model的book的信息book的id为: , ' + ${book.id}" />
<p th:text="'页面获取model的book的信息book的author为: , ' + ${book.author}" />
<p th:text="'页面获取model的book的信息book的name为: , ' + ${book.name} " />
</body>
</html>
浏览器访问localhost:8080/test4
此时返回的 bookinfo
就是逻辑视图名,需要携带的数据放在 model 中。
3.2 重定向
也可以重定向,事实上,如果在 SpringMVC 中有重定向的需求,一般采用这种方式:
@RequestMapping("/test6")
public String test6() {
return "redirect:/book";
}
浏览器输入localhost:8080/test6
发送请求
url地址发生改变,变为localhost:8080/book
3.3 forward 转发
也可以 forward 转发,事实上,如果在 SpringMVC 中有 forward 转发的需求,一般采用这种方式:
@RequestMapping("/test7")
public String test7() {
return "forward:/book";
}
浏览器输入localhost:8080/test7
发送请求
url地址没有发生改变
3.4 真的是 String
当然,也有一种情况,就是你真的想返回一个 String ,此时,只要在方法上加上 @ResponseBody 注解即可,或者 Controller 上本身添加的是组合注解 @RestController,像下面这样:
第一种方式
@RestController
public class HelloController {
@RequestMapping("/hello1")//get请求
public String hello1() {
return "hello srpngmvc";
}
}
@RestController=@Controller+@ResponseBody
第二种方式
//@RestController
@Controller
public class HelloController {
@RequestMapping("/hello1")//get请求
@ResponseBody
public String hello1() {
return "hello srpngmvc";
}
}
4.JSON
返回 JSON 算是最最常见的了,现在前后端分离的趋势下,大部分后端只需要返回 JSON 即可,那么常见的 List 集合、Map,实体类等都可以返回,这些数据由 HttpMessageConverter 自动转为 JSON ,如果大家用了 Jackson 或者 Gson ,不需要额外配置就可以自动返回 JSON 了,因为框架帮我们提供了对应的 HttpMessageConverter ,如果大家使用了 Alibaba 的 Fastjson 的话,则需要自己手动提供一个相应的 HttpMessageConverter 的实例,方法的返回值像下面这样:
需要的实体类
user.java
@Data
@AllArgsConstructor
@NoArgsConstructor
@Accessors(chain = true)
public class User {
private String username;
private String password;
private List<String> favorites;
}
controller中的测试方法
@GetMapping("/user")//get请求
@ResponseBody
public User getUser() {
User user = new User();
List<String> favorites = new ArrayList<>();
favorites.add("足球");
favorites.add("篮球");
user.setFavorites(favorites).setUsername("张三").setPassword("123456");
return user;
}
@GetMapping("/users")//get请求
@ResponseBody
public List<User> getUsers() {
List<User> users = new ArrayList<>();
for (int i = 0; i < 10; i++) {
User user = new User();
user.setPassword("张三" + i).setPassword("pwd" + i)
.setFavorites(new ArrayList<String>(Arrays.asList("football", "basketball")));
users.add(user);
}
return users;
}
总结
以上就是SpringMVC 方法四种不同类型的返回值
1.ModelAndView
2.void
3.其他
其他分为String返回视图名成和@ResponseBody返回json
测试controller的内容
import com.example.demo.demos.model.Book;
import com.example.demo.demos.model.User;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
/**
* @author shaoming
* @Date: 2021/4/9 17:18
* @Description:
*/
@Controller
public class TestController {
@RequestMapping("book")//get请求
// @ResponseBody
/**
* 返回值为ModelAndView
*/
public ModelAndView getAllBook() {
ModelAndView mv = new ModelAndView();
List<Book> books = new ArrayList<Book>();
Book b1 = new Book();
b1.setId(1).setAuthor("罗贯中").setName("三国演义");
Book b2 = new Book();
b2.setId(2).setAuthor("曹雪芹").setName("红楼梦");
books.add(b1);
books.add(b2);
mv.addObject("bs", books);
mv.setViewName("book");
return mv;
}
/**
* 返回值为void类型
*/
@RequestMapping("/test2")//get请求
@ResponseBody
public void test2() {
//你的代码
System.out.println("controller方法时没有返回值");
}
/**
* 返沪void类型的重定向,通过status和header进行设置(不常用)
* @param resp
* @throws IOException
*/
@RequestMapping("/test1")//get请求
@ResponseBody
public void test1(HttpServletResponse resp) {
resp.setStatus(302);
resp.addHeader("Location", "/book");
}
/**
* 返沪void类型的重定向
* @param resp
* @throws IOException
*/
@RequestMapping("/test11")//get请求
@ResponseBody
public void test11(HttpServletResponse resp) throws IOException {
resp.sendRedirect("/book");
}
@RequestMapping("/test5")//get请求
@ResponseBody
public void test5(HttpServletRequest req, HttpServletResponse resp) throws IOException, ServletException {
req.getRequestDispatcher("/book").forward(req, resp);
}
/**
* 返回值为void,并页面输出json格式字符窜
* @param resp
* @throws IOException
*/
@RequestMapping("/test3")//get请求
@ResponseBody
public void test3(HttpServletResponse resp) throws IOException {
/**
* 设置响应的数据为json格式
*/
resp.setContentType("application/json;charset=utf8");
PrintWriter out = resp.getWriter();
List<Book> books = new ArrayList<Book>();
Book b1 = new Book();
b1.setId(1).setAuthor("罗贯中").setName("三国演义");
Book b2 = new Book();
b2.setId(2).setAuthor("曹雪芹").setName("红楼梦");
books.add(b1);
books.add(b2);
/**
* 通过jackson工具类把java对象转为json格式的字符窜
*/
String booksJson = new ObjectMapper().writeValueAsString(books);
out.write(booksJson);
out.flush();
out.close();
}
/**
* 返回视图名称并通过model获取数据
* @param model
* @return
*/
@RequestMapping("/test4")
public String test4(Model model) {
Book b1 = new Book();
b1.setId(1).setAuthor("罗贯中").setName("三国演义");
model.addAttribute("book", b1);
model.addAttribute("username", "张三");
return "bookinfo";
}
/**
* 返回string类型的重定向
* @return
*/
@RequestMapping("/test6")
public String test6() {
return "redirect:/book";
}
/**
* 返回string类型的转发
* @return
*/
@RequestMapping("/test7")
public String test7() {
return "forward:/book";
}
/**
* 返回json
* @return
*/
@GetMapping("/user")//get请求
@ResponseBody
public User getUser() {
User user = new User();
List<String> favorites = new ArrayList<>();
favorites.add("足球");
favorites.add("篮球");
user.setFavorites(favorites).setUsername("张三").setPassword("123456");
return user;
}
@GetMapping("/users")//get请求
@ResponseBody
public List<User> getUsers() {
List<User> users = new ArrayList<>();
for (int i = 0; i < 10; i++) {
User user = new User();
user.setPassword("张三" + i).setPassword("pwd" + i)
.setFavorites(new ArrayList<String>(Arrays.asList("football", "basketball")));
users.add(user);
}
return users;
}
}
个人csdn博客网址:https://blog.csdn.net/shaoming314
个人博客网址:www.shaoming.club
个人gitee地址:https://gitee.com/shao_ming314/note
sword(“123456”);
return user;
}
@GetMapping("/users")//get请求
@ResponseBody
public List<User> getUsers() {
List<User> users = new ArrayList<>();
for (int i = 0; i < 10; i++) {
User user = new User();
user.setPassword("张三" + i).setPassword("pwd" + i)
.setFavorites(new ArrayList<String>(Arrays.asList("football", "basketball")));
users.add(user);
}
return users;
}
}
------
------
------
个人csdn博客网址:https://blog.csdn.net/shaoming314
[外链图片转存中...(img-SNcfjFBn-1617982685618)]
个人博客网址:www.shaoming.club
[外链图片转存中...(img-fynJGEWX-1617982685619)]
个人gitee地址:https://gitee.com/shao_ming314/note
[外链图片转存中...(img-zjPPq6oW-1617982685620)]