转载:http://www.cnblogs.com/zhongweiv/p/nodejs_express_webapp1.html

目录

  • 前言
  • 新建express项目并自定义路由规则
  • 如何提取页面中的公共部分?
  • 如何提交表单并接收参数?
    • GET 方式
    • POST 方式
  • 如何字符串加密?
  • 如何使用session?
  • 如何使用cookies?
  • 如何清除session和cookies?
  • 写在之后

前言

 经过学习Node.js,基本可以开始动手构建一个网站应用了,先用这一篇了解一些构建网站的知识!

 主要是些基础的东西,这里我们说下 express 项目分析...

 先从app.js看起

  • app.set(name,value)

  把名字为name的项的值设为value,用于设置参数

  app.set('views', path.join(__dirname, 'views'));   设置了模版文件夹的路径;主要清楚__dirname的意思就可以了,它是node.js中的全局变量,表示取当前执行文件的路径

  app.set('view engine', 'ejs');  设置使用的模版引擎,我们使用的ejs

  • app.use([path], function)

    用这个方法来使用中间件,因为express依赖于connect,有大量的中间件,可以通过app.use来使用;path参数可以不填,默认为'/'  (项目中用到的就不分别解释了,用到的时候自已查一API的中间件部分)

  app.use(express.static(path.join(__dirname, 'public'))); 这一句中可能要注意一下,express.static( )是处理静态请求的,设置了public文件,public下所有文件都会以静态资料文件形式返回(如样式、脚本、图片素材等文件)

var routes = require('./routes/index');
var users = require('./routes/users'); app.use('/', routes);
app.use('/users', users);

  上面代码表示当用户使用/访问时,调用routes,即routes目录下的index.js文件,其中.js后缀省略,用/users访问时,调用routes目录下users.js文件

  这就是为什么,我们示例中用http://localhost:8100/访问是,修改的index.js里的文件代码可以执行(当然index.js文件中也要写对应的代码,才能是我们最终看到的效果)

  • app.get(name)

  获取名为name的项的值

if (app.get('env') === 'development') {
app.use(function(err, req, res, next) {
res.status(err.status || 500);
res.render('error', {
message: err.message,
error: err
});
});
}

  表示如果是开发环境,处理error时会输出堆栈信息

  • 路由文件index.js

  主要看下面这段代码

router.get('/', function(req, res) {
res.render('index', { title: '<h1>Express</h1>'
,users:[{username: 'Wilson'},
{username: 'Wilson Zhong'},
{username: 'Zhong Wei'}]
});
});

  这段表示,router.get表示通过get请求/时,响应后面的function处理,两个参数分别是request、response;

  res.render表示调用模版引擎,解析名字index的模板,传并传入了title和users两个对象做为参数;

  为什么它会知道解板views目录下的index.ejs?而不是其它目录下的文件,或者后其它后缀名的文件?

  原因就是app.js中的设置:

app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'ejs');

  而这两个参数在index.ejs中可以使用,那么加上ejs的部分,就会返回最终生成的页面展现!

  如何去创建路由规则、如何去提交表单并接收表单项的值、如何去给密码加密、如何去提取页面公共部分(相当于用户控件和母版页)等等...

  下面就一步步开始吧^_^!...

新建express项目并自定义路由规则

  • 首先用命令行express+ejs创建一个项目sampleEjsPre
cd 工作目录
express -e sampleEjsPre
cd sampleEjsPre && npm install
  • 默认会有routes目录下会有index.js和users.js文件,这里为了不产生其它示例外的困扰,删除user.js文件
  • 打开app.js文件删除下面两行代码
var users = require('./routes/users');

...

app.use('/users', users);
  • 在routes目录下添加subform.js、usesession.js、usecookies.js、usecrypto.js文件,并在对应的js文件中添加如下代码

    var express = require('express');
    var router = express.Router(); /* GET home page. */
    router.get('/', function(req, res) {
    res.render('subform', { title: '提交表单及接收参数示例' });
    }); module.exports = router; subform.js 代码

    subform.js

    var express = require('express');
    var router = express.Router(); /* GET home page. */
    router.get('/', function(req, res) {
    res.render('usesession', { title: '使用session示例' });
    }); module.exports = router; usesession.js 代码

    usesession.js

    var express = require('express');
    var router = express.Router(); router.get('/', function(req, res) {
    res.render('usecookies', { title: '使用cookies示例' });
    }); module.exports = router; usecookies.js 代码

    usecookies.js

    var express = require('express');
    var router = express.Router(); router.get('/', function(req, res) {
    res.render('usecrypto', { title: '加密字符串示例' });
    }); module.exports = router; usecrypto.js 代码

    usecrypto.js

  • 在views目录下添加subform.ejs、usesession.ejs、usecookies.ejs、usecrypto.ejs文件,并在views目录下除了error.ejs外所有ejs文件中添加如下代码
<!DOCTYPE html>
<html>
<head>
<title><%= title %></title>
<link rel='stylesheet' href='/stylesheets/style.css' />
</head>
<body>
<a href="/">首页</a>
<a href="/subform">如何提交表单并接收参数?</a>
<a href="/usesession">如何使用session?</a>
<a href="/usecookies">如何使用cookies?</a>
<a href="/usecrypto">如何字符串加密?</a>
</body>
</html>
  • 在app.js文件中添加如下代码
  • var subform = require('./routes/subform');
    var usesession = require('./routes/usesession');
    var usecookies = require('./routes/usecookies');
    var usecrypto = require('./routes/usecrypto'); ... app.use('/subform', subform);
    app.use('/usesession', usesession);
    app.use('/usecookies', usecookies);
    app.use('/usecrypto', usecrypto);

    通过URL访问后,根据路由规则先到哪个文件,这里再说明下(app.js中有如下内容):

app.use([path], function)

  用这个方法来使用中间件,因为express依赖于connect,有大量的中间件,可以通过app.use来使用;path参数可以不填,默认为'/' (项目中用到的就不分别解释了,用到的时候自已查一API的中间件部分)

  app.use(express.static(path.join(__dirname, 'public'))); 这一句中可能要注意一下,express.static( )是处理静态请求的,设置了public文件,public下所有文件都会以静态资料文件形式返回(如样式、脚本、图片素材等文件)

var routes = require('./routes/index');
var users = require('./routes/users'); app.use('/', routes);
app.use('/users', users);

上面代码表示当用户使用/访问时,调用自定义变量routes,即 routes 目录下的 index.js 文件,其中.js后缀省略;

      用/users访问时,调用自定义变量uses,即 routes 目录下 users.js 文件

  这就是为什么,我们示例中用http://localhost:8100/访问是,修改的index.js里的文件代码可以执行(当然index.js文件中也要写对应的代码,才能是我们最终看到的效果)

  • 在app.js中添加8000端口监听并运行
...
app.listen(8000);
...

  运行界面如下:

  点击各链接都能正常跳转到对应的页面!这样第一步的目录就算达到了!

如何提取页面中的公共部分?

  在上一步创建的网站中每个页面都几乎一样,现在都只有导航部分?每个页都要写?当然不是,我们可以提取出来

  • 在views目录下新建一个nav.ejs文件,并添加如下代码
<a href="/">首页</a>
<a href="/subform">如何提交表单并接收参数?</a>
<a href="/usesession">如何使用session?</a>
<a href="/usecookies">如何使用cookies?</a>
<a href="/usecrypto">如何字符串加密?</a>
  • 把views目录下index.ejs、subform.ejs、usesession.ejs、usecookies.ejs、usecrypto.ejs修改成如下代码
<!DOCTYPE html>
<html>
<head>
<title><%= title %></title>
<link rel='stylesheet' href='/stylesheets/style.css' />
</head>
<body>
<% include nav %> # 若改为了其他引擎,例如 nav.html, 此处则需写成 <% include nav.html %>
</body>
</html>

  运行页面,发现和上次运行时没有作何区别,有了这样的办法更有利于减少重复代码、也更有利于统一布局!

<% include 文件名 %> express提供include来嵌入其它页,这和html嵌入其它页类似

如果用过express2.0版本的会发现当时没有这个include,用的是一个模版文件layout.ejs来布局!

如何提交表单并接收参数?

  如果要做一个网站应用,不可避免的会遇到表单的提交及获取参数的值,下面我们来看看用node.js + express怎么做

先来构建一个表单简单模拟登录GET方式提交数据

  • 打开subform.ejs文件,修改文件代码为如下:

<!DOCTYPE html>
<html>
<head>
<title><%= title %></title>
<link rel='stylesheet' href='/stylesheets/style.css' />
</head>
<body>
<% include nav %> <form>
用户名:<input type="text" id="txtUserName" name="txtUserName" />
密码:<input type="password" id="txtUserPwd" name="txtUserPwd" />
<input type="submit" value="提交">
</form> </body>
</html> subform.ejs 示例代码

subform.ejs 示例代码

  • 打开subform.js我们试着接收参数值并输出到控制台

     

var express = require('express');
var router = express.Router(); router.get('/', function(req, res) {
var
userName = req.query.txtUserName,
userPwd = req.query.txtUserPwd,
userName2 = req.param('txtUserName'),
userPwd2 = req.param('txtUserPwd'); console.log('req.query用户名:'+userName);
console.log('req.query密码:'+userPwd);
console.log('req.param用户名:'+userName2);
console.log('req.param密码:'+userPwd2); res.render('subform', { title: '提交表单及接收参数示例' });
}); module.exports = router; subform.js get方式源码

subform.js get方式源码

  • 运行,并提交表单 在浏览器中运行:http://localhost:8000/subform,输入表单项并提交,可以发现url发生了变化

  

  可以发现url中出现了我表单中输入并要提交的值!

  我们再看看控制台的输出

  

   我们完成了GET方式提交表单并接收到了值,不错^_^!(稍后在后面再去讲得到值的方式和区别)

  再来在上面的代码基础上去修改一下表单的method简单模拟登录POST方式提交数据

  • 首先修改一下subform.ejs文件中的form标签,修改为如下:
<form method="post">
...
</form>
  • 再在subform.js中添加代码,接收post提交、接收参数并输出到控制台
...

router.post('/',function(req, res){
var
userName = req.body.txtUserName,
userPwd = req.body.txtUserPwd,
userName2 = req.param('txtUserName'),
userPwd2 = req.param('txtUserPwd'); console.log('req.body用户名:'+userName);
console.log('req.body密码:'+userPwd);
console.log('req.param用户名:'+userName2);
console.log('req.param密码:'+userPwd2);  res.render('subform', { title: '提交表单及接收参数示例' }); }); ...
  • 运行,并提交表单 在浏览器中运行:http://localhost:8000/subform,输入表单项并提交,可以发现url不会发生变化

  

  改为post方式后,会发现不会跟get方式提交一样在url中出现了表单中输入并要提交的值!

  我们再看看控制台的输出

  

  OK,我们完成了POST提交表单并接收参数!

  再回过头看看GET和POST方式接收值,从直接效果上来看 

req.query:我用来接收GET方式提交参数

req.body:我用来接收POST提交的参数

req.params:两种都能接收到

  

大家自行看看Express的Request部分的API:http://expressjs.com/api.html#req.params

这里着重解释一下req.body,Express处理这个post请求是通过中间件bodyParser,你可以看到app.js中有一块代码

...

var bodyParser = require('body-parser');

...

app.use(bodyParser.json());
app.use(bodyParser.urlencoded()); ...

  没有这个中间件Express就不知道怎么处理这个请求,通过bodyParser中间件分析 application/x-www-form-urlencoded和application/json请求,并把变量存入req.body,这种我们才能够获取到!

如何字符串加密?

  当我们提交表单后,比如密码这些敏感信息,不做个加密处理那也太不把用户私密信息当回事了,Node.js提供了一个加密模块 Crypto http://nodejs.org/api/crypto.html

  下面我们用个示例使用一下

  • 打开usecrypto.js,修改代码为如下:
var express = require('express');
var router = express.Router();
var crypto = require('crypto'); /* GET home page. */
router.get('/', function(req, res) { res.render('usecrypto', { title: '加密字符串示例' }); }); router.post('/',function(req, res){
var
userName = req.body.txtUserName,
userPwd = req.body.txtUserPwd; //生成口令的散列值
var md5 = crypto.createHash('md5'); //crypto模块功能是加密并生成各种散列
var en_upwd = md5.update(userPwd).digest('hex'); console.log('加密后的密码:'+en_upwd); res.render('usecrypto', { title: '加密字符串示例' });
}); module.exports = router;
  • 打开usecrypto.ejs,修改代码为如下
<!DOCTYPE html>
<html>
<head>
<title><%= title %></title>
<link rel='stylesheet' href='/stylesheets/style.css' />
</head>
<body>
<% include nav %> <form method="post">
用户名:<input type="text" id="txtUserName" name="txtUserName" />
密码:<input type="password" id="txtUserPwd" name="txtUserPwd" />
<input type="submit" value="提交">
</form>
</body>
</html>
  • 运行,输入并提交表单,查看控件台输出

  

  成功MD5方式加密!

  其中用到了createHash(algorithm)方法 ,这是利用给定的算法生成hash对象

  Node.js提供的加密模块功能非常强大,Hash算法就提供了MD5、sha1、sha256等,根据需要去使用

  update(data, [input_encoding])方法,可以通过指定的input_encoding和传入的data数据更新hash对象,input_encoding为可选参数,没有传入则作为buffer处理 (input_encoding可为'utf-8'、'ascii'等)

  digest([encoding])方法,计算数据的hash摘要值,encoding是可选参数,不传则返回buffer (encoding可为 'hex'、'base64'等);当调用digest方法后hash对象将不可用;

如何使用session?

  Internet通讯协议分为stateful和stateless两类,对Web开发有一定了解的应该知道,http是stateless协议,客户端发送请求到服务端建立一个连接,请求得得到响应后连接即中断,服务器端不会记录状态,因此服务器端想

  要确定是哪个客户端提交过来的请求,那就必须要借助一些东西去完成,就是session和cookies,现在我们先说说session,以及在nodejs下使用session !

  session存在于服务器端,需要cookies的协助才能完成;服务器端和客户端通过session id来建立联系(具体session和cookies怎么协作的,可以自已去补充点相关知识,这里只简单提一下,不展开了,要不然这篇文章就更杂了^_^!)

  express中可以用中间件来使用session,express-session(https://github.com/expressjs/session ) 可以存在内存中,也可以存在mongodb、redis等中...

  更多中间件:https://github.com/senchalabs/connect#middleware

  下面我们通过示例看看怎么使用session  (内存方式)

  示例设计思路:使用两个页面,一个登录,两个页都判断是否有这个session,如果有,显示已登录,没有则显示一个登录按钮,点此按钮,记录session

  • 首先通过npm安装这个中间件,打开package.json文件,在dependencies节点下添加一个键值对  "express-session" : "latest" 
  "dependencies": {
...,
"express-session" : "latest"
}

  lateset:最新的

  • cd到项目根目录下,执行npm install

  

  • 打开app.js,添加如下代码
var express = require('express');
var path = require('path');
var favicon = require('static-favicon');
var logger = require('morgan');
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');
var session = require('express-session'); ... //这里传入了一个密钥加session id
app.use(cookieParser('Wilson'));
//使用靠就这个中间件
app.use(session({ secret: 'wilson'})); ...

  这些options就不解释了,通过上面中间件的链接,自已看一下

  • 我这里使用 usesession 和 usecookies 作示例,修改 js 和 ejs 如下

  

  

<!DOCTYPE html>
<html>
<head>
<title><%= title %></title>
<link rel='stylesheet' href='/stylesheets/style.css' />
</head>
<body>
<% include nav %> <% if(locals.islogin){ %>
用户已登录
<% } else { %>
<form method="post">
<input type="submit" value="登录">
</form>
<% } %>
</body>
</html> usesession.ejs 和 usecookies.ejs

usesession.ejs 和 usecookies.ejs

var express = require('express');
var router = express.Router(); router.get('/', function(req, res) { if(req.session.islogin)
{
console.log('usesession:' + req.session.islogin);
res.locals.islogin = req.session.islogin;
} res.render('usesession', { title: '使用session示例' });
}); router.post('/', function(req, res) { req.session.islogin = 'success';
res.locals.islogin = req.session.islogin; res.render('usesession', { title: '使用session示例' });
}); module.exports = router;

usession.js

var express = require('express');
var router = express.Router(); router.get('/', function(req, res) { if(req.session.islogin)
{
console.log('usecookies:' + req.session.islogin);
res.locals.islogin = req.session.islogin;
} res.render('usecookies', { title: '使用cookies示例' });
}); router.post('/', function(req, res) { req.session.islogin = 'success';
res.locals.islogin = req.session.islogin; res.render('usecookies', { title: '使用cookies示例' });
}); module.exports = router; usecookies.js 示例代码

usecookies.js

  • 运行并查看

  第一次运行时,查看两个页,效果如下:

  

  

  • 点击登录按钮后,再查看这两个页

  

  

  • 关闭浏览器,再打开查看这两个页,如第5步截图效果

  

  session的使用成功!

  

  官方示例:https://github.com/visionmedia/express/blob/master/examples/session/index.js

如何使用cookies?

  如果是登录,那常见就是“记录密码”或“自动登录”功能,这个一般用 cookies来完成

  cookies存在客户端,安全性较低,一般要存入加密后的信息;建议要设置使用过期时间或不使用时删除掉

  express也同样可以用中间件来使用:https://github.com/expressjs/cookie-parser

  

老套路,通过一个示例了解一下

   示例设计思路:在上面session示例的基础上,在usecookies部分登录同时记录cookies,来自动登录

  • 在上面session示例的基础上修改一下usecookies.js
var express = require('express');
var router = express.Router(); router.get('/', function(req, res) { if(req.cookies.islogin)
{
console.log('usecookies-cookies:' + req.cookies.islogin);
req.session.islogin = req.cookies.islogin;
} if(req.session.islogin)
{
console.log('usecookies:' + req.session.islogin);
res.locals.islogin = req.session.islogin;
} res.render('usecookies', { title: '使用cookies示例' });
}); router.post('/', function(req, res) { req.session.islogin = 'success';
res.locals.islogin = req.session.islogin; res.cookie('islogin', 'sucess', { maxAge: 60000 }); res.render('usecookies', { title: '使用cookies示例' });
}); module.exports = router;
  • 运行访问 http://localhost:8000/usecookies,点击登录按钮登录成功并记录cookies

maxAge为过期时长,毫秒为单位,我设置一分钟

  • 关闭浏览器,再次访问http://localhost:8000/usecookies ,页面显示已登录
  • 再次关闭浏览器,过一分钟再访问http://localhost:8000/usecookies,页面不再是已登录,而是显示登录按钮,表示cookies过期,不会自动登录

  cookies的使用到此也成功!

  官方示例:https://github.com/visionmedia/express/blob/master/examples/cookies/app.js   

 

如何清除session和cookies?

  清除非常简单,就不用示例说明了,有兴趣自已定义个路由规则,试试

//清除cookies
res.clearCookie('islogin'); //清除session
req.session.destroy();

写在之后

  最近比较忙,更新距上了篇时间较长了,本篇东西讲的比较杂,讲到的也比较有限,主要是为了后来会写的一个示例打基础;

  本篇内容讲到的一些知识点,其实都可以单独拿一整篇去讲,本篇基本原则是为了看了之后能使用;

  要想弄清楚原理或者更多的相关知识,自已可以花点时间去了解,或者找点资料去丰富一下,当然也可以留言,在我觉得我没乱说的情况下我会尽量解答^_^!

Next: modeJS(2)深了解: nodeJS 项目架构详解(app.js + Express + Http)

modeJS 深了解(1): Node.js + Express 构建网站预备知识的更多相关文章

  1. Nodejs学习笔记(六)--- Node.js + Express 构建网站预备知识

    目录 前言 新建express项目并自定义路由规则 如何提取页面中的公共部分? 如何提交表单并接收参数? GET 方式 POST 方式 如何字符串加密? 如何使用session? 如何使用cookie ...

  2. Nodejs学习笔记(六)—Node.js + Express 构建网站预备知识

    前言 前面经过五篇Node.js的学习,基本可以开始动手构建一个网站应用了,先用这一篇了解一些构建网站的知识! 主要是些基础的东西... 如何去创建路由规则.如何去提交表单并接收表单项的值.如何去给密 ...

  3. Nodejs学习笔记(七)--- Node.js + Express 构建网站简单示例

    目录 前言 新建项目.建立数据库以及其它准备工作 新建express + ejs 项目:sampleEjs 创建数据库 修改package.json文件,安装session和mysql模块 样式和JQ ...

  4. Nodejs学习笔记(七)—Node.js + Express 构建网站简单示例

    前言 上一篇学习了一些构建网站会用到的一些知识点:https://www.cnblogs.com/flyingeagle/p/9192936.html 这一篇主要结合前面讲到的知识,去构建一个较为完整 ...

  5. Nodejs学习笔记(十五)--- Node.js + Koa2 构建网站简单示例

    目录 前言 搭建项目及其它准备工作 创建数据库 创建Koa2项目 安装项目其它需要包 清除冗余文件并重新规划项目目录 配置文件 规划示例路由,并新建相关文件 实现数据访问和业务逻辑相关方法 编写mys ...

  6. [转]Nodejs学习笔记(十五)--- Node.js + Koa2 构建网站简单示例

    本文转自:https://www.cnblogs.com/zhongweiv/p/nodejs_koa2_webapp.html 目录 前言 搭建项目及其它准备工作 创建数据库 创建Koa2项目 安装 ...

  7. Nodejs学习笔记(十五)—Node.js + Koa2 构建网站简单示例

    前言 前面一有写到一篇Node.js+Express构建网站简单示例:http://www.cnblogs.com/zhongweiv/p/nodejs_express_webapp.html 这篇还 ...

  8. Node.js + Express 构建的订餐系统

    Node.js的版本 - v0.8.12 Express的版本 – v3.3.3  (安装 $ npm install -g express) 系统的登录逻辑是:获取用户名 + 密码,向内网RTX服务 ...

  9. node.js express mvc轻量级框架实践

    本文记录的是笔者最近抽私下时间给朋友做的一个时时彩自动下注系统,比较简单,主要也是为了学习一下node.js. 其实逻辑没什么可以深谈的,主要是想说说这套代码结构.结构如下图: js的代码比较难以维护 ...

随机推荐

  1. Symmetric Difference-freecodecamp算法题目

    Symmetric Difference 1.要求 创建一个函数,接受两个或多个数组,返回所给数组的对等差分(symmetric difference) 例子:给出两个集合 (如集合 A = {1, ...

  2. linux主机状态检测方式

    之前写过一个简单的脚本检测当前网段中主机状态的脚本,内容如下: #! /bin/bash #ping check host status trap "exit" 2 sping() ...

  3. form中 单选框 input[type="radio"] 分组

    在form中有时候需要给单选框分组,这种情况下 可以通过给单选框设置相同的name来进行分组: <html> <head> <title> </title&g ...

  4. Node.js 中流操作实践

    本文节选自 Node.js CheatSheet | Node.js 语法基础.框架使用与实践技巧,也可以阅读 JavaScript CheatSheet 或者 现代 Web 开发基础与工程实践 了解 ...

  5. 前段ztree 树状插件

    效果展示

  6. Insertion Sort Gym - 101955C 思路+推公式

    题目:题目链接 题意:对长为n的1到n的数列的前k个数排序后数列的最长上升子序列长度不小于n-1的数列的种数,训练赛时怎么都读不明白这个题意,最后还是赛后问了旁队才算看懂,英语水平急需拯救55555 ...

  7. Diycode开源项目 ImageActivity分析

    1.首先看一下效果 1.1做成了一个GIF 1.2.我用格式工厂有点问题,大小无法调到手机这样的大小,目前还没有解决方案. 1.3.网上有免费的MP4->GIF,参考一下这个网站吧. 1.4.讲 ...

  8. proguaid 混淆代码

    注意:这里有一个坑.就是-ignorewarnings 他老是混淆不了,告诉你不行.其实加上这句话,就可以了. 下面贴一下代码: -injars c:/ceb_lib.jar -outjars c:/ ...

  9. Java多线程-join方法

    thread.Join把指定的线程加入到当前线程,可以将两个交替执行的线程合并为顺序执行的线程.比如在线程B中调用了线程A的Join()方法,直到线程A执行完毕后,才会继续执行线程B. 具体例子看链接 ...

  10. Java中BigInteger类型

    BigInteger是java.math包提供的处理大整数类型,实现了大整数的存储,四则运算,判断素数的方法,求幂,求模,求逆元,求最大公约数等方法.本文主要分析下BigInteger对于大整数的存储 ...