安裝express
安裝 Express 并將其保存到依賴列表中:
$ cnpm install express --save
以上命令會將 Express 框架安裝在當前目錄的 node_modules 目錄中, node_modules 目錄下會自動創建 express 目錄。以下幾個重要的模塊是需要與 express 框架一起安裝的:
- body-parser - node.js 中間件,用于處理 JSON, Raw, Text 和 URL 編碼的數據。
- cookie-parser - 這就是一個解析Cookie的工具。通過req.cookies可以取到傳過來的cookie,并把它們轉成對象。
- multer - node.js 中間件,用于處理 enctype="multipart/form-data"(設置表單的MIME編碼)的表單數據。
安裝完后,我們可以查看下 express 使用的版本號:
$ cnpm list express
/data/www/node
└── express@4.15.2 -> /Users/tianqixin/www/node/node_modules/.4.15.2@express
express項目架構
Express項目的架構可以根據具體需求和規模的不同而有所不同,但通常遵循一些基本的組織原則。以下是一個常見的Express項目架構示例:
- 根目錄結構:
-
app.js
?或 ?server.js
:Express應用程序的入口文件,包含應用程序的配置和啟動代碼。package.json
:包含項目的依賴項和腳本配置。node_modules/
:存放項目依賴的Node.js模塊。public/
:存放靜態文件(如CSS、JavaScript、圖片等)。views/
:存放視圖模板文件(如EJS、Pug等)。
- 路由結構:
-
routes/
目錄:存放路由文件,可根據功能或模塊劃分子路由文件。app.js
中設置路由:在app.js
中通過app.use
或app.get
等方法將路由文件引入并設置路由路徑。
- 中間件:
-
middlewares/
目錄:存放自定義中間件函數。app.js
中使用中間件:在app.js
中通過app.use
方法使用中間件。
- 控制器:
-
controllers/
目錄:存放路由處理函數,負責處理請求并返回響應。- 與路由文件分離:控制器文件應與路由文件分離,遵循單一職責原則。
- 模型:
-
models/
目錄:存放數據模型定義和數據庫操作。- 與控制器分離:模型文件應與控制器文件分離,負責數據操作和業務邏輯。
- 配置:
-
config/
目錄:存放配置文件,如數據庫配置、環境變量等。- 環境變量:使用
.env
文件存放敏感信息,并通過dotenv
模塊加載。
- 錯誤處理:
-
- 錯誤處理中間件:編寫統一的錯誤處理中間件,處理應用程序中發生的錯誤。
- 測試:
-
tests/
目錄:存放單元測試和集成測試文件,使用測試框架進行測試。
以上是一個基本的Express項目架構示例,你可以根據具體項目需求和規模進行調整和擴展。
創建一個express示例
var express = require('express');
var app = express();app.get('/', function (req, res) {res.send('Hello World');
})var server = app.listen(8081, function () {var host = server.address().addressvar port = server.address().portconsole.log("應用實例,訪問地址為 http://%s:%s", host, port)})
請求和響應
Express 應用使用回調函數的參數: request 和 response 對象來處理請求和響應的數據。
app.get('/', function (req, res) {// --
})
app.post('/',(req,res)=>{})
request 和 response 對象的具體介紹:
Request 對象 - request 對象表示 HTTP 請求,包含了請求查詢字符串,參數,內容,HTTP 頭部等屬性。常見屬性有:
- req.app:當callback為外部文件時,用req.app訪問express的實例
- req.baseUrl:獲取路由當前安裝的URL路徑
- req.body / req.cookies:獲得「請求主體」/ Cookies
- req.fresh / req.stale:判斷請求是否還「新鮮」
- req.hostname / req.ip:獲取主機名和IP地址
- req.originalUrl:獲取原始請求URL
- req.params:獲取路由的parameters
- req.path:獲取請求路徑
- req.protocol:獲取協議類型
- req.query:獲取URL的查詢參數串
- req.route:獲取當前匹配的路由
- req.subdomains:獲取子域名
- req.accepts():檢查可接受的請求的文檔類型
- req.acceptsCharsets / req.acceptsEncodings / req.acceptsLanguages:返回指定字符集的第一個可接受字符編碼
- req.get():獲取指定的HTTP請求頭
- req.is():判斷請求頭Content-Type的MIME類型
Response 對象 - response 對象表示 HTTP 響應,即在接收到請求時向客戶端發送的 HTTP 響應數據。常見屬性有:
- res.app:同req.app一樣
- res.append():追加指定HTTP頭
- res.set()在res.append()后將重置之前設置的頭
- res.cookie(name,value [,option]):設置Cookie
- opition: domain / expires / httpOnly / maxAge / path / secure / signed
- res.clearCookie():清除Cookie
- res.download():傳送指定路徑的文件
- res.get():返回指定的HTTP頭
- res.json():傳送JSON響應
- res.jsonp():傳送JSONP響應
- res.location():只設置響應的Location HTTP頭,不設置狀態碼或者close response
- res.redirect():設置響應的Location HTTP頭,并且設置狀態碼302
- res.render(view,[locals],callback):渲染一個view,同時向callback傳遞渲染后的字符串,如果在渲染過程中有錯誤發生next(err)將會被自動調用。callback將會被傳入一個可能發生的錯誤以及渲染后的頁面,這樣就不會自動輸出了。
- res.send():傳送HTTP響應
- res.sendFile(path [,options] [,fn]):傳送指定路徑的文件 -會自動根據文件extension設定Content-Type
- res.set():設置HTTP頭,傳入object可以一次設置多個頭
- res.status():設置HTTP狀態碼
- res.type():設置Content-Type的MIME類型
路由
我們已經了解了 HTTP 請求的基本應用,而路由決定了由誰(指定腳本)去響應客戶端請求。
在HTTP請求中,我們可以通過路由提取出請求的URL以及GET/POST參數。
接下來我們擴展 Hello World,添加一些功能來處理更多類型的 HTTP 請求。
創建 express_demo2.js 文件,代碼如下所示:
var express = require('express');
var app = express();// 主頁輸出 "Hello World"
app.get('/', function (req, res) {console.log("主頁 GET 請求");res.send('Hello GET');
})// POST 請求
app.post('/', function (req, res) {console.log("主頁 POST 請求");res.send('Hello POST');
})// /del_user 頁面響應
app.get('/del_user', function (req, res) {console.log("/del_user 響應 DELETE 請求");res.send('刪除頁面');
})// /list_user 頁面 GET 請求
app.get('/list_user', function (req, res) {console.log("/list_user GET 請求");res.send('用戶列表頁面');
})// 對頁面 abcd, abxcd, ab123cd, 等響應 GET 請求
app.get('/ab*cd', function(req, res) { console.log("/ab*cd GET 請求");res.send('正則匹配');
})var server = app.listen(8081, function () {var host = server.address().addressvar port = server.address().portconsole.log("應用實例,訪問地址為 http://%s:%s", host, port)})
app.use
在Express中, `app.use` 函數用于將中間件函數綁定到應用程序的特定路徑。中間件函數可以訪問請求對象(req)、響應對象(res)和應用程序中的下一個中間件函數(next)。通過使用 `app.use` ,可以在請求到達特定路徑之前或之后執行一些操作,例如記錄日志、驗證用戶身份、處理請求等。
const express = require('express');
const app = express();// 自定義的日志記錄中間件函數
const logMiddleware = (req, res, next) => {console.log(`[${new Date().toLocaleString()}] - ${req.method} ${req.url}`);next();
};// 將日志記錄中間件綁定到應用程序的根路徑
app.use(logMiddleware);// 路由處理程序
app.get('/', (req, res) => {res.send('Hello World!');
});// 啟動服務器
app.listen(3000, () => {console.log('Server is running on port 3000');
});
托管靜態資源
app.use(express.static('./public'));
url里面不需要帶有public
http://localhost:8081/public.jpg
有兩個資源,按照引入順序
app.use('/public',express.static('./public'));
中間件
全局生效中間件
var express = require('express');
var app = express();
const ww=function(req,res,next){console.log(18948);next()
}
app.use(ww)
app.get('/',(req,res)=>{console.log('over');
})
var server = app.listen(8081, function () {var host = server.address().addressvar port = server.address().portconsole.log("應用實例,訪問地址為 http://%s:%s", host, port)})
局部生效中間件
var express = require('express');
var app = express();
const ww=function(req,res,next){req.a=1598next()
}
app.get('/',ww,(req,res)=>{res.send('over',req.a);
})
app.get('/55',(req,res)=>{res.send('over1',req.a);
})
var server = app.listen(8081, function () {var host = server.address().addressvar port = server.address().portconsole.log("應用實例,訪問地址為 http://%s:%s", host, port)})
錯誤全局中間件
var express = require('express');
var app = express();
app.get('/',(req,res)=>{throw new Error('服務器錯誤')res.send('home')
})
app.use(function(err,req,res,next) {res.send('Error'+err.message)
})
var server = app.listen(8081, function () {var host = server.address().addressvar port = server.address().portconsole.log("應用實例,訪問地址為 http://%s:%s", host, port)})
目的
防止整個項目崩潰
位置
必須放在所以的路由之后
內置中間件
注意事項
解析表單
html:
<html>
<body>
<form action="http://127.0.0.1:8081/process_post" method="POST">
First Name: <input type="text" name="first_name"> <br>Last Name: <input type="text" name="last_name">
<input type="submit" value="Submit">
</form>
</body>
</html>
node:
var express = require('express');
var app = express();
var bodyParser = require('body-parser');app.use(express.json())app.get('/index.html', function (req, res) {res.send(req.body)
})var server = app.listen(8081, function () {var host = server.address().addressvar port = server.address().portconsole.log("應用實例,訪問地址為 http://%s:%s", host, port)})
文件上傳
以下我們創建一個用于上傳文件的表單,使用 POST 方法,表單 enctype 屬性設置為 multipart/form-data。
html:
<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>
node:
var express = require('express');
var app = express();
var fs = require("fs");var bodyParser = require('body-parser');
var multer = require('multer');app.use('/public', express.static('public'));
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(8081, function () {var host = server.address().addressvar port = server.address().portconsole.log("應用實例,訪問地址為 http://%s:%s", host, port)})
項目
路由模塊化
router.js
const express=require('express');
// 創建路由對象
const router =express.Router()router.get('/',(req,res)=>{res.send('hello world')
})
module.exports=router;
server.js
var express = require('express');
const router = require('./router.js');
var app = express();app.use('/public',express.static('public'));
app.use(router)
var server = app.listen(8081, function () {var host = server.address().addressvar port = server.address().portconsole.log("應用實例,訪問地址為 http://%s:%s", host, port)})
url添加統一地址
app.use('/user',router)
連接MongoDB
要使用MongoDB,您需要安裝MongoDB數據庫,并且可以使用MongoDB的官方驅動程序或者第三方庫(如Mongoose)來與數據庫進行交互。以下是使用MongoDB的基本步驟:
- 安裝MongoDB數據庫:您可以從MongoDB的官方網站(https://www.mongodb.com/)下載適合您操作系統的安裝程序,并按照安裝指南進行安裝。
- 啟動MongoDB服務:安裝完成后,啟動MongoDB服務。在命令行中輸入 ?
mongod
(或 ?sudo mongod
)來啟動MongoDB服務。 - 連接到MongoDB數據庫:在另一個命令行窗口中輸入 ?
mongo
?命令來連接到MongoDB數據庫。
修改這3個能夠遠程訪問
檢驗:ip:27017
- 使用MongoDB Shell:通過MongoDB Shell,您可以執行各種數據庫操作,如創建數據庫、創建集合、插入文檔、查詢文檔等。以下是一些常用的MongoDB Shell命令:
-
- 創建數據庫:
use database_name
- 創建集合:
db.createCollection('collection_name')
- 插入文檔:
db.collection_name.insertOne({ key: value })
- 查詢文檔:
db.collection_name.find()
- 創建數據庫:
- 使用Node.js與MongoDB交互:如果您想在Node.js應用程序中使用MongoDB,可以使用MongoDB的官方Node.js驅動程序或者像Mongoose這樣的庫。以下是使用Mongoose庫的簡單示例:
const mongoose = require('mongoose');mongoose.connect('mongodb://localhost:27017/mydatabase', { useNewUrlParser: true, useUnifiedTopology: true });const db = mongoose.connection;
db.on('error', console.error.bind(console, 'connection error:'));
db.once('open', function() {console.log("Connected to MongoDB");
});// 定義模式和模型
const Schema = mongoose.Schema;
const userSchema = new Schema({name: String,age: Number
});
const User = mongoose.model('User', userSchema);// 創建文檔
const newUser = new User({ name: 'Alice', age: 30 });
newUser.save(function (err) {if (err) return console.error(err);console.log("User saved successfully!");
});
定義模式和模型(類似于ts的interface定義)
在使用Mongoose這樣的庫時,定義模式和模型是非常重要的步驟,用于幫助您在Node.js應用程序中與MongoDB數據庫進行交互。讓我來解釋一下這兩個概念的含義:
- 定義模式(Schema):模式是用來定義MongoDB文檔結構的一種方式,類似于表結構的定義。在Mongoose中,您可以通過定義模式來規定文檔中包含的字段、字段類型、默認值等信息。模式定義了文檔的結構,類似于一個數據模板,確保文檔符合特定的結構和規范。
例如,您可以定義一個用戶模式(User Schema),包含姓名(name)和年齡(age)兩個字段:
const userSchema = new Schema({
name: String,
age: Number
});
- 定義模型(Model):模型是基于模式創建的構造函數,用于對數據庫進行操作。在Mongoose中,您可以通過定義模型來創建具體的文檔實例,以便對數據庫進行增刪改查操作。模型是模式的實例化,它允許您在應用程序中使用模式定義的字段和規范。
通過使用上面定義的用戶模式,您可以創建一個用戶模型(User Model):
const User = mongoose.model('User', userSchema);
現在,您可以使用User模型來創建新的用戶文檔、查詢用戶數據、更新用戶信息等操作。
通過定義模式和模型,您可以規范化數據結構、提供數據驗證、簡化數據庫操作等。這些概念幫助您在Node.js應用程序中更好地與MongoDB數據庫進行交互,并更有效地管理數據。
在路由中使用
要在Express應用程序的路由中使用Mongoose模型(即在路由處理程序中與MongoDB數據庫進行交互),可以按照以下步驟進行操作:
- 引入Mongoose模型:首先,在您的Express應用程序中,確保已經引入了Mongoose模型。通常,您會在單獨的文件中定義模型,并在需要的地方引入該模型。
const User = require('./models/user'); // 假設User模型定義在models/user.js文件中
- 在路由處理程序中使用Mongoose模型:在您的路由處理程序中,您可以通過Mongoose模型執行數據庫操作,如查詢、插入、更新、刪除等操作。以下是一個簡單的示例
const express = require('express');
const router = express.Router();
const User = require('../models/user');// GET請求,獲取所有用戶
router.get('/users', async (req, res) => {try {const users = await User.find();res.json(users);} catch (err) {res.status(500).json({ message: err.message });}
});// POST請求,創建新用戶
router.post('/users', async (req, res) => {const user = new User({name: req.body.name,age: req.body.age});try {// 嘗試保存新用戶到數據庫const newUser = await user.save();// 如果保存成功,返回狀態碼201和新用戶信息res.status(201).json(newUser);} catch (err) {// 如果保存失敗,返回狀態碼400和錯誤信息res.status(400).json({ message: err.message });}
});module.exports = router;
在上面的示例中,我們定義了兩個路由處理程序,一個用于獲取所有用戶,另一個用于創建新用戶。在處理程序中,我們通過引入的User模型來執行數據庫操作,如查詢所有用戶(User.find())和創建新用戶(user.save())。
在Mongoose中,模型(Model)對象(如 User
)可以調用一些內置的方法來執行數據庫操作。以下是一些常用的Mongoose模型方法:
- save():將文檔保存到數據庫中。
- find():查找匹配條件的文檔。
- findOne():查找匹配條件的第一個文檔。
- findById():根據文檔ID查找文檔。
- findOneAndUpdate():查找并更新匹配條件的第一個文檔。
- updateOne():更新匹配條件的第一個文檔。
- updateMany():更新匹配條件的所有文檔。
- deleteOne():刪除匹配條件的第一個文檔。
- deleteMany():刪除匹配條件的所有文檔。
- countDocuments():統計匹配條件的文檔數量。
- aggregate():執行聚合操作,如分組、篩選等。
- distinct():查找匹配條件的文檔并返回指定字段的唯一值。
除了上述方法外,您還可以根據具體需求使用Mongoose提供的其他方法來執行更復雜的數據庫操作。這些方法使得在Node.js應用程序中與MongoDB數據庫交互變得更加方便和靈活。希望這些信息對您有幫助。如果您有任何進一步的問題,請隨時告訴我。
通過這種方式,在Express應用程序的路由中使用Mongoose模型,您可以方便地與MongoDB數據庫進行交互,執行各種數據庫操作。
https配置
var express = require('express');
var path = require('path');
var http = require('http');
var https = require('https');
var fs = require('fs');var app = express();app.get('/', function(req, res, next) {res.send('hello world');
});var httpServer = http.createServer(app);
httpServer.listen(9080);const options = {key: fs.readFileSync('./server.key'),cert: fs.readFileSync('./server.crt')
};
var httpsServer = https.createServer(options, app);
httpsServer.listen(9443);