官网: http://www.expressjs.com.cn/
首先假定你已经安装了 Node.js,接下来为你的应用创建一个目录,然后进入此目录并将其作为当前工作目录。
$ mkdir myapp
$ cd myapp
通过 npm init 命令为你的应用创建一个 package.json 文件。 欲了解 package.json 是如何起作用的,请参考 Specifics of npm’s package.json handling.
$ npm init
此命令将要求你输入几个参数,例如此应用的名称和版本。 你可以直接按“回车”键接受大部分默认设置即可,
接下来在 myapp 目录下安装 Express 并将其保存到依赖列表中。如下:
$ npm install express --save
var express = require("express");
var db = require("./db");
var app = express();
/**
* http://192.168.40.114:8081/hello
*/
app.get("/hello",function(req,res){
res.send("hello"); //响应内容
});
/**
* 启动web服务监听8081端口
*/
app.listen(8081,function(){
console.log("服务端启动, http://192.168.40.114:8081");
});
app.METHOD(PATH, HANDLER)
说明
• app 是express的一个实例instance
• METHOD 是 HTTP request method, in lowercase. 如GET, POST…
• PATH 是服务器请求地址路径
• HANDLER 路由匹配时执行的函数.
var express = require('express');
var app = express();
// 路由:字符串类型
app.get('/book', function(req, res, next){
res.send('book');
});
// 路由:字符串模式
app.get('/user/*man', function(req, res, next){
res.send('user'); // 比如: /user/man, /user/woman
});
Post请求处理
var express = require("express");
var db = require("./db");
var app = express();
//get请求方法,
//find请求url地址
app.get("/find",function(req,res){
res.send("find get >>>>>"); //响应内容
});
//post请求方法,
//find请求url地址
app.post("/find",function(req,res){
res.send("find post >>>>>"); //响应内容
});
/**
* 启动web服务监听8081端口
*/
app.listen(8081,function(){
console.log("服务端启动, http://192.168.40.114:8081");
});
响应数据库查询数据
db.js 模块
var mysql = require("mysql");
function query(sql,parmeters, callFunction) {
//创建数据库连接对象
var connection = mysql.createConnection(
{
host: "192.168.40.114",
user: "test",
password: "b123",
database: "ex1db"
}
);
connection.connect(); //打开数据库连接
connection.query(sql,parmeters,callFunction); //执行sql
connection.end(); //关闭数据连接
}
exports.query = query;
//module.exports = query;
app.js 模块
var express = require("express");
var db = require("./db");
var app = express();
app.get("/find",function(req,res){
var sql = "SELECT * FROM department";
db.query(sql,function(err,data){
if(err){
console.log("查询数据出错");
return;
}
var datajson = JSON.stringify(data);
res.send(datajson);
});
});
/**
* 启动web服务监听8081端口
*/
app.listen(8081,function(){
console.log("服务端启动, http://192.168.40.114:8081");
});
当你用的应用越来越复杂,不可避免的,路由规则也会越来越复杂。这个时候,对路由进行拆分是个不错的选择。
我们分别看下两段代码,路由拆分的好处就直观的体现出来了。
路由拆分前
var express = require('express');
var app = express();
app.get('/user/list', function(req, res, next){
res.send('/list');
});
app.get('/user/detail', function(req, res, next){
res.send('/detail');
});
app.listen(3000);
这样的代码会带来什么问题呢?无论是新增还是修改路由,都要带着/user前缀,这对于代码的可维护性来说是大忌。这对小应用来说问题不大,但应用复杂度一上来就会是个噩梦。
路由拆分后
可以看到,通过express.Router()进行了路由拆分,新增、修改路由都变得极为便利。
var express = require('express');
var app = express();
var user = express.Router();
user.get('/list', function(req, res, next){
res.send('/list');
});
user.get('/detail', function(req, res, next){
res.send('/detail');
});
app.use('/user', user); // mini app,通常做应用拆分
app.listen(3000);
body-parser是非常常用的一个express中间件,作用是对http请求体进行解析。使用非常简单,以下两行代码已经覆盖了大部分的使用场景。
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false })); //extended: false 表是只支持string|arrya类型,为true表示支持所有类型
在正式讲解前,我们先来看一个POST请求的报文,如下所示。
POST /test HTTP/1.1
Host: 127.0.0.1:3000
Content-Type: application/x-www-form-urlencoded; charset=utf8
Content-Encoding: gzip
name=helloword&password=123
其中需要我们注意的有Content-Type、Content-Encoding以及报文主体:
• Content-Type:请求报文主体的类型、编码。常见的类型有text/plain、application/json、application/x-www-form-urlencoded。常见的编码有utf8、gbk等。
• Content-Encoding:声明报文主体的压缩格式,常见的取值有gzip、deflate、identity。
• 报文主体:这里是个普通的文本字符串hello。
body-parser实现的要点如下:
var express = require("express");
var bodyParser = require("body-parser");
var app = express(); //创建一个express对象实例
app.use(bodyParser.json()); //解析json类型文本 content-type:application/json
app.use(bodyParser.urlencoded({extended:false})); //解析 名称值对类型文本 content-type:application/x-www-form-urlencoded
app.post("/login.do",function(req,res){
var body = req.body; //请求正文
console.log(body);
res.send(body);
});
app.get("/login.do",function(req,res){
var query = req.query; //请求正文
console.log(query);
res.send(query);
});
app.listen(8080,function(){
console.log("启动服务器成功! http://192.168.40.114:8080");
})
第一步: 安装body-parser模块
npm install body-parser
第二步: 获取模块,创建解析器
var bodyParser = require('body-parser') //获取模块
var jsonParser = bodyParser.json(); // 创建 application/json 解析 如: {名称1:值1,名称2:值2}
var urlencodedParser = bodyParser.urlencoded({ extended: false });// 创建 application/x-www-form-urlencoded 解析 如: 名称1=值1&名称2=值2
第三步: body-parser与exprerss web框架整合
app.use(jsonParser);
app.use(urlencodedParser);
第四步: 获取参数值
1. get请求
值1 = req.query.名称1
2. post请求
值1 = req.body.名称1
为了提供诸如图像、CSS 文件和 JavaScript 文件之类的静态文件,请使用 Express 中的 express.static 内置中间件函数。
此函数特征如下:
express.static(root, [options])
The root argument specifies the root directory from which to serve static assets. For more information on the options argument, see 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.static 中间件函数会根据目录的添加顺序查找所需的文件。
一般学习面向对象编程的时候,我们都会听到一句话:一切皆对象。而在学习express的过程中,很深的一个感受就是:一切皆中间件。比如常见的请求参数解析、cookie解析、gzip等,都可以通过中间件来完成。
包括但不限于如下。body-parser
compression
serve-static
session
cookie-parser
morgan
更多常用中间件,可以点击 这里 http://expressjs.com/en/resources/middleware.html
EJS是一个JavaScript模板库,用来从JSON数据中生成HTML字符串。
与最初的JavaScript相比较,一些不太了解你的代码的人可以更容易地通过EJS模板代码看得懂你的代码。
示例:
最终要实现的效果如下:
用户列表
.张三
.李四
.王二
不使用模块情况
这是用javascript实现的代码
var express = require("express");
var app = express();
/**
用户列表
.张三
.李四
.王二
*
*/
app.get("/list",function (request,response) {
var userJson = '{"title":"用户列表一","list":[{"name":"张三"},{"name":"李四"},{"name":"王二"}]}';
var userObj = JSON.parse(userJson); //json字符串=》json对象
//var jsonStr = JSON.stringify(json对象) //json对角 =>json字符串
userObj.list
var html = ''+userObj.title+'
' +
'' +
'- 张三
' +
'- 李四
' +
'- 王二
' +
'
';
response.send(html);
});
app.listen(8080,function () {
console.log("启动服务成功,监听8080端口");
});
使用EJS来找回你的明确、维护性良好的HTML代码结构。
注:data是json对象,不能使json字符串。
创建一个EJS模板,命名为userlist.ejs文件,内容如下:
ejs模块
<%= title %>
<% for(var i = 0; i
- <%= list[i].name %>
<%}%>
组装ejs模板和json数据响应给客户端
var express = require("express");
var ejs = require("ejs");
var app = express();
app.get("/list",function (request,response) {
var userJson = '{"title":"学生列表","list":[{"name":"张小三"},{"name":"李四"},{"name":"王二"}]}'; //json字符串数据
var userObj = JSON.parse(userJson); //json字符串=>json对象
ejs.renderFile("./userlist.ejs",userObj, function (err,data) {
if(err){console.log("ejs加载出错"+err);return;}
console.log(data); //控制台打印ejs模板文件和json对象数据 组装好html代码
response.send(data); //响应将ejs模板文件和json对象数据 组装好html代码给客户端;
});
});
app.listen(8080,function () {
console.log("启动服务成功,监听8080端口");
});
http://192.168.40.114:8080/list
EJS是一个javascript模板库,用来从json数据中生成HTML字符串
• 功能:缓存功能,能够缓存HTML模板;
• <% code %>用来执行javascript代码
模板中输出变量
• 声明变量<% title=“EJS Template engine” %>
• 输出变量<%= username %> 特殊字符将进行转义
<% users=["Jack","Rose","Alice","Ave"] %>
<% for(var item in users)
{ %>
- <%= users[item] %>
<% }
%>
• <% ‘脚本’ 标签,用于流程控制,无输出。
• <%_ 删除其前面的空格符
• <%= 输出数据到模板(输出是转义 HTML 标签)
• <%- 输出非转义的数据到模板
• <%# 注释标签,不执行、不输出内容
• <%% 输出字符串 ‘<%’
• %> 一般结束标签
• -%> 删除紧随其后的换行符
• _%> 将结束标签后面的空格符删除
通过 include 指令将相对于模板路径中的模板片段包含进来。(需要提供 ‘filename’ 参数。) 例如,如果存在 “./views/users.ejs” 和 “./views/user/show.ejs” 两个模板文件,你可以通过 <%- include(‘user/show’); %> 代码包含后者。
你可能需要能够输出原始内容的标签 (<%-) 用于 include 指令,避免对输出的 HTML 代码做转义处理。
<% users.forEach(function(user){ %>
<%- include('user/show', {user: user}); %>
<% }); %>
/设置默认模板引擎是html
app.engine('.html', ejs.__express);
app.set('view engine', 'html');
app.set("views","view"); //模板所在的目录为view
app.use(express.static('public')); //静态资源所有目录
(1)response.render方法用于渲染网页模板。
app.get("/", function(request, response) {
response.render("index", { message: "Hello World" });});
上面代码使用render方法,将message变量传入index模板,渲染成HTML网页。
response.render('user/user',{"title":"学生列表","list": [ { "name":"张三"},{"name":"李四"}]});
上述代码等价于下面代码ejs.renderFile, 将指定模板文件与json数据组装成html代码,发送给客户端
ejs.renderFile("./view/user/user.html", {"title":"学生列表","list": [ { "name":"张三"},{"name":"李四"}]} , function (err,data) {
if(err){
console.log("ejs模板加载出错"+err);
return;
}
response.send(data);
});
(2)response.redirect方法
response.redirect方法允许网址的重定向。可以重定向到静态文件
response.redirect("/hello/anime");
response.redirect("http://www.example.com");
response.redirect(301, "http://www.example.com");
(3)response.sendFile方法
response.sendFile方法用于发送文件。
response.sendFile("/path/to/anime.mp4");
app.use(bodyParaser.json()); //解析json类型数据
app.use(bodyParaser.urlencoded({extended:false})); //expanded:false表示解析值类型是string|Array, true表示解析值是任意类型
接收Post请求参数
var userName = req.body.name;
var passWord = req.body.password;
接收Get请求参数
var userName = req.query.name;
var passWord = req.query.password;
问题1
下述代码会报错
app.use(indexRouter);
app.use(bodyParser.urlencoded({extended:false})); //expanded:false表示解析值类型是string|Array, true表示解析值是任意类型
改为交换两行代码位置后正常
//必须放到路由前面
app.use(bodyParser.urlencoded({extended:false})); //expanded:false表示解析值类型是string|Array, true表示解析值是任意类型
app.use(indexRouter);