当前位置: 首页 > news >正文

Nop入门:极简服务层实现

Nop平台的后端服务采用NopGraphQL引擎来实现,它的设计相比于SpringMVC这种传统的Web框架要更加精炼、通用,仅包含数学层面上最小化的假定,通过类似数学的自动推理机制可以实现SpringMVC所无法达到的高度可组合性和可复用性。

NopGraphQL引擎的实现原理可以参考文章: 为什么在数学的意义上GraphQL严格的优于REST?和低代码平台中的GraphQL引擎

以下介绍如何集成spring框架,并实现一个最简单的后台服务函数。

一. 引入nop-spring-web-starter依赖

一般情况下可以选择将pom文件的parent设置为nop-entropy模块,从而自动引入缺省的maven配置

<pom><parent><groupId>io.github.entropy-cloud</groupId><artifactId>nop-entropy</artifactId><version>2.0.0-SNAPSHOT</version></parent><dependencies><dependency><groupId>io.github.entropy-cloud</groupId><artifactId>nop-spring-web-starter</artifactId></dependency></dependencies>
</pom>

二. 实现BizModel

NopGraphQL中的BizModel类似于SpringMVC中的Controller,只是它的特殊假定更少,是一种数学意义上的最小化定义。

@BizModel("Demo")
public class DemoBizModel {@BizQuerypublic String hello(@Name("message") String message) {return "Hi," + message;}@BizMutationpublic DemoResponse testOk(@RequestBean DemoRequest request) {DemoResponse ret = new DemoResponse();ret.setName(request.getName());ret.setResult("ok");return ret;}
}
  1. 在类上增加@BizModel注解,指定后台的服务对象名
  2. 在服务函数上增加@BizQuery或者@BizMutation注解,分别表示无副作用的查询操作和有副作用的修改操作。@BizMutation会指示NopGraphQL引擎自动打开数据库事务,确保后台服务函数在事务环境中执行。
  3. 通过@Name注解指定服务函数的参数名。如果参数类型是JavaBean,则会自动执行JSON解析将前台参数转换为对应类型

与SpringMVC的Controller对比,NopGraphQL会自动推定很多事情,从而极大降低的系统的不确定性:

  1. 前端的REST链接根据对象名和方法名自动推定,而无需手工指定,固定格式为 /r/{bizObjName}__{bizMethod}
  2. @BizQuery允许通过GET和POST两种HTTP方法调用,而@BizMutation只允许通过POST方法调用
  3. 通过GET方式调用时,可以通过URL链接来传递参数,例如/r/Demo__hello?message=abc。通过POST方式调用时可以通过URL来传参,也可以通过Http的body使用JSON格式传递。
  4. 可以通过@Name来一个个的指定前台参数,也可以通过@RequestBean将前台传递过来的所有参数包装为指定的JavaBean类型
  5. 服务函数总是返回POJO对象,并指定按照JSON格式进行编码

如果参数是可选的,可以使用@io.nop.api.core.annotations.core.Optional注解来标记,否则框架会自动校验参数不能为空。

三. 通用错误处理

NopGraphQL返回到前台的结果对象永远是ApiResponse<T>类型, 但是后台服务函数实现时并不需要像SpringMVC那样手工进行包装。

class ApiResponse<T>{int status;String code;String msg;T data;
}
  • status=0的时候表示执行成功,不为0表示执行失败
  • 失败时通过code来传递错误码,通过msg来传递国际化后的错误消息。
  • 执行成功的时候通过data来返回结果数据,也就是后台服务函数中的返回值。
  • Nop平台的这种标准返回格式与前端AMIS框架所需要的服务返回格式一致。

后端需要把错误信息返回到前台时,直接抛出异常即可

@BizModel("Demo")
public class DemoBizModel {@BizMutationpublic DemoResponse testError(@RequestBean DemoRequest request) {throw new NopException(ERR_DEMO_NOT_FOUND).param(ARG_NAME, request.getName());}
}@Locale("zh-CN")
public interface DemoErrors {String ARG_NAME = "name";ErrorCode ERR_DEMO_NOT_FOUND =define("nop.err.demo.not-found", "指定数据不存在: {name}", ARG_NAME);
}

错误码的定义和使用参见error-code.md

四. 框架中立

SpringMVC这种框架本质上是一个Web框架,很多人在使用时都会不自觉的引入对特定Web运行时的依赖,比如使用HttpServletRequest和HttpServletResponse对象等。

NopGraphQL强调框架的技术中立性,它仅表达业务逻辑,不依赖任何特定的运行时。即使是下载文件功能,也是通过WebContentBean这个POJO对象来返回结果,而不是使用HttpServletResponse中获取到的输出流。

NopGraphQL仅使用了/graphql/r/{operationName}等少数几个Http端点,可以很容易的运行在任何Web运行时环境中,甚至可以自己使用Netty编写一个简单的HttpServer即可,
不需要任何复杂的Web标准支持。目前NopGraphQL与Spring框架集成时底层是使用SpringMVC实现URL路由,而与Quarkus框架集成时是使用JAXRS标准注解。

有些人可能对GraphQL感到陌生,对于将整个前端迁移到GraphQL的调用模式上存在疑虑。NopGraphQL所强调的信息中立表达的概念,为这种问题提供了一个完美的解决方案:
我们通过代码表达的应该是某种技术中立的业务信息,框架可以根据这些技术中立的信息自动推导得到各种技术相关的接口形式。目前,基于NopGraphQL框架实现的业务函数,
可以自动发布为REST服务、GraphQL服务、Grpc服务、消息队列服务、批处理服务等。比如说:

  1. 我们可以通过/r/Demo__hello?message=abc这种REST接口形式调用DemoBizModel类中的hello方法
  2. 也可以通过query{ Demo__hello(message:'abc') } 这种GraphQL请求来访问同一个服务函数
  3. 如果引入了nop-rpc-grpc模块依赖,NopGraphQL引擎启动的时候还会自动生成如下proto服务定义,使得我们可以通过grpc来访问这个服务函数
syntax = "proto3";package graphql.api;message Demo__hello_request{optional string value = 1;
}message Demo__hello_response{optional string value = 1;
}service Demo{rpc hello(Demo__hello_request) returns (Demo__hello_response);
}

五. 查看服务定义

设置了nop.debug=true的时候,Nop平台会以调试模式启动。此时可以访问如下链接来获取所有服务定义:

  1. /p/DevDoc__graphql
  2. /p/DevDoc__beans

基于可逆计算理论设计的低代码平台NopPlatform已开源:

  • gitee: canonical-entropy/nop-entropy
  • github: entropy-cloud/nop-entropy
  • 开发示例:docs/tutorial/tutorial.md
  • 可逆计算原理和Nop平台介绍及答疑_哔哩哔哩_bilibili

http://www.mrgr.cn/news/64259.html

相关文章:

  • uniapp-vue3比对筛选
  • 如何在Linux命令行中使用GhatGPT
  • 在Ubuntu 上实现 JAR 包的自启动
  • Automated Isotope Identification Algorithm UsingArtificial Neural Networks-论文阅读
  • Android 百度面经
  • 【C++】关联式容器
  • untiy mlagents 飞机大战 ai训练
  • Java--正则表达式入门指南
  • ros入门:使用c++打印hello world
  • try…catch…finally语句里return语句的执行顺序是怎样的?
  • 【北京迅为】《STM32MP157开发板嵌入式开发指南》-第七十章 Buildroot制作根文件系统
  • 约瑟夫环问题——4个解法总结(C语言)
  • HTMLCSS:旋转的动态卡片
  • LInux系统编程(二)操作系统和进程
  • 锁策略, cas 和 synchronized 优化过程
  • Python爬虫详解:原理、常用库与实战案例
  • 【刷题13】链表专题
  • 使用WebAssembly优化Web应用性能
  • nodejs入门教程20:nodejs文件系统
  • uniapp-vue3比对筛选
  • 软件测试基础三(前端知识)
  • Elastix-基于ITK的医学图像配准库
  • Java中对象的转移(1)——序列化与反序列化
  • 初探Flink的序列化
  • 手撕快排的三种方法:让面试官对你刮目相看
  • 到底要不要用SAP Screen Personas