Express

一、服务端网页编程

1、什么是一个web服务器

前面已经记录,看笔记,如果不太好记得再来整理一下

什么是 web 服务器? - 学习 Web 开发 | MDN (mozilla.org)

2、建立一个网站需要的软件

3、如何将文件上传到web服务器

SFTP:将pc端文件上传到服务器 eg:FileZilla

Rsync:Unix系统 命令行使用rsync 一种本地到远程的文件同步工具

GitHub:允许通过Github Pages发布网站

其它:

Web界面:作为远程文件上传服务前端的HTML界面,由自己的托管服务提供

WebDAV:不了解

4、服务端简介

。。。

使用js和Nodejs进行服务端网页的编程 如果使用python的话就是Django框架

Node

开源、跨平台的运行时环境

可以直接运行于计算机或者服务器os上

省略了一些浏览器专用的API,添加了对OS API的支持(例如HTTP库或者文件系统库)

可以使用nodejs的HTTP包创建一个简单的web服务器

Express

是Node框架,是其它流行框架的底层库

设置Node开发环境

安装了Node和npm之后才可以使用Express

测试是否安装成功

C:\Users\邹阳>node -v
v16.16.0

C:\Users\邹阳>npm -v
8.11.0

创建一个基础纯Node服务器

  1. 创建一份hellonode.js代码

  2. 在代码所在位置的命令行输入 node hellonode.js

  3. 访问返回的URL 浏览器回显示出js中设置好的字符

NPM

  1. 创建一个目录且进入myapp

  2. 使用init命令

    该命令会为应用创建一个package.json文件,且该命令会请求一系列信息——包名、版本等 程序初始进入点的文件名index.js

  3. 查看package.json

    {
      "name": "myapp",
      "version": "1.0.0",
      "description": "这是一个学习npm的package",
      "main": "index.js",
      "scripts": {
        "test": "echo \"Error: no test specified\" && exit 1"
      },
      "author": "",
      "license": "ISC"
    }
    
  4. 在myapp中安装express

    npm install express
    

    package.json文件中会出现dependencies依赖包

  5. 调用require()使用库

    const express = require("express");
    const app = express();
    
    app.get("/", (req, res) => {
      res.send("Hello World!");
    });
    
    app.listen(8000, () => {
      console.log("示例程序正在监听 8000 端口!");
    });
    

    注意:这里文件名要保存为index.js

  6. 启动服务器

    node index.js
    

安装Express应用生成器

功能:生成express应用的框架

npm install express-generator -g

加上-g就是全局生成 对于所有应用都可以使用

进入应用目录,运行以下命令,即可创建一个名为 “helloworld” 的 Express 应用

express helloworld

ps:express会在当前目录的子目录创建新的应用,控制台可以看到构建的构成

cd helloworld
npm install

安装所有依赖

SET DEBUG=helloworld:* & npm start

运行应用:DEBUG可以展示应用运行时返回的有用的日志信息

 http://127.0.0.1:3000/

访问浏览器URL

Express教程

本地图书馆网站

创建站点框架

一、知识点

cmd powerShell bash三者之间的区别

cmd、bash、powershell_cmd和bash_我脾气很好的博客-CSDN博客

linux的bash要比cmd强大很多

安装express生成器

Linux版本:sudo npm install express-generator -g
windows版本:npm install express-generator -g

运行express

express

默认使用:Jade视图引擎+CSS

  -v, --view <engine>  添加 <engine> 视图引擎支持

挑选视图引擎时需要考虑的内容很多,详情可以见MDN的链接

Express 教程 2:创建站点框架 - 学习 Web 开发 | MDN (mozilla.org)

本项目使用Pug模板引擎

    -c, --css <engine>   添加 <engine> 样式表引擎支持 (less|stylus|compass|sass) (默认为纯 css)

上述命令可以选择CSS引擎(不是必须,不做要求)

数据库

express不提供数据库管理机制,可以使用Node支持的所有数据库

二、实现步骤

先在D盘安装生成器

npm install express-generator -g

然后在D盘中生成应用express-locallibrary-tutorial 确定视图引擎为Pug

express express-locallibrary-tutorial -v pug

在应用目录下安装依赖

npm install

运行应用

Linux版本:DEBUG=express-locallibrary-tutorial:* npm start
windows版本:SET DEBUG=express-locallibrary-tutorial:* & npm start

ps:npm start也可以启动命令,但是不会看到调试信息

浏览器中查看

http://localhost:3000/

一个Express应用就配置成功,托管于localhost:3000

因为文件改动时要重启服务器才能看到网站的改动,手动启停服务器麻烦,所以需要自动化

nodemon是一个最简便的自动化工具之一(通常全局安装)

npm install -g nodemon

还可以选择作为开发依赖安装在本地,使用这个项目的开发人员只要安装应用就可以自动获取

npm install --save-dev nodemon

ps:

这里解释一下npm install -s -g -d之间的区别

npm install -s

npm install XXX -s相当于npm install -S相当于 npm install –save

局部安装 表示生产环境下的依赖 如果依赖在项目中起作用的话,就需要-s安装

npm install -d

局部安装 表示开发环境下的依赖 如果项目上线后库就没用了,使用-d安装(例如webpack部署打包、babel解析代码等)

npm install -g

全局安装,安装过一次之后,可以直接使用

npm install

与npm install -s一样

全局安装完成之后的使用 nodemon来代替node即可

如果是局部安装那么需要按照MDN中的脚本操作

应用文档目录

/express-locallibrary-tutorial
    app.js:真实的应用入口 设置并返回express应用对象
    /bin
        www:js文件 调用应用入口的启动脚本(通过require app来启动) 还设置了一些应用的错误处理,加载 app.js 来完成其余工作
    package.json:定义依赖项和其它信息
    /node_modules
        [约 4,500 个子文件夹和文件]
    /public
        /images
        /javascripts
        /stylesheets
            style.css
    /routes :用不同模块保存应用路由
        index.js
        users.js
    /views:保存模板
        error.pug
        index.pug
        layout.pug

突然发现之前没有pug 所以需要手动安装一下

npm install pug

ps:

require()是一个全局的node函数,可以将模块导入到当前文件。

app.js文件:

1、使用 require() 导入了一些实用 node 库,其中包括之前用 NPM 下载的 expresshttp-errorsmorgan 和 *cookie-parser*,还有一个 path 库,它是用于解析文件和目录的核心 node 库。

2、然后 require() 的是用户路由目录中的模块。

3、用导入的 express 模块来创建 app 对象,然后使用它来设置视图(模板)引擎。

设置视图(模板)引擎

a、view

app.set("views", path.join(__dirname, "views"));

指定模板的存储文件夹

b、view engine

app.set("view engine", "pug");

指定模板库

4、app.use() 调用将中间件库添加进请求处理链。

5、所有中间件都已设置完毕后,现在把(之前导入的)路由处理器添加到请求处理链中。

6、最后一个中间件为错误和 HTTP 404 响应添加处理方法。

7、添加到exports模块,使其可以通过bin/www导入

module.exports = app;

ps:windows删除文件夹

rmdir /s FileName

npm查看已安装的包(全局、本地)

npm ls/npm -g ls
  • MDN上最后还有一个挑战自我,我增加了一个users文件夹然后将cool.js文件放置在了里面,在app.js中增加了该路由中间件但是好像路径这里设置有问题,目前还没有讲到,之后来填坑

使用数据库Mongoose

与数据库交互的方式

  1. 数据库的原生查询语句 SQL等

  2. 使用对象数据模型ODM或对象关系模型ORM(推荐)

    它们能够将网站中的数据表示为js对象,然后将他们映射到底层数据库

优缺点:原始查询语句的性能高,ODM或者ORM可以用js对象的思维而不用转向数据库语义的思维,可以更方便地对数据进行验证和检查。

ODM -> Mongoose:为异步工作环境设计的MongoDB对象建模工具(MongoDB 数据库里,“集合”中的“文档” 类似于 关系数据库里“表”中的“行”。

MongoDB 文档:https://mongoosejs.com/docs/guide.html

前面涉及到的连接数据库等在数据库那篇博文中

定义library模式

为每个模型创建单独的文件

/express-locallibrary-tutorial  // 项目根目录
  /models
    author.js
    book.js
    bookinstance.js
    genre.js

作者模型

const mongoose = require("mongoose");

const Schema = mongoose.Schema;

const AuthorSchema = new Schema(&#123;
  first_name: &#123; type: String, required: true, max: 100 &#125;,
  family_name: &#123; type: String, required: true, max: 100 &#125;,
  date_of_birth: &#123; type: Date &#125;,
  date_of_death: &#123; type: Date &#125;,
&#125;);

// 虚拟属性'name':表示作者全名
AuthorSchema.virtual("name").get(function () &#123;
  return this.family_name + ", " + this.first_name;
&#125;);

// 虚拟属性'lifespan':作者寿命
AuthorSchema.virtual("lifespan").get(function () &#123;
  return (
    this.date_of_death.getYear() - this.date_of_birth.getYear()
  ).toString();
&#125;);

// 虚拟属性'url':作者 URL
AuthorSchema.virtual("url").get(function () &#123;
  return "/catalog/author/" + this._id;
&#125;);

// 导出 Author 模型
module.exports = mongoose.model("Author", AuthorSchema);

路由和控制器

Express HTTP 请求/响应 路径

现在模型已经创建好了,现在要创建的主要是:

  • 路由
  • 控制器:获取到数据,创建一个HTML页面显示出数据,并将页面返回给用户,以便在浏览器中查看
  • 视图

路由入门

将所有与图书有关的路由保存在catalog模块中,在添加处理账户或者其它功能的路由时,可以分开保存。

1、需要在routes文件夹中添加路由模块

2、在app.js中添加该路由模块require然后使用use

路由函数

router.get("/about", (req, res) => &#123;
  res.send("关于此维基");
&#125;);

Router.get() 方法定义的“about”路由(下方重现的)仅响应 HTTP GET 请求。第一个参数是 URL 路径,第二个参数是一个回调,在收到带有路径的 HTTP GET 请求将调用之。

该回调有三个参数(通常命名为:reqresnext),分别是:HTTP 请求对象、HTTP 响应、中间件链中的下一个函数。

路径路由

路径可以是字符串或者字符串模式或者是正则表达式

路由参数

URL /book/create 会匹配 /book/:bookId 这样的路由(将提取值为'create' 的 'bookId')。

library所需路由

首页和列表页面没有包含任何额外的信息,因此它们返回的结果只取决于模型类型和数据库内容,创建和查询操作没有较大的变化

  • catalog/:主页。
  • catalog/<objects>/:模型(藏书、藏书副本、藏书种类、作者)的完整列表(例如 /catalog/books//catalog/genres/ 等)
  • catalog/<object>/<id>:具有 _id 字段值的特定模型的详细信息页面(例如 /catalog/book/584493c1f4887f06c0e67d37)。
  • catalog/<object>/create:添加新模型的表单(例如 /catalog/book/create)。
  • catalog/<object>/<id>/update:更新具有 _id 字段值的特定模型的表单(例如 /catalog/book/584493c1f4887f06c0e67d37/update)。
  • catalog/<object>/<id>/delete:删除具有 _id 字段值的特定模型的表单(例如 /catalog/book/584493c1f4887f06c0e67d37/delete)。

而其他URL用于处理特定文档/模型实例的,会将目的标识嵌入URL(例如id),可以使用路径参数提取嵌入的信息,并传递给路由处理器

ps:有些命令只对bash有效,要在windows上使用bash,最简单的方法就是安装git 然后使用git bash here

总结一下上述的路由过程:1、需要有各自模块对应的模型(book.js)里面定义的是各种字段以及虚拟属性等

2、建立自己的route文件夹下的路由页面 将所有模块的路由都写入到了catalog.js文件下 但是各个路由对应的回调函数需要在controller层中写逻辑,因此新建了一个controller文件夹,在里面写各个模块的回调逻辑

3、最后在app.js中加入catalog.js路由中间件,将入口页面跳转到catalog/books路由指定页面

模板入门

本项目中使用pug作为模板,它主要用于编写html,语法干净且空格敏感,受haml影响很大。

pug:视图引擎

项目中在view文件夹下,在进行项目修改之前,需要先搞懂pug的语法

模板语法

每一行中的第一个单词是 HTML 元素,并且缩进用于指示嵌套元素。非嵌套元素(例如,各个段落)位于不同的行上。

元素属性被定义在其关联元素之后的括号中。属性键值对之间可以使用,或者空格间隔开

link(rel='stylesheet', href='/stylesheets/style.css')

所有属性的值都被转义(例如“>”等字符转换为 HTML 代码等效项,如“>”),以防止注入 JavaScript 或跨站点脚本攻击。

如果标记后跟着等号,则以下文本将被视为 JavaScript 表达式。

h1= title
p= 'Evaluated and escaped expression:' + title

如果标记后面没有等号,则将内容视为纯文本。还可以在行的开头使用管道‘|’字符来表示纯文本,允许您使用if, else , else ifunless执行条件操作,使用each-inwhile语法执行循环/迭代操作。

ul
  each val in [1, 2, 3, 4, 5]
    li= val

语法还支持注释等,可以在链接中进行查看

Getting Started – Pug (pugjs.org)

学完了语法部分,因为页面有很多的commen部分,所以pug支持在基本模板上进行扩展

一般view/layout.pug就是基本模板

//- 基本模板 pug允许在基础模板上进行扩展 可以只替换每个页面不同的部分
doctype html
html
  head
    title= title
    link(rel='stylesheet', href='/stylesheets/style.css')
  body
    //- 块标记 block用于标记“可在派生模板中替换的内容部分”
    block content

如何使用基本模板

extends layout

block content
  h1= title
  p Welcome to #{title}

使用extends进行继承

接下来设计本地图书馆的基础模板(使用了Bootstrap的js和CSS)

修改部分:layout.pug基础模板+public/stylesheets/style.css

Bootstrap栅格系统,系统最多分为12列

主页设计

使用moment 来做日期格式化

moment是一个轻量级js日期库,用于解析、验证、操作和格式化日期