java转nodejs_纯Java⽹站开发改造为nodejs混合编程
早已对纯JAVA版的⽹站不满了,不管是繁重的代码编写量,和⽆谓的3层代码编写都让我提不起兴趣。但是提到nodejs我就有兴趣来做了,原来的⽹站是放到云服务器上的,由于CPU和内存的限制进⼀步影响了⽹站速度和承载量。达到什么程度呢,就是3个⼈同时应⽤就会造成访问慢或卡死。
于是我想到nodejs将原来⽹站重写。将来就会加速⽹站和体现并发数优势。很多⼈反对我这样做,说nodejs不适合重逻辑的部分,但好了,89%的应⽤都是直接从⽤户获得参数直接传透到数据库,为啥要写那么多代码,什么时候运⾏过其他计算。偶尔也是对参数进⾏个加减⽽已。为啥不将⼏百⾏代码缩减到⼏⾏。
既然要动⼿就开始,准备好nodejs,在官⽹下在nodejs1.2X安装好之后,下在javascript编辑器,或⽂本都⾏。我喜欢⽤⽂本直接编辑。
罗列了以下⼏个步骤:
1.安装nodejs mysql包(⽹上很多教程注意先安装git)
2.修改java⼯程⽂件中的web,添加跨域反问,并将跨域限制为本机
3.修改原⼯程jquery的ajax调⽤,使⽤访问本机127.0.0.1:1337端⼝访问
4.提供nodejs直接调⽤数据库的调⽤⽅法
5.修改调⽤返回的处理
最后就是写⼀个⼯具在原⽹站上进⾏500个轮询访问的效率查询,⽤以鉴定以前的效率和现在效率的差别。
这棵树就是我们需要改造的原因。原来的反问原理是,通过spring->访问controller->访问helper层->访问dao层->访问mysql->再依次将结果json返回页⾯处理。
上⾯就是全部步骤,其实我说错了,上⾯还不是整个过程。因为树是存在⼀张表中的。其中只有id,pried,name,leve,orderid等,所以关系都是锁在同⼀张表⾥,意味着要把所有树排列好⼀次拿出来是可以的。只要按默认顺序将树整个解析出来即可。但⽬前存在客户要求树也要按顺序列出来,也就是按order指定的顺序排列,那么⼀次将树拿出来解析就不可以了。
因此我采⽤先将根结点读数据库拿出来,在⽣成根结点界⾯的时候程序回调再去查询所有⼦节点,并从数据库返回结果⽣成整棵树。
这样本来⼀次调⽤却变成了N次调⽤,往返于服务器之间,登陆⼏个⽤户打开⼏次页⾯我的程序基本就慢的要死。
第⼀步介绍:我只介绍注意事项即可,其他的请搜索⽹上吧,⽽且都有很好的⽂章。安装好nodejs使⽤npm装载mysql模块是报错的,因为没装git,使⽤git后才能安装,输⼊以下命令
npm install felixge/node-mysql
完成安装mysql;
完成之后试写mysql功能简单调⽤⼀下:
varmysql= require('mysql');
atePool({connectionLimit:30,host:'localhost',user:'root',password:xxxx});
pool.query('SELECT * FROM zd.alga_cs;',function(err, rows, fields) {if(err)throwerr;console.log('The solution is: ', rows);
});
调⽤完成后看⼀下你是否能读出结果,测试成功则nodejs和mysql模块都装好了。
第⼆步:修改java原来的tomcat,因为在⼀个页⾯下以前⽤jquery的ajax调⽤spring对应的controller,
所以现在需要改成调⽤nodejs本地下的⼀个端⼝。我设置为127.0.0.1:1337下来访问我定义的nodejs代码块。
第⼀就直接修改了,例如将如下:
$.ajax({ async:false,type:"post", url:"UnDeparment.do",data:"", dataType:"text", success:function(msg){
mydata=eval("("+msg+")"); // alert(msg); $.each(mydata,function(idx,item){
unuser = unt; });
改成:
$.ajax({ async:false, type:"get",url:"127.0.0.1:1337/employee_getUnDepartment",data:"", dataType:"text",
success:function(msg){ mydata=eval("("+msg+")"); // alert(msg);
$.each(mydata,function(idx,item){ unuser = unt; });
127.0.0.1:1337/employee_getUnDepartment是直接可以返回json串的,怎么到这⾥就不⾏了呢?!原来还需要改造⼀下java的l配置,和加⼊两个jar包才⾏。
⽹上下载:cors-filter-2.4.jar和java-property-utils-1.9.1.jar;放⼊项⽬⼯程⾥的libs⽬录下,并引⽤这两个包。并将如下代码加到l⾥:
CORS
s.CORSFilter
cors.allowOrigin
cors.supportedMethods
GET,POST,HEAD,PUT,DELETE
cors.supportedHeaders
Accept,Origin,X-Requested-With,Content-Type,Last-Modified
Set-Cookie
cors.supportsCredentials
true
CORS
/*
注意我写的是127.0.0.1,也就是说我允许跨域到本机127.0.0.1位置。设置完了后再次调⽤,怎么回事,nodejs控制台已经返回了查询结果,但IE报⼀个ajax错误,查了之后发现如果是跨域访问,则需要返回的内容加上⽂件头。于是在返回结果的模块⾥加了头如下:
res.writeHeader(200,{'Access-Control-Allow-Origin':'*'//先写header否则返回⽆效在跨域访问时}) ;
加上这句,返回的串就可以显⽰到原来的界⾯上。速度嘛,当然⽐以前块⼏百毫秒,但调试变简单了,Ctrl+C终⽌程序,按上键显⽰上句命令,回车就完成了再次启动nodejs程序。
⽽且不受以前tomcat的影响,只要程序是nodejs⾥的,直接关闭nodejs再启动调试,使⽤者基本感觉不到你在⼀步步调试程序,他们其他的java应⽤⾥的程序还正常执⾏。
第三步修改ajax调⽤为nodejs远程:
$.ajax({async:false, type:"get",url:"127.0.0.1:1337/node_employee_getsubtree_do",
data:"citylist="+session_citylist+"&did="+id,success:function(msg){
alert(msg); }
});
这⾥有⼀个坑,就是type:get;如果你不注意原来⽤的是post的话,那么在nodejs处理⽐较复杂,因为post是流发送,也就是有个开始投送,到接收完毕的过程,在nodejs⾥需要处理开始,和回调函数,这样整个改造过程就⽐较⿇烦了。因为没有牵扯到需要post的表单,所以直接⽤get,否则参数会接收不到。当然如果你⽤了express的话当然可以⽤⾥⾯包含的接收post包装好的⽅法。
第四步提供调⽤subtree的nodejs⽅法:
//调⽤⼦树if(pathname=="/node_employee_getsubtree_do")
{varstr=arg.citylist;vardid=arg.did;varsubtree="";pool.query('select
idcity,cityName,b.departmentid,departmentName,departmentlimit,ployeeId) count from zd.city as a left outer join zd.department as b on a.idcity=b.cityId left outer ployee 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 derid asc ;',function(err, rows, fields) {if(err)throwerr;
subtree= JSON.stringify(rows);
res.writeHeader(200,{'Access-Control-Allow-Origin':'*'//先写header否则返回⽆效在跨域访问时}) ;
});
}
这⾥有两个坑,不⼩⼼你就掉⾥⾯了,第⼀个坑就是返回json串的⽅法,在nodejs⾥把结果集合改成json是⽤JSON.stringifv();⽅法格式化结果集。第⼆个坑就是Header必须写在前⾯,否则跨域不接受数据。我写的*是允许所有操作(GET
UPDATE DELETE POST等)跨域提供数据。
第五步,修改JAVA程序适合调⽤返回nodejs程序:
其实这步根本不需要做,为什么还需要这步,是因为,以前java调⽤dao返回结果结集的时候字段名称有⼤写有⼩写,有混合写的。但⽤nodejs调⽤后直接都是数据库⾥怎么写的字段名返回就是怎么写的。所以departMent有可能变成department,因此要详细核对⼀下,这个坑我已经掉进去过了。
这就是⼀个简单的混合程序完成了。但只是⽐java的快了⼀点点,那么怎么优化呢?下⾯介绍⼀下优化。
优化思路:
减少数据库调⽤à减少ajax调⽤
这个⼤⽅向⾛,⾸先是否使⽤redis,想了半天,还是算了,只是为了优化⼀棵树,何必动⽤神器。⾃⼰搞个HashTabls算了。⾸先采⽤变量来优化基础查询,如下:
res.writeHeader(200,{'Access-Control-Allow-Origin':'*'//先写header否则返回⽆效在跨域访问时}) ;//判断主树是否需要缓⼨
if(condmaintree!=str) {condmaintree=str;// console.log('citylist: ', str);pool.query('select
idcity,cityName,b.departmentid,departmentName,departmentlimit,ployeeId) count from zd.city as a left outer join zd.department as b on a.idcity=b.cityId left outer ployee 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
derid asc ;',function(err, rows, fields) {if(err)throwerr;console.log('读数据库! ');memmaintree= JSON.stringify(rows);
}else{console.log('直接返回!');
}
可以看出采⽤了nodejs全局变量condmaintree,因为所有⼈只有权限不同的才会需要重新加载树,所以可以这样做,改完之后只有第⼀次读取需要查数据库,否则直接http返回存在condmaintree⾥的json串。⼦树也是这样优化的,但字树的分⽀读取次数很多,需要很多全局变量,这不切合实际。怎么办,引⽤⾃⼰编写的HashTable,nodejs版如下HashTable.js:
varsize=0;varentry=newObject();
exports.add=function(key , value)
{if(!ainsKey(key))
{size++ ;
}entry[key] = value;
}
access转mysql教程视频{ainsKey(key) ?entry[key] :null;
}
{ainsKey(key) && (deleteentry[key] ) ) {size--;
}
}
{return(keyinentry);
}
{for(varpropinentry)
{if(entry[prop] == value)
{return true;
}
}return false;
}
{varvalues=newArray();for(varpropinentry) {values.push(entry[prop]);
}returnvalues;
}
{varkeys=newArray();for(varpropinentry) {keys.push(prop);
}returnkeys;
}
{returnsize;
}
exports.clear=function()
{size=0;entry=newObject();
}
调⽤过程如下:
varMhashTable= require('./HashTable.js');
//调⽤⼦树if(pathname=="/node_employee_getsubtree_do")
{varstr="";varcitylist=arg.citylist;vardid=arg.did;varsubtree="";if(citylist=="") {str+=" idcity =-1";
}else{str+=" idcity =";place(/,/g," or idcity =");str+=citylist;
}Value(did); //获得变量如果为null则访问数据库if(subtree==null) {pool.query('select
idcity,cityName,b.departmentid,departmentName,departmentlimit,ployeeId) count from zd.city as a left outer join zd.department as b on a.idcity=b.cityId left outer ployee 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 derid asc ;',function(err, rows, fields) {if(err)throwerr;subtree=
JSON.stringify(rows);MhashTable.add(did,subtree); //将结果存⼊hashtableconsole.log('哈希没到!: ',subtree);
res.writeHeader(200,{'Access-Control-Allow-Origin':'*'//先写header否则返回⽆效在跨域访问时}) ;
});
}else{
res.writeHeader(200,{'Access-Control-Allow-Origin':'*'//先写header否则返回⽆效在跨域访问时}) ;console.log('哈希到!:
',subtree);
}
}
这样做以后,⾸次60次的ajax调⽤确实访问了数据库,但第⼆次的刷新树的时候就不会调⽤数据库了。但这也不是最终的⽅法,我还是决定要去掉远程调⽤,那么在index.jsp框架页⾯⾥引⼊HashTable.js,但这个版本和nodejs⽤的稍微有点不同。代码如下:
HashTable.js
functionHashTable()
{
var size = 0;
varentry = new Object();
this.add = function (key , value)
{
if(!ainsKey(key))
{
size ++ ;
}
entry[key] = value;
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论