mvc三层架构
mvc, 即 model 、controller、view; mvc模式将model、view、controller分离;使用mvc分层是系统更加灵活,扩展性更强。让程序更加直观、复用性更强、可维护性更强。
model 负责数据访问; controller 负责消息处理; view 负责视图呈现。
利用mvc模式实现后端分层
mvc分层开发模式: web server : 用户发起请求 => 分析用户请求,处理路由 => 处理数据(操作数据库,操作缓存)=> view(data+template)=> response。即 controller => model => view。
实现一个koa框架的web服务
const Koa = require ( 'koa' ) ;
const KoaRouter = require ( 'koa-router' ) ;
const KoaStaticCache = require ( 'koa-static-cache' ) ;
const koaBody = require ( 'koa-body' ) ;
const mainController = require ( './contollers/main' ) ;
const userController = require ( './contollers/user' ) ;
const itemController = require ( './contollers/item' ) ;
const server = new Koa ( ) ;
const router = new KoaRouter ( ) ;
server. use ( KoaStaticCache ( './public' , {
prefix : '/public' ,
gzip : true ,
dynamic : true
} ) ) ;
server. use ( koaBody ( {
multipart : true ,
formidable : {
uploadDir : __dirname + '/public/upload' ,
keepExtensions : true
}
} ) ) ;
router. get ( '/' , mainController. index) ;
router. get ( '/user/register' , userController. register) ;
router. get ( '/user/login' , userController. login) ;
router. get ( '/item/add' , itemController. add) ;
router. post ( '/item/add' , itemController. addPost) ;
server. use ( router. routes ( ) ) ;
server. listen ( 8081 , ( ) => {
console. log ( '服务启动成功:http://localhost:8081' )
} ) ;
const tpl = require ( '../libs/tpl' ) ;
const itemsModel = require ( '../models/items' ) ;
module. exports = {
index : async ctx => {
let items = await itemsModel. getItems ( ) ;
ctx. body = tpl. render ( 'index.html' , {
items
} ) ;
}
}
const tpl = require ( '../libs/tpl' ) ;
module. exports = {
register : async ctx => {
ctx. body = '注册' ;
} ,
login : async ctx => {
ctx. body = '登陆'
}
}
const tpl = require ( '../libs/tpl' ) ;
const categoriesModel = require ( '../models/categories' ) ;
const itemsModel = require ( '../models/items' ) ;
module. exports = {
add : async ctx => {
let categories = await categoriesModel. getCategories ( ) ;
ctx. body = tpl. render ( 'add-item.html' , {
categories
} ) ;
} ,
addPost : async ctx => {
let data = ctx. request. body;
let files = ctx. request. files;
let filename = '' ;
if ( files && files. cover) {
let lastPos = files. cover. path. lastIndexOf ( '/' ) ;
filename = files. cover. path. substring ( lastPos+ 1 ) ;
}
let rs = await itemsModel. addItem ( [
data. category_id,
data. name,
data. price,
filename
] ) ;
console. log ( 'rs' , rs) ;
ctx. body = '添加成功' ;
}
}
const nunjucks = require ( 'nunjucks' ) ;
const tpl = new nunjucks. Environment (
new nunjucks. FileSystemLoader ( 'views' , {
watch : true ,
noCache : true
} )
) ;
module. exports = tpl;
const db = require ( './model' ) ;
module. exports = {
getItems ( ) {
return new Promise ( ( resolve, reject ) => {
db. query ( "select * from `items`" , function ( err, rs ) {
if ( err) {
reject ( err) ;
} else {
resolve ( rs) ;
}
} ) ;
} )
} ,
addItem ( newData ) {
return new Promise ( ( resolve, reject ) => {
db. query ( "insert into `items` (`category_id`, `name`, `price`, `cover`) values (?, ?, ?, ?)" , newData, function ( err, rs ) {
if ( err) {
reject ( err) ;
} else {
resolve ( rs) ;
}
} ) ;
} )
}
}
const db = require ( './model' ) ;
module. exports = {
getCategories ( ) {
return new Promise ( ( resolve, reject ) => {
db. query ( "select * from `categories`" , function ( err, rs ) {
if ( err) {
reject ( err) ;
} else {
resolve ( rs) ;
}
} ) ;
} )
}
}
const mysql2 = require ( 'mysql2' ) ;
let db = mysql2. createConnection ( {
host : '127.0.0.1' ,
port : 3306 ,
user : 'root' ,
password : 'Chen@123' ,
database : 'test'
} ) ;
module. exports = db;
<! DOCTYPE html >
< html lang = " en" >
< head>
< meta charset = " UTF-8" >
< meta name = " viewport" content = " width=device-width, initial-scale=1.0" >
< title> Document</ title>
< link rel = " stylesheet" href = " /public/css/css.css" />
</ head>
< body>
< div id = " app" >
< header id = " header" >
< a href = " /" id = " logo" > </ a>
< nav id = " nav" >
< a href = " " > 1</ a>
< a href = " " > 笔记本</ a>
< a href = " " > 家居</ a>
</ nav>
< div id = " user" >
< a href = " " > 登录</ a>
< a href = " " > 注册</ a>
</ div>
</ header>
< div id = " main" >
< ul class = " items-list" >
{%for item in items%}
< li class = " panel" >
< img src = " /public/upload/{{item.cover}}" alt = " " class = " cover" >
< div class = " name" > {{item.name}}</ div>
< div class = " price" > ¥ {{(item.price / 100).toFixed(2)}}</ div>
</ li>
{%endfor%}
</ ul>
< div class = " pagination-container" >
< div class = " pagination" >
< a href = " " class = " prev" > 上一页</ a>
< a href = " " > 1</ a>
< a href = " " > 2</ a>
< a href = " " > 3</ a>
< a href = " " class = " current" > 4</ a>
< a href = " " > 5</ a>
< a href = " " > 6</ a>
< a href = " " > 7</ a>
< a href = " " > 8</ a>
< a href = " " class = " next" > 下一页</ a>
</ div>
</ div>
</ div>
</ div>
</ body>
</ html>
<! DOCTYPE html >
< html lang = " en" >
< head>
< meta charset = " UTF-8" >
< meta name = " viewport" content = " width=device-width, initial-scale=1.0" >
< title> Document</ title>
< link rel = " stylesheet" href = " /public/css/css.css" />
</ head>
< body>
< header id = " header" >
< a href = " /" id = " logo" > </ a>
< nav id = " nav" >
< a href = " " > 1</ a>
< a href = " " > 笔记本</ a>
< a href = " " > 家居</ a>
</ nav>
< div id = " user" >
< a href = " " > 登录</ a>
< a href = " " > 注册</ a>
</ div>
</ header>
< div id = " main" >
< div class = " panel" >
< h2> 添加新商品</ h2>
< form action = " " method = " post" enctype = " multipart/form-data" >
< div class = " form-item" >
< label>
< span class = " txt" > 商品分类:</ span>
< select name = " category_id" >
< option value = " " > 请选择商品分类</ option>
{%for category in categories%}
< option value = " {{category.id}}" > {{category.name}}</ option>
{%endfor%}
</ select>
</ label>
</ div>
< div class = " form-item" >
< label>
< span class = " txt" > 商品名称:</ span>
< input type = " text" class = " form-input" name = " name" >
</ label>
</ div>
< div class = " form-item" >
< label>
< span class = " txt" > 价格:</ span>
< input type = " text" class = " form-input" name = " price" >
</ label>
</ div>
< div class = " form-item" >
< label>
< span class = " txt" > 封面:</ span>
< input type = " file" name = " cover" />
</ label>
</ div>
< div class = " form-item" >
< label>
< span class = " txt" > </ span>
< button class = " form-button primary" > 确认添加</ button>
</ label>
</ div>
</ form>
</ div>
</ div>
</ body>
</ html>