RequestMapping注解的细节和一些疑惑
1、SpringMVC中是否能出现两个相同的RequestMapping?,即使他们注解的方法不同。
RequestMapping中不能出现两个相同的RequestMapping,即使注解的方法不同
@RequestMapping("/controller")
public String Usercontroller(){
return "usercontroller"
}
@RequestMapping("/controller")
public String Itemcontroller(){
return "itemcontroller"
}
即使上面两个方法方法名不同,返回参数不同,但是还是不能同时出现,因为RequestMapping 相同会导致无法映射为具体的controller
2. RequesMapping注解除了能用在方法上,是否能用在类上?有什么作用?
RequestMapping可以用在方法上,也可以用在类上。如果同时使用(如下面的例子),那么想要映射到admin方法则需要 http/localhost:8080/xxx/Login/admin
,同理映射到common方法则需要http/localhost:8080/xxx/Login/common
,也就是说如果类使用RequestMapping注解,那么先需要映射到类这一个层面上,在映射到类中的具体方法。
@Controller
@RequestMapping("/Login")
public class Login{
@RequestMapping("/admin")
public String admin(){
return "admin";
}
@RequestMapping("/common")
public String common(){
return "common";
}
}
2、SpringMVC中能否多个请求路径映射到一个RequestMapping?
与出现同样的RequestMapping不同的是,多个uri请求可以映射到一个RequestMapping上。通产来说我们controller的代码是下面这样的:
@Controller
public class Login{
@RequestMapping("/admin")
public String admin(){
return "admin";
}
}
这是因为只有一个映射路径/admin
所以我们省略了前面的参数value
,如果想多个路径映射一个RequestMapping,我们可以采用下面的写法:
@Controller
public class Login{
@RequestMapping(value={"/admin","/common"})
public String admin(){
return "admin";
}
}
另外我们通过查看RequestMapping注解部分源代码:
@AliasFor("path")
String[] value() default {};
@AliasFor("value")
String[] path() default {};
发现,其实value
这个属性等同于path
。
3、SpringMVC中RequestMapping是否支持模糊匹配呢?
RequestMapping支持模糊匹配,我们将这种模糊匹配风格称之为Ant风格,为啥叫Ant风格我也不知道。具体的规则是这样的:
? 匹配一个字符
* 匹配0到N个任意字符
** 匹配0到N个字符,且左右两边不能出现字符,只能出现/ (人话就是只能放末尾)
示例:
*
:匹配任意单个字符。例如,/user/*/orders
可以匹配/user/123/orders
或/user/abc/orders
等。
**
:匹配任意数量(包括零)的目录。这在需要处理多层路径结构时非常有用。例如,/resources/**
可以匹配/resources/css/style.css
、/resources/js/app.js
或甚至更深的路径。
?
:匹配任何单个字符。例如,/user/{name}?/profile
中的?表示该位置可以是任意单个字符,如/user/johnD/profile
或/user/janeR/profile
4、SpringMVC中RequestMapping占位符的使用
@RequestMapping注解中的占位符是Spring MVC框架中用于路径变量匹配的一个重要特性。它允许你在URL路径中使用花括号{}包含的变量名,这样当请求到达时,这些变量将被解析并传递给控制器方法中的相应参数。这在RESTful风格的服务设计中尤其常见,因为它允许更自然地表达资源的URL。
普通的请求方式是http//localhost:8080/springmvc/onlinetime?username="zhangsan"
但是RESTful风格的请求是http//localhost:8080/springmvc/onlinetime/value1/value2
。所有的参数都变为uri中/value
,这样子似乎看起来更加清爽。那么我们该如何获取RESTful风格uri中的参数呢?参考如下代码
@RequestMapping(value="/testRESTful/{id}/{username}/{age}")
public String testRESTful(
@PathVariable("id")
int id,
@PathVariable("username")
String username,
@PathVariable("age")
int age){
System.out.println(id + "," + username + "," + age);
return "testRESTful";
}
其中的花括号{}就是我们所说的占位符,在RequstMapping的value参数中用{}将参数名称包裹,那么便可以活动参数。变量名为RequstMapping中value参数中用{}包裹的部分。关于RESTful风格编程,后面会出一篇博文简单介绍。
5、SpringMVC中RequestMapping注解中method的属性
现在我们有一段代码:
@Controller
public class Login{
@RequestMapping("/common")
public String admin(){
return "admin";
}
}
毫无疑问,我们只需要请求http://xxxxx.../common
便可以映射到对应方法上。有没有发现似乎少了什么,总觉得缺点啥东东? 是的没错,如果按照上面代码来说,不管是请求该uri的post方法还是get方法,又或是其他方法都可以进行映射。假设我就只需要该uri且请求方法为post的请求映射上去呢,该怎么办?这个时候就需要用到RequestMapping中的method属性指定请求类型。
请看RequestMapping注解部分源码:
public @interface RequestMapping {
xxxxxx....
RequestMethod[] method() default {};
xxxxxx....
}
不能说和value相似,兼职是亲生兄弟,熟悉的RequestMethod[]
意味着他和value一样可以有多个值。
接下来咱们对RequestMethod
这个关键字继续进行深入:
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//
package org.springframework.web.bind.annotation;
import org.springframework.http.HttpMethod;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
public enum RequestMethod {
GET,
HEAD,
POST,
PUT,
PATCH,
DELETE,
OPTIONS,
TRACE;
xxxx.............
}
发现RequestMethod
是一个 enum
枚举,好了一切真相大白。
@Controller
public class Login{
@RequestMapping(value="/common",method={RequestMethod.GET,RequestMethod.POST})
public String admin(){
return "admin";
}
}
6、RequestMapping中的衍生品
感觉些method的属性好麻烦还需要记忆RequestMethod
,真的很费脑,能不能给我一个已经制定好请求方法的RequestMapping,并且能减少我书写的麻烦。yes,RequestMapping中的衍生品
应召出现,以PostMapping
为例,他是指定好请求方法为POST
的RequestMapping
,使用这个注解久不需要写 method
。
我们扒一扒PostMapping
的底裤:
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@RequestMapping(
method = {RequestMethod.POST}
)
public @interface PostMapping {
@AliasFor(
annotation = RequestMapping.class
)
String name() default "";
@AliasFor(
annotation = RequestMapping.class
)
String[] value() default {};
@AliasFor(
annotation = RequestMapping.class
)
String[] path() default {};
@AliasFor(
annotation = RequestMapping.class
)
String[] params() default {};
@AliasFor(
annotation = RequestMapping.class
)
String[] headers() default {};
@AliasFor(
annotation = RequestMapping.class
)
String[] consumes() default {};
@AliasFor(
annotation = RequestMapping.class
)
String[] produces() default {};
}
所以各位爱卿有何看法? 换肤!!!妥妥换肤 必须封号!😢
还有GetMapping、PutMapping、DeleteMapping、PatchMapping 通通举报 😊
7、Web请求方式
我们在上面介绍了如何通过method的属性指定请求方式,或者直接使用PostMapping类似这种RequestMapping中的衍生品。但是我们并没有介绍不同的请求方式之间的不同。我觉得大家应该见名知意。但是我还是要写。嘿嘿!接下来介绍常见请求和作用效果,以及post和get二选一(头大,能不能两个都要)
7.1 常见请求和作用效果
- GET:获取资源,只允许读取数据,不影响数据的状态和功能。使用 URL 中传递参数或者在 HTTP 请求的头部使用参数,服务器返回请求的资源。
- POST:向服务器提交资源,可能还会改变数据的状态和功能。通过表单等方式提交请求体,服务器接收请求体后,进行数据处理。
- PUT:更新资源,用于更新指定的资源上所有可编辑内容。通过请求体发送需要被更新的全部内容,服务器接收数据后,将被更新的资源进行替换或修改。
- DELETE:删除资源,用于删除指定的资源。将要被删除的资源标识符放在 URL 中或请求体中。
- HEAD:请求服务器返回资源的头部,与 GET 命令类似,但是所有返回的信息都是头部信息,不能包含数据体。主要用于资源检测和缓存控制。
- PATCH:部分更改请求。当被请求的资源是可被更改的资源时,请求服务器对该资源进行部分更新,即每次更新一部分。
- OPTIONS:请求获得服务器支持的请求方法类型,以及支持的请求头标志。“OPTIONS *”则返回支持全部方法类型的服务器标志。
- TRACE:服务器响应输出客户端的 HTTP 请求,主要用于调试和测试。
- CONNECT:建立网络连接,通常用于加密 SSL/TLS 连接。
- 使用超链接以及原生的form表单只能提交get和post请求,put、delete、head请求可以使用发送ajax请求的方式来实现。
- 使用超链接发送的是get请求
- 使用form表单,如果没有设置method,发送get请求
- 使用form表单,设置method="get",发送get请求
- 使用form表单,设置method="post",发送post请求
问一个问题:<form method ="put/delete/head></form>
这个表单使用的时候,用啥方式?
回答错误。 用get捏 因为表单只支持post和get并且没有设置的话默认get.
7.2 GET和POST区别和选择
post和get有一些区别,这决定了我们是使用get还是使用post。
数据显示:*get请求的数据会显示在uri上,但是post请求的数据是放在请求体中。
数据长度:get请求携带的数据是有长度限制的,而post理论上是无限长度
数据类型:get只能发送普通的字符串并且长度还有限制,但是post可以发送任何类型的数据。包括普通字符串,流媒体等信息:视频、声音、图片。
安全性:理论上来说get比post安全,因为get不会修改服务器数据,而是从服务器请求数据,post则是更多用于修改服务器的数据
是否支持缓存:post请求是支持缓存的,也就是说post的每一次请求都是新请求,但是get如果发送二次请求则会走缓存
如何选择?
- 如果你是想从服务器上获取资源,建议使用GET请求,如果你这个请求是为了向服务器提交数据,建议使用POST请求。
- 大部分的form表单提交,都是post方式,因为form表单中要填写大量的数据,这些数据是收集用户的信息,一般是需要传给服务器,服务器将这些数据保存/修改等。
- 如果表单中有敏感信息,建议使用post请求,因为get请求会回显敏感信息到浏览器地址栏上。(例如:密码信息)
- 做文件上传,一定是post请求。要传的数据不是普通文本。
- 其他情况大部分都是使用get请求。
8、RequesMapping的params属性
params属性用来设置通过请求参数来映射请求。
对于RequestMapping注解来说:
- value属性是一个数组,只要满足数组中的任意一个路径,就能映射成功
- method属性也是一个数组,只要满足数组中任意一个请求方式,就能映射成功。
- params属性也是一个数组,不过要求请求参数必须和params数组中要求的所有参数完全一致后,才能映射成功。
params有四种使用方法,具体如下:
1.@RequestMapping(value="/login", params={"username", "password"}) 表示:请求参数中必须包含 username 和 password,才能与当前标注的方法进行映射。
2.@RequestMapping(value="/login", params={"!username", "password"}) 表示:请求参数中不能包含username参数,但必须包含password参数,才能与当前标注的方法进行映射。
3.@RequestMapping(value="/login", params={"username=admin", "password"}) 表示:请求参数中必须包含username参数,并且参数的值必须是admin,另外也必须包含password参数,才能与当前标注的方法进行映射。
4.@RequestMapping(value="/login", params={"username!=admin", "password"}) 表示:请求参数中必须包含username参数,但参数的值不能是admin,另外也必须包含password参数,才能与当前标注的方法进行映射。
注意:如果前端提交的参数,和后端要求的请求参数不一致,则出现400错误!!!
HTTP状态码400的原因:请求参数格式不正确而导致的。
9、RequestMapping的header属性
headers和params原理相同,用法也相同。
当前端提交的请求头信息和后端要求的请求头信息一致时,才能映射成功。
请求头信息怎么查看?在chrome浏览器中,F12打开控制台,找到Network,可以查看具体的请求协议和响应协议。在请求协议中可以看到请求头信息,都是以键值对形式存在的:例如
header的四种用法:
1.@RequestMapping(value="/login", headers={"Referer", "Host"}) 表示:请求头信息中必须包含Referer和Host,才能与当前标注的方法进行映射。
2.@RequestMapping(value="/login", headers={"Referer", "!Host"}) 表示:请求头信息中必须包含Referer,但不包含Host,才能与当前标注的方法进行映射。
3.@RequestMapping(value="/login", headers={"Referer=http://localhost:8080/springmvc/", "Host"}) 表示:请求头信息中必须包含Referer和Host,并且Referer的值必须是http://localhost:8080/springmvc/,才能与当前标注的方法进行映射。
4.@RequestMapping(value="/login", headers={"Referer!=http://localhost:8080/springmvc/", "Host"}) 表示:请求头信息中必须包含Referer和Host,并且Referer的值不是http://localhost:8080/springmvc/,才能与当前标注的方法进行映射。
注意:如果前端提交的请求头信息,和后端要求的请求头信息不一致,则出现404错误!!!
总结:
事实上,header、value、method、params都是帮助RequestMapping好的映射。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?