[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的注解就介绍到这里了,如有纰漏还请指出~~

相关推荐
许彰午7 小时前
我手写了一个 Java 内存数据库(四):索引引擎、SQL 解析与总结
java·数据库·sql
TO_ZRG7 小时前
Android Broadcast Receiver完全入门指南
java·后端·spring
Knight_AL7 小时前
使用 CyclicBarrier + 自定义线程池实现 SpringBoot 并行报表(完整性能对比)
java·spring boot·后端
人道领域7 小时前
【LeetCode刷题日记】347.前k个高频元素
java·数据结构·算法·leetcode
tjl521314_217 小时前
02C++ 静态变量与链接性
java·jvm·c++
摇滚侠8 小时前
Public Key Retrieval is not allowed
java·数据库·mysql
计算机学姐8 小时前
基于微信小程序的宠物服务系统【uniapp+springboot+vue】
java·vue.js·spring boot·mysql·微信小程序·uni-app·宠物
lst04268 小时前
Maven 构建命令
java·maven
梅孔立8 小时前
Aspose.Words Java 表格动态删列、合并列、表头重建、全局字体统一解决方案
java·开发语言·word·aspose·在线编辑
空中海8 小时前
第一章:入门篇 — Maven 核心概念与基础使用
java·maven