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为例,他是指定好请求方法为POSTRequestMapping ,使用这个注解久不需要写 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 连接。

  1. 使用超链接以及原生的form表单只能提交get和post请求,put、delete、head请求可以使用发送ajax请求的方式来实现。
  2. 使用超链接发送的是get请求
  3. 使用form表单,如果没有设置method,发送get请求
  4. 使用form表单,设置method="get",发送get请求
  5. 使用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如果发送二次请求则会走缓存

如何选择?

  1. 如果你是想从服务器上获取资源,建议使用GET请求,如果你这个请求是为了向服务器提交数据,建议使用POST请求。
  2. 大部分的form表单提交,都是post方式,因为form表单中要填写大量的数据,这些数据是收集用户的信息,一般是需要传给服务器,服务器将这些数据保存/修改等。
  3. 如果表单中有敏感信息,建议使用post请求,因为get请求会回显敏感信息到浏览器地址栏上。(例如:密码信息)
  4. 做文件上传,一定是post请求。要传的数据不是普通文本。
  5. 其他情况大部分都是使用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好的映射。

posted @ 2024-07-03 10:43  BLBALDMAN  阅读(24)  评论(0编辑  收藏  举报