目录
3.1.3 @RequestMapping是GET请求还是POST请求?
一、了解Servlet
要想了解Spring MVC,先理解下Servlet,Servlet是一种实现动态页面的技术,准确来讲Servlet是一套Java Web开发的规范,或者说是一套Java Web开发的技术标准。
二、什么是Spring MVC?
Spring MVC全程Spring Web MVC,它是基于Servlet API构建的原始Web框架,从一开始就包含在Spring框架中。它正式名称为Spring Web MVC,但它通常被称为Spring MVC,Spring MVC是一个WEB框架。
2.1 MVC定义
MVC是Model View Controller的缩写,它是软件工程中的一种软件架构设计模式,它把软件系统分为模式、视图和控制器三个基础部分。
- View(视图):指在应用程序中专门用来与浏览器进行交互,展示数据的资源
- Model(模型):是应用程序的主题部分,用来处理程序中数据逻辑的部分
- Controller(控制器):可以理解为一个分发器,用来决定对于视图发来的请求,需要用哪一个模型来处理,以及处理完后跳回哪一个视图
举例:
比如去饭店吃饭,客户进店之后,服务员来接待客户点餐,客户点餐之后,把客户菜单交给前厅,前厅根据客户菜单给后厨下达命令,后厨负责做饭,做完之后,再根据菜单告诉服务员,这是哪位客人的饭菜。
在这个过程中:
服务员就是View(视图):负责接待客户,帮助客人点餐以及给顾客端饭
前厅就是Controller(控制器):根据用户的点餐情况,来选择给哪个后厨下达命令
后厨就是Model(模型):根据前厅的要求完成客户的用餐需求
2.2 Spring MVC介绍
MVC是一种架构设计模式,也是一种思想,而Spring MVC是对MVC思想的具体实现,除此之外,Spring MVC还是一个Web框架。
总结来说,Spring Mvc是一个实现了MVC模式的Web框架。
其实,Spring MVC我们在前面已经用过了,在创建Spring Boot项目时,我们在勾选Spring Web框架其实就是Spring MVC框架:
这可能就有点懵了,前面创建的不是Spring Boot项目嘛?怎么又变成了Spring MVC项目了?它们之间到底有着什么样的联系?
Spring Boot只是实现Spring MVC的其中一种方式而已,Spring Boot可以添加很多依赖,借助这些依赖实现不同的功能,Spring Boot通过添加Spring Web MVC框架来实现web功能。
不过在Spring在实现MVC时,也结合自身项目的特点,做出了一些改变,相对而言,下面的图或许更适合一些。
比如上面的例子,去饭店吃饭,一些饭店是前厅来负责接待客户,帮助客户点餐,也就是Controller来负责接收用户的请求
再举一个例子:
比如你去面试公司,可能直接是面试团队来接待候选人,直接省去了HR中间的交接过程,再由面试团队挑选面试官对你进行面试,面试官再将面试情况返回给面试团队,再转交给HR,HR再通知你是否面试通过。
三、学习Spring MVC
学习Spring MVC,重点也就是学习如何通过浏览器和用户程序进行交互
主要分以下三个方面:
- 建立连接:将用户(浏览器)和Java程序连接起来,也就是访问一个地址能够调用到我们的Spring程序。
- 请求:用户请求的时候会带一些参数,在程序中要想办法获取到参数,所以请求这块主要是获取参数的功能。
- 响应:执行了业务逻辑之后,要把程序执行的结果返回给用户,也就是响应。
3.1 建立连接
在Spring MVC中使用@RequestMapping来实现URL路由映射,也就是浏览器连接程序的作用。
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class UserController {
@RequestMapping("/sayHi")
public String sayHi() {
return "hello, Spring MVC";
}
}
接下来访问:http://127.0.0.1:8080/sayHi,就可以看到程序返回的数据了
3.1.1 @RequestMapping注释介绍
@RequestMapping是Spring Web MVC应用程序中最常用的注解之一,它是用来注册接口的路由映射的。
表示服务收到请求时,路径为/sayHi的请求就会调用sayHi这个方法的代码。
路由映射:当用户访问一个URL时,将用户的请求对应到程序中某个类的某个方法的过程就叫路由映射。
既然@RequestMapping已经达到了我们的目的,为什么还需要加@RestController注解呢?
我把@RestController注解去掉,再访问一次:
可以看到,程序报了404,找不到页面
这就是@RestController起到的作用
是因为一个项目中会有很多类,每个类可能会有很多的方法,Spring程序怎么知道要执行哪个方法呢?
Spring会对所有的类进行扫描,如果类加了注解@RestController,Spring才会去看这个类里面的方法有没有加@RequestMapping这个注解,当然它的作用不止这一点,后续会详细介绍。
3.1.2 @RequestMapping使用
@RequestMapping既可修饰类,也可以修饰方法,当修饰类和方法时,访问的地址是类路径+方法路径。
- @RequestMapping标识一个类:设置映射请求的请求路径的初始信息
- @RequestMapping标识一个方法:设置映射请求请求路径的具体信息
为什么 @RequestMapping既可修饰类,也可以修饰方法?
点进去@RequestMapping源码进行查看
红色框中是它的元注解,表示这个注解既可修饰方法 ,也可修饰方法,具体后面介绍。
注意:
- 我们在写项目时,最好也用@RequestMapping注解修饰类,因为我们要是没加这个类注解的话,Spring在进行扫描的时候,不同的类中可能存在相同的修饰方法的@RequestMapping注解,这就会导致找不到究竟执行哪条命令。
- @RequestMapping的URL路径最前面加不加/都可以,Spirng程序启动时,会进行判断,如果前面没有加/,Spring会接上一个/
3.1.3 @RequestMapping是GET请求还是POST请求?
此处我们使用Postman来发送请求
1、发送GET请求
2、发送POST请求
通过上图发现,@RequestMapping既支持GET请求也支持POST请求。
3.2 请求
访问不同的路径,就是发送不同的请求,在发送请求时,可能会带一些参数,所以学习Spring的请求,主要学习如何传递参数到后端以及后端如何接收。
传递参数,此处使用Postman来模拟。
3.2.1 传递单个参数
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/param")
public class Param {
@RequestMapping("/m1")
public String param(String name) {
return "接到的参数name:" + name;
}
}
3.2.2 传递多个参数
@RequestMapping("/m2")
public String param2(String name, String password) {
return "接到的参数name:" + name + ", password:" + password;
}
注意:当有多个参数时,前后端进行参数匹配时,是以参数的名称进行匹配的,因此参数的位置是不影响后端参数的结果。
3.2.3 传递对象
如果参数比较多,方法声明就需要有很多形参,并且后续每次新增一个参数,也需要修改方法声明,我们不妨把这些参数封装成一个对象。
@RequestMapping("/m3")
public String param3(Person p) {
return p.toString();
}
3.2.4 后端参数重命名
@RequestMapping("/m4")
public String param4(@RequestParam("time") String createTime) {
return "接收到的参数createTime:" + createTime;
}

注意:
- 使用@RequestParam进行参数重命名时,请求参数只能和@RequestParam声明的名称一致,才能进行参数绑定和赋值。
- 使用@RequestParam进行参数重命名时,参数就变成了必传参数。
如果想注解的参数不是必传参数呢?
非必传参数设置
先来了解下参数必传的原因,我们查看@RequestParam注解的实现细节就可以发现端倪,注解实现如下:
可以看到required的默认值为true,表示的含义就是:该注解修饰的参数为必传 。
既然如此,我们可以用过设置@RequestParam中的required=false来避免不传递时报错,具体实现如下:
@RequestMapping("/m4")
public String param4(@RequestParam(value = "time", required = false) String createTime) {
return "接收到的参数createTime:" + createTime;
}
可以看到添加required=false后,在请求的URL中没有添加time参数,程序没有报错。
3.2.5 传递数组
@RequestMapping("/m5")
public String param5(String[] arrayParam) {
return Arrays.toString(arrayParam);
}
3.2.6 传递集合
集合参数:和数组类似,同一个请求参数名有很多个,且需要使用@RequestParam绑定参数关系
@RequestMapping("/m6")
public String param6(@RequestParam List<String> list) {
return "size:" + list.size() + ",listParam:" + list;
}
3.2.7 传递JSON对象
接收JSON对象,需要使用@RequestBody注解
@RequestBody:请求正文,意思就是这个注解作用在请求正文的数据绑定,请求参数必须在写请求正文中。
@RequestMapping("/m7")
public String param7(@RequestBody Person person) {
return person.toString();
}
通过Fiddler观察一下请求参数:
3.2.8 获取URL中参数@PathVariable
path variable:路径变量
和字面表达的意思一样,这个注解主要作用在请求URL路径上的数据绑定
@RequestMapping("/m8/{id}/{name}")
public String param8(@PathVariable Integer id, @PathVariable("name") String username) {
return "解析参数id:" + id + ",name:" + username;
}
3.2.9 上传文件
@RequestMapping("/m9")
public String param9(@RequestPart("file") MultipartFile file) throws IOException {
//获取文件名称
String filename = file.getOriginalFilename();
//文件上传到指定路径
file.transferTo(new File("G:/temp" + filename));
return "文件名称:" + filename;
}