当前位置:   article > 正文

全栈低码设计开源框架 json-script-rule 简介_json script rule

json script rule
前言

一个好的设计应该是简约而不简单的,简约是为看着不复杂,使用起来也并不复杂,而不简单是为虽然看上去它很简单但实际上它却不简单,它内里包罗万象海纳百川能够解决许多复杂的场景问题。在我们实际的开发过程中其实经常能够碰见一些问题,而对于这些问题每一个人也都有自己的解决思路,一个好的解决思路它能将一些复杂的问题变得简单化,让我们后续解决其它问题时变得游刃有余,不再需要和产品去争论哪些我们能实现哪些我们实现不了,反之一个不好的解决思路则可能会将一个简单的问题复杂化,诚如此那将会是极其糟糕和愚蠢的,不仅把自己弄得焦头烂额,而且让整个项目都变得更加的难以维护不断的进行重构。

有关设计相关的优秀作品其实有很多,比如spring、json等,它们简约而不简单的设计几乎涵盖了所有应用场景,而在它们这种设计的基础上又集成了基于这些设计的其它应用框架,这些框架之间相互的配合最终完成了各种复杂的业务场景,因此可以说是非常典型的优秀作品。其实有的时候一个好的思路往往是解决问题的关键,可能你趴在代码上狂敲了一晚都不如更换一个解决思路来的更快更好更完美,而这一点往往总是被我们给忽略掉。在互联网蓬勃发展的当下,更多的人所专注的可能是如何解决高并发高性能的问题,这些问题能够考察一个人是否能够解决一些问题,但却考察不出一个人是否能够更好的解决一些问题,因此一个大牛级别的程序员往往更多关注的是如何架构出一套完美的代码体系,不仅能够支撑高并发高性能,而且同时还能在不断的更新迭代中保证系统的稳定、快速开发等问题。

因此说到这里我认为一个优秀的设计思想要远比一个技术更加的重要,更加的能够体现程序员的水平,因为这些优秀的技术无一例外不是引用了一些独特的设计思想才迅速拥有了一大批使用者的,而如何能够让我们的业务程序也能像那些应用框架一样拥有良好的性能、扩展性、可读性和复用性则是我们今天所要探讨的话题。说到设计大家可能印象中立刻就会联想到二十四种设计模式以及java的六大设计原则,其实大差不差,今天所要提到的设计框架主要就是采用了设计模式中的策略模式的思想,通过封装、配置、来达到低码开发、高复用等目的,它主要基于两个思想,一是面向插件开发,二是前后倒置,这听起来和spring似乎很像,但这的的确确就是它的两个概念,它就是json-script-rule,接下来我将详细介绍(注意加粗字体部分)。

介绍

json-script-rule是一款开源的全栈低码设计框架,之所以说它是设计框架,是因为它更倾向于程序的设计和拆分,它更像是一个程序片段的封装者和调用者,通过它我们可以将一些通用的代码逻辑拆分出来并封装成插件(高内聚低耦合)用以提高代码的复用性,之后再将这些插件有序的组合起来相互调用以此来完成一些更为复杂的业务场景的实现,而这整个过程将会在前端实现。这听起来十分的炸裂,后端的业务逻辑要在前端实现?那么它是如何实现的呢?在这之前需要先明确它的两个基本思想。

  • 前后倒置:是指后端的java代码片段由前端的json脚本来进行调用,这看上去像是前端在写后端的代码一样。
  • 面向规则:将一些代码片段高内聚低耦合化,按照其业务或功能封装成一个个单一职责但却拥有复杂功能可通过属性进行动态功能配置的插件,接下来在整个开发过程中利用这些封装好的插件进行开发,进而达到程序的可复用性。

明确了这些概念之后我们该如何理解这个东西呢,其实它并没有多复杂的技术,如果非要比喻的话,它就像是将代码拆卸成一个个单一业务职责的带有业务逻辑的controller接口,前端调用这些controller接口来完成页面上的一些复杂的业务需求

那么它与我们传统的controller又有什么区别呢?

  1. 设计不同,controller设计之初是用来控制跳转逻辑的,它不应该含有业务代码,而且基于这种设计在某些应用场景下可能无法使用,比如说rpc调用,它调用的是interface中的方法而非controller接口,但是json-script-rule封装的插件不仅可以与前端交互也可以与后端交互。
  2. controller和controller之间是不存在事务的,而插件之间是在同一个事务下执行的。
  3. controller的映射地址会随着接口的增加而不断的增加,而json-script-rule是固定不变的,它将更多的精力集中在业务场景和插件的使用上。
  4. controller无法很好的集成在其它的项目中,而json-script-rule可以很好的发布,供给其它项目去复用,如json-script-rule框架内置的crud插件可以实现crud的低代码开发,正是基于此优势
  5. 前端调用多个controller可能会产生多个请求,而json-script-rule只需要一次请求即可,减少了网络开销
  6. controller是一个方法,而json-script-rule插件是一个实现了IJSRuleActionModel接口的类,基于类的开发比基于方法的开发具有更多的选择性,如继承等
  7. controller的参数在形参中,而json-script-rule参数在其类的字段中,有更高的扩展性,如在这些字段上自定义一些注解等
  8. controller返回的是封装给前端的响应结果,而json-script-rule插件返回的是代码的执行结果,最终也会封装成响应结果返回前端
  9. json-script-rule是一个调用者,它可以通过一定的判断逻辑统筹调用多个代码片段,而controller不是,它只是一个前后端交互的接口,如果需要业务判断,那它只能借助于前端的代码来进行判断并决定后续调用其它哪些controller,这对于前端的职责来说是不友好的同时也是不合理的

json-script-rule顾名思义它是由json脚本所组成的一些通用业务规则,它意在解决一些简单的、通用的业务场景的封装和调用,从而达到一种可通过自由配置的方式来动态实现后端功能的动态接口

接下来将以框架内置的低代码插件为入手点对它进行详细的拆解,目前框架内置插件包括增、删、改、查、上传、导入、导出、主子表插入,分流器,我们可以在任意地方调用这些插件来实现一些简单的功能,无需后端代码,无需后端部署,只需要在前端写一行简单的json脚本即可实现一个功能接口的开发。此外它还支持自定义插件的开发,你可以将一些简单的、通用的业务逻辑封装成一个自定义的插件集成到框架插件库中,最后再通过调用这些封装好的插件来快速实现一个业务场景并发布,而整个过程对于所有的调用者来说是0码的。

那么这些个低代码插件它与我们平常的开发到底有什么不同?它又有哪些优势?它又能解决开发者的哪些痛点呢?
接下来将会用几篇文章详细概述这个框架的使用,首先我们先简单直观的对比一下传统开发与低码开发的差异,说到差异这里就不得不先说一下传统方案的一些弊病,先以mybatis和jpa为例:

  1. 生成的文件过多,如果按照规范开发,每当增加一个功能或者一个表的时候,通常都会增加一个controller、一个service、一个impl、一个mapper、一个xml、一个po,dto,vo甚至do等,造成打包后的项目变得不再"轻量"
  2. 查询数据库的代码中嵌入了过多的eq,And,Or,isNull等耦合性和可读性均较差的代码,且不同的人用的框架不一样,所写的逻辑也不一样,没有一个统一的标准,让人不得不去一行一行的读代码来理解前任开发者的逻辑
  3. 每当项目出了bug,或是业务上的更改,都需要修改后端代码才能解决问题,并且需要重新打包部署才能生效,这样不仅增加了工作量,也拉长了开发周期,更容易出现反复测试反复重现bug的现象
  4. 开发人员的水平良莠不齐,尤其是在做项目时很少有人会考虑程序的设计、封装、复用等特性,一旦出现各写各的代码,随着人员的流动公司原有的产品将会变得十分难以维护,不得不进行重构
  5. 有些通用的功能缺乏统一的标准,如发送短信,上传图片等,虽然有第三方的api支持,但是每个公司对这些api的后台处理逻辑却是不相同的,缺少一个功能强大的统一插件,这样就不需要重复开发了。
  6. 如果你的项目里一旦确定使用了某一种框架,如mybatis或是jpa等,那么日后想要更换几乎是不可能的,因为这样的改动很有可能会带来巨大的工作量
  7. 一旦类和服务写的过多,当你修改一个功能时你会发现你需要一层一层的去逐源,此外当你展开一个文件夹时映入眼帘的将会是大量的文件,看了便让人觉得眼花缭乱,不仅来回切换十分的麻烦,而且极容易改错
  8. 如果后端代码的改动涉及到了前端,又或是前端想调整json结构,如返回字段的名称有改变,返回字段的个数有改变,返回数据的主子表结构或顺序有改变等等,这些全都需要后端配合才能完成,这不仅增加了沟通的成本还极大的降低了开发的效率,需要依赖后端开发人员不说而且还非常的麻烦,时时刻刻都要考虑改动所带来的成本,因此在敏捷开发中绝对是个硬伤
  9. 调试错误十分耗费时间,通常开发一个接口可能需要借助各种工具或框架,一旦出现错误,很难在短时间内排查出问题并加以解决

说完了几个传统开发的痛点,那么接下来看看json-script-rule它内置的插件是如何开发一个功能的。
在进行开发之前首先需要引入依赖和po类的配置,这些将在稍后会进行具体的说明。此外,如果你希望降低学习成本,不使用原生的方式,那么你还需要在前端还需要引入json-script-rule.js这个文件(用于简化构建json),接下来从项目上截取一部分vue开发的例子做一个demo:

  1. export function requestRule(body) {
  2. return request({
  3. url: "/json/script/start",
  4. method: 'post',
  5. data: body
  6. })
  7. }

上面的代码是前端自己封装的方法,用于处理所有调用json-script-rule的请求(如设置token什么的),如果没有更改框架内置控制器路径的话,那么这个url是系统默认的/json/script/start,是固定不变的(如果配置了context-path则需在前面加上),接下来在前端只需要一行代码便可以实现一个插入的功能,如下:

  1. import { jsr_build_body } from "@/xx/xxxx/json-script-rule";
  2. add() {
  3. let body = jsr_build_body([{ name: 'asddsa', plugin: 'add', class: 'ClassName', datas: this.form }]);
  4. requestRule(body ).then(response => {
  5. if (response.code == 200) {
  6. this.msgSuccess("新增成功");
  7. this.open = false;
  8. this.getList();
  9. }
  10. });
  11. }

说明:上面的代码只是列举了一个简单的例子,相信稍微有些基础的朋友一眼就能看得懂,这里实现功能的一行代码就是构建body的jsr_build_body这个方法,它是json-script-rule.js中封装的方法,用于简单构建json脚本的,这一行的代码里有几个关键属性,如下:

  • name:是随便起的名字,用于标识返回结果的名字
  • plugin:表示调用的是框架内置的add插件
  • class:对应的是po实体类名(实体类会映射表名)
  • datas:要插入的数据对象数组

总结:至此,一个后台的插入功能便做好了,整个过程我们只在前端配置了4个参数,可以说开发效率是非常的快,不仅如此,当你后端更改了表字段,或者更改了查询条件等都可以通过调整参数的形式来完成且避免了重新打包部署发布的繁琐过程。此外对于前端开发者来说,如果你会使用这个插件,那么只要是框架内置的这些插件支持的功能,则都可以通过这种方式来实现全栈开发,即便是内置插件不满足的功能,你也可以通过框架提供的自定义插件开发来实现这种低代码配置化开发。而对于后端开发者而言整个过程后端是不需要写任何代码的(只更改对应的po类对象),即便哪一天业务变更了,只要是在插件功能范围内的,那么也不需要更改任何后端的代码,只需要调整前端json的请求参数就可以了,十分的便捷。

目前crud插件支持 mysql,postgresql,kingbase,oracle 数据库,绝大部分的查询场景均支持,这里包括字段,函数,分组,排序、关联,条件,左右内外连查询,子查询和视图查询等等。

优劣对比

所有的软件框架都存在它的优势和它的劣势,那么这里也列举出一些它的优点和缺点以供开发者自行选择考虑

优点
  1. 前后端通用的设计,无论是后端还是前端都可以使用
  2. 面向规则开发,强化代码设计,有效规避bug,提升代码复用性,节约开发时间成本
  3. 后端不需要打包及重新部署,即改即出结果
  4. 轻量级容器,整个jar包大概200kb左右
  5. 支持扩展,自定义开发,整个框架的设计几乎可以满足大部分定制化开发需要
  6. 采用分离式设计,不耦合于主项目的bean配置,如mybatis配置sqlSessionFactory,pagehelper配置分页等,插件中的配置属性与主项目的完全分离,互不干扰,无论是在pom中直接引用starter或是单独的包,或是代码中实现的配置属性,均不产生耦合
  7. 日志体系健全,对于所发生的错误能够通过日志信息快速定位问题
  8. 代码侵入性极低,即使后续不使用也不会对原有的项目产生任何耦合
  9. 兼容多个数据库,采用单独处理的方式处理各种数据库之间的差异
  10. 提供自定义开发所需要用到的注解,工具,配置,接口,以及缓存等
  11. 支持加密处理,目前仅支持国密sm2非对称性加密(集成hutool包处理)
  12. 安全接口,有效杜绝sql的注入
  13. 一次请求可返回多个结果,因此不需要加载一个页面时请求后台的多个接口
  14. 框架本身独立于项目,是个基于spring容器的小型容器,因此项目即便更换框架后,那些原有的已经用该框架开发过的接口也不会受到任何的影响
  15. 安装上手十分简单接地气,后端只需要简单的两步就可以进行json开发了,执行效率非常高
  16. 插件可以极大程度的在不同的环境下进行复用,迁移都十分的方便
  17. 不仅有效降低了项目大小,而且还减少了书写开发文档的时间
  18. 开源的微框架,国人项目,且一直在维护,后续可能还会发布一些更为全面的功能以及插件,可以极大的减少开发的工作量
  19. 结合良好的横向设计,再进行纵向的封装,便能够纵横捭阖,一动皆动
  20. 开发手感非常高,易读、易用、易扩展
  21. 支持rpc调用(since 4.0 version)
缺点
  1. 仅支持post请求
  2. 仅支持单数据源,多数据源下只能选择一个数据源
  3. 不支持webflux
  4. 采用空间换时间,会占用少部分内存空间
  5. 由于部分插件功能全面,因此相对于常规接口来说其安全性略显不足(4.0版本之后框架引入内置权限系统可以弱化这一部分的缺点)
  6. 如果是自定义插件开发,那么高度依赖开发者的设计能力
插件主要依赖说明

jdk1.8
spring boot dependencies
lombok

安装说明
  1. 引入依赖,仅此一步即可

  1. <dependency>
  2. <groupId>io.github.ying1dudu</groupId>
  3. <artifactId>json-script-rule-spring-boot-starter</artifactId>
  4. <version>4.0</version>
  5. </dependency>

提示:如果maven无法下载或想体验抢先版本的则可以直接到插件地址下载jar包并放入本地maven库里,这里面还包括了json-script-rule.js等前端、postman脚本、导入导出模板样例等等
插件地址:https://gitee.com/ying1dudu/json-script-rule-jar.git

  1. 如果你不使用框架内置的crud功能(包括引用crud插件的导入导出和主子表),那么此步可以跳过,application(yml和properties等文件类型都可以)中配置po实体类(映射数据库表或视图的java简单对象)的包路径,属性为locations(3.2.4版本以后支持多路径扫描,多个用逗号分割),如下

  1. edi:
  2. rule:
  3. locations: xx.xx,yy.yy,zz.zz

注意1:locations可以指向一个或多个目录,它用于识别po实体类存放的位置(它可以指向你旧有的mybatis的目录),框架中所说的直接类名是指以这些目录为basePackges的包名+类名,自3.2.4版本以后,JSRuleTable注解不是必须的注解,如果不加该注解则跳过该po实体类(不做缓存则不能进行crud操作)**,JSRuleField注解也是非必须的,如果你的变量名刚好和表字段名一致,那么就不需要配置该注解

注意2:尽量避免多个根目录下含有相同的包名+类名(直接类名),如果无法避免直接类名名称冲突,则需要写上类的全限定名(只有冲突时才会用到全限定类名),如配置外键注解fk属性时,且在使用json时前缀也要换成类的全限定名而不能用locations根目录下的直接类名,如果直接类名没有冲突,则json正常使用直接类名即可(默认禁用全限定类名)

提示1:多模块应用下开发一样可以通过locations指向子模块po实体类路径(只要这些路径被加载到classpath中且可以通过getResource获取到即可),locations通常在启动模块的application配置文件中配置即可,此外还可以通过继承JSRuleExtendDefault类或实现IJSRuleMappingsInfo这个接口来自定义数据库或xml等文件中存储的信息,将其对象化后可加载到系统缓存中,通过代码手动一样可以实现类似locations的配置(详情参考自定义开发)

提示2:locations所指向的目录全部都是根目录,这些根目录下还可以有子目录(这些目录下的包名+类名尽量避免名称冲突),在使用json进行请求时,classes属性中的类名应该以根目录为basePackges,如果根目录下还有子目录(包)则类名前面应加上这个包名,此为直接类名,如下:包名.ZsTestPO便是直接类名

  1. {
  2. ......
  3. "relation":{
  4. "classes":["包名.ZsTestPO","xx.ZsTestSon2"]
  5. }
  6. }

提示3:如果在当前配置文件中配置了spring.profiles.active属性并指向了其它配置文件,则子配置文件将会覆盖当前属性
至此,通过上面的两个步骤,整个框架便安装完成了,这其实和大多数集成在springboot的第三方框架一样

使用说明

由于插件的功能比较多,此处只简单说明查询插件的最基本的用法,后面将会推出更为详细的文档说明。
注:实例中为了配合说明,故意加了很多不规范的命名,如多加了两个空格,如有下划线,且此外还加了很多重复的字段等

  1. 配置po类,示例如下

  1. @JSRuleTable(name= "zs_test")
  2. @Data
  3. public class ZsTestPO {
  4. @JSRuleField(pk=true)
  5. private String id;
  6. private String name;
  7. @JSRuleField(name= " create_date ")
  8. private Date create_date;
  9. @JSRuleField(name= "birth_day")
  10. private Date birthDay;
  11. private double salary;
  12. private String remark;
  13. private Double bonus;
  14. @JSRuleField(name= "test_field",alias="sum_test_field")
  15. private String test_field;
  16. @JSRuleField(name= "sum1_salary",alias="lbv_salary")
  17. private String sumSalary;
  18. @JSRuleField(name= "qian",imports= {"qian"})
  19. private String qian;
  20. }

看第二个

  1. @JSRuleTable(name="zs_test_son2")
  2. public class ZsTestSon2 {
  3. @JSRuleField(pk=true)
  4. public String id;
  5. @JSRuleField(name= "zs_test_id",fk="ZsTestPO",dependent= "ZsTestPO.id")
  6. public String zs_test_id;
  7. @JSRuleField(name= "zs_test_id",fk="view.neibu.ZsTestPOView",dependent= "view.neibu.ZsTestPOView.id")
  8. public String zs_test_id2;
  9. @JSRuleField(name= "zs_test_id",fk="ZsTestPOCopy")
  10. public String zs_test_id3;
  11. @JSRuleField(name= "zs_test_son1_id",fk="test.business.po.ZsTestUpdate")
  12. public String zs_test_son_id;
  13. @JSRuleField(name="zs_test_son1_id",fk= "view.ZsTestView")
  14. public String zs_test_son1_id2;
  15. @JSRuleField(name= "oh_yes")
  16. public String ohYes;
  17. public String test_field_a;
  18. @JSRuleField(dependent= "ZsTestPO.name")
  19. public String name;
  20. }

说明:所有的json所面向的操作均是后端的class类(无论是Po实体映射类还是model参数类)对象而非数据库表,因此尽管表里有10个字段,但在po类里你配置了8个字段,那么你就只能用这8个字段,如果多配置了一些不是表里的字段,那么需要用JSRuleField注解中的ignore属性设置为true对其忽略处理,否则使用的时候会报错

由于部分插件功能比较强大,因此从4.0版本开始要求开发者考虑插件权限的控制,这里为了演示方便直接重写插件方法并返回true,如下(详情可参考自定义开发篇以及权限篇的说明)

  1. @Data
  2. @EqualsAndHashCode(callSuper=false)
  3. @Component
  4. public class JSRuleGetCustomModel extends JSRuleGet<MyActions>{
  5. @Override
  6. public boolean isOwner(Map<String,Object> params,Set<String> roles) {
  7. return true;
  8. }
  9. }

上面是直接重写了查询模型JSRuleGet的isOwner方法,返回true表示可以对该插件进行使用,默认不写的话则是false
接下来需要自定义一个Action仓库,用于装载上面的插件,这里取名为MyActions,代码如下

  1. @Data
  2. @EqualsAndHashCode(callSuper=true)
  3. @Component
  4. public class MyActions extends JSRuleAction<MyActions>{
  5. public JSRuleGetCustomModel get;
  6. }

这里需要重写父类字段的get,用来替换框架内置的get插件,除非你要自己写一个查询的插件,否则一定要重写get字段

参数说明
  • pk:设置主键(目前仅支持单主键,不支持复合主键,也不提议使用复合主键)
  • fk:设置外键,这里的值对应的是直接类名,直接类名就是在 locations 属性所配置的多个basePackges根路径下的位置开始,在这个目录下如果有包名则加上包名,例如xx.ZsTestPO便是直接类名,此外,直接写成全类名也是可以的
  • name:表示对应数据库的表字段名,如果没有配置则默认认为java字段名即为数据库表字段名
  • alias:表示数据库表字段的别名,如果设置了则会以别名的形式返回给前端
  • imports:设置导入时,模板文件头部行对应的某表列的字段名,后续将会在导入规则中详细说明
  • exports:设置导出时,如果没有设置模板,将会使用此属性进行默认导出列的头
  • dependent:设置主子表的依赖关系,使用主子表时子表的某个字段值将从主表中获得,如主外键关联
  1. 启动开发者自己的本地项目,并用postman进行测试http://localhost:端口号/配置的context-path路径/json/script/start

  1. 11:05:26.901 [main] INFO e.r.w.s.JSRuleStart - [printInfomation,38] - action=edi.rule.model.JSRuleAction
  2. 11:05:26.901 [main] INFO e.r.w.s.JSRuleStart - [printInfomation,39] - mapper=edi.rule.frame.mybatis.dao.MapperForMysql
  3. 11:05:26.901 [main] INFO e.r.w.s.JSRuleStart - [printInfomation,40] - dbFields=edi.rule.extend.adapter.JSRuleMysqlSysFields
  4. 11:05:26.901 [main] INFO e.r.w.s.JSRuleStart - [printInfomation,41] - dbFunctions=edi.rule.extend.adapter.JSRuleMysqlFunctions
  5. 11:05:26.901 [main] INFO e.r.w.s.JSRuleStart - [printInfomation,42] - handler=edi.rule.work.processor.JSRuleInitByJson
  6. 11:05:26.901 [main] INFO e.r.w.s.JSRuleStart - [printInfomation,43] - locations=edi.business.po
  7. 11:05:26.901 [main] INFO e.r.w.s.JSRuleStart - [printInfomation,44] - rootPath=D:\workspace\json-script-rule\rule
  1. 通过postman请求接口,json如下

  1. {
  2. "actions": [
  3. {
  4. "name": "test_get",
  5. "get": {
  6. "relation": {
  7. "classes":["ZsTestPO"]
  8. },
  9. "groupShow":true,
  10. "fields":["name","salary","currentDate"],
  11. "condition":{
  12. "where":{
  13. "eq":{"ZsTestPO.name":["ccc"]}
  14. }
  15. }
  16. }
  17. }
  18. ]
  19. }
参数说明:
  • classes:表示关联的类的相关信息,也就是相关联的表的信息,这里的ZsTestPO是类名而不是表名
  • name:action作为结果返回的唯一标识
  • get:表示此次操作为查询动作
  • where:是matches属性的别名,表示具体的查询条件,这里表示查询ZsTestPO实体类对应的表的id字段等于"5260c8c5-47f2-4890-aff3-6b4fd5fb62f0"的数据(注意这里的属性是一个数组,用于某些条件为某一个值或(or)为null的情况)
  • fields:表示所要查询并返回的字段
  • groupShow:表示将两个表的数据分开显示(因此这里实际上datas中只有2条数据返回)
    返回结果如下

  1. {
  2. "code": 200,
  3. "msg": "operation successfully(操作成功)",
  4. "result": {
  5. "test_get": {
  6. "pageNum": 1,
  7. "pageSize": 10,
  8. "dataSize": 1,
  9. "totalPage": 1,
  10. "totalCount": 1,
  11. "data": [
  12. {
  13. "current_date": "2023-11-15 00:00:00",
  14. "ZsTestPO": {
  15. "name": "ccc",
  16. "salary": 2200.00
  17. }
  18. }
  19. ]
  20. }
  21. },
  22. "log": null
  23. }

所解析的sql为

select name as "name" ,salary as "salary" ,current_date as "current_date"  from  zs_test  where zs_test.name='ccc'

至此,后端的json-script-rule便安装测试完成了,接下来的几篇将着重介绍如何使用框架内置封装的插件

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/花生_TL007/article/detail/422609
推荐阅读
相关标签
  

闽ICP备14008679号