一、概述
在上一篇中,我们已经可以使用mime类型模块以及文件传输模块为客户端返回任何类型的文件,但目前能返回的只有静态的HTML,css等文件,而jsp等服务器端语言却可以通过<% %>标签来实现java的扩张,根据请求来指定返回给客户端的html,从而只需要有一个html模板,就可以返回无数个html页面,而不用一个一个页面的编写,然后根据请求路由各个HTML。
今天,我们要实现的就是类似jsp这样的html模板文件(当然,远没有jsp那般强大)。首先,得先介绍一下JSON(JavaScript Object Notation)
二、JSON
JSON是一种轻量级的数据交换格式,可用来替代xml成为服务端和客户端之间数据交换格式。程序解析起JSON数据来也非常快。下面是JSON的语法和一段示例:
- 数据在名称/值对中
- 数据由逗号分隔
- 花括号保存对象
- 方括号保存数组
{
"menu": {
"id": "file",
"value": "File",
"popup": {
"menuitem": [
{ "value": "New", "onclick": "CreateNewDoc()" },
{ "value": "Open", "onclick": "OpenDoc()" },
{ "value": "Close", "onclick": "CloseDoc()" }
]
}
}
}
从语法和示例我们可以看出:JSON具有两种结构,对象(使用{})和数组(使用[])
JSON基于JavaScript标准的一个子集,所以基于JavaScript的Node.js使用起JSON来是得天独厚。
三、开发步骤
项目依旧是延续着上一篇的TestFrame,但不会很涉及,主要是讲讲实现方法
1、创建data文件夹和data.json
首先,我们先来确定一下等会要显示的数据。和以前一样,今天的也是显示唐诗,JSON数据如下:
{
"jingyesi":{
"title":"静夜思",
"1":"床前明月光",
"2":"疑是地上光",
"3":"举头望明月",
"4":"低头思故乡"
},
"chunxiao":{
"title":"春晓"
"1":"春眠不觉晓",
"2":"处处闻啼鸟",
"3":"夜来风雨声",
"4":"花落知多少"
}
}
只为示例,所以只有两首。
2、创建tangshi.html模板
下面就是创建一个html的唐诗模板:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>唐诗</title>
<link href="./stylesheets/index.css" rel="stylesheet" type="text/css">
</head>
<body>
<nav>%title%</nav>
<div id="value">
<p>%1%</p>
<p>%2%</p>
<p>%3%</p>
<p>%4%</p>
</div>
</body>
</html>
现有文件目录结构如下:
红色方框里就是新添加的文件和文件夹。
3、创建render.js模板渲染函数
在有了模板以后,我们就要根据数据和模板来创建新的html,然后将此html文件返回给客户端,下面是render这个渲染函数(我们将其做成一个模块):
render.js
/**
* Created by Administrator on 2015/4/1.
*/
//文件模块
var fs = require('fs');
//获取mime模块
var mime = require("mime");
//获取response模块
var response = require("./response");
var render = function(res,filePath,dataSource,target){
//读取文件进行渲染
fs.readFile(filePath,function(err,data){
if(err){
console.log(err);
}else{
var targetData = dataSource[target];
//转换HTML模板,生成新的HTML
var dataString = data.toString();
dataString = dataString.replace("%title%",targetData["title"]);
dataString = dataString.replace("%1%",targetData["1"]);
dataString = dataString.replace("%2%",targetData["2"]);
dataString = dataString.replace("%3%",targetData["3"]);
dataString = dataString.replace("%4%",targetData["4"]);
response.response(res,filePath,dataString);
}
});
};
exports.render = render;
render函数参数说明:
res : response,用于响应客户端,此参数将传给response模块
filePath : html模板的路径
dataSource : JSON文件的数据源
target : 唐诗的名字(如chunxiao)
在这里,还用到了一个response模块,这是为了尽量不去改以前的代码,所以为render模块单独写了一个响应模块,代码如下:
response.js
/**
* Created by Administrator on 2015/4/1.
*/
//获取mime模块
var mime = require("mime");
var response = function(res,filePath,data){
res.writeHead(200,{ //响应客户端,将文件内容发回去
'Content-type':mime.lookup(filePath)}); //通过后缀名指定mime类型
res.end(data);
};
exports.response = response;
4、使用render
在这里要修改一下Luyou.js
首先是在文件开头加上:
//获取render模块
var render = require("./file/render");
//模板路径
var ts = "./file/tangshi.html";
//数据源路径
var data = "./data/data.json";
然后是Http服务器文件路由函数的修改,
//创建HTTP服务器
var server = http.createServer(function(req,res){
console.log(req.url); //在控制台打印请求
//判断URL,提供不同的路由
if(req.url == '/index' || req.url == '/') { //主页
index.index(res);
}
else if(req.url.substr(0,8) == '/tangshi'&& req.url.indexOf(".")<=0) {
//获取诗名
var name = req.url.substr(9); //获取/tangshi/以后的字符串,即诗名
//读取JSON文件内容
fs.readFile(data,function(err,data){
if(err){
console.log(err);
}else{
console.log(name);
var dataString = data.toString();
var dataJson = JSON.parse(dataString);
console.log(dataJson);
if(!dataJson[name]){ //如果没有诗存在,则跳到404 error
error404(res);
return;
}
render.render(res,ts,dataJson,name);
}
});
}
else { //访问其它静态文件,如/stylesheets/index.css
req.url = req.url.replace("/tangshi","");
Response(res,"./file"+req.url);
}
});
客户端查询唐诗的路径有两条:
http://localhost:3000/tangshi/jingyesi
http://localhost:3000/tangshi/chunxiao
然后在/tangshi
路径里会对url
进行处理,提取出诗名后进行render
处理,至于req.url.indexOf(".")<=0
是为了防止静态css文件也在这条路由路径处理。