栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

WebRose-低代码PaaS平台的新流派,前后端都可直接在线极简式编码

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

WebRose-低代码PaaS平台的新流派,前后端都可直接在线极简式编码

文章目录
  • 前言
  • 一、WebRose具体如何在线开发?
  • 二、前端JS编码
    • 1.创建前端组件的方法
    • 2.操作前端组件方法
    • 2.动态创建布局
    • 3.前端跳转新页面
    • 4.调用后端微服务Java逻辑
  • 三、后端Java在线开发
    • 1.后端开发界面
    • 2.后端逻辑类结构
    • 3.后端操作数据库
    • 4.后端开发总结
  • 四、单据模板
    • 1.单据模板理念
    • 2.模板配置界面
    • 3.拖拉拽配置方式
    • 4.所见即所得配置方式
  • 五、异常定位与在线调试
    • 1.异常堆栈窗口
    • 2.点击异常之源代码
    • 3.查看服务器端控制台
  • 六、SQL执行工具
  • 七、JRE客户端访问模式
  • 八、总结


前言

点击地址可进入WebRose在线体验系统(无需注册用户,直接访问)
www.webrose.net.cn:5015/wrs/framework/login.html

WebRose平台是近年来在百花齐放的低代码PaaS平台市场出现的一支新流派,受到了越来越多的开发者关注,这是一个极其简单易用,但又功能非常强大,可100%完全在线开发(包括前端JS与后端Java调试)的低代码开发平台,其理念与思路与许多根据表结构生成前后端源代码(代码生成器)的思路大有不同,另辟蹊径,自成一派。

WebRose低代码主要体现在以下几点:
1、一个界面搞定开发全过程,即从建表,建模板,建前端JS与后端Java在一个功能上全部搞定,快速上手简单到极点。

2、直接在线编码,不是生成源代码的思路,前端只要一个JS,后端只要一个普通Java类就够了,没有html,Vue,Controller,Service,实体VO等一批源文件,“所见即所得”模板配置方式,非常低代码。

3、在线编译调试发生异常时,点击异常堆栈直接跳转到源代码窗口的对应行号,就像Idea/Eclipse等开发工具中Debug一样快速定位问题。

4、还有Java客户端开发与访问模式,遇到一些不适合Web开发的需求时提供另一种强有力的选择,B/S与C/S模式两者无缝完美合二为一,可以与硬件设备交互(比如串口/USB传感器),非常适用于工业互联网,智能制造,智慧医疗等行业。

点击上面链接可直接进入系统体验,第一个菜单中有多个在线视频,详细讲解如何开发与使用,里面还预置了大量经典Demo,从菜单页签上右键可以查看各功能点源代码(即如何低代码)。系统截图如下:

.
.

一、WebRose具体如何在线开发?

系统有一个【★在线PaaS开发台】功能点,就在这里开发!
在一个界面上就可以完成全过程开发,包括:前端JS,后端Java,单据模板创建,SQL建表。截图如下:

截图中PaaS工作台中有4个页签,第一个是在线写前端JS低代码,第二个是在线写Java低代码,第三个是创建与配置单据模板,第四个是写SQL直接建表。
JS与Java编码页面中左边是编码区域,右边是各种例子代码,可以复制到左边编码框中,提高效率。
.
.

二、前端JS编码 1.创建前端组件的方法

WebRose一大特点是:无论是创建数据组件(表格/表单/树)还是布局组件(多页签/分割器)都只要一行代码就解决问题。简言之:凡是一行能解决问题的,绝不用两行代码。

创建表格的代码如下:

//一行代码创建表格,第1个参数是微服务名(单体时为空),第二个是div的id,第三个参数是模板编码
WRS.createBillList("", "d1", "demo_user1_SYSTEM");

创建卡片(即表单)的代码如下:

//一行代码创建卡片(即表单),第1个参数是微服务名(单体时为空),第二个是div的id,第三个参数是模板编码
WRS.createBillCard("", "d1", "demo_user1_SYSTEM");

创建树代码如下:

//一行代码创建树,第1个参数是微服务名(单体时为空),第二个是div的id,第三个参数是模板编码
WRS.createBillTree("", "d1", "demo_user1_SYSTEM");

直接创建一段静态Html

WRS.createHtml("d1", "");

把布局组件与数据组件组合到一起:

//下面这是是创建一个左右布局,左边是树,右边是卡片的
WRS.createSplit("d1", "左右", 300); //界面左右分割
WRS.createBillTree("", "d1_A", "demo_corp1_SYSTEM");  //左边是机构树
WRS.createBillCard("", "d1_B", "demo_corp1_SYSTEM");  //右边是机构卡片

下面这个是机构/部门/人员结合多页签与分割布局

WRS.createSplit("d1", "左右", 300);  //先左右布局
WRS.createTabb("d1_B", ["部门", "人员"]);  //在右边再创建多页签
WRS.createBillTree("", "d1_A", "demo_corp1_SYSTEM");  //左边是机构树
WRS.createBillList("", "d1_B_1", "demo_dept1_SYSTEM");  //右边第一个页签是部门表
WRS.createBillList("", "d1_B_2", "demo_user3_SYSTEM");  //右边第二个页签是人员表

下面这个是机构/部门/人员结另一种分割布局嵌套

WRS.createSplit("d1", "左右", 300);  //先左右布局
WRS.createSplit("d1_B", "上下", 280);  //右边再做上下布局
WRS.createBillTree("", "d1_A", "demo_corp1_SYSTEM");  //左边机构树
WRS.createBillList("", "d1_B_A", "demo_dept1_SYSTEM");  //右上是部门表
WRS.createBillList("", "d1_B_B", "demo_user3_SYSTEM");  //右下是人员表

由上几段代码可以看出,WebRose的理念与特点是:一行代码解决一个问题,无论是布局组件还是数据组件都只要一行代码创建,低代码简洁到无法再简洁(零代码我们认为不太现实,或者说丧失了灵活度,只能做一些简单固化的功能,比如单表增删改,即零代码的实际意义有限,而低代码是可行的)。

布局组件可以实现任意层次无限嵌套,但没有采用的html/xml(或vue)那种本身就是嵌套结构的思路,而是通过id的命名规则来实现父子div的关联嵌套,比如在id为“d1”创建分割器时,就会以"_A"与"_B"为后辍创建两个子div,即d1_A与d1_B,然后就可以继续在这两个子div中继续创建,多页签则是以_1、_2、_3…为后辍。

这种扁平化代码结构更简洁,代码量最少,而且在页面层次非常多时,那种嵌套结构的语法就有点像“JS回调地狱”一样,量变导致质变,可读性就不太友好了,有种代码错位层次太深,眼睛都看花了的感觉,不如扁平化语法简洁。

举例,如果我们用Vue的语法样同样实现一个先左右布局,然后右边再有两个页签的代码比较一下就更容易理解.
Vue语法如下:


  
  
  
    
	    部门
	    人员
		
  

WebRose语法如下:

WRS.createSplit("d1", "左右", 300);  //先左右布局
WRS.createTabb("d1_B", ["部门", "人员"]);  //在右边再创建多页签

通过比较可以看出WebRose的语法更简洁。

这里的本质区别是,一种是用XML自身的嵌套结构表达父子隶属关系,一种是通用id命名规则表达父子隶属关系,而前者是有头有尾的,即有个〈div〉,必然还要有个〈/div〉,所以代码行数必然至少要多一行,而要想进一步低代码简化代码行数,使用id名称直接表达隶属关系肯定会更简洁。

使用id命名规则表达父子隶属关系,还带来一个好处是代码本没就是扁平化了,从上往下一行行代码是对齐的,没有嵌套结构,反而可读性更友好,尤其是在层次非常深的时候。

在线演示系统中,特意做一个层次非常多与深的功能例子,代码如下:

WRS.createTabb("d1", ["页签1", "页签2"]);
WRS.createSplit("d1_1", "左右", 300);
WRS.createTabb("d1_1_B", ["部门", "人员"]);
WRS.createSplit("d1_2", "上下", 300);
WRS.createSplit("d1_2_A", "左右", 300);
WRS.createTabb("d1_2_B", ["部门", "人员"]);
WRS.createBillTree("", "d1_1_A", "DEMO_CORP_CODE1.xml");  //左边树
WRS.createBillList("", "d1_1_B_1", "DEMO_DEPT_CODE1.xml");  //部门表
WRS.createBillList("", "d1_1_B_2", "DEMO_USER_CODE3.xml");  //人员
WRS.createBillTree("", "d1_2_A_A", "DEMO_CORP_CODE1.xml");  //机构树
WRS.createBillCard("", "d1_2_A_B", "DEMO_CORP_CODE1.xml");  //机构卡片
WRS.createBillList("", "d1_2_B_1", "DEMO_DEPT_CODE1.xml");  //部门表
WRS.createBillList("", "d1_2_B_2", "DEMO_USER_CODE2.xml");  //人员表

后来也再用Vue语法验证做这个例子,就发现代码层次真的太深了,代码量太大,量变导致质变,可读性不够友好。

这里需要指出的是,Vue静态XML嵌套结构与JS扁平化结构两种思路各有优缺点(决不能说谁优谁劣),WebRose这样设计基于以下几点考虑:
1.想进一步体现低代码思想,代码更少一点更简洁一点,不想有复杂嵌套结构,所以想在Vue组件化基础上再封装一层,把常见的表格/卡片/树/查询框及布局组件封装成一个函数,一行代码搞定,其实内部可以理解成依然是一个“Vue组件”,肯定还是一个双向数据绑定的组件,可以简单理解成是基于Vue思想的再次封装。

2.对于管理软件来说,常见的七八种数据与布局组件已经可以解决了85%(甚至更高)以上的各种界面需求了,剩下的就是一些非常个性化界面需求了,那些个性化的界面封装组件没有意义(因为没有重用性),即使用Vue也没必要封装组件的,真不如直接写Html算了,所以既然这样,不如抓大放小,把常用的组件用新思路,封装更进一步,更简洁一些,然后又可以与html混合在一起运行,依然可以使用Html的嵌套结构。即可以先创建一段个性化的html,然后在获取其中某个div的id中使用WRS.createBillCard()也是可以创建对象的,两者不矛盾,可以混合在一起执行的。

3.什么都用JS创建界面,缺点就是没有了界面与逻辑分离的概念,即html/vue静态页面是表达界面展现,而JS是处理逻辑,两者分离的思想是许多人非常认可的,道理也是非常对的,但在实际应用中也发现,管理软件许多界面都是高度封装与抽象的“数据化界面”,就是表格/表单/树/按钮这几种东东反复叠加,然后通过单据模板配置,这里的组件表达就一行很简单的配置(只有一个模板编码参数),什么Css展示效果都已封装成了组件里面的一部分了,美工也不需要再为每个页面做什么效果了(简称画页面),最后导致所谓的静态页面内容越来越简单(有的页面甚至只有一个div了,其他啥都没有),静态页面分离似乎如同鸡肋一般,随着封装程度越高,这种趋势与感觉越明显,好象最后不如放弃静态页面,什么都是JS动态创建反倒更省事,下面有讲动态创建页面会再次讲到这一点。
.

2.操作前端组件方法

创建好组件(表格/卡片/树)后,如何操作或调用这些组件,比如往卡片中设置某个字段的值,或者取得表格选中行的数据。

这个非常简单,即上面一行代码创建组件时,同时也在当前window中创建了一个对象,对象名就是拿div的id加上_BillList、_BillCard、_BillTree等后辍,这个对象可以直接使用,比如d1_BillList,d1_A_BillCard…

比如下面这段代码,其中的“d1_A_BillList”就在第2行代码创建时生成了,后面可以直接拿来使用:

WRS.createSplit("d1", "上下", 350);  //界面上下分割
WRS.createBillList("", "d1_A", "DEMO_DEPT_CODE1.xml");  //部门主表
WRS.createBillList("", "d1_B", "DEMO_USER_CODE3.xml");  //人员子表
d1_A_BillList.addRowSelectAction(onSelectDept);  //d1_A_BillList对象已有,可直接使用

当然,也可以为创建的组件自己重新取个名字,有时可读性好一些(尤其是层次数量较多时),代码如下:

var myDeptTable,myUserTable;  //自己定义变量名
WRS.createSplit("d1", "上下", 350);  //界面上下分割
myDeptTable = WRS.createBillList("", "d1_A", "DEMO_DEPT_CODE1.xml");  //部门主表,返回自己对象名
myUserTable = WRS.createBillList("", "d1_B", "DEMO_USER_CODE3.xml");  //人员子表,返回自己对象名
myDeptTable.addRowSelectAction(onSelectDept);  //使用自己的对象名

只要取得d1_A_BillList或d1_A_BillCard这个对象句柄,就可以直接操作其中的方法与变量,这与Vue等现在流行的“组件化”,“双向数据绑定”思想是一样的,即只要操作对象属性或方法,页面会自动同步渲染,不需要程序员去解决渲染同步问题。

比如BillCard(卡片/即表单)的常用方法有(所有方法查看平台完整帮助):

d1_A_BillCard.setItemValue("usercode","001");  //设置表单中某个字段值
d1_A_BillCard.getItemValue("usercode");  //取得某个字段值
d1_A_BillCard.setBillCardValue({"usercode":"001","username":"张三"});  //设置整个表单值,会根据不同控件类型渲染不同效果
d1_A_BillCard.getBillCardValue();  //取得整个表单值
d1_A_BillCard.setItemEditable("usercode",false);  //设置某个控件不可编辑

从卡片设置值的方法可以看出,开发人员只要了解这一个setItemValue方法就够了,而不需要学习各种具体控件(比如文本框,下拉框,图片上传)的具体API,平台会负责不同控件之间的转换渲染出不同效果,这样学习难度就低多了。

BillList(表格)的常用方法有(所有方法查看平台完整帮助):

d1_B_BillList.getSelectedRowData();  //取得选中行的数据
d1_B_BillList.getSelectedRowIndex();  //取得选中行的行号
d1_B_BillList.addRowData(1,{"usercode":"001","username":"张三"});  //插入一行数据
d1_B_BillList.deleteRow(3);  //删除某一行数据
d1_B_BillList.addRowSelectAction(function(_rowData){});  //行选择变化监听事件

总之,各种控件肯定都有非常全面的API函数,可能满足实现各种常见需求。
.

2.动态创建布局

有人应该已经看出,平台创建前端页面与组件都是使用JS函数来创建,甚至创建一段静态html也是使用函数WRS.createHtml来创建,即没有html文件一切都是JS,或者说是与vue等基于html文件中自定义标签名,然后解析文件渲染界面思路不同。

即一种是完全由JS程序动态创建界面,一种是本身还是静态文件,只是定义不同标签,然后解析出动态页面。两种各有优缺点,适用于不同场景。

两者最大的区别在于根据某个条件绘制出完全不同的界面时,解决思路不同。

Vue解决思路是肯定要先把所有页面都写好,然后根据一个条件,用v-if=“条件关系”,与v-else属性来处理,举个例子,比如根据登录人员的编号,如果是admin(管理员),则使用左右布局(左边机构右边人员),如果不是admin用户,则使用多页签布局,也可比较一下两种语法:

Vue的语法类似如下:

部门表 人员表
部门表 人员表

WebRose平台JS代码机制如下:

if(LoginUser.code=='admin'){
   WRS.createSplit("d1", "左右", "40%");
   myDeptTable = WRS.createBillList("","d1_A", "部门模板编码");
   myUserTable = WRS.createBillList("","d1_B", "人员模板编码");
} else {
  WRS.createTabb("d1", ["部门", "人员"]);
  myDeptTable = WRS.createBillList("","d1_1", "部门模板编码");
  myUserTable = WRS.createBillList("","d1_2", "人员模板编码");
}

即像这种根据条件动态输出页面的场景,两种思路各有优缺点(也决不能说谁优谁劣),只是JS代码动态创建的逻辑可读性在某些人看来比静态页面配置条件属性更好些,更符合人的正向思维习惯(v-if/v-else有人觉得生涩,好象是要反来过思考),尤其是逻辑有多层if/else嵌套时,静态条件属性思路还需要把复杂条件先折算成一个变量进行配置,因为无法像JS代码那样自由灵活的搞出多层if/else,而一切都使用JS代码动态创建页面则没有这些问题,非常灵活、自由、自然。所以这两种思路也是各有利弊,也是换个思路尝试,要辩证看待。

前面已提到,针对管理软件“数据化界面”为主的需求场景,随着越来越高度的封装,之前的静态Html/Vue页面展现与动态JS代码分离的思想越来越失去平衡,有点“头重脚轻”,即静态页面内容越来越少,JS代码越来越多,有的页面甚至就只剩下一个div了,如同鸡肋一般,所以干脆不如考虑可以放弃静态页面,全部使用JS创建页面算了,然后抓大放小,把常用的七八种组件继续封装增加功能,解决绝大部分需求场景,剩下的就直接使用html画页面,因为那种情况已不多了,可以接受。

有个小技巧,就是因为放弃静态页面了,全部使用JS创建页面,连创建html也是使用函数WRS.createHtml()了,这带来一个麻烦,就是html要当成JS字符串反义输出,写起来不方便,尤其是美工事先做好的界面还要转义一下。这时可以写个小工具,用程序来完成这个翻译转义。即下面这个转换可以用程序处理。

把上面的代码翻译成下面的,写个程序实现即可。

let str_html = "";
str_html += "rn";
str_html += "rn";
str_html += "";
WRS.createHtml("d1_A",str_html);

但是,凡事都有例外,使用WRS.createHtml()反义输出html只适用于少量html的场景,即这种功能界面大部分是WRS.createBillList/createCard这种组件,只有少量在地方需要一段个性化html(比如表格底部有一排按钮与文字),这种情况是可以的,但如果本身就是一个非常庞化的个性化页面,几乎全部是个性化html(比如有的首页界面),则这种情况肯定不适合采用JS反向输出html的思路(有点本末倒置的感觉),肯定还是要回到静态页面思路上来。这种情况的解决方法是:

在配置菜单时,把菜单类型不选择WRS,而选择LOCALURL,设置一个html文件的路径(比如:/project_demo/MyUser.html),就可以了。即系统认为该功能入口是一个html文件,而是不是一个WebRose(简称WRS)的JS文件入口,然后中一切都回到静态文件的思路上来了,即浏览器先直接解析这个html文件,然后其中依然可以调用WRS的各种函数进行逻辑处理。

这个LOCALURL还有个重要价值是,这里可引用使用任何其他框架写的页面,比如以前使用其他框架写的功能也可以整合进来,即WebRose是个完全开放的框架,完全可以与任何其他框架合并运行。菜单配置截图如下:
.
.

3.前端跳转新页面

一个业务功能经常一个页面满足不了需求的,经常要跳转或切换多个页面(有的也叫路由),在WebRose中叫弹出窗口,因为许多切换页面是以弹出模态窗口的方式出现,然后只要把弹出窗口满屏显示(同时隐藏标题栏),就是等价于切换到一个新页面。切换页面还要传数据参数到新页面,以及从新页面接收返回数据,具体方法如下:

let par = {"usercode": "001"};  //传输到新窗口中的参数
WRS.openDialog('新窗口标题', '/project_demo//NewDialog.js',800,500,par, function(_rt){
  console.log("接收到新窗口中的返回值:" + _rt);
});

即使用WRS.openDialog弹出新窗口,设置窗口标题,新窗口JS路由路径,窗口宽度高度,接收返回数据的回调函数,就可以了,如果想满屏显示,只要把容器大小的宽度高度都设成-1,下面代码就是弹出一个满屏窗口,而且隐藏标题,这其实就等价于跳转到另一个完整的页面。

let par = {"usercode": "001","$NoTitle":"Y"};  //$NoTitle这个特殊变量可以隐藏标题
WRS.openDialog('新窗口标题', '/project_demo//NewDialog.js', -1, -1, par, function(_rt){
  console.log("接收到新窗口中的返回值:" + _rt);
});

在新页面中使用特定函数关闭窗口,就可以返回数据到父页面,代码如下:

WRS.closeDialog({"code":"OK","msg":"返回内容"});

即使用WRS.closeDialog函数关闭本页面(窗口)时,参数中的数据就会自动传输到父页面打开窗口时的那个回调函数中(见上面代码回调函数)。
.

4.调用后端微服务Java逻辑

前端调用后端,一般是指定一个Controller路径,设置入参进行调用,WesRose进行进行了封装,只要直接调用某个Java类名与方法名即可,具体如下:

let par = {"usercode":"001"};
let jsoRt = WRS.doClassMethodCall("", "cn.com.projectdemo.bs.TestBSO", "test01", par);
console.log("同步调用接收到返回值:" + jsoRt);

异步调用如下(方法名叫doClassMethodCall2,比同步方法名多了一个2)

let par = {"usercode":"001"};
WRS.doClassMethodCall2("", "cn.com.projectdemo.bs.TestBSO", "test01", par, function(jsoRt){
  console.log("异步调用接收到返回值:" + jsoRt);
});

这种设计出于两方面考虑:
一是既然想要低代码,就首先应该考虑减少代码类的数量,即这样可以省略掉Controller类与Service类(被封装到平台底层去了),只需要一个“纯业务逻辑"类,代码数量减少了,更接近低代码了。

二是服务器端Java代码在线编码后要立即编译生效(不能重启服务器)控制Spring容器热加载Class,而且在分布式环境下,Class类不能存储在某一个Server上(这样其他Server取不到), 而是存储在数据库中的,即整个Class加载需要重构,所以远程调用就不如直接使用类名与方法名作为参数调用更方便。

后端Java如何在线开发,以及与前端调用参数与返回值传输,请继续往下看。
.
.

三、后端Java在线开发 1.后端开发界面

后端微服务Java业务功能逻辑在线开发与前端JS开发是一个页面上,具体说就是第二个页签中,截图如下:

即在第一个页签进行前端JS在线编码,第二个页签中进行后端Java在线编码,直接在线编译保存后就立即生效,不需要重启服务器。前端调用后端这个Java逻辑就是上面讲的JS方法中直接指定类名与方法名即可。

2.后端逻辑类结构

一个标准的后端逻辑如下:

package cn.com.projectdemo.bs;

import org.json.JSONObject;

public class TestBSO{

  public JSONObject test01(JSONObject _par) throws Exception {
    String str_code = _par.optString("usercode");  //取得前端传入的参数值
  
    //执行具体业务逻辑...
  
    JSONObject jsoRt = new JSONObject();  //创建返回对象!
    jsoRt.put("code", "OK");
    jsoRt.put("msg", "后端返回结果");
    return jsoRt;
  }
}

上面这段就是标准典型的后端Java逻辑,从中也可以“低代码”思想,即这是一个标准的普通Java类,没有设置任何注解,也没有继承于任何抽象类或接口,只引用了唯一的对象org.json.JSONObject(这个类就是对应前端JSON对象格式),只要懂一点Java基础语法知识就能学习。

后端Java逻辑只要遵守唯一约定,就是对应方法入参与出参都必须是JSONObject类型即可。

这种设计也是现在流行的“面向领域”的理念,即尽可能的将“业务代码”与“基础服务代码”分离,业务代码中不要出现基础框架代码(比如注解/抽象类/接口),因为这样就会被某种基础框架绑死,以后万一需要升级或迁移到其他基础框架上时,就要修改大量业务代码。反之,如果业务代码就是一种“纯业务代码”不直接强关联基础代码,则影响非常小。

值得一提的是,后端Java编码是使用的标准Java语言,也是需要先编译成Class(只不过是热加载可立即运行),而没有采用Python/Ruby/Groovy/NodeJS这种动态语言(按理说动态语言更适合做配置化),这是为了可以与标准开发模式代码相互转换,即之前许多业务逻辑都是在Idea等开发工具中使用Java语言开发的,如果有一天想把这样代码转换成在线代码,或者反过来,把原来在线编码的再转换到开发工具中重新打Jar包发版,这两种转换之间最好是代码是一种,一点都不要修改,而不是说凡是在开发工具中写的发版本包的都是java语言,凡是在线配置的又是另一种语言,两种无法直接转换,这会带来许多不方便,不灵活。另外从功能角度讲,肯定是Java语言更健壮强大,最适合做复杂业务逻辑开发。

3.后端操作数据库

后端业务逻辑最常见的就是操作数据库,一般做法就是使用MyBatis等持久化工具结合实体VO进行数据处理,而WebRose在这一方面也有一些不同。

下面是典型的查询数据逻辑:

CommDMO commDMO = new CommDMO();  //创建数据库处理工具类

//直接送SQL查询mysql数据源
HashVO[] hvs = commDMO.getHashVOsByDS("ds_mysql","select * from demo_user where sex='M' and age>=30");

//送预编译模式SQL查询oracle数据源
HashVO[] hvs = commDMO.getHashVOsByDSPrepared("ds_oracle","select * from demo_user where sex=? and age>?", new Object[]{"M", 30});

String username = hvs[0].getStringValue("username");  //取得姓名字段值
int age = hvs[0].getIntValue("age");  //取得年龄字段值
Date birthday = hvs[0].getDateValue("birthday");  //取得出生日期,返回java.sql.Date对象类型

下面是典型的Insert数据代码:

InsertSQLBuilder isql = new InsertSQLBuilder("demo_user");  //创建Insert对象,指定表名
isql.putFieldValue("rid", UUID.randomUUID().toString());  //主键
isql.putFieldValue("usercode", "001"); //设置工号
isql.putFieldValue("username", "张三");  //设置姓名
isql.putFieldValue("age", 32);  //设置年龄

new CommDMO().executeUpdate(isql);  //提交数据库

下面是典型的Update数据代码:

UpdateSQLBuilder isql = new UpdateSQLBuilder("demo_user","usercode='001'"); //创建Update对象,指定表名与where条件
isql.putFieldValue("username", "李四");  //更改姓名
isql.putFieldValue("age", 41);  //更改年龄

new CommDMO().executeUpdate(isql);  //提交数据库

下面是典型的Delete数据代码:

DeleteSQLBuilder isql = new DeleteSQLBuilder ("demo_user","sex='M' and age>30"); //创建Delete对象
new CommDMO().executeUpdate(isql);  //提交数据库

由上代码可以看出增删改查都是使用一种通用的Java对象,比如所有查询返回都是HashVO这个对象类型,而增改删则使用InsertSQLBuilder/UpdateSQLBuilder/DeleteSQLBuilder这三个通用的Java对象,这三个对象底层最后实际执行时都是使用PrePareSQL预编译机制(性能与安全绝对可靠),而且会自动根据数据源的不同类型(Mysql/Oracle/DB2/…)进行数据格式兼容性转换,关键是事务控制也是绝对保证的,可以简单理解与与MyBatis/Hibernate的目标及底层实现原理是一样的,相当于自我实现了一套MyBatis的核心功能。

之所以这样设计,也是基于两方面考虑:

1.想进一步体现低代码思想,减少代码量,即使用通用数据对象可以省掉实体VO对象,如果为每张表建一个实体VO类,这本身的代码量就非常大,似乎谈不上叫什么低代码。

2.实体VO之Java对象本身是一种静态对象,而且都是要编译后运行,现在要想实现PaaS在线编码,在线配置立即生效,一切都需要是动态的,最基本常见的一个需求就是表单要加一个字段,增删改查逻辑要立即全好了,如果还是采用实体VO对象,则加个字段就要改代码(加变量加get/set方法),然后再修改相关其他地方代码,还要编译发布(甚至还要重启服务器),这似乎也不像是低代码模式。

所以为了进一步体现“低代码”的理念与思想,WebRose平台采用了通用Java对象类,服务器端只有一个Java逻辑类就够了,没有Controller类,没有Service类,没有实体VO类,表中增加或修改字段只要在单据模板中配置一下就立即生效了,不需要修改其他任何东西,这才非常简单,非常低代码。

但是,需要特别指出的是,平台也不是封闭与不兼容的,即只有HashVO对象,而无法使用实体VO,事实上,HashVO本身也提供了方法可以直接转换成实体VO,查询数据,修改数据时也可以直接返回实体VO,具体如下。
把一个HashVO转换成实体VO代码:

DemoUserVO userVO = hvo.toEntityVO(DemoUserVO.class);  //HasVO本身有方法可以直接转实体VO,只要传入实体VO的Class

查询时也有方法可以直接返回实体VO数组

CommDMO commDMO = new CommDMO(); 
DemoUserVO[] userVOs = commDMO.getEntityVOs("select * from admin_sm_user where sex='M'", DemoUserVO.class);

用实体VO来修改数据提交

DemoUserVO userVO = hvo.toEntityVO(DemoUserVO.class);  //把HashVO转成实体VO
UpdateSQLBuilder  isql = new UpdateSQLBuilder(userVO); //把实体VO再转换成UpdateSQLBuilder
new CommDMO().executeUpdate(isql);  //提交数据库

即平台也是可以与MyBatis及实体VO进行无障碍自由转换的,在那些不强调配置化,非常个性化的复杂业务场景中,使用实体VO进行开发肯定还是有不少好处的,这需要辩证看待。
.

4.后端开发总结

总之,WebRose后端Java编码体现三个核心要点:
1.可以在线编码立即生效,而且使用标准Java语言(不是另一种动态语言),集合了Java语言与动态语言的优点。

2.是标准的普通Java类,无需实现任何注解/抽象类/接口,不与底层框架代码强关联,是“纯业务逻辑”开发。

3.数据库处理可以使用通用类与方法,这种理念我们称之为“类存储过程”,即代码量低得几乎与数据库存储过程类似,但其实又是Java语言,屏蔽了存储过程的各种缺点,可以简单理解成是初衷与目标是想以某种“Java存储过程”的方式来进行简洁高效的数据库编程。

●存储过程备注(来自百度百科):是在大型数据库系统中,一组为了完成特定功能的SQL语句集,存储在数据库中,用户通过指定存储过程的名字并给出参数来调用存储过程。
存储过程优点是:代码简洁(低代码),性能高,减少网络流量,安全性高。
缺点是:调试困难,难以进行横向分布式扩展,移植性差。

.

四、单据模板 1.单据模板理念

单据模板是平台是非常重要的,也是唯一的配置,有的框架叫表单设计器,但本平台中的模板是把表单、表格、树、查询框,查询关联、后端存储相关,等所有信息都合成在一个模板中配置,可以简单理解是一种“N合一”的思想。

这种“N合一”的设计思路是基于以下三方面考虑:

1.也是为了进一步体现“低代码”思想,即所有配置合成一个对学习者来说肯定最简单,而不是要切换好与学习好几个地方的不同配置,就一个功能点,一个界面,学完就全OK了。

2.从数据模型角度讲,表单/表格/树等组件本质上是一个东西,许多配置信息合并在一起是有道理的,表单本质上就是把表格中一条记录“展开显示”,树本质上也是一个特殊的表格(只显示一个字段,错位显示而已),比如一个性别字段,存储值是M/W,显示值是男/女,这个配置信息无论在表格、表单、查询框中都是一样的,就应该合并在一起。所以WebRose就把能合并都合并成一个,属于某种特定组件(卡片/表格/树)的属性以分组的形式在模板中进行配置。

3.前后端配置一体化,即大部分信息是前端使用的,但有的配置信息是属于后端使用的(比如:是否参与保存/是否加密存储/过滤条件),而前后端这些配置又有着密切关系(比如分页就同时涉及到前后端),因为许多公司前后端是两个独立团队,所以前端配置与后端配置是独立的,没有考虑进一步合并,如果进一步合并,则又会简化许多。

2.模板配置界面

模板配置分模板主表(整体配置),与各个字段的配置,实际运行截图如下:


.

3.拖拉拽配置方式

需要指出的是,在PaaS开发台中第三个页签模板配置中,有个【拖拉拽配置】,即可以进行拖拉控件的方式配置表单,因为现在流行的“表单设计器”风格(有人甚至认为这是唯一正确的),所以不得不提一下。


这是标准典型的拖拉式配置表单,直接拖动控件进行配置,可视化配置,这个功能WebRose也有,而且非常精致,但根据实际经验,更推崇一种“所见即所得”的配置方式。继续往下看。

4.所见即所得配置方式

拖拉控件方式配置现在比较流行,但WebRose平台更建议另一种“所见即所得”配置方式,即直接从实际运行界面,在某个控件上右键直接进入配置,然后保存后立即刷新就看到效果,而不是先在模板配置界面中配置,然后回到运行界面重新打开查看效果,在两个界面之间来回切换肯定不如“所见即所得”来得更快捷方便。
所见即所得之右键配置效果如下:

从运行界面直接“所见即所得”配置还有个好处是,有许多配置是与运行数据相关的(比如表格行记录状态颜色),在设计器中配置看不出任何效果,必须在运行界面中实际跑起来才看到效果,所以不如直接从运行界面配置来得更方便。

了解模板配置最简单的方式就是进入在线演示测试系统,随便选择一个表格或卡片右键就可以可看配置,每个配置项上都是详细帮助说明。配置项虽然很多(因为功能必须强大),但所有配置都合在这里了,即平台总共就这一个配置(大部分都是勾选型与选择型配置),只要掌握就全会了。

可以简单理解,前端掌握几个JS对象,后端掌握几个Java类,再加上这一个模板配置,就可以使用WebRose平台进行各种业务功能开发了,非常简单易学。
.
.

五、异常定位与在线调试 1.异常堆栈窗口

异常处理也是WebRose的一大特点,每个程序员都明白一个道理就是编程其实是大部分精力就是处理各种各样的异常,所以当发生程序异常时如何快速定位与分析出异常原因显得非常重要,有时甚至是最重要。

在开发环境中遇到异常因为有源代码,可以debug,所以分析异常比较容易,而在生产运行环境发生异常时,只根据异常堆栈日志有时真不太容易分析出原因,尤其是服务器端异常,一是没有源代码可定位分析调试,二是日志非常多(高并发时),很低难找到本次线程调用的相关日志。

WebRose因为前后端都是在线编码,即源代码都是在线的,所以就在发生异常时,把客户端与服务器端堆栈与源代码的关系打通了,在异常窗口中,像在Idea/Eclipse等开发工具中一样,点击异常堆栈可以直接跳转到对应的源代码的对应行数,从而快速定位问题。而且是把本次线程调用的服务器端堆栈也返回到客户端显示,同时还可以直接从前端查看服务器端Java控制台,进行各种输出调试,这样一来分析异常就方便多了。

实际运行截图如下(在线演示测试系统有此Demo):

2.点击异常之源代码

点击服务器端Java堆栈链接,打开Java源代码如下:

.
点击前端JS异常堆栈,打开JS源代码如下:

由上截图可以看出,因为在线编码有前后端源码,然后把异常堆栈与源代码查看关联打通,在发生异常时可以快速查看到源代码中所在行号位置,这样就可以很容易分析问题原因。

3.查看服务器端控制台

分析出问题原因后,同样也因为是在线编码,就可以直接在线修改与调试,当场解决问题,而不需要发布版本,解决与调试问题时,经常需要把变量值打印出来查看内容,在前端使用console.log打印浏览器就可看到,而后端使用System.out.println()打印则不容易看到,所以平台在Java编码界面的右下角也提供了一个【查看服务器控制台】按钮,点开可以查看服务器端Java控制台,运行截图如下:

这里有个小技巧,在高并发时日志输出速度会非常快,不一定找得到对应的日志,即System.out.println的输出也不容易找到,可以把想要查看的对象数据包装在一个业务异常中抛出,这样前端就会弹出异常窗口,直接在前端窗口中从异常内容看到这个变量值!这本质上就是想只查看本次线程调用中的变量值,而不想被其他线程干扰。
例码如下:

String str_sql = "select * from demo_userrr where rid='" + str_rid + "'";
System.out.println("rnrn★★★★★输出SQL看看【" + str_sql   + "】★★★★★rn");
//把变量值放在异常内容中抛到查看,这样就不会与其他线程干扰
throw new WLTAppException("不是真的异常,只是输出SQL看看【" + str_sql   + "】!");

.

六、SQL执行工具

在线PaaS工作台最后一个页签叫“SQL执行工具”,就是可以直接执行建表SQL,因为在线开发新功能,肯定要创建新的业务表的,所以要有一个可以在线建表功能。截图如下:

这个工具几乎每个公司与框架都有,有的框架还把这个建表工具做成了一个表格可视化界面,客户体验更友好,其实最后也是根据表格中的数据生成SQL执行的,WebRose平台认为写SQL并不复杂,而且更自由与灵活(可以写各种类型的),所以也换了思路,没有做可视化界面,而是提供了各种SQL的Demo模板(界面左边表格),可以快速复制SQL,然后在复制后的SQL基础上修改,这也是很方便的,有时实际效率反而更高,即感觉可视化建表工具不是特别关键。
.

七、JRE客户端访问模式

WebRose的功能点除了使用纯Web/JS开发之外,还可以使用Java客户端开发,然后使用JRE登录系统。这也是与业内其他低代码平台极其不同的一个特点,或者说至少目前还没有发现与此完全相同的“前端Web与Java两者合二为一”的技术平台。

即客户端不是浏览器,而JRE应用程序(即java.exe),然后也是从服务器端下载前端页面(页面是用Java语言写的),再远程调用服务器端Java业务逻辑类,即前端与后端都是Java语言,也这也叫RIA(富客户端)三层架构,也有人叫三层C/S架构,或者说是集成了B/S与C/S优点的复合模式。

之所以又搞出客户端应用程序,是因为在项目实施过程中遇到一些需求场景,用纯Web/JS不适合做,而只能用应用程序开发,比如以下场景:

1.客户端要写本地文件,或要与硬件设备通讯(比如身份证读卡器/USB口传感器/串口通讯),等与本地系统资源打交道,web浏览器因为安全沙箱限制,JS无法解决这些需求,必须要应用程序。这在工业互联网,智能制造,智慧医疗等行业特别有需求价值。

2.一些功能非常复杂,客户体验要求非常高,有大量多线程,多层次的界面不适合用Web开发,而更适合用应用程序,最典型的是一些开发工具或工作流/报表设计器之类的界面(WebRose中的流程编辑器就是这样做的)。再比如Idea/Eclipse这些大型程序必须是应用程序开发,而不是Web。

3.客户端本身有非常复杂的,非常耗内存的逻辑计算,JS虽然也能开发,但没有Java语言功能健壮,开发成本会高很多,为了考虑开发与维护成本,也更适合使用应用程序开发。

Java本身也有客户端桌面程序开发包(Swing/JFX),再加上Java语言非常健壮,然后服务器端又是Java语言,如果前后端都是Java语言,则在数据交换上非常方便,这比前端用.NetFrameWork应用程序开发,后端用Java好处多得多,比如只要懂java语言一个团队就行,不需要懂两种技术的团队,人力成本会低一半。

最关键的是WebRose平台前端无论是JS还是JRE开发的界面,后端是同一套,即可以共享后端所有功能,下面是JS前端与Java前端调用后端的代码比较,一看就明白了:
JS前端调用后端代码:

let par = {"usercode":"001"};
let jsoRt = WRS.doClassMethodCall("", "cn.com.projectdemo.bs.TestBSO", "test01", par);
console.log("同步调用接收到返回值:" + jsoRt);

.
Java前端调用后端代码:

JSONObject par = new JSONObject();
par.put("usercode", "001"); 
JSONObject jsoRt = UIUtil.doClassMethodCall(null, "cn.com.projectdemo.bs.TestBSO", "test01", par);
System.out.println("同步调用接收到返回值:" + jsoRt );

由上两段代码可以看出,两者调用的是同一个后端逻辑类与方法,两者的方法几乎是对称的。

同样,对应前面创建一个机构与人员表上下布局的页面,使用Java客户端开发的代码如下:

BillListPanel deptList = new BillListPanel("demo_dept_SYSTEM");  //部门表
BillListPanel userList = new BillListPanel("demo_user_SYSTEM");  //人员表

//上下布局,上面是部门,下面是人员
WLTSplitPane split = new WLTSplitPane(WLTSplitPane.VERTICAL_SPLIT, deptList, userList);
this.add(split);

即使用Java模式开发,就是标准的Java语言,什么都是Java变量对象,标准的Java开发模式。
打包发版本时,只要把客户端Java程序也一起打到Spring运行jar包中,然后客户访问某个功能点时,WebRose平台会自动下载对应的前端Class类,然后在前端加载打开界面。

Java客户端访问先要到Java登录首页下载JRE,解压安装后,桌面会创建一个“Java云平台”图标,双击弹出登录窗口,输入微服务端的地址,就可以进入系统。截图如下:

.
下面是Java客户端访问后运行工作流设计器的截图:

需要再次说明的是,无论是Web浏览器访问与Java客户端访问,都是同一个系统,因为Web是前后端分离,所以前端监听端口是5015,其访问的后端其实就是9015端口,也就是Java访问的这个端口,即两者是同一个系统。

WebRose平台 同时又提供了Java客户端开发与访问模式,最大的价值有三点:
1.对一些不适合用Web开发(或Web根本就搞不了),多了一种强有力的可选择的武器,更灵活与强大,就好比既练就了九阴真经,又同时练就了九阳神功,不同场景使用更适合的技术,尤其在一些特殊行业有着强烈优势。

2.前后端都是Java语言开发,开发过程非常简单,技术团队只要懂Java语言就够了,不需要学习新技术,不需要组装两种技术团队。

3.前端无论是何种方式,后端逻辑都完全共享,不需要重复开发,只不过前端有两种方式,而且有的是Web,有的用Java开发,整体工作量并没有多增加一点点。

总之,Java客户端运行模式是WebRose平台极其与众不同的一大特点,有其独特的应用场景优势。
.

八、总结

綜上所述,可以看出WebRose是一个真正意义上的可完全在线PaaS模式开发的低代码平台,主要具有以下特点:

1.只在一个功能界面上(PaaS开发台)就完成了整个前后端逻辑开发,建表,建模板,从零开始实现所有功能的开发,非常简单易学(只要学会这一个功能即可)。

2.前端创建布局与组件,采用的是JS代码动态创建,扁平化基本JS语法(非嵌套多层次),一行代码创建一个组件或布局,总共就四五种数据组件与两三种布局组件就可满足90%以上的开发需求,基本上一看例子代码就会开发。前端大概只要掌握不到20个常用API就可以应对绝大部开发,2~3天左右的学习周期。

3.后端Java逻辑类结构是普通Java类,不依赖任何注解/抽象类/接口,只要懂点Java基础语法就会开发,操作数据库使用通用对象,代码简洁度类似“存储过程”,而且不需要Controller类、Service类、实体VO类、只需要一个纯业务逻辑普通Java类,是真正的低代码。并且是标准的Java语言(非其他动态语言),可以在线编译立即热加载Class,即客户端可以立即调用生效,无需重启服务器等。后端大概只要掌握不到15个常用API就可以应对绝大部开发,1~2天左右的学习周期。

4.模板配置也是合并成一个,无论是表单,表格,树,存储等各方面的配置,都在这个单据模板配置中,只要学会这一个模板配置就够了,没有其他第二个配置功能,绝大部分配置都是选择型,且有大量在线帮助与Demo,极其简单容易学习。3~4天学习周期。

5.异常定位可以直接跳转到源代码对应行号,像在Idea等开发工具中调试一样简便,极大提高解决问题的效率。

6.除了Web外,还有Java客户端开发与访问模式,以一种集合了B/S与C/S优点的应用程序方式开发一些要求更高功能更强的复杂程序,又与Web访问模式共享后端逻辑,既灵活又强大。

强烈建议点击下面地址进入系统实际体验。

www.webrose.net.cn:5015/wrs/framework/login.html
.
.

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/931111.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号