vesh

码农nodejs版本VESH框架,使用函数责任链模式 实现了 默认文件跳转,自定义错误页,空文件处理,URL解析,Querystring与Form参数解析,PostFiles解析,MVC自动映射,SQL自动服务化,可继承页面,静态文件,json,tjson,jsonp,tjsonp,string,void,xjson,xjosnp等等6种JSON格式,http与https等等操作

Usage no npm install needed!

<script type="module">
  import vesh from 'https://cdn.skypack.dev/vesh';
</script>

README

gcl

目录

Install

$ npm install vesh

码农村 nodejs VESH框架 通过详细的分层和良好的接口设计框架切分保证了每层内部的改动不会影响其他层的访问,而且保证了可持续性,可扩展性,节省了开发时间和人力

Introduction

vesh为同名C#类库的nodes翻译版本,总体上分为

  • VMCI vesh前端(View,ViewModel,Control(框架核心用于控件、事件、数据获取的绑定方案),Interface(ajax+ws)
  • ECMI vesh后端服务层(Entity,Control(框架核心用于过滤、分发、调用、数据获取、转换输出的绑定方案),Model,Interface(DB+Object+ws+cach))
  • SS 第三方服务层
  • VH 虚拟机+硬件

Here is an example on how to use it:

    //找个js 在它的同一个文件夹下放置好同名的npcf(可以复制test.npcf)、base.npcf和ni.npcf文件。然后把如下代码写入你的JS文件,并执行它 你就可以启动VESH框架了
    (function(VESH,V,C){
        V.isDebug = true;
        C.getApplicationConfigManager((err,cm)=>{
            try{
                var app = new VESH.App(cm);
                app.start(81);
            }catch(e){console.log(e);}
        });
    })(require('vesh/com/coooders/Project/VESH/V/Control/app'),require('gcl/com/coooders/common/tool'),require('gcl/com/coooders/io/config'));

从这个例子当中,我们可以知道:

  • VESH提供了一个httpServer可以start或者stop。
  • VESH依托GCL框架集按照提供的自定义配置文件npcf和ni.npcf 开始构建App所需要使用的类并完成他们的服务。

config

    {
        AppSettings:{},
        Middler:{
            'VESH.view': {
                pack: '',
                path: 'vesh/com/coooders/Project/VESH',
                method: 'constructor',
                mode: 'static',
                //基本日志信息 		
                'com.coooders.Project.VESH.Logger': {type:'Logger', mode: 'static', path: "gcl/com/coooders/io/log",method:"constructorbean",constructorparalength:"1",params: [
                        {type:'LogRecord',method:"constructor",params:[0,true,true,false]},
                        {name:'Lisener',type:'LogLisener',method:"constructor",params:[[
                            {type:'LogTypeTrigger',method:'constructor',params:[0,1]},
                            {type:'RegexTrigger',method:'constructor',params:['HttpServer:']}
                        ],{type:'LogRecord',method:"constructor",params:[0,true,true,true]},[{type:'FileResource',method:"constructor",params:['./log/HttpServer_{name}.log','yyyyMMddHH']}],true]},
                        {name:'Lisener',type:'LogLisener',method:"constructor",params:[[
                            {type:'LogTypeTrigger',method:'constructor',params:[0,1]},
                            {type:'RegexTrigger',method:'constructor',params:['VESH:']}
                        ],{type:'LogRecord',method:"constructor",params:[0,true,true,true]},[{type:'FileResource',method:"constructor",params:['./log/VESH_{name}.log','yyyyMMddHH']}],true]}            
                    ]
                },
                'com.coooders.Project.VESH.HttpModulers':{mode:'static', params:[
                    {type:'DefaultModuler',path:'~V/Control/modulers',params:['/abc.htm',true]},
                    {type:'HeaderModuler',path:'~V/Control/modulers',params:[{'Access-Control-Allow-Origin':'*','Server':'VESH.node/0.1.3','X-Powered-By':'com.coooders'}]},
                    {type:'FormModuler',path:'~V/Control/modulers'},
                    {type:'FilesModuler',path:'~V/Control/modulers',params:['./tmp',Math.pow(2,20)*10]},
                    {type:'CookieModuler',path:'~V/Control/modulers'},
                    {type:'EmptyModuler',path:'~V/Control/modulers'},
                    {type:'LoadModuler',path:'~V/Control/modulers',params:['com.coooders.project.esb']},
                    {type:'NiModuler',path:'~V/Control/modulers',params:[
                        [                    
                            {type:'FormFilter'},
                            {type:'SessionFilter',params:['.User;abc']},
                        ],{middler:true},"Ni"]},                
                    {type:'ActionModuler',path:'~V/Control/modulers'},
                    {type:'ViewModuler',path:'~V/Control/modulers',method:'constructorbean',constructorparalength:2,params:[
                        '/',{type:'StaticControler',method:'constructor',params:['htm;css;js;jpg;jpeg;png;gif;xml;ico;swf;eot;svg;ttf;woff']},
                        {param:'Controler',params:['void',{type:'VoidControler'}]},
                        {param:'Controler',params:['x',{type:'XControler'}]},
                        {param:'Controler',params:['json',{type:'JsonControler'}]},
                        {param:'Controler',params:['tjson',{type:'TJsonControler'}]},
                        {param:'Controler',params:['jsonp',{type:'JsonPControler',params:['_bk']}]},
                        {param:'Controler',params:['tjsonp',{type:'TJsonPControler',params:['_bk']}]},
                        {param:'Controler',params:['string',{type:'StringControler'}]},
                        {param:'Controler',params:['html',{type:'FormatPageControler',params:['html']}]},
                        {param:'Controler',params:['jhtml',{type:'JsonPageControler',params:['jhtml']}]}
                    ]}    
                ]},
                'com.coooders.Project.VESH.HttpModulers1':{mode:'static', params:[
                    //{type:'CacheModuler',path:'~V/Control/modulers'},                            
                ]},            
                'com.coooders.Project.VESH.SessionDataManagerFactory':{type:'SessionDataManagerFactory',method:'constructor',mode:'static',path:'~V/Control/session',params:[
                    {type:'SessionDataAdapter',method:'constructorbean','constructorparalength':1,mode:'static',params:[
                        {ref:'VESH.view/CookieResource'},
                        {param:'Resource',params:["aaa",{type:'ConstSessionSource',mode:'static',params:['aaa=2&bbb=3']}]},
                        {param:'Resource',params:[".User",{ref:'VESH.view/SecurityResource'}]},
                        {param:'Resource',params:[".Pers",{ref:'VESH.view/SecurityResource'}]}
                    ]},            
                    8,
                    "language"
                ]},
                "CookieResource":{type:'CookieSessionSource',mode:'static',path:'~V/Control/session'},
                "SecurityResource":{type:'SecuritySessionSourceDecorator',mode:'static',path:'~V/Control/session',params:[
                    {ref:'VESH.view/CookieResource'},
                    {type:'',path:'gcl/com/coooders/module/des3xcrypt',params:["dQ69muDQO5Xq2I0Q2278+ZTKq/JnecDk","wjG3Vwmk34U="]}
                ]}
            },
            Ni:{……}
        }
    }
  • 根据GCL的定义,Middler节点是IOC框架GCL.middler的专属节点可以通过getObjectByAppName('VESH.view','name')方式创建实例.
  • 所以VESH框架使用VESH.View作为基本的节点其中 com.coooders.Project.VESH.Logger,com.coooders.Project.VESH.HttpModulers,com.coooders.Project.VESH.SessionDataManagerFactory三个节点为VESH专属节点
  • com.coooders.Project.VESH.Logger 定义VESH的默认日志记录实例,其记录方式和位置根据是框架的还是VESH客户代码导致的错误分为 HttpServer_/VESH_开头的两个文件。
  • com.coooders.Project.VESH.HttpModulers 定义VESH的使用的解析器序列,设计上VESH使用责任链方式对一个每一个URL进行处理,譬如DefaultModuler负责处理默认路径,FormModuler负责将querystring,form,files参数设置到会话对象session上。
  • com.coooders.Project.VESH.SessionDataManagerFactory 定义了VESH的会话管理器工厂,它负责在每次会话请求都创建一个SessionDataManager实例,并调用SessionDataAdapter从Cookie\Memcache\Object等等方式同步会话信息

ni.npcf

    {
        "Ni":{
            'ajaxtest11': { 'command': 'select * from ac_case limit ?limit1;select ?limit1 as l1;', 'params': { 'limit1': {type:'Int'} }, 'template': 'template1' },
            'ajaxtest22': { 'command': 'SELECT top 10 *,@limit1 as "l1" FROM [dbo].[ssidb_User];select @limit1 as "l1";', 'params': { 'limit1':{type:'Int'} }, 'template': 'template2' },
            'update11': { 'command': 'update ac_case set DelFlag = 0 where DelFlag = 0;SELECT ROW_COUNT();', 'params': { 'limit1':{type:'Int'} }, 'template': 'template1' },
            'update22': { 'command': 'update [dbo].[ssidb_User] set Status = 1 where Status = 1;select @@RowCount;', 'params': { 'limit1':{type:'Int'} }, 'template': 'template2' },
            'ajaxtest33': { 'command': 'test', 'params': { 'limit1':{type:'Int'} }, 'template': 'template3' },
            'ajaxtest44': { 'command': 'insert into abc<a> (a,cacheValue) values (?a,?cacheValue);', 'params': { 'a':{type:'Int'},'cacheValue':{type:'String'} }, 'template': 'template5' },		
            'ajaxtest55': { 'command': 'select cacheValue from abc<a> where a=?a', 'params': { 'a':{type:'Int'},'cacheValue':{type:'String'} }, 'template': 'template5' },
            'ajaxtest66': { 'command': 'update abc<a> set cacheValue = ?cacheValue where a=?a', 'params': { 'a':{type:'Int'},'cacheValue':{type:'String'} }, 'template': 'template5' },
            'ajaxtest77': { 'command': 'delete from abc<a> where a=?a', 'params': { 'a':{type:'Int'},'cacheValue':{type:'String'} }, 'template': 'template5' },
            'ajaxtest11.Set': { 'command': 'insert into abc<cacheKey> (cacheKey,cacheValue) values (?cacheKey,?cacheValue);', 'params': { 'cacheKey':{type:'String'},'cacheValue':{type:'String'} }, 'template': 'template4' },
            'ajaxtest11.Cache': { 'command': 'select cacheValue from abc<cacheKey> where cacheKey=?cacheKey;', 'params': { 'cacheKey':{type:'String'} }, 'template': 'template4' }		
        }
    }
  • 根据GCL的定义,Ni节点是DB框架GCL.ni的专属节点 然后就可以通过template.excute('ajaxtest11',params,(err,result)=>{})的统一方式来进行mysql,mssql,memcached,mongodb,object方式的调用和自动缓存
  • VESH框架更进一步实现外部通过.json,.jsonp,.tjson,.tjsonp的方式直接调用ni框架里面的命令来返回数据,而不需要写任何nodejs代码。其安全性可由ajax中的会话参数保证。

action

  //可以在启动文件的同一文件夹下新建一个文件夹 Module
  //然后放入两个文件 action.js 和 index.html
  //action.js
  (function(V,M){
        module.exports = function(){
            var _ = this,__ = {};
            V.inherit.apply(_,[M.AAction,[]]);
            _.test = (req,rep,session)=>{
                session.status=new Date().toUTCString();
                return false;
            };
        };
    })(require('gcl/com/coooders/common/tool'),require('vesh/com/coooders/Project/VESH/V/Control/modulers'));
    //index.html
    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
    <html xmlns="http://www.w3.org/1999/xhtml" inherit1="/V/contentpage">
    <head id="Head1" runat="server">
        <meta name="renderer" content="webkit" />
        <title>VESH helloworld</title>
    </head>
    <body>
        <h1>Hello World</h1>
        <h2><%=name%></h2>
    </body>
    </html>
  • 然后直接访问http://127.0.0.1:81/Module/test.string 你会得到一个当前时间的UTC格式时间戳
  • 然后直接访问http://127.0.0.1:81/Module/index.html?name=baibing OK你会看到我的名字
  • 至此一个简单的MVC模式页面和应用完成了当然你也可以把页面的名字改成index2.html然后在action.js中添加一个方法 _.index = (req,rep,session)=>{session.status="index2";return false;};这样的返回结果与index2.html是一样的
  • action的调用由ActionModuler负责完成你可以在vesh/com/coooders/Project/VESH/V/Control/core-modulers中找到他
  • 因为它使用V.callback方法所以action方法有三种返回方式 return false;最后一个参数call(null,false);或者return function(call){call(null,false);};
  • 请永远不要返回true 否则会导致后面的ViewModuler无法执行也无法导出成页面,除非使用的是.x结尾由action完全处理rep.setHeader('content-type');session.end(200);session.writeStream(stream);等等方式
  • action的有一个默认方法preload(request,response,session) 是在本文件夹下的任何文件,方法,Ni命令被调用时首先触发的,可以做拦截或者参数过滤之用。
  • action的所有方法都具有(request,response,session)三个参数因为是V.callback调用的 所以实际上有第四个参数call。这里的request和response都是nodejs原生对象并未添加任何属性,而session对象则是VESH框架添加的会话信息管理实例,所有的扩展属性和方法都主要在这类上,modulers中的很多类也是用来在这个实例上添加属性的
  • action影响页面的有两种方式 1)session.status 默认值为url解析后的页面地址,如果status改为其他页面的值(无后缀)则实现MVC转向 2)session.dbresult 默认值为同名ni命令执行后的数据集[]如果没有那么为空数组 action可以修改或者添加session.dbresult中的值供后面的页面调用
  • ni命令,preload,action,页面的执行顺序是 如果文件夹下有action.js或者action.njs则调用其preload方法,然后查看有无同名ni命令(命令规则在下面)如果有那么执行ni命令,然后执行action中同名方法,然后根据status和url的后缀使用具体的view格式进行页面输出。

session

    //action.js
    (function(V,M){
            module.exports = function(){
                var _ = this,__ = {};
                V.inherit.apply(_,[M.AAction,[]]);
                _.test = (req,rep,session,call)=>{
                    console.log(session.url);//parse(url);
                    console.log(session.querystring);//query.parse(url.querystring);
                    console.log(session.form);//post parse
                    console.log(session.param(key));//union querystring & form
                    console.log(session.files);//S.PostFile(save,remove,filepath)[]
                    console.log(session.extend);//html
                    console.log(session.classtype);///Module/action
                    console.log(session.methodname);//com.coooders.Project.ESB.Module.test
                    console.log(session.status);//test
                    console.log(session.AppSettings(key));//返回配置节点AppSettings中的对象
                    console.log(session.config().getConfigValue(config,key))//返回配置节点的config/value的值
                    console.log(session.middler().getObjectByAppName(key,name))//返回getObjectByAppName值
                    session.log().info('OK'[,[],222]); //打印日志 debug,error,test,info,release等等
                    session.ni().excute('temp','command',{a:2,b:1},(err,result)=>V.tryC2(err,()=>{
                        if(result.hasData())
                        /**/
                        call(null,false);
                    },call));
                    session.user.login([true/false]);//会根据true,false清理loginTime UserID等等信息
                    console.log(session.user.isLogin());//ture/false
                    console.log(session.user.sessionID([sessionID]));//只可以设置一次的会话ID
                    console.log(session.user.userID([userID]));//可设置多次的用户ID
                    console.log(session.user.systemID([systemID]));//系统ID(前后台)
                    console.log(session.user.loginTime());//Date()
                    console.log(session.user.EntityID([EntityID]));//可设置角色ID
                    console.log(session.user.EIDS([EIDS]));//可设置角色串
                    session.data('abc').data('key')=333;
                    session.data('abc').data('key2')=444;
                    console.log(session.data('abc').name());//abc 其会话存储模式会根据npcf中SessionDataAdapter定义的属性中是否找到了对应abc的数据源而定,否则会使用默认数据源
                    console.log(session.data('abc').serialize());//{key:333,key2:444}
                    session.data('abc').clear();//清除数据
                    session.data('abc').clearCache();//清除缓存数据
                    rep.setHeader('Content-Type',MIME.html+";charset=utf-8");
                    session.end(200,"<html>");//这里的功能和return true差不多
                    session.write(……+'</html>');
                    ………………………………
                    session.clearWrite();
                    rep.setHeader('Content-Type',MIME.jpg);
                    session.end(200);//这里的功能和return true差不多
                    session.writeStream(F.createReadStream(path));
                    ………………………………
                    session.clearStreams();
                    session.dbresult = {a:2,b:3};
                    ………………………………
                    session.ni().excute('template','command',{a:11},(err,result)=>V.tryC2(err,()=>{
                        if(result.hasData())
                            session.dbresult.push(result.last());
                        call(null,false);
                    },call));
                    ……………………………
                    session.redirect(url)//302跳转
                    …………………………
                    session.status = new Date().toUTCString();
                    return false;
                };
            };
        })(require('gcl/com/coooders/common/tool'),require('vesh/com/coooders/Project/VESH/V/Control/modulers'));
  • session对象是vesh/com/coooders/Project/VESH/V/Control下的SessionDataManager类实例。
  • session对象统一了会话信息的存取方式和后台数据和服务的调用方式 使得业务代码的主要部分可以不随技术和后端的改进而变化。实现了代码的稳定和分离。
  • 其主要功能在于统一处理此次请求相关的属性、数据和上下文资源,还有会话信息。

session配置

  • 请注意test.npcf文件中定义SessionDataAdapter的一段json
     'com.coooders.Project.VESH.SessionDataManagerFactory':{type:'SessionDataManagerFactory',method:'constructor',mode:'static',path:'~V/Control/session',params:[
            {type:'SessionDataAdapter',method:'constructorbean','constructorparalength':1,mode:'static',params:[
                {ref:'VESH.view/CookieResource'},
                {param:'Resource',params:["aaa",{type:'ConstSessionSource',mode:'static',params:['aaa=2&bbb=3']}]},
                {param:'Resource',params:[".User",{ref:'VESH.view/SecurityResource'}]},
                {param:'Resource',params:[".Pers",{ref:'VESH.view/SecurityResource'}]}
            ]},            
            8,
            "language"
        ]},
        "CookieResource":{type:'CookieSessionSource',mode:'static',path:'~V/Control/session'},
        "SecurityResource":{type:'SecuritySessionSourceDecorator',mode:'static',path:'~V/Control/session',params:[
            {ref:'VESH.view/CookieResource'},
            {type:'',path:'gcl/com/coooders/module/des3xcrypt',params:["dQ69muDQO5Xq2I0Q2278+ZTKq/JnecDk","wjG3Vwmk34U="]}
        ]}
  • SessionDataAdapter使用了constructorbean方式使用CookieResource作为默认会话源,使用SecurityResource作为.User和.Pers的加密Cookie会话源,使用定值会话源作为aaa的值存储。
  • 当然也可以扩展新的会话源譬如 NiSessionSource = function(middler,appname,templatename,savename,loadname,clearname) 通过设置middler对象,Ni参数,templatename和save、load、clear方法可以将{key,value}数据存入ni框架支持各种DB和NoSQL存储中大大方便了会话信息的存储和扩展

SessionResource的扩展

    var S = require('vesh/com/coooders/Project/VESH/V/Control');
    S.**SessionSource = function(){
            var _ = this, __ = {};
            V.inherit.apply(_,[S.ASessionSource,[]]);
            _.load = (SessionDataManager,id,name,call)=>{call(null,{})};
            _.save = (SessionData,data,call)=>{call(null,'')};
            _.clear = (SessionData)=>{call(null,'')};
    }
  • 继承S.ASessionSource,分别实现load,save,clear三个方法就可以扩展一个新的Session会话源了
  • SessionDataManager是action中的session对象。
  • SessionData就是action中session.data(key)返回的对象 拥有sessionID()/name()/clear()/clearCache()/serialize()/data()等等方法是一个具体的会话数据和存取单元

ajax

    ni.npcf 中设置 'com.coooders.project.esb.Module.test': { 'command': 'select * from ac_case limit ?limit1;select ?limit1 as l1;', 'params': { 'limit1': {type:'Int'} }, 'template': 'template1' }
    http://localhost:81/Module/test.json?_n=template&limit1=10
  • 通过如上的URL就可以将ni.npcf中对应的com.coooders.project.esb.Module.test 命令通过json数组得到。
  • 有关com.coooders.project.esb的前缀是由test.npcf中 {type:'LoadModuler',path:'~V/Control/modulers',params:['com.coooders.project.esb']},定义的。
  • 而且URL中/Module/test.json会被解析成.Module.test 加上前置的命令名完成对web请求的URL解析,此前置命令名主要为了防止URL可以直接访问不带头部的ni命令。
  • 而且其输入的参数可以通过querystring和form方式作为参数自动填充params的值,也可以通过SessionFilter将sessionData中对应的会话信息放置入params中但是session中的参数都会以_开头 譬如 _User_UID,_User_SID,_User_EID,_User_EIDS,_User_PIDS,_User_LT就分别代表了sessionData.user的UserID,SystemID,EntityID,EIDS,PIDS,loginTime等等
  • Filter的扩展方式可见vesh/com/coooders/Project/VESH/V/Control/core-modulers下的FormFilter例子 V.inherit.apply(,[M.AFilter,[]]);然后扩展.fill = (req,rep,session,form)=>{form[key]=value;} 即可
  • ni框架的扩展方式可见GCL框架集ni框架DBFactory的扩展方式。

html

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
    <html xmlns="http://www.w3.org/1999/xhtml" inherit="/V/contentpage">
    <head id="Head1" runat="server">
        <meta name="renderer" content="webkit" />
        <title>VESH helloworld</title>
    </head>
    <body>
        <h1>Hello World</h1>
        <h2><%=name%></h2>
    </body>
    </html>

    ///V/contentpage文件定义
    (function(V,S){
        V.merge(module.exports,{
            Menu:
            '<div class="nav">'+
                '<h2>'+
                    '<b></b>'+
                    '关于****中心'+
                '</h2>'+
                '<dl class="curr">'+
                    '<dd>'+
                        '<a href="/Module/about/AboutUs.html" class="curr">关于我们</a>'+
                        '<a href="/Module/about/Rules.html">**规则</a>'+
                        '<a href="/Module/about/Questions.html">常见问题</a>'+
                        '<a href="/Module/about/Example.html">****示范条款</a>'+
                        '<a href="/Module/about/Price.html">****费用</a>'+
                        '<a href="/Module/about/ContactUs.html">联系方式</a>'+
                        '<a href="/Module/about/CheckCode.html">印章码查询</a>'+
                    '</dd>'+
                '</dl>'+
            '</div>'
        },S,true);
    })(require('gcl/com/coooders/common/tool'),require('./page'));

    ///V/page.js
    (function(V,S){
        V.merge(exports,{
            Header:
            '<meta charset="utf-8" />'+
            '<meta http-equiv="X-UA-Compatible" content="IE=edge" />'+
            '<meta name="viewport" content="user-scalable=no, width=device-width, initial-scale=1, maximum-scale=1" />'+
            '<meta content="yes" name="apple-mobile-web-app-capable" />'+
            '<meta content="black" name="apple-mobile-web-app-status-bar-style" />'+
            '<meta content="telephone=no" name="format-detection" />'+
            '<meta name="keywords" content="" />'+
            '<meta name="description" content="" />'+
            '<link rel="Stylesheet" href="../../Style/module/home/global.css" />'+
            '<div class="p_top">'+
                '<div class="p_logo">&nbsp;</div>'+
            '</div>',
            Footer:
            '<div class="p_bottom">'+
                '<ul class="p_list_contain p_bottom_contact" id="Ul1">'+
                    '<li data-index="0" class="p_li_even">'+
                        '<span vid="aboutus" class="p_bottom_contactspan click" name="contact"><a href="/Module/about/AboutUs.html">关于我们</a></span>'+
                    '</li>'+
                    '<li data-index="1" class="p_li_odd">'+
                        '<span vid="rules" class="p_bottom_contactspan click" name="contact"><a href="/Module/about/Rules.html">****规则</a></span>'+
                    '</li>'+
                    '<li data-index="1" class="p_li_odd">'+
                        '<span vid="rules" class="p_bottom_contactspan click" name="contact"><a href="/Module/about/Questions.html">常见问题</a></span>'+
                        '<li data-index="1" class="p_li_odd">'+
                            '<span vid="rules" class="p_bottom_contactspan click" name="contact"><a href="/Module/about/Example.html">****示范条款</a></span>'+
                        '</li>'+
                    '</li>'+
                    '<li data-index="2" class="p_li_even">'+
                        '<span vid="price" class="p_bottom_contactspan click" name="contact"><a href="/Module/about/Price.html">****费用</a></span>'+
                    '</li>'+
                    '<li data-index="3" class="p_li_odd">'+
                        '<span vid="contactus" class="p_bottom_contactspan click" name="contact"><a href="/Module/about/ContactUs.html">联系方式</a></span>'+
                    '</li>'+
                    '<li data-index="4" class="p_li_odd">'+
                        '<span vid="checkcode" class="p_bottom_contactspan click" name="contact"><a href="/Module/about/CheckCode.html">印章码查询</a></span>'+
                    '</li>'+
                '</ul>'+
                '<div class="p_bottom_rights"><span>版权所有:</span>****委员会 <span>ICP备案</span>ICP备****号-1</div>'+
            '</div>'
        },S,true);
    })(require('gcl/com/coooders/common/tool'),require('./scriptpage'));

    ///V/scriptpage
    exports.HeaderScript=
        '<style type="text/css">'+
            '.animate {'+
                'transition: all 0.3s;'+
                '-webkit-animation-timing-function: ease;'+
            '}'+
        '</style>';
    exports.FooterScript=
        '<script src="../../Scripts/ref/jquery-1.8.0.min.js" type="text/javascript"></script>'+
        '<script src="../../Scripts/VJ.min.js" type="text/javascript"></script>'+
        '<script src="../../Scripts/ni/ni.js" type="text/javascript"></script>'+
        '<script src="../../Scripts/config.js" type="text/javascript"></script>'+
        '<script type="text/javascript">var User = <%=user%>;console.log(User);</script>';
  • 目前的页面定义由npcf文件中的 {param:'Controler',params:['html',{type:'FormatPageControler',params:['html']}]},{param:'Controler',params:['jhtml',{type:'JsonPageControler',params:['jhtml']}]} 定义
  • FormatPageControler使用<%=%>进行动态数据填充,而且仅仅可以多级替换,不能实现<%{%><%}%>的复杂操作。主要原因是目前主要实现前端渲染,较少后端喷绘数据未来会实现express下标准的页面。
  • JsonPageControler完全使用Json格式定义页面,可以方便的完成插入的合并,目前还在测试中。
  • FormatPageControler中允许html节点的inherit获取指定的js/njs文件获取HeaderScript,Header,Menu,Footer,FooterScript属性并替换前(HeaderScript),标签后(Header,Menu),标签前(Footer,FooterScript) 三个位置。而且inherit节点中也允许放置<%=%> 进行替换操作
  • FormatPageControler中对<%=%>的替换,允许按照a.b.c的方式从session.dbresult,session,req,form中按照一级一级的方式进行替换。

https

Here is an example on how to use it:

    //找个js 在它的同一个文件夹下放置好同名的npcf(可以复制test.npcf)、base.npcf和ni.npcf文件。然后把如下代码写入你的JS文件
    //并且执行 certmake.bat 新建ca.key与ca.cert
    (function(VESH,V,C){
        V.isDebug = true;
        C.getApplicationConfigManager((err,cm)=>{
            try{
                var app = new VESH.HttpsApp(cm,F.readFileSync('./ca.key'),F.readFileSync('./ca.crt'));
                app.start(81);
            }catch(e){console.log(e);}
        });
    })(require('vesh/com/coooders/Project/VESH/V/Control/app'),require('gcl/com/coooders/common/tool'),require('gcl/com/coooders/io/config'));

从这个例子当中,我们可以知道:

  • VESH提供了一个httpsServer可以start或者stop。
  • VESH依托openssl使用openssl方法生成公钥与私钥例子。
  • 然后就可以正常使用Https服务了,特别地仍然可以使用gcl/com/coooders/net/tool进行https的请求。工具类本身是兼容的

debugging-and-reporting-problems

  • that is All
  • EMail:baibing0004@sohu.com
  • QQ:26342049

Running tests

  node vesh/test.js;

配置例子文件

vesh/test.npcf; vesh/ni.npcf;

Todo

  • 考虑Linux下cluster server功能的实现
  • 考虑使用volitary模板实现模板类页面方式继承