Article Directory
Express
What is Express?
Express is a fast, open and minimalist web development framework based on the Node.js platform
basic use
Install
Run in the root directory where the project is located:
npm i [email protected]
Create a basic web server
//导入 express
const express = require('express')
// 创建 web 服务器
const app = express()
//
app.get('/user/:id', (res, req) => {
res.send() //向客户端响应文本或字符串
req.query() //默认是个空对象;可以获取到客户端发送过来的查询参数例 ?name=zs&age=20
req.params //默认空对象,可以访问到URL中,通过: 匹配到的动态参数[:id]
// :必须写 id可以任意修改,它是参数的名字
//还可以写多个 'user/:id/:name/:age'
})
// 调用 app.listen(端口号, 启动成功后的回调函数) ,启动服务器
app.listen(80,() => {
console.log('express server running at http://127.0.0.1')
})
Listen for GET requests
app.get('URL', function(res, req) {
})
// res : 请求对象(包含与请求相关的属性和方法)
// req : 响应对象(包含与响应相关的属性和方法)
Listen for POST requests
app.post('URL', function(res, req) {
})
express.static()
Through this function, we can create a static resource server very conveniently, and open access to files in a certain directory; the directory name storing static files will not appear in the url
app.use(express.static('public'))
Host multiple static resources
That is, calling the express.static() function multiple times
When accessing static resource files, the express.static() function will find the required files according to the order in which the directories are added
ALL+ shang
mount path prefix
app.use('/abc',express.static('./abc'))
mount prefix before path
nodemon
Monitor changes in project files. When the code is modified, nodemon will automatically restart the project for us
Install
npm install -g nodemon
use
Change node to nodemon
routing
The routing in express is the mapping relationship : the mapping relationship between the client's request and the server processing function
It is divided into three parts: the type of request (METHOD), the URL address of the request (PATH), and the processing function (HANDLER):
app.METHOD(PATH, HANDLER)
route matching
- Match according to the order of definition
- The corresponding processing function will only be called when the request type and the requested URL match successfully at the same time
Modular Routing
//导入 express
const express = require('express')
//创建路由对象
const router = express.Router()
//挂载具体的路由
router.get('/', (req, res) => {
})
router.post('/',(req, res) => {
})
//向外导出路由对象
module.exports = router
Register routing module
const express = require('express')
const app = express()
const router = require('./url')
//注册路由模块
app.use(router)
app.use() //函数作用,注册全局中间件
Add a prefix to the routing module
app.use('/abc',router)
middleware
Format
function(req, res, next)
The role of the next function
The next function is the key to realize the continuous invocation of multiple middleware, and it means to transfer the flow relationship to the next middleware or route.
How to use middleware
const express = require('express')
const app = express()
//定义一个最简单的中间件函数
const mw = function(req, res, next) {
//把流转关系转交给下一个中间件或路由
next()
}
app.listen(80,() => {
})
Global middleware
Any request initiated by the client will trigger the middleware after reaching the server, which is called globally effective middleware
app.use(mw)
Short form global middleware
app.use((req, res, next) => {
next()
})
effect:
Multiple middleware share the same req and res. Based on this feature, we can uniformly add custom properties or methods to the req and res objects in the upstream middleware for downstream middleware or routing to use
locally valid middleware
Middleware without app.use()
const express = require('express')
const app = express()
const mw1 = (req ,res ,next) => {
next()
}
app.get('/',mw1,(req, res) => {
//mw1只在此函数中生效
//若有多个局部中间件 添加到mw1后面,用逗号(,)隔开
})
app.post('/',(req, res) => {
})
app.listen(80, () => {
})
Notes on using middleware
- Be sure to register middleware before routing
- Multiple middleware can be called continuously for processing
- Don't forget to call the next() function
- In order to prevent code logic confusion, do not write additional code after calling the next() function
- When multiple middlewares are called continuously, req and res objects are shared between multiple middlewares
Classification of middleware
Route-level middleware
error level middleware
//定义错误级别的中间件, 捕获整个项目的异常错误, 从而防止程序的崩溃
app.use(err, req, res, next) => {
res.send('Error:' + err.message)
}
//错误级别中间件要放在所有路由之后
Express built-in middleware
- express.static
- express.json parses request body data in JSON format
- express.urlencoded parses request body data in URL-encoded format
The req.body attribute accepts the request body data sent by the client;
If you do not configure an intermediate for parsing form data, req.body is equal to undefined by default
app.use(express.json()) //内置中间件
app.use(express.urlencoded({
extended:false}))
used in routingreq.body
use of database
pk: primary key, unique identifier
NN: Value is not allowed to be empty
UQ: unique value
AI: value auto increment
Default/Expression : default value
What is SQL?
SQL is a structured query language, a programming language specially used to access and process databases. It allows us to manipulate the data in the database in the form of editing.
--
note
From the [table] specified by FROM, query [all] data, * means [all columns]
select * from 表名称
From the [table] specified by FROM, query the data of the specified column name
select 列名称 from 表名称
Insert a new row of data into the data table
insert into 表名称(列1,列2...) values (值1, 值2,...)
modify the data in the table
update 表名称 set 列名称 = 新值 where 列名称 = 某值
Multiple column changes, separated by commas
- update specifies which data to update
- SET specifies the new value corresponding to the column
- Use where to specify the update conditions
delete row in table
delete form table name where id=
Keywords are not case sensitive
where child clause
The where clause is used to limit the selection criteria.
<>和!=都表示不等号
and must satisfy multiple conditions at the same time
or either condition is satisfied
order by sorts the result set according to the specified column, the default is sorted in ascending order (ASC) (DESC keyword, can be sorted in descending order)
select * from users order by id
default ascending
[External link picture transfer failed, the source site may have an anti-leeching mechanism, it is recommended to save the picture and upload it directly (img-tM1nzSVY-1647130047397)(C:\Users\Lenovo\Desktop\typora\img\orderby.png)]
select * from users order by id desc
descending order
[External link picture transfer failed, the source site may have an anti-leeching mechanism, it is recommended to save the picture and upload it directly (img-e8nLNXfo-1647130047399)(C:\Users\Lenovo\Desktop\typora\img\orderbydesc.png)]
For multiple collations, separate them with commas
count(*) function
The count(*) function is used to return the total number of data items in the query result
select count(*) from 表名称
as keyword
alias the column
select username as uname, password as upwd from users
Operate MySQL in the project
npm install mysql
Establish a connection to the mysql database
const db = mysql.createPool({
host: '127.0.0.1', //数据库的 IP 地址
user: 'root', //登录数据库的账号
password: 'admin123', //登录数据库的密码
database: 'my_db_01' //指定要操作那个数据库
})
Test that the MySQL module is working properly
db.query('select 1',(err, results) => {
if(err) return console.log(err.message)
console.log(results)
})
Query all data in the users table
const sqlStr = 'select * from users'
db.query(sqlStr, (err, result) => {
if(err) return console.log(err.message)
//如果使用 select 查询语句,执行的结果为 数组
console.log(result)
})
insert data
//要插入到 users 表中的数据对象
const user = {
username: 'Spider-Man', password: 'pcc121'}
//待执行的 SQL 语句, 其中英文的 ? 表示占位符
const sqlStr = 'insert into users(username, password) value(?, ?)'
//使用数组的形式依次为 ? 占位符指定具体的值
db.query(sqlStr, [user.username, user.password], (err, results) => {
if(err) return console.log(err.message)
//如果执行 insert into 插入语句, 则 results 是一个对象
if(results.affectedRows === 1) {
//判断是否插入成功
console.log('插入数据成功')
}
})
A convenient way to insert data
//要插入到 users 表中的数据对象
const user = {
username: 'Spider-Man', password: 'pcc121'}
//待执行的 SQL 语句, 其中英文的 ? 表示占位符
const sqlStr = 'insert into users SET ?'
//直接将数据对象作为占位符
db.query(sqlStr, user, (err, results) => {
if(err) return console.log(err.message)
//如果执行 insert into 插入语句, 则 results 是一个对象
if(results.affectedRows === 1) {
//判断是否插入成功
console.log('插入数据成功')
}
})
update data
const user = {
id: 6, username: 'aaa', password: '000'}
const sqlStr = 'update users set username=?, password=? where id=?'
db.query(sqlStr, [user.username, user.password, user.id], (err, results) => {
if(err) return console.log(err.message)
//如果执行 insert into 插入语句, 则 results 是一个对象
if(results.affectedRows === 1) {
//判断是否插入成功
console.log('更新成功')
}
})
A convenient way to update data
// 要更新的数据对象
const user = {
id = 7, username: 'aaaa', password: '0000'}
// 要执行的 sql 语句
const sqlStr = 'update users set ? where id=?'
//调用 db.query() 执行sql语句,同时使用数组依次为占位符指定具体的值
db.query(sqlStr, [user,user.id], (err, results) => {
if(err) return console.log(err.message)
if(results.affectedRows === 1) {
console.log('更新数据成功')
}
})
delete data
const delete = 'delete from users where id=?'
db.query(sqlStr, 5, (err, results) => {
if(err) return console.log(err.message)
if(results.affectedRows === 1) {
console.log('删除数据成功')
}
})
mark for deletion
const sqlStr = 'update users set status=? where id=?'
db.query(sqlStr, [1, 6], (err, results) => {
if(err) return console.log(err.message)
if(results.affectedRows === 1) {
console.log('删除数据成功')
}
})
Front-end and back-end development models
Authentication
Server-side rendering uses Session authentication mechanism
The stateless nature of the HTTP protocol means that each HTTP request of the client is independent, there is no direct relationship between multiple consecutive requests, and the server is not destined to retain the state of each HTTP request.
How to break through the stateless limitation of HTTP?
A cookie is a string of no more than 4kb stored in the user's browser . It consists of a name, a value, and several other optional attributes used to control the validity period, security, and scope of use of the cookie.
Cookies under different domain names are independent. Whenever the client initiates a request, all unexpired cookies under the current domain name will be automatically sent to the server together.
Several major features of cookies: 1. Automatic sending 2. Independent domain name 3. Expiration time limit 4. 4KB limit
Role in identity authentication: When the client requests the server for the first time, the server sends an identity authentication cookie to the client in the form of a response header, and the client will automatically save the cookie in the browser.
Subsequently, when the client browser requests the server each time, the browser will automatically send the cookie related to identity authentication to the server in the form of a request header, and the server can find out the identity of the client
Cookies are not secure, please do not use cookies to store important and private data!
Improve the security of identity authentication
How sessions work
Install express-session
npm install express-session
configuration
const express = require('express')
const session = require('express-session')
const app = express()
app.use(
session({
secret: 'keyboard cat',
resave: false,
saveUninitialized: true
}))
store information
req.session.user = req.body
req.sesion.islogin = true
clear session
req.session.destroy()
Clear the session information saved by the server
Front-end and back-end separation using JWT authentication mechanism
JWT consists of three parts:
Header(头部).Payload(有效荷载).Signature(签名)
Use between the three. Separated
The Payload part is the real information of the user, which is a string generated after the user information is encrypted
Header and Signature are security-related parts, just to ensure the security of Token
How to use
Authorization: Bearer <token>
Install JWT related packages
npm install jsonwebtoken express-jwt
jsonwebtoken is used to generate JWT string
express-jwt is used to parse and restore JWT strings into JSON objects
Define the secret key
In order to ensure the security of the JWT string, we specifically define a sercet key for encryption and decryption:
- When generating the JWT string, you need to use the secret key to encrypt the user's information, and finally get the encrypted JWT string
- When parsing and restoring the JWT string to a JSON object, you need to use the secret key for decryption
const secreKey = 'itheima No1 ^_^'
Generate JWT string after login
Parameter 1: User's information object
Parameter two: encrypted key
Parameter 3: configuration object, you can configure the current token string
sign({
username: userinfo.username}, secretKey, {
expiresIn: '100s'})
Revert JWT string to JSON object
req.user() Get user information