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/90
app.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)=>{});
```javascript
const 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
```javascript
const 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.use
router.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-->function
function 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去加载进来
```javascript
const 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-parser
2. router级别
```javascript
const 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数据库
![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. 创建一个名叫User 的模型(models文件夹)
--attributes 后跟表字段<br />--name 模型名称(表名)<br />npx sequelize-cli model:generate --name User --attributes name:string
5. 安装mysql驱动
npm i mysql2
6. 运行迁移,将User模型同步到数据库(在数据库中创建表)
--env 后跟迁移环境(config.json中定义:key)<br />npx sequelize-cli db:migrate --env=development
7. 尝试添加数据
```javascript
const 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"
}
}