0


@RequestMapping用法详解

Request

是请求的意思,而

Mapping

是映射的意思,合起来就是请求映射,什么是请求映射,http://localhost:8080/student/get 这个很明显是一个请求的url吧,通过url我们要调用到代码当中的方法,方法那么多,怎么知道调用哪个呢?没错就是依靠

@RequestMapping

,可以在方法当中使用

@RequestMapping("/student/get")

,这样就可以通过

/student/get

这个

url

调用到这个方法了,一句话:

用于建立请求的URL 和 处理请求方法之间的对应关系。

目录

一. @RequestMapping的源码

@RequestMapping是属于springmvc当中的注解,由于现在都流行springboot,减少了springmvc相关的配置文件以致于,很多人都淡化了springmvc的认识,基本上都只知道spring,spring给我们提供了IOC容器还有AOP切面等等,而springmvc主要是帮我们处理请求映射相关,比如前端的传的值,到controller之后直接可以映射到实体类当中,其实这些都是springmvc的功劳。

@Target({ElementType.TYPE,ElementType.METHOD})@Retention(RetentionPolicy.RUNTIME)@Documented@Mappingpublic@interfaceRequestMapping{Stringname()default"";@AliasFor("path")String[]value()default{};@AliasFor("value")String[]path()default{};RequestMethod[]method()default{};String[]params()default{};String[]headers()default{};String[]consumes()default{};String[]produces()default{};}

可以看到注解中的属性除了 name() 返回的字符串,其它的方法均返回数组,也就是可以定义多个属性值,例如 value() 和 path() 都可以同时定义多个字符串值来接收多个URL请求

RequestMapping注解当中用到了三个元注解:@Documented、@Target、@Retention

1.1. @Target作用

里面用到了一个@Target注解,他是干什么的?

@Target在 java中 是注释类。@Target作用于修饰的注释可以修饰的类型范围。

  • @Target(ElementType.TYPE) —— 接口、类、枚举、注解
  • @Target(ElementType.FIELD) —— 字段、枚举的常量
  • @Target(ElementType.METHOD) —— 方法
  • @Target(ElementType.PARAMETER) —— 方法参数
  • @Target(ElementType.CONSTRUCTOR) —— 构造函数
  • @Target(ElementType.LOCAL_VARIABLE) —— 局部变量
  • @Target(ElementType.ANNOTATION_TYPE) —— 注解
  • @Target(ElementType.PACKAGE) —— 包

比如

@Target({ElementType.TYPE, ElementType.METHOD})

,就代表着@RequestMapping可以用在 接口、类、枚举、注解上、还可以用在方法上!

1.2. @Retention(RetentionPolicy.RUNTIME)

注解按生命周期来划分可分为3类:

  • RetentionPolicy.SOURCE:注解只保留在源文件,当Java文件编译成class文件的时候,注解被遗弃;也就是编译时有效。
  • RetentionPolicy.CLASS:注解被保留到class文件,但jvm加载class文件时候被遗弃,这是默认的生命周期;加载时被抛弃。
  • RetentionPolicy.RUNTIME:注解不仅被保存到class文件中,jvm加载class文件之后,仍然存在;一直有效!

lombok可以通过@Data注解省去get set 方法,实际上@Data的生命周期就是RetentionPolicy.SOURCE,他是通过注解来标记这个方法要生成get set方法,然后在编译的时候直接会生成get set。生成过后,就被抛弃了。

在这里插入图片描述

1.3. @Documented

@Documented

@Deprecated

注解长得有点像,

@Deprecated

是用来标注某个类或者方法不建议再继续使用,

@Documented

只能用在注解上,如果一个注解@B,被

@Documented

标注,那么被@B修饰的类,生成文档时,会显示@B。如果@B没有被

@Documented

标注,最终生成的文档中就不会显示@B。这里的生成文档指的JavaDoc文档!

@Deprecated

注解基本上所有框架自定义的注解都会添加,所谓javadoc其实就是JDK给我们提供的一个生成文档的工具!

由于篇幅问题,@Documented详解请看这篇文章:https://blog.csdn.net/weixin_43888891/article/details/126981711

1.4. @Mapping

这个注解应该就是具有真正功能性的注解了,当然我们实际开发当中一般也不会用这个注解。

1.5. @AliasFor

@RequestMapping("student")

等同于

@RequestMapping(value = "student")

,而@RequestMapping注解当中

path

属性又使用了

@AliasFor("value")

,也就意味着我们设置了

value

属性,就算不设置

path

属性,也可以通过

path

属性获取到value的值!

@AliasFor("path")String[]value()default{};@AliasFor("value")String[]path()default{};
AliasFor

是Spring提供的注解,

Alias

是别名的意思,

For

是为了,首先我们通过命名可以得出一个结论,他是为了别名而自定义的注解!

Spring中@AliasFor注解的作用有两点:

  1. 将同一个注解类的属性设置互为别名
  2. 将一个注解上的属性值传递给另一个注解

但这并不是java原生支持的,需要通过Spring中提供的工具类:

org.springframework.core.annotation.AnnotationUtils

或者

org.springframework.core.annotation.AnnotatedElementUtils

来解析。AnnotatedElementUtils内部还是调用的AnnotationUtils。

想要了解详情的可以看这篇文章:https://blog.csdn.net/weixin_43888891/article/details/126962698

二. @RequestMapping的属性

  • name:此处name属性,相当于方法的注释,使方法更易理解
  • path:用于指定请求的 URL。
  • method:用于指定请求的方式。
  • params:用于指定限制请求参数的条件。它支持简单的表达式。要求请求参数的 key 和 value 必须和配置的一模一样。
  • headers:用于指定限制请求消息头的条件。
  • value:用于指定请求的 URL。它和 path 属性的作用是一样的。
  • consumes:指定处理请求的提交内容类型(Content-Type),例如:application/json、text/html时,才能够让该方法处理请求
  • produces:指定返回的内容类型,返回的内容类型必须是request请求头(Accept)中所包含的类型

三. 实战应用

3.1. 搭建项目

主要搭建的是springboot+jsp项目

1.新建一个springboot项目

2.指定web资源目录

在src/main下创建webapp目录,用于存放jsp文件。这就是一个普通的目录

设置完成后,webapp文件夹就会多出一个像图中显示出来的蓝点,此时,便可在webapp中找到jsp的创建选项了。

3.添加pom依赖

使用jsp的话,tomcat-embed-jasper这个依赖一定要有!

<dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency><dependency><groupId>org.apache.tomcat.embed</groupId><artifactId>tomcat-embed-jasper</artifactId></dependency></dependencies><build><!--告诉maven,src/main/webapp和src/main/resources都需要进行编译--><resources><resource><directory>src/main/webapp</directory><filtering>true</filtering><includes><include>**/*.*</include></includes></resource><resource><directory>src/main/resources</directory><filtering>true</filtering></resource></resources><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin></plugins></build>

4.添加application配置

server.port=8888
# 配置SpringMVC视图解析器
spring.mvc.view.prefix=/
spring.mvc.view.suffix=.jsp
spring.mvc.view.prefix=/

为什么要配置一个

/

呢?因为webapp其实就是设置的编译后的根目录,可以看到index.jsp就是在根目录!

在这里插入图片描述

5.新建一个index.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html><head><title>Title</title></head><body><h1>Heelo word</h1><p><ahref="#">User Login</a></body></html>

6.启动项目,测试访问: http://localhost:8888/

通过端口访问,他是默认会去找

index.jsp

在这里插入图片描述

7.新建一个success.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html><head><title>Title</title></head><body><h1>Welcome</h1></body></html>

3.2. 测试 value 和 path 属性

这两个属性作用相同,可以互换,如果仅有这一个属性,则可以省略,下面两个例子均采用省略的方式

示例一:

1.新建UserController

将 @RequestMapping 注解在 login 方法上,而UserController上不添加 @RequestMapping 注解,这时的请求 URL 是相对于 Web 根目录

@ControllerpublicclassUserController{@RequestMapping("/login")publicStringlogin(){return"success";}}

2.调整index.jsp

这时的方法 login() 能处理的 URL 请求路径是基于 Web 应用的,也就是 http://localhost:8888/login,也就是 index.jsp 页面中的 User Login 链接地址应该是:

<p> <a href="login">User Login</a>

示例二:

将 @RequestMapping 注解在 UserController 类上,这时类的注解是相对于 Web 根目录,而方法上的是相对于类上的路径

1.调整UserController

@Controller@RequestMapping("/user")publicclassUserController{@RequestMapping("/login")publicStringlogin(){return"success";}}

2.调整index.jsp

这时的方法login()能处理的 URL 请求路径则是 http://localhost:8888/user/login,也就是 index.jsp 页面中的 User Login 链接地址应该是:

<p> <a href="user/login">User Login</a>

3.3. 测试 method 属性

1)简介:@RequestMapping 中的 method 主要用来定义接收浏览器发来的何种请求。在Spring中,使用枚举类

org.springframework.web.bind.annotation.RequestMethod

来定义浏览器请求的方式。

Http规范定义了多种请求资源的方式,最基本的有四种,分别为:GET(查)、POST(增)、PUT(改)、DELETE(删),而URL则用于定位网络上的资源相当于地址的作用,配合四种请求方式,可以实现对URL对应的资源的增删改查操作。

在实际应用中,很多人并没有按照这个规范做,因为使用GET/POST同样可以完成PUT和DELETE操作。

如果不指定method属性,就代表着任何请求方式都能访问该方法!

2)通过

@RequestMapping(value="/login",method=RequestMethod.GET)

来指定 login()方法 仅处理通过 GET 方式发来的请求

@Controller@RequestMapping(path ="/user")publicclassUserController{@RequestMapping(path ="/login", method=RequestMethod.GET)publicStringlogin(){return"success";}}

这时,如果浏览器发来的请求不是GET的话,将收到浏览器返回的错误提示,也就是得通过链接的方式而不是表单的方式:

<a href="user/login>User Login</a>

3)通过

@RequestMapping(value="/login",method=RequestMethod.POST)

来指定 login()方法 仅处理通过 POST 方式发来的请求

@Controller@RequestMapping(path ="/user")publicclassUserController{@RequestMapping(path ="/login", method=RequestMethod.POST)publicStringlogin(){return"success";}}

这时,必须通过表单的方式发送请求,否则将收到浏览器返回的错误提示

<form action="user/login" method="post">
    <input type="submit" value="使用Post发送请求"/>
</form>

4)由于在 RequestMapping 注解类中 method() 方法返回的是 RequestMethod 数组,所以可以给 method 同时指定多个请求方式,例如:

@Controller@RequestMapping(path ="/user")publicclassUserController{// 该方法将同时接收通过GET和POST方式发来的请求@RequestMapping(path ="/login", method={RequestMethod.POST,RequestMethod.GET})publicStringlogin(){return"success";}}

3.4. 测试 params 属性

该属性表示请求参数,也就是追加在URL上的键值对,多个请求参数以&隔开,例如:

http://localhost/user/login?username=admin&password=123456

则这个请求的参数为username=admin以及password=123456,@RequestMapping 中可以使用 params 来限制请求参数,来实现进一步的过滤请求,举个例子:

@Controller@RequestMapping(path ="/user")publicclassUserController{// 该方法将接收 /user/login 发来的请求,且请求参数必须为 username=kolbe&password=123456@RequestMapping(path ="/login", params={"username=admin","password=123456"})publicStringlogin(){return"success";}}

该例中则表示 UserController 中的 login() 方法仅处理 /user/login 发来的请求,且必须带有

username=admin&password=123456

的请求参数,否则浏览器将返回

HTTP 400

的错误, 对应 index.jsp 中的键接地址为:

<a href="user/login?username=admin&password=123456">User Login</a>

3.5. 测试 headers 属性

该属性表示

请求头

,用于HTTP协义交互的信息被称为HTTP报文,客户端发送的HTTP报文被称为

请求报文

,服务器发回给客户端的HTTP报文称为

响应报文

,报文由

报文头部

报文体

组成。

  • 请求头部(RequestHeaders):请求头包含许多有关客户端环境和请求正文的信息,例如浏览器支持的语言、请求的服务器地址、客户端的操作系统等。
  • 响应头部(Rsponse Headers):响应头也包含许多有用的信息,包括服务器类型、日期、响应内容的类型及编码,响应内容的长度等等。

如果你安装的是Chrome浏览器,可以通过在网页中 右击鼠标---->审查元素---->Network---->Name中点击网页---->右侧查看Headers即可,如果Name中没有出现网页,可以刷新一下即可,下边是我电脑中的一个请求头部示例:

在这里插入图片描述

回规正题,通过 @RequestMapping 中的 headers 属性,可以限制客户端发来的请求

@Controller@RequestMapping(path ="/user")publicclassUserController{// 表示只接收本机发来的请求@RequestMapping(path ="/login", headers="Host=localhost:8888")publicStringlogin(){return"success";}}

3.6. 带占位符的URL

1)带占位符的URL是Spring 3.0 新增的功能,可以通过 @PathVariable 将 URL 中的占位符绑定到控制器的处理方法的参数中,占位符使用{}括起来

2)带占位符的URL示例:需要配合@PathVariable接受参数

@Controller@RequestMapping(path ="/user")publicclassUserController{@RequestMapping(value="/{id}", method=RequestMethod.GET)publicStringshow(@PathVariable("id")Integer id){return"success";}}

在这个控制器中 show() 方法将可以接收 user/1、user/2、user/3等等的路径请求,请求的方法必须为GET,使用 @PathVariable 为应用实现 REST 规范提供了具大的便利条件。

3.7. REST 风格的 URL 请求

1)简介:REST(Representational State Transfer):(资源)表现层状态转化,它是目前最流行的一种软件架构,其结构清晰、易于理解、扩展方便且符合标准,正在越来越多的被实践到应用中。

2)REST 风格的 URL 请求

请求路径 请求方法 作用
-/user/1 HTTP GET 得到id为1的user
-/user/1 HTTP DELETE 删除id为1的user
-/user/1 HTTP PUT 更新id为1的user
-/user HTTP POST 新增user

3)JSP目前仅支持 发送GET 和 POST,那put和delete请求怎么办呢?使用带有附加隐藏表单字段 (_method) 的普通 POST 来传递“真正的”HTTP 方法。 然后由spring提供的

org.springframework.web.filter.HiddenHttpMethodFilter

这个过滤器来进行过滤,将请求转发到put和delete请求,请求参数的名称默认为

_method

,可以通过

HiddenHttpMethodFilter

当中的

setMethodParam

来修改的。

# 启动HiddenHttpMethodFilter过滤器,以支持浏览器可以发送DELETE PUT 请求
spring.mvc.hiddenmethod.filter.enabled=true

4)由于表单无法发送 DELETE 和 PUT 请求,所以为了让 HiddenHttpMethodFilter 识别请求的方法,需要在表单中添加一个隐藏域,名字为 _method 值为 DELETE 或 POST 或PUT,修改后 index.jsp 页面代码如下:

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html><head><title>Title</title></head><body><h1>Heelo word</h1><ahref="user/login?username=admin&password=123456">User Login</a><!-- 得到id为1的user --><ahref="user/1">Test Rest GET</a><!-- 新建id为1的user --><formaction="user"method="post"><inputtype="hidden"name="_method"value="POST"/><inputtype="submit"value="Test Rest POST"/></form><!-- 删除id为1的user --><formaction="user/1"method="post"><inputtype="hidden"name="_method"value="DELETE"/><inputtype="submit"value="Test Rest DELETE"/></form><!-- 更新id为1的user --><formaction="user/1"method="post"><inputtype="hidden"name="_method"value="PUT"/><inputtype="submit"value="Test Rest PUT"/></form></body></html>

5)添加控制器

@Controller@RequestMapping("/user")publicclassUserController{@RequestMapping(value="/{id}", method=RequestMethod.GET)publicStringshow(@PathVariable("id")Integer id){System.out.println("查看id为:"+ id +"的user");return"success";}@RequestMapping(value="/{id}", method=RequestMethod.PUT)publicStringupdate(@PathVariable("id")Integer id){System.out.println("更新id为:"+ id +"的user");return"success";}@RequestMapping(value="/{id}", method=RequestMethod.DELETE)publicStringdestroy(@PathVariable("id")Integer id){System.out.println("删除id为:"+ id +"的user");return"success";}@RequestMapping(value="", method=RequestMethod.POST)publicStringcreate(){System.out.println("新建user");return"success";}}

6)启动测试:DELETE和PUT请求,到达控制器后,返回时(forward)会报HTTP 405的错误提示,但是请求已经到达了后台。说明是在转发到success的时候进行报错的!

在这里插入图片描述

@RestController就代表这个控制器 不会根据返回值 去寻找视图,代表的是返回的Json数据,或者

@ResponseBody+@Controller

注解,同样也是,而我们并没有用

@RestController

,只用了@Controller,每个方法都是返回的String,SpringMvc会根据这个返回的String去寻找对应的页面,然后他默认是请求转发的,而success请求需要通过

get

post

才能转发成功,

put和delete

就会报405,解决方案:

  1. 将请求转发(forward)改为请求重定向(redirect)
  2. 自己手动写一个Filter来包装HttpRequest中的getMethod()方法
@RequestMapping(value="/{id}", method=RequestMethod.PUT)publicStringupdate(@PathVariable("id")Integer id){System.out.println("更新id为:"+ id +"的user");return"redirect:/success.jsp";}@RequestMapping(value="/{id}", method=RequestMethod.DELETE)publicStringdestroy(@PathVariable("id")Integer id){System.out.println("删除id为:"+ id +"的user");return"redirect:/success.jsp";}

3.8. consumers属性

一般我们不会设置consumers和produces属性,了解即可!

指定处理请求的提交内容类型(Content-Type),例如:application/json、text/html时,才能够让该方法处理请求

@RequestMapping(value ="getUser",consumes ="application/json")@ResponseBodypublicModelAndViewgetUser(){ModelAndView view =newModelAndView();return view;}

3.9. produces属性

指定返回的内容类型,返回的内容类型必须是request请求头(Accept)中所包含的类型

@RequestMapping(value ="login",produces ="application/json")@ResponseBodypublicStringlogin(){return"success";}

此外,produces属性还可以指定返回值的编码

@RequestMapping(value = "getUser",produces = "application/json,charset=utf-8")

,则指明返回utf-8编码

四. @RequestMapping扩展注解

spring基于@RequestMapping又扩展出来了4个注解

@GetMapping
@PostMapping
@DeleteMapping
@PutMapping

看源码就可以看出来,连属性都是和@RequestMapping一样,

@PutMapping

就相当于是

@RequestMapping(method = RequestMethod.PUT)

,说白了就是想帮助我们省代码,没有其他用途!功能都是一样的!

在这里插入图片描述

标签: java spring spring boot

本文转载自: https://blog.csdn.net/weixin_43888891/article/details/126861310
版权归原作者 怪 咖@ 所有, 如有侵权,请联系我们删除。

“@RequestMapping用法详解”的评论:

还没有评论