最近公司准备把一个老项目的WEB端优化一下,打算用Nodejs做前端,这样可以和移动APP共用大部分的接口,减少后端的维护工作量。
本人小白一个,一直对前端也比较感兴趣,所以就负责这个项目的开发工作。
之前做了些功课,所以最后决定nodejs框架选择 express , 模板的话比较喜欢ejs ,前端框架就直接bootstrap + jquery
第一个问题就是想知道目录结构应该如何定义,我是按照express默认的目录结构设计的。想知道比较专业的目录结构应该是什么样的,或者是比较合理的。 下面我会把我的目录结构及文件内容及构成说一下,请大家帮忙指点一下
bin 是express 默认生成的
config 里面是一些配置文件和一些公共方法,下面会一个个介绍
logs 日志目录 主要是访问日志和请求服务端的请求URL和返回结果日志
other 这个没用,释放一些我自己临时写的东西,生产环境里没有这个
node_modules 这个就不解释了(我看有的说可以把这个去掉,目前还没有尝试)
public 静态文件目录,这个目录的话生产环境中都放到nginx目录下面了
routes 路由,我的路由是一个业务建立一个路由
views 模板,和路由类似,一个业务建立一个文件夹,相应的模板文件
下面就对每个文件详细介绍了
1.config 目录
dz_msg.js 里面是一些返回的提示信息
functions.js 里面是一些公共方法
reslogs 是log4j的配置
settings就是一些配置信息
2.logs 目录 里面是用户的访问日志,及 请求后台服务端结构的请求URL和返回结果的记录,方便查看,以后可以方便做分析和优化
3.routes 目录
4.views 目录
以上就是我的目录就够和文件构成, 希望专家们能够帮我提提意见, 本人小白一个,看看我这个项目怎么改进,能够更好。谢谢了
第二个问题就是, 我的APP.JS 还请专家给看写的是否合理, 对于一个互联网的产品来说还需要哪些中间件或者需要安全上有哪些考虑
var express = require('express');
var fs = require('fs');
var path = require('path');
var favicon = require('serve-favicon');
var logger = require('morgan');
var cookieParser = require('cookie-parser');
var session = require('express-session');
var bodyParser = require('body-parser');
var filestream = require('file-stream-rotator')
//加载配置文件
var settings = require('./config/settings');
//加载路由文件
var index = require('./routes/index');
var search = require('./routes/search');
var users = require('./routes/users');
var business = require('./routes/business');
var maps = require('./routes/maps');
var direct = require('./routes/direct');
var tourism = require('./routes/tourism');
var app = express();
//设置Express的模板文件类型、目录、后缀
app.set('views', path.join(__dirname, 'views'));
app.engine('.html', require('ejs').__express);
app.set('view engine', 'html');
//设置开发环境并记录日志
var logdir = path.join(__dirname, 'logs');
fs.existsSync(logdir) || fs.mkdirSync(logdir);
var alogstream = filestream.getStream({
date_format: 'YYYYMMDD',
filename: path.join(logdir, 'access-%DATE%.log'),
frequency: 'daily',
verbose: false
})
app.use(logger('combined', {stream: alogstream}));
//加载解析json中间件
app.use(bodyParser.json());
//加载解析urlencode中间件
app.use(bodyParser.urlencoded({ extended: false }));
//加载解析cookie中间件
app.use(cookieParser());
//加载静态文件目录设置
app.use(express.static(path.join(__dirname, 'public')));
//设置session
app.use(session({
//用来对session数据进行加密的字符串.这个属性值为必须指定的属性。
secret: settings.SESSION_SECRET,
//表示cookie的name,默认cookie的name是:connect.sid。
//name: 'bjbus.com',
//cookie过期时间,毫秒。
//cookie: {maxAge: 60000},
//指每次请求都重新设置session cookie,假设你的cookie是6000毫秒过期,每次请求都会再设置6000毫秒。
resave: true,
//是指每次请求都重新设置session cookie,假设你的cookie是6000毫秒过期,每次请求都会再设置6000毫秒。
saveUninitialized: true,
}));
app.use(function(req, res, next){
res.locals.title = settings.SITETITLE;
res.locals.keywords = settings.SITEKEYWORDS;
res.locals.description = settings.SITEDISCRIPTION;
var _user = req.session.userinfo;
if(_user){
res.locals.userinfo = _user;
}
next();
});
//设置路由指向
app.use('/', index);
app.use('/search', search);
app.use('/users', users);
app.use('/business', business);
app.use('/direct', direct);
app.use('/maps', maps);
app.use('/direct', direct);
app.use('/tourism', tourism);
module.exports = app;
第三个问题就是我不知道如何在用户登录后session的页面判断上怎么能够写的更加简洁,以下是我目前的写法, 但是这个每个需要判断的session的地方都要这么些,感觉有点累
第四个问题是, 在登录的时候我是这么实现的, 用户在进入登录页后,我先生成一个uuid 这个uuid 我是通过IP + 随机数 + SESSION_SECRET 然后MD5加密出来的,然后将这个值放到session中 , 用户登录时,需要提交用户名,密码 和 uuid ,服务端去验证这个uuid是否和session中的一致,如果一样证明没问题,然后再判断用户信息是否正确。下面是代码
登陆页
/* 登录页面 */
router.get('/login', function(req, res, next) {
if(req.session.userinfo){
res.render('error.html', {
errormsg: msg.is_login
});
return;
}
var uuid = functions.getClientIP(req) + functions.randomNum(false, 6) + settings.SESSION_SECRET;
uuid = functions.dz_md5(uuid);
req.session.uuid = uuid;
res.locals.title = "用户登录 - " + res.locals.title;
res.render('login.html', {
uuid: uuid
});
});
登录处理页
/* 登录处理 */
router.post('/doLogin/:u/:p/:uuid/:r', function(req, res, next) {
if(req.session.userinfo){
res.json({
errormsg: msg.is_login
});
return;
}
var u = req.params.u
,p = req.params.p
,uuid = req.params.uuid;
if(uuid == req.session.uuid){
if(functions.isEmpty(u) || functions.isEmpty(p)){
res.json({errorMsg: msg.user_error});
}else{
var param = [];
param.push("v_act=v_login")
param.push("v_mid=" + settings.Interface.mid);
param.push("v_pass=" + p);
param.push("v_uname=" + u);
functions.dz_http_get(param, function(data){
if(typeof data === 'string'){
res.json({errorMsg: data});
}else{
var userinfo = {
uid: data.uid,
uname: data.uname,
phone: data.phone
}
req.session.userinfo = userinfo;
req.session.uuid = null;
res.json(data);
}
});
}
}else{
res.json({errorMsg: msg.login_overtime});
}
});
目前只是刚刚开始,后续的问题可能还有很多,还请大家多多帮助!有问题会继续更新,大家拜托了!
继续更新遇到的问题 --- 0718
先来让大家看看我的http.get是怎么写的
dz_http_get: function(param, callback){
//param 是接口需要的参数
param = param.join("&");
param += "&v_sign=" + this.dz_md5(param+settings.Interface.key);
var url = settings.Interface.url + param;
logger.info(url);
http.get(url, function(response) {
if(response.statusCode == 200){
var resJson = "";
response.setEncoding('utf8');
response.on('data', function(data){
resJson += data;
});
response.on('end', function () {
logger.debug(resJson);
resJson = JSON.parse(resJson);
if(resJson.v_status == "00"){
return callback(resJson.v_data)
}else{
return callback(resJson.v_scontent)
}
});
}else{
return callback(msg.response_err)
}
}).on('error', function(e) {
return callback(msg.request_err)
});
},
目前我遇到了这么一个问题,我提交给服务端接口的URL 如果里面包含中文,则node.js的http.get 返回的就是400错误。如果中文encode就没事儿了, 包含中文的链接在浏览器中都是没问题的,只是在node中报错,还请大神看看这个是什么问题
http://xxxxxx?v_act=v_ecpeople&v_mid=10005&v_pic=10007510000000000001&v_pid=46272&v_pname=%E9%98%BF%E6%96%AF%E9%A1%BF&v_ptel=13800000001&v_tel=13671378601&v_type=1&v_uid=1&v_sign=a69bc72211cb8da82dc02467742fb80a
http://xxxxxx?v_act=v_ecpeople&v_mid=10005&v_pic=10007510000000000001&v_pid=46272&v_pname=阿斯顿&v_ptel=13800000001&v_tel=13671378601&v_type=1&v_uid=1&v_sign=a69bc72211cb8da82dc02467742fb80a
是这样…
你这里nodejs做的应该算中间端。毕竟前端一般指你express里的views,nodejs以及express算后端更合适,只不过人家的nodejs及express通常访问的是数据库,而你访问的是另外一组api。
有一点是可以提醒一下的:你得花1个小时琢磨一下express中connect的机制,也就是中间件机制到底是怎么一回事。中间件就是帮助你处理大片api需要同样的前置或后置操作的情况的。
我们直接采用nodejs写的api操作数据库,前端用SPA,比你的方式更进一步。不过我们是从0开始,比较方便这样设计,具体情况得具体分析。