Request
是请求的意思,而Mapping
是映射的意思,合起来就是请求映射,什么是请求映射,http://localhost:8080/student/get 这个很明显是一个请求的url吧,通过url我们要调用到代码当中的方法,方法那么多,怎么知道调用哪个呢?没错就是依靠@RequestMapping
,可以在方法当中使用@RequestMapping("/student/get")
,这样就可以通过/student/get
这个url
调用到这个方法了,一句话:用于建立请求的URL 和 处理请求方法之间的对应关系。
@RequestMapping是属于springmvc当中的注解,由于现在都流行springboot,减少了springmvc相关的配置文件以致于,很多人都淡化了springmvc的认识,基本上都只知道spring,spring给我们提供了IOC容器还有AOP切面等等,而springmvc主要是帮我们处理请求映射相关,比如前端的传的值,到controller之后直接可以映射到实体类当中,其实这些都是springmvc的功劳。
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Mapping
public @interface RequestMapping {
String name() 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
里面用到了一个@Target注解,他是干什么的?
@Target在 java中 是注释类。@Target作用于修饰的注释可以修饰的类型范围。
比如@Target({ElementType.TYPE, ElementType.METHOD})
,就代表着@RequestMapping可以用在 接口、类、枚举、注解上、还可以用在方法上!
注解按生命周期来划分可分为3类:
lombok可以通过@Data注解省去get set 方法,实际上@Data的生命周期就是RetentionPolicy.SOURCE,他是通过注解来标记这个方法要生成get set方法,然后在编译的时候直接会生成get set。生成过后,就被抛弃了。
@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
这个注解应该就是具有真正功能性的注解了,当然我们实际开发当中一般也不会用这个注解。
@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注解的作用有两点:
但这并不是java原生支持的,需要通过Spring中提供的工具类:org.springframework.core.annotation.AnnotationUtils
或者org.springframework.core.annotation.AnnotatedElementUtils
来解析。AnnotatedElementUtils内部还是调用的AnnotationUtils。
想要了解详情的可以看这篇文章:https://blog.csdn.net/weixin_43888891/article/details/126962698
主要搭建的是springboot+jsp项目
1.新建一个springboot项目
2.指定web资源目录
在src/main下创建webapp目录,用于存放jsp文件。这就是一个普通的目录
设置完成后,webapp文件夹就会多出一个像图中显示出来的蓝点,此时,便可在webapp中找到jsp的创建选项了。
3.添加pom依赖
使用jsp的话,tomcat-embed-jasper这个依赖一定要有!
<dependencies>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-webartifactId>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-testartifactId>
<scope>testscope>
dependency>
<dependency>
<groupId>org.apache.tomcat.embedgroupId>
<artifactId>tomcat-embed-jasperartifactId>
dependency>
dependencies>
<build>
<resources>
<resource>
<directory>src/main/webappdirectory>
<filtering>truefiltering>
<includes>
<include>**/*.*include>
includes>
resource>
<resource>
<directory>src/main/resourcesdirectory>
<filtering>truefiltering>
resource>
resources>
<plugins>
<plugin>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-maven-pluginartifactId>
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>Titletitle>
head>
<body>
<h1>Heelo wordh1>
<p> <a href="#">User Logina>
body>
html>
6.启动项目,测试访问: http://localhost:8888/
通过端口访问,他是默认会去找
index.jsp
的
7.新建一个success.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Titletitle>
head>
<body>
<h1>Welcomeh1>
body>
html>
这两个属性作用相同,可以互换,如果仅有这一个属性,则可以省略,下面两个例子均采用省略的方式
示例一:
1.新建UserController
将 @RequestMapping 注解在 login 方法上,而UserController上不添加 @RequestMapping 注解,这时的请求 URL 是相对于 Web 根目录
@Controller
public class UserController {
@RequestMapping("/login")
public String login() {
return "success";
}
}
2.调整index.jsp
这时的方法 login() 能处理的 URL 请求路径是基于 Web 应用的,也就是 http://localhost:8888/login,也就是 index.jsp 页面中的 User Login 链接地址应该是:
示例二:
将 @RequestMapping 注解在 UserController 类上,这时类的注解是相对于 Web 根目录,而方法上的是相对于类上的路径
1.调整UserController
@Controller
@RequestMapping("/user")
public class UserController {
@RequestMapping("/login")
public String login() {
return "success";
}
}
2.调整index.jsp
这时的方法login()能处理的 URL 请求路径则是 http://localhost:8888/user/login,也就是 index.jsp 页面中的 User Login 链接地址应该是:
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")
public class UserController {
@RequestMapping(path = "/login", method=RequestMethod.GET)
public String login() {
return "success";
}
}
这时,如果浏览器发来的请求不是GET的话,将收到浏览器返回的错误提示,也就是得通过链接的方式而不是表单的方式:
来指定 login()方法 仅处理通过 POST 方式发来的请求
@Controller
@RequestMapping(path = "/user")
public class UserController {
@RequestMapping(path = "/login", method=RequestMethod.POST)
public String login() {
return "success";
}
}
这时,必须通过表单的方式发送请求,否则将收到浏览器返回的错误提示
4)由于在 RequestMapping 注解类中 method() 方法返回的是 RequestMethod 数组,所以可以给 method 同时指定多个请求方式,例如:
@Controller
@RequestMapping(path = "/user")
public class UserController {
// 该方法将同时接收通过GET和POST方式发来的请求
@RequestMapping(path = "/login", method={RequestMethod.POST,RequestMethod.GET})
public String login() {
return "success";
}
}
3.4. 测试 params 属性
该属性表示请求参数,也就是追加在URL上的键值对,多个请求参数以&隔开,例如:
http://localhost/user/login?username=admin&password=123456
则这个请求的参数为username=admin以及password=123456,@RequestMapping 中可以使用 params 来限制请求参数,来实现进一步的过滤请求,举个例子:
@Controller
@RequestMapping(path = "/user")
public class UserController {
// 该方法将接收 /user/login 发来的请求,且请求参数必须为 username=kolbe&password=123456
@RequestMapping(path = "/login", params={"username=admin","password=123456"})
public String login() {
return "success";
}
}
该例中则表示 UserController 中的 login() 方法仅处理 /user/login 发来的请求,且必须带有 username=admin&password=123456
的请求参数,否则浏览器将返回HTTP 400
的错误, 对应 index.jsp 中的键接地址为:
User Login
3.5. 测试 headers 属性
该属性表示请求头
,用于HTTP协义交互的信息被称为HTTP报文,客户端发送的HTTP报文被称为请求报文
,服务器发回给客户端的HTTP报文称为响应报文
,报文由报文头部
和报文体
组成。
- 请求头部(RequestHeaders):请求头包含许多有关客户端环境和请求正文的信息,例如浏览器支持的语言、请求的服务器地址、客户端的操作系统等。
- 响应头部(Rsponse Headers):响应头也包含许多有用的信息,包括服务器类型、日期、响应内容的类型及编码,响应内容的长度等等。
如果你安装的是Chrome浏览器,可以通过在网页中 右击鼠标---->审查元素---->Network---->Name中点击网页---->右侧查看Headers即可,如果Name中没有出现网页,可以刷新一下即可,下边是我电脑中的一个请求头部示例:
回规正题,通过 @RequestMapping 中的 headers 属性,可以限制客户端发来的请求
@Controller
@RequestMapping(path = "/user")
public class UserController {
// 表示只接收本机发来的请求
@RequestMapping(path = "/login", headers="Host=localhost:8888")
public String login() {
return "success";
}
}
3.6. 带占位符的URL
1)带占位符的URL是Spring 3.0 新增的功能,可以通过 @PathVariable 将 URL 中的占位符绑定到控制器的处理方法的参数中,占位符使用{}括起来
2)带占位符的URL示例:需要配合@PathVariable接受参数
@Controller
@RequestMapping(path = "/user")
public class UserController {
@RequestMapping(value="/{id}", method=RequestMethod.GET)
public String show(@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>Titletitle>
head>
<body>
<h1>Heelo wordh1>
<a href="user/login?username=admin&password=123456">User Logina>
<a href="user/1">Test Rest GETa>
<form action="user" method="post">
<input type="hidden" name="_method" value="POST"/>
<input type="submit" value="Test Rest POST"/>
form>
<form action="user/1" method="post">
<input type="hidden" name="_method" value="DELETE"/>
<input type="submit" value="Test Rest DELETE"/>
form>
<form action="user/1" method="post">
<input type="hidden" name="_method" value="PUT"/>
<input type="submit" value="Test Rest PUT"/>
form>
body>
html>
5)添加控制器
@Controller
@RequestMapping("/user")
public class UserController {
@RequestMapping(value="/{id}", method=RequestMethod.GET)
public String show(@PathVariable("id") Integer id) {
System.out.println("查看id为:" + id + "的user");
return "success";
}
@RequestMapping(value="/{id}", method=RequestMethod.PUT)
public String update(@PathVariable("id") Integer id) {
System.out.println("更新id为:" + id + "的user");
return "success";
}
@RequestMapping(value="/{id}", method=RequestMethod.DELETE)
public String destroy(@PathVariable("id") Integer id) {
System.out.println("删除id为:" + id + "的user");
return "success";
}
@RequestMapping(value="", method=RequestMethod.POST)
public String create() {
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,解决方案:
- 将请求转发(forward)改为请求重定向(redirect)
- 自己手动写一个Filter来包装HttpRequest中的getMethod()方法
@RequestMapping(value="/{id}", method=RequestMethod.PUT)
public String update(@PathVariable("id") Integer id) {
System.out.println("更新id为:" + id + "的user");
return "redirect:/success.jsp";
}
@RequestMapping(value="/{id}", method=RequestMethod.DELETE)
public String destroy(@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")
@ResponseBody
public ModelAndView getUser(){
ModelAndView view = new ModelAndView();
return view;
}
3.9. produces属性
指定返回的内容类型,返回的内容类型必须是request请求头(Accept)中所包含的类型
@RequestMapping(value = "login",produces = "application/json")
@ResponseBody
public String login() {
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)
,说白了就是想帮助我们省代码,没有其他用途!功能都是一样的!