news 2026/8/10 13:11:57

SpringMVC的五大注解

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
SpringMVC的五大注解

一个SpringBoot项目首先会引入的依赖就是SpringMVC

<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-webmvc</artifactId> </dependency>

一、SpringMVC模型

所谓MVC就是:Model、View、Controller三层。

Model作为数据的载体,View作为视图层,负责给客户端返回包装好的数据,Controller负责接收View发来的请求,调用Model并协调View和Model的关系。

那么前端在哪个范围呢,前端不在上述三个范围中的任何一个里!前端是专门发起请求向后端请求数据的,与前端直接交互的是浏览器

其关系大致是这样的:

那么作为后端开发人员,掌握SpringMVC模型是十分有必要的。

这篇博客就和博主来挖掘一下SpringMVC模型的常用开发注解吧。

二、View层

视图层,可以向浏览器返回一个页面,也可以返回一段打包好的数据。

但是,现代开发模式(前后端分离),前端变得越来越复杂那么就需要有专门的开发者去做,并且两种开发方式和思维都有所不同。前端主要就是做数据渲染处理和请求的发起和响应。

那么在这种情况下,后端的View层就被完全弱化,只希望返回纯数据,而非渲染好的页面。

因此View就没有必要单独新建一个软件包了,所有View层的操作和Controller层合并为同一层。

那么我们以此给项目分层,先做如下分层:

在controller层写一个Person类,等下需要演示注解。

2.1@ResponseBody

这个注解表示:标记方法/类的返回值不经过视图解析器,直接以HTTP响应体的形式返回(如JSON/字符串),跳过View层渲染。

如果加在类上,则表示该类中的所有方法返回值都是纯数据;加在方法上则表示该方法返回的纯数据。这个注解是弱化View层的核心注解

这个注解最爱和谁搭配呢?@RestController = @ResponseBody + @Controller

这是个类注解,需要加在类上。

我们前面讲了,View层的工作和Controller层合并在一起,那么我是用@RestController这个注解就两全其美了。即能将controller标注出来,而且可以将类中的所有方法的返回值跳过View解析器直接返回给浏览器。

目前还不能举例子,我们看完Controller层就可以了。

三、Controller层

前面讲到,现代开发模式实行的是“前后端分离”,后端弱化View层。

因此View的一些工作就和Controller合并在一起了。

3.1核心控制器注解

3.1.1@Controller

这个注解是类注解,用于标记一个类为控制器组件,使其被SpringIoC容器扫描并管理。该类中的方法可以通过注解映射HTTP请求,接收前端请求和协调业务层处理逻辑,返回视图名。

但是如果加了@ResponseBody则是返回数据。

3.1.2@RequestMapping

浏览器发起了请求后端怎么接收并作出对应的响应呢?这就需要思考浏览器是怎么获取后端服务的。

浏览器中有一个一个网址,形如:http://127.0.0.1:8080/index.html

或者形如:http://127.0.0.1:8034/people/getPeople?name='zhangsan'

两种URL不同之处在于前者请求的是一个HTML页面,这个HTML页面是提前写好的,作为一种静态资源存储在服务器中。

后者有一个访问的路径,在people目录下的getPeople资源,然后跟一个简单的参数。

前端在请求资源时,一定要知道资源的准确位置,例如/index.html,/people/getPeople

那么,SpringMVC就将每个资源用目录来建立逻辑关系。

使用@RequestMapping("/逻辑目录")用于将后端接口(资源,接口也是资源的一部分)映射到指定的URL路径,前端就需要根据这个逻辑目录来发起HTTP请求来访问对应资源。因此前端开发人员要和后端开发人员密切配合确保资源的位置是准确无误的,同时这样定位资源的文档应该在接口文档中明确规定好的。

现在举个例子:

先给这个类加上“/person”根目录。

类中有一个方法getPeople,这个方法没有参数,并且使用@RequestMapping("/getPeople")将这个接口映射到/person/getPeople这个URL上。前端只需要指定这个目录,无需参数发起请求,后端便会执行对应的方法。

运行程序后,在浏览器输入对应的URL即可访问。

URL:http://localhost:8080/person/getPerson

也可以是:htpp://127.0.0.1:8080/person/getPerson

因为目前项目在我们本机上运行,因此IP地址填写自己的即可,这里采用一个特殊的IP127.0.0.1来快速表示自己(也可以用localhost),紧跟着的就是端口号。8080是SpringBoot项目启动的默认端口,可以更改,但在只有一个项目时可以不用管。

3.1.3@RestController

正如前面讲到:@RestController = @ResponseBody + @Controller

前面的例子中,我们并没有加@Controller注解,而是使用的是@RestController注解。那么我如果将其修改成@Controller会怎么样?

运行程序。

404,找不到资源。为什么?如果不加@ResponseBody则SpringBoot会自动去将其解析成视图,找不到对应的视图与之对应,就会报错。

我们在resources/templates文件夹下创建一个HTML文件,这个目录时SpringBoot和Thymeleaf的默认约定,专门存放需要后端渲染的动态HTML页面,这个目录和存放纯静态资源的目录resources/static有本质区别。

然后引入一个视图解析器Thymeleaf依赖:

<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-thymeleaf</artifactId> </dependency>

新建一个Controller,然后写获取Html页面的方法,返回值为String。

这样就会根据返回的字符串查找视图名称,并返回匹配的视图。

3.2请求映射注解

前面我们讲到浏览器会发出一个携带URL的请求,同时还有一个重要的请求方式。

有Post,Get、Delete、Put,每种请求的格式大题上是一致的,从某种程度上来说每种请求方式是通用的,但是出于标准我们重点区分Post和Get。

浏览器默认发出的是什么请求呢?

答案是Get请求,@RequestMapping注解是一个通用的注解,会响应所有类型的请求。

但是我们还有更加细致的注解,分别是:@GetMapping 和 @PostMapping

浏览器的请求方式要和后端设置的接收请求方式一致,否则就不能成功响应。

但是如果改成@PostMaping则不能请求成功

浏览器报错显示请求方式不被允许。

3.3请求参数获取

3.3.1@RequestParam

这个注解用前端携带参数请求后端时,协调前后端参数名不一致问题。

正常情况下,如果前后端参数需要约定成一致的,但如果处于某种原因没法达成一致,则可以这个注解把前端的参数正确映射到后端参数上,如:

但是如果前端不知道每个参数的准确名称,那么就会和后端接口的参数匹配不上,从而匹配失败,a ,b 会为空,制造问题。

报错500,后端错误。

那么就可以使用这种方式来达成一致:

第一个参数为c,仅供前端使用。

3.3.2@PathVariable

获取URL路径变量,如people/{id}

3.3.3@RequestBody

这个注解常用来接收前端传来的Json/XML格式的参数,自动封装成对象。为了能传递Json格式的参数,我们最方便的是使用postman来模拟发送请求。

此时前端必须发送Post请求,因为Get请求没有请求体。

后端可以采用Map或者对应的实体来接收,如果采用实体接收,那么实体属性必须有相应的Setter和Getter方法,否则会参数绑定失败。此外,采用实体接收如果Json有多余的字段则会被舍弃,实体的属性没有被赋值的则是null。

Person实体

package com.miao.springmvcannotationdemo.model; public class Person { private String name; private Integer age; public Person(){ } public Person(String name,int age){ this.name = name; this.age = age; } public void setName(String name){ this.name = name; } public void setAge(int age){ this.age = age; } public String getName(){ return this.name; } public Integer getAge(){ return this.age; } @Override public String toString(){ return this.name+" "+this.age; } }

后端

postman请求及响应如下:

但是如果缺少@RequestBody则会请求失败。

四、Model层

Model也可以成为DAO层,或者是Entity实体层,用来存放实体类其与数据库表对应。就相当于是一个中间层,每次查询时会把查到的数据填充到我们的实体类中,这样就可以被Java操作使用。

例如有这样一张User表(简化):

idbigint
user_namevarchar(50)
agetinyint unsigned

那么可以构建出一个与之对应的实体类:

public class User { private Long id; private String userName; private Integer age; }

注意mysql中的字段是蛇形命名法,在Java中的属性则是使用小驼峰命名法。

这是命名规范,如果刻意追求两者完全一致也行,因为最后在数据填充时就是根据属性一一匹配的。我们后面可以利用mybatis的驼峰映射功能解决,所以不用为此担心。

现在我们有了这样一个实体类,但是缺少对应的set和get方法。我们可以选择手动添加,注意set和get的方法名必须按照setId()、setUserName()等小驼峰命名方式。否则后面因为方法名的错误会导致数据填充失败。

前面也讲到使用实体类接收对象时,必须有对应的set和get方法,其次就是方法名要正确。

五、总结

以上就是作者对SpringMVC的理解,后续学习mybatis时我们有Lombok依赖,使用@Data注解可以不用手动设置set和get方法。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/8/10 13:10:29

Nmap从零入门:网络安全信息收集核心工具详解与实战

你刚接触网络安全&#xff0c;是不是经常听到“Nmap”这个名字&#xff0c;却不知道从何下手&#xff1f;网上教程要么太零散&#xff0c;要么直接甩出一堆命令参数&#xff0c;看得人一头雾水。你需要的不是一个冰冷的命令手册&#xff0c;而是一个能带你从零开始&#xff0c;…

作者头像 李华
网站建设 2026/8/10 13:09:37

BilibiliDown终极指南:5分钟掌握B站视频下载与音频提取技巧

BilibiliDown终极指南&#xff1a;5分钟掌握B站视频下载与音频提取技巧 【免费下载链接】BilibiliDown (GUI-多平台支持) B站 哔哩哔哩 视频下载器。支持稍后再看、收藏夹、UP主视频批量下载|Bilibili Video Downloader &#x1f633; 项目地址: https://gitcode.com/gh_mirr…

作者头像 李华
网站建设 2026/8/10 13:07:56

GetQzonehistory:三步搞定QQ空间历史说说完整备份终极指南

GetQzonehistory&#xff1a;三步搞定QQ空间历史说说完整备份终极指南 【免费下载链接】GetQzonehistory 获取QQ空间发布的历史说说 项目地址: https://gitcode.com/GitHub_Trending/ge/GetQzonehistory 在数字记忆日益珍贵的今天&#xff0c;QQ空间里那些记录青春点滴的…

作者头像 李华
网站建设 2026/8/10 13:06:18

AI编程Agent:从代码补全到工作流引擎的范式跃迁

1. 从“遥控器”到“副驾驶”&#xff1a;AI编程Agent的范式跃迁 如果你在2023年问我&#xff0c;AI编程助手是什么&#xff0c;我可能会说&#xff0c;它是一个更聪明的代码补全工具&#xff0c;或者一个能回答技术问题的聊天机器人。但到了2024年&#xff0c;这个答案已经彻底…

作者头像 李华
网站建设 2026/8/10 13:05:09

目标检测中的PS RoI Pooling:原理、实现与全卷积设计思想

1. 从R-CNN到R-FCN&#xff1a;目标检测的演进与PS RoI Pooling的诞生如果你在目标检测领域摸爬滚打过一段时间&#xff0c;从R-CNN、Fast R-CNN、Faster R-CNN一路走来&#xff0c;再到YOLO、SSD&#xff0c;你可能会觉得&#xff0c;检测器的核心矛盾似乎已经从“准不准”转向…

作者头像 李华