nodejs学习之(服务器搭建,封装服务器)

服务器搭建

let http = require('http')

// 调用createServer方法创建实例
let server = http.createServer()

// 绑定一个request事件处理函数
// 这个函数得作用就是处理接收请求,并且根据url进行不同得处理
// 接收到请求,后面有两个回调函数得参数,分别是请求得信息,和响应得信息
server.on('request',(req,res)=>{

  // 设置请求头编码
  res.writeHead(200,{'Content-Type': 'text/html;charset=UTF-8' })

  let url = req.url
  if (url === '/') {
    res.end('<h1>首页</h1>')
  }else if (url=== 'fenlei') {
    res.end('<h1>分类</h1>')
  }else if (url === 'wode') {
    res.end('<h1>我得</h1>')
  }else{
    res.end('<h1>404</h1>')
  }
})

// 开始服务器,监听端口号
server.listen(3000,()=>{
  console.log('服务器已经开启,可以通过访问http://127.0.0.1:3000/来获取数据');
  
})

设置状态码和响应头

response.writeHead(200, { 'Content-Type': 'text/plain' });

设置响应头

response.setHeader('Content-Type', 'text/html');

写入内容

response.write(fileData);

结束响应

response.end();

封装服务器

let http = require('http')
let path = require('path')
let url = require('url')

class app {
  constructor(){
    console.log('进来');
    this.server = http.createServer()
    // 定义一个对象来存放url和他得回调函数,在调用on得使用,根据url来调用函数
    this.objEvent = {}
      //  },
      //  '/aa':function (req,res){ console.log('<h1>我得<h1>');
    
    this.server.on('request',(req,res)=>{
      // 解析路径,比如 "/"  { root: '/', dir: '/', base: '', ext: '', name: '' }
       let pathObj =path.parse(req.url)
      // 检测url是否为obj对象中已经定义好得对象,否则就404
      // 由于在objEvent中定义得 是以url 为键值 ,以fn为值得形式
      // 在执行on方法得事情,其实if也是一种循环,当检测到objEvent里面得有值得时候,就会执行下面得东西
      if (pathObj.dir in this.objEvent) {
        // 把路径后面得传给下面req
        req.path1 = pathObj.base
        this.objEvent[pathObj.dir](req,res)
      }else{
        res.writeHead(200,{'Content-Type': 'text/html;charset=UTF-8' })
        res.end('<h1>404<h1>')
      }
    })
  }
  on(url,fn){
    // 把fn赋值给键值url得值
    this.objEvent[url] = fn;
  }
  run(port,callback){
    this.server.listen(port,callback)
  }
}

let a = new app()
a.on('/',(req,res)=>{
  res.end('aaa')
})

a.on('/aa',(req,res)=>{
  res.writeHead(200,{'Content-Type': 'text/html;charset=UTF-8' })
  if (req.path1 === 'index.html') {
    res.end('<h1>我得</h1>')
  }else{
    res.end('<h1>其他</h1>')
  }
 
})
a.run(80,()=>{
  console.log("服务器其启动");
})

实现静态服务器

能够根据需要请求的文件,原封不动的将服务器磁盘中的数据直接返回给到浏览器。

let http = require('http')
let path = require('path')
let fs = require('fs')

class app {
  constructor(){
    this.server = http.createServer()
    this.objEvent = {}

// 第一步首先在构造函数里面定义一个访问静态目录得url
    this.staticdir = '/static'  
    this.server.on('request',(req,res)=>{
       let pathObj =path.parse(req.url)
      if (pathObj.dir in this.objEvent) {
        req.path1 = pathObj.base
        this.objEvent[pathObj.dir](req,res)
 // 第二步然后判断如果是访问静态目录
      }else if (pathObj.dir == this.staticdir ) {
      // 第三步,改变一下后缀名
        res.writeHead(200,{'Content-Type': this.getgetContentType(pathObj.ext)})
        // 第四步,读取静态目录里面得内容
        let rs = fs.createReadStream('./static/'+ pathObj.base)
        // 第五步,返回给浏览器
        rs.pipe(res)
              }
      else{
        res.writeHead(200,{'Content-Type': 'text/html;charset=UTF-8' })
        res.end('<h1>404<h1>')
      }
    })
  }
  on(url,fn){
    // 把fn赋值给键值url得值
    this.objEvent[url] = fn;
  }
  run(port,callback){
    this.server.listen(port,callback)
  } 
  getgetContentType(extName){
    switch (extName) {
        case ".jpg":
            return "image/jpeg";
        case ".html":
            return "text/html;charset=utf-8";
        case ".js":
            return "text/javascript;charset=utf-8";
        case ".json":
            return "text/json;charset=utf-8";
        case ".gif":
            return "image/gif";
        case ".css":
            return "text/css"
    }
  }
}

let a = new app()
// 第六步,也是重点,在这里可以惊醒修改访问静态目录得url
a.staticdir = '/qqq'
a.on('/',(req,res)=>{
  res.end('aaa')
})

a.on('/aa',(req,res)=>{
  res.writeHead(200,{'Content-Type': 'text/html;charset=UTF-8' })
  if (req.path1 === 'index.html') {
    res.end('<h1>我得</h1>')
  }else{
    res.end('<h1>其他</h1>')
  }
 
})
a.run(80,()=>{
  console.log("服务器其启动");
})

实现通关url进行动态渲染

根据url的值来获取不同序列号的值

let http = require('http')
let path = require('path')

class app {
  constructor(){
    console.log('进来');
    this.server = http.createServer()
    // 定义一个对象来存放url和他得回调函数,在调用on得使用,根据url来调用函数
    this.objEvent = {}
      //  },
      //  '/aa':function (req,res){ console.log('<h1>我得<h1>');
    
    this.server.on('request',(req,res)=>{
      // 解析路径,比如 "/"  { root: '/', dir: '/', base: '', ext: '', name: '' }
       let pathObj =path.parse(req.url)                                          // 第三步,获取路由
      // 检测url是否为obj对象中已经定义好得对象,否则就404
      // 由于在objEvent中定义得 是以url 为键值 ,以fn为值得形式
      // 在执行on方法得事情,其实if也是一种循环,当检测到objEvent里面得有值得时候,就会执行下面得东西
      if (pathObj.dir in this.objEvent) {                                        // 第四步,检测路由在不在保存得对象里                                  
        this.objEvent[pathObj.dir](req,res)                                       // 第五步,再得话执行回调函数
        req.path1 = pathObj.base                                                  // 第六步,定义路由后面得子路由,放到req里面
      }else{ 
        res.writeHead(200,{'Content-Type': 'text/html;charset=UTF-8' })
        res.end('<h1>404<h1>')
      }
    })
  }
  on(url,fn){                                                                 // 第二步,把路由通关键值为序号,回调为值得方式保存起来
    // 把fn赋值给键值url得值
    this.objEvent[url] = fn;
  }
  run(port,callback){
    this.server.listen(port,callback)
  }
}

let a = new app()
a.on('/',(req,res)=>{
  res.end('aaa')
})

a.on('/aa',(req,res)=>{
  res.writeHead(200,{'Content-Type': 'text/html;charset=UTF-8' })
  if (req.path1 === 'index.html') {
    res.end('<h1>我得</h1>')
  }else{
    res.end('<h1>其他</h1>')
  }
})

a.on('/movie',(req,res)=>{                                                                          // 第一步,定义路由
  res.writeHead(200,{'Content-Type': 'text/html;charset=UTF-8' })
  let movie=[
    {
      title:'aa',
      bef:'11111111111111111111111111111111111111111'
    },
    {
      title:'bb',
      bef:'22222222222222222222222222222222222222222'
    }
  ]
  // 这里就是把绑定url里面的值来把序列号里面的值
  let index = req.path1                                                                            // 第八步,从请求体中拿出来子路由
  res.send(movie[index].title)                                                                   // 第九步,通关子路由展示不同得内容
})

a.run(80,()=>{
  console.log("服务器其启动");
})

实现简单{{}}语法

首先讲述一下正则的exec方法,匹配到的内容是再返回的结果中序列号第二个,并且执行一次匹配一次,再继续执行则往下面匹配
在这里插入图片描述
这里使用这个方法,其实和上面动态使用路由思路差不多,但是这里使用这个render函数代表输出。
这个render函数得作用就是匹配html文件里面使用 类似 {{title}} 这样得参数,并且使用正则匹配,当匹配到{{}} 就根据里面得内容,就替换掉

let http = require('http')
let path = require('path')
let fs = require('fs')

class app {
  constructor(){
    console.log('进来');
    this.server = http.createServer()
    this.objEvent = {}
    this.server.on('request',(req,res)=>{
       let pathObj =path.parse(req.url)
       let pathAll = pathObj.dir 
      if (pathAll in this.objEvent) {
        res.render = render                                                                 // 第一步,定义一个render函数赋值render
        // 把路径后面得传给下面req
        req.path1 = pathObj.base 
        this.objEvent[pathAll](req,res)
      }else{
        res.writeHead(200,{'Content-Type': 'text/html;charset=UTF-8' })
        res.end('<h1>404<h1>')
      }
    })
  }
  on(url,fn){
    // 把fn赋值给键值url得值
    this.objEvent[url] = fn;
  }
  run(port,callback){
    this.server.listen(port,callback)
  }
}

let a = new app()
a.on('/',(req,res)=>{
  res.end('aaa')
})

a.on('/aa',(req,res)=>{
  res.writeHead(200,{'Content-Type': 'text/html;charset=UTF-8' })
  if (req.path1 === 'index.html') {
    res.end('<h1>我得</h1>')
  }else{
    res.end('<h1>其他</h1>')
  }
})
a.on('/movie',(req,res)=>{
  res.writeHead(200,{'Content-Type': 'text/html;charset=UTF-8' })
  let movie=[
    {
      title:'aa',
      bef:'11111111111111111111111111111111111111111'
    },
    {
      title:'bb',
      bef:'22222222222222222222222222222222222222222'
    }
  ]
  let index = req.path1
  // res.end(movie[index].title)
  res.render(movie[index],'./index.html')                                                        // 第二步,把数据和html模板传进来
})

function render(options,path) {
  fs.readFile(path,{encoding:'utf-8',flag:'r'},( (err,data)=>{                                   // 第三步,读取模板,匹配{{}},
    if (err) {
    }else{
      let reg = /\{\{(.*?)\}\}/igs
      let result;
      // 下面以循环的方式来多次执行exec方法来匹配全部值出来
      while (result= reg.exec(data)) {
        // 取result[1],是为了取正则匹配到的结果,比如tltie 就是匹配到的结果
        let strKey = result[1].trim()                                                            // 第四步,拿到{{}}里面得值作为键值
        // 然后以上面匹配到的内容与存在的数据进行对比,以匹配到的内容作为键值(序号)来赋值或者取内容
        let strValue = options[strKey]                                                           // 通过键值拿到相对应得内容
        data = data.replace(result[0],strValue)                                                  // 把读取到得内容替换掉
      }
    }
    // end方法就是打印出来
    // 因为已经把render函数复制给res,并且上面使用箭头函数,这里得this就是res
    this.end(data)
  }))
}
a.run(80,()=>{
  console.log("服务器其启动");
})


{{}}便利遍历数组得封装

html代码

  <ul>
    {%for {stars} %}
    <li>{{item}}</li>
    {%endfor%}
  </ul>

js封装代码-

let http = require('http')
let path = require('path')
let fs = require('fs')

class app {
  constructor(){
    console.log('进来');
    this.server = http.createServer()
    // 定义一个对象来存放url和他得回调函数,在调用on得使用,根据url来调用函数
    this.objEvent = {}
      //  },
      //  '/aa':function (req,res){ console.log('<h1>我得<h1>');
    
    this.server.on('request',(req,res)=>{
      // 解析路径,比如 "/"  { root: '/', dir: '/', base: '', ext: '', name: '' }
       let pathObj =path.parse(req.url)
       let pathAll = pathObj.dir 
      // 检测url是否为obj对象中已经定义好得对象,否则就404
      // 由于在objEvent中定义得 是以url 为键值 ,以fn为值得形式
      // 在执行on方法得事情,其实if也是一种循环,当检测到objEvent里面得有值得时候,就会执行下面得东西
      if (pathAll in this.objEvent) {
        res.render = render
        // 把路径后面得传给下面req
        req.path1 = pathObj.base 
        this.objEvent[pathAll](req,res)
      }else{
        res.writeHead(200,{'Content-Type': 'text/html;charset=UTF-8' })
        res.end('<h1>404<h1>')
      }
    })
  }
  on(url,fn){
    // 把fn赋值给键值url得值
    this.objEvent[url] = fn;
  }
  run(port,callback){
    this.server.listen(port,callback)
  }
}

let a = new app()
a.on('/',(req,res)=>{
  res.end('aaa')
})

a.on('/aa',(req,res)=>{
  res.writeHead(200,{'Content-Type': 'text/html;charset=UTF-8' })
  if (req.path1 === 'index.html') {
    res.end('<h1>我得</h1>')
  }else{
    res.end('<h1>其他</h1>')
  }
})

// 下面就进行动态渲染,通关url的的值来动态渲染出内容
a.on('/movie',(req,res)=>{
  res.writeHead(200,{'Content-Type': 'text/html;charset=UTF-8' })
  let movie=[
    {
      title:'aa',
      bef:'11111111111111111111111111111111111111111',
      stars:['aaa','bbb','ccc']
    },
    {
      title:'bb',
      bef:'22222222222222222222222222222222222222222'
    }
  ]
  // 这里就是把绑定url里面的值来把序列号里面的值
  let index = req.path1
  // res.end(movie[index].title)
  res.render(movie[index],'./index.html')
})
function render(options,path) {
  fs.readFile(path,{encoding:'utf-8',flag:'r'},( (err,data)=>{
    if (err) {
    }else{
      // 匹配字符串
      // 这里注释掉方法得原因是,这里会匹配到数组中得{{}}并且会替换掉,会导致下面匹配不到
      // data =  replaceStr(data,options)
      // 匹配数组
      // 空格也是匹配对象,下面要是没有空格,会匹配不到
      let reg = /\{\%for \{(.*?)\} \%\}(.*?)\{\%endfor\%\}/igs
      let  result = ''
      while (result = reg.exec(data)) {
        let arrKey = result[1].trim()
        let arrValue = options[arrKey]   
        let listArr = ''
        // 这里拿到得值是一个数组,对数组进行循坏
        arrValue.forEach((item,i) =>{
          // replaceStr函数返回得是匹配后得到得值也就是<li>和内容,每一次匹配就把内容相加,再替换得时候就可以直接呈现出来
          // 因为options参数要求是有键值得,所以这里得item需要有键值
          listArr = listArr + replaceStr(result[2],{item})
        })
        // 把上面获得得内容进行替换
        data = data.replace(result[0],listArr)
      }
      
    }
    // end方法就是打印出来
    // 因为已经把render函数复制给res,并且上面使用箭头函数,这里得this就是res
    this.end(data)
  }))
}

function replaceStr(data,options){
  let reg = /\{\{(.*?)\}\}/igs
  let result;
  // 下面以循环的方式来多次执行exec方法来匹配全部值出来
  while (result= reg.exec(data)) {
    // 取result[1],是为了取正则匹配到的结果,比如tltie 就是匹配到的结果
    let strKey = result[1].trim() 
    // 然后以上面匹配到的内容与存在的数据进行对比,以匹配到的内容作为键值(序号)来赋值或者取内容
    let strValue = options[strKey]
    data = data.replace(result[0],strValue)
  }
  return data
}

a.run(80,()=>{
  console.log("服务器其启动");
})

其实上面这段代码有可以改进得地方,假如要匹配得是一个数组里面得对象

      title:'bb',
      bef:'22222222222222222222222222222222222222222',
      stars:[
        {name:'aa',sex:'bb'}
      ]

怎么把上面得值匹配到下面得html中呢

  <ul>
    {%for {stars} %}
    <li>{{item.name}}</li>
    <li>{{item.sex}}</li>
    {%endfor%}
  </ul>

其实只需要再根据键值获取值得时候,改成eval方法来对获取值进行加工就行,如代码

function replaceStr(data,options){
  let reg = /\{\{(.*?)\}\}/igs
  let result;
  // 下面以循环的方式来多次执行exec方法来匹配全部值出来
  while (result= reg.exec(data)) {
    // 取result[1],是为了取正则匹配到的结果,比如tltie 就是匹配到的结果
    let strKey = result[1].trim() 
    // 然后以上面匹配到的内容与存在的数据进行对比,以匹配到的内容作为键值(序号)来赋值或者取内容
    // let strValue = options[strKey]
    let strValue = eval('options.'+strKey)             // 再这里使用这个方法,这个方法把里面得字符串当成js代码来执行
    data = data.replace(result[0],strValue)
  }
  return data
}

实现使用正则来写动态路径

let http = require('http')
let path = require('path')
let fs = require('fs')

class app {
  constructor(){
    this.server = http.createServer()
    this.objEvent = {}
    this.server.on('request',(req,res)=>{
       let pathObj =path.parse(req.url)
       let pathAll = pathObj.dir 
       																													
      for (const key in this.objEvent) {                 // 第一步,从这里开始,因为调用on会弄进对象中,循坏对象拿出on上面的路径
        let regstr = key
        let reg = new RegExp(key,'igs')                   // 生成正则对象
        
        if (reg.test(req.url)) {                          // 然后匹配网页上填写的路径是否符合正则
          res.render = render
          req.path1 = pathObj.base 
          this.objEvent[key](req,res)                      // 符合就执行
          break;
        }
      }
      // if (pathAll in this.objEvent) {
      //   res.render = render
      //   // 把路径后面得传给下面req
      //   req.path1 = pathObj.base 
      //   this.objEvent[pathAll](req,res)
      // }else{
      //   res.writeHead(200,{'Content-Type': 'text/html;charset=UTF-8' })
      //   res.end('<h1>404<h1>')
      // }
    })
  }
  on(url,fn)
    this.objEvent[url] = fn;
  }
  run(port,callback){
    this.server.listen(port,callback)
  }
}

let a = new app()                           // 下面的on里面使用正则路径
a.on('^\/$',(req,res)=>{
  res.end('aaa')
})

a.on('/aa/(.*)',(req,res)=>{                               
  res.writeHead(200,{'Content-Type': 'text/html;charset=UTF-8' })
  if (req.path1 === 'index') {
    res.end('<h1>我得</h1>')
  }else{
    res.end('<h1>其他</h1>')
  }
})

// 下面就进行动态渲染,通关url的的值来动态渲染出内容
a.on('/movie/[01]',(req,res)=>{
  res.writeHead(200,{'Content-Type': 'text/html;charset=UTF-8' })
  let movie=[
    {
      title:'aa',
      bef:'11111111111111111111111111111111111111111',
      stars:['aaa','bbb','ccc']
    },
    {
      title:'bb',
      bef:'22222222222222222222222222222222222222222',
      stars:[
        {name:'aa',sex:'bb'}
      ]
    }
  ]
  // 这里就是把绑定url里面的值来把序列号里面的值
  let index = req.path1
  // res.end(movie[index].title)
  res.render(movie[index],'./index.html')
})
function render(options,path) {
  fs.readFile(path,{encoding:'utf-8',flag:'r'},( (err,data)=>{
    if (err) {
    }else{
      let reg = /\{\%for \{(.*?)\} \%\}(.*?)\{\%endfor\%\}/igs
      let  result = ''
      while (result = reg.exec(data)) {
        let arrKey = result[1].trim()
        let arrValue = options[arrKey]   
        let listArr = ''
        arrValue.forEach((item,i) =>{
          listArr = listArr + replaceStr(result[2],{item})
        })
        data = data.replace(result[0],listArr)
      }
      
    }
    this.end(data)
  }))
}

function replaceStr(data,options){
  let reg = /\{\{(.*?)\}\}/igs
  let result;
  // 下面以循环的方式来多次执行exec方法来匹配全部值出来
  while (result= reg.exec(data)) {
    // 取result[1],是为了取正则匹配到的结果,比如tltie 就是匹配到的结果
    let strKey = result[1].trim() 
    // 然后以上面匹配到的内容与存在的数据进行对比,以匹配到的内容作为键值(序号)来赋值或者取内容
    // let strValue = options[strKey]
    let strValue = eval('options.'+strKey)
    data = data.replace(result[0],strValue)
  }
  return data
}

a.run(80,()=>{
  console.log("服务器其启动");
})


  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值