【Spring】Spring MVC 入门(2)
本系列共涉及4个框架:Sping,SpringBoot,Spring MVC,Mybatis。
博客涉及框架的重要知识点,根据序号学习即可。
目录
本系列共涉及4个框架:Sping,SpringBoot,Spring MVC,Mybatis。
博客涉及框架的重要知识点,根据序号学习即可。
1、什么是MVC
1.1定义
1.2模型
1.3详解
2、什么是Spring Web MVC
2.1官方定义
2.2三大功能
2.3 模型
2.4建立连接
2.5@RequestMapping 注解
3、请求
3.1传递单个参数
3.2传递多个参数
3.3传递数组
3.4传递集合
3.5传递JSON
3.6在URL中获取参数
3.7文件上传
编辑
4、响应
4.1返回静态页面
4.2返回数据@Responsebody
4.3返回HTML代码片段
4.4返回JSON
4.5设置状态码
4.6设置header
4.6.1设置Content-Type
4.6.2设置其他header
5、应用分层
5.1什么是应用分层
5.2如何分层-----三层架构
5.3MVC与三层架构的区别
1、什么是MVC
1.1定义
MVC 是 Model View Controller 的缩写,它是软件工程中的⼀种软件架构设计模式,它把软件系统分为模型、视图和控制器三个基本部分。
1.2模型
1.3详解
- View(视图) 指在应⽤程序中专门用来与浏览器进行交互,展示数据的资源.
- Model(模型) 是应⽤程序的主体部分,⽤来处理程序中数据逻辑的部分
- Controller(控制器)可以理解为⼀个分发器,⽤来决定对于视图发来的请求,需要⽤哪⼀个模型来处理,以及处理完后需要跳回到哪⼀个视图。即⽤来连接视图和模型
2、什么是Spring Web MVC
2.1官方定义
(1)Spring Web MVC 是基于 Servlet API 构建的原始 Web 框架,从⼀开始就包含在 Spring 框架中。它的正式名称“Spring Web MVC”来⾃其源模块的名称(Spring-webmvc),但它通常被称为"Spring MVC"
(2)MVC 是⼀种架构设计模式, 也⼀种思想, ⽽ Spring MVC 是对 MVC 思想的具体实现. 除此之外, Spring MVC还是⼀个Web框架。
总结来说,Spring MVC 是⼀个实现了 MVC 模式的 Web 框架。
(3)Spring MVC 全称是 Spring Web MVC 。其实, Spring MVC 我们在前⾯已经⽤过了, 在创建 Spring Boot 项目时,我们勾选的 Spring Web 框架 其实就是 Spring MVC 框架。这时候可能大家就懵了, 前⾯创建的不是SpringBoot项⽬吗? 怎么又变成了Spring MVC项⽬? 他们之间到底有着什么样的关系? ---------Spring Boot 只是实现Spring MVC的其中⼀种⽅式。Spring Boot 可以添加很多依赖, 借助这些依赖实现不同的功能。Spring Boot 通过添加Spring Web MVC框架, 来实现web功能。
2.2三大功能
咱们学习Spring MVC, 重点也就是学习如何通过浏览器和程序进行交互。主要分以下三个方⾯:
1. 建⽴连接:将用户(浏览器)和 Java 程序连接起来,也就是访问⼀个地址能够调用到我们的
Spring 程序。
2. 请求: 用户请求的时候会带⼀些参数,在程序中要想办法获取到参数, 所以请求这块主要是获取参数的功能。
3. 响应: 执行了业务逻辑之后,要把程序执行的结果返回给用户, 也就是响应.
对于 Spring MVC 来说,掌握了以上 3 个功能就相当于掌握了 Spring MVC
2.3 模型
2.4建立连接
2.5@RequestMapping 注解
@RequestMapping 是 Spring Web MVC 应用程序中最常被用到的注解之⼀,它是⽤来注册接⼝的
路由映射的。表示服务收到请求时, 路径为/hello的请求就会调⽤ hello() 这个⽅法的代码.
路由映射: 当用户访问⼀个 URL 时, 将用户的请求对应到程序中某个类的某个方法的过程就叫路由映射。
既然 @RequestMapping 已经可以达到我们的目的了, 我们为什么还要加 @RestController
呢? 我们把 @RestController 去掉, 再来访问⼀次:
可以看到, 程序报了404, 找不到该页面。这就是 @RestController 起到的作用。
⼀个项⽬中, 会有很多类, 每个类可能有很多的⽅法, Spring程序怎么知道要执⾏哪个⽅法呢?
Spring会对所有的类进⾏扫描, 如果类加了注解@RestController, Spring才会去看这个类⾥⾯的⽅法 有没有加 @RequestMapping 这个注解, 当然他的作⽤不⽌这⼀点,后续详说。
- @RequestMapping 即可修饰类,也可以修饰⽅法 ,当修饰类和⽅法时,访问的地址是类路径 + 方法路径
- @RequestMapping标识⼀个类:设置映射请求的请求路径的初始信息
- @RequestMapping标识⼀个⽅法:设置映射请求请求路径的具体信息
3、请求
3.1传递单个参数
(1)后端代码:
@RequestMapping("/param")
@RestController
public class ParamController {
@RequestMapping("/m1")
public String m1(String name){
//传递单个参数
return "传递的单个参数为:"+name;
}
}
运行结果:
(2)后端代码:
@RequestMapping("/m2")
public String m2(int age){
//传递单个参数 接收参数为基本数据类型时,必须传参,否则会报500,所以最好用包装类接收
return "传递的单个参数为:"+age;
}
运行结果:
3.2传递多个参数
(1)后端代码:
@RequestMapping("/m3")
public String m3(String name,String password){
//传递多个参数
return "name:"+name+",password:"+password;
}
运行结果:
(2)后端代码:
@RequestMapping("/param")
@RestController
public class ParamController {
@RequestMapping("/m4")
public String m4(Person person){
//传递多个参数
return person.toString();
}
}
public class Person {
private int id;
private String name;
private String password;
@Override
public String toString() {
return "Person{" +
"id=" + id +
", name='" + name + '\'' +
", password='" + password + '\'' +
'}';
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}
运行结果:
(3)后端代码:
@RequestMapping("/m5")
public String m5(@RequestParam(value = "username",required = false) String name){
//重命名,前后端定义的字段名不一样 前端:username 后端:name
//并且@RequseParam注解是必传,没有传参会报错 除非required设置为false
return " 接收到的name:"+name;
}
运行结果:
3.3传递数组
后端代码:
@RequestMapping("/m6")
public String m6(String[] arr){
//传递数组
return Arrays.toString(arr);
}
运行结果:
3.4传递集合
后端代码:
@RequestMapping("/m7")
public String m7(@RequestParam List<Integer> list){
//传递集合和传递数组类似,同一个请求参数名有多个时,默认情况下是封装为数
// 组的,但是如果要封装到集合,要使用注解
//@RequestParam 绑定参数关系
return "size:"+list.size()+",list:"+list;
}
运行结果:
3.5传递JSON
后端代码:
@RequestMapping("/m8")
public String m8(@RequestBody Person person){
//传递JSON,需要使用@RequestBody注解
//requestbody:请求正文,意思这个注解作用
//在请求正文的数据绑定,请求参数必须写在请求正文中
return person.toString();
}
运行结果:【用postman进行接口测试】
3.6在URL中获取参数
后端代码:
@RequestMapping("/m9/{id}/{name}")
public String m9(@PathVariable Integer id,@PathVariable String name){
//获取URL中的参数
//@PathVariable,这个注解主要作用在请求url路径上的数据绑定
return "id:"+id+",name:"+name;
}
运行结果:
3.7文件上传
后端代码:
@RequestMapping("/m10")
public String m10(@RequestPart MultipartFile file) throws IOException {
//上传文件使用注解@RequestPart
//获取文件名称
String fileName=file.getOriginalFilename();
//文件上传到指定路径
file.transferTo(new File("D:/108code/"+file.getOriginalFilename()));
return "接收到的文件名"+fileName;
}
运行结果:
4、响应
4.1返回静态页面
静态页面index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
hello,index
</form>
</body>
</html>
后端代码:
@RestController
@RequestMapping("/index")
public class IndexController {
@RequestMapping("/m1")
public Object m1(){
//返回静态页面
return "/index.html";
}
}
结果:
结果却发现, ⻚⾯未正确返回, http响应把
"/index.html"
当做了http响应正⽂的数据
那Spring MVC如何才能识别出来
index.html
是⼀个静态⻚⾯, 并进⾏返回呢?
我们需要把
@RestController
改为
@Controller
正确代码如下:
@Controller
@RequestMapping("/index")
public class IndexController {
@RequestMapping("/m1")
public Object m1(){
//返回静态页面
return "/index.html";
}
}
注解:@RestController与@Controller的区别:
MVC的概念也逐渐发⽣了变化, View不再返回视图, ⽽是返回显⽰视图时需要的数据.
所以前⾯使⽤的 @RestController 其实是返回的数据.
@RestController = @Controller + @ResponseBody
@Controller : 定义⼀个控制器, Spring 框架启动时加载, 把这个对象交给Spring管理.
@ResponseBody : 定义返回的数据格式为⾮视图, 返回⼀个 text/html 信息
4.2返回数据@Responsebody
@RequestMapping("/m2")
public Object m2(){
//返回数据@ResponseBody
return "/index.html";
}
4.3返回HTML代码片段
@RequestMapping("/m3")
public String m3(){
//返回HTML代码片段
return "<h1>hello,html</h1>";
}
4.4返回JSON
@RequestMapping("/m4")
public HashMap<String,String> m4(){
//返回JSON
HashMap<String,String> map=new HashMap<>();
map.put("java","java value");
map.put("mysql","mysql value");
return map;
}
4.5设置状态码
@RequestMapping("/m5")
public String m5(HttpServletResponse response){
//设置状态码
response.setStatus(401);
return "设置状态码成功";
}
【Fiddle抓包查看状态码是否设置成功】
4.6设置header
4.6.1设置Content-Type
@RequestMapping(value = "/m6",produces = "application/json")
public String m6(){
//设置content-type
return "{\"success\":true}";
}
4.6.2设置其他header
@RequestMapping(value = "/m7")
public String m7(HttpServletResponse response){
//设置其他header
response.setHeader("MyHeader","MyHeaderValue");
return "设置header成功";
}
5、应用分层
5.1什么是应用分层
(1)什么是应⽤分层
应⽤分层 是⼀种软件开发设计思想, 它将应⽤程序分成N个层次, 这N个层次分别负责各⾃的职责, 多个层次之间协同提供完整的功能. 根据项⽬的复杂度, 把项⽬分成三层, 四层或者更多层.
常⻅的MVC设计模式, 就是应⽤分层的⼀种具体体现
(2)为什么需要应⽤分层?
在最开始的时候,为了让项⽬快速上线,我们通常是不考虑分层的. 但是随着业务越来越复杂,⼤量的 代码混在⼀起,会出现逻辑不清晰、各模块相互依赖、代码扩展性差、改动⼀处就牵⼀发⽽动全⾝等 问题. 所以学习对项⽬进⾏分层就是我们程序员的必修课了
5.2如何分层-----三层架构
(1)之前学习的 "MVC", 就是把整体的系统分成了 Model(模型), View(视图)和Controlle(控制器)三个层次,也就是将用户视图和业务处理隔离开,并且通过控制器连接起来,很好地实现 了表现和逻辑的解耦,是⼀种标准的软件分层架构。
(2)目前现在更主流的开发方式是 "前后端分离" 的⽅式, 后端开发⼯程师不再需要关注前端的实现, 所以对 于Java后端开发者, 又有了⼀种新的分层架构: 把整体架构分为表现层、业务逻辑层和数据层。这种分层方式也称之为"三层架构".
- 表现层: 就是展⽰数据结果和接受⽤⼾指令的,是最靠近⽤⼾的⼀层
- 业务逻辑层: 负责处理业务逻辑, ⾥⾯有复杂业务的具体实现
- 数据访问层: 负责存储和管理与应⽤程序相关的数据
(3)按照上面的层次划分, Spring MVC 站在后端开发⼈员的⻆度上, 也进行了支持, 把上面的代码划分为三 个部分:
- Controller:控制层。接收前端发送的请求,对请求进⾏处理,并响应数据。
- Service:业务逻辑层。处理具体的业务逻辑。
- Dao:数据访问层,也称为持久层。负责数据访问操作,包括数据的增、删、改、查
5.3MVC与三层架构的区别
(1)关于二者的关系, ⼀直存在不同的观点。有人认为三层架构是MVC模式的⼀种实现, 也有⼈认为MVC是三层架构的替代方案, 等等各种说法都有。根本原因是⼤家站在不同的角度来看待这个问题的
(2)从概念上来讲, 二者都是软件⼯程领域中的架构模式
- MVC架构模式由三部分组成, 分别是: 模型(Model), 视图(View)和控制器(Controller);三层架构将业务应⽤划分为:表现层, 业务逻辑层, 数据访问层
- MVC中, 视图和控制器合起来对应三层架构中的表现层. 模型对应三层架构中的业务逻辑层, 数据层, 以及实体类,二者其实是从不同⻆度对软件工程进行了抽象
- MVC模式强调数据和视图分离, 将数据展示和数据处理分开, 通过控制器对两者进行组合;三层架构强调不同维度数据处理的高内聚和低耦合, 将交互界⾯, 业务处理和数据库操作的逻辑分开。角度不同也就谈不上互相替代了。