Node.js 框架 Express 介绍
Express 是一个极简且灵活的 Node.js Web 应用框架,提供了一组强大而实用的功能,用于构建 Web 应用程序和 API。它简化了 Node.js 原生 HTTP 模块的使用,使开发者能够更轻松地处理路由、请求、响应等任务。
1. 为什么使用 Express?
简化路由:通过路由机制,Express 允许开发者轻松地为不同 URL 创建处理程序。
中间件支持:Express 提供了中间件的支持,可以在请求处理的不同阶段执行特定逻辑。
扩展性强:Express 可以通过各种第三方中间件和插件来扩展功能,如身份验证、日志记录、文件上传等。
支持模板引擎:可以使用模板引擎如 EJS、Pug 渲染动态 HTML 页面。
2. Express 使用
2.1. 安装 Express
npm install express
2.2. 创建 Express 应用
const express = require('express');
const app = express();// 定义一个简单的路由
app.get('/', (req, res) => {res.send('Hello, Express!');
});// 启动服务器
const port = 3000;
app.listen(port, () => {console.log(`Server running at http://localhost:${port}`);
});
2.3. 路由系统
Express 提供了简单的路由机制,允许根据 HTTP 方法和路径定义请求处理程序。路由可以定义为不同的 HTTP 动作(如 GET、POST 等),并绑定到特定的路径上。
app.get('/users', (req, res) => {res.send('Get all users');
});app.post('/users', (req, res) => {res.send('Create a new user');
});app.put('/users/:id', (req, res) => {res.send(`Update user with ID ${req.params.id}`);
});app.delete('/users/:id', (req, res) => {res.send(`Delete user with ID ${req.params.id}`);
});
在这个例子中,我们定义了多个路由来处理不同的 HTTP 请求类型和路径参数。
2.4. 使用中间件
中间件是在 Express 中处理请求和响应的核心机制。中间件函数可以拦截请求,执行某些操作,或者将请求传递给下一个中间件或最终的路由处理程序。
2.4.1. 内置中间件
express.json(): 解析 application/json 类型的请求体。
express.static(): 用于提供静态资源,如图片、CSS 文件等。
// 使用内置中间件解析 JSON 请求体
app.use(express.json());// 使用内置中间件提供静态文件服务
app.use(express.static('public'));
2.4.2. 自定义中间件
自定义中间件可以拦截请求,进行身份验证、日志记录或其他逻辑。
// 自定义中间件,记录请求的时间
app.use((req, res, next) => {console.log('Time:', Date.now());next(); // 调用 next() 传递请求给下一个中间件
});
2.5. 路由器(Router)
Router 是 Express 中的一个子路由器,可以将路由逻辑分组。它使得应用的路由结构更加清晰和模块化。
const express = require('express');
const app = express();
const userRouter = express.Router();// 定义用户相关的路由
userRouter.get('/', (req, res) => {res.send('List of users');
});userRouter.get('/:id', (req, res) => {res.send(`Get user with ID ${req.params.id}`);
});// 将 userRouter 注册到 /users 路径
app.use('/users', userRouter);app.listen(3000, () => {console.log('Server is running on port 3000');
});
2.6. 处理错误
在 Express 中可以通过错误处理中间件捕获并处理路由或其他中间件中的错误。
// 定义路由
app.get('/', (req, res) => {throw new Error('Something went wrong!'); // 抛出错误
});// 错误处理中间件
app.use((err, req, res, next) => {console.error(err.stack);res.status(500).send('Internal Server Error');
});
2.7. 使用模板引擎
Express 支持模板引擎,可以生成动态 HTML 页面。常见的模板引擎有 EJS、Pug、Handlebars 等。
首先安装 EJS:
npm install ejs
然后设置 Express 使用 EJS:
app.set('view engine', 'ejs');// 渲染一个 EJS 模板
app.get('/', (req, res) => {res.render('index', { title: 'My Express App', message: 'Hello, EJS!' });
});
EJS 模板文件(views/index.ejs)的内容示例:
<!DOCTYPE html>
<html><head><title><%= title %></title></head><body><h1><%= message %></h1></body>
</html>
3. 实战项目:用户管理 API
让我们通过一个简单的用户管理 API 来进一步理解 Express 的功能。这是一个处理用户 CRUD(创建、读取、更新、删除)操作的示例。
const express = require('express');
const app = express();app.use(express.json()); // 解析 JSON 请求体// 模拟的用户数据
let users = [{ id: 1, name: 'John' },{ id: 2, name: 'Jane' },
];// 获取所有用户
app.get('/users', (req, res) => {res.json(users);
});// 获取单个用户
app.get('/users/:id', (req, res) => {const user = users.find(u => u.id === parseInt(req.params.id));if (!user) return res.status(404).send('User not found');res.json(user);
});// 创建新用户
app.post('/users', (req, res) => {const user = {id: users.length + 1,name: req.body.name,};users.push(user);res.status(201).json(user);
});// 更新用户
app.put('/users/:id', (req, res) => {const user = users.find(u => u.id === parseInt(req.params.id));if (!user) return res.status(404).send('User not found');user.name = req.body.name;res.json(user);
});// 删除用户
app.delete('/users/:id', (req, res) => {const userIndex = users.findIndex(u => u.id === parseInt(req.params.id));if (userIndex === -1) return res.status(404).send('User not found');users.splice(userIndex, 1);res.status(204).send(); // 204表示无内容
});const port = 3000;
app.listen(port, () => {console.log(`Server is running on port ${port}`);
});
4. 更多中间件与 express 开发细节
在 Express 中,中间件是扩展其功能的核心机制之一,它允许我们在请求处理的不同阶段执行逻辑操作。除了前面提到的内置中间件外,Express 社区中还存在许多强大的第三方中间件,用于处理身份验证、会话、跨域、cookie 等任务。下面我们详细讨论一些常用的中间件,比如 cookie-parser、jsonwebtoken(JWT)、以及其他常见的中间件。
4.1. cookie-parser - 处理 Cookie
cookie-parser 是 Express 中用于解析客户端请求中 Cookie 的中间件。它可以从 HTTP 请求头中解析出 Cookie,并以对象的形式提供给开发者。
安装:
npm install cookie-parser
使用:
const express = require('express');
const cookieParser = require('cookie-parser');
const app = express();// 使用 cookie-parser 中间件
app.use(cookieParser());// 设置 cookie
app.get('/setcookie', (req, res) => {res.cookie('username', 'john_doe');res.send('Cookie has been set');
});// 读取 cookie
app.get('/getcookie', (req, res) => {let username = req.cookies['username'];if (username) {res.send(`Hello, ${username}`);} else {res.send('No cookie found');}
});// 清除 cookie
app.get('/clearcookie', (req, res) => {res.clearCookie('username');res.send('Cookie cleared');
});app.listen(3000, () => {console.log('Server running on port 3000');
});
res.cookie:用于设置 Cookie,支持指定过期时间、加密等。
req.cookies:通过 cookie-parser,可以直接从 req.cookies 读取解析后的 Cookie。
在设置 Cookie 时,可以指定一些选项,如 maxAge、secure 和 httpOnly。
res.cookie('username', 'john_doe', { maxAge: 900000, httpOnly: true });
maxAge:设置 Cookie 的有效期,单位为毫秒。
httpOnly:将 Cookie 标记为仅通过 HTTP 传输,不能通过 JavaScript 获取,增加安全性。
secure:如果设置为 true,Cookie 仅通过 HTTPS 传输。
4.2. 使用 JWT 进行身份验证
jsonwebtoken 是用于生成和验证 JSON Web Tokens(JWT)的库,通常用于在 Web 应用中进行身份验证。JWT 是一种紧凑的、URL 安全的令牌格式,它可以安全地传递信息并且可验证来源。
安装:
npm install jsonwebtoken
使用 JWT 进行身份验证:
首先,我们需要生成一个 JWT 令牌,并在客户端请求时验证该令牌。
const express = require('express');
const jwt = require('jsonwebtoken');
const app = express();app.use(express.json());const secretKey = 'your-secret-key';// 用户登录,生成 JWT 令牌
app.post('/login', (req, res) => {const user = { id: 1, username: req.body.username };const token = jwt.sign(user, secretKey, { expiresIn: '1h' });res.json({ token });
});// 验证 JWT 中间件
const authenticateToken = (req, res, next) => {const token = req.headers['authorization'];if (!token) return res.sendStatus(401);jwt.verify(token.split(' ')[1], secretKey, (err, user) => {if (err) return res.sendStatus(403);req.user = user;next();});
};// 受保护的路由
app.get('/protected', authenticateToken, (req, res) => {res.json({ message: 'This is a protected route', user: req.user });
});app.listen(3000, () => {console.log('Server running on port 3000');
});
解析和验证 JWT 过程:
1. 生成 JWT:使用 jwt.sign() 方法生成一个签名的 JWT,通常包含用户信息和一个加密密钥。生成时可以指定过期时间,如 1h 表示一小时。
2. 验证 JWT:通过 jwt.verify() 验证请求中的 JWT 是否有效。该函数会验证令牌是否通过我们指定的 secretKey 进行签名。
JWT 的好处是可以在客户端和服务器之间传递经过签名的用户信息,而无需在服务器上存储会话状态。
4.3. cors - 处理跨域请求
在 Web 应用开发中,跨域资源共享(CORS)是一种允许浏览器从不同的域请求资源的机制。Express 中的 cors 中间件使得处理跨域请求变得简单。
安装:
npm install cors
使用:
const cors = require('cors');// 使用 CORS 中间件
app.use(cors());// 可以限制允许的源
app.use(cors({ origin: 'http://example.com' }));
选项:
origin:允许的源,可以是一个特定的域名或者 *,表示所有源。
methods:允许的 HTTP 方法,例如 GET,POST,PUT,DELETE。
credentials:设置为 true 时,允许跨域请求发送 Cookie。
4.4. express-session - 会话管理
express-session 是用于在服务器端管理用户会话的中间件,它可以存储会话数据,并通过 session ID 识别用户。对于一些需要状态管理的 Web 应用来说,它是非常重要的。
安装:
npm install express-session
使用:
const session = require('express-session');app.use(session({secret: 'secret-key',resave: false,saveUninitialized: true,cookie: { secure: false } // true 时需要 HTTPS
}));// 设置会话
app.get('/set-session', (req, res) => {req.session.username = 'john_doe';res.send('Session set');
});// 获取会话
app.get('/get-session', (req, res) => {const username = req.session.username;if (username) {res.send(`Hello, ${username}`);} else {res.send('No session found');}
});
选项:
secret:必须提供一个加密密钥来签名会话 ID,确保会话数据的安全。
resave:如果 false,表示只有在会话变化时才会保存到存储中。
saveUninitialized:如果 true,表示即使会话未被修改,也会保存未初始化的会话。
4.5. morgan - 日志记录
morgan 是用于记录 HTTP 请求日志的中间件,可以帮助开发者在开发和调试过程中跟踪请求信息。
安装:
npm install morgan
使用:
const morgan = require('morgan');// 使用 morgan 记录请求日志
app.use(morgan('combined')); // 使用 'combined' 预设格式// 自定义格式
app.use(morgan(':method :url :status :res[content-length] - :response-time ms'));
4.6. body-parser - 处理请求体
虽然 Express 4.16.0 之后内置了对 JSON 和 urlencoded 的解析支持,但 body-parser 仍然是处理请求体的常用中间件。
安装:
npm install body-parser
使用:
const bodyParser = require('body-parser');// 解析 application/json 类型的请求体
app.use(bodyParser.json());// 解析 application/x-www-form-urlencoded 类型的请求体
app.use(bodyParser.urlencoded({ extended: true }));
4.7. 总结
cookie-parser:用于解析和操作客户端的 Cookie。
jsonwebtoken (JWT):用于生成和验证 JSON Web Tokens,适合身份验证。
cors:用于处理跨域资源共享请求。
express-session:用于在服务器端管理用户会话。
morgan:用于记录 HTTP 请求日志,帮助调试。
body-parser:解析请求体,处理 JSON 和表单数据。
这些中间件在 Express 应用中可以解决不同的需求,从身份验证、会话管理、跨域请求到日志记录等,让开发更加高效和模块化。