从零开始学_JavaScript_系列(27)——myblog的优化【1】样式表分离、localStorage
http://blog.csdn.net/qq20004604/article/details/52167293
以上优化是从前端方式优化的;
这篇是在后端方面添加访问记录和计数的功能。
(42)博客的优化(2)——用fs模块来记录访问情况
讲道理说呢,我觉得用mysql来记录访问情况更好一点,不过为了学习使用fs模块,我这里就使用fs模块好了。
需求:
①以ip为参考;
②重复ip两次访问时间间隔在一小时内的,算一次访问,并且更新最新访问时间;
③同一ip两次访问时间间隔超过1个小时的,算是一次新的访问;
④只保留最近一小时的访问记录;(具体实施时,采取下次添加新的访问记录时,删除超过1个小时的记录);
步骤:
①首先,无论访问哪个页面时,都应该对访问ip进行处理,因此打开app.js,在所有路由之前添加如下代码:
var visitCount = require('./models/visit');
app.use('/', visitCount);
这段代码的意思是,无论你访问什么路径,都先交给visitCount这个模块进行处理;
②在models文件夹下建立visit.js文件;
首先,我们打算利用fs模块,那么要引入;
其次,路由模块也得正常引入;
第三,我们要让无论是什么路径都能处理,因此要在路径时使用“/:xxx”这样的方式,来匹配任何路径;
第四,要支持响应任何类型请求,比如get、post等,因此应该用all;
因此写下以下代码:
var fs = require("fs");
var express = require('express'); // 调用express模块
var router = express.Router(); // 调用模块的Router方法
router.all("/:anyurl", function (req, res, next) {
//处理代码
next(); //交给之后的路由继续处理
})
module.exports = router;
这里没有写处理代码,我们需要将对访问进行记录的代码,放在处理代码的位置,即next()命令之前;
③处理访问记录;
第一个,我们要能获取访问ip,方法是:
req.connection.remoteAddress
其次,我们要能读取文件,这个文件存储了总的访问次数和最近一小时的访问ip;
文件以json格式存储,方便JSON.parse()解析,因此存储时需要将对象转为JSON字符串,即使用JSON.stringify()命令;
第三,为了方便,存储时间时,将Date类型对象转为毫秒的number类型;
第四,调用fs.readFile来读取,fs.writeFile来写入;
第五,要清除过期的访问记录
声明一个函数,他有一个方法:
function visitCount() {
this.visitCheck = function (ip) {
fs.readFile("./LastVisitIP.json", "utf8", function (err, data) {
if (err) {
throw err;
}
// 因此读取的文件可能存在字符串开头是空白字符,如果不移除则无法解析
// 推测是因为UTF8格式的txt文件会在开头占用三个字节;
data = data.replace(/^\s*/, "");
var obj = JSON.parse(data);
// 先检查当前的,如果时间过期(一小时),则删除这条访问记录
var nowTime = new Date().getTime();
for (var i in obj) {
if (i != "visitNumber" & nowTime - obj[i] > 3600000) {
delete obj[i];
}
}
if (ip in obj) { //如果还有记录,说明是重复访问
console.log("IP:" + ip + ", last visit time is " + new Date(obj[ip]))
} else { //否则是非重复访问
obj[ip] = nowTime; //添加访问记录,形式是key为ip,val为访问时间转为毫秒后的形式
obj.visitNumber++; //访问计数+1
console.log("IP:" + ip + " is the first visit.The visit time is " + new Date(obj[ip]));
}
//将新的数据写入
fs.writeFile("./LastVisitIP.json", JSON.stringify(obj), "utf8", function (err) {
if (err) {
throw err;
}
})
})
};
}
使用时,生成一个他的实例,然后调用它的visitCheck方法,参数传当前访问的ip;
var count = new visitCount();
count.visitCheck(req.connection.remoteAddress);
将以上代码放在路由中的next()之前,便能满足我们的需求。
var fs = require("fs");
var express = require('express'); // 调用express模块
var router = express.Router(); // 调用模块的Router方法
router.all("/:anyurl", function (req, res, next) {
var count = new visitCount();
count.visitCheck(req.connection.remoteAddress);
next();
})
function visitCount() {
this.visitCheck = function (ip) {
fs.readFile("./LastVisitIP.json", "utf8", function (err, data) {
if (err) {
throw err;
}
// 因此读取的文件可能存在字符串开头是空白字符,如果不移除则无法解析
// 推测是因为UTF8格式的txt文件会在开头占用三个字节;
data = data.replace(/^\s*/, "");
var obj = JSON.parse(data);
// 先检查当前的,如果时间过期(一小时),则删除这条访问记录
var nowTime = new Date().getTime();
for (var i in obj) {
if (i != "visitNumber" & nowTime - obj[i] > 3600000) {
delete obj[i];
}
}
if (ip in obj) { //如果还有记录,说明是重复访问
console.log("IP:" + ip + ", last visit time is " + new Date(obj[ip]))
} else { //否则是非重复访问
obj[ip] = nowTime; //添加访问记录,形式是key为ip,val为访问时间转为毫秒后的形式
obj.visitNumber++; //访问计数+1
console.log("IP:" + ip + " is the first visit.The visit time is " + new Date(obj[ip]));
}
//将新的数据写入
fs.writeFile("./LastVisitIP.json", JSON.stringify(obj), "utf8", function (err) {
if (err) {
throw err;
}
})
})
};
}
module.exports = router;