methodinfo(低代码平台将如何改变软件开发)

1. methodinfo,低代码平台将如何改变软件开发?

随着低代码概念的火热,相关的技术及产品也是层出不穷,不管是老牌行业软件厂商还是开放平台厂商,不论是互联网行业企业SAAS软件新动向还是新兴的低代码创新产品服务,都在第一时间打出了低代码这张牌。各个平台虽然各有优势,但大多又是自成体系,真正在企业方面进行选择时却一时难以抉择。对于低代码平台的功能评价,以及各平台组件间的互联互通则成为了市场上迫切需求。

在刚刚过去的2022年,在平台互联互通的方面,阿里在第二季度推出开源引擎 “LowCodeEngin”,国家队信通院也应市场需求在第四季度推出了《低代码开发平台通用技术要求》,针对低代码相关概念以及功能点新型了进一步的规范和梳理。

在全面开放的大背景下,CodeBee团队,推出了基于开源LGPL协议 低代码引擎(LowCodeEngine)。

二,产品组成低代码引擎,由界面设计器、OneCode通码框架以及,DSM领域建模工具 三部分支撑体系相互支撑的部分来组成,通过开放标准的组件协议完成相互继承支持。

(1) 视图设计器引擎设计器,采用的是拖拽引擎+插件的构造模型,用户可以通过开放的低代码协议编写插件。支持JS和JAVA两种扩展语言。样式构建提供了标准CSS3编辑器,支持事件动作以及函数动态扩展。支持自定义函数库扩展,支持阿里字体图片等资源库。

(2)OneCode通码编辑器:OneCode,是一款为低代码语言定制的统一语法体系,采用Java语言作为原生语言,运行在JVM环境中,用户可以通过Java语言与低代码应用进行交互,也可以通过Java语言完成引擎插件,调用代码引擎完成编译部署应用。

(3)DSMEngine领域建模:DSMEngine 是独立于设计器的OneCode建模工具,平台采用领域建模模型,支持仓储管理、聚合应用,以及CodeFactory输出为OneCode代码编译输出。

DSM模型支持三种建模模式:

(1)CodeFrist 代码优先模式

通过Java语言 OneCode 模式原生撰写。

(2)ViewFrist 视图优先

通过视图引擎拖拽完成前期的交互模型,反向完成DSM模型。

(3)ModuleFrist 模型优先

通过数据库,微服务接口等模式,构建基础模型。

DSM逆向转换

通过不同方式完成的DSM模型,可以通过OneCode 在视图、Code 、以及Module 三种方式之间自由切换,利用相关工具完成仿真调试以及部署运行。

DSM第三方语言转换

DSM出码模块采用了独立的模板架构,除了可以以OneCode形式存在,还可以支持独立的出码模块定制独立的第三方语言模型输出。

三,设计器引擎介绍(1)功能概览

(2)设计器布局

设计器引擎是低代码引擎前端的SDK,面向开发人员,他本身不是一套可以适应所有人的低代码平台,而是技术开发人员可以通过扩展插件,周边生态,完成自身业务的定制,实现协同办公,CRM客户管理、物联网平台等通过低代码能力赋能业务系统

(3)物料库

"物料":低代码引擎的核心目的之一是建设跨行业的低代码框架,而每个行业由于其应用的领域不同,使用的人员以及方法方式不同,在一些底层组件方面会有会有加大差距。比如:政府业务中会大量使用的非规则表单元素,企业应用中各个行业自有的图标体系,物联网行业大量的设备图标图片以及实时联网图。

(4)组件库组件定义:可以用于低代码平台的组件,包含了搭建体验增强配置,可以在设计器中 进行拖拽、配置等操作。有两种分类方式:按照场景可以分为基础组件、业务组件、图 表组件、布局组件和复合组件等。通常用户可以自主完成相关设定,并根据业务特点在视图引擎中进行自行扩展(后续章节中会演示实际注册示例)

组件通常是一组完成特定功能的可交互组件,根据不同的引擎模式,在引擎中完成加载渲染配置。

配置示例

Code转换

组件调试导入

(5)支撑管理公共资源导入

(6)样式体系

DOM树透视样式盒

DOM树透视

添加图片注释,不超过 140 字(可选)

配图示例代码

{ "alias":"BuildTreeTreeView", "key":"xui.UI.TreeView", "host":this, "properties":{ "name":"BuildTreeTreeGrid", "items":[ { "borderType":"none", "caption":"JAVA树", "dynDestory":false, "hidden":false, "id":"getBuildTree", "imageClass":"bpmfont bpmgongzuoliuxitongpeizhi", "tagVar":{ } } ], "iniFold":false, "dynDestory":true }, "CS":{ "KEY":{ "color":"#000000", "font-weight":"lighter", "border-radius":"0px 2px 0px 0px" }, "BAR":{ "font-family":"tahoma,geneva,sans-serif" } } }

动态样式盒

添加图片注释,不超过 140 字(可选)

代码配置示例

{ "alias":"xui_ui_cssbox1", "key":"xui.UI.CSSBox", "host":this, "properties":{ "className":"xui-css-ame", "normalStatus":{ "color":"#eeeeee", "border-radius":"6px", "box-shadow":"inset 0px 1px 0px #87C1DD", "text-shadow":"0 1px 0 #297192", "$gradient":{ "stops":[ { "pos":"0%", "clr":"#4BA3CC" }, { "pos":"70%", "clr":"#3289B2" } ], "type":"linear", "orient":"T" }, "cursor":"pointer", "border-top":"solid #3899C6 1px", "border-right":"solid #3899C6 1px", "border-bottom":"solid #3899C6 1px", "border-left":"solid #3899C6 1px" }, "hoverStatus":{ "border-radius":"0px 3px 0px 0px" } } }

(7)事件框架

添加图片注释,不超过 140 字(可选)

配置代码示例:

{ "alias":"BuildTreeTreeView", "key":"xui.UI.TreeView", "host":this, "properties":{ "name":"BuildTreeTreeGrid", "items":[ { "borderType":"none", "caption":"JAVA树", "dynDestory":false, "hidden":false, "id":"getBuildTree", "imageClass":"bpmfont bpmgongzuoliuxitongpeizhi", "tagVar":{ } } ], "iniFold":false, "dynDestory":true }, "events":{ //获取数据 "onGetContent":{ "actions":[ { "args":[ "{page.ReloadChild.setQueryData()}", null, null, "{args[1].tagVar}", "" ], "desc":"设置扩展参数", "method":"setQueryData", "redirection":"other:callback:call", "target":"ReloadChild", "type":"control" } ] }, //数据项选择 "onItemSelected":{ "actions":[ { "args":[ "{args[1].id}" ], "conditions":[ { "symbol":"non-empty", "right":"", "conditionId":"_nonempty_{args[1].className}", "left":"{args[1].className}" } ], "desc":"删除存在页", "method":"removeItems", "target":"BuildTreeTab", "type":"control" } ] } } }

(8)动作调用功能概览

添加图片注释,不超过 140 字(可选)

添加图片注释,不超过 140 字(可选)

配置实例代码:

{ "args":[ "{page.ReloadChild.setQueryData()}", null, null, "{args[1].tagVar}", "" ], "desc":"设置扩展参数", "method":"setQueryData", "redirection":"other:callback:call", "target":"ReloadChild", "type":"control" }, { "args":[ "{page.ReloadChild.invoke()}", "temp", null, "{args[2]}" ], "desc":"子节点装载", "method":"invoke", "redirection":"other:callback:call", "return":false, "target":"ReloadChild", "type":"control" } ] }

(9)插件体系插件是嵌入到设计器的内置管理功能,不同于业务组件,插件更多的是系统极的扩展功能。在实际应用中也比较常见,如系统运行期我们要根据用户不同显示不同内容数据,这就需要权限插件来完成,而业务用户在使用过程也会涉及到大量的业务和数据的流转功能而这些功能则需要动态的来管理页面的属性,甚至动态生成注入页面。这就需要流程插件来辅助完成。 在实际开发过程中特别是真实项目的工程开发时,我们往往要针对工程方面的进行很多的宏操作比如批量的修改特定组件样式,按特定条件检索复制组件特性,自动添加动作等等。这些都需要类似的宏插件来完成,OneCode 在整合后端运行以及服务部署方面也是按插件体系来规范的。分别针对,DSM建模提供了DSM插件,发布管理及运行提供了OPS插件, API整合方面提供了代理服务器插件,系统插件部分采用全开源方式共有需要的用户自行修改方便用户后期可以参照插件体系来修改自身的插件体系。

添加图片注释,不超过 140 字(可选)

添加图片注释,不超过 140 字(可选)

四,OneCode中后台OneCode 本身基于JAVA语言体系,是在Java Spring 注解基础上的一套扩展子集,可以在普通额Java程序中通过添加注解,来实现前后台与低代码引擎的交互处理。

(1)渲染原理

(2)示例展示

添加图片注释,不超过 140 字(可选)

(3)完整模块OneCode

添加图片注释,不超过 140 字(可选)

添加图片注释,不超过 140 字(可选)

@Controller @RequestMapping("/admin/org/person/") @MethodChinaName(cname = "人员管理", imageClass = "spafont spa-icon-login") @Aggregation(sourceClass = PersonService.class) public class PersonAPI { @RequestMapping(method = RequestMethod.POST, value = "Persons") @GridViewAnnotation() @ModuleAnnotation( caption = "人员列表") @APIEventAnnotation(autoRun = true, bindMenu = {CustomMenuItem.reload}) @ResponseBody public ListResultModel<List<PersonGridView>> getPersons(String orgId) { ListResultModel<List<PersonGridView>> resultModel = new ListResultModel<List<PersonGridView>>(); List<Person> personList = new ArrayList<>(); try { personList = getService().getPersons(orgId); resultModel = PageUtil.getDefaultPageList(personList, PersonGridView.class); } catch (Exception e) { e.printStackTrace(); } return resultModel; } @MethodChinaName(cname = "人员信息") @RequestMapping(method = RequestMethod.POST, value = "PersonInfo") @NavGroupViewAnnotation() @APIEventAnnotation(callback = {CustomCallBack.ReloadParent, CustomCallBack.Close}, bindMenu = {CustomMenuItem.editor}) @DialogAnnotation @ModuleAnnotation(caption = "编辑人员信息", width = "800", height = "550") @ResponseBody public ResultModel<PersonNav> getPersonInfo(String personId) { ResultModel<PersonNav> resultModel = new ResultModel<PersonNav>(); return resultModel; } @MethodChinaName(cname = "添加人员") @RequestMapping(method = RequestMethod.POST, value = "AddPersonView") @FormViewAnnotation @APIEventAnnotation(bindMenu = {CustomMenuItem.add}, autoRun = true) @Disabled @ModuleAnnotation( caption = "添加人员信息", width = "370", height = "260") @ResponseBody public ResultModel<AddPerson> AddPerson(String orgId) { ResultModel<AddPerson> resultModel = new ResultModel<AddPerson>(); CtPerson person = new CtPerson(); person.setOrgId(orgId); resultModel.setData(new AddPerson(person)); return resultModel; } @MethodChinaName(cname = "保存成员信息") @RequestMapping(value = {"savePerson"}, method = {RequestMethod.GET, RequestMethod.POST}) @APIEventAnnotation(callback = {CustomCallBack.ReloadParent, CustomCallBack.Close}, bindMenu = CustomMenuItem.save) public @ResponseBody ResultModel<Boolean> savePerson(@RequestBody CtPerson person) { ResultModel<Boolean> userStatusInfo = new ResultModel<Boolean>(); getService().savePerson(person); return userStatusInfo; } @MethodChinaName(cname = "删除人员") @RequestMapping(value = {"delPerson"}, method = {RequestMethod.GET, RequestMethod.POST}) @APIEventAnnotation(callback = {CustomCallBack.Reload, CustomCallBack.ReloadParent}, bindMenu = CustomMenuItem.delete) public @ResponseBody ResultModel<Boolean> delPerson(String iD) { ResultModel<Boolean> userStatusInfo = new ResultModel<Boolean>(); getService().delPerson(iD); return userStatusInfo; } PersonService getService() { return EsbUtil.parExpression(PersonService.class); } } @PageBar // @GridAnnotation(event = CustomGridEvent.editor, customService = PersonService.class, customMenu = {GridMenu.Add, GridMenu.Delete, GridMenu.Reload}) public class PersonGridView { @CustomAnnotation(pid = true, hidden = true) String orgId; @CustomAnnotation(pid = true, hidden = true) String roleId; @CustomAnnotation(uid = true, hidden = true) String iD; @CustomAnnotation(caption = "用户名称", required = true) String name; @CustomAnnotation(caption = "账户信息", required = true) String account; @CustomAnnotation(caption = "邮箱") String email; @InputAnnotation(inputType = InputType.password) @CustomAnnotation(caption = "密码", required = true) String password; @CustomAnnotation(caption = "手机") String mobile; @CustomAnnotation(caption = "部门名称") String orgName; public PersonGridView(Person person) { this.iD = person.getID(); this.orgId = person.getOrgId(); this.name = person.getName(); this.account = person.getAccount(); this.password = person.getPassword(); this.mobile = person.getMobile(); this.email = person.getEmail(); Org org = null; try { org = OrgManagerFactory.getOrgManager().getOrgByID(person.getOrgId()); this.orgName = org.getName(); } catch (OrgNotFoundException e) { e.printStackTrace(); } } } @BottomBarMenu @FormAnnotation(bottombarMenu = {CustomFormMenu.Save, CustomFormMenu.Close}, customService = PersonService.class, col = 1) public class AddPerson { @CustomAnnotation(uid = true, hidden = true) String iD; @CustomAnnotation(caption = "用户名称", required = true) String name; @CustomAnnotation(pid = true, hidden = true) String orgId; @CustomAnnotation(pid = true, hidden = true) String roleId; @CustomAnnotation(caption = "账户信息", required = true) String account; @CustomAnnotation(caption = "邮箱") String email; @InputAnnotation(inputType= InputType.password) @CustomAnnotation(caption = "密码", required = true) String password; @CustomAnnotation(caption = "手机") String mobile; public AddPerson(Person person) { this.iD = person.getID(); this.orgId = person.getOrgId(); this.name = person.getName(); this.account = person.getAccount(); this.password = person.getPassword(); this.mobile = person.getMobile(); this.email = person.getEmail(); } }

(五)DSM建模工具DSM建模,百度百科是这样定义的:

特定域建模(Domain-specific modeling,DSM),是一种设计和开发系统(如电脑软件)的软件工程方法学。它系统使用图形化特定域语言(DSL),表现系统的各个方面。DSM的语言倾向于支持比通用建模语言更高级别的抽象,因此需要较少的努力和更少的底层细节来描述特定系统。

低代码技术应用可以通过提供更强的工具,提升程序员的代码效率。但其本质上也是一种特定场景下的软件描述方法,这个层面上低码技术和DSM思想是有其相通相同之处的,产品在设计之初就将DSM建模语言的构建以及工具支撑作为了底层支撑设计,将应用中积累的建模应用采用DSM的思想进行重构整合在底层打通。

我们将现有的资源类的工具,统一到仓库应用中,包括统一的物料库导入,统一的数据源(数据库,外部存储)管理。并通代码工厂的辅助构建统一到Contenxt(OneCode)的当前环境技术模型中。在各个特定的业务模型中,完成独立的聚合实体整合,以及相应的服务管理,并为相关的方法模型透视管理服务。在OneCode 的基础之上,摆脱传统的 代码模板与生成机制。实现代码向模型的逆向能力。将DSM设计能贯穿整个项目开发实施管理过程,打造结余真实的代码之上的建模语言。

(1)仓储建模

(2)聚合应用

(3)视图工厂

(4)支撑域

添加图片注释,不超过 140 字(可选)

(5)流程建模

添加图片注释,不超过 140 字(可选)

六,应用集成(1)内核最小集合集成(JS离线应用)设计器内核完全采用JS脚本完成,是独立的前端框架。内核版本包括:RAD 页面设计编辑器,xui运行运行脚本两部分。

添加图片注释,不超过 140 字(可选)

最小集合仅包含,页面设计及器以及插件框架。

设计界面集成:

下载开源包后,运行debug.html 即可打开编辑器。

添加图片注释,不超过 140 字(可选)

集成到自由应用时只需要,引入两个关键的js lib包即可集成到自有的应用。

<script type="text/javascript" src="/RAD/xui.js"></script> <script type="text/javascript" src="/RAD/index.js"></script> <script type="text/javascript"> var lang = (function () { var dft = 'zh-cn', map = { 'en-us': 'en', 'zh-cn': 'cn' }, n = navigator, l = (n.language || n.browserLanguage || '').toLowerCase(); return map[l] || map[dft]; })(); xui.include("xui.Locale." + lang + '.doc', "/RAD/Locale/" + lang + ".js", function () { xui.Module.load('RAD', function () { SPA = this; }, lang); });

运行支撑环境集成:打开:

设计完成的文件再应用环境中引入如下代码即可

<script type="text/javascript" src="/xui/js/xui-all.js"></script> <script type="text/javascript" src="./xuiconf.js"></script> <script type="text/javascript" src="/xui/Locale/cn.js"></script>

(2)团队协作版团队协作版是独立的服务器部署版,在官网上申请账号后,可以在独立的服务器上运行。启动后通过浏览器访问 http://demoserver:83 用管理员 sysadmin 登录:

首次登录 会进入默认的工程配置界面

配置工程

关联API

设定团队管理员

methodinfo(低代码平台将如何改变软件开发)

2. 如何做微信小程序查询类的?

序:北漂做了几年的程序猿,英语水平极差,所以在程序上没有太高的造诣,但是还是想把自己所能做的的记录下来。

下边来完成一个微信小程序的车辆违章查询,在最后我会放上源码链接,所以内容上就不对代码做太多解释,只说下思想。

1:数据来源,车辆违章查询的数据来源想到的就是三方接口,那么我选择的是以前做公众号开发时候时候的聚合数据(API数据接口_开发者数据定制),注册申请。

进入全国车辆违章查询可以看到三个接口:1:获取支持城市参数接口 2:请求违章查询接口3:接口剩余次数请求。有了这三个接口就可以实现一个简单的车辆违章查询了。

2:微信小程序,有了数据的来源就等于有了灵魂,之后就是怎样利用数据源来实现了,首先就是小程序的学习。安装以及创建项目。查看文档(https://mp.weixin.qq.com/debug/wxadoc/dev/?t=1476197488080)

个人建议先把文档看一遍,这一遍并不是要记住文档,而是要在脑子里对小程序有一个初步的印象,更重要的是建立一个索引目录,之后开发的时候能够根据目录索引到具体位置。

一遍文档看下来,首先想到的是需要哪些知识才能开发

懂一点html,css,js,每个页面包括一个js,ixml,wuss

之前有对react native (react native)了解点,发现在页面与数据交互上有很多的相似,建议有兴趣的可以看了解一下,有助于理解。

API方面因为之前做过公众号开发,所以看了一下应该是wxjs的接口开放。

安装创建工程根据文档来就好了,因为没有内测号就只能创建一个无appid的项目

下载IDE创建项目:MyCar

ui方面需要三个:主页,添加查询车辆信息页,查询页

在app.json中加入三个页面

"pages": [

"pages/home/home",

"pages/addcar/addcar",

"pages/query/query"

]

主页需要展示添加查询车辆列表以及添加车辆

点击添加车辆需转到添加页面

在wxml中添加按钮的组建对应的js中实现对页面的跳转

home.wxml:

<view wx:if="{{surplus >= 0}}">

<button type="default" bindtap="bindtapAdd" hover-class="other-button-hover"> 添加车辆 </button>

</view>

home.js:

bindtapAdd:function(){

wx.navigateTo({

url: '../addcar/addcar'

})

},

在添加页面要做的是将车辆信息缓存的微信的本地,那么就需要使用聚合的接口来获取支持的城市供用户选择,获取聚合的数据后需要做一个二级联动,由于还没有太多时间来研究wxcss所以页面做的比较粗糙。

当用户填好数据后存储到数据缓存,这里涉及到两个知识点一个是请求url一个是数据缓存

请求可查询城市数据

requestCitys:function(){

var page = this;

wx.request({

url: 'http://localhost:3000/wz/citys',

header: {

'Content-Type': 'application/json'

},

success:function(res){

var res = res.data;

page.analysisRes(res);

},

fail:function(res){

page.setData({

toastInfo:util.toErrMsg(0),

toastHidden:false

})

console.log(res);

}

})

}

保存用户数据并且退回到主界面

wx.setStorageSync('cars',cars);

wx.navigateBack();

用户在主界面需要将缓存的数据用列表形式展示并且点击列表后需要使用查询车辆违章接口进行查询

home.js

//加载列表数据

reloadData:function(){

var value = wx.getStorageSync('cars')

if (value) {

var cars = [];

var i = 0;

for(var key in value) {

cars[i]= value[key];

i++;

}

this.setData({

cars:cars

})

}

},

//跳转到查询页面

onclikItem:function(e){

var id = e.target.id;

var carname = this.data.cars[id].name

wx.navigateTo({

url: '../query/query?carname='+carname

})

},

home.wxml:

<scroll-view scroll-x="true">

<viewwx:for="{{cars}}" wx:for-index="idx" wx:for-item="car">

<view id="{{idx}}" bindtap="onclikItem">

<text id="{{idx}}">

{{car.name}}

</text>

<text id="{{idx}}">

{{car.showhphm}}

</text>

</view>

</view>

在查询页面需要调用查询接口

requestQuery:function(car){

var hphm = encodeURI(car.city.abbr+car.hphm)

var page = this;

wx.request({

url: 'http://localhost:3000/wz/query',

method:'POST',

data:{

key:page.data.AppKey,

city:car.city_code,

hphm:hphm,

hpzl:car.hpzl,

engineno:car.engineno,

classno:car.classno

},

header: {

// 'Content-Type': 'application/json'

},

success: function(res) {

var res = res.data;

if(res.resultcode == 200){

console.log(res.result.lists);

page.setData({

lists:res.result.lists

})

}else{

page.setData({

toastInfo:res.reason,

toastHidden:false

})

console.log(res);

}

},

fail:function(res){

page.setData({

toastInfo:util.toErrMsg(0),

toastHidden:false

})

console.log(res);

}

})

}

这样小程序的基本功能就算完成了,这里要说下的是小程序测数据与页面刷新很类似react native ,Page中的data数据改变,wxml中使用数据的的组件就会自动刷新,这个跟以往我做android ios 的略有区别,适应下就好了。

下面说下中转路由,这次选用的是node的express作为web服务器 数据库用嘛mongodb,这个是才接触的所以使用的也比较初级。

Node.js

Express - 基于 Node.js 平台的 web 应用开发框架

建议安装Homebrew这样会比较方便

Homebrew

Homebrew, Mac系统的包管理器,用于安装NodeJS和一些其他必需的工具软件。

/usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"

译注:在Max OS X 10.11(El Capitan)版本中,homebrew在安装软件时可能会碰到/usr/local目录不可写的权限问题。可以使用下面的命令修复:

sudo chown -R `whoami` /usr/localbrew install node

$ npm install express --save

创建web服务器MyCarServer,编辑器个人习惯用Sublime Text: The text editor you'll fall in love with

这里需要再下载两个扩展包用来实现post以及mongodb的连接

GitHub - expressjs/body-parser: Node.js body parsing middleware

$ npm install body-parser

GitHub - Automattic/mongoose: MongoDB object modeling designed to work in an asynchronous environment.

$ npm install mongoose

安装mongoldb这个我是看的视频,大家页可以自行百度

http://www.jikexueyuan.com/course/1976_1.html?ss=1

项目中创建models.js来驱动数据库

var config = require('./config.json');

// var uri = 'mongodb://username:password@hostname:post/databasename';

var host = config.host;

var port = config.port;

var dbName = config.dbname;

var uri = 'mongodb://' + host + ':' + port + '/' + dbName

var mongoose = require('mongoose')

console.log('uri:', uri)

mongoose.connect(uri);

var CarStatusScheme = new mongoose.Schema({

cachetime: Number,

resdata: String

})

var CarCitysScheme = new mongoose.Schema({

cachetime: Number,

resdata: String

})

var CarQueryScheme = new mongoose.Schema({

cachetime: Number,

resdata: String,

hphm: String

})

mongoose.model('CarStatus', CarStatusScheme);

mongoose.model('CarCitys', CarCitysScheme);

mongoose.model('CarQuery', CarQueryScheme);

在app.js中

var mongoose = require('mongoose');

require('./models.js');

在创建config.json用来做一些常规配置

{

"dbname": "mycar",

"port": "27017",

"host": "localhost",

"statuscache": 1000,

"cityscache": 1000,

"querycache": 1000,

"debug": true

}

在app.js中使用配置

var config = require('./config.json')

var debug = config.debug

get请求

//接口剩余请求次数查询

// 请求示例:http://v.juhe.cn/wz/status?key=xxxxxxx

// 请求参数说明:

// 名称 类型 必填 说明

// key string 是 应用APPKEY(应用详细页查询)

// dtype string 否 返回数据的格式,xml或json,默认json

// 返回参数说明:

// 名称 类型 说明

// error_code int 返回码

// reason string 返回说明

// data - 返回结果集

// surplus string 剩余次数

app.get('/wz/status', function(req, res) {

if (debug) {

http://console.info('http get /wz/status')

}

CarStatus.find({}, function(err, docs) {

if (err) {

console.error("CarStatus.find err:", err)

} else {

if (docs.length > 0) {

var carStatus = docs[0];

var curtime = Date.now();

var cachetime = carStatus.cachetime;

if (curtime - cachetime < statuscachetime * 1000) {

var resData = carStatus.resdata;

res.json(JSON.parse(resData))

} else {

requestJHStatus(res);

}

} else {

requestJHStatus(res);

}

}

});

});

post 请求

// 接口地址:http://v.juhe.cn/wz/query

// 支持格式:json/xml/jsonp

// 请求方式:post get

// 请求示例:http://v.juhe.cn/wz/query?city=SH&hphm=苏L50A11&engineno=123456&key=key

// 接口备注:因交管局线路迁移,即日起至四月底安徽,山东,杭州等省市偶尔出现临时维护,请关注

// 调用样例及调试工具:API测试工具

// 请求参数说明:

// 名称 类型 必填 说明

// dtype string 是 返回数据格式:json或xml或jsonp,默认json

// callback String 否 返回格式选择jsonp时,必须传递

// key string 是 你申请的key

// city String 是 城市代码 *

// hphm String 是 号牌号码 完整7位 ,需要utf8 urlencode*

// hpzl String 是 号牌类型,默认02,暂只支持小型车

// engineno String 否 发动机号 (根据城市接口中的参数填写)

// classno String 否 车架号 (根据城市接口中的参数填写)

// 返回参数说明:

// 名称 类型 说明

// province String 查询省份代码

// city String 查询城市代码

// hphm String 查询的号牌号码

// lists Array 违章列表

// date String 违章时间

// area String 违章地点

// act String 违章行为

// code String 违章代码(仅供参考,不一定有值)

// fen String 违章扣分(仅供参考,不一定有值)

// money String 违章罚款(仅供参考,不一定有值)

// handled String 是否处理,1处理 0未处理 空未知

app.post('/wz/query', function(req, res) {

if (debug) {

http://console.info('http post /wz/query')

}

console.log(req.headers['content-type'])

http://console.info('/wz/query req.body:', req.body)

// http://console.info('/wz/query req.data:', req)

var carquery = new CarQuery({

hphm: req.body.hphm,

cachetime: Date.now()

})

http://console.info('/wz/query hphm:', carquery.hphm)

CarQuery.find({

'hphm': carquery.hphm

}, function(err, docs) {

if (err) {

console.error("CarQuery.find err:", err)

} else {

if (docs.length > 0) {

var carQuery = docs[0];

var curtime = Date.now();

var cachetime = carQuery.cachetime;

if (curtime - cachetime < querycache * 1000) {

var resData = carQuery.resdata;

res.json(JSON.parse(resData))

} else {

requestJHQuery(req.body, res);

}

} else {

requestJHQuery(req.body, res);

}

}

});

});

post请求需要引入body-parse

var bodyParser = require('body-parser');

// parse application/x-www-form-urlencoded

app.use(bodyParser.urlencoded({

extended: false

}))

// parse application/json

app.use(bodyParser.json())

这里还有一个未解决的就是小程序中请求中如果设置

header: {

// 'Content-Type': 'application/json'

},

在web服务器中是接收不到body数据的,所以暂时的解决方式是注释 // 'Content-Type': 'application/json'

这样就算完成了基础功能

哎!不会文章表达还是微信(xiongandaqu)沟通吧

3. 如何解决FtpWebRequest基础连接已经关闭?

方法:去掉FTP服务器中的中文欢迎词或改成英文欢迎词就不会发生错误,这是微软的一个BUG。

代码:

public void Upload(string filename)

{

//IP

string FtpIP = System.Web.ConfiguratIOn.WebConfigurationManager.AppSettings["ftpIP"];

//用户名

string FtpUserName = System.Web.Configuration.WebConfigurationManager.AppSettings["ftpUsrName"];

//用户密码

string FtpPassord = System.Web.Configuration.WebConfigurationManager.AppSettings["ftpUsrPsw"];

FileInfo fileInf = new FileInfo(filename);

string uri = "ftp://" + FtpIP + "/SYS/" + fileInf.Name;

FtpWebRequest reqFTP;

// 根据uri创建FtpWebRequest对象

reqFTP = (FtpWebRequest)FtpWebRequest.Create(new Uri(uri));

// ftp用户名和密码

reqFTP.Credentials = new NetworkCredential(FtpUserName, FtpPassord);

// 默认为true,连接不会被关闭

// 在一个命令之后被执行

reqFTP.KeepAlive = false;

// 指定执行什么命令

reqFTP.Method = WebRequestMethods.Ftp.UploadFile;

// 指定数据传输类型

reqFTP.UseBinary = true;

// 上传文件时通知服务器文件的大小

reqFTP.ContentLength = fileInf.Length;

// 缓冲大小设置为2kb

int buffLength = 2048;

byte[] buff = new byte[buffLength];

int contentLen;

// 打开一个文件流 (System.IO.FileStream) 去读上传的文件

FileStream fs = fileInf.OpenRead();

try

{

// 把上传的文件写入流

//Stream strm = reqFTP.GetRequestStream();

Stream strm = reqFTP.GetRequestStream();

// 每次读文件流的2kb

contentLen = fs.Read(buff, 0, buffLength);

// 流内容没有结束

while (contentLen != 0)

{

// 把内容从file stream 写入 upload stream

strm.Write(buff, 0, contentLen);

contentLen = fs.Read(buff, 0, buffLength);

}

// 关闭两个流

strm.Close();

fs.Close();

}

catch (Exception ex)

{

throw ex;

}

}

4. invoke的用法?

invoke这个方法就是调用委托,MSDN上的解译是:Control.Invoke 方法在拥有此控件的基础窗口句柄的线程上执行委托。

重载列表--------------------------------------------------------------------------------名称 说明 Control.Invoke (Delegate) 在拥有此控件的基础窗口句柄的线程上执行指定的委托。 由 .NET Compact Framework 支持。

Control.Invoke (Delegate, Object[]) 在拥有控件的基础窗口句柄的线程上,用指定的参数列表执行指定委托。 由 .NET Compact Framework 支持。 具体参考请看:http://msdn.microsoft.com/zh-cn/library/30s4t80c(v=VS.80).aspx我的理解就是,用invoke调用用的委托方法,是被Controller控制的,如果Controller有错误,invoke就会报错,然后终止调用的委托,就和一个进程和线的关系差不多

5. dubbo?

一、dubbo配置之间的关系:

左边是服务提供方的相关配置,右边是服务消费方的相关配置。中间是两方的共享配置。下边是方法和方法参数的相关配置。

ReferenceConfig继承ConsumerConfig,ServiceConfig继承ProviderConfig。如果没有进行Reference和Service的配置,默认是Consumer和Provider的配置。

二、配置覆盖关系:

1、方法级优先,接口级次之,全局配置再次之。(级别小的优先)

2、如果级别一样,则消费方优先,提供方次之。

其中,服务提供方配置,通过URL经由注册中心传递给消费方。

(配置的查找顺序,其他retries,loadbalance,actives等类似)

三、标签:

四、举例

1、项目中的配置

dubbo.xml的配置如下:

<!-- 应用信息,用于计算依赖关系 -->

<dubbo:application name="basicInfoservice"/>

<!-- 使用zookeeper注册中心暴露服务地址 -->

<dubbo:registry protocol="zookeeper" address="${dubbo.registry.address}" register="${dubbo.registry.register}"/>

<!--使用dubbo协议,basicInfoservice应用的端口为20881-->

<dubbo:protocol name="dubbo" port="20881"/>

<!--提供方的超时时间为3s-->

<dubbo:provider timeout="3000"/>

<!--消费方的超时时间为3s-->

<dubbo:consumer check="false" timeout="3000"/>

<!--需要引用的服务-->

<dubbo:reference id="dictionaryFacade" interface="com.dmsdbj.itoo.singleTableMaintain.facade.DictionaryFacade" />

<!--需要暴露的服务-->

<dubbo:service id="studentFacade" interface="com.dmsdbj.itoo.basicInfo.Facade.StudentFacade" />

<!--studentFacade服务的超时时间为30s,addStudent方法的超时时间为60s-->

<dubbo:service id="studentFacade" interface="com.dmsdbj.itoo.basicInfo.facade.StudentFacade" timeout="30000"

loadbalance="roundrobin" >

<dubbo:method name="addStudent" timeout="60000"/>

</dubbo:service>

dubbo-server.properties配置如下:

dubbo.registry.address=zookeeper://192.168.22.156:2181?backup=192.168.22.154:2181,192.168.22.156:2182

dubbo.basicInfo.group=basicInfo

dubbo.basicInfo.version=1.0.0

dubbo.registry.register=false

上述实例,我们的全局的超时时间为3s,负载均衡策略为随机,student服务的超时时间为30s,负载均衡策略为轮询。addStudent的超时时间为60s。

2、

<dubbo:annotation package="com.dmsdbj.itoo.basicInfo.facade"/>

这段配置的作用是开启注解扫描。

开启注解之后,就可以使用@Reference和@Service来订阅服务或者暴露服务啦。需要注意的是@Service并不是Spring的注解,而是

dubbo的注解 import com.alibaba.dubbo.config.annotation.Service;

也可以说<dubbo:reference>标签+@Autowired等价于<dubbo:annotation package="">+@Reference。

6. 中如何调用com组件?

在 C++ 中,要调用 COM 组件,可以使用 COM 对象(Component Object Model,简称 COM)的 Dispatch 函数。Dispatch 函数是 COM 组件的接口函数,用于接收客户端代码的请求并执行相应的操作。

以下是一个简单的示例,演示如何使用 C++ 调用 COM 组件:

1. 创建 COM 对象:

```c++

#include <comtypes.h>

// 创建 COM 对象

IDITypeInfo *pTIInfo;

strcpy(pTIInfo, "MyTIInfo");

// 注册 COM 对象

COM_CREATE_TYPE_INFO(pTIInfo);

```

2. 获取 COM 对象的信息:

```c++

#include <comtypes.h>

// 获取 COM 对象的信息

IDITypeInfo *pTIInfo = (IDITypeInfo *)COM_ GetActiveTIInfo();

```

3. 调用 COM 组件的函数:

```c++

// 调用 COM 组件的函数

void MyTIFunction(int arg1, int arg2) {

// 处理客户请求

}

// 调用 COM 组件的函数

MyTIFunction(1, 2);

```

在上面的示例中,我们使用 `COM_ GetActiveTIInfo()` 函数获取当前活动的 TIDI 对象的信息,然后使用 `COM_CREATE_TYPE_INFO()` 函数注册一个 TIDI 类型的 COM 对象。最后,我们使用 `COM_ GetActiveTIInfo()` 函数获取当前活动的 TIDI 对象的信息,并调用其函数 `MyTIFunction()`。

需要注意的是,COM 组件的使用需要具备一定的 COM 编程知识和经验。如果不熟悉 COM,建议先学习 COM 的基本概念和编程技巧。

7. repo的格式?

[epel]

name=Extra Packages for Enterprise Linux 6 - x86_64

baseurl=http://mirrors.aliyun.com/epel/6/x86_64

http://mirrors.aliyuncs.com/epel/6/x86_64

#mirrorlist=https://mirrors.fedoraproject.org/metalink?repo=epel-6&arch=x86_64

failovermethod=priority

enabled=1

gpgcheck=0

gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-EPEL-6

[epel-debuginfo]

name=Extra Packages for Enterprise Linux 6 - x86_64 - Debug

baseurl=http://mirrors.aliyun.com/epel/6/x86_64/debug

http://mirrors.aliyuncs.com/epel/6/x86_64/debug

#mirrorlist=https://mirrors.fedoraproject.org/metalink?repo=epel-debug-6&arch=x86_64

failovermethod=priority

enabled=0

gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-EPEL-6

gpgcheck=0

[epel-source]

name=Extra Packages for Enterprise Linux 6 - x86_64 - Source

baseurl=http://mirrors.aliyun.com/epel/6/SRPMS

http://mirrors.aliyuncs.com/epel/6/SRPMS

#mirrorlist=https://mirrors.fedoraproject.org/metalink?repo=epel-source-6&arch=x86_64

failovermethod=priority

enabled=0

gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-EPEL-6

gpgcheck=0

免责声明:本文作者:“游客”,版权归作者所有,观点仅代表作者本人。本站仅提供信息存储分享服务,不拥有所有权。信息贵在分享,如有侵权请联系ynstorm@foxmail.com,我们将在24小时内对侵权内容进行删除。
(130)
爱奇艺会员免费账号(爱奇艺的会员不是免费
上一篇 2023年12月03日
北桥芯片(主板上的南桥芯片和北桥芯片是干
下一篇 2023年12月03日

相关推荐

  • 三星w589报价(华为路由器sw5200分几个版本)

    一个版本,WS5200全千兆版RTL芯片方案RTL8197FS+RTL8812BRH+RTL8367RB...

    2023年10月29日
  • a42(42a电流等于多少千瓦)

    答:在额定电压220伏中,42安可以承载9.240千瓦。根据电功率与电压和电流强度的定义公式P=UI=220伏×42安=9240瓦。...

    2023年10月30日
  • 二手笔记本电脑价格(预算在1600以内要求性价比高点)

    首先购买二手笔记本有风险,而且风险不小。如果你不是很了解笔记本的小白(例如不会自己装系统,不会自己拆机换固态),其实不建议购买二手笔记本,但是你一定要买,我推荐你去淘宝搜索笔吧评测室,不知道能否打开这个链接:...

    2023年11月05日
  • 华为c8500s(华为公司的发展历史)

    1987年,深圳成立了一家注册资金为21000元的民营企业,主营业务是为一家香港公司生产的PBX,即用户交换机做销售代理。这就是最早的华为。...

    2023年11月06日
  • adobe audition 3.0(Adobeaudition多轨音频两个音轨怎么合并)

    运行AdobeAudition3.0,切换到多轨,在音轨1上按鼠标右键--插入--音频,插入第1个单声道音频文件;在音轨2上按鼠标右键--插入--音频,插入第2个单声道音频文件(插入其他音轨相同),在音轨2、3、4....波形上按住鼠标右键,...

    2023年11月10日
  • samsungapps是什么(三星电视每次打开app都用不了)

    您可以先检查一下您这台电视的固件版本,方法:按遥控器项目键→选择支持→联系Samsung,查看当前固件版本号,固件升级方法,下面为您提供参考:【固件升级】...

    2023年11月12日
  • 四川发生非煤矿山顶板事故(怎么鉴别真假茅台)

    茅台酒是假酒的重灾区,现在的造假技术都特别高明,有不少人买茅台酒的人平时都不舍得喝,只是买回来当宝贝供着,最可怕的是藏了几年才发现是假酒。...

    2023年11月21日
  • qq号码采集器(QQ群的线报机器人怎么弄得)

    就是开发的一个软件而已,他们把自己网站的内容实时发布到群里。比如说这个找线报,他们网站就是采集全网线报的(应该是收集了很多网站,公众号之类的吧,然后实时更新),然后实时发到群里。自己做一个机器人就行了,易语言写的...

    2023年11月27日
  • 电脑下载(哪些音乐软件下载歌曲免费还好用)

    老猫是专注APP的分享的,曾经也接触过很多音乐软件是公认不错的。自从酷狗、网易、扣扣等音乐软件开启版权及付费等权限以后,很多音乐因为版权等原因是无法下载的。下面老猫,推荐几款音乐下载的软件。...

    2023年11月29日
  • ex文件怎么打开(exb是什么文件格式)

    1.EXB是一种电子书文件格式。2.EXB文件格式是由韩国的iRiver公司开发的,主要用于iRiver电子书阅读器上的电子书存储和阅读。它采用了压缩算法,可以将电子书的体积大大缩小,同时保持高质量的阅读体验。3.EXB文件格式目前已经被广泛...

    2023年12月02日
返回顶部