[SpringMVC] SpringWebMVC常见注解介绍

本文将来简单介绍一下SpringMVC中的常见注解


1. 路由映射:一切连接的起点

@RequestMapping

这是最常被用到的注解,它是用来注册接口的路由映射的。简单的说,就是把浏览器输入的 URL 对应到你代码里的某个类或方法。

场景化铺垫 : 想象你在双十一凌晨疯狂抢购,你点击"结算"按钮的那一刻,浏览器发出的请求必须精准撞进服务器对应的"处理订单"的方法里,这就是 @RequestMapping 在后台立的功。

java 复制代码
@RestController  
@RequestMapping("/hello")  
public class UserController {  
    @RequestMapping ("/sayHi")  
    public String sayHi(){  
        return "hello ,Spring MVC";  
    }  
}

访问 http://127.0.0.1:8080/hello/sayHi 即可调用此方法,url的路径就是我们在类前面添加的注解路径("/hello") + 方法前的注解路径("/sayHi"),

在浏览器中直接输入对应的网址,即可观察到return 的结果

当然,也可以使用Postman这样的工具来观察接口的返回结果

避坑指南

  • URL 路径前面加不加 /(斜杠)都可以,Spring 启动时会自动判断并拼接,但是还是建议在路径前添加 /

  • 它既可以修饰类(设置初始路径),也可以修饰方法(设置具体路径)。

  • 默认它支持 GET、POST 等所有请求方式。如果想限定某种方式,需要设置 method 属性。

不过除了上面直接在方法上面修改注解的的方式之外,也可以在方法的参数列表中添加对应的method来限制请求的类型,

此时再尝试发送post请求就能正常处理了

2. 参数传递:别再拿不到数据了!

在和用户程序交互时,获取参数是核心。这里有几个注解必须掌握:

@RequestParam(后端参数重命名)

场景化铺垫 : 前端小哥在页面上定义的参数名叫 time,但你在后端为了规范非要叫 createtime。这时候如果不加处理,数据根本传不过来,直接返回 null 让你怀疑人生!

java 复制代码
@RequestMapping("/m4")
public Object method_4(@RequestParam(value = "time", required = false) String createtime) {
    return "接收到参数createtime:" + createtime;
}

注意 :使用了 @RequestParam 后,该参数默认变为必传 。如果想设置成非必传,记得加上 required = false

@RequestBody(接收 JSON 数据)

场景化铺垫 : 现在的开发流行"前后端分离",前端传过来的往往是一个复杂的 JSON 对象。如果你还是像以前那样直接传参,后端拿到的对象属性全都是 null

java 复制代码
@RequestMapping("/m7")
public Object method7(@RequestBody Person person) {
    return person.toString();
}

敲黑板 :接收 JSON 对象必须 使用 @RequestBody,否则数据无法成功绑定。

比如我们先定义一个person类对象,即可就可以给通过json的方式来对person中的属性进行赋值,以下方法过于繁琐,后面可以使用lombok插件的方式来自动为我们在编译时生成对应属性获取方法

java 复制代码
public class Person {  
    private int id;  
    private String name;  
    private int age;  
    private String address;  
  
    public void setId(int id) {  
        this.id = id;  
    }  
  
    public void setName(String name) {  
        this.name = name;  
    }  
  
    public void setAge(int age) {  
        this.age = age;  
    }  
  
    public void setAddress(String address) {  
        this.address = address;  
    }  
  
    public String getName() {  
        return name;  
    }  
  
    public int getId() {  
        return id;  
    }  
  
    public int getAge() {  
        return age;  
    }  
  
    public String getAddress() {  
        return address;  
    }  
  
    @Override  
    public String toString() {  
        return "Person{" +  
                "id=" + id +  
                ", name='" + name + '\'' +  
                ", age=" + age +  
                ", address='" + address + '\'' +  
                '}';  
    }  
}

@PathVariable(获取 URL 中的变量)

这个注解主要作用在请求 URL 路径上的数据绑定。

java 复制代码
// 访问路径类似:/hello/m8/5/zhangsan
@RequestMapping("/m8/{id}/{name}")
public String method8(@PathVariable Integer id, @PathVariable("name") String userName) {
    return "解析参数id:" + id + ", name: " + userName;
}

不过这里也涉及到一点,那就是把int类型的id定义为包装类型Integer,为什么不定位int呢?其实这是为了避免状态码500异常 ,5XX的状态码一般被认为是服务器处理失败

为何会出现500异常?如果把null传递给 int ,就会出现类型不匹配,这在前端参数传递中如果传递失败就会出现.比如把int类型的实际传递一个String,但是当我们使用Integer包装类型,则会只出现400等4开头的状态码

3. 会话与 Header:识别"自己人"

@CookieValue & @SessionAttribute

场景化铺垫: 医院看病需要"就诊卡"。你第一次挂号得到这张卡(Session 创建),以后去抽血、拍片只需要刷一下卡(携带 Cookie/SessionID),医生就能识别你的身份。在 Web 开发中,这就是会话机制。

HTTP无连接,每次客户端与服务器建立连接服务器都无需记住客户端的状态,这是出于传输效率考虑的.但是此时却使用了会话机制来保存状态,这难道不是与"无连接",的特性相违背吗?

实则不然,试想一下,你每次轻车熟路的点击一个你登陆过很多次的网站,但是每次都要求你输入登录账号和密码.这给人的体验自然是极其不良好的,http的无连接是在底层架构的选择上实现的,是基于TCP的无连接特性来保证高效传输,但是在业务上是需要使得其变得有状态,这就需要cookie和session来配合实现

这种设计逻辑如下:

  1. HTTP(基础层): 保持无状态,确保传输的轻量和高并发能力。

  2. Cookie/Session(应用层): 像是一个"临时身份证"。服务器不主动记你,而是发给你一个编号(Session ID),你每次来的时候自己带上。

维度 HTTP 无状态 (Stateless) Cookie/Session 机制
目的 追求高并发、易扩展、低耦合 追求业务连续性、用户识别
位置 协议传输层/网络架构 业务应用层
服务器压力 极低(不存连接上下文) 中等(仅存必要的业务数据)
  • @CookieValue:从 Cookie 中获取值。

  • @SessionAttribute:从 Session 中获取值。

java 复制代码
@GetMapping("/set")  
public String setData(HttpServletResponse response, HttpSession session) {  
    // 显式写入一个 Cookie    Cookie cookie = new Cookie("user_tag", "AI-Explorer-99");  
    cookie.setPath("/");  
    cookie.setMaxAge(3600); // 有效期1小时  
    response.addCookie(cookie);  
  
    // 向 Session 中存入一个属性  
    session.setAttribute("user_level", "Vip-Member");  
  
    return "数据已写入!Cookie: user_tag=AI-Explorer-99, Session: user_level=Vip-Member";  
}  
  
  
//获取cookie - 获取名为user_tag的cookie  
@GetMapping("/getCookie")  
public String getData(@CookieValue("user_tag") String userTag) {  
  
    return "user_tag:" + userTag;  
}  
  
//获取session  
@GetMapping("/getSession")  
public String getSessionData(@SessionAttribute("user_level") String userLevel) {  
    return "user_level:" + userLevel;  
}

由于cookie是存储在客户端(浏览器)中,我们需要把构建好的cookie通过
HttpServletResponse 对象将其添加到响应头中。

session存储在服务端中,需要操作 HttpSession 对象的setAttribute方法,往Session中存储内容

我们先启动服务,存储Cookie和Session,随后通过接口尝试获取

可以看到存储的cookie和session都能正常被拿到.

这里参考cookie是客户端存储,session是服务端存储,不妨我们来重新启动一下服务,来观察还能正常获取cookie和session


4. 响应处理:到底是页面还是数据?

@Controller vs @RestController

我们先在src/main/resources/static/ 这个路径下写一个简单的前端页面index.html

html 复制代码
<!DOCTYPE html>  
<html lang="en">  
<head>  
    <meta charset="UTF-8">  
    <meta name="viewport" content="width=device-width, initial-scale=1.0">  
    <title>Document</title>  
</head>  
<body>  
    hello cheems , 我是index页面  
</body>  
</html>

同时在@RestController这个注解的类下添加一个方法,来尝试调用这个接口,为我们返回前端渲染的页面

java 复制代码
@RestController  
@RequestMapping("/request")  
public class RequestController {
	//返回静态页面  
	@RequestMapping("/getIndex")  
	public Object getIndex(){  
		return "/index.html";  
	}
}

但是当输入:http://127.0.0.1:8080/request/getIndex 时,只返回了一个字符串,看上去我们的接口是吧其当作String类型给return了。这是因为在 Spring MVC 中,@RestController 的作用相当于 @Controller + @ResponseBody。这意味着该类下所有方法的返回值都会被直接写入 HTTP 响应体中(当作普通字符串),而不会被解析为跳转页面的路径。

那么如何才能正确拿到这个页面呢?这个时候就需要来使用 @Controller了

  • @Controller :定义一个控制器,默认返回视图(静态页面)。

  • @ResponseBody :定义返回的数据格式为非视图(直接返回文本、HTML 片段或 JSON)。

  • @RestController :本质上就是 @Controller + @ResponseBody,适合现在流行的前后端分离模式,直接返回数据给前端渲染。


5. 总结

Spring MVC 的学习本质上就是掌握这些注解的用法。通过这些注解,我们可以轻松完成:

  1. 建立连接(@RequestMapping)

  2. 获取请求参数(@RequestParam, @RequestBody, @PathVariable)

  3. 给出响应(@ResponseBody, @RestController)

下面是一个核心注解总结表

Spring MVC 核心注解功能总结表,仅供参考

注解名称 主要功能描述 常用场景示例
@RequestMapping 路由映射:将用户请求的 URL 绑定到特定的类或方法上 。 想象双十一凌晨,你的点击必须精准命中"结算"逻辑 。
@RequestParam 后端参数重命名:当前端传参 key 与后端变量名不一致时进行手动映射 。 页面传的是 time,后端接收变量叫 createtime
@RequestBody 接收 JSON 数据:将 HTTP 请求正文中的 JSON 字符串转为 Java 对象 。 前端通过 Ajax 发送了一个包含用户详细信息的 JSON 结构 。
@PathVariable 获取路径变量:从动态 URL 路径中直接提取参数值 。 访问特定资源,如:http://.../user/5 中的 5 就是 ID 。
@RequestPart 文件上传:用于接收前端通过表单上传的文件数据(MultipartFile) 。 用户在个人资料页上传头像图片 cat.jpg
@ResponseBody 返回数据:表示该方法返回的是响应正文数据,而非跳转视图页面 。 仅给前端返回一个"操作成功"的字符串或一组 JSON 数据 。
@Controller 定义控制器:声明类为控制器,默认会将返回值解析为视图(HTML)路径 。 访问 /index 时,服务器需要跳转并展示 index.html 页面 。
@RestController 数据控制器 :是 @Controller@ResponseBody 的组合,默认返回数据 。 目前主流的前后端分离开发,后端只负责提供 API 数据接口 。
@CookieValue 获取 Cookie:从 HTTP 请求头的 Cookie 字段中快速提取特定名称的值 。 检查浏览器是否保存了用户的特定偏好设置或令牌 。
@SessionAttribute 获取 Session:从服务器端的会话(Session)中获取存储的用户信息 。 确认当前操作的用户是否已经登录(从 Session 取出 username) 。
@RequestHeader 获取 Header:从 HTTP 请求报头中获取特定的 Header 信息(如 User-Agent) 。 识别用户是用什么浏览器访问的,以便进行兼容性处理 。

💡 每日思考题

既然 @RequestMapping 默认支持所有请求方式,而在企业级接口开发中,我们通常会严格区分 GET 和 POST。除了在 @RequestMapping 里手动指定 method 属性外,Spring 还提供了哪些更简洁、语义更明确的注解来替代它?(提示:想想组合注解)

有关SpringMVC的注解就介绍到这里了,如有纰漏还请指出~~

相关推荐
me8322 小时前
【Java】Spring MVC接口执行流程详解:从前端请求到参数封装全解析(前端到底是怎么和后端交互的?)
java·spring·mvc
niucloud-admin2 小时前
插件开发——upgrade 插件版本升级
java
vortex52 小时前
Gradle 从入门到实战
java·gradle
代码丰2 小时前
Zero Code Studio:LangChain4j 工具调用 + LangGraph4j 工作流双模式的 AI 网站生成系统
java·人工智能
云烟成雨TD2 小时前
Spring AI 1.x 系列【28】基于内存和 MySQL 的多轮对话实现案例
java·人工智能·spring
Lyyaoo.2 小时前
【JAVA基础面经】String、StringBuffer、StringBuilder
java·开发语言
TeamDev2 小时前
JxBrowser 8.18.2 版本发布啦!
java·前端·跨平台·桌面应用·web ui·jxbrowser·浏览器控件
晴天sir2 小时前
Redis 在业务中的几种典型用法
java·数据库·redis
WJX_KOI3 小时前
MemOS —— 为大语言模型 (LLMs) 和智能体打造的记忆操作系统。
java·人工智能·语言模型