Express 是一种保持最低程度规模的灵活 Node.js Web 应用程序框架,为 Web 和移动应用程序提供一组强大的功能。
Ubuntu 16.04
假设已经安装了nodejs
mkdir myapp
cd myapp
实用npm init 命令为应用程序创建package.json文件 关于package.json的更多信息参考:https://docs.npmjs.com/files/package.json
npm init 输入相应的信息
安装express框架,如果要将express保存到依赖库中后面跟–save,否则不跟
npm install express –save
这里解释下这个 –save,就是把安装的express 和对应的版本号写进packages.json文件中,如果事先在package.json中写入了依赖,那么直接执行npm install即可
在此基础上我们来创建我们的HelloWorld
创建app.js,添加以下内容
var express = require('express');
var app = express();
app.get('/', function (req, res) {
res.send('Hello World!');
});
app.listen(3000, function () {
console.log('Example app listening on port 3000!');
});
执行node app.js 报错
Cannot find module ‘express’
分析:在安装express时已经指定了 –save,我也尝试了 -g ,但是依旧还是这个问题,后来查资料发现说是 -g安装的位置(用户目录)与node安装路径的位置不在同一个目录导致的,需要配置以下NODE_PATH,ok,我们来配置下环境变量
vim ~/.bashrc
加入(/home/master/.nvm/versions/node/v6.9.5/bin 是我node的位置)
#nodejs
export NODE_PATH=/home/master/.nvm/versions/node/v6.9.5/bin
export PATH=$PATH:$NODE_PATH
此时再执行node app.js ,浏览器访问 localhost:3000
除了手动创建程序的各个文件,我们也可以使用express应用程序生成器生成整个框架
npm install express-generator -g
可以使用-h来查看帮助
master@ubuntu:~/Desktop$ express -h
Usage: express [options] [dir]
Options:
-h, --help output usage information
--version output the version number
-e, --ejs add ejs engine support
--pug add pug engine support
--hbs add handlebars engine support
-H, --hogan add hogan.js engine support
-v, --view add view support (ejs|hbs|hjs|jade|pug|twig|vash) (defaults to jade)
-c, --css add stylesheet support (less|stylus|compass|sass) (defaults to plain css)
--git add .gitignore
-f, --force force on non-empty directory
express –view=pug myapp
master@ubuntu:~/Desktop$ express --view=pug myapp
create : myapp
create : myapp/package.json
create : myapp/app.js
create : myapp/public
create : myapp/public/javascripts
create : myapp/public/images
create : myapp/public/stylesheets
create : myapp/public/stylesheets/style.css
create : myapp/routes
create : myapp/routes/index.js
create : myapp/routes/users.js
create : myapp/views
create : myapp/views/index.pug
create : myapp/views/layout.pug
create : myapp/views/error.pug
create : myapp/bin
create : myapp/bin/www
install dependencies:
$ cd myapp && npm install
run the app:
$ DEBUG=myapp:* npm start
cd myapp
npm install
npm start
路由由于确定应用程序如何响应对特定端点的请求机会,包含一个URL(或路径)和一个特定的请求方法(GET,POST等)。每个路由都有一个或多个处理程序函数,这些函数在路由匹配时执行。
路由定义采用以下结构:
app.METHOD(PATH, HANDLER)
其中:
路由方法派生自HTTP方法之一,以下代码是为访问应用程序根目录的GET和POST方法定义的路由示例
// GET method route
app.get('/', function (req, res) {
res.send('GET request to the homepage');
});
// POST method route
app.post('/', function (req, res) {
res.send('POST request to the homepage');
});
Express 支持对英语HTTP方法的以下路由方法:get,post,put,head,delete,options,trace,copy,lock,mkcol,move,purge,propfind,proppatch,unlock,report,mkactivity,ceckout,merge,msearch,notify,subscribe,unsubscribe,patch,connect。
有一种特殊的路由方法:app.all() ,他并非派生自HTTP方法,该方法用于在所有请求方法的路径中装入中间件函数。在以下示例中,无论使用GET。POST,PUT,DELETE还是http模块中支持的其他任何HTTP请求方法,都将为针对 “/secret” 的请求执行处理程序。
app.all('/',function(req,res,next){
console.log('Accessing the secret section...');
next(); //pass control to the next handle
});
路由路径
路由路径与请求方法相结合,用于定义可以在其中提出请求的端点。路由路径可以是字符串,字符串模式或正则表达式。以下是基于字符串路由的一些示例:
// 此路由路径将请求与根路由 / 匹配。
app.get('/',function(req,res){
res.send('root');
});
//此路由路径将请求与 /about 匹配。
app.get('about',function(req,res){
res.send('about');
});
//此路由路径将请求与 /random.text 匹配。
app.get('/random.text',function(req,res){
res.send('random.text');
});
//以下是基于字符串模式的路由路径的一些示例。
//此路由路径将匹配 acd 和 abcd。
app.get('/ab?cd',function(req,res){
res.send('ab?cd')
});
//此路由路径将匹配 abcd、abbcd、abbbcd 等。
app.get('/ab+cd',function(req,res){
res.send('ab+cd');
});
//此路由路径将匹配 abcd、abxcd、abRABDOMcd、ab123cd 等。
app.get('ab*cd',function(req,res){
res.send('ab*cd');
});
//此路由路径将匹配 /abe 和 /abcde。
app.get('/ab(cd)?e',function(req,res){
res.send('/a/');
});
//基于正则表达式的路由路径的示例:
//此路由路径将匹配名称中具有“a”的所有路由。
app.get(/a/,function(req,res){
res.send('/a/');
});
// 此路由路径将匹配 butterfly 和 dragonfly,但是不匹配 butterflyman、dragonfly man 等。
app.get(/.*fly$/,function(req,res){
res.send('/.*fly$/');
});
你可以提供多个回调函数,以类似与中间件的行为方式来处理请求,唯一例外是这些回调函数可能调用 next(‘route’) 来绕过省区的路由回调,你可以使用此机制对路由施加先决条件,在灭有路由继续执行当前路由的情况下,可将控制权传递给后续路由。路由处理程序的形式可以是一个函数,一组函数,或者两者的结合,如下示例所示:
//单个回调函数可以处理一个路由。例如:
app.get('/example/a',function(req,res){
res.send('Hello from A');
});
//多个回调函数可以处理一个路由(确保您指定 next 对象)。例如:
app.get('/example/b', function(req,res,next){
console.log('the respnse will be sent by the next function');
next();
},function(req,res){
res.send('Hello from B');
});
//一组回调函数可以处理一个路由。例如:
var cb0 = function(req,res,next){
console.log('CB0');
next();
};
var cb1 = function(req,res,next){
console.log('CB1');
next();
};
var cb2 = function(res,res){
res.send('Hello from C');
};
app.get('/example/c',[cb0,cb1,cb2]);
//独立函数与一组函数的组合可以处理一个路由。例如:
var ab1 = function(req,res,next){
console.log('AB1');
next();
};
var ab2 = function(req,res,next){
console.log('AB2');
next();
}
app.get('/example/d',[ab1,ab2],function(req,res,next){
console.log('the response will be sent by the next function ...');
next();
},function(req,res){
res.send('Hello from D');
});
下表中响应独享(res)的方法可以向客户机发送响应,并终止请求/响应循环。如果没有从路由处理程序调用其中任何方法,客户机请求将保持挂起状态。
方法 | 描述 |
---|---|
res.download() | 提示将要下载文件。 |
res.end() | 结束响应进程。 |
res.json() | 发送 JSON 响应。 |
res.jsonp() | 在 JSONP 的支持下发送 JSON 响应。 |
res.redirect() | 重定向请求。 |
res.render() | 呈现视图模板。 |
res.send() | 发送各种类型的响应。 |
res.sendFile | 以八位元流形式发送文件。 |
res.sendStatus() | 设置响应状态码并以响应主体形式发送其字符串表示 |
你可以使用app.route() 为路由路径创建可链接的路由处理程序,因为在单一位置指定路径,所以可以减少冗余和输入错误,有关路由的更多信息,请参阅:http://expressjs.com/zh-cn/4x/api.html#router
//以下是使用 app.route() 定义的链式路由处理程序的示例。
app.route('/book')
.get(function(req,res){
res.send('Get a random book');
})
.post(function(req,res){
res.send('add a book');
})
.put(function(req,res){
res.send('update the book');
});
使用express.Router类来创建可安装的模块化路由处理程序,Router实例是完整的中间件和路由系统,因此,常常将其称为” 微型应用程序”。以下示例将路由器创建为模块,在其中装入中间件,定义一些路由,然后安装在主应用程序的路径中。
在应用程序中创建birds.js文件,写入以下内容:
var express = require('express')
var router = express.Router();
// middleware that is specific to this router
router.use(function(req,res,next){
console.log('Time:' ,Date.now());
next();
});
// define the home page route
router.get('/',function(req,res){
res.send('Birds home page');
});
// define the about route
router.get('/about',function(req,res){
res.send('About birds');
})
module.exports = router
在app.js中引用
var birds = require('./birds');
var express = require('express');
var app = express();
app.listen(3000, function () {
console.log('Example app listening on port 3000!');
});
app.use('/birds',birds);
此应用程序现在可针对 /birds 和 /birds/about 的请求,调用特定于此路由的 timeLog 中间价函数。
为了提供诸如图像、CSS 文件和 JavaScript 文件之类的静态文件,请使用 Express 中的 express.static 内置中间件函数。
将包含静态资源的目录的名称传递给 express.static 中间件函数,以便开始直接提供这些文件。例如,使用以下代码在名为 public 的目录中提供图像、CSS 文件和 JavaScript 文件:
app.use(express.static(‘public’));
现在便可以引用public目录下的文件
http://localhost:3000/images/kitten.jpg
http://localhost:3000/css/style.css
http://localhost:3000/js/app.js
http://localhost:3000/images/bg.png
http://localhost:3000/hello.html
Express 相对于静态目录查找文件,因此静态目录的名称不是此 URL 的一部分。
要使用多个静态资源目录,请多次调用 express.static 中间件函数:
app.use(express.static(‘public’));
app.use(express.static(‘files’));
Express 以您使用 express.static 中间件函数设置静态目录的顺序来查找文件。
要为 express.static 函数提供的文件创建虚拟路径前缀(路径并不实际存在于文件系统中),请为静态目录指定安装路径,如下所示:
app.use(‘/static’, express.static(‘public’));
现在,可以装入具有 /static 路径前缀的 public 目录中的文件。
http://localhost:3000/static/images/kitten.jpg
http://localhost:3000/static/css/style.css
http://localhost:3000/static/js/app.js
http://localhost:3000/static/images/bg.png
http://localhost:3000/static/hello.html
然而,向 express.static 函数提供的路径相对于您在其中启动 node 进程的目录。如果从另一个目录运行 Express 应用程序,那么对于提供资源的目录使用绝对路径会更安全:
app.use(‘/static’, express.static(__dirname + ‘/public’));
Express框架的入门篇基本就是上边这些内容了,截止到这里我们并没有演示一个完整的例子,那么下面我们来看一个表单提交的例子,在以上代码的基础上。
在项目myapp 目录下创建public (存放img,js,css文件)和templates(存放html文件)
var express = require('express');
// var birds = require('./birds');
var app = express();
app.use(express.static('public')); //static file
app.use(express.static('templates')); //static file
//
// app.listen(3000, function () {
// console.log('Example app listening on port 3000!');
// });
app.get('/index.html', function (req, res) {
res.sendFile( __dirname + "/" + "index.html" );
})
app.get('/form_get', function (req, res) {
// 输出 JSON 格式
response = {
username:req.query.username,
email:req.query.email,
};
console.log(response);
res.end(JSON.stringify(response));
})
var server = app.listen(3000, function () {
var host = server.address().address
var port = server.address().port
console.log("应用实例,访问地址为 http://%s:%s", host, port)
})
<html>
<head>
<meta charset="UTF-8">
<title>testtitle>
<link rel="stylesheet" href="http://127.0.0.1:3000/css/index.css">
head>
<div class="login-main">
<h3 align="center">------------Login-------------h3>
<form role="form" method="get" action="http://127.0.0.1:3000/form_get">
<input class="incon" name="username" type="text" placeholder="username">
<input class="incon" name="email" type="text" placeholder="email">
<input class="btnincon" type="submit" value="登录">
<hr style="height:1px;border:none;border-top:1px solid darkgray;" />
form>
table>
div>
body>
html>
/*登录注册样式 */
hr{
margin-bottom: 5px;}
.loginbody{ background-repeat: no-repeat; background-size:cover;}
.login-main{
width:400px; height: 300px;margin: auto; overflow: hidden; margin-top:8%; border-radius: 4px; border: 1px solid darkgray;
box-shadow: -10px 10px 20px gray;}
.login-main h3{ text-indent: 0.5em;}
.incon{ width: 360px; font-size: 16px; margin-left:20px; margin-top:20px; height: 38px; border-radius: 2px; text-indent: 1em;}
.btnincon{ width: 200px; font-size: 16px; margin-left:100px; margin-top:20px; height: 38px; border-radius: 2px; text-indent: 1em;}
把html文件中的method改为 post,action中的form_get 改成form_post
var bodyParser = require('body-parser');
// 创建 application/x-www-form-urlencoded 编码解析
var urlencodedParser = bodyParser.urlencoded({ extended: false })
app.post('/form_post', urlencodedParser, function (req, res) {
// 输出 JSON 格式
response = {
username:req.bod.username,
email:req.body.email,
};
console.log(response);
res.end(JSON.stringify(response));
})
npm install body-parser –save
重新测试会看到同样的效果
<html>
<head>
<title>文件上传表单title>
head>
<body>
<h3>文件上传:h3>
选择一个文件上传: <br />
<form action="/file_upload" method="post" enctype="multipart/form-data">
<input type="file" name="image" size="50" />
<br />
<input type="submit" value="上传文件" />
form>
body>
html>
var express = require('express');
var app = express();
var fs = require("fs");
var bodyParser = require('body-parser');
var multer = require('multer');
app.use(express.static('public'));
app.use(express.static('templates'));
app.use(bodyParser.urlencoded({ extended: false }));
app.use(multer({ dest: '/tmp/'}).array('image'));
app.get('/index.html', function (req, res) {
res.sendFile( __dirname + "/" + "index.html" );
})
app.post('/file_upload', function (req, res) {
console.log(req.files[0]); // 上传的文件信息
var des_file = __dirname + "/" + req.files[0].originalname;
fs.readFile( req.files[0].path, function (err, data) {
fs.writeFile(des_file, data, function (err) {
if( err ){
console.log( err );
}else{
response = {
message:'File uploaded successfully',
filename:req.files[0].originalname
};
}
console.log( response );
res.end( JSON.stringify( response ) );
});
});
})
var server = app.listen(3000, function () {
var host = server.address().address
var port = server.address().port
console.log("应用实例,访问地址为 http://%s:%s", host, port)
})
npm install fs –save
npm install multer –save
上一篇:Node.js历险记之剑未配好,已出江湖