node+express项目案例(二)

本文详细介绍了使用Node.js和Express框架构建项目的全过程,包括数据库操作、路由管理、模板应用、登录验证、MD5密码加密等核心功能实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 

node+express项目案例(一):https://blog.youkuaiyun.com/Chris__wang/article/details/90738551

node+express项目案例(二):https://blog.youkuaiyun.com/Chris__wang/article/details/90738794

node+express项目案例(三):https://blog.youkuaiyun.com/Chris__wang/article/details/90744140


项目地址:https://github.com/wangyeky3419/node-app

数据库用的是mysql数据库,表内数据会放在代码中

本项目虽然页面不多,但是包含了基本的数据库建立,查询,修改,删除,插入,路由管理以及artTemplate模板应用,页面登录,cookie登录用户信息存储,md5密码加密等

前面已经介绍了页面的基本样式,下面开始介绍一下代码部分

项目的整体架构如上图   

README.md

# bin 项目的启动文件,也可以放其他脚本
# node_modules 项目依赖
# public 存放静态文件(css, js, img)
# routes 路由控制器
# views 视图目录 (暂时没用上)
# template  模板放的位置
# app.js 项目入口及程序启动文件
# package.json 配置信息

 由于没用涉及到文件上传,故而static目录暂时也没有用上,目录结构很清晰简单

首先介绍app.js   项目入口  注:文件中有些中间件暂时没用用上,但是后期可能会用上,所以没用删除

1. 安装node环境

2. 根据引入的中间件下载依赖    如npm install express express-static ....   --save

var express = require('express');//express框架
var static = require('express-static')//接受一个参数,就是静态资源文件所在的目录,也就是文件读取
var bodyParser = require('body-parser');//能够解析数据类的post,但是对于文件上传类型的post不能解析,所以他有点不好
var multer = require('multer');//解析post文件
var cookieParser = require('cookie-parser');
var cookieSession = require('cookie-session');
//创建一个multer对象,指明文件上传到哪个目录
const multerObj = multer({dest:'./static/upload'})
// var consolidate = require('consolidate');//----------------------
var atrTemplate = require('express-art-template')

const expressRoute = require('express-route');
var path = require('path');//解析文件路径
var favicon = require('serve-favicon');

var server = express();//创建服务
server.listen(8080);
var router = express.Router();
//1.获取前台请求数据
//get
server.use(bodyParser.urlencoded())//解析post数据的req.body数据,不然解析不出来会报错
server.use(multerObj.any())
//2. cookie session
server.use(cookieParser())
server.use(cookieParser());
(function(){
    //防止被污染变量,用一个函数包起来
    var keys = [];
    for(var i = 0; i < 10000; i++){
        keys[i]='a_'+Math.random()
    }
    server.use(cookieSession({
        name:'session_id',
        keys:keys,
        maxAge:20*60*1000//20min后过期
    }));
})()

server.use(express.static(__dirname+'/public/'))//将静态文件目录指定到public下
server.use(express.static(__dirname+'/template/'))//将每个页面的静态文件目录指定到template下

//======================模板================================
//将指定的art文件渲染成html(art)文件
server.engine('art',atrTemplate);
//模板文件放在哪,这里的views是固定写法,指定模板文件位置(这里是放在template里)
server.set('views','./template');
//输出什么东西,view engine(写法固定,意思是视图引擎),这里设置的是输出html
server.set('view engine','html');
//======================route路由==========================
//创建route放在routes文件夹中  route必须用use   不能用get

server.use('/',require('./routes/index.js')())//当访问根目录的时候,跳转到routes/index.js文件里的route
// server.use('/login',require('./routes/web/login.js')())//当访问login目录的时候,跳转到web/login.js文件里的route里

代码中注释写的非常清楚了,所以文章里就不过多介绍了

接着是跳转到routes下

其中routes下index.js是主路由,login.js    news.js    user.js分别是对应页面的路由,

index.js

const express = require('express');
const urlLib = require('url');

module.exports = function(){
    var router = express.Router();
    //检查登录状态,如更没登录,跳转到登录状态
    router.use((req,res,next)=>{//没有登录
        if(req.url!='/favicon.ico'){
            var pattern = new RegExp("/", "g");
            var reqUrl = req.url.replace(pattern,'');
            reqUrl = '/'+reqUrl
            if(!req.session['admin_id']&&reqUrl!='/login'){
                //这里检查如果没有登录(没有admin_id)就会重定向到登录界面
                //当登录后,就会设置admin_id
                res.redirect('/login');//重定向
                //备注,重定向后还是会重新访问这里文件,这时候还会做判断,如果判断失败,走else
            }else{
                next()
            }
        }
    });
    router.get('/',(req,res)=>{
        res.render('index.art',{
            path:'./user/user.art'
        })
    })

    //当访问login,跳转到login路由,进行登录页面渲染
    router.use('/login',require('./login.js')());

    //当访问user,跳转到user路由,进行user.art渲染
    router.use('/user',require('./user.js')());
 
    //当访问news,跳转到news路由,进行news.art渲染
    router.use('/news',require('./news.js')());
   
    return router;
}

在index.js里面检查登录状态时,经常会有其他路径干扰,故而加上了过滤,这里如果有大神有好办法,也希望指教一下,

routes/login.js

const express = require('express');
const mysql = require('mysql');
const utils = require('../public/utils/md5.js')//引入md5
var db = mysql.createPool({
    host:'localhost',
    user:'root',
    password:'9527',
    database:'learn'
});
module.exports = function(){
    var router = express.Router();
    //当请求方式为get的时候,约定为访问页面
    router.get('/',(req,res)=>{
        res.render('login/login.art',{});
    })
    //当请求方式为post的时候,约定为登录操作
    router.post('/',(req,res)=>{
        var username = req.body.userName;
        //将获取的密码转成md5加密形式,而且数据库存的也是加密后的,并且有后缀
        var password = utils.md5(req.body.password+utils.MD5_SUFFIX);
        db.query(`SELECT * FROM admin_table WHERE username='${username}'`,(err,data)=>{
            if(err){
                res.status(500).send('服务器出错').end()
            }else{//成功
                if(data.length == 0){
                    res.status(400).send('该用户不存在').end()
                }else{//成功且有值
                    if(data[0].password == password){//对比的是md5后的值
                        //给session赋值
                        req.session['admin_id'] = data[0].ID;
                        //重定向到首页
                        res.redirect('/')
                    }else{
                        res.status(400).send('密码不正确')
                    }
                }
            }
        })
    })
    //注册register
    router.post('/register',(req,res)=>{
        var username = req.body.userName;
        //将获取的密码转成md5加密形式,而且数据库存的也是加密后的,并且有后缀
        var password = utils.md5(req.body.password+utils.MD5_SUFFIX);
        //注册部分
    })
    return router;
}

注册部分由于时间问题没写完,这里跟普通的数据库增加数据一样,只不过是增加了一个md5密码加密

路由部分的user.js   news.js跟这也一样

下面是模板部分。这里用的是.art扩展名,index.art是首页包含导航部分,其余分别是下属子页面,其中如果js和css代码如果不多,我就直接写在art文件里了,并没有外部引用。

 

template/login/login.art     

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <!-- 因为这个是login页面,所以每个地址都会默认加上一个login,所以访问页面使用../  -->
    <link rel="stylesheet" href="../css/bootstrap.min.css">
    <link rel="stylesheet" href="./login.css">
    <title>登录</title>
</head>
<body>
    <canvas id="can"></canvas>
    <div class="box center_middle">
        <form class="center_middle loginForm" action="/login" method="post">
            <div class="form-group row">
                <label for="userName" class="col-sm-2 col-form-label">账号:</label>
                <div class="col-sm-10">
                <input type="text" class="form-control" id="userName" name="userName" placeholder="请输入账号" required>
                </div>
            </div>
            <div class="form-group row">
                <label for="password" class="col-sm-2 col-form-label">密码:</label>
                <div class="col-sm-10">
                <input type="password" class="form-control" id="password" name="password" placeholder="请输入密码" required>
                </div>
            </div>
            <div class="form-group row">
                <div class="col-sm-2"></div>
                <div class="col-sm-10">
                    <div class="form-check">
                        <input class="form-check-input" type="checkbox" id="gridCheck1">
                        <label class="form-check-label" for="gridCheck1">
                            记住密码
                        </label>
                        <a href="#">忘记密码!</a>
                    </div>
                </div>
            </div>
            <div class="form-group row">
                <div class="col-sm-8 offset-sm-4">
                <button class="btn btn-primary" type="submit">登录</button>
                &nbsp;&nbsp;&nbsp;&nbsp;
                <button type="" class="btn btn-primary" id="register" onclick="return false">注册</button>
                </div>
            </div>
        </form>

        <!-- 注册 -->
        <form class="center_middle registerForm" action="/login/register" method="post" onsubmit="return false">
            <div class="form-group row">
                <label for="name" class="col-sm-3 col-form-label">账号:</label>
                <div class="col-sm-9">
                <input type="name" class="form-control" id="userName" name="userName" placeholder="请输入账号" required>
                </div>
            </div>
            <div class="form-group row">
                <label for="password" class="col-sm-3 col-form-label">密码:</label>
                <div class="col-sm-9">
                <input type="password" class="form-control" id="password" name="password" placeholder="请输入密码" required>
                </div>
            </div>
            <div class="form-group row">
                <label for="password2" class="col-sm-3 col-form-label">确认密码:</label>
                <div class="col-sm-9">
                <input type="password" class="form-control" id="password2" placeholder="请再次输入密码" required>
                </div>
            </div>
            <div class="form-group row">
                <div class="col-sm-9 offset-sm-3">
                <button type="submit" class="btn btn-primary" id="back">返回</button>
                &nbsp;&nbsp;&nbsp;&nbsp;
                <button class="btn btn-primary" id="registerSave">注册</button>
                </div>
            </div>
        </form>
    </div>
    
    <script src="../js/jquery.min.js"></script>
    <script src="../js/bootstrap.min.js"></script>
    <script src="../js/dat.gui.js"></script>
    <script src="./login.js"></script>
</body>
</html>

template/index.art        可以对应上面的routes/index.js看

<!doctype html>
<html lang="en">
    <head>
        <meta charset="utf-8">
        <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
        <link rel="stylesheet" href="/css/bootstrap.min.css">
        <title>Chris_Wang</title>
        <style>
            .main_content {
                margin-top:56px;
            }
        </style>
    </head>
<body>
    <div class="container" style="height:3000px">
        <nav class="navbar navbar-expand-lg fixed-top navbar-dark bg-primary">
            <a class="navbar-brand" href="https://blog.youkuaiyun.com/Chris__wang" target="_blank">Chris_Wang</a>
            <div class="collapse navbar-collapse" id="navbarSupportedContent">
            <ul class="navbar-nav mr-auto">
                <li class="nav-item active nav_item_">
                <a class="nav-link" href="/">用户信息</a>
                </li>
                <li class="nav-item nav_item_news">
                <a class="nav-link" href="news">新闻列表</a>
                </li>
                <li class="nav-item dropdown">
                <a class="nav-link dropdown-toggle" href="#" id="navbarDropdown" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
                    公司简介
                </a>
                <div class="dropdown-menu" aria-labelledby="navbarDropdown">
                    <a class="dropdown-item nav_item_news_about" href="about">关于我们</a>
                    <a class="dropdown-item" href="#">企业风采</a>
                </div>
                </li>
            </ul>
            <form class="form-inline my-2 my-lg-0">
                <input class="form-control mr-sm-2" type="search" placeholder="Search" aria-label="Search">
                <button class="btn btn-outline-success my-2 my-sm-0" type="submit">Search</button>
            </form>
            </div>
        </nav>
        <div class="main_content">
            <!--根据路由跳转时传递的path数据,确定要加载的是哪个页面文件,后面的$data是传递给子组件的数据,其中routes/news.js文件处传递过data数据-->
            {{include $data['path'] $data}}
        </div>
    </div>
  </body>
</html>
<script src="/js/bootstrap.min.js"></script>
<script>
    //导航当前页高亮显示
    var items = $('.nav-item');
    var pathname = window.location.pathname
    var pattern = new RegExp("/", "g");
    var activeName = pathname.replace(pattern,'');
    for(var i = 0; i < items.length; i++){
        $(items[i]).removeClass('active')
    }
    $('.nav_item_'+activeName).addClass('active')
</script>

注:代码中部分类名如mr-sm-2  my-2等是bootstrap4里面新增加的实用性工具类,详见

https://v4.bootcss.com/docs/4.0/getting-started/introduction/

中文文档:https://cloud.tencent.com/developer/doc/1018

未完待续。。。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值