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,监听文件变化自动重启服务

const express = require('express');//创建一个express实例const app = express();/* app.use((req, res) => {res.json({name: "东振"});}); *///请求示例:http://localhost:3000/name/90app.get('/name/:age', (req, res) => {let { age } = req.params;res.json({name: "东振",age});});app.post('/name', (req, res) => {res.end("tom post");});app.listen(3000, () => {console.log('serve启动成功');});//对比 node 原生写法/* const http = require('http');const serve = http.createServer((req,res)=>{}); */
{"name": "express-demo","version": "1.0.0","description": "","main": "index.js","scripts": {"start":"nodemon ./src/app.js","test": "echo \"Error: no test specified\" && exit 1"},"keywords": [],"author": "","license": "ISC","dependencies": {"express": "^4.17.3"}}
路由的介绍和路由定义规则
- 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(‘服务已启动’); });
<a name="YGCAv"></a>##### express路由API使用1. 定义一个路由,满足不论客户端以什么样的方式发送请求都能得到响应使用all这个api,app.all('/demo',(req,res)=>{});```javascriptconst express = require('express');const app = express();app.all('/demo', (req,res) => {res.json({message: "demo",method: req.method});});app.listen(3000, () => {console.log('服务已启动');});
- 定义一个路由,忽略uri,无论用户使用任何路径,服务器都可以响应
使用all这个api,app.all(‘*’,(req,res)=>{});
const express = require('express');const app = express();app.all('*', (req,res) => {res.json({message: "demo",method: req.method,uri:req.path});});app.listen(3000, () => {console.log('服务已启动');});
- 以上两个需求,也可以使用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(‘服务已启动’); });
4. 如何做路由的拆分(app是application,一个web 服务的实例)express.router进行路由拆分:<br />访问路径:127.0.0.1:3000/member/list```javascriptconst express = require('express');const app = express();const memberRouter = require('./member.router');const skuRouter = require('./sku.router');//注册路由app.use('/member', memberRouter);app.use('/sku', skuRouter);app.listen(3000, () => {console.log('服务已启动');});
const express = require('express');const router = express.Router();// router.[method] //get/put/post/delete// router.all// router.userouter.get('/list',(req,res)=>{res.json({list:[{id:"001",name:"李四"}]});});module.exports = router;
中间件
- 什么是express的中间件?
- 内置中间件和第三方中间件介绍
- 自定义中间件
例如: ```javascript const express = require(‘express’); const app = express();//中间件完整结构(类比生活中的插排)//1.是一个函数//2.函数入参err,req,res,next-->functionfunction demo_middleware(err,req,res,next){//1.异常//2.处理业务功能,然后转交控制权--next//3.响应请求--结束响应-->当作路由的处理函数}
//中间件完整结构(类比生活中的插排) //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. app级别- 注册的时候,一定是在最顶级- app.use-->api去加载进来```javascriptconst express = require('express');const app = express();function middlewareApplication(req,res,next){console.log('每次收到请求,都会经过我');next();}app.use(middlewareApplication);app.listen(3000, () => {console.log('服务启动成功');});
内置中间件
- express.static ```javascript const express = require(‘express’); const app = express();
//加载一个static的中间件 / 第一个参数就是路径 第二个参数是配置参数/ app.use(express.static(‘static’, { extensions: [“html”, “htm”] }));
app.listen(3000, () => { console.log(‘服务启动成功’); });
- express.json- express.urlencoded第三方中间件<br />npm install cookie-parser2. router级别```javascriptconst express = require('express');const app = express();const userRouter = require('../router/user_router');app.use(function(req,res,next){console.log('from application middleware');next();});app.use('/user',userRouter);app.listen(3000, () => {console.log('服务启动成功');});
第一种方式
const express = require('express');const router = express.Router();//router级别的中间件router.use(function(req,res,next){console.log('from router middleware');next();});//路由其实是一个中间件的概念.router.get('/demo',(req,res)=>{res.json({message:'from router demo'});});module.exports = router;
第二种方式,在路由内部使用中间件
const express = require('express');const router = express.Router();//1.router级别的中间件router.use(function (req, res, next) {console.log('from router middleware');next();});function vlaid_login_params(req, res, next) {let { username, password } = req.query;if (!username || !password) {res.json({message: "参数校验失败"});} else {//在req或者是res中随便定义一个属性req.formdata = {username,password}next();}}//路由其实是一个中间件的概念.//2.路由内部使用中间件router.get('/login', [vlaid_login_params/* middleware 一系列的中间件 */], (req, res) => {let {formdata} = req;res.json({formdata,message: 'from router demo'});});module.exports = router;
第三方router级中间件
npm i multer -s
- 异常处理(app级别、router级别)
异常处理
- 异常捕获(express框架会捕获这些异常并抛出给前端,由于展示效果不太友好,可以定义一个处理异常的中间件,抛给前端做依据,让前端做异常展示优化)

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

express不认为404是错误
const express = require('express');const app = express();app.get('/login', (req, res) => {throw new Error('测试异常处理');});function handleErrorMiddleWare(err, req, res, next) {if (err) {let { message } = err;res.status(500).json({message: `${message || "服务器内部异常"}`,});} else { }}function handle404(req, res, nex) {res.json({message: "404"});}/**处理404,因为express框架没有将404划分到异常一边,所以在处理404时,思路就是别的路由都处理不了之后我处理,在编写时位置靠后放**/app.use(handle404);//将处理异常的中间件放到所有路由的最后面方便收集并处理异常app.use(handleErrorMiddleWare);app.listen(3000, () => {console.log('服务启动成功');});
- Express内置异常处理
自定义异常处理
//定义一个中间件----- 层层抛出异常function handleErr(req,res,next){try {throw new Error('抛出异常');} catch (error) {next(error);//传递给下一层,异常处理一定是收口的,统一处理}//Promise.then().catch(next);}
mySql的安装和使用
mySql中文官网:https://www.mysqlzh.com/
下载地址:https://cdn.mysql.com//Downloads/MySQLInstaller/mysql-installer-community-8.0.28.0.msi
安装:一路next即可,遇到execute点击,然后继续nextsequelize集成和使用
什么是ORM?对象管理模型。将数据库中的表,以对象的形式展示。对象与表是关联的。sequelize是其中一种
- sequelize的作用,数据库与nodejs关联,将数据库以对象的形式操作
- 在nodejs应用中集成sequelize(sequelize中文网:https://www.sequelize.com.cn/ 关联sequelize-cli地址:https://www.sequelize.com.cn/other-topics/migrations)
- npm i sequelize sequelize-cli -save
- 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>
备注:config、migrations(数据库迁移文件)、seeders(初始化脚本)、models(ORM中比较重要的部门,跟数据库表关联)3. 创建express-demo数据库4. 创建一个名叫User 的模型(models文件夹)--attributes 后跟表字段<br />--name 模型名称(表名)<br />npx sequelize-cli model:generate --name User --attributes name:string5. 安装mysql驱动npm i mysql26. 运行迁移,将User模型同步到数据库(在数据库中创建表)--env 后跟迁移环境(config.json中定义:key)<br />npx sequelize-cli db:migrate --env=development7. 尝试添加数据```javascriptconst express = require('express');const app = express();const models = require("../models");function handleNameNull(req, res, next) {let { name } = req.query;if (!name) {res.statusCode = 500;res.json({message: "缺少name参数"});} else {req.formdata = {name};next();}}app.get('/create', [handleNameNull], async (req, res) => {let { formdata } = req;//promise user--> sequelize对象let user = await models.User.create({name: formdata.name});res.json({user,message: "创建成功!"});});app.get('/list', async (req, res) => {let list = await models.User.findAll();//查询全部数据res.json({list});});app.get('/detail/:id', async (req, res) => {let { id } = req.params;let detail = await models.User.findOne({where: {id: id}});res.json({detail});});app.listen(3000, () => {console.log("启动成功!");});
{"name": "express-middleware-demo","version": "1.0.0","description": "","main": "index.js","scripts": {"start": "nodemon ./src/app.js","test": "echo \"Error: no test specified\" && exit 1"},"keywords": [],"author": "","license": "ISC","dependencies": {"express": "^4.17.3","mysql2": "^2.3.3","nodemon": "^2.0.15","sequelize": "^6.17.0","sequelize-cli": "^6.4.1"}}
