RequestMapping注解

news2024/10/7 18:28:22

一、RequestMapping的作用

@RequestMapping 注解是 Spring MVC 框架中的一个控制器映射注解,用于将请求映射到相应的处理方法上。具体来说,它可以将指定 URL 的请求绑定到一个特定的方法或类上,从而实现对请求的处理和响应。

二、RequestMapping的出现位置

在这里插入图片描述

通过RequestMapping的源码可以看到RequestMapping注解只能出现在类上或者方法上

三、类上与方法上结合使用

我们先来看,在同一个web应用中,是否可以有两个完全一样的RequestMapping。测试一下:假设两个RequestMapping,其中一个是展示用户详细信息,另一个是展示商品详细信息。提供两个Controller,一个是UserController,另一个是ProductController。如下:

package com.liming.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

/**
 * @author LiMing
 * @version 1.0
 * @description:
 * @date 2024/4/8 10:39
 */
@Controller
public class UserController {

    @RequestMapping("/detail")
    public String toDetail(){
        return "detail";
    }
    
}
package com.liming.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

/**
 * @author LiMing
 * @version 1.0
 * @description: TODO
 * @date 2024/4/8 10:41
 */
@Controller
public class ProductController {

    @RequestMapping("detail")
    public String toDetail(){
        return "detail";
    }

}

以上两个Controller的RequestMapping相同,都是"/detail",我们来启动服务器看会不会出现问题:异常发生了,异常信息如下

org.springframework.beans.factory.BeanCreationException: 
Error creating bean with name 'org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping': 
Ambiguous mapping. Cannot map 'userController' method 
com.liming.controller.UserController#toDetail()
to { [/detail]}: There is already 'productController' bean method
com.liming.controller.ProductController#toDetail() mapped.

以上异常信息大致的意思是:不明确的映射。无法映射UserController中的toDetail()方法,因为已经在ProductController中映射过了!!!!
通过测试得知,在同一个webapp中,RequestMapping必须具有唯一性。怎么解决以上问题?两种解决方案:

  • 第一种方案:将方法上RequestMapping的映射路径修改的不一样。
  • 第二种方案:在类上添加RequestMapping的映射路径,以类上的RequestMapping作为命名空间,来加以区分两个不同的映射。

3.1 第一种方案

将方法上RequestMapping的映射路径修改的不一样。

@RequestMapping("/user/detail")
public String toDetail(){
    return "/user/detail";
}
@RequestMapping("/product/detail")
public String toDetail(){
    return "/product/detail";
}

为这两个请求分别提供对应的视图页面和首页:

在这里插入图片描述

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>商品详情页面</title>
</head>
<body>
<h1>商品详情</h1>
</body>
</html>
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>用户详情页面</title>
</head>
<body>
<h1>用户详情</h1>
</body>
</html>

在首页面添加两个超链接:

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>index page</title>
</head>
<body>
<h1>index page</h1>
<a th:href="@{/user/detail}">用户详情</a><br>
<a th:href="@{/product/detail}">商品详情</a><br>
</body>
</html>

启动Tomcat服务器,并测试:http://localhost:8081/springmvc/

在这里插入图片描述

点击用户详情,点击商品详情,都可以正常显示:

在这里插入图片描述

在这里插入图片描述

3.2 第二种方案

在类上和方法上都使用RequestMapping注解来进行路径的映射。假设在类上映射的路径是"/a",在方法上映射的路径是"/b",那么整体表示映射的路径就是:"/a/b"
在第一种方案中,假设UserController类中有很多方法,每个方法的 RequestMapping注解中都需要以"/user"开始,显然比较啰嗦,干脆将"/user"提升到类级别上,例如:

@Controller
@RequestMapping("/user")
public class UserController {

    @RequestMapping("/detail")
    public String toDetail(){
        return "/user/detail";
    }

}
@Controller
@RequestMapping("/product")
public class ProductController {

    @RequestMapping("/detail")
    public String toDetail(){
        return "/product/detail";
    }

}

经过测试,程序可以正常执行!!!

四、RequestMapping注解的value属性

4.1 value属性的使用

value属性是该注解最核心的属性,value属性填写的是请求路径,也就是说通过该请求路径与对应的控制器的方法绑定在一起。另外通过源码可以看到value属性是一个字符串数组

在这里插入图片描述

既然是数组,就表示可以提供多个路径,也就是说,在SpringMVC中,多个不同的请求路径可以映射同一个控制器的同一个方法

编写新的控制器:

@Controller
public class RequestMappingTestController {

    @RequestMapping(value = {"/testValue1", "/testValue2"})
    public String testValue(){
        return "testValue";
    }

}

提供视图页面:

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>test Value</title>
</head>
<body>
<h1>Test RequestMapping's Value</h1>
</body>
</html>

在index.html文件中添加两个超链接:

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>index page</title>
</head>
<body>
<h1>index page</h1>
<a th:href="@{/user/detail}">用户详情</a><br>
<a th:href="@{/product/detail}">商品详情</a><br>

<!--测试RequestMapping的value属性-->
<a th:href="@{/testValue1}">testValue1</a><br>
<a th:href="@{/testValue2}">testValue2</a><br>

</body>
</html>

启动服务器,测试,点击以下的两个超链接,发送请求,都可以正常访问到同一个控制器上的同一个方法:

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

4.2 Ant风格的value

value是可以用来匹配路径的,路径支持模糊匹配,我们把这种模糊匹配称之为Ant风格。关于路径中的通配符包括:

  • ?:代表任意一个字符
  • *:代表0到N个任意字符
  • **:代表0到N个任意字符,并且路径中可以出现路径分隔符/

注意:** 通配符在使用时,左右不能出现字符,只能是 /

测试一下这些通配符,在 RequestMappingTestController 中添加以下方法:

@RequestMapping("/x?z/testValueAnt")
public String testValueAnt(){
    return "testValueAnt";
}

提供视图页面:

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>test Value Ant</title>
</head>
<body>
<h1>测试RequestMapping注解的value属性支持模糊匹配</h1>
</body>
</html>

在index.html页面中编写超链接:

<!--测试RequestMapping注解的value属性支持模糊匹配-->
<a th:href="@{/xyz/testValueAnt}">测试value属性的模糊匹配</a><br>

测试结果如下:

在这里插入图片描述

在这里插入图片描述

通过修改浏览器地址栏上的路径,可以反复测试通配符 ? 的语法:

在这里插入图片描述

将 ? 通配符修改为 * 通配符:

//@RequestMapping("/x?z/testValueAnt")
@RequestMapping("/x*z/testValueAnt")
public String testValueAnt(){
    return "testValueAnt";
}

打开浏览器直接在地址栏上输入路径进行测试:

在这里插入图片描述

在这里插入图片描述

将 * 通配符修改为 ** 通配符:

@RequestMapping("/x**z/testValueAnt")
public String testValueAnt(){
    return "testValueAnt";
}

在这里插入图片描述

注意:/x**z/ 实际上并没有使用通配符 **,本质上还是使用的 *,因为通配符 ** 在使用的时候,左右两边都不能有任何字符,必须是 /

@RequestMapping("/**/testValueAnt")
public String testValueAnt(){
    return "testValueAnt";
}

启动服务器发现报错了:
在这里插入图片描述

以上写法在Spring5的时候是支持的,但是在Spring6中进行了严格的规定,** 通配符只能出现在路径的末尾,例如:

@RequestMapping("/testValueAnt/**")
public String testValueAnt(){
    return "testValueAnt";
}

测试结果:

在这里插入图片描述

4.3 value中的占位符(重点)

到目前为止,我们的请求路径是这样的格式:uri?name1=value1&name2=value2&name3=value3
其实除了这种方式,还有另外一种格式的请求路径,格式为:uri/value1/value2/value3,我们将这样的请求路径叫做 RESTful 风格的请求路径。

普通的请求路径:http://localhost:8080/springmvc/login?username=admin&password=123&age=20
RESTful风格的请求路径:http://localhost:8080/springmvc/login/admin/123/20

如果使用RESTful风格的请求路径,在控制器中应该如何获取请求中的数据呢?可以在value属性中使用占位符,例如:/login/{id}/{username}/{password}

在 RequestMappingTestController 类中添加一个方法:

@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";
}

提供视图页面:

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>test RESTful</title>
</head>
<body>
<h1>测试value属性使用占位符</h1>
</body>
</html>

在 index.html 页面中添加超链接:

<!--测试RequestMapping注解的value属性支持占位符-->
<a th:href="@{/testRESTful/1/zhangsan/20}">测试value属性使用占位符</a>

启动服务器测试:

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

五、RequestMapping注解的method属性

5.1 method属性的作用

在Servlet当中,如果后端要求前端必须发送一个post请求,后端可以通过重写doPost方法来实现。后端要求前端必须发送一个get请求,后端可以通过重写doGet方法来实现。当重写的方法是doPost时,前端就必须发送post请求,当重写doGet方法时,前端就必须发送get请求。如果前端发送请求的方式和后端的处理方式不一致时,会出现405错误。

HTTP状态码405,这种机制的作用是:限制客户端的请求方式,以保证服务器中数据的安全。
假设后端程序要处理的请求是一个登录请求,为了保证登录时的用户名和密码不被显示到浏览器的地址栏上,后端程序有义务要求前端必须发送一个post请求,如果前端发送get请求,则应该拒绝。那么在SpringMVC框架中应该如何实现这种机制呢?可以使用RequestMapping注解的method属性来实现。

通过RequestMapping源码可以看到,method属性也是一个数组

在这里插入图片描述

数组中的每个元素是 RequestMethod,而RequestMethod是一个枚举类型的数据:

在这里插入图片描述

接下来,我们来测试一下:
在RequestMappingTestController类中添加以下方法:

@RequestMapping(value="/login", method = RequestMethod.POST)
public String testMethod(){
    return "testMethod";
}

提供视图页面:

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>test Method</title>
</head>
<body>
<h1>Login Success!!!</h1>
</body>
</html>

在index.html页面中提供一个登录的form表单,后端要求发送post请求,则form表单的method属性应设置为post:

<!--测试RequestMapping的method属性-->
<form th:action="@{/login}" method="post">
    用户名:<input type="text" name="username"/><br>
    密码:<input type="password" name="password"/><br>
    <input type="submit" value="登录">
</form>

启动服务器,测试:

在这里插入图片描述

在这里插入图片描述

通过测试,前端发送的请求方式post,后端处理请求的方式也是post,就不会有问题。
当然,如果后端要求前端必须发送post请求,而前端发送了get请求,则会出现405错误,将index.html中form表单提交方式修改为get:

<!--测试RequestMapping的method属性-->
<form th:action="@{/login}" method="get">
    用户名:<input type="text" name="username"/><br>
    密码:<input type="password" name="password"/><br>
    <input type="submit" value="登录">
</form>

再次测试:

在这里插入图片描述

因此,可以看出,对于RequestMapping注解来说,多一个属性,就相当于多了一个映射的条件,如果value和method属性都有,则表示只有前端发送的请求路径 + 请求方式都满足时才能与控制器上的方法建立映射关系,只要有一个不满足,则无法建立映射关系。例如:@RequestMapping(value=“/login”, method = RequestMethod.POST) 表示当前端发送的请求路径是 /login,并且发送请求的方式是POST的时候才会建立映射关系。如果前端发送的是get请求,或者前端发送的请求路径不是 /login,则都是无法建立映射的。

5.2 衍生Mapping

对于以上的程序来说,SpringMVC提供了另一个注解,使用这个注解更加的方便,它就是:PostMapping,使用该注解时,不需要指定method属性,因为它默认采用的就是POST处理方式:

修改RequestMappingTestController代码如下

//@RequestMapping(value="/login", method = RequestMethod.POST)
@PostMapping("/login")
public String testMethod(){
    return "testMethod";
}

在SpringMVC中不仅提供了 PostMaping注解,像这样的注解还有四个,包括:

  • GetMapping:要求前端必须发送get请求
  • PutMapping:要求前端必须发送put请求
  • DeleteMapping:要求前端必须发送delete请求
  • PatchMapping:要求前端必须发送patch请求

5.3 web的请求方式

前端向服务器发送请求的方式包括哪些?共9种,前5种常用,后面作为了解:

  • 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请求
  6. 使用form表单,设置method=“put/delete/head”,发送get请求。(针对这种情况,可以测试一下)

将index.html中登录表单的提交方式method设置为put:

<!--测试RequestMapping的method属性-->
<form th:action="@{/login}" method="put">
    用户名:<input type="text" name="username"/><br>
    密码:<input type="password" name="password"/><br>
    <input type="submit" value="登录">
</form>

修改RequestMappingTestController类的代码:

@RequestMapping(value="/login", method = RequestMethod.PUT)
//@PostMapping("/login")
public String testMethod(){
    return "testMethod";
}

测试结果:

在这里插入图片描述

通过测试得知,即使form中method设置为put方式,但仍然采用get方式发送请求。

5.4 GET和POST的区别

  • HTTP请求协议之GET请求:
GET /springmvc/login?username=lucy&userpwd=1111 HTTP/1.1                           请求行
Host: localhost:8080                                                                    请求头
Connection: keep-alive
sec-ch-ua: "Google Chrome";v="95", "Chromium";v="95", ";Not A Brand";v="99"
sec-ch-ua-mobile: ?0
sec-ch-ua-platform: "Windows"
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.54 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Sec-Fetch-Site: same-origin
Sec-Fetch-Mode: navigate
Sec-Fetch-User: ?1
Sec-Fetch-Dest: document
Referer: http://localhost:8080/springmvc/index.html
Accept-Encoding: gzip, deflate, br
Accept-Language: zh-CN,zh;q=0.9
                                                                                        空白行
                                                                                        请求体
  • HTTP请求协议之POST请求:
POST /springmvc/login HTTP/1.1                                                  请求行
Host: localhost:8080                                                                  请求头
Connection: keep-alive
Content-Length: 25
Cache-Control: max-age=0
sec-ch-ua: "Google Chrome";v="95", "Chromium";v="95", ";Not A Brand";v="99"
sec-ch-ua-mobile: ?0
sec-ch-ua-platform: "Windows"
Upgrade-Insecure-Requests: 1
Origin: http://localhost:8080
Content-Type: application/x-www-form-urlencoded
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.54 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Sec-Fetch-Site: same-origin
Sec-Fetch-Mode: navigate
Sec-Fetch-User: ?1
Sec-Fetch-Dest: document
Referer: http://localhost:8080/springmvc/index.html
Accept-Encoding: gzip, deflate, br
Accept-Language: zh-CN,zh;q=0.9
                                                                                      空白行
username=lisi&userpwd=123                                                             请求体

5.4.1 区别是什么

  1. get请求发送数据的时候,数据会挂在URI的后面,并且在URI后面添加一个“?”,"?"后面是数据。这样会导致发送的数据回显在浏览器的地址栏上。

http://localhost:8080/springmvc/login?username=zhangsan&userpwd=1111

  1. post请求发送数据的时候,在请求体当中发送。不会回显到浏览器的地址栏上。也就是说post发送的数据,在浏览器地址栏上看不到。
  2. get请求只能发送普通的字符串。并且发送的字符串长度有限制,不同的浏览器限制不同。这个没有明确的规范。get请求无法发送大数据量。
  3. post请求可以发送任何类型的数据,包括普通字符串,流媒体等信息:视频、声音、图片。post请求可以发送大数据量,理论上没有长度限制。
  4. get请求在W3C中是这样说的:get请求比较适合从服务器端获取数据。
  5. post请求在W3C中是这样说的:post请求比较适合向服务器端传送数据。
  6. get请求是安全的。因为在正确使用get请求的前提下,get请求只是为了从服务器上获取数据,不会对服务器数据进行修改。
  7. post请求是危险的。因为post请求是修改服务器端的资源。
  8. get请求支持缓存。 也就是说当第二次发送get请求时,会走浏览器上次的缓存结果,不再真正的请求服务器。(有时需要避免,怎么避免:在get请求路径后添加时间戳)
  9. post请求不支持缓存。每一次发送post请求都会真正的走服务器。

5.4.2 怎么选择

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

六、RequestMapping注解的params属性

6.1 params属性的理解

params属性用来设置通过请求参数来映射请求。

对于RequestMapping注解来说:

  • value属性是一个数组,只要满足数组中的任意一个路径,就能映射成功
  • method属性也是一个数组,只要满足数组中任意一个请求方式,就能映射成功。
  • params属性也是一个数组,不过要求请求参数必须和params数组中要求的所有参数完全一致后,才能映射成功。

在这里插入图片描述

6.2 params属性的4种用法

  • @RequestMapping(value=“/login”, params={“username”, “password”}) 表示:请求参数中必须包含 username 和 password,才能与当前标注的方法进行映射。
  • @RequestMapping(value=“/login”, params={“!username”, “password”}) 表示:请求参数中不能包含username参数,但必须包含password参数,才能与当前标注的方法进行映射。
  • @RequestMapping(value=“/login”, params={“username=admin”, “password”}) 表示:请求参数中必须包含username参数,并且参数的值必须是admin,另外也必须包含password参数,才能与当前标注的方法进行映射。
  • @RequestMapping(value=“/login”, params={“username!=admin”, “password”}) 表示:请求参数中必须包含username参数,但参数的值不能是admin,另外也必须包含password参数,才能与当前标注的方法进行映射。

注意:如果前端提交的参数,和后端要求的请求参数不一致,则出现400错误!!!

HTTP状态码400的原因:请求参数格式不正确而导致的。

6.3 测试params属性

在 RequestMappingTestController 类中添加如下方法:

@RequestMapping(value="/testParams", params = {"username", "password"})
public String testParams(){
    return "testParams";
}

提供视图页面:

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>testParams</title>
</head>
<body>
<h1>测试RequestMapping注解的Params属性</h1>
</body>
</html>

在index.html文件中添加超链接:

<!--测试RequestMapping的params属性-->
<a th:href="@{/testParams(username='admin',password='123')}">测试params属性</a>

当然,你也可以这样写:这样写IDEA会报错,但不影响使用。

<a th:href="@{/testParams?username=admin&password=123}">测试params属性</a><br>

启动服务器,测试:

在这里插入图片描述

在这里插入图片描述

假如发送请求时,没有传递username参数会怎样?

<a th:href="@{/testParams(password='123')}">测试params属性</a><br>

启动服务器,测试:

在这里插入图片描述

提示无效的请求参数,服务器无法或不会处理当前请求。

七、RequestMapping注解的headers属性

7.1 认识headers属性

headersparams原理相同,用法也相同。当前端提交的请求头信息后端要求的请求头信息一致时,才能映射成功。请求头信息怎么查看?在浏览器中,F12打开控制台,找到Network,可以查看具体的请求协议和响应协议。在请求协议中可以看到请求头信息,例如:

image.png
请求头信息和请求参数信息一样,都是键值对形式,例如上图中:

  • Referer: http://localhost:8080/springmvc/ 键是Referer,值是http://localhost:8080/springmvc/
  • Host: localhost:8080 键是Host,值是localhost:8080

7.2 headers属性的4种用法

  • @RequestMapping(value=“/login”, headers={“Referer”, “Host”}) 表示:请求头信息中必须包含Referer和Host,才能与当前标注的方法进行映射。
  • @RequestMapping(value=“/login”, headers={“Referer”, “!Host”}) 表示:请求头信息中必须包含Referer,但不包含Host,才能与当前标注的方法进行映射。
  • @RequestMapping(value=“/login”, headers={“Referer=http://localhost:8080/springmvc/”, “Host”}) 表示:请求头信息中必须包含Referer和Host,并且Referer的值必须是http://localhost:8080/springmvc/,才能与当前标注的方法进行映射。
  • @RequestMapping(value=“/login”, headers={“Referer!=http://localhost:8080/springmvc/”, “Host”}) 表示:请求头信息中必须包含Referer和Host,并且Referer的值不是http://localhost:8080/springmvc/,才能与当前标注的方法进行映射。

注意:如果前端提交的请求头信息,和后端要求的请求头信息不一致,则出现404错误!!!

7.3 测试headers属性

在 RequestMappingTestController 类中添加以下方法:

@RequestMapping(value="/testHeaders", headers = {"Referer=http://localhost:8081/springmvc/"})
public String testHeaders(){
    return "testHeaders";
}

提供视图页面:

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>test Headers</title>
</head>
<body>
<h1>测试RequestMapping注解的headers属性</h1>
</body>
</html>

在index.html页面中添加超链接:

<!--测试RequestMapping的headers属性-->
<a th:href="@{/testHeaders}">测试headers属性</a><br>

启动服务器,测试结果:

在这里插入图片描述

在这里插入图片描述

将后端控制器中的headers属性值进行修改:

@RequestMapping(value="/testHeaders", headers = {"Referer=http://localhost:8888/springmvc/"})
public String testHeaders(){
    return "testHeaders";
}

再次测试:

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1577444.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

互联网需要做安全防护吗?

互联网需要做安全防护&#xff0c;因为网络攻击的风险随时存在。一旦遭受大规模攻击&#xff0c;企业很可能会受到严重影响&#xff0c;甚至会造成巨大的经济损失和品牌声誉受损。因此&#xff0c;建议企业在安全防护方面做好以下几点&#xff1a; 加强网络安全意识教育&#x…

linux基础篇:Linux中磁盘的管理(分区、格式化、挂载)

Linux中磁盘的管理&#xff08;分区、格式化、挂载&#xff09; 一、认识磁盘 1.1 什么是磁盘 磁盘是一种计算机的外部存储器设备&#xff0c;由一个或多个覆盖有磁性材料的铝制或玻璃制的碟片组成&#xff0c;用来存储用户的信息&#xff0c;这种信息可以反复地被读取和改写…

python WAV音频文件处理—— (2)处理PCM音频-- waveio包

破译 PCM-Encoded 的音频样本 这部分将变得稍微高级一些&#xff0c;但从长远来看&#xff0c;它将使在 Python 中处理 WAV 文件变得更加容易。 在本教程结束时&#xff0c;我们将构建出 waveio 包&#xff1a; waveio/ │ ├── __init__.py ├── encoding.py ├── met…

在git上先新建仓库-把本地文件提交远程

一.在git新建远程项目库 1.选择新建仓库 以下以gitee为例 2.输入仓库名称&#xff0c;点击创建 这个可以选择仓库私有化还公开权限 3.获取仓库clone链接 这里选择https模式就行&#xff0c;就不需要配置对电脑进行sshkey配置了。只是需要每次提交输入账号密码 二、远…

解决网站“不安全”、“不受信”、“排名下降”,你需要——「SSL证书」

在网络时代&#xff0c;确保网站用户数据安全显得愈发关键。SSL证书作为网络安全的关键要素&#xff0c;对网站而言具有重大意义。 SSL&#xff08;Secure Sockets Layer&#xff09;证书是一种数字证书&#xff0c;用于加密和验证网络通信。它存在于客户端&#xff08;浏览…

【小白学机器学习12】假设检验之3:t 检验 (t检验量,t分布,查t值表等)

目录 1 t 检验的定义 1.1 来自维基百科和百度百科 1.2 别名 1.3 和其他检验的区别 2 适用情况&#xff1a; 2.1 关于样本情况 2.2 适合检查的情况 2.2.1 单样本均值检验&#xff08;One-sample t-test&#xff09; 2.2.2 两独立样本均值检验&#xff08;Independent …

【随笔】Git 高级篇 -- 提交的技巧(上) rebase commit --amend(十八)

&#x1f48c; 所属专栏&#xff1a;【Git】 &#x1f600; 作  者&#xff1a;我是夜阑的狗&#x1f436; &#x1f680; 个人简介&#xff1a;一个正在努力学技术的CV工程师&#xff0c;专注基础和实战分享 &#xff0c;欢迎咨询&#xff01; &#x1f496; 欢迎大…

鸿蒙南向开发:【智能烟感】

样例简介 智能烟感系统通过实时监测环境中烟雾浓度&#xff0c;当烟雾浓度超标时&#xff0c;及时向用户发出警报。在连接网络后&#xff0c;配合数字管家应用&#xff0c;用户可以远程配置智能烟感系统的报警阈值&#xff0c;远程接收智能烟感系统报警信息。实现对危险及时报…

python 如何生成uuid

UUID&#xff08;Universally Unique Identifier&#xff09;是通用唯一识别码&#xff0c;在许多领域用作标识&#xff0c;比如我们常用的数据库也可以用它来作为主键&#xff0c;原理上它是可以对任何东西进行唯一的编码的。作为新手一看到类似varchar(40)这样的主键就觉得有…

ctf刷题记录2(更新中)

因为csdn上内容过多编辑的时候会很卡&#xff0c;因此重开一篇&#xff0c;继续刷题之旅。 NewStarCTF 2023 WEEK3 Include &#x1f350; <?phperror_reporting(0);if(isset($_GET[file])) {$file $_GET[file];if(preg_match(/flag|log|session|filter|input|data/i, $…

笔记 | 编译原理L1

重点关注过程式程序设计语言编译程序的构造原理和技术 1 程序设计语言 1.1 依据不同范型 过程式(Procedural programming languages–imperative)函数式(Functional programming languages–declarative)逻辑式(Logical programming languages–declarative)对象式(Object-or…

解决游戏霍格沃兹找不到EMP.dll问题的5种方法

在玩《霍格沃兹》游戏时&#xff0c;我们可能会遇到一些错误提示&#xff0c;其中之一就是“缺少dll文件”。其中&#xff0c;EMP.dll文件丢失是一个常见的问题。这个问题可能会导致游戏无法正常运行或出现各种错误。为了解决这个问题&#xff0c;本文将介绍5种解决方法&#x…

【线段树】【前缀和】:1687从仓库到码头运输箱子

本题简单解法 C前缀和算法的应用&#xff1a;1687从仓库到码头运输箱子 本文涉及的基础知识点 C算法&#xff1a;前缀和、前缀乘积、前缀异或的原理、源码及测试用例 包括课程视频 线段树 LeetCode1687从仓库到码头运输箱子 你有一辆货运卡车&#xff0c;你需要用这一辆车…

paddle实现手写数字模型(一)

参考文档&#xff1a;paddle官网文档环境&#xff1a;Python 3.12.2 &#xff0c;pip 24.0 &#xff0c;paddlepaddle 2.6.0 python -m pip install paddlepaddle2.6.0 -i https://pypi.tuna.tsinghua.edu.cn/simple调试代码如下&#xff1a; LeNet.py import paddle import p…

初学python记录:力扣1600. 王位继承顺序

题目&#xff1a; 一个王国里住着国王、他的孩子们、他的孙子们等等。每一个时间点&#xff0c;这个家庭里有人出生也有人死亡。 这个王国有一个明确规定的王位继承顺序&#xff0c;第一继承人总是国王自己。我们定义递归函数 Successor(x, curOrder) &#xff0c;给定一个人…

数据结构——二叉树——二叉搜索树(Binary Search Tree, BST)

目录 一、98. 验证二叉搜索树 二、96. 不同的二叉搜索树 三、538. 把二叉搜索树转换为累加树 二叉搜索树&#xff1a;对于二叉搜索树中的每个结点&#xff0c;其左子结点的值小于该结点的值&#xff0c;而右子结点的值大于该结点的值 一、98. 验证二叉搜索树 给你一个二叉树的…

GAMES Webinar 317-渲染专题-图形学 vs. 视觉大模型|Talk+Panel形式

两条路线&#xff1a;传统渲染路线&#xff0c;生成路线 两种路线的目的都是最终生成图片或者视频等在现在生成大火的情况下&#xff0c;传统路线未来该如何发展呢&#xff0c;两种路线是否能够兼容呢 严令琪 这篇工作是吸取这两条路各自优势的一篇工作 RGB是一张图&#xff…

好用的AI智能工具:AI写作、AI绘画、AI翻译全都有

在科技不断进步的今天&#xff0c;人工智能&#xff08;AI&#xff09;已经成为我们日常生活中不可或缺的一部分。它不仅在各个领域都有应用&#xff0c;还为我们提供了许多方便快捷的工具。对此&#xff0c;小编今天推荐7款人工智能软件&#xff0c;AI写作、AI绘画、AI翻译全都…

Vue - 你知道Vue组件之间是如何进行数据传递的吗

难度级别:中级及以上 提问概率:85% 这道题还可以理解为Vue组件之间的数据是如何进行共享的,也可以理解为组件之间是如何通信的,很多人叫法不同,但都是说的同一个意思。我们知道,在Vue单页面应用项目中,所有的组件都是被嵌套在App.vue内…

2024/4/1—力扣—BiNode

代码实现&#xff1a; /*** Definition for a binary tree node.* struct TreeNode {* int val;* struct TreeNode *left;* struct TreeNode *right;* };*/void convertBiNode_pro(struct TreeNode *root, struct TreeNode **p) {if (root) {convertBiNode_pro(roo…