途牛网站开发需求,邯郸市中小学健康管理平台登录,安徽省工程建设信息网官网查询,大连建设工程综合管理平台综合应用服务端知识点搭建项目
下载安装所需的第三方模块
npm init -y
npm i express cors mysql
# express 用于搭建服务器
# cors 用于解决跨域
# mysql 用于操作数据库# 后面用到什么#xff0c;再下载创建app.js
之前#xff0c;我们开启一个服务器#xff0c;js文件…综合应用服务端知识点搭建项目
下载安装所需的第三方模块
npm init -y
npm i express cors mysql
# express 用于搭建服务器
# cors 用于解决跨域
# mysql 用于操作数据库# 后面用到什么再下载创建app.js
之前我们开启一个服务器js文件名一般都是 01-xxx.js 03-xxx.js。
对于正常的一个项目来说用于开启服务的js文件一般都叫做 app.js
// 开启服务
const express require(express);
const app express();
app.listen(3006, () console.log(server running~));使用路由模块精简项目结构 使用路由模块的原因意义
试想如果项目有100个路由接口全部放到app.js中这样的代码不好维护效率也比较低下所以需要按照路由接口功能的不同分别使用小文件存放这些路由接口这些小文件就叫做路由模块 比如登录注册相关的全部放到 ./routers/login.js 中比如文章处理相关的全部放到 ./routers/article.js 中比如书籍管理相关的全部放到 ./routers/books.js 中
代码如何实现
路由文件中的代码 加载express创建路由对象将路由接口挂载到路由对象上导出路由对象
/*** 1. 加载express* 2. 创建路由对象* 3. 把路由挂载到路由对象上* 4. 导出路由对象*/const express require(express);
const router express.Router();// 下面是图书管理相关的路由
router.get(/getbooks, (req, res) {res.send(我是获取书籍的接口);
});router.post(/addbook, (req, res) {});router.get(/delbook, (req, res) {});module.exports router;app.js 中的代码 加载路由模块并注册成中间件。注册的时候可以统一加前缀
// 开启服务
const express require(express);
const app express();
app.listen(3006, () console.log(server running~));// 加载路由模块并注册成中间件
let books require(./routers/books);
app.use(/api, books);开启服务nodemon app.js) 然后通过浏览器来测试一下你的接口是否能够正常访问 创建数据库、数据表
数据库还可以使用昨天的 user 数据库。
在里面创建一张数据表books 添加几条模拟数据 粗略的完成获取书籍的接口 目前 数据准备好了接口能够正常访问了 下面要做的事情 getbooks接口中通过mysql模块查询所有的书籍并把结果响应给客户端中间件解决跨域问题
getbooks接口
router.get(/getbooks, async (req, res) {// 查询数据库user、数据表books里面的数据把查询的结果响应给客户端const mysql require(mysql); // require加载一个模块后会缓存起来const conn mysql.createConnection({host: localhost,user: root,password: 12345678,database: user // 填写数据库名});conn.connect();conn.query(select * from books, (err, result) {if (err) return console.log(err);res.json({status: 200,msg: 获取成功,data: result});});conn.end();
});应用级别的中间件解决跨域
应用级别的中间件 写到app.js中的中间件该中间件会影响所有的路由 路由级别的中间件 写到 路由文件中的中间件该中间件只会影响当前的路由文件
因为整个项目的全部路由都需要解决跨域问题所以需要定义应用级别的中间件
所以在app.js中加入如下代码
// 配置中间件解决跨域问题
app.use((req, res, next) {res.set({Access-Control-Allow-Origin: *});next();
});封装db.js
试想后面还有很多路由中需要对数据库进行操作难道每次执行SQL语句都要写5个步骤操作MySQL的5个步骤吗
答肯定不是那样的话代码太多。代码复用性太差了
解决办法封装
具体做法
创建 db.js里面封装 使用mysql模块的5个步骤导出函数其他路由中需要加载导入db模块然后调用函数即可
db.js 中的代码
function db(sql, params, callback) {const mysql require(mysql);const conn mysql.createConnection({host: localhost,user: root,password: 12345678,database: user // 填写数据库名});conn.connect();conn.query(sql, params, callback);conn.end();
}// 导出函数
module.exports db;getbooks接口中使用
// 获取书籍接口
router.get(/getbooks, async (req, res) {// 查询数据库user、数据表books里面的数据把查询的结果响应给客户端db(select * from books, null, (err, result) {if (err) return console.log(err);res.json({status: 200,msg: 获取成功,data: result});});
});使用Promise
如果查询书籍信息的时候还要查询总记录数怎么办
答嵌套查询嵌套的层数太多就会形成回调地狱
解决办法使用Promise
具体做法
在db.js中加个一个封装Promise的函数db2db2中调用db函数从而完成Promise的封装导出db2
function db(sql, params, callback) {const mysql require(mysql);const conn mysql.createConnection({host: localhost,user: root,password: 12345678,database: user // 填写数据库名});conn.connect();conn.query(sql, params, callback);conn.end();
}function db2 (sql, params) {return new Promise((resolve, reject) {// 这里写异步代码db(sql, params, (err, result) {err ? reject(err) : resolve(result);});});
}// 导出函数
module.exports db2;优化上述两个函数
function db (sql, params null) {const mysql require(mysql); // require加载一个模块后会缓存起来const conn mysql.createConnection({host: localhost,user: root,password: 12345678,database: user // 填写数据库名});return new Promise((resolve, reject) {// 这里写异步代码conn.connect();conn.query(sql, params, (err, result) {err ? reject(err) : resolve(result);});conn.end();});
}// 导出函数
module.exports db;完整的图示 Web 开发模式
目前主流的 Web 开发模式有两种分别是:
基于服务端渲染的传统 Web 开发模式基于前后端分离的新型 Web 开发模式
服务端渲染的开发模式
特点 所有的web资源由同一个服务器统一管理前后端代码必须放到一起 页面和页面中使用的数据由服务器组装最后将完整的HTML页面响应给客户端 代码
// 用于开启服务const fs require(fs);
const express require(express);
const app express();
app.listen(3000, () console.log(启动了));// 显示首页的接口
app.get(/index.html, (req, res) {// res.send(1111)fs.readFile(./public/index.html, utf-8, (err, data) {if (err) return console.log(err);data data.replace({{title}}, 悯农);data data.replace({{content}}, 锄禾日当午汗滴禾下土);res.send(data);});
});真实的服务端渲染模式和前后端分离的模式难度上差不多。 优点
**前端耗时少。**因为服务器端负责动态生成 HTML 内容浏览器只需要直接渲染页面即可。尤其是移动端更省电。有利于SEO。因为服务器端响应的是完整的 HTML 页面内容所以爬虫更容易爬取获得信息更有利于 SEO搜索引擎。
缺点: **占用服务器端资源。**即服务器端完成 HTML 页面内容的拼接如果请求较多会对服务器造成一定的访问压力。 不利于前后端分离开发效率低。使用服务器端渲染则无法进行分工合作尤其对于前端复杂度高的项目不利于 项目高效开发。
前后端分离的开发模式
特点
依赖于Ajax技术。后端不提供完整的 HTML 页面内容而 是提供一些 API 接口前端通过 Ajax 调用后端提供的 API 接口拿到 json 数据 之后再在前端进行 HTML 页面的拼接最终展示在浏览器上。
简而言之前后端分离的 Web 开发模式就是后端只负责提供 API 接口前端使用 Ajax 调用接口的开发模式。
优点
**开发体验好。**前端专注于 UI 页面的开发后端专注于api 的开发且前端有更多的选择性。**用户体验好。**Ajax 技术的广泛应用极大的提高了用户的体验可以轻松实现页面的局部刷新。**减轻了服务器端的渲染压力。**因为页面最终是在每个用户的浏览器中生成的。
缺点
**不利于SEO。**因为完整的 HTML 页面需要在客户端动态拼接完成所以爬虫对无法爬取页面的有效信息。(解决方 案:利用 Vue、React 等前端框架的 SSR (server side render)技术能够很好的解决 SEO 问题!)
如何选择 Web 开发模式
不谈业务场景而盲目选择使用何种开发模式都是耍流氓。 比如企业级网站公司的网站主要功能是展示而没有复杂的交互并且需要良好的 SEO则这时我们就需要使用服务器端渲染; 而类似后台管理页面交互性比较强不需要 SEO 的考虑那么就可以使用前后端分离的开发模式。 另外具体使用何种开发模式并不是绝对的为了同时兼顾了首页的渲染速度和前后端分离的开发效率一些网站采用了 首屏服务器端渲染即对于用户最开始打开的那个页面采用的是服务器端渲染而其他的页面采用前后端分离开发模式。
身份认证机制
对于服务端渲染和前后端分离这两种开发模式来说分别有着不同的身份认证方案:
服务端渲染推荐使用 Session 认证机制Session也会用到Cookie前后端分离推荐使用 JWT 认证机制
Cookie
原理 实现身份认证
搭建基础的服务器 下载安装第三方模块 express 和 cookie-parser 创建app.js 加载所需模块 const express require(express);const cookieParser require(cookie-parser); 中间件配置 cookie-parser app.use(cookieParser()) 实现三个路由 /login.html 里面直接响应login.html页面/api/login/index.html 里面直接响应index.html页面 创建存放index页面的public文件夹 创建index.html创建login.html 完成登录接口 如果登录成功设置cookie。res.cookie(key, value, 配置项);跳转到 /index.html 路由 /index.html 路由中根据cookie判断是否登录从而完成身份认证 详见代码 const express require(express);
const cookieParser require(cookie-parser);
const path require(path);const app express();
app.listen(3000, () console.log(启动了));// 接收POST请求体
app.use(express.urlencoded({extended: false}));
// 配置cookie-parser
app.use(cookieParser());// 准备三个路由// 用于显示登录页面
app.get(/login.html, (req, res) {// sendFile方法可以读取文件并将读取的结果响应给客户端// 要求参数必须是一个绝对路径res.sendFile(path.join(__dirname, public, login.html));
});// 用于完成登录验证的判断账号密码是否正确的接口
app.post(/api/login, (req, res) {// console.log(req.body);// 约定假设账号是 admin、密码是123if (req.body.username admin req.body.password 123) {// 登录成功跳转到index.html// 设置cookie// res.cookie(key, value, 选项);// res.cookie(isLogin, 1); // 没有填选项默认cookie有效期是会话结束res.cookie(isLogin, 1, {maxAge: 2*60*1000});res.send(scriptalert(登录成功); location.href/index.html;/script);} else {// 登录失败}
});// 显示index.html页面的
app.get(/index.html, (req, res) {// 获取cookie// console.log(req.cookies);if (req.cookies.isLogin req.cookies.isLogin 1) {res.sendFile(path.join(__dirname, public, index.html));} else {// 没有登录res.send(scriptalert(请先登录); location.href/login.html;/script);}
});优缺点
优点 体积小客户端存放不占用服务器空间浏览器会自动携带不需要写额外的代码比较方便 缺点 客户端保存安全性较低。但可以存放加密的字符串来解决可以实现跨域但是难度大难理解代码难度高不适合前后端分离式的开发
适用场景
传统的服务器渲染模式存储安全性较低的数据比如视频播放位置等
Session
原理 实现身份认证 搭建基础的服务器 下载安装第三方模块 express 和 express-session 创建app.js 加载所需模块 const express require(express);const session require(express-session); 中间件配置 session app.use(session({secret: adfasdf, // 这个随便写saveUninitialized: false,resave: false
}))实现三个路由 /login.html 里面直接响应login.html页面/api/login/index.html 里面直接响应index.html页面 创建存放index页面的public文件夹 创建index.html创建login.html 完成登录接口 如果登录成功使用session记录用户信息。 req.session.isLogin 1;
req.session.username req.body.username;跳转到 /index.html 路由 /index.html 路由中根据session判断是否登录从而完成身份认证 详见代码 const express require(express);
const session require(express-session);
const path require(path);const app express();
app.listen(3000, () console.log(启动了));// 接收POST请求体
app.use(express.urlencoded({extended: false}));
// 配置session
app.use(session({secret: asdf23sfsd23,// 下面两项设置成true或者false都可以。使用内存存储session的时候下面两项没作用saveUninitialized: false,resave: false
}));// 准备三个路由// 用于显示登录页面
app.get(/login.html, (req, res) {// sendFile方法可以读取文件并将读取的结果响应给客户端// 要求参数必须是一个绝对路径res.sendFile(path.join(__dirname, public, login.html));
});// 用于完成登录验证的判断账号密码是否正确的接口
app.post(/api/login, (req, res) {// console.log(req.body);// 假设账号任意密码必须是123if (req.body.password 123) {// 假设登录成功// req.session.xxxx yyyyreq.session.isLogin 1;
/*p欢迎你{{username}}/p
*/req.session.username req.body.username;// 做出响应res.send(scriptalert(登录成功); location.href/index.html;/script);}
});// 显示index.html页面的
app.get(/index.html, (req, res) {// 获取session req.sessionif (req.session.isLogin req.session.isLogin 1) {const fs require(fs);fs.readFile(./public/index.html, utf-8, (err, data) {if (err) return console.log(err);// 更换用户名data data.replace({{username}}, req.session.username);res.send(data);});} else {res.send(scriptalert(请登录); location.href/login.html;/script);}});优缺点
优点 服务端存放安全性较高浏览器会自动携带cookie不需要写额外的代码比较方便适合服务器端渲染模式 缺点 会占用服务器端空间session实现离不开cookie如果浏览器禁用cookiesession不好实现不适合前后端分离式的开发
适用场景
传统的服务器渲染模式安全性要求较高的数据可以使用session存放比如用户私密信息、验证码等