Dieser Artikel stellt hauptsächlich die Entwicklung von NodeJS vor – Express-Routing und Middleware. Der Herausgeber findet ihn ziemlich gut. Jetzt werde ich ihn mit Ihnen teilen und als Referenz geben. Folgen wir dem Editor, um einen Blick darauf zu werfen.
Routing
Normalerweise ist das Format einer HTTP-URL wie folgt:
host[:port][path]
http stellt die dar Protokoll.
Gastgeber bedeutet Gastgeber.
Port ist der Port, ein optionales Feld. Wenn nicht angegeben, ist der Standardwert 80.
Pfad gibt den URI (Uniform Resource Identifier, Uniform Resource Locator) der angeforderten Ressource an. Wenn der Pfad nicht in der URL angegeben ist, wird er im Allgemeinen standardmäßig auf „/“ gesetzt (normalerweise ergänzt durch einen Browser oder andere). HTTP-Client) überlegen).
Das sogenannte Routing ist die Art und Weise, wie mit dem Pfadteil in der HTTP-Anfrage umgegangen wird. Beispielsweise bestimmt das Routing für die URL „xxx.com/users/profile“, wie mit dem Pfad /users/profile umgegangen wird.
Sehen wir uns die Express-Version des HelloWorld-Codes an, die wir in „Erste Schritte mit der Node.js-Entwicklung – Express-Installation und -Nutzung“ bereitgestellt haben:
var express = require('express'); var app = express(); app.get('/', function (req, res) { res.send('Hello World!'); }); app.listen(8000, function () { console.log('Hello World is listening at port 8000'); });
Der app.get()-Aufruf im obigen Code Tatsächlich wird unserer Website eine Route hinzugefügt und der Pfad „/“ wird zur Verarbeitung durch die -Funktion angegeben, die durch den zweiten Parameter von get dargestellt wird. Das
express-Objekt kann mithilfe der folgenden Methoden Routen für gängige HTTP-Methoden angeben:
app.METHOD(path, callback [, callback ...])
Routenpfad
Beispiel für Routing-Pfad mit Zeichenfolge:
// 匹配根路径的请求 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('ab(cd)?e'); });
Zeichen ?, +, * und () sind reguläre Ausdrücke Teilmengen, - und . werden wörtlich in stringbasierten Pfaden interpretiert.
Beispiel für Routing-Pfad mit regulären Ausdrücken:
// 匹配任何路径中含有 a 的路径: app.get(/a/, function(req, res) { res.send('/a/'); }); // 匹配 butterfly、dragonfly,不匹配 butterflyman、dragonfly man等 app.get(/.*fly$/, function(req, res) { res.send('/.*fly$/'); });
Routen-Handle
Für die Anfrageverarbeitung können mehrere angegeben werden >Callback-Funktion, die sich wie Middleware verhält. Der einzige Unterschied besteht darin, dass diese Callback-Funktionen möglicherweise die next('route')-Methode aufrufen und andere Route-Callback-Funktionen überspringen. Mit diesem Mechanismus können Vorbedingungen für das Routing definiert werden. Wenn es keinen Sinn macht, die Ausführung auf dem vorhandenen Pfad fortzusetzen, kann die Kontrolle dem verbleibenden Pfad übertragen werden.
Routenhandles gibt es in vielen Formen und können eine Funktion, ein Array von Funktionen oder eine Mischung aus beiden sein, wie unten gezeigt
Verwenden Sie eine Rückruffunktion, um das Routing zu verwalten:
app.get('/example/a', function (req, res) { res.send('Hello from A!'); });
Verwenden Sie mehrere Callback-Funktionen, um Routen zu verarbeiten (denken Sie daran, das nächste Objekt anzugeben):
app.get('/example/b', function (req, res, next) { console.log('response will be sent by the next function ...'); next(); }, function (req, res) { res.send('Hello from B!'); });
Verwenden Sie Callback-Funktions-Arrays, um Routen zu verarbeiten:
var cb0 = function (req, res, next) { console.log('CB0'); next(); } var cb1 = function (req, res, next) { console.log('CB1'); next(); } var cb2 = function (req, res) { res.send('Hello from C!'); } app.get('/example/c', [cb0, cb1, cb2]);
GemischtVerwenden Sie Funktionen und Funktionsarray-Verarbeitungsrouting:
var cb0 = function (req, res, next) { console.log('CB0'); next(); } var cb1 = function (req, res, next) { console.log('CB1'); next(); } app.get('/example/d', [cb0, cb1], function (req, res, next) { console.log('response will be sent by the next function ...'); next(); }, function (req, res) { res.send('Hello from D!');
METHOD kann der Kleinbuchstabe von HTTP-Methoden wie GET und POST sein, z. B. app.get, app.post. Der Pfadteil kann entweder ein String-Literal oder ein regulärer Ausdruck sein. Das einfachste Beispiel besteht darin, einen Parameter „/“ im app.get()-Aufruf im vorherigen Code in „*“ zu ändern, und die Bedeutung wird eine andere sein. Vor der Änderung würden nur Zugriffe in der Form „localhost:8000“ oder „localhost:8000/“ „Hello World!“ zurückgeben, aber nach der Änderung würde „localhost:8000/xxx/yyyy.zz“ Access zurückgeben Geben Sie auch „Hello World!“ zurück.
Wenn Sie Express zum Erstellen eines Webservers verwenden, besteht ein sehr wichtiger Teil der Aufgabe darin, zu entscheiden, wie auf Anforderungen für einen bestimmten Pfad reagiert werden soll, nämlich die Routing-Verarbeitung.
Die direkteste Methode zur Routenkonfiguration besteht darin, app.get() und app.post() aufzurufen, um sie einzeln zu konfigurieren. Bei Websites, die eine große Anzahl von Routen verarbeiten müssen, kann dies jedoch Leben verursachen . Daher müssen wir in der tatsächlichen Entwicklung Routing-Parameter (Abfragezeichenfolge, regulärer Ausdruck, benutzerdefinierte Parameter, Post-Parameter) kombinieren, um die Arbeitsbelastung zu reduzieren und die Wartbarkeit zu verbessern.
Middleware
Es gibt ein Middleware-Konzept in Express. Die sogenannte Middleware bezieht sich auf einige Funktionen, die in dieser Phase nach dem Empfang der Anfrage und vor dem Senden der Antwort ausgeführt werden.
Um Middleware in die Verarbeitungskette einer Route einzufügen, können Sie die use-Methode des Express-Objekts verwenden. Der Prototyp dieser Methode lautet wie folgt:
app.use([path,] function [, function...])
Wenn app.use keinen Pfadparameter bereitstellt, ist der Pfad standardmäßig „/“. Wenn Sie Middleware für einen Pfad installieren, wird die Middleware immer dann angewendet, wenn auf einen Pfad zugegriffen wird, der auf diesem Pfad basiert. Wenn Sie beispielsweise eine Middleware für „/abcd“ festlegen, wird die Middleware auch angewendet, wenn auf „/abcd/xxx“ zugegriffen wird.
Der Prototyp der Middleware-Funktion lautet wie folgt:
function (req, res, next)
Der erste Parameter ist die Anforderung des Anforderungsobjekts. Der zweite Parameter ist das Response-Objekt res. Die dritte Funktion ist die nächste Funktion, die die Middleware-Aufrufkette steuert. Wenn Sie möchten, dass die nachfolgende Middleware weiterhin Anforderungen verarbeitet, müssen Sie die nächste Methode aufrufen.
Ein typischer Aufruf zum Anwenden einer Middleware-Funktion auf einen bestimmten Pfad lautet wie folgt:
app.use('/abcd', function (req, res, next) { console.log(req.baseUrl); next(); })
app.static middleware
Express stellt A Statische Middleware, die zur Verarbeitung von GET-Anfragen für statische -Dateien auf der Website verwendet werden kann und auf die über express.static zugegriffen werden kann.
Express.static wird wie folgt verwendet:
express.static(root, [options])
第一个参数root,是要处理的静态资源的根目录,可以是绝对路径,也可以是相对路径。第二个可选参数用来指定一些选项,比如maxAge、lastModified等,
一个典型的express.static应用如下:
var options = { dotfiles: 'ignore', etag: false, extensions: ['htm', 'html'], index: false, maxAge: '1d', redirect: false, setHeaders: function (res, path, stat) { res.set('x-timestamp', Date.now()); } } app.use(express.static('public', options));
上面这段代码将当前路径下的public目录作为静态文件,并且为Cache-Control头部的max-age选项为1天。还有其它一些属性,请对照express.static的文档来理解。
使用express创建的HelloExpress项目的app.js文件里有这样一行代码:
app.use(express.static(path.join(dirname, 'public')));
这行代码将HelloExpress目录下的public目录作为静态文件交给static中间件来处理,对应的HTTP URI为“/”。path是一个Node.js模块,dirname是Node.js的全局变量,指向当前运行的js脚本所在的目录。path.join()则用来拼接目录。
有了上面的代码,你就可以在浏览器里访问“localhost:3000/stylesheets/style.css”。我们做一点改动,把上面的代码修改成下面这样:
app.use('/static', express.static(path.join(dirname, 'public')));
上面的代码呢,针对/static路径使用static中间件处理public目录。这时你再用浏览器访问“localhost:3000/stylesheets/”就会看到一个404页面,将地址换成“localhost:3000/static/stylesheets/style.css”就可以了。
Router
Express还提供了一个叫做Router的对象,行为很像中间件,你可以把Router直接传递给app.use,像使用中间件那样使用Router。另外你还可以使用router来处理针对GET、POST等的路由,也可以用它来添加中间件,总之你可以将Router看作一个微缩版的app。
下面的代码创建一个Router实例:
var router = express.Router([options]);
然后你就可以像使用app一样使用router:
// invoked for any requests passed to this router router.use(function(req, res, next) { // .. some logic here .. like any other middleware next(); }); // will handle any request that ends in /events // depends on where the router is "use()'d" router.get('/events', function(req, res, next) { // .. });
定义了router后,也可以将其作为中间件传递给app.use:
app.use('/events', router);
上面这种用法,会针对URL中的“/events”路径应用router,你在router对象上配置的各种路由策略和中间件,都会被在合适的时候应用。
路由模块
express工具创建的应用,有一个routes目录,下面保存了应用到网站的Router模块,index.js和user.js。这两个模块基本一样,我们研究一下index.js。
下面是index.js的内容:
var express = require('express'); var router = express.Router(); /* GET home page. */ router.get('/', function(req, res, next) { res.render('index', { title: 'Express' }); }); module.exports = router;
index.js创建了一个Router实例,然后调用router.get为“/”路径应用了路由函数。最后呢使用module.exports将Router对象导出。
下面是app.js里引用到index.js的代码:
var routes = require('./routes/index'); ... app.use('/', routes);
第一处,require(‘./routes/index')将其作为模块使用,这行代码导入了index.js,并且将index.js导出的router对象保存在变量routes里以供后续使用。注意,上面代码里的routes就是index.js里的router。
第二处代码,把routes作为一个中间件,挂载到了“/”路径上。
模块
前面分析index.js时看到了module.exports的用法。module.exports用来导出一个Node.js模块内的对象,调用者使用require加载模块时,就会获得导出的对象的实例。
我们的index.js导出了Router对象。app.js使用require(‘./routes/index')获取了一个Router实例。
module.exports还有一个辅助用法,即直接使用exports来导出。
exports.signup = function(req, res){ //some code } exports.login = function(req, res){ //some code }
上面的代码(假定在users.js文件里)直接使用exports来导出。当使用exports来导出时,你设置给exports的属性和方法,实际上都是module.exports的。这个模块最终导出的是module.exports对象,你使用类似“exports.signup”这种形式设置的方法或属性,调用方在require后都可以直接使用。
使用users模块的代码可能是这样的:
var express = require('express'); var app = express(); ... var users = require('./routes/users'); app.post('/signup', users.signup); app.post('/login', users.login); ...
1. 什么是router路径,什么是middleware?
我们输入www.baidu.com 来访问百度的主页,浏览器会自动转换为 www.baidu.com:80/(省略一些参数)。 http://代表我们同服务器连接使用的是http协议,www.baidu.com 代表的是服务器的主机地址,会被我们的pc通过DNS解析为IP地址。80是默认的应用层端口。/ 即为我们访问的服务器(www.baidu.com)的路径,服务器要对我们访问的这个路径做出响应,采取一定的动作。我们可以把这一过程看做一个路由。
访问的路径‘/'即为router的路径,服务器采取的动作即为middleware,即为一个个特殊的函数。
2. router路径
www.baidu.com/test: 路径为 /test
www.baidu.com/test?name=1&number=2: 路径同样为/test, ?后面会被服务器理解传给路径的参数。
3. Middleware
An Express application is essentially a stack of middleware which are executed serially.(express应用其实就是由一系列顺序执行的Middleware组成。)
A middleware is a function with access to the request object (req), the response object (res), and the next middleware in line in the request-response cycle of an Express application. It is commonly denoted by a variable named next. Each middleware has the capacity to execute any code, make changes to the request and the reponse object, end the request-response cycle, and call the next middleware in the stack. Since middleware are execute serially, their order of inclusion is important.(中间件其实就是一个访问express应用串入的req,res,nex参数的函数,这个函数可以访问任何通过req,res传入的资源。)
If the current middleware is not ending the request-response cycle, it is important to call next() to pass on the control to the next middleware, else the request will be left hanging.(如果当前中间件没有完成对网页的res响应 ,还可以通过next把router 留给下一个middleware继续执行)
With an optional mount path, middleware can be loaded at the application level or at the router level. Also, a series of middleware functions can be loaded together, creating a sub-stack of middleware system at a mount point.
路由的产生是通过HTTP的各种方法(GET, POST)产生的,Middleware可以跟router路径跟特定的HTTP方法绑定,也可以跟所有的方法绑定。
3.1 通过express应用的use(all),把Middleware同router路径上的所有HTTP方法绑定:
app.use(function (req, res, next) { console.log('Time: %d', Date.now()); next(); })
3.2 通过express应用的http.verb,把Middleware同router路径上的特定的HTTP方法绑定:
app.get('/', function(req, res){ res.send('hello world'); }); app.post('/', function(req, res){ res.send('hello world'); });
4. Express的Router对象
当express实例的路由越来越多的时候,最好把路由分类独立出去,express的实例(app) 能更好的处理其他逻辑流程。Express的Router对象是一个简化的 app实例,只具有路由相关的功能,包括use, http verbs等等。最后这个Router再通过app的use挂载到app的相关路径下。
var express = require('express'); var app = express(); var router = express.Router(); // simple logger for this router's requests // all requests to this router will first hit this middleware router.use(function(req, res, next) { console.log('%s %s %s', req.method, req.url, req.path); next(); }); // this will only be invoked if the path ends in /bar router.use('/bar', function(req, res, next) { // ... maybe some additional /bar logging ... next(); }); // always invoked router.use(function(req, res, next) { res.send('Hello World'); }); app.use('/foo', router); app.listen(3000);
router的路由必须通过app.use和app.verbs 挂载到app上才能被响应。所以上述代码,只有在app捕捉到 /foo路径上的路由时,才能router中定义的路由,虽然router中有针对 '/' 的路由,但是被app中的路由给覆盖了。
附:app.verbs和app.use的路由路径区别:
先看一段测试代码:
var express = require('express'); var app = express(); var router = express.Router(); app.get('/', function(req, res){ console.log('test1'); }); app.use('/', function(req, res){ console.log('test2'); }); router.get('/', function(req, res){ console.log('test3'); }); app.listen(4000);
输入url: localhost:4000
输出结果:test1
输入url: localhost:4000/hello
输出结果:test2
结论:app.get挂载‘/'的路由只响应跟'/'精确匹配的GET请求。 而app.use挂载的'/'的路由响应所有以'/' 为起始路由的路由,且不限制HTTP访问的方法。以下说明:Mounting a middleware at a path will cause the middleware function to be executed whenever the base of the requested path matches the path.
Das obige ist der detaillierte Inhalt vonNode.js entwicklungsdetaillierte Codebeispiele für Express-Routing und Middleware. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!