赞
踩
一个好的设计应该是简约而不简单的,简约是为看着不复杂,使用起来也并不复杂,而不简单是为虽然看上去它很简单但实际上它却不简单,它内里包罗万象海纳百川能够解决许多复杂的场景问题。在我们实际的开发过程中其实经常能够碰见一些问题,而对于这些问题每一个人也都有自己的解决思路,一个好的解决思路它能将一些复杂的问题变得简单化,让我们后续解决其它问题时变得游刃有余,不再需要和产品去争论哪些我们能实现哪些我们实现不了,反之一个不好的解决思路则可能会将一个简单的问题复杂化,诚如此那将会是极其糟糕和愚蠢的,不仅把自己弄得焦头烂额,而且让整个项目都变得更加的难以维护不断的进行重构。
有关设计相关的优秀作品其实有很多,比如spring、json等,它们简约而不简单的设计几乎涵盖了所有应用场景,而在它们这种设计的基础上又集成了基于这些设计的其它应用框架,这些框架之间相互的配合最终完成了各种复杂的业务场景,因此可以说是非常典型的优秀作品。其实有的时候一个好的思路往往是解决问题的关键,可能你趴在代码上狂敲了一晚都不如更换一个解决思路来的更快更好更完美,而这一点往往总是被我们给忽略掉。在互联网蓬勃发展的当下,更多的人所专注的可能是如何解决高并发高性能的问题,这些问题能够考察一个人是否能够解决一些问题,但却考察不出一个人是否能够更好的解决一些问题,因此一个大牛级别的程序员往往更多关注的是如何架构出一套完美的代码体系,不仅能够支撑高并发高性能,而且同时还能在不断的更新迭代中保证系统的稳定、快速开发等问题。
因此说到这里我认为一个优秀的设计思想要远比一个技术更加的重要,更加的能够体现程序员的水平,因为这些优秀的技术无一例外不是引用了一些独特的设计思想才迅速拥有了一大批使用者的,而如何能够让我们的业务程序也能像那些应用框架一样拥有良好的性能、扩展性、可读性和复用性则是我们今天所要探讨的话题。说到设计大家可能印象中立刻就会联想到二十四种设计模式以及java的六大设计原则,其实大差不差,今天所要提到的设计框架主要就是采用了设计模式中的策略模式的思想,通过封装、配置、来达到低码开发、高复用等目的,它主要基于两个思想,一是面向插件开发,二是前后倒置,这听起来和spring似乎很像,但这的的确确就是它的两个概念,它就是json-script-rule,接下来我将详细介绍(注意加粗字体部分)。
json-script-rule是一款开源的全栈低码设计框架,之所以说它是设计框架,是因为它更倾向于程序的设计和拆分,它更像是一个程序片段的封装者和调用者,通过它我们可以将一些通用的代码逻辑拆分出来并封装成插件(高内聚低耦合)用以提高代码的复用性,之后再将这些插件有序的组合起来相互调用以此来完成一些更为复杂的业务场景的实现,而这整个过程将会在前端实现。这听起来十分的炸裂,后端的业务逻辑要在前端实现?那么它是如何实现的呢?在这之前需要先明确它的两个基本思想。
明确了这些概念之后我们该如何理解这个东西呢,其实它并没有多复杂的技术,如果非要比喻的话,它就像是将代码拆卸成一个个单一业务职责的带有业务逻辑的controller接口,前端调用这些controller接口来完成页面上的一些复杂的业务需求。
那么它与我们传统的controller又有什么区别呢?
json-script-rule顾名思义它是由json脚本所组成的一些通用业务规则,它意在解决一些简单的、通用的业务场景的封装和调用,从而达到一种可通过自由配置的方式来动态实现后端功能的动态接口。
接下来将以框架内置的低代码插件为入手点对它进行详细的拆解,目前框架内置插件包括增、删、改、查、上传、导入、导出、主子表插入,分流器,我们可以在任意地方调用这些插件来实现一些简单的功能,无需后端代码,无需后端部署,只需要在前端写一行简单的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个参数,可以说开发效率是非常的快,不仅如此,当你后端更改了表字段,或者更改了查询条件等都可以通过调整参数的形式来完成且避免了重新打包部署发布的繁琐过程。此外对于前端开发者来说,如果你会使用这个插件,那么只要是框架内置的这些插件支持的功能,则都可以通过这种方式来实现全栈开发,即便是内置插件不满足的功能,你也可以通过框架提供的自定义插件开发来实现这种低代码配置化开发。而对于后端开发者而言整个过程后端是不需要写任何代码的(只更改对应的po类对象),即便哪一天业务变更了,只要是在插件功能范围内的,那么也不需要更改任何后端的代码,只需要调整前端json的请求参数就可以了,十分的便捷。
目前crud插件支持 mysql,postgresql,kingbase,oracle 数据库,绝大部分的查询场景均支持,这里包括字段,函数,分组,排序、关联,条件,左右内外连查询,子查询和视图查询等等。
所有的软件框架都存在它的优势和它的劣势,那么这里也列举出一些它的优点和缺点以供开发者自行选择考虑
jdk1.8
spring boot dependencies
lombok
- <dependency>
- <groupId>io.github.ying1dudu</groupId>
- <artifactId>json-script-rule-spring-boot-starter</artifactId>
- <version>4.0</version>
- </dependency>
提示:如果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:尽量避免多个根目录下含有相同的包名+类名(直接类名),如果无法避免直接类名名称冲突,则需要写上类的全限定名(只有冲突时才会用到全限定类名),如配置外键注解fk属性时,且在使用json时前缀也要换成类的全限定名而不能用locations根目录下的直接类名,如果直接类名没有冲突,则json正常使用直接类名即可(默认禁用全限定类名)
提示1:多模块应用下开发一样可以通过locations指向子模块po实体类路径(只要这些路径被加载到classpath中且可以通过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="test.business.po.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对其忽略处理,否则使用的时候会报错
由于部分插件功能比较强大,因此从4.0版本开始要求开发者考虑插件权限的控制,这里为了演示方便直接重写插件方法并返回true,如下(详情可参考自定义开发篇以及权限篇的说明)
- @Data
- @EqualsAndHashCode(callSuper=false)
- @Component
- public class JSRuleGetCustomModel extends JSRuleGet<MyActions>{
- @Override
- public boolean isOwner(Map<String,Object> params,Set<String> roles) {
- return true;
- }
- }
上面是直接重写了查询模型JSRuleGet的isOwner方法,返回true表示可以对该插件进行使用,默认不写的话则是false
接下来需要自定义一个Action仓库,用于装载上面的插件,这里取名为MyActions,代码如下
- @Data
- @EqualsAndHashCode(callSuper=true)
- @Component
- public class MyActions extends JSRuleAction<MyActions>{
- public JSRuleGetCustomModel get;
- }
这里需要重写父类字段的get,用来替换框架内置的get插件,除非你要自己写一个查询的插件,否则一定要重写get字段
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
- {
- "actions": [
- {
- "name": "test_get",
- "get": {
- "relation": {
- "classes":["ZsTestPO"]
- },
- "groupShow":true,
- "fields":["name","salary","currentDate"],
- "condition":{
- "where":{
- "eq":{"ZsTestPO.name":["ccc"]}
- }
- }
- }
- }
- ]
- }
- {
- "code": 200,
- "msg": "operation successfully(操作成功)",
- "result": {
- "test_get": {
- "pageNum": 1,
- "pageSize": 10,
- "dataSize": 1,
- "totalPage": 1,
- "totalCount": 1,
- "data": [
- {
- "current_date": "2023-11-15 00:00:00",
- "ZsTestPO": {
- "name": "ccc",
- "salary": 2200.00
- }
- }
- ]
- }
- },
- "log": null
- }
所解析的sql为
select name as "name" ,salary as "salary" ,current_date as "current_date" from zs_test where zs_test.name='ccc'
至此,后端的json-script-rule便安装测试完成了,接下来的几篇将着重介绍如何使用框架内置封装的插件
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。