super(data,message)
this.errno = -1
}
}
module.exports = {
SuccessModel,
ErrorModel
}
4. 中间件开发
登陆校验的中间件 loginCheck
其实就是检查 session 中是否存有用户名的信息(信息在登陆成功时写进 session)
const { ErrorModel } = require(‘…/model/resModel’)
module.exports = async (ctx, next) => {
if (ctx.session.username) {
await next()
return
}
ctx.body = new ErrorModel(‘未登录’)
}
5. 控制层开发
接下来就讲一下控制层的实现,主要是连接数据库的sql语句来实现数据的交互
const xss = require(‘xss’)
const { exec } = require(‘…/db/mysql’)
const getList = async (author, keyword) => {
let sql = select * from blogs where 1=1
if (author) {
sql += and author='${author}'
}
if (keyword) {
sql += and title like '%${keyword}%'
}
sql += order by createtime desc;
return await exec(sql)
}
const getDetail = async (id) => {
const sql = select * from blogs where id='${id}'
const rows = await exec(sql)
return rows[0]
}
const newBlog = async (blogData = {}) => {
// blogData 是一个博客对象,包含 title content author 属性
const title = xss(blogData.title)
const content = xss(blogData.content)
const author = blogData.author
const createTime = Date.now()
const sql = `
insert into blogs (title, content, createtime, author)
values (‘ t i t l e ′ , ′ {title}', ' title′,′{content}’, c r e a t e T i m e , ′ {createTime}, ' createTime,′{author}');
`
const insertData = await exec(sql)
return {
id: insertData.insertId
}
}
const updateBlog = async (id, blogData = {}) => {
// id 就是要更新博客的 id
// blogData 是一个博客对象,包含 title content 属性
const title = xss(blogData.title)
const content = xss(blogData.content)
const sql = `
update blogs set title=‘ t i t l e ′ , c o n t e n t = ′ {title}', content=' title′,content=′{content}’ where id=${id}
`
const updateData = await exec(sql)
if (updateData.affectedRows > 0) {
return true
}
return false
}
const delBlog = async (id, author) => {
// id 就是要删除博客的 id
const sql = delete from blogs where id='${id}' and author='${author}';
const delData = await exec(sql)
if (delData.affectedRows > 0) {
return true
}
return false
}
module.exports = {
getList,
getDetail,
newBlog,
updateBlog,
delBlog
}
5. 连接数据库
说明一下 exec函数其实就是数据库查询的函数
const mysql = require(‘mysql’)
const { MYSQL_CONF } = require(‘…/conf/db’)
//创建链接对象
const con = mysql.createConnection(MYSQL_CONF)
//开始连接
con.connect()
//统一执行sql函数
function exec(sql) {
const promise = new Promise((resolve, reject) => {
con.query(sql, (err, result) => {
if (err) {
reject(err)
return
}
resolve(result);
})
})
return promise
}
module.exports = {
exec,
escape:mysql.escape
}
连接 mysql 的具体配置,分为生产环境和开发环境
const env = process.env.NODE_ENV //获取环境变量
let MYSQL_CONF
if (env === ‘dev’) {
MYSQL_CONF = {
host: ‘localhost’,
user: ‘root’,
port: 3306,
password: ‘password’,
database: ‘myblog’
}
}
if (env === ‘production’) {
MYSQL_CONF = {
host: ‘localhost’,
user: ‘root’,
port: 3306,
password: ‘password’,
database: ‘myblog’
}
}
module.exports = {
MYSQL_CONF
}
1. sql 注入
const sql = select username,realname from users where username=${username} andpassword=${password};
首先我们看一下 sql 的数据库查询,要是用户名输入 zhangsan' --
就会把后面的密码注释了(也就是说不用密码就可以登陆)
解决方式是使用 mysql:escape
进行转义
2. xss攻击
比如新建博客的时候可能会输入 <script>alert(1)</script>
的形式,就会造成xss攻击,解决方式就是转义字符(如<,>等基本可以避免攻击)
const newBlog = async (blogData = {}) => {
// blogData 是一个博客对象,包含 title content author 属性
const title = xss(blogData.title)
const content = xss(blogData.content)
const author = blogData.author
const createTime = Date.now()
const sql = `
insert into blogs (title, content, createtime, author)
values (‘ t i t l e ′ , ′ {title}', ' title′,′{content}’, c r e a t e T i m e , ′ {createTime}, ' createTime,′{author}');
`
const insertData = await exec(sql)
return {
id: insertData.insertId
}
}
利用node的文件流,创建一个写文件流,并把它记录到本地文件当中
// logger
app.use(async (ctx, next) => {
const start = new Date()
await next()
const ms = new Date() - start
console.log(${ctx.method} ${ctx.url} - ${ms}ms
)
})
const ENV = process.env.NODE_ENV
//记录日志
if (ENV !== ‘production’) {
app.use(morgan(‘dev’));
} else {
const logFileName = path.resolve(__dirname, ‘logs’, ‘access.log’)
const writeStream = fs.createWriteStream(logFileName, {
flags: ‘a’
})
app.use(morgan(‘combined’, {
stream: writeStream
}));
}
const http = require(‘http’)
// 组合中间件
function compose(middlewareList) {
return function (ctx) {
// 中间件调用
function dispatch(i) {
const fn = middlewareList[i]
try {
return Promise.resolve(fn(ctx, dispatch.bind(null, i+1)))
} catch(err) {
return Promise.reject(err)
}
}
return dispatch(0)
}
}
class LikeKoa2 {
constructor() {
this.middlewareList = []
}
use(fn) {
this.middlewareList.push(fn)
return this
}
createCtx(req, res) {
const ctx = {
req,
res
}
return ctx
}
handleRequest(ctx, fn) {
return fn(ctx)
}
callback() {
const fn = compose(this.middlewareList)
return (req, res) => {
const ctx = this.createCtx(req, res)
return this.handleRequest(ctx, fn)
}
}
lsiten(…args) {
const server = http.createServer(this.callback())
server.listen(…args)
}
}
module.exports = {
LikeKoa2
}
1. pm2 介绍
-
进程守护,如果系统崩溃则会自动重启 node app.js和 nodemon app.js
-
启动多进程,充分利用cpu和内存
-
自带日志记录功能
2. pm2 配置与多进程
-
优点: 充分利用多核cpu优势。
-
缺点: 多进程之间,内存无法共享;解决方法是多进程访问redis,实现数共享
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。
深知大多数前端工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!
因此收集整理了一份《2024年Web前端开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上前端开发知识点,真正体系化!
由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!
如果你觉得这些内容对你有帮助,可以扫码获取!!(备注:前端)
最后
由于篇幅限制,pdf文档的详解资料太全面,细节内容实在太多啦,所以只把部分知识点截图出来粗略的介绍,每个小节点里面都有更细化的内容!有需要的程序猿(媛)可以帮忙点赞+点击【学习资料】即可免费领取!
提升又不知道该从何学起的朋友,同时减轻大家的负担。**
[外链图片转存中…(img-QohPw8Ho-1712292690654)]
[外链图片转存中…(img-jkKfrKma-1712292690654)]
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上前端开发知识点,真正体系化!
[外链图片转存中…(img-9uQt5fI4-1712292690655)]
由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!
如果你觉得这些内容对你有帮助,可以扫码获取!!(备注:前端)
最后
由于篇幅限制,pdf文档的详解资料太全面,细节内容实在太多啦,所以只把部分知识点截图出来粗略的介绍,每个小节点里面都有更细化的内容!有需要的程序猿(媛)可以帮忙点赞+点击【学习资料】即可免费领取!
[外链图片转存中…(img-GBs8dCxh-1712292690655)]
[外链图片转存中…(img-NxnkyQLz-1712292690655)]