SpringBoot+Angular前后端分离的数据流浅析

零、前言

之前学过ThinkPHP,在初学的时候,几乎没有任何基础。当时被这种MVC分离的框架搞晕了,都不知道数据是怎么在各层之间传递的。
后来发现,搞懂MVC的关键,就是理解数据流。当时我还做了一张很大的图片,记录了MVC和数据库之间传值的方式和CRUD的过程。(由于这张图片是很久以前制作的,可能不完全正确)
image

当把数据流融会贯通之时,就是开悟之日。

一、由浅入深,分析流程

浏览器、前后台、数据库

先从整体上分析浏览器、前后台、数据库之间的数据流:

图片.png

上图只是为了搞清楚数据在各个部门间的传递过程,图中的前台代码和后台代码实际上都是MVC,只是为了方便理解,在图中简化了。

MVC

接下来,展开它们:

图片.png

解释数据流

用文字来解释一下上图的数据流:

  1. 用户通过浏览器Url向前台发起请求
  2. 前台服务器返回前台程序
  3. 执行前台程序
  4. 前台C层通过Url请求后台C层的方法
  5. 后台C层调用服务层方法
  6. 后台服务层调用仓库的接口
  7. 仓库通过SQL请求数据库
  8. 数据库返回数据给仓库
  9. 后台仓库接收数据,返回给后台服务层
  10. 服务层把数据转换成对象,返回给后台C层
  11. 后台C层把对象转换为JSON字符串,并返回给前台C层
  12. 前台C层接收JSON字符串,转化为对象,渲染V层组件
  13. 获取返回后的组件,呈现给浏览器页面

对以上过程的一些说明:

  • 前台C层只负责数据转发,前台V层是没有数据的页面模板
  • 后台C层只负责数据转发,后台M层是业务逻辑的具体实现
  • 前后台的交互,是通过前台C层向后台C层发起Http请求来实现的
  • 后台和数据库的交互,是通过M层发起SQL语句来实现的
  • 前台实体、后台实体、数据表字段始终相互对应

二、功能的具体实现

前台请求后台:HttpClient

//定义请求地址url
const url = 'http://localhost:8080/Klass';  
//定义需要请求的对象
const klass = new Klass(undefined, this.name.value,  
 this.teacher  
);

//执行http请求,并订阅
//使用观察者模式,如果成功或失败,则执行对应的代码
this.httpClient.post(url, klass)  
  .subscribe(() => {  
    console.log('保存成功');  
 this.router.navigateByUrl('/klass', {relativeTo: this.route});  
  }, (response) => {  
    console.log(`向${url}发起的post请求发生错误` + response); 
  });

前台直接显示C层变量:双花括号{{}}

//V层代码
<td>{{student.name}}</td>

前台C、V层双向数据绑定:[(ngModel)]

//C层代码
username: string;

//V层代码
<input type="text" id="username" name="username" [(ngModel)]="username">

前台表单:(ngSubmit)

//C层代码
public onSubmit(): void {  
 
}

//V层代码
<form id="teacherAddForm" (ngSubmit)="onSubmit()">  

</form>

前台按钮:(click)

//C层代码
onDelete(klass: Klass): void {  

}


//V层代码
<button (click)="onDelete(klass)">删除</button>

后台C层调用服务层方法:接口

//StudentService(服务层)
Student save(Student student);

//StudentServiceImpl(接口的具体实现)
public Student save(Student student) {  
    return this.studentRepository.save(student);  
}

//StudentController(C层,调用M层Save()) 
public Student save(@RequestBody Student student) {  
    return studentService.save(student);  
}

后台向数据库请求数据:仓库

//StudentServiceImpl (服务层接口的具体实现)
public Page<Student> findAll(Pageable pageable) {  
    return this.studentRepository.findAll(pageable);  
}

//StudentRepository (仓库:执行请求数据库的动作)
default Page findAll(String name, String sno, Klass klass, @NotNull Pageable pageable) {  
    Assert.notNull(pageable, "传入的Pageable不能为null");  
Specification<Student> specification = StudentSpecs.containingName(name)  
            .and(StudentSpecs.startWithSno(sno))  
            .and(StudentSpecs.belongToKlass(klass));  
return this.findAll(specification, pageable);  
}  

总结

对于这些MVC分离或者前后台分离的框架,理解它们的关键,就在于搞明白数据从哪来到哪去。这是站在一个宏观的整体的角度去看待问题。

如果不理解数据流,只关注代码本身,那么代码就只会是一个个片段,而无法在思维中连成整体。

从我一个小白的角度来看,搞明白数据流,是学习如何使用框架的良好开端。

阅读 1.1k

推荐阅读
目录