目录
[一、Spring MVC概述](#一、Spring MVC概述)
[1. @RequestController注解](#1. @RequestController注解)
[2. @RequestMapping注解](#2. @RequestMapping注解)
[3. Postman](#3. Postman)
[3.1 下载与安装](#3.1 下载与安装)
[3.2 创建请求](#3.2 创建请求)
[1. 传递单个参数](#1. 传递单个参数)
[2. 传递多个参数](#2. 传递多个参数)
[3. 传递对象](#3. 传递对象)
[4. 后端参数重命名](#4. 后端参数重命名)
[5. 传递数组](#5. 传递数组)
[6. 传递集合](#6. 传递集合)
[7. 传递JSON数据](#7. 传递JSON数据)
[7.1 JSON概念](#7.1 JSON概念)
[7.2 JSON 语法规则](#7.2 JSON 语法规则)
[7.3 JSON 与 Java 对象互转](#7.3 JSON 与 Java 对象互转)
[7.4 JSON优点](#7.4 JSON优点)
[7.5 传递JSON对象](#7.5 传递JSON对象)
[8. 从URL中获取参数](#8. 从URL中获取参数)
[9. 上传文件](#9. 上传文件)
[10. 获取Cookie](#10. 获取Cookie)
[11. 获取session](#11. 获取session)
[12. 获取Header](#12. 获取Header)
[1. 返回静态页面](#1. 返回静态页面)
[2. 返回数据](#2. 返回数据)
[3. 返回HTML代码片段](#3. 返回HTML代码片段)
[4. 返回JSON](#4. 返回JSON)
[5. 设置状态码](#5. 设置状态码)
[6. 设置Header](#6. 设置Header)
一、Spring MVC概述
官网https://docs.spring.io/spring-framework/reference/web/webmvc.html

Spring MVC 是 Spring 框架的一个模块,专门用于构建基于 Java 的 Web 应用程序。它基于模型-视图-控制器(MVC)设计模式,提供了一种灵活、可扩展的方式来开发动态网页应用。
简单来说,Spring MVC是一个Web框架。
既然是Web框架,那么当用户在浏览器中输入了url之后,我们的Spring MVC项目就可以感知到用户的请求,并给予响应。
学习Spring MVC,也就是学习如何通过浏览器和用户程序进行交互。
交互主要分以下三个方面:
- 建立连接:将用户(浏览器)和Java程序连接起来,也就是访问一个地址能够调用到我们的Spring程序;
- 请求:用户请求的时候会带一些参数,在程序中要想办法获取到参数,所以请求主要是获取参数的功能;
- 响应:执行了业务逻辑之后,要把程序执行的结果返回给用户。
二、建立连接
在Spring MVC中使用@RequestMapping注解来是想URL路由映射,也就是浏览器连接程序的作用。
先创建一个Spring Boot项目,再创建一个UserController类,实现用户通过浏览器和程序的交互,代码如下:
java
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class HelloController {
@RequestMapping("/hello")
public String hello() {
return "Hello World";
}
}
方法名和路径名无需一致。
运行程序后,接下来在浏览器访问http://127.0.0.1:8080/hello:

1. @RequestController注解
@RequestController是 Spring MVC 中的一个组合注解,主要用于简化 RESTful Web 服务的开发,将方法的返回值直接序列化为 JSON 或 XML 响应体,无需额外的视图解析。
核心特性:
- 自动将方法返回值转换为 HTTP 响应体。
- 默认使用@ResponseBody注解效果,无需显式声明。
- 适用于返回 JSON/XML 数据的 API 场景。
2. @RequestMapping注解
@RequestMapping是Spring MVC应用程序中最常被用到的注解之一,用来注册接口的路由映射。
当服务收到请求时,路径为/hello的请求就会调用hello这个方法的代码。
路由映射:当用户访问一个URL时,将用户的请求对应到程序中某个类的某个方法的过程。
@RequestMapping既可修饰类,也可以修饰方法,当修饰类和方法时,访问的地址是类路径+方法路径。
@RequestMapping标识一个类:设置映射请求的请求路径的初始信息
@RequestMapping标识一个方法:设置映射请求请求路径的具体信息
java
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RequestMapping("/Spring")
@RestController
public class HelloController {
@RequestMapping("/hello")
public String hello() {
return "Hello World";
}
}
访问地址:http://127.0.0.1:8080/Spring/hello

@RequestMapping的URL路径最前面加不加/(斜杠)都可以,Spring程序启动时,会进行判断,如果前面没有加/,Spring会拼接上一个/。
@RequestMapping的URL路径也可以是多层路径,最终访问时,依然是类路径+方法路径。
java
@RequestMapping("/Spring/1")
@RestController
public class HelloController {
@RequestMapping("/hello/2")
public String hello() {
return "Hello World";
}
}
访问地址:http://127.0.0.1:8080/Spring/1/hello/2

@RequestMapping既支持Get请求,又支持Post请求。同理,也支持其他的请求方式。可以通过method参数或者@GetMapping/@PostMapping来指定。
java
import org.springframework.web.bind.annotation.*;
@RequestMapping("user")
@RestController
public class UserController {
//既支持get,又支持post
@RequestMapping("/m1")
public String m1() {
return "m1";
}
//只支持get
@RequestMapping(value = "/m2", method = RequestMethod.GET)
public String m2() {
return "m2";
}
//相当于
@GetMapping("/m4")
public String m4() {
return "m4";
}
//只支持post
@RequestMapping(value = "/m3", method = RequestMethod.POST)
public String m3() {
return "m3";
}
//相当于
@PostMapping("/m5")
public String m5() {
return "m5";
}
}
3. Postman
为了更加方便的测试后端方法,我们可以使用 API 开发与测试工具--Postman。
3.1 下载与安装
在官网下载,安装过程很简单,这里就不赘述了。
3.2 创建请求


如何操作:

普通传参,也就是通过查询字符串来传参。
学习HTTP环节时,我们通过URL来访问互联网上的某一个资源,URL的格式如下:
其中,查询字符串就是请求的参数。
在Postman上可以这样设置:

与此同时,URL也会变化:
三、请求
访问不同的路径,就是发送不同的请求.在发送请求时,可能会带一些参数,所以学习Spring的请求,主要是学习如何传递参数到后端以及后端如何接收。
1. 传递单个参数
传递单个参数,在SpringMVC中直接用方法中的参数就可以,比如以下代码:
java
@RequestMapping("/request")
@RestController
public class RequestController {
@RequestMapping("/r1")
public String r1(String keyword){
return "接收参数:" + keyword;
}
}
可以在URL中自定义keyword=spring访问地址:

也可以使用Postman:
先输入URL:

再输入参数:

点击send:

可以看到,后端程序正确地拿到了参数值。
注意事项:
- 参数名一定要一致;
- 使用基本类型来接收参数时,参数必须传(除boolean类型),否则会报500错误类型,不匹配时,会报400错误类型,所以企业开发中,对于参数可能为空的数据,建议使用包装类型。
| | 包装类 | 基本数据类型 |
| 代码 |java @RequestMapping("/r3") public String r3(Integer number){ return "接收参数: " + number; }
|java @RequestMapping("/r4") public String r4(int number){ return "接收参数: " + number; }
|
| 正常传参 ||
|
非正常传参
2. 传递多个参数
java
@RequestMapping("/r2")
public String r2(String username, String password){
return "接收参数: username:" + username + ", password:" + password;
}

URL中参数的顺序可以调换,不影响正常传参。
3. 传递对象
创建一个UserInfo对象类:
java
public class UserInfo {
private String name;
private Integer gender;
private Integer age;
public UserInfo(){
}
public UserInfo(String name, Integer age, Integer gender) {
this.age = age;
this.gender = gender;
this.name = name;
}
public Integer getGender() {
return gender;
}
public void setGender(Integer gender) {
this.gender = gender;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "UserInfo{" +
"age=" + age +
", name='" + name + '\'' +
", gender=" + gender +
'}';
}
}
传参代码:
java
@RequestMapping("/r5")
public String r5(UserInfo userInfo){
return "接收参数: " + userInfo.toString();
}

Spring会根据参数名称自动绑定到对象的各个属性上,如果某个属性未传递,则赋值为null(基本类型则赋值为默认初识值,比如int类型的属性,会被赋值为0)。
4. 后端参数重命名
某些特殊的情况下,前端传递的参数key和我们后端接收的key可以不一致,比如前端传递了一个q给后端,而后端是使用keyword字段来接收的,这样就会出现参数接收不到的情况,如果出现这种情况,我们就可以使用@RequestParam来重命名前后端的参数值。
java
//此时q为必传参数
@RequestMapping("/r6")
public String r6(@RequestParam("q") String keyword){
return "接收参数: keyword=" + keyword;
}
//此时q为非必传参数
@RequestMapping("/r7")
public String r7(@RequestParam(value = "q", required = false) String keyword){
return "接收参数: keyword=" + keyword;
}

5. 传递数组
java
//传递数组
@RequestMapping("/r8")
public String r8(String[] arr){
return "接收参数:arr=" + Arrays.toString(arr);
}
可以用',',也可以一个一个地传递。


6. 传递集合
和数组类似,同一个请求参数名有为多个,且需要使用@RequestParam绑定参数关系。
java
//传递集合
@RequestMapping("/r9")
public String r9(@RequestParam List<Integer> list){
return "接收参数:list=" + list;
}

7. 传递JSON数据
7.1 JSON概念
JSON(JavaScript Object Notation)是一种轻量级的数据交换格式,采用文本格式存储和传输数据,易于人阅读和编写,也便于机器解析和生成。它基于 ECMAScript 的子集,但独立于编程语言,广泛用于 Web 应用和 API 交互。
7.2 JSON 语法规则
- 数据以键值对形式表示,键名用双引号包裹,例如
"name": "Alice"
。 - 数据之间用逗号分隔,例如
{"name": "Alice", "age": 25}
。 - 花括号
{}
表示对象(Object),方括号[]
表示数组(Array)。 - 支持的数据类型:字符串、数字、布尔值、对象、数组、
null
。
java
{
"name": "Alice",
"age": 30,
"isStudent": false,
"hobbies": ["reading", "coding"],
"address": {
"city": "New York",
"country": "USA"
}
}
7.3 JSON 与 Java 对象互转
java
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.junit.jupiter.api.Test;
public class JsonTest {
@Test
void testObject2Json() throws JsonProcessingException {
ObjectMapper objectMapper = new ObjectMapper();
//创建java对象
UserInfo userInfo = new UserInfo("zhangsan", 15, 1);
//对象转json
String s = objectMapper.writeValueAsString(userInfo);
System.out.println(s);
}
@Test
void testJson2Object() throws JsonProcessingException {
ObjectMapper objectMapper = new ObjectMapper();
//创建Json字符串
String s = "{\"name\":\"ZhangSan\",\"gender\":1,\"age\":15}";
//Json转对象
UserInfo userInfo = objectMapper.readValue(s, UserInfo.class);
System.out.println(userInfo);
}
}


7.4 JSON优点
- 简单易用:语法简单,易于理解和编写,可以快速地进行数据交换。
- 跨平台支持:JSON可以被多种编程语言解析和生成,可以在不同的平台和语言之间进行数据交换和传输。
- 轻量级:相较于XML格式,JSON数据格式更加轻量级,传输数据时占用带宽较小,可以提高数据传输速度。
- 易于扩展:JSON的数据结构灵活,支持嵌套对象和数组等复杂的数据结构,便于扩展和使用。
- 安全性:JSON数据格式是一种纯文本格式,不包含可执行代码,不会执行恶意代码,因此具有较高的安全性。
7.5 传递JSON对象
传递JSON对象,需要使用@RequestBody注解。
java
//传递Json
@RequestMapping("/r10")
public String r10(@RequestBody UserInfo userInfo){
return "接收参数:" + userInfo.toString();
}

8. 从URL中获取参数
需要在参数前添加@PathVariable注解。
java
//从url中获取参数
@RequestMapping("/article/{articleID}")
public String r11(@PathVariable Integer articleID){
return "接收文章ID:" + articleID;
}

也可以获取多个参数(没有按照顺序也能正确执行)。
java
@RequestMapping("/article/{type}/{articleID}")
public String r12(@PathVariable Integer articleID, @PathVariable String type){
return "接收文章ID:" + articleID + ",type: " + type;
}

9. 上传文件
文件参数类型使用MultipartFile。
java
@RequestMapping("/r13")
public String r13(MultipartFile file) throws IOException {
file.transferTo(new File("D:\\temp\\" + file.getOriginalFilename()));
return "文件上传成功: " + file.getOriginalFilename();
}

点击"+ New file from local machine",在本地选择你要上传的文件。

点击send。

D盘temp文件夹中也成功出现了我们想要上传的文件。

10. 获取Cookie
设置Cookie
保存,就获得另一个Cookie。
也可以添加多个Cookie值。
方法一:
java
@RequestMapping("/r14")
public String r14(HttpServletRequest request, HttpServletResponse response){
Cookie[] cookies = request.getCookies();
if (cookies != null) {
for (Cookie cookie: cookies) {
System.out.println(cookie.getName() + ':' + cookie.getValue());
}
}
return "返回Cookie成功!";
}
request:请求,response:响应
这两个参数不是绑定出现的,所以以上代码可以不用谢response。
方法二:
java
@RequestMapping("/r15")
public String r15(@CookieValue("name") String name) {
return "从注解获取到name的值:" + name;
}

这种方法虽然简洁,但是一次只能获取到一个Cookie值。
11. 获取session
Session是服务器端的机制,我们需要先存储,才能再获取。
java
//session存储
@RequestMapping("/setSession")
public String setSession(HttpServletRequest request) {
//从Cookie中获取SessionID,再根据SessionID获取Session对象
HttpSession session = request.getSession();
//session默认存储在内存中
session.setAttribute("name", "zhangsan");
session.setAttribute("age", 15);
return "session存储成功!";
}

获取session有两种方式:
java
HttpSession getSession(boolean create);
HttpSession getSesion();
参数如果为true,则当不存在会话是新建会话;参数如果为false,则当不存在会话时返回null。
方法一:
java
//获取session
@RequestMapping("/getSession")
public String getSession(HttpServletRequest request) {
HttpSession session = request.getSession(false);
//若用户登录,session有值,用户未登录,session为null
if (session == null) {
return "用户未登录";
} else {
String name = (String) session.getAttribute("name");
return "登录用户为:" + name;
}
}

方法二:
java
@RequestMapping("/getSession2")
public String getSession2(HttpSession session) {
//相当于getSession参数为true,则不存在session为null的情况
String name = (String) session.getAttribute("name");
return "登录用户为:" + name;
}

方法三:
java
@RequestMapping("/getSession3")
public String getSession3(@SessionAttribute("name") String name) {
return "登录用户为:" + name;
}

12. 获取Header
方法一:
java
//获取Header
@RequestMapping("/getHeader")
public String getHeader(HttpServletRequest request) {
String userAgent = request.getHeader("User-Agent");
return "从header获取userAgent:" + userAgent;
}

方法二:
java
@RequestMapping("/getHeader2")
public String getHeader2(@RequestHeader("User-Agent") String userAgent) {
return "从header获取userAgent:" + userAgent;
}

四、响应
1. 返回静态页面
先创建前端页面,注意在resources/static/路径下创建。

html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1>我是Index页面</h1>
</body>
</html>
java
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
@RequestMapping("/resp")
@Controller
public class RespController {
//返回页面
@RequestMapping("/r1")
public String returnPage(){
return "/index.html";
}
}

但若是把类注解写成@RestController,那么运行之后却发现,页面未正确返回,http响应把"/index.html"当做了http响应正文的数据。
随着互联网的发展,目前项目开发流行"前后端分离"模式,Java主要是用来做后端项目的开发,所以也就不再处理前端相关的内容了。MVC的概念也逐渐发生了变化,View不再返回视图,而是返回显示视图时需要的数据。所以前面使用的@RestController其实是返回的数据。
而@RestController=@Controller+@ResponseBody+......
java
//@RestController源码
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Controller
@ResponseBody
public @interface RestController {
@AliasFor(
annotation = Controller.class
)
String value() default "";
}
@ResponseBody既是类注解,又是方法注解。作为类注解的时候,表示该类的所有方法全部返回数据,作为方法注解时,表示该方法返回数据。
如果一个类全部返回数据,可以使用@RestController或者@Controller+@ResponseBody;
如果一个类全部返回页面,使用@Controller。
2. 返回数据
java
//返回数据
@ResponseBody
@RequestMapping("/r2")
public String returnData() {
return "我是前端需要的数据";
}

3. 返回HTML代码片段
java
@ResponseBody
@RequestMapping("/r3")
public String returnHTML() {
return "<h1>我是一级标题</h1>";
}

也可以使用produces设置响应的Content-type:
java
@ResponseBody
@RequestMapping(value = "/r4", produces = "text/plain")
public String returnHTML2() {
return "<h1>我是一级标题</h1>";
}

4. 返回JSON
java
@ResponseBody
@RequestMapping("/r5")
public UserInfo returnJSON() {
return new UserInfo("zhangsan", 20, 1);
}

5. 设置状态码
java
@ResponseBody
@RequestMapping("/r6")
public UserInfo setStatus(HttpServletResponse response) {
response.setStatus(401);
return new UserInfo("zhangsan", 20, 1);
}


使用postman观察,可以看出,状态码不影响页面的显示。
6. 设置Header
java
@ResponseBody
@RequestMapping("/r7")
public String setHeader(HttpServletResponse response) {
response.setHeader("myHeader", "myHeader");
return "设置Header成功";
}


创作不易,给个三连支持一下吧