小男孩‘自慰网亚洲一区二区,亚洲一级在线播放毛片,亚洲中文字幕av每天更新,黄aⅴ永久免费无码,91成人午夜在线精品,色网站免费在线观看,亚洲欧洲wwwww在线观看

分享

純Java網(wǎng)站開發(fā)改造為nodejs混合編程

 春和秋榮 2019-06-25

早已對(duì)純JAVA版的網(wǎng)站不滿了,不管是繁重的代碼編寫量,和無(wú)謂的3層代碼編寫都讓我提不起興趣。但是提到nodejs我就有興趣來(lái)做了,原來(lái)的網(wǎng)站是放到云服務(wù)器上的,由于CPU和內(nèi)存的限制進(jìn)一步影響了網(wǎng)站速度和承載量。達(dá)到什么程度呢,就是3個(gè)人同時(shí)應(yīng)用就會(huì)造成訪問(wèn)慢或卡死。

         于是我想到nodejs將原來(lái)網(wǎng)站重寫。將來(lái)就會(huì)加速網(wǎng)站和體現(xiàn)并發(fā)數(shù)優(yōu)勢(shì)。很多人反對(duì)我這樣做,說(shuō)nodejs不適合重邏輯的部分,但好了,89%的應(yīng)用都是直接從用戶獲得參數(shù)直接傳透到數(shù)據(jù)庫(kù),為啥要寫那么多代碼,什么時(shí)候運(yùn)行過(guò)其他計(jì)算。偶爾也是對(duì)參數(shù)進(jìn)行個(gè)加減而已。為啥不將幾百行代碼縮減到幾行。

       既然要?jiǎng)邮志烷_始,準(zhǔn)備好nodejs,在nodejs.org官網(wǎng)下在nodejs1.2X 安裝好之后,下在javascript編輯器,或文本都行。我喜歡用文本直接編輯。

    羅列了以下幾個(gè)步驟  :

1.      安裝nodejs mysql   (網(wǎng)上很多教程注意先安裝git

2.      修改java工程文件中的web,添加跨域反問(wèn),并將跨域限制為本機(jī)

3.      修改原工程jqueryajax調(diào)用,使用訪問(wèn)本機(jī)127.0.0.1:1337端口訪問(wèn)

4.      提供nodejs直接調(diào)用數(shù)據(jù)庫(kù)的調(diào)用方法

5.      修改調(diào)用返回的處理

最后就是寫一個(gè)工具在原網(wǎng)站上進(jìn)行500個(gè)輪詢?cè)L問(wèn)的效率查詢,用以鑒定以前的效率和現(xiàn)在效率的差別。

這棵樹就是我們需要改造的原因。原來(lái)的反問(wèn)原理是,通過(guò)spring->訪問(wèn)controller->訪問(wèn)helper->訪問(wèn)dao->訪問(wèn)mysql->再依次將結(jié)果json返回頁(yè)面處理。

上面就是全部步驟,其實(shí)我說(shuō)錯(cuò)了,上面還不是整個(gè)過(guò)程。因?yàn)闃涫谴嬖谝粡埍碇械?。其中只?/span>id,pried,name,leve,orderid等,所以關(guān)系都是鎖在同一張表里,意味著要把所有樹排列好一次拿出來(lái)是可以的。只要按默認(rèn)順序?qū)湔麄€(gè)解析出來(lái)即可。但目前存在客戶要求樹也要按順序列出來(lái),也就是按order指定的順序排列,那么一次將樹拿出來(lái)解析就不可以了。

因此我采用先將根結(jié)點(diǎn)讀數(shù)據(jù)庫(kù)拿出來(lái),在生成根結(jié)點(diǎn)界面的時(shí)候程序回調(diào)再去查詢所有子節(jié)點(diǎn),并從數(shù)據(jù)庫(kù)返回結(jié)果生成整棵樹。

這樣本來(lái)一次調(diào)用卻變成了N次調(diào)用,往返于服務(wù)器之間,登陸幾個(gè)用戶打開幾次頁(yè)面我的程序基本就慢的要死。

第一步介紹:我只介紹注意事項(xiàng)即可,其他的請(qǐng)搜索網(wǎng)上吧,而且都有很好的文章。安裝好nodejs使用npm裝載mysql模塊是報(bào)錯(cuò)的,因?yàn)闆]裝git,使用git后才能安裝,輸入以下命令

npm install felixge/node-mysql

完成安裝mysql

完成之后試寫mysql功能簡(jiǎn)單調(diào)用一下:

var mysql  = require('mysql');



var pool  = mysql.createPool({

  connectionLimit : 30,

  host            : 'localhost',

  user            : 'root',

  password        : xxxx

});
 
pool.query('SELECT * FROM zd.alga_cs;', function(err, rows, fields) {

  if (err) throw err;

  console.log('The solution is: ', rows);

});

       調(diào)用完成后看一下你是否能讀出結(jié)果,測(cè)試成功則nodejsmysql模塊都裝好了。

 

       第二步:修改java原來(lái)的tomcat,因?yàn)樵谝粋€(gè)頁(yè)面下以前用jqueryajax調(diào)用spring對(duì)應(yīng)的controller,所以現(xiàn)在需要改成調(diào)用nodejs本地下的一個(gè)端口。我設(shè)置為127.0.0.1:1337下來(lái)訪問(wèn)我定義的nodejs代碼塊。

       第一就直接修改了,例如將如下:

 

$.ajax({ async:false,type:"post", url:"employee.getUnDeparment.do",data:"", dataType:"text", success:function(msg){ mydata=eval("("+msg+")"); // alert(msg); $.each(mydata,function(idx,item){ unuser = item.count; });

       改成:

$.ajax({ async:false, type:"get",url:"http://127.0.0.1:1337/employee_getUnDepartment",data:"", dataType:"text", success:function(msg){ mydata=eval("("+msg+")"); // alert(msg); $.each(mydata,function(idx,item){ unuser = item.count; });

       然后就不出數(shù)據(jù)了,按下IEF12,看到提示CORS錯(cuò)誤!nodejs寫的http模塊使用http:// 127.0.0.1:1337/employee_getUnDepartment是直接可以返回json串的,怎么到這里就不行了呢?!原來(lái)還需要改造一下javaweb.xml配置,和加入兩個(gè)jar包才行。

       網(wǎng)上下載:cors-filter-2.4.jarjava-property-utils-1.9.1.jar;放入項(xiàng)目工程里的libs目錄下,并引用這兩個(gè)包。并將如下代碼加到web.xml:

 

   <filter>

       <filter-name>CORS</filter-name>

       <filter-class>com.thetransactioncompany.cors.CORSFilter</filter-class>

       <init-param>

           <param-name>cors.allowOrigin</param-name>

           <param-value>http://127.0.0.1</param-value>

       </init-param>

       <init-param>

           <param-name>cors.supportedMethods</param-name>

           <param-value>GET,POST,HEAD,PUT,DELETE</param-value>

       </init-param>

       <init-param>

           <param-name>cors.supportedHeaders</param-name>

<param-value>Accept,Origin,X-Requested-With,Content-Type,Last-Modified</param-value>

       </init-param>

       <init-param>

           <param-name>cors.exposedHeaders</param-name>

           <param-value>Set-Cookie</param-value>

       </init-param>

       <init-param>

           <param-name>cors.supportsCredentials</param-name>

           <param-value>true</param-value>

       </init-param>

   </filter>

    <filter-mapping>

       <filter-name>CORS</filter-name>

       <url-pattern>/*</url-pattern>

</filter-mapping>

 

注意我寫的是127.0.0.1,也就是說(shuō)我允許跨域到本機(jī)127.0.0.1位置。設(shè)置完了后再次調(diào)用,怎么回事,nodejs控制臺(tái)已經(jīng)返回了查詢結(jié)果,但IE報(bào)一個(gè)ajax錯(cuò)誤,查了之后發(fā)現(xiàn)如果是跨域訪問(wèn),則需要返回的內(nèi)容加上文件頭。于是在返回結(jié)果的模塊里加了頭如下:

res.writeHeader(200,{

  'Access-Control-Allow-Origin' : '*'  // 先寫header 否則返回?zé)o效在跨域訪問(wèn)時(shí)

}) ;

加上這句,返回的串就可以顯示到原來(lái)的界面上。速度嘛,當(dāng)然比以前塊幾百毫秒,但調(diào)試變簡(jiǎn)單了,Ctrl+C終止程序,按上鍵顯示上句命令,回車就完成了再次啟動(dòng)nodejs程序。

而且不受以前tomcat的影響,只要程序是nodejs里的,直接關(guān)閉nodejs再啟動(dòng)調(diào)試,使用者基本感覺不到你在一步步調(diào)試程序,他們其他的java應(yīng)用里的程序還正常執(zhí)行。

 

第三步修改ajax調(diào)用為nodejs遠(yuǎn)程:

$.ajax({async:false, type:"get",url:"http://127.0.0.1:1337/node_employee_getsubtree_do", data:"citylist="+session_citylist+"&did="+id,success:function(msg){

alert(msg); }

});

 

這里有一個(gè)坑,就是type:get;如果你不注意原來(lái)用的是post的話,那么在nodejs處理比較復(fù)雜,因?yàn)?/span>post是流發(fā)送,也就是有個(gè)開始投送,到接收完畢的過(guò)程,在nodejs里需要處理開始,和回調(diào)函數(shù),這樣整個(gè)改造過(guò)程就比較麻煩了。因?yàn)闆]有牽扯到需要post的表單,所以直接用get,否則參數(shù)會(huì)接收不到。當(dāng)然如果你用了express 的話當(dāng)然可以用里面包含的接收post包裝好的方法。

 

第四步提供調(diào)用subtreenodejs方法:

//調(diào)用子樹

if(pathname=="/node_employee_getsubtree_do") {

  var str = arg.citylist;

  var did = arg.did;

  var subtree = "";

 pool.query('select idcity,cityName,b.departmentid,departmentName,departmentlimit,count(c.employeeId) count  from zd.city as a left outer join zd.department as b on a.idcity=b.cityId left outer join zd.employee c on b.departmentId = c.departmentId  where 1 =1 and ('+str+')  and b.pre='+ did +' and b.level=1  group by idcity,cityName,b.departmentid,departmentName,departmentlimit order by a.idcity asc,b.orderid asc ;', function(err, rows, fields) {

      if (err) throw err;
            subtree = JSON.stringify(rows);
     res.writeHeader(200,{

        'Access-Control-Allow-Origin' : '*'  // 先寫header 否則返回?zé)o效在跨域訪問(wèn)時(shí)

      }) ;



      res.end(subtree);

     });

 

  }

這里有兩個(gè)坑,不小心你就掉里面了,第一個(gè)坑就是返回json串的方法,在nodejs里把結(jié)果集合改成json是用JSON.stringifv();方法格式化結(jié)果集。第二個(gè)坑就是Header必須寫在前面,否則跨域不接受數(shù)據(jù)。我寫的*是允許所有操作(GET UPDATE DELETE POST等)跨域提供數(shù)據(jù)。

 

第五步,修改JAVA程序適合調(diào)用返回nodejs程序:

其實(shí)這步根本不需要做,為什么還需要這步,是因?yàn)?,以?/span>java調(diào)用dao返回結(jié)果結(jié)集的時(shí)候字段名稱有大寫有小寫,有混合寫的。但用nodejs調(diào)用后直接都是數(shù)據(jù)庫(kù)里怎么寫的字段名返回就是怎么寫的。所以departMent有可能變成department,因此要詳細(xì)核對(duì)一下,這個(gè)坑我已經(jīng)掉進(jìn)去過(guò)了。

 

這就是一個(gè)簡(jiǎn)單的混合程序完成了。但只是比java的快了一點(diǎn)點(diǎn),那么怎么優(yōu)化呢?下面介紹一下優(yōu)化。

優(yōu)化思路:

       減少數(shù)據(jù)庫(kù)調(diào)用à減少ajax調(diào)用

這個(gè)大方向走,首先是否使用redis,想了半天,還是算了,只是為了優(yōu)化一棵樹,何必動(dòng)用神器。自己搞個(gè)HashTabls算了。首先采用變量來(lái)優(yōu)化基礎(chǔ)查詢,如下:

res.writeHeader(200,{

  'Access-Control-Allow-Origin' : '*'  // 先寫header 否則返回?zé)o效在跨域訪問(wèn)時(shí)

}) ;



//判斷主樹是否需要緩寸

if(condmaintree!=str) {

  condmaintree = str;

  // console.log('citylist: ', str);

  pool.query('select idcity,cityName,b.departmentid,departmentName,departmentlimit,count(c.employeeId) count  from zd.city as a left outer join zd.department as b on a.idcity=b.cityId left outer join zd.employee c on b.departmentId = c.departmentId  where 1 =1 and ('+str+')  and b.level=0 group by idcity,cityName,b.departmentid,departmentName,departmentlimit  order by a.idcity asc,b.orderid asc ;', function(err, rows, fields) {

    if (err) throw err;

     console.log('讀數(shù)據(jù)庫(kù)! ');

    memmaintree = JSON.stringify(rows);

    res.end(memmaintree); //數(shù)組和json之間的數(shù)據(jù)轉(zhuǎn)換

 });

} else {

  console.log('直接返回!');

  res.end(memmaintree);

}

 可以看出采用了nodejs全局變量condmaintree,因?yàn)樗腥酥挥袡?quán)限不同的才會(huì)需要重新加載樹,所以可以這樣做,改完之后只有第一次讀取需要查數(shù)據(jù)庫(kù),否則直接http返回存在condmaintree里的json串。子樹也是這樣優(yōu)化的,但字樹的分支讀取次數(shù)很多,需要很多全局變量,這不切合實(shí)際。怎么辦,引用自己編寫的HashTable,nodejs版如下HashTable.js

 

 

var size = 0;

var entry = new Object();



exports.add = function (key , value)

{

    if(!this.containsKey(key))

    {

        size ++ ;

    }

    entry[key] = value;

}



exports.getValue = function (key)

{

    return this.containsKey(key) ? entry[key] : null;

}



exports.remove = function ( key )

{

    if( this.containsKey(key) && ( delete entry[key] ) )

    {

        size --;

    }

}



exports.containsKey = function ( key )

{

    return (key in entry);

}



exports.containsValue = function ( value )

{

    for(var prop in entry)

    {

        if(entry[prop] == value)

        {

            return true;

        }

    }

    return false;

}



exports.getValues = function ()

{

    var values = new Array();

    for(var prop in entry)

    {

        values.push(entry[prop]);

    }

    return values;

}



exports.getKeys = function ()

{

    var keys = new Array();

    for(var prop in entry)

    {

        keys.push(prop);

    }

    return keys;

}



exports.getSize = function ()

{

    return size;

}



exports.clear = function ()

{

    size = 0;

    entry = new Object();

}

 

調(diào)用過(guò)程如下:

var MhashTable = require('./HashTable.js');
//調(diào)用子樹

if(pathname=="/node_employee_getsubtree_do") {

  var str = "";

  var citylist = arg.citylist;

  var did = arg.did;

  var subtree = "";

  if(citylist=="") {

    str += " idcity =-1";

  } else {

    str +=" idcity =";

    citylist= citylist.replace(/,/g," or idcity =");

    str+=citylist;

  }

  subtree = MhashTable.getValue(did); //獲得變量如果為null則訪問(wèn)數(shù)據(jù)庫(kù)

  if(subtree == null) {

    pool.query('select idcity,cityName,b.departmentid,departmentName,departmentlimit,count(c.employeeId) count  from zd.city as a left outer join zd.department as b on a.idcity=b.cityId left outer join zd.employee c on b.departmentId = c.departmentId  where 1 =1 and ('+str+')  and b.pre='+ did +' and b.level=1  group by idcity,cityName,b.departmentid,departmentName,departmentlimit order by a.idcity asc,b.orderid asc ;', function(err, rows, fields) {

      if (err) throw err;

      subtree = JSON.stringify(rows);

      MhashTable.add(did,subtree); //將結(jié)果存入hashtable

      console.log('哈希沒找到!: ', subtree);

      res.writeHeader(200,{

        'Access-Control-Allow-Origin' : '*'  // 先寫header 否則返回?zé)o效在跨域訪問(wèn)時(shí)

      }) ;

      res.end(subtree);

     });

  } else {

    res.writeHeader(200,{

      'Access-Control-Allow-Origin' : '*'  // 先寫header 否則返回?zé)o效在跨域訪問(wèn)時(shí)

    }) ;

    console.log('哈希找到!: ', subtree);

    res.end(subtree);

  }

}

       這樣做以后,首次60次的ajax調(diào)用確實(shí)訪問(wèn)了數(shù)據(jù)庫(kù),但第二次的刷新樹的時(shí)候就不會(huì)調(diào)用數(shù)據(jù)庫(kù)了。但這也不是最終的方法,我還是決定要去掉遠(yuǎn)程調(diào)用,那么在index.jsp框架頁(yè)面里引入HashTable.js,但這個(gè)版本和nodejs用的稍微有點(diǎn)不同。代碼如下:

HashTable.js

functionHashTable()

{

    var size = 0;

    varentry = new Object();

    this.add = function (key , value)

    {

        if(!this.containsKey(key))

        {

            size ++ ;

        }

        entry[key] = value;

    }

    this.getValue = function (key)

    {

        return this.containsKey(key) ?entry[key] : null;

    }

    this.remove = function ( key )

    {

        if( this.containsKey(key) && (delete entry[key] ) )

        {

            size --;

        }

    }

    this.containsKey = function ( key )

    {

        return (key in entry);

    }

    this.containsValue = function ( value )

    {

        for(var prop in entry)

        {

            if(entry[prop] == value)

            {

                return true;

            }

        }

        return false;

    }

    this.getValues = function ()

    {

        var values = new Array();

        for(var prop in entry)

        {

            values.push(entry[prop]);

        }

        return values;

    }

    this.getKeys = function ()

    {

        var keys = new Array();

        for(var prop in entry)

        {

            keys.push(prop);

        }

        return keys;

    }

    this.getSize = function ()

    {

        return size;

    }

    this.clear = function ()

    {

        size = 0;

        entry = new Object();

    }

}

 

改造index.jsp 加入下列代碼:

<scripttype="text/javascript">

//樹緩存

var subtreeHashTabls = new HashTable();

</script>

 

在具體調(diào)用的方法里加入hashtable查詢的過(guò)程,如下:

function getsubTree(id) {

var result = subtreeHashTabls.getValue(id);

var str = "";

if(result ==null) { //alert("遠(yuǎn)程取!");

$.ajax({async:false, type:"get",url:"http://127.0.0.1:1337/node_employee_getsubtree_do",data:"citylist="+session_citylist+"&did="+id,success:function(msg){

subtreeHashTabls.add(id,msg);// alert(msg);

}}); }

result =subtreeHashTabls.getValue(id);

var mydata=eval(result);

…}

 

經(jīng)過(guò)這樣的改造后,只需要讀取一次樹,其他時(shí)候讀取樹完全由內(nèi)存里的HashTable讀取,根本都不需要訪問(wèn)ajax跟服務(wù)器發(fā)生交互。

改造完畢后,我的頁(yè)面首次加載比原來(lái)快1秒,再次加載快3秒,當(dāng)然并發(fā)量我并沒有測(cè)試,應(yīng)該部署后會(huì)比原來(lái)強(qiáng)大許多,這就是nodejs優(yōu)勢(shì),當(dāng)然HashTable也盡了很大的力。

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購(gòu)買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶 評(píng)論公約

    類似文章 更多