作者: HalfSugar

  • 数据库复习

    第一章 绪论

    1.1 数据库系统概述

    1.1.1 四个概念

    1. 数据(Data)描述事物的符号记录 是 数据。数据含义 是 数据语义
    2. 数据库(DB,DataBase)长期储存在计算机内,有组织的,可共享的大量数据的集合。特点:
      1. 按一定的数据模型组织、描述和储存。
      2. 较小冗余度。
      3. 较高数据独立性和易扩展性。
      4. 可共享。
    3. 数据库管理系统(DBMS,DataBase Management System)用户与操作系统间的一层数据管理软件,是计算机的基础软件。功能:
      • 数据定义
      • 数据组织、存储、管理
      • 数据操纵
      • 数据库事务管理和运行管理
      • 数据库建立和维护
    4. 数据库系统存储、管理、处理和维护数据的系统。

    1.1.2 历程

    1. 人工管理阶段
    2. 文件系统阶段
    3. 数据库系统阶段

    1.1.3 数据库系统的特点

    1. 数据结构化
    2. 数据共享性高、冗余度低、易扩充
    3. 数据独立性高
    4. 数据 由 数据管理系统 统一管理控制

    1.2 数据模型

    对数据特征的抽象。

    是数据库系统的核心和基础

    根据模型应用目的可以将模型分为两大类:

    1. 概念模型
    2. 逻辑模型和物理模型

    1.2.1 概念模型

    基本概念:

    1. 实体客观存在并可相互区别的事物称为 实体 。一条数据本身是一个实体。
    2. 属性实体具有的某一特性称为 属性
    3. 码唯一标识实体的属性集称为
    4. 实体型实体名和属性名集合来抽象刻画实体,称为 实体型。如 学生(姓名,学号,性别,出生日期)是一个实体型。
    5. 实体集同一类型的实体集合。
    6. 联系不同实体集之间的联系。有一对一,一对多,多对多。

    E-R 方法:实体-联系方法。

    1.2.2 数据模型的组成要素

    • 数据结构数据库的组成对象以及对象之间的联系。
    • 数据操作操作及操作规则。对各种对象的实例允许执行的操作的集合。
    • 数据的完整性约束条件一组完整性规则。

    1.2.3 常用数据模型

    • 层次模型
    • 网状模型
    • 关系模型
    • 面向对象数据模型
    • 对象关系数据模型
    • 半结构化数据模型

    基本层次联系 是指两个记录以及它们间的一对多(包括一对一)的联系。

    1.2.4 数据模型详解

    层次模型

    特点:

    • 有且只有一个结点没有双亲节点,称为根节点
    • 根以外其它结点有且只有一个双亲节点

    //类似树,只有一个父节点但可以很多个子节点。

    优点:

    1. 数据结构简单清晰
    2. 查询效率高
    3. 良好的完整性支持

    缺点:

    1. 非层次性的不适合用层次模型表示
    2. 具有多个父节点的关系,使用层次模型比较复杂
    3. 查询子女结点必须通过双亲节点
    4. 层次命令趋于程序化

    网状模型

    特点:

    1. 允许一个以上的节点无双亲
    2. 一个结点可以有多个双亲

    优点:

    1. 更直接描述现实世界
    2. 性能良好,存取效率高

    缺点:

    1. 结构复杂
    2. 嵌入高级语言后,用户不易掌握
    3. 必须了解系统结构的细节

    关系模型

    数据结构
    • 关系:一张表
    • 元组:一行
    • 属性:一列
    • 码:唯一标识
    • 域:属性的取值范围
    • 分量:元组的一个属性值
    • 关系模式:对关系的描述,理解成表头,但表示成关系名(属性1,属性2,属性3,……)

    关系模型要求关系规范化,不允许表中有表。

    术语对比

    关系术语一般表格的术语
    关系名表名
    关系模式表头
    关系一张表
    元组
    属性
    属性名列名
    属性值列值
    分量一条记录中的一个列值
    非规范关系表中有表

    优点:

    1. 建立在严格的数学概念上
    2. 数据结构简单、清晰,用户易懂、易用
    3. 存取路径对用户透明

    1.3 数据库系统的三级模式结构

    外模式、模式、内模式 三个抽象级别。

    1. 模式也称 逻辑模式 ,是数据库中全体数据的逻辑结构和特征的描述,是所有用户的公共数据视图。
    2. 外模式也称 子模式用户模式 ,它是数据库用户能够看见和使用的局部数据的逻辑结构和特征的描述,是数据库用户的数据视图,是与某一应用有关的数据的逻辑表示。
    3. 内模式也称 存储模式 ,一个数据库只有一个内模式,它是数据物理结构和存储方式的描述。是数据在数据库内部的组织方式。

    1.4 数据库系统的二级映像功能与数据独立性

    两层映像:

    • 外模式 / 模式映像一个模式(数据的全局逻辑结构)可以有多个外模式(数据的局部逻辑结构)。注:应用程序是根据数据的外模式编写的。数据与程序有逻辑独立性。模式改变时,外模式可以不变。
    • 模式 / 内模式映像当存储结构改变时,模式和应用程序都可以不改变。数据与程序具有物理独立性。

    第二章 关系数据库

    2.1 关系数据结构及形式化定义

    2.1.1 关系

    • 域属性的取值范围。定义:域是一组具有相同数据类型的值的集合。域允许的不同取值个数称为 基数
    • 笛卡尔积就是把多个域的全部组合遍历。例如 老师域×学生域 得到 全部(老师,学生)。
    • 关系笛卡尔积代表全部的可能性,但现实中往往并不是全部可能性都真实存在。因此笛卡尔积的子集称为关系。若某一属性组的值能唯一地标识一个元组,而其子集不能,则称该属性组为 候选码 多个候选码,选一个为 主码 。候选码的各种属性称为 主属性 。不包含在各种候选码中的属性称为 非主属性非码属性 。候选码有时候只有一个属性,有时候可能包含全部属性,即全部属性才能唯一地标识一个元组。后者称为 全码 。三种类型:
      • 基本关系(基本表,基表)
      • 查询表
      • 视图表
      关系模型要求关系规范化6条性质
      1. 列是同质的,每个分量来自同一个域。
      2. 不同的列可以出于同一个域。如 老师域和学生域 合成 人域。但属性名(列名)需要区分开。
      3. 列的顺序无所谓。
      4. 行的顺序无所谓
      5. 任意两个元组的候选码不同。(候选码是唯一标识)
      6. 分量必须取原子值。即每个分量都是一个不可分的数据项。(基本)

    2.2 关系的完整性

    实体完整性、参照完整性、用户定义的完整性。

    1. 实体完整性主属性不能取空值。
    2. 参照完整性外码对于关系 R 中每个元组,外码要么取空,要么取外码所在表的主码(唯一标识)。
    3. 用户定义的完整性例如分数在0~100之间。

    2.3 关系代数

    传统集合运算:

    1. 并 R ∪ S
    2. 差 R – S 属于R但不属于S
    3. 交 R ∩ S
    4. 笛卡尔积 ×

    关系运算

    1. 选择 Sigma σF(R)选择满足条件的元组。
    2. 投影 派 ΠA(R)关系 R 的投影是从 R 中选择出若干属性列,组成新的关系。
    3. 连接 $$
      R \Join S
      $$
      从两个 关系 的笛卡尔积中选取满足条件的元组。
    4. 除运算 R ÷ S 包含所有在 R 不在 S 的属性和值。

    2.4 关系演算

    ALPHA 语言

    GET 检索操作

    • GET W(SC.Cno) //条件为空
    • GET W(5)(Student.Sno,Student.Sage):Student.Sdept=‘IS’ DOWN Student.Sage //取五个 IS 系学生的学号年龄,年龄降序排列。

    PUT 插入操作

    HOLD 取指令,类似于指针指向一个关系

    UPDATE 修改操作,不允许修改主码

    DELETE

    DROP

    基本格式

    操作语句 工作空间名(数量)(表达式):操作条件

    RANGE A B 把 A 重命名为 B 。

    函数名功能
    COUNT对元组计数
    TOTAL求总和
    MAX求最大值
    MIN求最小值
    AVG求平均值

    QBE 语言

    Query By Example。

    在表中填条件。

    操作符

    操作符意义
    P.Print 打印
    U.Update 更新
    I.Insert 插入
    D.Delete 删除

    第三章 SQL

    3.1 概述

    特点:

    1. 综合统一
    2. 高度非过程化
    3. 面向集合的操作方式
    4. 同一种语法结构提供多种使用方式
    5. 语言简洁,易学易用

    数据库中只存放视图定义,不存放视图数据。

    3.2 SQL 语句

    操作关键字:

    关键字作用
    CREATE创建
    DROP删除表,索引
    ALTER TABLE修改
    UPDATE更新
    DELETE删除数据

    ALTER TABLE 适用于表和索引的修改,可以ADD列,DROP列,ALTER列

    名词关键字:

    关键字意义
    SCHEMA模式
    TABLE
    INDEX索引

    数据类型:(挖坑,下辈子填)

    SELECT 语句中可选的条件:

    关键字作用
    DISTINCT去除重复
    ALL不去除重复

    通配符:

    • % 任意长度
    • _ 一位长度

    WHERE 子句常用查询条件:

    3.3 索引(INDEX)

    索引存在可以加快查询速度。

    3.4 视图(VIEW)

    CREATIVE VIEW name (列名1,列名2…) AS SELECT [WITH CHECK OPTION];

    第四章 数据库安全性

    4.1 安全性概述

    安全性:保护数据库以防止不合法的使用所造成的数据泄露、更改或破坏。

    不安全因素:

    1. 非授权用户对数据库恶意存取破坏
    2. 数据库的重要或敏感的数据被泄露
    3. 安全环境的脆弱性

    4.2 安全性控制

    常用方法和技术:

    1. 用户标识和鉴别
    2. 存取控制
    3. 视图机制
    4. 审计
    5. 数据加密
    1. 用户身份鉴别
      • 静态口令
      • 动态口令
      • 生物特征
      • 智能卡
    2. 存取控制
      • 定义用户权限
      • 合法权限检查
    3. 自主存取控制两个要素:
      • 数据库对象
      • 操作类型
      授权:定义用户权限
    4. 授权
      1. 授予 GRANTGRANT 操作如SELECT ON TABLE name TO username;
      2. 收回 REVOKEREVOKE 操作如SELECT ON TABLE name TO username;
    5. 强制存取控制方法强制存取控制是对数据本身进行密集标记。无论数据如何复制,标记和数据是一个不可分的整体。只有符合密级标记要求的用户才可以操纵数据,从而提供了更高级别的安全性。数据库所管理的实体被分为主体和客体。客体受主体操控。可以理解成,主体是操作者,客体是资料。敏感度标记分配给主体与客体的实例值。主体:许可证级别。客体:密级。敏感度标记:
      1. 绝密
      2. 机密
      3. 可信
      4. 公开
      规则:
      1. 主体许可证级别高于等于客体密级则可读
      2. 主体许可证级别低于等于客体密级则可写

    第五章 数据库完整性

    正确性相容性

    5.1 实体完整性

    主码不能取空值。

    定义实体完整性(设置主码)

    1. 列级定义(单属性)
    2. 表级定义(单属性或多属性)

    检查实体完整性

    1. 检查主码值是否唯一
    2. 检查主码的各个属性是否为空

    5.2 参照完整性

    外码对于关系 R 中每个元组,外码要么取空,要么取外码所在表的主码(唯一标识)。

    定义参照完整性(设置外码)

    表级定义。

    FOREIGN KEY (属性名) REFERENCES 表名(属性名)

    检查参照完整性

    5.3 用户定义的完整性

    如列值非空,列值唯一,列值是否满足一个条件表达式 CHECK(列名 条件)。

    1. 列级定义
    2. 元组上定义

    第六章 关系数据理论

    6.1 函数依赖

    X→Y则函数依赖。

    通过X可以推出Y。

    6.2 码

    候选码

    主码

    主属性:包含在任何一个候选码中的属性。

    其它叫非主属性。

    码:候选码和主码统一简称。

    6.3 范式

    关系数据库中的关系是要满足一定要求的,满足不同程度要求的为不同范式。

    最低要求 1NF。第一范式中,进一步要求为 2NF。

    规范化:一个低一级范式的关系模式,通过模式分解可以转换为若干个高一级范式的关系模式的集合。

    6.4 2NF

    若R∈1NF,且每一个非主属性完全函数依赖于任何一个候选码,则R∈2NF。

    6.5 3NF

    没有传递依赖关系的存在称为3NF。

    定义:设R<U,F>不存在 码X,属性组Y,非主属性Z,使得

    $$
    X\to Y,Y\to Z,Y\not{\to } X
    $$

    成立,则称 R<U,F>∈3NF。

    第七章 数据库设计

    7.1 基本步骤

    1. 需求分析
    2. 概念结构设计
    3. 逻辑结构设计
    4. 物理结构设计
    5. 数据库实施
    6. 数据库运行和维护

    7.2 E-R 图

    E-R 图是概念结构设计中的概念。

    E-R 模型

    两个实体型之间的联系:

    1. 一对一联系(1:1)
    2. 一对多联系(1:n)
    3. 多对多联系(m:n)

    多个实体型之间的联系:

    一对一,一对多,多对多。

    单个实体型内的联系:

    一对一,一对多,多对多。

    E-R 图

    实体型:矩形

    属性:椭圆

    联系:菱形

    第十章 数据库恢复技术

    10.1 事务

    定义

    是用户定义的一个数据库操作序列。

    这一系列操作,要不全都做,要不全都不做。是不可分割的。

    特性

    ACID 特性:

    1. 原子性(不可分割)
    2. 一致性(使数据库中的数据不发生逻辑错误)
    3. 隔离性(并发的各个事务之间不能相互干扰)
    4. 持续性(永久性,事务提交后,其改变或者效果应该是永久性的)

    干扰因素:

    1. 不同事务交叉执行
    2. 事务执行时被强行停止

    第十一章 并发控制

    11.1 概述

    事务是并发控制的基本单位

    并发操作带来的不一致性

    1. 丢失修改
    2. 不可重复读
    3. 读 “脏” 数据

    主要原因:并发操作破坏了事务的隔离性。

    并发控制机制就是要用正确的方式调度并发操作,使一个用户事务的执行不受其他事务的干扰。

    并发控制主要技术:

    1. 封锁
    2. 时间戳
    3. 乐观控制法
    4. 多版本并发控制

    11.2 可串行化调度

    定义

    多个事务的并发执行是正确的,当且仅当其结果与按某一次序串行执行这些事务时的结果相同。

    可串行性

    是并发事务正确调度的准则。

    11.3 两段锁协议(2PL)

    事务两个阶段:

    1. 获得封锁,扩展阶段:在对任何数据进行读、写操作之前,首先要申请并获得对该数据的封锁。
    2. 释放封锁,收缩阶段:在释放一个封锁之后,事物不再申请和获得任何其他封锁。

    11.4 封锁的粒度

    封锁对象的大小。

    封锁对象可以是逻辑单元,也可以是物理单元。

    封锁粒度与系统的并发度和并发控制的开销密切相关。

    多种封锁粒度,供不同的事务选择。称为多粒度封锁

  • Web 课程设计

    本文参考1 WebSocket之仿QQWeb即时聊天系统(上)

    本文参考2 WebSocket之仿QQWeb即时聊天系统(下)

    本文参考3 Node.js 教程_菜鸟

    本文参考4 socket.io 概述

    摇骰子摇到了1,所以选择了仿QQWeb即时聊天系统

    功能要求

    1. 实现Web的点对点即时的文本消息聊天功能。
    2. 实现Web的表情的发送、接收和显示功能。
    3. 实现Web的图片的发送、接收和显示功能。
    4. 实现本地消息的存储,在离线的时候也能加载和查看历史消息;
    5. 要求使用WebSocket

    功能分析

    就是能发 文本、表情、图片。点对点。

    还使用了WebSocket

    WebSocket

    WebSocket

    WebSocket 是独立的、创建在 TCP 上的协议。

    Websocket 通过HTTP/1.1 协议的101状态码进行握手。

    为了创建Websocket连接,需要通过浏览器发出请求,之后服务器进行回应,这个过程通常称为“握手”(handshaking)。

    WebSocket的出现,使得浏览器具备了实时双向通信的能力。

    1. WebSocket可以在浏览器里使用
    2. 支持双向通信
    3. 使用很简单

    WebSocket 使得客户端和服务器之间的数据交换变得更加简单,允许服务端主动向客户端推送数据。在 WebSocket API 中,浏览器和服务器只需要完成一次握手,两者之间就直接可以创建持久性的连接,并进行双向数据传输。

    现在,很多网站为了实现推送技术,所用的技术都是 Ajax 轮询。轮询是在特定的的时间间隔(如每1秒),由浏览器对服务器发出HTTP请求,然后由服务器返回最新的数据给客户端的浏览器。这种传统的模式带来很明显的缺点,即浏览器需要不断的向服务器发出请求,然而HTTP请求可能包含较长的头部,其中真正有效的数据可能只是很小的一部分,显然这样会浪费很多的带宽等资源。

    HTML5 定义的 WebSocket 协议,能更好的节省服务器资源和带宽,并且能够更实时地进行通讯。

    浏览器通过 JavaScript 向服务器发出建立 WebSocket 连接的请求,连接建立以后,客户端和服务器端就可以通过 TCP 连接直接交换数据。

    当你获取 Web Socket 连接后,你可以通过 send() 方法来向服务器发送数据,并通过 onmessage 事件来接收服务器返回的数据。

    WebSocket是一个很棒的概念,我单独拿出来写。

    WebSocket

    创建 对象

    以下 API 用于创建 WebSocket 对象。

    var Socket = new WebSocket(url, [protocol] );
    

    以上代码中的第一个参数 url, 指定连接的 URL。第二个参数 protocol 是可选的,指定了可接受的子协议。


    属性

    以下是 WebSocket 对象的属性。假定我们使用了以上代码创建了 Socket 对象:

    属性描述
    Socket.readyState只读属性 readyState 表示连接状态,可以是以下值:0 – 表示连接尚未建立。1 – 表示连接已建立,可以进行通信。2 – 表示连接正在进行关闭。3 – 表示连接已经关闭或者连接不能打开。
    Socket.bufferedAmount只读属性 bufferedAmount 已被 send() 放入正在队列中等待传输,但是还没有发出的 UTF-8 文本字节数。

    WebSocket 事件

    以下是 WebSocket 对象的相关事件。假定我们使用了以上代码创建了 Socket 对象:

    事件事件处理程序描述
    openSocket.onopen连接建立时触发
    messageSocket.onmessage客户端接收服务端数据时触发
    errorSocket.onerror通信发生错误时触发
    closeSocket.onclose连接关闭时触发

    WebSocket 方法

    以下是 WebSocket 对象的相关方法。假定我们使用了以上代码创建了 Socket 对象:

    方法描述
    Socket.send()使用连接发送数据
    Socket.close()关闭连接

    为了建立一个 WebSocket 连接,客户端浏览器首先要向服务器发起一个 HTTP 请求,这个请求和通常的 HTTP 请求不同,包含了一些附加头信息,其中附加头信息"Upgrade: WebSocket"表明这是一个申请协议升级的 HTTP 请求,服务器端解析这些附加的头信息然后产生应答信息返回给客户端,客户端和服务器端的 WebSocket 连接就建立起来了,双方就可以通过这个连接通道自由的传递信息,并且这个连接会持续存在直到客户端或者服务器端的某一方主动的关闭连接。

    一些准备工作

    根据大佬RongLin02的博客做一些准备工作。

    首先是对于WebSocket的了解。以上已经介绍了。

    然后是安装Node.js,你也可以进入 官网 下载。学习页面。

    NPM的安装,在上一步极有可能已经附带完成。

    socket.io

    是一个WebSocket库,用起来很方便。

    库所以只需要引入而不需要下载。

    在项目根目录 右键–在集成终端中打开

    执行以下代码:

    npm install jquery
    npm install socketio
    npm install express
    

    会生成一个node_modules文件夹用来存放安装好的模块,一些配置信息会生成在package-lock.jsonpackage.json文件中。

    使用方法

    中文文档

    在中文文档里面发现第一个文档 socket.io 快速入门教程——聊天应用 就和我们的任务很像。

    按照其流程一步一步来。

    常用方法

    socket.emit('A',value);
    

    这个是发送方法,A是名字,叫什么名字都行,value就是要发送的值,可以是服务器给客户端发送,也可以是客户端给服务器发送,类型也可以是一个对象。

    socket.on('A',function(data){
            console.log(data);
        });
    

    有发送就有接受,服务器或者客户端会监听,如果有终端通过 名字 A 发送,就会获取到发送的数据,并且把value存到data中,所以说上边的那个data的值就是emitvalue

    emiton一对一。

    运行方法

    ​ 根目录下 右键-终端运行 输入 node index.js

    或 编译器左边项目目录右键打开于终端。在编译器下方的窗口输入指令。

    REPL 命令

    • ctrl + c – 退出当前终端。
    • ctrl + c 按下两次 – 退出 Node REPL。
    • ctrl + d – 退出 Node REPL.
    • 向上/向下 键 – 查看输入的历史命令
    • tab 键 – 列出当前命令

    学习过程

    1. 服务器端的编写

    socket.io 快速入门教程——聊天应用

    Node.js Express 框架

    创建服务器

    使用 http.createServer() 方法创建服务器,并使用 listen 方法绑定端口3000 。 函数通过 request, response 参数来接收和响应数据。

    在项目根目录 新建一个 index.js 文件来创建应用。

    var app = require('express')();
    var http = require('http').Server(app);
    
    app.get('/', function(req, res){
        console.log("主页 POST 请求");
        res.send('<h1>Hello world</h1>');
    });
    
    
    var server = app.listen(3000, function () {
    
        var host = server.address().address
        var port = server.address().port
    
        console.log("访问地址为 http://%s:%s", host, port)
    
    })
    

    这段代码作用如下:

    1. Express 初始化 app 作为 HTTP 服务器的回调函数 (见第 2 行)。
    2. 定义了一个路由/来处理首页访问。在终端输出"主页 POST 请求",给客户端返回'<h1>Hello world</h1>'
    3. 使 http 服务器监听端口 3000。也就是说这个代码只对端口3000有效。

    路由/其实是域名后面的东西。如果访问 localhost:3000/,因为 域名后面只有“/”,所以匹配了这个路由。

    运行node index.js

    2. Node.js

    模块

    引入模块

    Node.js 中,引入一个模块非常简单。

    创建 hello.js 文件,代码如下:

    //hello.js
    exports.world = function() {
      console.log('Hello World');
    }
    //world模块就暴露了,调用见下
    

    创建一个 main.js 文件并引入 hello 模块,代码如下:

    //main.js
    var hello = require('./hello');//引入
    hello.world();//调用
    

    以上实例中,代码 require('./hello') 引入了当前目录下的 hello.js 文件(./ 为当前目录,node.js 默认后缀为 js)。

    Node.js 提供了 exportsrequire 两个对象。

    exports 是模块公开的接口。

    require 用于从外部获取一个模块的接口,即所获取模块的 exports 对象。

    有时候我们只是想把一个对象封装到模块中,格式如下:

    module.exports = function() {
      // ...
    }
    

    例如:

    //hello.js 
    function Hello() { 
        var name; 
        this.setName = function(thyName) { 
            name = thyName; 
        }; 
        this.sayHello = function() { 
            console.log('Hello ' + name); 
        }; 
    }; 
    module.exports = Hello;        //暴露接口
    

    这样就可以直接获得这个对象了:

    //main.js 
    var Hello = require('./hello'); 
    hello = new Hello(); 
    hello.setName('BYVoid'); 
    hello.sayHello(); 
    

    Node.js 中自带了一个叫做 http 的模块,我们在我们的代码中请求它并把返回值赋给一个本地变量。

    这把我们的本地变量变成了一个拥有所有 http 模块所提供的公共方法的对象。


    模块的加载

    在路径 Y 下执行 require(X) 语句执行顺序:

    1. 如果 X 是内置模块
       a. 返回内置模块
       b. 停止执行
    2. 如果 X 以 '/' 开头
       a. 设置 Y 为文件根路径
    3. 如果 X 以 './' 或 '/' or '../' 开头
       a. LOAD_AS_FILE(Y + X)
       b. LOAD_AS_DIRECTORY(Y + X)
    4. LOAD_NODE_MODULES(X, dirname(Y))
    5. 抛出异常 "not found"
    
    LOAD_AS_FILE(X)                    //作为文件加载
    1. 如果 X 是一个文件, 将 X 作为 JavaScript 文本载入并停止执行。
    2. 如果 X.js 是一个文件, 将 X.js 作为 JavaScript 文本载入并停止执行。
    3. 如果 X.json 是一个文件, 解析 X.json 为 JavaScript 对象并停止执行。
    4. 如果 X.node 是一个文件, 将 X.node 作为二进制插件载入并停止执行。
    
    LOAD_INDEX(X)                    //加载索引
    1. 如果 X/index.js 是一个文件,  将 X/index.js 作为 JavaScript 文本载入并停止执行。
    2. 如果 X/index.json 是一个文件, 解析 X/index.json 为 JavaScript 对象并停止执行。
    3. 如果 X/index.node 是一个文件,  将 X/index.node 作为二进制插件载入并停止执行。
    
    LOAD_AS_DIRECTORY(X)             //作为目录加载
    1. 如果 X/package.json 是一个文件,
       a. 解析 X/package.json, 并查找 "main" 字段。
       b. let M = X + (json main 字段)
       c. LOAD_AS_FILE(M)
       d. LOAD_INDEX(M)
    2. LOAD_INDEX(X)
    
    LOAD_NODE_MODULES(X, START)        //加载节点模块
    1. let DIRS=NODE_MODULES_PATHS(START)
    2. for each DIR in DIRS:
       a. LOAD_AS_FILE(DIR/X)
       b. LOAD_AS_DIRECTORY(DIR/X)
    
    NODE_MODULES_PATHS(START)        //节点模块路径
    1. let PARTS = path split(START)
    2. let I = count of PARTS - 1
    3. let DIRS = []
    4. while I >= 0,
       a. if PARTS[I] = "node_modules" CONTINUE
       b. DIR = path join(PARTS[0 .. I] + "node_modules")
       c. DIRS = DIRS + DIR
       d. let I = I - 1
    5. return DIRS
    


    回调函数

    回调函数在完成任务后就会被调用,Node 使用了大量的回调函数,Node 所有 API 都支持回调函数。


    函数

    一个函数可以作为另一个函数的参数。我们可以先定义一个函数,然后传递,也可以在传递参数的地方直接定义函数。

    举例来说,你可以这样做:

    function say(word) {
      console.log(word);
    }
    
    function execute(someFunction, value) {
      someFunction(value);
    }
    
    execute(say, "Hello");
    

    匿名函数

    我们可以把一个函数作为变量传递。但是我们不一定要绕这个”先定义,再传递”的圈子,我们可以直接在另一个函数的括号中定义和传递这个函数:

    function execute(someFunction, value) {
      someFunction(value);
    }
    execute(function(word){ console.log(word) }, "Hello");
    

    我们在 execute 接受第一个参数的地方直接定义了我们准备传递给 execute 的函数。

    用这种方式,我们甚至不用给这个函数起名字,这也是为什么它被叫做匿名函数 。

    全局对象

    __filename

    __filename 表示当前正在执行的脚本的文件名。它将输出文件所在位置的绝对路径,且和命令行参数所指定的文件名不一定相同。 如果在模块中,返回的值是模块文件的路径。

    __dirname

    __dirname 表示当前执行脚本所在的目录。


    文件系统

    Node 导入文件系统模块(fs)语法如下所示:

    var fs = require("fs")
    

    Node.js 文件系统

    Node.js Web 模块

    使用 Node 创建 Web 服务器
    Node.js 提供了 http 模块,http 模块主要用于搭建 HTTP 服务端和客户端,使用 HTTP 服务器或客户端功能必须调用 http 模块,代码如下:

    var http = require('http');
    

    Node.js Express 框架

    Express 是一个简洁而灵活的 node.js Web应用框架, 提供了一系列强大特性帮助你创建各种 Web 应用,和丰富的 HTTP 工具。

    使用 Express 可以快速地搭建一个完整功能的网站。

    Express 框架核心特性:

    • 可以设置中间件来响应 HTTP 请求。
    • 定义了路由表用于执行不同的 HTTP 请求动作。
    • 可以通过向模板传递参数来动态渲染 HTML 页面。
    请求和响应

    Express 应用使用回调函数的参数: requestresponse 对象来处理请求和响应的数据。

    app.get('/', function (req, res) {
       // --
    })
    

    requestresponse 对象的具体介绍:

    Request 对象 – request 对象表示 HTTP 请求,包含了请求查询字符串,参数,内容,HTTP 头部等属性。

    常见属性有:

    1. req.app:当callback为外部文件时,用req.app访问express的实例
    2. req.baseUrl:获取路由当前安装的URL路径
    3. req.body / req.cookies:获得「请求主体」/ Cookies
    4. req.fresh / req.stale:判断请求是否还「新鲜」
    5. req.hostname / req.ip:获取主机名和IP地址
    6. req.originalUrl:获取原始请求URL
    7. req.params:获取路由的parameters
    8. req.path:获取请求路径
    9. req.protocol:获取协议类型
    10. req.query:获取URL的查询参数串
    11. req.route:获取当前匹配的路由
    12. req.subdomains:获取子域名
    13. req.accepts():检查可接受的请求的文档类型
    14. req.acceptsCharsets / req.acceptsEncodings / req.acceptsLanguages:返回指定字符集的第一个可接受字符编码
    15. req.get():获取指定的HTTP请求头
    16. req.is():判断请求头Content-Type的MIME类型

    Response 对象 – response 对象表示 HTTP 响应,即在接收到请求时向客户端发送的 HTTP 响应数据。

    常见属性有:

    1. res.app:同req.app一样
    2. res.append():追加指定HTTP头
    3. res.set()在res.append()后将重置之前设置的头
    4. res.cookie(name,value [,option]):设置Cookie
    5. opition: domain / expires / httpOnly / maxAge / path / secure / signed
    6. res.clearCookie():清除Cookie
    7. res.download():传送指定路径的文件
    8. res.get():返回指定的HTTP头
    9. res.json():传送JSON响应
    10. res.jsonp():传送JSONP响应
    11. res.location():只设置响应的Location HTTP头,不设置状态码或者close response
    12. res.redirect():设置响应的Location HTTP头,并且设置状态码302
    13. res.render(view,[locals],callback):渲染一个view,同时向callback传递渲染后的字符串,如果在渲染过程中有错误发生next(err)将会被自动调用。callback将会被传入一个可能发生的错误以及渲染后的页面,这样就不会自动输出了。
    14. res.send():传送HTTP响应
    15. res.sendFile(path [,options] [,fn]):传送指定路径的文件 -会自动根据文件extension设定Content-Type
    16. res.set():设置HTTP头,传入object可以一次设置多个头
    17. res.status():设置HTTP状态码
    18. res.type():设置Content-Type的MIME类型

    app.use
    app.use(path,callback)

    app.use(path,callback)中的callback既可以是router对象又可以是函数。

    app.get(path,callback)中的callback只能是函数。

    当一个路由有好多个子路由时用app.use(path,router)

    例子:

    http://localhost:3000/home/one

    http://localhost:3000/home/two

    http://localhost:3000/home/three

    路由/home后面有三个子路由紧紧跟随,分别是/one,/two,/three,如果使用app.get(),则要不断的重复,很麻烦,也不利用区分。

    我们可以创建一个router.js专门用来一个路由匹配多个子路由。

    var express = require('express')
    var router = express.Router()
    router.get("/",(req,res)=>{
        res.send("/")
    })
    router.get("/one",(req,res)=>{
        res.send("one")
    })
    router.get("/two",(req,res)=>{
        res.send("second")
    })
    router.get("/three",(req,res)=>{
        res.send("three")
    })
    module.exports = router;
    //module.exports把router暴露出去了。
    

    app.js中导入router.js

    var express = require('express')
    var router = require("./router")
    var app = express()
    
    app.use('/home',router) //router路由对象中的路由都会匹配到"/home"路由后面
    app.get('/about', function (req, res) {
      console.log(req.query)
      res.send('你好,我是 Express!')
    })
    app.listen(3000, function () {
      console.log('app is running at port 3000.')
    })
    

    app.use(express.static(‘public’));

    为了提供对静态资源文件(图片,css,js文件)的服务,请使用Express内置的中间函数express.static

    传递一个包含静态资源的目录给express.static中间件用于立即开始提供文件。 比如用以下代码来提供public目录下的图片、css文件和js文件:

    app.use(express.static('public'));
    

    如果前台想请求后台public目录下images/08.jpg静态的图片资源
    通过: http://localhost:3000/images/08.jpg

    通过多次使用express.static中间件来添加多个静态资源目录:

    app.use(express.static('public'));
    app.use(express.static('file'));
    

    Express将会按照你设置静态资源目录的顺序来查看静态资源文件。

    为了给静态资源文件创建一个虚拟的文件前缀(文件系统中不存在),可以使用express.static函数指定一个虚拟的静态目录,如下:

    app.use('/static', express.static('public'));
    

    现在你可以使用‘/static’作为前缀来加载public文件夹下的文件了。

    比如: http:// localhost:3000/static/image/kitten.jpg


    get/post

    get

    “读取“一个资源。比如Get到一个html文件。反复读取不应该对访问的数据有副作用。

    post

    例如,在页面里<form> 标签会定义一个表单。点击其中的submit元素会发出一个POST请求让服务器做一件事。这件事往往是有副作用的,不幂等的。

    post是一种提交。

    4. 客户端的编写

    socket.io 快速入门教程——聊天应用

    在上面的这个代码里面,我们对访问 localhost:3000 采用 res.send() 方法,让其返回一个网页。这样显然对于前端并不友好。

    替代的方法是新建一个 index.html 文件作为服务器响应。

    现在我们用 sendFile 来重构之前的回调:

    app.get('/', function(req, res){
    res.sendFile(__dirname + '/index.html');
    });
    

    __dirname指的是当前文件所在文件夹的绝对路径。

    index.html 内容如下:

    <!doctype html>
    <html>
      <head>
        <title>Socket.IO chat</title>  <!--网页名称-->
        <style>
          * { margin: 0; padding: 0; box-sizing: border-box; }
          body { font: 13px Helvetica, Arial; }
          form { background: #000; padding: 3px; position: fixed; bottom: 0; width: 100%; }
          form input { border: 0; padding: 10px; width: 90%; margin-right: .5%; }
          form button { width: 9%; background: rgb(130, 224, 255); border: none; padding: 10px; }
          #messages { list-style-type: none; margin: 0; padding: 0; }
          #messages li { padding: 5px 10px; }
          #messages li:nth-child(odd) { background: #eee; }
        </style>
      </head>
      <body>
        <ul id="messages"></ul>
        <form action="">
          <input id="m" autocomplete="off" /><button>Send</button>
        </form>
      </body>
    </html>
    

    1. margin 属性为“外边距”,指的是围绕在元素边框的空白区域;
    2. Padding 属性为“内边距”,定义元素边框与元素内容之间的空间。
    3. box-sizing 是设置盒子模型用的,他其实是设置容器最终的尺寸的计算方法,盒子的计算方法如下: width(宽度) + padding(内边距) + border(边框) = 元素实际宽度
      height(高度) + padding(内边距) + border(边框) = 元素实际高度 上面的计算方法是按照box-sizing:content-box来说的,根据这种设置办法是,先规定了显示区域的大小,在加上边框和内边距就是元素最终显示的大小 还有另外一种模式,就是box-sizing:border-box,他的使用方式就是,先规定了最终显示的区域大小,实际内容展示区域是根据最终区域大小减去边框和内边距,自适应比较强,有时候比较方便页面布局一些。
    4. font 规定文本的字体、字体尺寸、字体颜色。

    日后再补。

    5. 集成 Socket.IO

    Socket.IO 由两部分组成:

    • 一个服务端用于集成 (或挂载) 到 Node.JS HTTP 服务器: socket.io
    • 一个加载到浏览器中的客户端: socket.io-client

    开发环境下, socket.io 会自动提供客户端。

    Socket.IO 的核心理念就是允许发送、接收任意事件和任意数据。任意能被编码为 JSON 的对象都可以用于传输。

    6. jQuery

    $就是jQuery的别称。

    jQuery就是jQuery库提供的一个函数.(好像也不仅仅只是函数, 因为还有 $.ajax(options) 这样的使用,等同 jQuery.ajax(options))

    这个函数的作用是根据 () 里的参数进行查找和选择html文档中的元素, 函数作用之一就是GetElementByID的代替,但()内不仅可以是ID,还可以是各类选择器。

    比如:

    $(document)就是 选取整个文档对象。

    7. HTML

    ![img](Web 课程设计.assets/02A7DD95-22B4-4FB9-B994-DDB5393F7F03.jpg)

    • <!DOCTYPE html> 声明为 HTML5 文档
    • <html> 元素是 HTML 页面的根元素
    • <head> 元素包含了文档的元(meta)数据,如 <meta charset=“utf-8”> 定义网页编码格式为 utf-8
    • <title> 元素描述了文档的标题
    • <body> 元素包含了可见的页面内容
    • <h1> 元素定义一个大标题
    • <p> 元素定义一个段落

    学习过程中的代码

    前期的学习到这里结束。

    接下来放一段到此为止的代码。

    服务端:

    const { data } = require('jquery');
    const app = require('express')();
    const http = require('http').Server(app);
    const io = require('socket.io')(http);
    
    app.get('/', function(req, res){
        res.sendFile(__dirname + '/index.html');
        console.log("主页 get 请求");
    });
    
    
    io.on('connection', function(socket){
        console.log("一位用户连接");
        socket.on('chat message', function(msg){
            console.log('message: ' + msg);
            io.emit('chat message', msg);
        });
        socket.on('disconnect', function(){
            console.log('用户关闭连接');
        });
    });
    
    http.listen(3000, function(){
        console.log('http://127.0.0.1:3000');
    });
    

    客户端

    <!doctype html>
    <html>
    <head>
        <title>Socket.IO chat</title>
        <style>
            * { margin: 0; padding: 0; box-sizing: border-box; }
            body { font: 13px Helvetica, Arial; }
            form { background: #000; padding: 3px; position: fixed; bottom: 0; width: 100%; }
            form input { border: 0; padding: 10px; width: 90%; margin-right: .5%; }
            form button { width: 9%; background: rgb(130, 224, 255); border: none; padding: 10px; }
            #messages { list-style-type: none; margin: 0; padding: 0; }
            #messages li { padding: 5px 10px; }
            #messages li:nth-child(odd) { background: #eee; }
        </style>
    </head>
    <body>
    <ul id="messages"></ul>
    <form action="">
        <input id="m" autocomplete="off" /><button>Send</button>
    </form>
    
    
    </body>
    <script src="/socket.io/socket.io.js"></script>
    <script src="https://code.jquery.com/jquery-1.11.1.js" rel="external nofollow" ></script>
    <script>
        $(function () {
            var socket = io();
            $('form').submit(function(){
                socket.emit('chat message', $('#m').val());
                $('#m').val('');
                return false;
            });
            socket.on('chat message', function(msg){
                $('#messages').append($('<li>').text(msg));
            });
        });
    </script>
    </html>
    

    文件结构

    接下来正式开始。我将在上面代码的基础上修改。


    开始

    本地数据库

    建立数据库

    数据库建表

    index.js文件添加依赖及定义,现在定义部分如下

    const { data } = require('jquery');
    const express=require('express');
    const app = require('express')();
    const http = require('http').Server(app);
    const io = require('socket.io')(http);
    const mysql = require('mysql');
    const url = require('url');
    const fs = require('fs');
    const { Console } = require('console');
    const { query } = require('express');
    const PORT = 3000;
    

    后端代码

    const { data } = require('jquery');
    const express=require('express');
    const app = require('express')();
    const http = require('http').Server(app);
    const io = require('socket.io')(http);
    const mysql = require('mysql');
    const url = require('url');
    const fs = require('fs');
    const { Console } = require('console');
    const { query } = require('express');
    const Front=__dirname +"/Front/";
    const PORT = 3000;
    
    const _cilents=[];          //在线的名称
    
    //数据库连接
    const connection = mysql.createConnection({
        host: 'localhost',
        user: 'root',
        password: 'mhqdcqxs',
        database: 'ChatProject'
    });
    
    //从数据库中查询
    function select_user(data,callback){
        //连接数据库开始查询
        let sql = 'SELECT * FROM user where ac = \''+data.username+'\';';
        connection.query(sql,function (err, result) {
            if(err){
                console.log('[SELECT ERROR] - ',err.message);
                callback(null)
                //如果查不到就返回null
            }
            //用回调函数表示执行完了。回调函数是哪个?取决于传参。
            //查到了就返回结果
            callback(result);
        });
    }
    
    //插入数据库
    function insert_user(data){
        let sql ='INSERT INTO user VALUES (\''+data.username+'\',\''+data.password+'\');';
        connection.query(sql,(err,result)=>{
            if(err){
                console.log('[INSERT ERROR] - ',err.message);
                return;
            };
        });
    }
    
    app.get('/', function(req, res){
        res.sendFile(Front + 'index.html');
        console.log("主页 get 请求");
    });
    
    io.on('connection', function(socket){
        socket.on('login',function(data){
    
            //寻找是否在线
            var t_cilent = _cilents.find(item => item == data.username);
            if(t_cilent){
                socket.emit('loginFail','该用户已经登录');
                return ;
            }
    
            //从数据库中寻找
            select_user(data,result=>{
                if(result.length){
                    if(result[0].pw != data.password){
                        socket.emit('loginFail','密码错误!');
                        return ;
                    }
                }
                else{
                    insert_user(data);
                }
    
                //记录已经登录的用户
                _cilents.push(data.username);
    
                socket.emit('loginSuccess',_cilents);
    
                //全局广播,来了新用户
                io.emit('updateUser', _cilents);
                socket.username = data.username;
            })
        });
    
        // 用户断开连接的功能
        socket.on('disconnect', () => {
            // 把当前用户的信息删除
            // 找到断开连接的用户的下标
            const idx =_cilents.findIndex(item => item == socket.username)
            // 删除函数,第一个参数是下标,第二个是距离,也就是删几个元素
            _cilents.splice(idx, 1);
            // 告诉所有人,用户发生更新
            io.emit('updateUser', _cilents)
        });
    
        socket.on('sendMessage',data=>{
            var toSocket = null
            //找到接收者在io.sockets.sockets中的位置。
            for (const key in io.sockets.sockets) {
                if (io.sockets.sockets[key].username == data.toName) {
                    toSocket = key
                    break
                }
            }
            if (toSocket) {
                // 发送给指定用户
                socket.to(toSocket).emit('receiveMessage', {
                    msg:data.msg,
                    fromName:data.name,
                    time : data.time,
                    name:data.toName
                })
            }
    
            //将数据存入文件中
            let url = './history/'+data.name+'To'+data.toName+'.txt';
            fs.appendFile(url,'\n'+JSON.stringify(data), err => {if (err) {console.log(err)}});
            if(data.toName != data.name){
                let t_url = './history/'+data.toName+'To'+data.name+'.txt';
                fs.appendFile(t_url,'\n'+JSON.stringify(data), err => {if (err) {console.log(err)}});
            }
        });
    
        socket.on('sendImage',data=>{
            var toSocket = null
            //console.log(io.sockets.sockets)
            for (const key in io.sockets.sockets) {
                if (io.sockets.sockets[key].username == data.toName) {
                    toSocket = key
                    break
                }
            }
            //console.log(data);
            if (toSocket) {
                // 发送给指定用户
                socket.to(toSocket).emit('receiveImage', {
                    image:data.image,
                    fromName:data.name,
                    time : data.time,
                    name:data.toName
                })
            }
    
            //将数据存入文件中
            let url = './history/'+data.name+'To'+data.toName+'.txt';
            fs.appendFile(url,'\n'+JSON.stringify(data), err => {if (err) {console.log(err)}});
            if(data.toName != data.name){
                let t_url = './history/'+data.toName+'To'+data.name+'.txt';
                fs.appendFile(t_url,'\n'+JSON.stringify(data), err => {if (err) {console.log(err)}});
            }
        })
    
    });
    
    http.listen(PORT, function(){
        console.log('http://127.0.0.1:'+PORT+'/');
    });
    

    后面没有了,开发时间太紧没有继续记录,但以上作为一个前置步骤已经比较完整。

  • Web 复习提纲

    Web

    概念

    Web:在计算机网页开发设计中指网页

    发展历程(3个阶段)

    1. 静态文档阶段:

      格式:htm、html、shtml。

    2. 动态网页阶段:

      动态网页指网页具有动态和个性化的交互,而不是动态效果。

      格式:jsp、php、asp。

    3. Web2.0阶段:

      以用户为中心,促进信息交换和协同合作。

      例:博客,微博,百科全书,社交网络,对等计算(P2P),即时信息,基于地理信息服务。

    Web牵涉的技术

    1. 客户端技术
      • HTML
      • CSS:层叠样式表
      • Flash:交互式矢量动画制作技术
      • 客户端脚本技术
    2. 服务器端技术
      • CGI:通用网关接口。
      • ASP
      • PHP:一种开发动态网页技术的名称。
      • ASP.NET:建立动态Web应用程序的技术。
      • JSP:基础是Java。

    HTML

    Web应用开发中的一种客户端技术。网页制作标注性语言,不算程序设计语言。

    定义超文本标记语言

    1. 客户端技术的基础
    2. 用于显示网页信息。
    3. 不需要编译,由浏览器解释执行。

    不区分大小写。

    文档结构

    文档标记若是成对出现,均是以 <?> 开头,以 </?> 结束。注意斜杠方向。

    主要标记

    html 标记

    是HTML文件的开头。

    以 <html> 开头, </html> 结束。

    成对出现。

    head 标记

    头标记,放置文件信息。

    成对出现。

    title 标记

    网页标题标记,内含网页标题。

    定义在 head 标记内

    显示在浏览器顶部。

    成对出现。

    body 标记

    页面主体标记。页面内容定义在 <body> 标记中。

    成对出现。

    常用标记

    • 换行:<br>
    • 段落:<p>
    • 标题:<h?> “?”是一个数字,如 <h1> 表示一级标题。成
    • 居中:<center>
    • 文字列表标记
      • 无序列表 <ul> unordered list 成
      • 有序列表 <ol> ordered list 成

    表格标记

    • 表格标记: <table>

      标记内可以定义属性。

    • 标题标记: <caption>

      标记内可以定义属性。

    • 表头标记: <th>

      标记内可以定义属性。

    • 表格行标记: <tr>

      标记内可以定义属性。

    • 单元格标记: <td>

      标记内可以定义属性。

    表单标记

    表单是类似登录界面用户名文本框和密码文本框的元素。

    • <form> 标记,表单标记,成
    • <input> 标记,表单输入标记 ,
    • <select> 标记,下拉菜单标记,成
    • <textarea> 标记,多行文本标记,一般存在于 <form> 标记中,创造一个可以输入多行文本的输入框。

    form 是一整块表单,可能包含多个输入框,而 input 是单个输入框。

    超链接标记和图片标记

    • 超链接标记:<a> ,成
    • 图像标记:<img> ,成

    CSS

    样式表(层叠样式表)。

    1. 对网页的样式实现了更精确的控制。
    2. 美化页面
    3. 优化网页速度(本身提供很多滤镜效果,避免使用大量图片,压缩文件体积,提高下载速度)

    与HTML的关系:HTML是内容,CSS是形式。

    CSS规则

    CSS的三部分:选择符(选择器)、属性、属性值。

    选择器

    标记选择器

    如a选择器

    <style>
        a{
            <!--属性值-->
        }
    </style>
    

    类别选择器
    ID选择器

    属性

    字体属性,文本属性,背景属性,布局属性,边界属性,列表项目属性,表格属性等。

    属性值

    属性的有效值。

    页面中如何加入css

    1. 行内样式

      通过行内定义样式,控制页面样式。

    2. 内嵌式样式表

      利用 <style></style> 标记将CSS样式包含在页面中。

    3. 链接式样式表

      将 CSS 定义在一个单独的文件中,在 HTML 中通过 <link> 引用。

    Javascript

    脚本语言

    特点

    1. 解释性
    2. 基于对象
    3. 事件驱动
    4. 安全性
    5. 跨平台

    区分大小写。

    行尾分号可有可无。

    弱类型。

    大括号标记代码块。

    注释 // /**/

    Ajax技术

    异步的 JavaScript 与 XML 。

    是 JavaScript 、 XML 、 CSS 、 DOM 等多种已有技术的组合。

    核心: XMLHttpRequest ,一个具有应用程序接口的 JavaScript 对象。

    Ajax 引擎:

    • 用户通过 Ajax 引擎与服务器端通信,返回结果提交给 Ajax 引擎,再由 Ajax 引擎来决定将这些数据插入页面的指定位置。

    优点:

    1. 减轻服务器负担
    2. 把一部分服务器负担的工作转移到客户端
    3. 无刷新更新页面
    4. 可以调用 XML 等外部数据
    5. 基于标准化的并广泛支持的技术不需要下载插件或者小程序

    JSP

    动态网页技术标准。

    技术特征

    1. 跨平台
    2. 业务代码分离
    3. 组件重用
    4. 继承 Java Servlet 功能
    5. 预编译

    基本构成

    1. 指令标签
    2. HTML 语句
    3. 注释
    4. 嵌入 Java 代码
    5. JSP 动作标签

    指令标签

    指令标签不会产生任何内容输出到网页中,主要是定义JSP页面的相关信息。

    <%@ %>

    page 指令

    <%@ page   %>
    

    1. language 属性,语言,目前只能Java
    2. extends 属性,继承的Java类
    3. import 属性,导入的类包
    4. pageEncoding 属性,定义编码格式
    5. contentType 属性,设置mime类型和字符编码

    include 指令

    在 JSP 中包含另一个文件的内容。静态包含,代码不会执行。

    taglib指令

    加载用户自定义标签。

    request 对象

    代表客户端请求信息。

    作用域:一次请求。

    作用

    1. 获取请求参数
    2. 获取 form 表单信息
    3. 获取请求客户端信息
    4. 在作用域中管理属性
    5. cookie管理

    response 对象

    代表的是对客户端的响应。

    将 JSP 容器处理过的对象传回到客户端。

    作用域: JSP 页面内有效。

    作用

    1. 重定向网页
    2. 处理 HTTP 文件头
    3. 设置输出缓冲

    session 对象

    与用户请求相关的对象。服务器自动生成。

    用 Map 类来保存数据,因此保存数据格式为 “key/value” 。其中 value 可以是复杂的对象类型,不仅仅是字符串类型。

    作用域:在一次会话范围内有效。

    作用

    1. 创建及获取 session 信息
    2. 从会话中移除指定的绑定对象
    3. 销毁 session
    4. 会话超时的管理
    5. session 对象的应用

    application 对象

    将信息保存在服务器中,直到服务器关闭。生命周期长,类似于 “全局变量” 。

    作用域:在整个上下文中生效。

    作用

    1. 访问应用程序初始化参数
    2. 管理应用程序环境属性

    Servlet

    是 使用 Java Servlet 接口 运行在 Web 应用服务器上的 Java 程序。

    可以处理 Web 浏览器或其他 HTTP 客户端程序发送的请求。

    Servlet 对象需要布置到 Servlet 容器中。

    Servlet 生命周期

    客户端请求 -> 客户端第一次请求服务

    加载 Servlet -> 容器加载 Servlet 类,放入 Servlet 实例池

    初始化 Servlet 对象 -> Servlet 对象的 init() 方法初始化

    处理请求 -> 容器通过 Servlet 的 service() 方法处理客户端请求,service() 方法中,实例对不同的 HTTP 请求作出不同处理并响应

    处理完成,回收对象 -> Web 容器关闭时,容器调用 Servlet 对象的 destroy() 方法对资源进行释放。此后, Servlet 对象将被垃圾回收器回收

    Servlet 技术特点

    1. 方便、实用的 API 方法
    2. 高效的处理方式
    3. 跨平台
    4. 更加灵活、扩展
    5. 安全性高

    Servlet 配置

    1. 声明 Servlet 对象
    2. 映射 Servlet

    数据库系统

    组成部分

    1. 数据库
    2. 数据库管理系统和应用系统
    3. 数据库管理员

    关键组成部分:数据库管理系统,包括数据库定义、数据查询、数据维护等。

    JDBC

    用于执行 SQL 语句的 API 类包。

    一组 Java 语言编写的类和接口。

    操作

    1. 同数据库建立连接
    2. 向数据库发送 SQL 语句
    3. 处理数据库返回的结果

    优点

    1. JDBC 与 ODBC 相似,便于开发人员理解
    2. JDBC 使软件开发人员可以完全专注于业务逻辑的开发。
    3. JDBC 支持多种关系型数据库,大大增加了软件的可移植性。
    4. JDBC API 是面向对象的,软件开发人员可以对其二次封装,提高代码重用性。

    缺点

    1. 通过 JDBC 访问数据库时速度将受到一定影响。
    2. 虽然 JDBC API 是面向对象的,但通过 JDBC 访问数据库依然是面向关系的。
    3. JDBC 提供了对不同厂家的产品的支持,将对数据源带来影响。

    数据库操作的五大步骤

    1. 加载 JDBC 驱动程序。
    2. 创建 Connection 对象的实例。
    3. 执行 SQL 语句。
    4. 获得查询结果
    5. 关闭连接

    Spring MVC 框架

    Spring MVC 是一款基于 MVC 架构模式的轻量级 Web 框架。

    M:model

    V:view

    C:controller

    目的:

    1. 将 Web 开发模块化
    2. 解耦整体架构
    3. 简化 Web 开发流程

    MVC 设计模式

    三个核心

    1. 模型

      模型代表核心功能。

    2. 视图

      指用户看见并与之交互的界面。即 Java Web 应用程序的外观。

    3. 控制器

      负责交互和将用户输入的数据导入模型。

    三者关系

    ​ 视图:显示数据 发送请求 接收数据更新

    4、选择视图显示给用户↑↓1、发送请求

    ​ 控制器:接收请求 将请求映射到模型

    ​ 3、更新后回复控制器↑↓2、更新模型

    ​ 模型:处理业务流程 通知视图更新

    MVC模式特点

    1. 框架机制

      Servlet 实现

    2. 拦截机制

      • 方法级别的拦截
      • 线程安全
    3. 性能

      零配置

    4. 配置

      项目管理和安全高

    5. 设计思想

      Servlet 扩展

    6. 集成

      继承 Ajax

    体系结构

    1. HTTP 请求
    2. 寻找处理器
    3. 调用处理器
    4. 调用模型处理业务
    5. 得到处理结果
    6. 处理视图映射
    7. 将模型数据传给 View 显示
    8. HTTP 响应

    Spring 的 DAO 模式(书P~259~)

    DAO :数据访问对象,Data Access Object

    作用:将持久性相关的问题与一般业务规则和工作隔离开来。

    SSM

    分别为 Spring 、SpringMVC 、MyBatis 三大框架。

    作用

    使用框架可以减少代码量。框架内有封装好的方法可供使用,枯燥的操作交给框架完成。

  • 世界,你好!

    这是什么?

    这是半糖(站主)的博客发布网站,会尽量保证内容的正确性。

    有什么内容?

    学得比较杂乱,计算机相关、或者书法一类的东西,偶尔可能还有福利。?

    可以注册吗?

    不可以哦,也不许评论,也不许盒我。

    如果内容有误请发送邮件至 [email protected] ,感谢指正。有些文章缺失图片是因为我懒得搞图床了,我会找一个好的方法来共享 PDF 资料。