web应用基础和第一个express应用

web应用包含java开发的接口和数据库
express是nodejs一种web框架(接收req,处理res,防止网站攻击、处理路由问题)

  • mkdir express-demo 创建文件夹express-demo
  • cd express-demo进入该文件夹
  • npm init -y快速生成npm项目
  • 创建git忽略文件.gitignore,添加node_modules忽略文件夹
  • npm i express -s在生产环境安装express
  • npm i nodemon -d安装nodemon,监听文件变化自动重启服务

20220321144706388.png

  1. const express = require('express');
  2. //创建一个express实例
  3. const app = express();
  4. /* app.use((req, res) => {
  5. res.json({
  6. name: "东振"
  7. });
  8. }); */
  9. //请求示例:http://localhost:3000/name/90
  10. app.get('/name/:age', (req, res) => {
  11. let { age } = req.params;
  12. res.json({
  13. name: "东振",
  14. age
  15. });
  16. });
  17. app.post('/name', (req, res) => {
  18. res.end("tom post");
  19. });
  20. app.listen(3000, () => {
  21. console.log('serve启动成功');
  22. });
  23. //对比 node 原生写法
  24. /* const http = require('http');
  25. const serve = http.createServer((req,res)=>{
  26. }); */
  1. {
  2. "name": "express-demo",
  3. "version": "1.0.0",
  4. "description": "",
  5. "main": "index.js",
  6. "scripts": {
  7. "start":"nodemon ./src/app.js",
  8. "test": "echo \"Error: no test specified\" && exit 1"
  9. },
  10. "keywords": [],
  11. "author": "",
  12. "license": "ISC",
  13. "dependencies": {
  14. "express": "^4.17.3"
  15. }
  16. }

路由的介绍和路由定义规则
  • web 服务如何处理一个客户端请求
  • url—>网络—>dns解析—>目标服务器。(浏览器发送请求URL,通过网络传输数据,DNS域名解析之后找到请求的目标服务器,服务器针对请求做出回应【根据路由规则判断如何响应】)

路由规则:a.根据请求的method区分。b.通过uri(URL中不包含域名端口和参数的部分,比如:https://www.baidu.com/a/b/c.html?q=90)

express路由演示
  • mkdir express-route-demo
  • cd express-route-demo
  • npm init -y
  • mkdir src
  • src下新建app.js
  • npm i express -s、npm i nodemon -d
  • package.json配置运行脚本”scripts”:{“dev”:”nodemon ./src/app.js”} ```javascript const express = require(‘express’);

const app = express();

//1.通过 请求的 方法类型 get/post/put/delete app.get(‘/demo’, (req, res) => { //req:请求对象 //res:服务器响应对象 res.json({ message: “hello express route from get demo” }); });

app.post(‘/demo’, (req, res) => { res.json({ message: “hello express route from post demo” }); });

//2.通过uri app.get(‘/user/byname’, (req, res) => { let { name } = req.query; res.json({ name }); }); app.get(‘/user/byid’, (req, res) => { let { id } = req.query; res.json({ id
}); });

app.listen(3000, () => { console.log(‘服务已启动’); });

  1. <a name="YGCAv"></a>
  2. ##### express路由API使用
  3. 1. 定义一个路由,满足不论客户端以什么样的方式发送请求都能得到响应
  4. 使用all这个api,app.all('/demo',(req,res)=>{});
  5. ```javascript
  6. const express = require('express');
  7. const app = express();
  8. app.all('/demo', (req,res) => {
  9. res.json({
  10. message: "demo",
  11. method: req.method
  12. });
  13. });
  14. app.listen(3000, () => {
  15. console.log('服务已启动');
  16. });
  1. 定义一个路由,忽略uri,无论用户使用任何路径,服务器都可以响应

使用all这个api,app.all(‘*’,(req,res)=>{});

  1. const express = require('express');
  2. const app = express();
  3. app.all('*', (req,res) => {
  4. res.json({
  5. message: "demo",
  6. method: req.method,
  7. uri:req.path
  8. });
  9. });
  10. app.listen(3000, () => {
  11. console.log('服务已启动');
  12. });
  1. 以上两个需求,也可以使用app.use(中间件)实现 ```javascript const express = require(‘express’);

const app = express(); //任何请求方式都可以请求到 app.use(‘/demo’, (req, res) => { res.json({ massage: “demo”, method: req.method }); }); //任何uri都可以响应 app.use((req, res) => { res.json({ massage: “*”, method: req.method, uri: req.path }); }); app.listen(3000, () => { console.log(‘服务已启动’); });

  1. 4. 如何做路由的拆分(appapplication,一个web 服务的实例)
  2. express.router进行路由拆分:<br />访问路径:127.0.0.1:3000/member/list
  3. ```javascript
  4. const express = require('express');
  5. const app = express();
  6. const memberRouter = require('./member.router');
  7. const skuRouter = require('./sku.router');
  8. //注册路由
  9. app.use('/member', memberRouter);
  10. app.use('/sku', skuRouter);
  11. app.listen(3000, () => {
  12. console.log('服务已启动');
  13. });
  1. const express = require('express');
  2. const router = express.Router();
  3. // router.[method] //get/put/post/delete
  4. // router.all
  5. // router.use
  6. router.get('/list',(req,res)=>{
  7. res.json({
  8. list:[
  9. {
  10. id:"001",
  11. name:"李四"
  12. }
  13. ]
  14. });
  15. });
  16. module.exports = router;

中间件
  • 什么是express的中间件?
  • 内置中间件和第三方中间件介绍
  • 自定义中间件
    1. //中间件完整结构(类比生活中的插排)
    2. //1.是一个函数
    3. //2.函数入参err,req,res,next-->function
    4. function demo_middleware(err,req,res,next){
    5. //1.异常
    6. //2.处理业务功能,然后转交控制权--next
    7. //3.响应请求--结束响应-->当作路由的处理函数
    8. }
    例如: ```javascript const express = require(‘express’); const app = express();

//中间件完整结构(类比生活中的插排) //1.是一个函数 //2.函数入参err,req,res,next—>function function demo_middleware(err,req,res,next){ //1.异常 //2.处理业务功能,然后转交控制权—next //3.响应请求—结束响应—>当作路由的处理函数 }

function valid_name_middleware(req,res,next){ let {name} = req.query; if(!name){ res.json({ message:”缺少name参数” }); }else { next(); } }

app.use(‘*’,valid_name_middleware);

app.get(‘/test’,(req,res)=>{ res.json({ message:”test” }); }); app.listen(3000, () => { console.log(‘服务启动成功’); });

  1. 使用场景:
  2. 1. app级别
  3. - 注册的时候,一定是在最顶级
  4. - app.use-->api去加载进来
  5. ```javascript
  6. const express = require('express');
  7. const app = express();
  8. function middlewareApplication(req,res,next){
  9. console.log('每次收到请求,都会经过我');
  10. next();
  11. }
  12. app.use(middlewareApplication);
  13. app.listen(3000, () => {
  14. console.log('服务启动成功');
  15. });

内置中间件

  • express.static ```javascript const express = require(‘express’); const app = express();

//加载一个static的中间件 / 第一个参数就是路径 第二个参数是配置参数/ app.use(express.static(‘static’, { extensions: [“html”, “htm”] }));

app.listen(3000, () => { console.log(‘服务启动成功’); });

  1. - express.json
  2. - express.urlencoded
  3. 第三方中间件<br />npm install cookie-parser
  4. 2. router级别
  5. ```javascript
  6. const express = require('express');
  7. const app = express();
  8. const userRouter = require('../router/user_router');
  9. app.use(function(req,res,next){
  10. console.log('from application middleware');
  11. next();
  12. });
  13. app.use('/user',userRouter);
  14. app.listen(3000, () => {
  15. console.log('服务启动成功');
  16. });

第一种方式

  1. const express = require('express');
  2. const router = express.Router();
  3. //router级别的中间件
  4. router.use(function(req,res,next){
  5. console.log('from router middleware');
  6. next();
  7. });
  8. //路由其实是一个中间件的概念.
  9. router.get('/demo',(req,res)=>{
  10. res.json({
  11. message:'from router demo'
  12. });
  13. });
  14. module.exports = router;

第二种方式,在路由内部使用中间件

  1. const express = require('express');
  2. const router = express.Router();
  3. //1.router级别的中间件
  4. router.use(function (req, res, next) {
  5. console.log('from router middleware');
  6. next();
  7. });
  8. function vlaid_login_params(req, res, next) {
  9. let { username, password } = req.query;
  10. if (!username || !password) {
  11. res.json({
  12. message: "参数校验失败"
  13. });
  14. } else {
  15. //在req或者是res中随便定义一个属性
  16. req.formdata = {
  17. username,
  18. password
  19. }
  20. next();
  21. }
  22. }
  23. //路由其实是一个中间件的概念.
  24. //2.路由内部使用中间件
  25. router.get('/login', [vlaid_login_params/* middleware 一系列的中间件 */], (req, res) => {
  26. let {formdata} = req;
  27. res.json({
  28. formdata,
  29. message: 'from router demo'
  30. });
  31. });
  32. module.exports = router;

第三方router级中间件
npm i multer -s

  1. 异常处理(app级别、router级别)

这节课程demo项目结构:
20220322154008160.png

异常处理
  • 异常捕获(express框架会捕获这些异常并抛出给前端,由于展示效果不太友好,可以定义一个处理异常的中间件,抛给前端做依据,让前端做异常展示优化)

20220322155434823.png

  1. const express = require('express');
  2. const app = express();
  3. app.get('/login',(req,res)=>{
  4. throw new Error('测试异常处理');
  5. });
  6. function handleErrorMiddleWare(err,req,res,next){
  7. if(err){
  8. let {message} = err;
  9. res.status(500).json({
  10. message:`${message || "服务器内部异常"}`,
  11. });
  12. }else{}
  13. }
  14. //将处理异常的中间件放到所有路由的最后面方便收集并处理异常
  15. app.use(handleErrorMiddleWare);
  16. app.listen(3000, () => {
  17. console.log('服务启动成功');
  18. });

20220322155530519.png
express不认为404是错误

  1. const express = require('express');
  2. const app = express();
  3. app.get('/login', (req, res) => {
  4. throw new Error('测试异常处理');
  5. });
  6. function handleErrorMiddleWare(err, req, res, next) {
  7. if (err) {
  8. let { message } = err;
  9. res.status(500).json({
  10. message: `${message || "服务器内部异常"}`,
  11. });
  12. } else { }
  13. }
  14. function handle404(req, res, nex) {
  15. res.json({
  16. message: "404"
  17. });
  18. }
  19. /**
  20. 处理404,因为express框架没有将404划分到异常一边,
  21. 所以在处理404时,思路就是别的路由都处理不了之后
  22. 我处理,在编写时位置靠后放
  23. **/
  24. app.use(handle404);
  25. //将处理异常的中间件放到所有路由的最后面方便收集并处理异常
  26. app.use(handleErrorMiddleWare);
  27. app.listen(3000, () => {
  28. console.log('服务启动成功');
  29. });
  1. npm i sequelize sequelize-cli -save
  2. npx sequelize-cli init ```bash PS D:\OpenSource\express-middleware-demo> npm i sequelize sequelize-cli -save

added 70 packages, and audited 237 packages in 19s

23 packages are looking for funding run npm fund for details

1 high severity vulnerability

To address all issues, run: npm audit fix

Run npm audit for details. PS D:\OpenSource\express-middleware-demo> npx sequelize-cli init

Sequelize CLI [Node: 14.19.1, CLI: 6.4.1, ORM: 6.17.0]

Created “config\config.json” Successfully created models folder at “D:\OpenSource\express-middleware-demo\models”. Successfully created migrations folder at “D:\OpenSource\express-middleware-demo\migrations”. Successfully created seeders folder at “D:\OpenSource\express-middleware-demo\seeders”. PS D:\OpenSource\express-middleware-demo>

  1. 备注:configmigrations(数据库迁移文件)、seeders(初始化脚本)、models(ORM中比较重要的部门,跟数据库表关联)
  2. 3. 创建express-demo数据库
  3. ![20220323160552125.png](https://cdn.nlark.com/yuque/0/2022/png/1247361/1648022801595-07bdc02d-4ee4-4ece-9c9f-eca19ece2113.png#clientId=u4497031f-e1fd-4&crop=0&crop=0&crop=1&crop=1&from=ui&id=uf10e3258&margin=%5Bobject%20Object%5D&name=20220323160552125.png&originHeight=825&originWidth=1182&originalType=binary&ratio=1&rotation=0&showTitle=false&size=80693&status=done&style=none&taskId=u8f1f4e85-c573-4e24-ba14-612a2a19947&title=)
  4. 4. 创建一个名叫User 的模型(models文件夹)
  5. --attributes 后跟表字段<br />--name 模型名称(表名)<br />npx sequelize-cli model:generate --name User --attributes name:string
  6. 5. 安装mysql驱动
  7. npm i mysql2
  8. 6. 运行迁移,将User模型同步到数据库(在数据库中创建表)
  9. --env 后跟迁移环境(config.json中定义:key)<br />npx sequelize-cli db:migrate --env=development
  10. 7. 尝试添加数据
  11. ```javascript
  12. const express = require('express');
  13. const app = express();
  14. const models = require("../models");
  15. function handleNameNull(req, res, next) {
  16. let { name } = req.query;
  17. if (!name) {
  18. res.statusCode = 500;
  19. res.json({
  20. message: "缺少name参数"
  21. });
  22. } else {
  23. req.formdata = {
  24. name
  25. };
  26. next();
  27. }
  28. }
  29. app.get('/create', [handleNameNull], async (req, res) => {
  30. let { formdata } = req;
  31. //promise user--> sequelize对象
  32. let user = await models.User.create({
  33. name: formdata.name
  34. });
  35. res.json({
  36. user,
  37. message: "创建成功!"
  38. });
  39. });
  40. app.get('/list', async (req, res) => {
  41. let list = await models.User.findAll();//查询全部数据
  42. res.json({
  43. list
  44. });
  45. });
  46. app.get('/detail/:id', async (req, res) => {
  47. let { id } = req.params;
  48. let detail = await models.User.findOne({
  49. where: {
  50. id: id
  51. }
  52. });
  53. res.json({
  54. detail
  55. });
  56. });
  57. app.listen(3000, () => {
  58. console.log("启动成功!");
  59. });
  1. {
  2. "name": "express-middleware-demo",
  3. "version": "1.0.0",
  4. "description": "",
  5. "main": "index.js",
  6. "scripts": {
  7. "start": "nodemon ./src/app.js",
  8. "test": "echo \"Error: no test specified\" && exit 1"
  9. },
  10. "keywords": [],
  11. "author": "",
  12. "license": "ISC",
  13. "dependencies": {
  14. "express": "^4.17.3",
  15. "mysql2": "^2.3.3",
  16. "nodemon": "^2.0.15",
  17. "sequelize": "^6.17.0",
  18. "sequelize-cli": "^6.4.1"
  19. }
  20. }