1.什么是耦合
耦合,也称耦合度,一般在项目中表示依赖程度的概念
耦合度高表示组件与组件之间的依赖程度较高,稳定性高,但是扩展性差
耦合度低表示两个组件之间的依赖程度低,进行功能拓展比较方便
应用软件开发时,用户的需求经常发生变化,耦合度较低的项目 进行功能的变化会更加容易,代码的更新/维护的成本会更低
2.前后端耦合开发
前后端耦合开发的模式下,每个项目都是一个独立的项目(包括前端、后端)
前端开发与后端开发由同一个项目组负责
前端代码的运行、依赖后端代码的运行环境,不能独立运行
前端页面的后缀名通常不是.html/.htm,一般和依赖的后端环境有关
.ejs 后端-NodeJS环境
.jsp 后端-Java环境
.php 后端-PHP环境
3.NodeJS操作MySQL
1.操作模块概述
项目中使用到新的功能时,需要检索对应的工具模块是否存在,存在的话直接使用,不存在的话需要自定义功能模块
NodeJS操作MySQL用到的第三方模块:mysql
npm install mysql
let mysql = require('mysql') //项目中引入模块
let connection = mysql.createConnection({ //创建一个连接对象
host: 'localhost',
user: 'me',
password: '123456',
database: 'my_db'
})
connection.connect() //连接指定数据库
//执行sql语句
connection.query('SELECT 1 + 1 AS solution',(error,results,fields)=>{
if(error) throw error
return results
})
connection.end() //断开和数据库的连接
2.数据操作
数据库准备数据:创建数据库 myshop
//创建数据库
create databaser myshop default charset 'UTF8'
//指定数据库
user myshop
//创建数据表
create table user(
id int primary key auto_increament comment '用户编号'
username varchar(50) not null comment '用户账号'
passowrd vachar(50) not null comment '用户密码'
nickname varchar(50) not null comment '用户昵称'
)
创建NodeJS测试应用,完成数据库的基本访问
创建项目文件夹 demo/
npm init
npm install mysql -s
完成数据的增加、查询、修改、删除,解决sql注入漏洞
3.Express项目开发
1.项目架构
开发一个博客项目:前端页面视图、后端服务程序、都是包含在一个项目中进行开发,前后端耦合架构模式,开发项目
2.初始化项目
1.数据库初始化
创建数据库
-- 创建数据库
create database webblog default charset 'UTF8';
-- 指定数据库
use webblog;
-- 创建数据表
-- 用户
create table author(
id int primary key auto_increment comment '作者编号',
username varchar(50) not null comment '登录账号',
password varchar(50) not null comment '登录密码',
nickname varchar(50) not null comment '昵称',
age int default 0 comment '年龄',
gender char(5) comment '性别',
email varchar(50) comment '邮箱',
phone varchar(20) comment '手机',
ustate int default 0 comment '状态0正常1锁定2删除'
);
-- 文章类别
create table articleType(
id int primary key auto_increment comment '类别编号',
name varchar(20) not null comment '类别名称',
intro text comment '类别说明'
);
-- 文章
create table article(
id int primary key auto_increment comment '文章编号',
title varchar(100) not null comment '文章标题',
content text not null comment '文章内容',
publish datetime comment '发表时间',
read_count int default 0 comment '阅读次数',
word_count int default 0 comment '文章字数',
astate int default 0 comment '状态0正常1草稿箱2回收站',
author int not null comment '文章作者'
);
3.注册功能
1.安装Express脚手架
脚手架:用于快速操作一系列文件的命令
npm install express-generator -g
2.脚手架创建项目
express webblog -e
3.安装项目依赖
npm i //安装基本依赖
安装mysql数据库依赖
npm i mysql -S
4.注册功能实现
创建博客用户注册页面:webblog/view/user/register.ejs
<h2>用户注册</h2>
<form action="/users/reg" method="POST">
账号:<input type="text" name="username" id="username"><br />
密码:<input type="password" name="password" id="password"><br />
确认密码:<input type="password" name="confirm" id="confirm"><br />
昵称:<input type="text" name="nickname" id="nickname"><br />
<input type="submit" value="作者注册">
</form>
访问注册页面
首先确认users.js路由子模块的访问路径,app.js
app.use('/users',usersRouter)
编辑webblog/routes/users.js,添加访问注册页面的路由函数
router.get("/reg", (req, resp)=> {
resp.render(path.join(path.join(__dirname,'../views/user',), "register"), {
msg: ""
})
})
浏览器访问地址栏 http://localhost:3000/users/reg,看到注册页面
数据库访问模块
注册之前先完成数据库访问模块的编写,创建webblog/routes/data.js
const mysql = require("mysql")
const connection = mysql.createConnection({
host: "localhost",
user: "root",
password: "root",
database: "webblog"
})
connection.connect()
module.exports = connection
注册功能实现
let connection = require("./data")
...
// 用户注册
router.post("/reg", (req, resp) => {
// 1. 解构注册数据
let { username, password, confirm, nickname } = req.body
// 2. 验证账号是否存在
let sql = `select * from author where username = '${username}'`
connection.query(sql, (err, result) => {
if (result.length > 0) {
return resp.render(path.join(BASE_DIR, "register"), {
msg: "账号已经被占用,请使用其他账号注册"
})
}
// 3. 验证密码是否一致
if (password !== confirm) {
return resp.render(path.join(BASE_DIR, "register"), {
msg: "密码不一致,请重新注册"
})
}
// 4. 注册成功
sql = `insert into author (username, password, nickname)
values('${username}', '${password}', '${nickname}')`
connection.query(sql, (err, result) => {
if(err) {
return resp.render(path.join(BASE_DIR, "register"), {
msg: "服务器繁忙,请稍后再试"
})
}
return resp.render(path.join(BASE_DIR, "register"), {
msg: "注册成功"
})
})
})
})
5.用户登录
1.创建登录页面
创建ejs文件: webblog/view/users/login.ejs
<h2>用户登录</h2>
<p><%=msg %></p>
<form action="/users/login" method="post">
账号:<input type="text" name="username" id="username"><br />
密码:<input type="password" name="password" id="password"><br />
<input type="submit" value="作者登录">
</form>
2.访问登录页面
// 访问用户登录页面
router.get("/login", (req, resp)=> {
resp.render(path.join(BASE_DIR, "login"), {
msg: ""
})
})
浏览器访问http://localhost:3000/users/login
3.实现用户登录
// 处理用户登录
router.post("/login", (req, resp) => {
// 1. 解构登录数据
let {username, password} = req.body
// 2. 验证账号、密码
let sql = `select * from author where
username = '${username}' and password = '${password}'`
connection.query(sql, (err, result)=> {
if(result.length === 1) {
// 登录成功
req.session.login = result[0]
return resp.render(path.join(BASE_DIR, "login"), {
msg:"登录成功"
})
} else{
return resp.render(path.join(BASE_DIR, "login"), {
msg:"账号或者密码有误,请重新登录"
})
}
})
})
4.启用session会话
安装项目依赖
npm install express-session -S
var session = require('express-session')
app.use(session({
secret:'加密混淆码',
resave:false,
saveUninitialized: true
}))
5.修改用户密码
1.创建修改密码页面
访问首页视图函数,编辑webblog/routes/index.js
router.get('/', function(req, res, next) {
res.render('index', { req });
});
修改登录视图函数,编辑webblog/routes/users.js
....
if(result.length === 1) {
// 登录成功
req.session.login = result[0]
// return resp.render(path.join(BASE_DIR, "login"), {
// msg:"登录成功",
// req
// })
return resp.redirect("/")
}
....
修改首页中的内容:编辑webblog/views/index.ejs
<h1>博客首页</h1>
<%if (req.session.login) {%>
<p>尊敬的用户<%=req.session.login.nickname %> 欢迎访问博客系统</p>
<p><a href="/users/chgpwd">修改用户密码</a></p>
<% } else {%>
<p><a href="/users/login">作者登录</a></p>
<% } %>
创建修改用户密码的页面:webblog/views/author/chgpwd.ejs
<h2>修改用户密码</h2>
<p><%=msg %></p>
<form action="/users/chgpwd" method="POST">
原密码:<input type="text" name="old_password" id="old_password"><br />
新密码:<input type="text" name="new_password" id="new_password"><br />
确认密码:<input type="text" name="new_password2" id="new_password2"><br />
<input type="submit" value="修改密码">
</form>
2.访问修改页面路由函数
编辑webblog/routes/users.js
router.get("/chgpwd", (req, resp) => {
resp.render(path.join(BASE_DIR, "chgpwd"), {
msg: ""
})
})
3.修改密码实现
// 修改登录密码
router.post("/chgpwd", (req, resp) => {
// 解构获取数据
let {old_password, new_password, new_password2} = req.body
// 1. 验证原密码是否正确
if(old_password !== req.session.login["password"]) {
return resp.render(path.join(BASE_DIR, "chgpwd"), {
msg: "原密码输入有误,请重新输入"
})
}
// 2. 验证两次新密码输入是否一直
if(new_password !== new_password2) {
return resp.render(path.join(BASE_DIR, "chgpwd"), {
msg: "两次新密码输入不一致,请重新输入"
})
}
// 3. 修改密码,跳转回登录页面
let sql = `update author set password = '${new_password}'
where username = '${req.session.login.username}'`
connection.query(sql, (err, result) =>{
if(err) {
return resp.render(path.join(BASE_DIR, "chgpwd"), {
msg: "服务器繁忙,请稍后再试"
})
}
return resp.redirect("/users/login")
})
})
6.发表文章
1.创建发表文章页面
webblog/views/publish.ejs
<h2>发表文章</h2>
<form action="/article/publish" method="POST">
文章标题:<input type="text" name="title" id="title"><br />
文章内容:<textarea name="content" id="content" cols="30" rows="10">
</textarea><br />
<input type="submit" value="发表文章">
</form>
2.创建访问页面的路由函数
创建一个文章模块:webblog/routes/article.js
const express = requrie("express")
const router = express.Router()
router.get("/publish", (req, resp)=> {
resp.render(path.join(__dirname, "../views/publish"))
})
module.exports = router
将文章模块注册到app.js中
...
var articleRouter = require("./routes/article")
...
app.use('/article', articleRouter)
3.实现发表文章
编辑webblog/routes/article.js,添加post请求处理发表文章数据
// 发表文章""
router.post("/publish", (req, resp) => {
// 1.解构发表文章的数据
let {title, content} = req.body
// 2.获取需要的其他数据
let currentTime = new Date()
let author = req.session.login.id
// 3.添加文章内容到数据库
let sql = `insert into article(title, content, publish, author)
values('${title}','${content}','${currentTime}','${author}')`
connnection.query(sql, (err, result) => {
if(err) {
return render(path.join(__dirname, "../views/publish"), {
msg: "服务器繁忙,请稍后再试"
})
}
return render(path.join(__dirname, "../views/publish"), {
msg: "文章发表成功"
})
})
})