前后端分离介绍及优势分析
前后端分离的核心思想是前端 HTML 页面通过 ajax 调用后端的 RESTful API 接口并使用 json 格式进行数据交互。前后端除了数据的传输外,没有太多的联系,所以前后端人员可以独立开发,独立测试。
关于前后端分离开发的优势,个人觉得有以下几点:
- 前后端分离的开发模式下,后端人员可以把精力放在业务功能的实现和系统的稳定性上,而前端工程师就可以把精力放在页面表现,速度流畅,兼容性,用户体验等这些方面。随着业务需求的增多,我们需要更高效的开发模式,所以前后端分离的方式更适合协同敏捷开发;
- 针对各种不同的终端(Web端、移动端),都可以使用同一套后台服务;
- 页面和接口通过Ajax请求进行交互,所以前后端站点、数据库都可以分别部署于不同的服务器上,甚至每一个后台接口也都可以单独部署,这样就减轻了单个服务器的压力。此外由于前端页面和后台接口是分开的,所以说前后端的维护和修改也是互相独立的;
- 可以快速定位问题,不会出现互相踢皮球的现象。页面逻辑,跳转错误,浏览器兼容性问题,脚本错误,页面样式等问题,全部由前端工程师来负责;接口数据出错,数据没有提交成功,应答超时等问题,全部由后端工程师来解决。大家各司其职,各自负责;
- 即使后端服务暂时超时或者宕机了,前端页面也会正常访问,只不过数据刷不出来而已;
- 在高并发情况下,可以同时水平扩展前后端服务器;
- 前端大量的组件代码得以复用,组件化,提升开发效率。
接口文档规范
前后端分离过程中,前后端人员可以通过规范的接口说明文档来进行对接,一个接口文档的示例如下:
其中,一个规范的接口文档至少应该包括请求地址(url)、请求类型(get、post)、请求参数列表(包括参数调用示例,比如一个参数中包含多个值,是通过“,”分隔,还是封装成数组传输,以及参数的取值范围等)、返回数据的类型(json、xml、string等),以及返回数据的示例等,如果返回的json字符串包含较多字段,最好也要对每一个字段的含义进行说明。(一个规范的测试用例,可以帮助前端人员快速完成前后端功能的对接。)
如果前后端进度差不多同步的话,可以在每一个接口开发完成就将接口文档发给前端,而不要等所有接口都开发完才和前端对接,这样可以提高效率,并且及时根据新的需求去改变接口;另一方面,如果对开发效率要求很高的话,就要在页面设计完成后,就由前后端人员和产品经理共同确定接口文档,然后前后端人员严格按照接口文档开发(这个时候就不能随便改动了)。
数据安全性考虑
因为常规的web项目无论如何前端都是要通过公网访问到后台 api ,所以后端 api 是暴露在外网中,由此带来很多隐患。为了防止数据被外部调用,导致数据泄露(比如被爬虫获取),前后端分离的接口可以增加 Token 作为参数(比如钉钉小程序的官方接口),或者加上 Cookies,从而可以保证接口的访问权限。
参数配置
对于一些可能在使用过程中会变动的参数,比如文件路径的前缀,尽量不要写在移动端代码中或前端代码中,而是建议写在配置中,方便修改。
如果是移动端,代码修改后需要重新生成安装包;如果是 web 端,也是同样的道理。而如果将配置信息写在后台代码的配置文件中,在需要修改时直接在后台修改 web.config 即可,前台是感受不到变化的,这样能提高系统的可维护性,这也是前后端分离的一个优势。
缓存机制
有些场景下,后端在将数据返回给前端之前,会经过复杂的数据处理,其中包括从数据库中获取数据,对数据进行处理,对数据结构进行重新组织,如果数据量较大的话会耗费很多时间。
而如果一个接口返回的数据相对是固定的,这种情况下就没有必要每次都重新获取,所以可以将这些相对固定的信息记录在缓存中。比如在数据库中省/市/县区域是固定的,如果每次都重新获取并进行处理,会浪费很多时间,而通过将其写入 redis 缓存,可以节约很多时间,极大地提高响应速度。
跨域问题处理
在前端向后端发送POST请求时,会产生两个请求记录(OPTIONS和POST),比方说发送POST请求“/getdata”,在控制台能看到两个URL一致的请求,第一个无 body、无响应,以 OPTIONS 方式发送,第二个才是正常的有参数 body、有response,以POST方式提交的请求。这是 POST 的实现机制导致的结果,当发生跨域请求时,浏览器会先发送一个options请求,来确认服务器是否能够正常通讯,是否允许接受请求,如果不能就不会发送真正的请求过来,如果测试通讯正常,则开始发送真正的请求。
关于这个问题,需要针对POST请求在后台进行设置,允许 OPTIONS 请求,否则 POST 请求就会受到影响。关于 OPTIONS 请求的处理方式,各种编程语言、应用框架中不尽相同,这里不做说明。
错误代码说明
一个接口在执行代码的过程中,可能会出现各种情况,理想情况下会得到预期的结果,但也可能因为各种原因导致无法功能正常执行,这时后台代码要将错误信息返回前端。这个时候一般不会将错误信息直接返回给前端,因为不方便前端展示。这里就可以用状态码表示请求结果。
而前端需要有机制应对后端请求超时以及后端服务错误的情况,友好的展示给用户。
可以参考 HTTP 状态码,像404表示服务器无法找到所请求的页面,500 表示服务器代码发生了错误,408 表示请求超时等。也可以将错误信息用代码表示,比如用“-1”表示数据库连接失败,用“-2”表示参数有误等,当然最终这些返回值的意义要在接口文档中写清楚。
一般在接口返回的数据中,可以包含请求成功与否,错误代码,返回信息等,比如钉钉小程序开发文档中提供的示例:
前后端人员配合事项
这前后端分离的开发模式下,开发之前会先完成页面设计,然后据此构建好数据表,然后前后端人员一起研究页面之后共同决定接口设计,这里建议前后端人员都要研究一下页面,这样才能更好地了解需求。比如:
- 前端开发人员需要要了解后台数据的大致内容,比如返回内容的组织形式;
- 后端人员也要了解页面中的输入参数、以及页面需要的返回参数,比如前端需要以何种形式组织数据,是否需要分页,是否需要后端告知数据的总条数,这些只看功能需求本身是无法得到的。
在接口设计确定了之后,在实现的过程中后端要严格按照设计实现,需要改动的话要和前端人员协商后再处理,否则最后得到的接口可能不符合前端的需求,导致页面无法渲染。
当然并不是所有的接口都可以提前定义,有一些是要在开发过程中进行调整。在开发的过程中,双方也要及时沟通,才能最快地解决问题,完成任务。
前后端职责划分
有一个比较常见的问题是前端和后端开发人员对职责的区分不清楚,比如说,有一个功能可以通过前端也可以通过后台来实现,这时可能会存在疑问,就是这个功能谁来做。这时需要大家相互协调,考虑前后端实现的难度和效率,比如:
- 涉及到比较多数据操作的可以由后台来做;
- 在高并发场景下,对于既可以前端做也可以后端做的逻辑,建议是放到前端,因为逻辑需要计算资源进行计算,如果放到后端去执行,则会消耗带宽、内存、CPU等等计算资源。由于服务端的计算资源是有限的,而如果放到前端,使用的是客户端的计算资源,这样高并发场景下服务端负载就会下降;
- 类似于数据校验这种,前后端都需要做。
注意事项
- 在开需求会议的时候,前后端工程师尽量全部参加,并且需要制定好接口文档,后端工程师要写好测试用例,不要让前端工程师充当后端的专职测试,推荐使用 Postman 或 Soapui 或 Jmeter,service层的测试可以用 Junit;
- 关于 Postman 之类的调试工具,可能会有一个坑,就是这些工具太智能了,有些问题在上面是调试不出来的。比较常见的是跨域问题,可能在 Postman 调试是通的,但是到了浏览器上就会报错。
所以如果前端人员反映接口有问题,可以先不要急着否认,建议可以自己写一个 js 脚本,通过 Ajax 方法调用一下,看看是不是有问题,也就是尽量把自己当成一个前端人员,在前端人员的开发环境下去找问题。 - 前后端分离,尽量避免返回值是 null,而是返回特定的错误码,并提示返回 null 的原因。