以前学过ThinkPHP,在初学的时候,几乎没有任何基础。当时被这种MVC分离的框架搞晕了,都不知道数据是怎么在各层之间传递的。
后来发现,搞懂MVC的关键,就是理解数据流。当时我还作了一张很大的图片,记录了MVC和数据库之间传值的方式和CRUD的过程。(因为这张图片是好久之前制做的,可能不彻底正确)数据库
当把数据流融会贯通之时,就是开悟之日。浏览器
先从总体上分析浏览器、先后台、数据库之间的数据流:服务器
上图只是为了搞清楚数据在各个部门间的传递过程,图中的前台代码和后台代码实际上都是MVC,只是为了方便理解,在图中简化了。框架
接下来,展开它们:post
用文字来解释一下上图的数据流:学习
对以上过程的一些说明:this
//定义请求地址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); });
//V层代码 <td>{{student.name}}</td>
//C层代码 username: string; //V层代码 <input type="text" id="username" name="username" [(ngModel)]="username">
//C层代码 public onSubmit(): void { } //V层代码 <form id="teacherAddForm" (ngSubmit)="onSubmit()"> </form>
//C层代码 onDelete(klass: Klass): void { } //V层代码 <button (click)="onDelete(klass)">删除</button>
//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分离或者先后台分离的框架,理解它们的关键,就在于搞明白数据从哪来到哪去。这是站在一个宏观的总体的角度去看待问题。url
若是不理解数据流,只关注代码自己,那么代码就只会是一个个片断,而没法在思惟中连成总体。spa
从我一个小白的角度来看,搞明白数据流,是学习如何使用框架的良好开端。code