全栈要懂:
前端:
html+css+js
正则
less/sass/stylus
vue全家桶
react全家桶
webpack
vue-cli
vite
Node.js(npm/yarn)
http-server
https://zh.javascript.info
红宝书
后端(Node.js):
mongodb
Node.js(npm)
express/koa
jwt
后端(Java):
servlet+filter+listener+jdbc+jackson
maven
tomcat
mysql
spring全家桶
部署:
阿里云租服务器
买域名
nginx
redis
pm2
前端(不太重要):
canvas/svg
jq
bootstrap
layui
element-ui/antd等管理系统的组件库
nginx:
nginx.conf 自己改配置, 改ip和端口
nginx.exe 开启nginx
前言
在使用express前, 最好懂得原生Node.js是如何做后端服务的
express的搭建
-
express-generator工具的使用
-
先安装express-generator
npm i -g express-generator
-
构建项目(连项目的文件结构都搞好了)
express 项目名 [-e]
-e 即支持-ejs
-
-
传统方法-手动搭建express
-
npm init
-
安装express
npm i express -S -
自己敲代码
-
express的所有用法
express-myconnection中间件 和 mysql连接池还没有
// 搭建服务的用法
const express = require('express') // www.js
const path = require('path') // www.js
const fs = require('fs') // www.js
const app = express() // www.js
const port = 3000 // www.js
app.listen(port, () => console.log('server is running...')) // www.js
// 允许跨越
app.all('*', (req, res, next) => {
res.header("Access-Control-Allow-Origin", "*");
res.header("Access-Control-Allow-Methods","PUT,POST,GET,DELETE,OPTIONS");
res.header('Access-Control-Allow-Headers', 'Origin, X-Requested-With, Content-Type, Accept, Authorization');
next();
});
// 开放静态资源
app.use("/public", express.static(path.join(__dirname,"public")))
// get用法
app.get('/', (req,res) => {
const id = req.query.id
res.json() // => 原生的res.setHeader('content-type','application/json')
res.send() // => 原生的res.end(), 但可以自动转换任何类型, 所以就可以不需要res.json()
})
.get('/', (req,res) => {
res.end('welcome juln')
})
.get('*', (req, resp) => {
resp.redirect('/404.html')
})
// post的body的用法
const bodyParser = require('body-parser') // www.js
// 如果是json就转换
app.use( bodyParser.json() ) // www.js
// 如果是urlencoded数据(form传过来的数据)就转换, 官方推荐{extended: false}, 表示用系统模块queryString来处理数据
app.use( bodyParser.urlencoded( {extended: false} ) ) // www.js
/**
* 如果post请求体的数据非常大的话, 要替换成下面两行, 因为express请求体的默认limit很小
* app.use( bodyParser.json( {limit: '50mb'} ) )
* app.use( bodyParser.urlencoded( {limit: '50mb', extended: false} ) )
*/
app.post('/postTest', (req,res) => {
console.log(req.body)
res.end()
})
// router分模块的用法
const router = express.Router()
app.use(router) // www.js
const userRouter = express.Router()
const blogRouter = express.Router()
router.use(userRouter) // 等同于router.use('/',userRouter), 即路由的拼接
router.use(blogRouter)
// 每个router的get和post用法
userRouter.get('/login', (req,res) => {
res.end('login page')
})
// 图片的响应
// form的图片媒体传输问题 (文件信息在req.files[0]或req.file中) (前端: form[enctype="multipart/form-data"])
// multer会将上传的文件信息写到req.file中,表单的文本域信息放到 req.body中(所以不需要再引入body-parser)
const multer = require('multer') // www.js
const objMulter = multer({dest: path.join(__dirname,'../public/uploadImages')}) // 如果不添加dest属性,这些文件将保存在内存中,永远不会写入磁盘; 目录不存在则自动创建
// app.use(objMulter.any()) // 接受任意input[type=file][name=*]的图片
app.use(objMulter.single('img')) // 只接受input[type=file][name=img]的图片
let avatorRouter = express.Router()
app.use(avatorRouter)
avatorRouter.post(
'/postAvator',
objMulter.single('img'), // 针对本路由的中间件
(req,res) => {
console.log(req.file)
const newname=req.file.path+path.parse(req.file.originalname).ext
fs.rename(req.file.path,newname,function(err){
if(err){
res.send('上传失败')
}else{
res.send('上传成功')
}
})
}
)
// 图片的请求和响应
.get('/getAvator', (req,res) => {
const rs = fs.createReadStream(path.join(__dirname,'../public/a.jpg'))
rs.pipe(res)
})
// express-jwt的使用
// npm install express-jwt jwt中间件
// npm install jsonwebtoken 生成token
// 加入中间件
const expressJwt = require('express-jwt')
app.use(expressJwt({
secret: 'secret12345', // 签名的密钥 或 PublicKey
credentialsRequired: false, // 是否允许不带token, 默认为false
algorithms: ['HS256'], // 设置jwt的算法
requestProperty: 'auth', // 修改请求头参数, 默认为Authorization
}).unless({
path: ['/login', '/signup'] // 指定路径不经过 Token 解析
}))
// 生成token
const jwt = require('jsonwebtoken')
app.post('/login', function (req, res) {
// 注意默认情况 Token 必须以 Bearer+空格 开头
const token = 'Bearer ' + jwt.sign(
{
id: user._id,
admin: user.role === 'admin'
},
'secret12345',
{
expiresIn: 3600 * 24 * 3
}
)
res.json({
status: 'ok',
data: { token: token }
})
})
// 获取解析内容
app.get('/xxx', function(req, res) {
console.log(req.user); // req.user 实际就是 JWT 的 payload 部分:
})
// 解析失败
app.use(function (err, req, res, next) {
if (err.name === 'UnauthorizedError') {
res.status(401).send('invalid token')
}
})
/* ================== mysql连接配置 =================== */
const dbConfig = {
host: '127.0.0.1',
port: '3306',
database: 'blog',
user: 'root',
password: '1234'
}
module.exports = dbConfig
/* ================== mysql连接配置 =================== */
/* =================== mysql连接 ====================== */
const mysql = require('mysql')
const dbConfig = require('../config/db')
const con = mysql.createConnection(dbConfig)
con.connect()
const query = function(sqlStr) {
return new Promise( (resolve,reject) => {
con.query(sqlStr, (err,result) => {
if(err) {
reject(err)
}
resolve(result)
})
})
}
module.exports = query
/* =================== mysql连接 ====================== */
/* =================== dbQuery的使用 ================== */
const dbQuery = require('./dbQuery.js')
dbQuery('select * from user').then( result => {
if(result.affectedRows > 0) {
console.log(result)
}
})
/* =================== dbQuery的使用 ================== */