前言
之前利用net模块创建的服务器是比较麻烦的,今天我们用node.js中的http模块搭建服务器
需要创建的文件,用图片展示
1.先写好配置文件server.conf
port=12306
page_path=page
static_file_type=.html|.js|.css|.jpg|.png|.gif|.ico|.svg
web_path=web
log_path=log
log_name=server.log
2.利用config.js处理好配置文件
const fs = require("fs")
//读取配置文件,将它分割成数组
const confs = fs.readFileSync("./server.conf").toString().split("\r\n")
const configObj = {}
//处理配置信息
for(var i = 0; i < confs.length; i++){
var temp = confs[i].split("=")
if(temp.length < 2){
continue
}else{
configObj[temp[0]] = temp[1]
}
}
//静态文件处理
if(configObj.static_file_type){
configObj.static_file_type = configObj.static_file_type.split("|")
}else{
throw new Error("配置文件异常,缺少:static_file_type")
}
//导出模块
module.exports = configObj
3.连接数据库dao.js
var mysql = require("mysql")
function connection(){
var con = mysql.createConnection({
host:"127.0.0.1",
port:"3306",
user:"root",
password:"123456",
database:"school"
})
return con
}
module.exports.connection = connection;
4.各个数据表操作(student.js)
var db = require("./dao")
function all(success) {
var sql = "select * from student"
var con = db.connection()
con.connect()
con.query(sql, function (error, res) {
if (error == null) {
success(res)
} else {
console.log(error)
}
})
con.end()
}
function classAndAge(num, age, success) {
var con = db.connection()
var sql = "select * from student where num = ? and age = ?;"
var arr = [num, age]
con.connect()
con.query(sql, arr, function (error, res) {
if (error == null) {
console.log(success(res))
success(res)
} else {
console.log(error)
}
})
con.end()
}
function passAndName(name, pass,success) {
var con = db.connection()
var sql = "select * from student where num = ? and password = ?;"
var arr = [name, pass]
con.connect()
con.query(sql, arr, function (error, res) {
if (error == null) {
success(res)
}else {
console.log(error)
}
})
con.end()
}
module.exports = {
all,
passAndName,
classAndAge
}
5.总加载器loader.js
var fs = require("fs")
var config = require("./config")
var pathMap = new Map()
//读取web下的所有文件路径
var files = fs.readdirSync(config.web_path)
//循环遍历web文件,将每个子加载器的模块集合
for(var i = 0; i < files.length; i ++){
var temp = require("./"+config.web_path+'/'+files[i])
if(temp.path){
for(var [k,v] of temp.path){
if(pathMap.get(k) == null){
pathMap.set(k,v)
}else{
var errMsg = "url path异常,url:"+k;
throw new Error(errMsg)
}
}
}
}
module.exports = pathMap
6.子加载器loginController.js
var student = require("../service/studentService")
var url = require("url")
var path = new Map()
function getData(request,response){
student.all(function(res){
response.writeHead(200)
response.write(JSON.stringify(res))
response.end()
})
}
function login(request,response){
var params = url.parse(request.url,true).query
if(!params.user){
//POST请求
request.on("data",function(data){
var user = data.toString().split("&")[0].split("=")[1];
var pass = data.toString().split("&")[1].split("=")[1];
student.passAndName(user ,pass,function(res){
if(res.length > 0){
response.writeHead(302,{"location":"index.html","Set-Cookie":"id="+res[0].id}) //重定向
response.end("ok")
}else{
response.end("error")
}
})
})
}else{
//GET请求
student.passAndName(params.user ,params.pass,function(res){
if(res.length > 0){
// response.writeHead(302,{"location":"index.html"}) //重定向
response.end("ok")
}else{
response.end("error")
}
})
}
}
path.set("/getData",getData)
path.set("/login",login)
module.exports.path = path
7.拦截器 filterLoader.js
var fs = require("fs")
var config = require("./config")
var filterSet = []
var files = fs.readdirSync(config.filter_path)
for(var i = 0; i < files.length; i ++){
var temp = require("./"+config.filter_path+'/'+files[i])
filterSet.push(temp)
}
module.exports = filterSet
8.子拦截器loginFilter.js
var url = require("url")
var config = require("../config")
var typeArr = config.static_file_type
function loginFilter(req,res){
var pathName = url.parse(req.url).pathname;
if(pathName == "/login.html" || pathName == "/login" || staticFile(pathName)){
return true
}
if(req.headers.cookie){
var cookies = req.headers.cookie.split(";")
for(var i = 0; i < cookies.length; i++){
if(cookies[i].split("=")[0].trim() == "id"){
return true
}
}
}
res.writeHead(302,{"location":"/login.html"})
res.end()
return false
}
//是否静态文件封装(跳过html文件)
function staticFile(pathName) {
for (var i = 0; i < typeArr.length; i++) {
var temp = typeArr[i]
if(temp == '.html'){
continue
}
if (pathName.indexOf(temp) == pathName.length - temp.length) {
return true
}
}
return false
}
module.exports = loginFilter
9.主文件index.js
var http = require("http")
var url = require("url")
var config = require("./config")
var typeArr = config.static_file_type
var fs = require("fs")
var loader = require("./loader")
var log = require("./log")
var filter = require("./filterLoader")
http.createServer(function (request, response) {
var pathName = url.parse(request.url).pathname
var isStatic = staticFile(pathName)
log(pathName)
for(var i = 0; i < filter.length; i++){
var flag = filter[i](request,response)
if(!flag){
return
}
} //拦截器
if (isStatic) {
// 请求静态文件
try {
var data = fs.readFileSync(config["page_path"] + pathName)
response.writeHead(200);
response.write(data);
response.end();
} catch (e) {
response.writeHead(404);
response.write("<html><body><h1>404 NotFound</h1></body></html>")
response.end();
}
} else {
//请求动态文件
if (loader.get(pathName)) {
try {
//执行加载该模块
loader.get(pathName)(request, response)
} catch (e) {
response.writeHead(500);
response.write("<html><body><h1>500 BadServer</h1></body></html>")
response.end();
}
} else {
response.writeHead(404);
response.write("<html><body><h1>404 NotFound</h1></body></html>")
response.end();
}
}
}).listen(config.port)
log("服务已启动")
//是否静态文件封装
function staticFile(pathName) {
for (var i = 0; i < typeArr.length; i++) {
var temp = typeArr[i]
if (pathName.indexOf(temp) == pathName.length - temp.length) {
return true
}
}
return false
}
10.打印日志log.js
var fs = require("fs")
var config = require("./config")
var path = config.log_path +"/" + config.log_name
function log(data){
//异步打印
fs.appendFile(path,data+"\n",{flag:"a"},function(){})
}
module.exports = log