json-script-rule是一款开源的全栈低码设计框架,之所以说是设计框架,是因为它更倾向于程序的设计,将传统的低码概念(将程序员由面向代码转向面向业务)升级到由面向业务转向面向程序设计,通过在后台组装横向的代码逻辑将其封装成一个个功能插件进而再通过页面直接输入指令达到一种可配置的动态代码的低代码功能架构。
为了更好的能够理解其中的含义,我们先来举一个简单的例子进行说明,假设你写了一个Service A,如果你的代码考虑的很全,设计的很好,那么你可以通过参数可以随时调整这个接口的功能,但如果你考虑的不是很全面,那有可能某一天因为一个新功能,你可能要去修改这个Service A。除此之外,假设这个Service A某一天你将它做的非常完美了,那么你又如何将它发布给其它人去用呢?这个时候你可能会去想假如当初有人给我提供了这个Service A我是否不用花精力和心思再去写一个新的了?而我写的插件似乎又没法分享给其它人,甚至自己的项目中也无法做到很好的迁移,造成了同样的功能不仅要写大量的代码,而且复用性还很差,不仅如此在使用过程中还需要去看对方的代码,真的是辣眼睛0 0
说了这么多其实我们可以再转换一个思路去思考一个问题,假如有一天你只需要在前端或postman中输入一行指令,就能让你得到你想要的结果,比如去查询一个表的数据,那么你只需要输入get tableA,比如将某张表的数据用excel导出来,那么你只需要输入export tableA,这样看起来是不是会很舒服?我想答案是肯定的,当然了,实际上的功能不可能只有这么简单,它可能会让你导出到某个路径下,那么我们也可以更改一下指令export tableA to path D:/xxxx。总而言之,我们希望像yum或Homebrew那样,只需要通过命令来解决代码的问题,那么我们就需要将插件设计好,这个时候我们的json-script-rule便有了用武之地了。
json-script-rule顾名思义它是由json脚本所组成的前后端通用的规则引擎架构,它意在解决一些简单的、通用的业务场景的逻辑封装,从而达到一种可通过配置的方式来实现后端功能的效果。目前框架包含增、删、改、查、上传、导入、导出、主子表插入,分流器等9个内置插件,我们可以在任意地方调用这些插件来实现一些简单的功能,无需后端代码,无需后端部署,只需要在前端写一行简单的json脚本即可实现一个功能接口的开发。此外它还支持自定义插件的开发,你可以将一些简单的、通用的业务逻辑封装成一个自定义的插件集成到框架插件库中,最后再通过调用这些封装好的插件来实现快速0码开发。
那么这个东西它与我们平常的开发到底有什么不同?它有哪些优势?它又能解决开发者的哪些痛点呢?
接下来将会用几篇文章详细概述这个框架的使用,首先我们先简单直观的对比一下传统开发与低码开发的差异,说到差异这里就不得不先说一下传统方案的一些弊病,先以mybatis和jpa为例:
说完了几个传统开发的痛点,那么接下来看看json-script-rule它是如何开发一个功能的。
在进行开发之前首先需要引入依赖和po类的配置,这些将在稍后会进行具体的说明。此外,如果你希望降低学习成本,不使用原生的方式,那么你还需要在前端还需要引入json-script-rule.js这个文件(用于简化构建json),接下来从项目上截取一部分vue开发的例子做一个demo:
export function requestRule(body) {
return request({
url: "/json/script/start",
method: 'post',
data: body
})
}
上面的代码是前端自己封装的方法,用于处理所有调用json-script-rule的请求(如设置token什么的),如果没有更改框架内置控制器的路径的话,那么这个url是系统默认的/json/script/start,是固定不变的(如果配置了context-path则需在前面加上),接下来在前端只需要一行代码便可以实现一个插入的功能,如下:
import { jsr_build_body } from "@/xx/xxxx/json-script-rule";
add() {
let body = jsr_build_body([{ name: 'asddsa', plugin: 'add', class: 'ClassName', datas: this.form }]);
requestRule(body ).then(response => {
if (response.code == 200) {
this.msgSuccess("新增成功");
this.open = false;
this.getList();
}
});
}
说明:上面的代码只是列举了一个简单的例子,相信稍微有些基础的朋友一眼就能看得懂,这里实现功能的一行代码就是构建body的jsr_build_body这个方法,它是json-script-rule.js中封装的方法,用于简单构建json脚本的,这一行的代码里有几个关键属性,如下:
总结:至此,一个后台的插入功能便做好了,整个过程我们只在前端配置了4个参数,可以说开发效率是非常的快,而且对于前端开发者来说,如果你会使用这个插件,那么只要是框架内置的这些插件支持的功能,则都可以通过这种方式来实现全栈的开发,即便是内置插件不满足的功能,你也可以通过框架提供的自定义插件开发来实现这种低代码配置化开发。而对于后端开发者而言整个过程后端是不需要写任何代码的,即便哪一天业务变更了,也不需要更改后端的代码,只需要调整前端json的参数就可以了,比如说由原来的插入A表变成插入B表,比如说插入A表后再插入C表D表等,都可以通过调整json参数来实现,只需要修改class的属性以及增加action的个数即可,而且修改完成后也不需要后端打包部署,十分的便捷。
json-script-rule是一个依赖于spring容器的全栈低码开发框架,它的设计主要依赖于两个重要的概念,一是前后倒置,二是面向规则(配置)。
目前crud插件支持 mysql,postgresql,kingbase,oracle(6,8,10) 数据库,绝大部分的查询场景均支持,这里包括字段,函数,分组,排序、关联,条件,左右内外连查询,子查询和视图查询等等。
jdk1.8
spring boot dependencies
lombok
错误信息:Unsupported class file major version 61.
解决:spring boot以及mybatis框架等恢复支持jdk1.8的版本,如spring的2.7.10,mybatis2.3.1以下的版本
io.github.ying1dudu
json-script-rule-spring-boot-starter
3.2.7
提示:如果maven无法下载或想体验抢先版本的则可以直接到插件地址下载jar包并放入本地maven库里,这里面还包括了json-script-rule.js等前端、postman脚本等
插件地址:https://gitee.com/ying1dudu/json-script-rule-jar.git
edi:
rule:
locations: xx.xx,yy.yy,zz.zz
注意1:locations可以指向一个或多个目录,它用于识别po实体类存放的位置(它可以指向你旧有的mybatis的目录),框架中所说的直接类名是指以这些目录为basePackges的包名+类名,自3.2.4版本以后,JSRuleTable注解不是必须的注解,如果不加该注解则跳过该po实体类(不做缓存则不能进行crud操作)**,JSRuleField注解也是非必须的,如果你的变量名刚好和表字段名一致,那么就不需要配置该注解
注意2:尽量避免多个根目录下含有相同的包名+类名,如果无法避免名称冲突,则需要写上类的全名(Class.getName(),只有冲突时才会用到全名),如配置外键注解fk属性时,且在使用json时前缀也要换成类的全名而不能用locations根目录下的直接类名,如果没有名称冲突,则json正常使用直接类名即可(默认禁用全名)
提示1:多模块应用下开发一样可以通过locations指向子模块po实体类路径(只要这些路径可以通过getResource获取到即可),locations通常在启动模块的application配置文件中配置即可,此外还可以通过继承JSRuleExtendDefault类或实现IJSRuleMappingsInfo这个接口来自定义数据库或xml等文件中存储的信息,将其对象化后可加载到系统缓存中,通过代码手动一样可以实现类似locations的配置(详情参考自定义开发)
提示2:locations所指向的目录全部都是根目录,这些根目录下还可以有子目录(这些目录下的包名+类名尽量避免名称冲突),在使用json进行请求时,classes属性中的类名应该以根目录为basePackges,如果根目录下还有子目录(包)则类名前面应加上这个包名,此为直接类名,如下:包名.ZsTestPO便是直接类名
{
......
"relation":{
"classes":["包名.ZsTestPO","xx.ZsTestSon2"]
}
}
提示3:如果在当前配置文件中配置了spring.profiles.active属性并指向了其它配置文件,则子配置文件将会覆盖当前属性
至此,通过上面的两个步骤,整个框架便安装完成了,这其实和大多数集成在springboot的第三方框架一样
由于插件的功能比较多,此处只简单说明查询插件的最基本的用法,后面将会推出更为详细的文档说明。
注:实例中为了配合说明,故意加了很多不规范的命名,如多加了两个空格,如有下划线等,此外还加了很多重复的字段等
@JSRuleTable(name= "zs_test")
@Data
public class ZsTestPO {
@JSRuleField(pk=true)
private String id;
private String name;
@JSRuleField(name= " create_date ")
private Date create_date;
@JSRuleField(name= "birth_day")
private Date birthDay;
private double salary;
private String remark;
private Double bonus;
@JSRuleField(name= "test_field",alias="sum_test_field")
private String test_field;
@JSRuleField(name= "sum1_salary",alias="lbv_salary")
private String sumSalary;
@JSRuleField(name= "qian",imports= {"qian"})
private String qian;
}
@JSRuleTable(name="zs_test_son2")
public class ZsTestSon2 {
@JSRuleField(pk=true)
public String id;
@JSRuleField(name= "zs_test_id",fk="ZsTestPO",dependent= "ZsTestPO.id")
public String zs_test_id;
@JSRuleField(name= "zs_test_id",fk="view.neibu.ZsTestPOView",dependent= "view.neibu.ZsTestPOView.id")
public String zs_test_id2;
@JSRuleField(name= "zs_test_id",fk="ZsTestPOCopy")
public String zs_test_id3;
@JSRuleField(name= "zs_test_son1_id",fk="ZsTestUpdate")
public String zs_test_son_id;
@JSRuleField(name="zs_test_son1_id",fk= "view.ZsTestView")
public String zs_test_son1_id2;
@JSRuleField(name= "oh_yes")
public String ohYes;
public String test_field_a;
@JSRuleField(dependent= "ZsTestPO.name")
public String name;
}
说明:所有的json所面向的操作均是后端的class类(无论是Po实体映射类还是model参数类)对象而非数据库表,因此尽管表里有10个字段,但在po类里你配置了8个字段,那么你就只能用这8个字段,如果多配置了一些不是表里的字段,那么需要用JSRuleField注解中的ignore属性设置为true对其忽略处理,否则使用的时候会报错
http://localhost:端口号/配置的context-path路径/json/script/start
11:05:26.901 [main] INFO e.r.w.s.JSRuleStart - [printInfomation,38] - action=edi.rule.model.JSRuleAction
11:05:26.901 [main] INFO e.r.w.s.JSRuleStart - [printInfomation,39] - mapper=edi.rule.frame.mybatis.dao.MapperForMysql
11:05:26.901 [main] INFO e.r.w.s.JSRuleStart - [printInfomation,40] - dbFields=edi.rule.extend.adapter.JSRuleMysqlSysFields
11:05:26.901 [main] INFO e.r.w.s.JSRuleStart - [printInfomation,41] - dbFunctions=edi.rule.extend.adapter.JSRuleMysqlFunctions
11:05:26.901 [main] INFO e.r.w.s.JSRuleStart - [printInfomation,42] - handler=edi.rule.work.processor.JSRuleInitByJson
11:05:26.901 [main] INFO e.r.w.s.JSRuleStart - [printInfomation,43] - locations=edi.business.po
11:05:26.901 [main] INFO e.r.w.s.JSRuleStart - [printInfomation,44] - rootPath=D:\workspace\json-script-rule\rule
{
"rule": {
"actions": [
{
"name": "test-get",
"get": {
"relation":{
"classes":["ZsTestPO","ZsTestSon2"]
},
"isGroupShow":true,
"fields":["ZsTestSon2.id","salary"],
"condition":{
"where":{
"equal":{"ZsTestPO.id":["5260c8c5-47f2-4890-aff3-6b4fd5fb62f0"]}
}
}
}
}
]
}
}
{
"code": 200,
"msg": "操作成功",
"result": {
"test-get:": {
"pageNum": 1,
"pageSize": 10,
"totalPage": 1,
"totalCount": 2,
"datas": [
{
"ZsTestSon2": {
"id": "2d20b69a-6980-4354-8723-8fe922414926"
},
"ZsTestPO": {
"salary": 2200
}
},
{
"ZsTestSon2": {
"id": "dba7c159-4442-49dc-a5da-bf5ba28a0d17"
},
"ZsTestPO": {
"salary": 2200
}
}
]
}
},
"log": null
}
所解析的sql为
select zs_test_son2.id as "ZsTestSon2-id" ,salary as "salary" from zs_test_son2 , zs_test where zs_test.id=zs_test_son2.zs_test_id and zs_test.id='5260c8c5-47f2-4890-aff3-6b4fd5fb62f0'
至此,后端的json-script-rule便安装测试完成了,接下来的几篇将介绍如何使用