天天看点

程序员必须要掌握的Springweb服务构建轻量级Web实战经验

作者:程序员高级码农II

轻量级Web实战经验

介绍完Spring Boot所具备的各项开发轻量级Web的功能特性,接下来,让我们看看在应用程序中使用这些功能特性时应该遵循哪些最佳实践。

设计合理的HTTP端点

RESTful风格把位于服务器端的访问入口看作一种资源,每个资源都使用URI得到一个唯一的地址。从设计规范上讲,我们使用名词来对资源进行描述,标准格式如代码清单4-77所示。

代码清单4-77 RESTful风格标准请求格式代码

http(s)://域名:端口[/版本]/资源1[/子资源2/.../子资源n][/路径变量]

其中的版本号是可选项,而资源本身则是一种嵌套形式,我们可以在资源内部嵌套各种层级的子资源。一个设计合理的HTTP端点如代码清单4-78所示。

代码清单4-78 一个合理的HTTP端点定义代码

GET http(s)://demo.springboot.com/v1.1/user/friend/10

可以看到上面这个HTTP端点示例的结构非常清晰,我们从这个URL中能够明确资源的层级以及各级所对应的内容。在传输协议上,RESTful风格使用的就是标准的HTTP方法,比如最常见的GET、PUT、POST和DELETE。表4-2展示了RESTful风格的一些具体示例。

表4-2 RESTful风格示例

程序员必须要掌握的Springweb服务构建轻量级Web实战经验

如果你的RESTful接口写得足够标准,其他开发人员应该可以轻松地根据请求方式与URL的语义,猜出这些接口的作用,这也是RESTful风格的核心价值所在。

开发自解释型Open API

HATEOAS技术的主要亮点是在返回结果中提供链接,用于指向其他相关对象,使得客户端开发人员不需要查看API定义文档,也知道下一步应该做什么。在日常开发过程中,如果工作中仅涉及单纯的前后端交互接口,实际上并没有特别的需要来引入HATEOAS。

最适合HATEOAS的应用场景应该是对外开放公共的接口,也就是通常所说的Open API。因为外部团队的开发人员如果根据Open API的定义就能明确其功能和使用方式,那么无疑能够极大降低对接的成本和时间。

使用GraphQL替代RESTful API

在一定程度上,我们可以认为GraphQL是RESTful API的替代物。接下来,我们围绕这个话题展开讨论。

1. GraphQL的应用场景

需要明确的是,我们并不推荐你在任何场景下都使用GraphQL。对于那些API定义与资源概念匹配度较高,也不需要实现类似在用户信息内部嵌套家庭成员信息的复杂查询场景,传统的RESTful API仍然是首选,各个HTTP端点之间相互独立,职责非常明确。但对某些场景而言,GraphQL则更有优势。

首先,对于业务复杂度较高的场景,推荐使用GraphQL。因为复杂度的产生很大程度上是由于应用程序关联的系统、模块以及功能之间的联动与交互程度很高。这时候如果采用RESTful所提供的基于资源的方式来设计方法,接口定义与资源概念一般很难匹配,也就无法很好地表达API的含义。

其次,对于互联网应用而言,业务和需求变化很快,对应的API定义和数据结构同样也是多变的。这时候,通过引入GraphQL能够有效降低沟通成本。

这点对于分布式办公场景尤其明显,因为在这种场景下前后端开发人员往往需要反复确认API定义和响应数据类型,沟通成本很高。

最后,如果你的团队采用的是敏捷开发模式,在文档化管理的流程和工具使用上比较薄弱的话,同样建议使用GraphQL。GraphQL把开发人员从维护文档的工作中释放出来,通过请求和响应结果之间的对应关系,解决前后端数据的一致性和同步性。

2. 实施GraphQL的策略

关于如何实施GraphQL,我们首先要讨论的是由谁来实现GraphQL,是前端还是服务端呢?这个问题一直被大家争论。对于大多数系统而言,前后端都需要紧密配合,在这个配合过程中,前端开发人员的痛点往往是多于服务端开发人员的。所以,一般场景下前端开发人员对于引入GraphQL的诉求要强

于服务端开发人员。另外,如果采用和RESTful API一样的开发模式,那么实现GaphQL的工作量主要是在服务端。服务端开发人员需要基于GraphQL规范重新设计并实现API,通常都建议单独构建一个数据层来对外暴露GraphQLAPI,如图4-10所示。

程序员必须要掌握的Springweb服务构建轻量级Web实战经验

图4-10 在后端服务中构建数据层示意图

请注意,GraphQL只是一种规范,并不是开发语言,而支持GraphQL的开发语言有很多种,包括面向前端的Javascript,面向服务端的Java、Go等。

所以,原则上,前端和服务端都有能力去实现GraphQL。例如,图4-11所示的就是构建在前端系统和后端服务之间的一个数据层,可以由前端团队来实现这个数据层。

程序员必须要掌握的Springweb服务构建轻量级Web实战经验

图4-11 在前端系统中构建数据层示意图

在具体实施GraphQL的策略上,我们也可以总结几条最佳实践。如果你已经实现了一部分RESTful API,那么可以让GraphQL与这部分RESTful API并存发展。尤其是对于那些单一的RESTful服务,可以把GraphQL直接嫁接到已有的RESTful服务上。通过这种策略,RESTful服务中已经实现的业务逻辑层、数据访问层组件都可以得到复用,我们要做的只是开放一个新的GraphQL访问入口而已。而且,对于一项新技术的引入过程,GraphQL和RESTful服务在一段时间内并存发展也符合其平滑过渡的客观需求,如图4-12所示。

程序员必须要掌握的Springweb服务构建轻量级Web实战经验

图4-12 RESTful和GraphQL并存发展示意图

如果你正在采用微服务架构,那么引入GraphQL的策略就可以在所有后端微服务之前架设一层由GraphQL构建的数据层,并对后端服务提供的数据进行自由组装之后再开放给前端。这种实施策略类似于微服务架构中的API网关,一方面对前端请求进行适配和路由,另一方面完成前后端之间的解耦。

轻量级Web面试题分析

面试题1:@RestController注解与@Controller注解有什么区别?

答案:对于使用过Spring Boot的开发人员而言,这是一道送分题。在基于传统Spring WebMVC开发Web服务时,我们往往需要将@Controller注解和@ResponseBody注解组合在一起使用,目的就是确保返回的响应结果是JSON格式。而Spring Boot引入的@RestController注解会自动使用JSON实现HTTP请求和响应的序列化和反序列化。

面试题2:在使用RestTemplate工具类时,如果想要同时发起GET和POST请求,你可以选择使用哪些方法?

答案:RestTemplate工具类提供了一系列非常有用的方法组来实现对HTTP端点的访问,其底层就是基于execute()方法实现的,所以我们可以使用该方法来实现基于各种HTTP方法的远程调用。但是execute()方法比较偏底层,更多的时候我们使用exchange()这个通用方法,它既能发送GET和POST请求,也能用于其他各种类型的请求。

面试题3:如果让你开发一款用于HTTP远程调用的工具,你会如何进行设计并实现?

答案:这是一道开放式的面试题,也是比较有代表性的一类试题,考查你是否能够在理解目前主流实现工具的基础上提供一些自身的思考和总结。

对于HTTP远程调用,创建请求对象、执行远程调用以及处理响应结果是最基本的流程。而在Spring Boot中,RestTemplate是一个优秀的工具类,基于模板方法实现了完整的HTTP请求和响应过程。我们也可以把RestTemplate看作HTTP远程调用工具的一种样板,因此,可以参考本章中关于RestTemplate的实现原理给出对该问题的解答思路和过程。

面试题4:REST成熟度模型是什么样的?你能简要描述什么是HATEOAS吗?

答案:很多时候,我们习惯使用传统的RESTful API来实现HTTP端点,但实际上这并不是REST的全部。只有使用了超媒体的Web API才代表REST模型的最高成熟度。关于如何实现这种成熟度,业界也提供了HATEOAS,也就是使用了超媒体的应用状态引擎。针对这类面试题,重点是讲清楚多媒体、超链接、超媒体等这些核心概念,一般不需要对细节做过多讲述。

面试题5:你能简要描述Spring HATEOAS的开发模式和应用场景吗?

答案:Spring HATEOAS是Spring家族中专门针对HATEOAS的开发框架,它的开发模式实际上和RESTful API在本质上是一致的,都是围绕“资源”这一核心概念设计的开发流程。与实现普通Controller不同,Spring HATEOAS对资源和链接的实现有特定的一套API,并且提供了强大的资源装配器来完成对资源的组合。Spring HATEOAS的应用场景也比较广泛,在Spring Boot内部就大量使用HATEOAS来暴露HTTP端点,典型的例子就是Spring Boot Actuator组件。而对于日常开发而言,推荐使用Spring HATEOAS来暴露面向外部系统的Open API。

面试题6:结合日常开发过程,你有没有在使用RESTful API时碰到一些痛点?

答案:这也是一道典型的开放式面试题。这种问题不一定有标准的答案,主要考查的是你对开发过程的思考和总结。事实上,关于前后台API联调和对接过程中所碰到的问题,每个公司、每个团队都存在,关键在于我们如何看待和定位这些问题。在本章中提到的远程调用的数据格式、参数和返回值、多次请求以及HTTP端点数量的问题在日常开发过程中都很典型,我们可以结合自身的一些案例进行讨论,充分表述自己的观点。

面试题7:使用过GraphQL吗?你觉得它有什么优势?

答案:这道题的问法虽然和上一题完全不同,但回答的方式实际上是类似的。在大多数团队中,GraphQL目前还没有得到应用。所以,这道题更多考查的是你的知识点的广度。如果你了解这个主题,那么可以按照本章中对这一主题的讲述思路组织内容,并用自己的语言进行表述。如果你不了解这个主题,那也需要做到能够变通,通过提出一些问题把GraphQL的含义搞清楚,然后按照上一题的思路进行表述。

本文给大家讲解的内容是springweb服务构建轻量级Web技术体系:轻量级Web实战经验

  • 下文给大家讲解的是springweb服务应用响应式Web开发组件:响应式编程和Spring Boot