名称

Mojolicious::Guides::路由-路由请求

概述

本文档包含对Mojolicious公司路由器及其基本概念。

概念

Essentials每Mojolicious公司开发人员应该知道。

调度员

每个web框架的基础都是一个小黑匣子,它将传入的请求与生成相应响应的代码连接起来。

GET/user/show/1->$c->render(text=>'Daniel');

这个黑盒子通常被称为调度员。有许多实现使用不同的策略来建立这些连接,但大多数都是基于将请求URL的路径部分映射到某种类型的响应生成器。

/user/show/2->$c->render(text=>'Isabell');/user/show/3->$c->render(text=>“Sara”);/user/show/4->$c->render(text=>“Stefan”);/user/show/5->$c->render(text=>'Fynn');

虽然很可能使所有这些连接都是静态的,但效率也相当低。这就是为什么正则表达式通常用于使分派过程更加动态的原因。

qr/用户/显示/(\d+)!->$c->render(文本=>$users{$1});

现代调度器拥有HTTP所能提供的几乎所有功能,并且可以使用比请求路径更多的变量,例如请求方法和诸如主机,用户代理接受.

GET/user/show/23 HTTP/1.1主持人:mojolique.org用户代理:Mojolicious(Perl)接受:text/html、application/xhtml+xml、application/xml;q=0.9,*/*;q=0.8

路线

虽然正则表达式非常强大,但它们看起来也不太好看,对于普通的路径匹配来说通常过于繁琐。

qr/用户/管理员/(\d+)!->$c->render(文本=>$users{$1});

这就是路线发挥作用的地方,它们从地面开始设计,用占位符表示路径。

/user/admin/:id->$c->render(文本=>$users{$id});

静态路径和上面的路由之间的唯一区别是:id占位符。一个或多个占位符可以位于路线中的任何位置。

/用户/:角色/:id

基本概念Mojolicious公司路由器将提取的占位符值转换为散列。

/user/admin/23->/user/:role/:id->{role=>“admin”,id=>23}

这个散列基本上是每个Mojolicious公司应用程序中,稍后您将了解更多有关这方面的信息。在内部,路由被编译为正则表达式,因此您可以通过一点经验来获得两者的最佳效果。

/用户/管理员/:id->qr/(?-xism:^\/user\/admin\/([^\/.]+))/

路径中的尾部斜杠始终是可选的。

/user/admin/23/->/user/:role/:id->{role=>'admin',id=>23}

可逆性

与正则表达式相比,路由还有一个巨大的优势,那就是它们很容易可逆,提取的占位符可以随时转换回路径。

/sebastian->/:name->{name=>“sebastian”}{name=>“sebastian”}->/:name->/sebastian

每个占位符都有一个名称,即使它只是一个空字符串。

标准占位符

标准占位符是最简单的占位符形式,它们使用冒号前缀并匹配除/.,类似于正则表达式([^/.]+).

/hello->/:name/hello->undef/塞巴斯蒂安/23/hello->/:name/hello->undef/塞巴斯蒂安.23/你好->/:名字/你好->unde/sebastian/hello->/:name/hello->{name=>“sebastian”}/sebastian23/hello->/:name/hello->{name=>“sebastian 23”}/塞巴斯蒂安23/hello->/:name/hello->{name=>'sebastian 23'}

所有占位符都可以由<>将它们与周围的文本分开。

/hello->/<:name>hello->unde/塞巴斯蒂安/23hello->/<:name>hello->undef/sebastian.23hello->/<:name>hello->undef/sebastianhello->/<:name>hello->{name=>“sebastian”}/sebastian23hello->/<:name>hello->{name=>“sebastian 23”}/塞巴斯蒂安23hello->/<:name>hello->{name=>'sebastian 23'}

冒号前缀对于由以下内容包围的标准占位符是可选的<>.

/我动人的->/<one>♥<两个>->{one=>“i”,两个=>“mojolicious”}

宽松的占位符

宽松占位符与标准占位符一样,但使用哈希前缀并匹配除以下字符之外的所有字符/,类似于正则表达式([^/]+).

/hello->/#name/hello->unde/塞巴斯蒂安/23/hello->/#name/hello->undef/sebastian.23/hello->/#name/hello->{name=>'sebastiang.23'}/sebastian/hello->/#name/hello->{name=>“sebastian”}/sebastian23/hello->/#name/hello->{name=>“sebastian 23”}/塞巴斯蒂安23/hello->/#name/hello->{name=>'sebastian 23'}

它们对于手动匹配文件名和扩展名特别有用,而不是使用格式检测.

/music/song.mp3->/music/#filename->{filename=>'song.mp3'}

通配符占位符

通配符占位符与上述两种类型的占位符类似,但使用星号前缀并绝对匹配所有内容,包括/.,类似于正则表达式(.+).

/hello->/*name/hello->unde/sebastian/23/hello->/*name/hello->{name=>'sebastian/23'}/sebastian.23/hello->/*name/hello->{name=>'sebastiang.23'}/sebastian/hello->/*name/hello->{name=>“sebastian”}/sebastian23/hello->/*name/hello->{name=>“sebastian 23”}/sebastian 23/你好->/*名称/你好->{名称=>“sebastian 23'”}

它们对于手动匹配整个文件路径非常有用。

/music/rock/song.mp3->/music/*filepath->{filepath=>'rock/song.mp3'}

基础

最常用的功能Mojolicious公司开发人员应该知道。

最小路线

属性Mojolicious中的“路线”包含可用于生成路由结构的路由器。

#应用程序包MyApp;使用Mojo::Base“Mojolicious”,-签名;子启动($self){#路由器我的$r=$self->路线;#路线$r->get('/welcome')->to(controller=>'foo',action=>'welcome'');}1;

上面的最小路由将加载并实例化类MyApp::控制器::Foo并将其称为欢迎方法。路由通常在启动方法,但路由器可以从任何地方访问(甚至在运行时)。

#控制器包MyApp::控制器::Foo;使用Mojo::Base“Mojolicious::Controller”,-签名;#行动子欢迎($self){#渲染响应$self->render(text=>“你好”);}1;

所有路由都以定义它们的相同顺序进行匹配,一旦找到合适的路由,匹配就会停止。因此,您可以通过首先声明最常访问的路由来提高路由性能。路由缓存还将自动用于更优雅地处理突发流量峰值。

路由目的地

使用以下方法开始新路线后Mojolicious::Routes::Route中的“get”,您还可以使用链式方法以散列形式为其指定目的地Mojolicious::Routes::Route中的“to”.

#/welcome->{controller=>'foo',action=>'welcome'}$r->get('/welcome')->to(controller=>'foo',action=>'welcome'');

现在,如果路由匹配传入的请求,它将使用此散列的内容来尝试查找适当的代码以生成响应。

HTTP方法

已经有最常见的HTTP请求方法的快捷方式,如Mojoliques::路线::路线中的“帖子”,和以获得更多控制Mojolicious::Routes::Route中的“any”接受具有任意请求方法的可选数组引用作为第一个参数。

#PUT/你好->未定义#GET/hello->{controller=>'foo',action=>'hello'}$r->get('/hello')->to(controller=>'foo',action=>'hello');#PUT/hello->{controller=>'foo',action=>'hello'}$r->put('/hello')->to(controller=>'foo',action=>'hello');#POST/hello->{controller=>'foo',action=>'hello'}$r->post('/hello')->to(controller=>'foo',action=>'hello');#GET|POST/bye->{controller=>'foo',action=>'bye'}$r->any(['GET','POST']=>'/bey')->to(controller=>'foo',action=>'bye');#*/whatech->{controller=>'foo',action=>'whatech'}$r->any(“/whatever”)->to(controller=>'foo',action=>'whatever’);

有一个小例外,头部请求被视为等于得到,但即使有响应,也不会随响应一起发送内容。

#GET/test->{controller=>'bar',action=>'test'}#头部/测试->{控制器=>“bar”,动作=>“test”}$r->get('/test')->to(controller=>'bar',action=>'test');

您也可以使用_方法查询参数以覆盖请求方法。当使用仅支持得到邮政.

#PUT/stuff->{controller=>“baz”,action=>“stuff”}#帖子/东西_方法=PUT->{controller=>“baz”,操作=>“stuff”}$r->put(“/stuff”)->to(controller=>baz,action=>stuff);

个人退休保险

IRI的处理是透明的,这意味着路径可以保证从字节到字符的非转义和解码。

#GET(获取)/(Unicode雪人)->{controller=>'foo',action=>'snowman'}$r->获取('/☃')->到(控制器=>“foo”,动作=>“雪人”);

斯塔什

匹配路由的生成哈希实际上是整个路由的中心Mojolicious公司请求周期。我们称之为stash,它会一直持续到生成响应为止。

#/bye->{controller=>“foo”,action=>“bye”,mymessage=>“bye”}$r->get('/bye')->to(controller=>'foo',action=>'bye',mymessage=>'bye');

有一些具有特殊意义的stash值,例如控制器行动,但通常可以用生成响应所需的任何数据填充它。一旦发送,整个存储内容可以随时更改。

再见($self){#从隐藏处获取消息my$msg=$self->stash('mmessage');#更改隐藏邮件$self->stash(mymessage=>“欢迎”);}

你可以使用Mojolicious中的“默认值”设置应用程序中随处可用的默认存储值。

$app->defaults(mymessage=>“你好”);

有关保留存储值的完整列表,请参阅Mojolicious::Controller中的“stash”.

嵌套的管线

还可以从路由中构建树结构以删除重复代码。但是,具有子级的路由本身无法匹配,只有这些嵌套路由的实际端点可以匹配。

#/foo->undef#/foo/bar->{controller=>'foo',action=>'bar'}my$foo=$r->any('/foo')->to(controller=>'foo');$foo->get('/bar')->to(action=>'bar');

存储只是从一个路由继承到另一个路由,新的值覆盖旧的值。

#/cats->{controller=>“cats”,action=>“index”}#/cats/nyan->{controller=>'cats',action=>'nyan'}#/cats/lol->{controller=>“cats”,action=>“default”}my$cats=$r->any('/cats')->to(controller=>'cats',action=>'default');$cats->get('/')->to(action=>'index');$cats->get('/nyan')->to(action=>'nyan');$cats->get('/lol');

使用几个常见的前缀,您还可以大大提高具有许多路由的应用程序的路由性能,因为只有在前缀首先匹配时才会尝试使用子代。

特殊存储值

当调度员看到控制器行动它将始终尝试将存储中的值转换为要分派到的类和方法控制器值转换自蛇形外壳驼峰命名法使用Mojo::Util中的“camelize”并附加到一个或多个名称空间,默认为基于应用程序类的控制器名称空间(MyApp::控制器)以及裸应用程序类(我的应用程序),并且按该顺序搜索这些名称空间。动作值根本没有更改,因此这两个值都区分大小写。

#应用程序包MyApp;使用Mojo::Base“Mojolicious”,-签名;子启动($self){#/bye->MyApp::控制器::Foo->bye$self->routes->get('/bye')->to(controller=>'foo',action=>'bye');}1;#控制器包MyApp::控制器::Foo;使用Mojo::Base“Mojolicious::Controller”,-签名;#行动再见($self){#渲染响应$self->render(text=>“再见”);}1;

控制器类非常适合组织大型项目中的代码。有更多的调度策略,但由于控制器是最常用的策略,它们也有一种特殊的快捷方式,即控制器#动作.

#/bye->{controller=>“foo”,action=>“bye”,mymessage=>“bye”}$r->get('/bye')->to('foo#bye',mymessage=>'bye');

骆驼化期间-字符替换为::,这允许多级控制器层次结构。

#/->MyApp::控制器::Foo::Bar->hi$r->get('/')->to('foo-bar#hi');

您也可以只指定控制器以CamelCase形式代替snake_case。

#/->MyApp::控制器::Foo::Bar->hi$r->get('/')->to('Foo::Bar#hi');

出于安全原因,调度员将始终检查控制器实际上是的子类Mojolicious::控制器莫霍然后发送给它。

命名空间

您可以使用命名空间stash值以更改整个路由及其所有子路由的名称空间。

#/bye->MyApp::MyController::Foo::Bar->bye$r->get('/bye')->to(namespace=>“MyApp::MyController”,controller=>“Foo::Bar”,action=>“bye”);

这个控制器始终从转换蛇形外壳驼峰命名法具有Mojo::Util中的“camelize”,然后附加到此命名空间.

#/bye->MyApp::MyController::Foo::Bar->bye$r->get('/bey')->to('foo-bar#bye',namespace=>'MyApp::MyController');#/hey->MyApp::MyController::Foo::Bar->hey$r->get('/hey')->to('Foo::Bar#hey',namespace=>'MyApp::MyController');

您还可以使用router属性更改应用程序中所有路由的默认名称空间Mojolicious::Routes中的“名称空间”,通常默认为基于应用程序类的命名空间(MyApp::控制器)以及裸应用程序类(我的应用程序).

$r->名称空间([“MyApp::MyController”]);

路由回叫

这个哥伦比亚广播公司stash值不会被嵌套路由继承,可以用来绕过控制器并执行回调。

$r->get('/bye')->to(cb=>sub($c)){$c->render(text=>“再见”);});

但就像在Mojolicious::精简您还可以直接传递回调,这通常看起来要好得多。

$r->get('/bye'=>sub($c){$c->render(text=>“再见”);});

命名的路由

命名路由将允许在整个框架中的许多方法和帮助程序中进行反向引用,其中大多数方法和帮助器在内部依赖于Mojolicious::Controller中的“url_for”为了这个。

#/foo/marcus->{controller=>'foo',action=>'bar',user=>'marcus'}$r->get('/foo/:user')->to('foo#bar')->name('baz');#为路由“baz”生成URL“/foo/marcus”(在前面的请求上下文中)我的$url=$c->url_for(“baz”);#为路由“baz”生成URL“/foo/jan”my$url=$c->url_fo('baz',user=>'jan');#生成URL“http://127.0.0.1:3000/foo/jan用于路线“baz”我的$url=$c->url_for('baz',user=>'jan')->to_abs;

您可以使用指定名称Mojolicious::Routes::Route中的“name”或者让路由器自动生成一个,这将等于没有非单词字符的路由本身,但是自定义名称具有更高的优先级。

#/foo/bar(“foobar”)$r->get('/foo/bar')->to('test#stuff');#生成URL“/foo/bar”我的$url=$c->url_for('foobar');

要引用当前路线,可以使用保留名称现在的或者根本没有名字。

#为当前路由生成URLmy$url=$c->url_fo(“当前”);我的$url=$c->url_for;

若要检查或获取当前路线的名称,可以使用辅助程序Mojolicious::Plugin::DefaultHelpers中的“current_route”.

#当前路线的名称我的$name=$c->current_route;#在多条路线共享的代码中检查路线名称如果$c->current_route(“登录”)为$c->stash(button=>“绿色”);

可选占位符

提取的占位符值将简单地重新定义旧的存储值(如果它们已经存在)。

#/bye->{controller=>'foo',action=>'bar',mymessage=>'bye'}#/hey->{controller=>'foo',action=>'bar',mymessage=>'hey'}$r->get('/:mymessage')->to('foo#bar',mymessage=>'hi');

还有一个有趣的效果,如果已经存在同名的stash值,占位符会自动变为可选的,这与正则表达式的工作原理类似([^/.]+)?.

#/->{controller=>'foo',action=>'bar',mymessage=>'hi'}$r->get('/:mymessage')->to('foo#bar',mymessage=>'hi');#/test/123->{controller=>'foo',action=>'bar',mymessage=>'hi'}#/test/bye/123->{controller=>'foo',action=>'bar',mymessage=>'bye'}$r->get('/test/:mymessage/123')->to('foo#bar',mymessage=>'hi');

如果两个可选占位符只由斜线分隔,那么斜线也可以成为可选的。

限制性占位符

使占位符更具限制性的一种非常简单的方法是替代方法,您只需列出可能的值,然后这些值的工作方式与正则表达式类似(本德|leela).

#/fry->undef#/bender->{controller=>'foo',action=>'bar',name=>'bender'}#/leela->{controller=>'foo',action=>'bar',name=>'leela'}$r->get('/:name'=>[name=>['bender','leela']])->to('foo#bar');

您还可以直接调整占位符后面的正则表达式,只需确保不要使用^$或捕获组(...),因为占位符在内部成为较大正则表达式的一部分,所以无法捕获组(?:...)但都很好。

#/23->{controller=>'foo',action=>'bar',number=>23}#/test->undef$r->get('/:number'=>[number=>qr/\d+/])->to('foo#bar');#/23->未定义#/test->{controller=>'foo',action=>'bar',name=>'test'}$r->get('/:name'=>[name=>qr/[a-zA-Z]+/])->to('foo#bar');

通过这种方式,您可以获得易于阅读的路由和正则表达式的原始功能。

占位符类型

如果您有多条使用限制性占位符的路由,也可以使用Mojolicious::Routes中的“add_type”.

#具有备选方案的类型$r->add_type(futureama_name=>[‘bender’,‘leela’]);#/fry->undef#/bender->{controller=>'foo',action=>'bar',name=>'bender'}#/leela->{controller=>'foo',action=>'bar',name=>'leela'}$r->get('/<name:futurama_name>')->to('foo#bar');

占位符类型的工作方式与限制性占位符类似,它们只是可与<占位符:类型>符号。

#调整正则表达式的类型$r->add_type(上部=>qr/[A-Z]+/);#/user/ROOT->{controller=>'users',action=>'show',name=>'ROOT'}#/user/root->undef#/user/23->取消定义$r->get('/user/<name:upper>')->to('users#show');

一些类型如号码非常常用,因此默认情况下可以使用。

#/article/12->{controller=>“article”,action=>“show”,id=>12}#/article/test->undef$r->get('/article/<id:num>')->to('articles#show');

有关可用占位符类型的完整列表,请参见Mojolicious::Routes中的“TYPES”.

反省

命令Mojolicious::Command::routes可以从命令行中使用,以列出所有可用路由以及名称和底层正则表达式。

$ ./myapp.pl路由-v/foo/:名称。。。。POST fooname ^/foo/([^/.]+)/?(?:\.([^/]+))?$/酒吧。。U.*巴^/巴+/呸。。。获取baz^/baz/?(?:\.([^/]+))?$/雅达….*雅达^/雅达/?(?:\.([^/]+))?$

低于

要与多个嵌套管线共享代码,可以使用Mojolicious::Routes::Route中的“under”,因为与正常的嵌套路由不同,使用它生成的路由具有自己的中间目的地,并且在匹配时会导致额外的调度周期。

#/foo->undef#/foo/bar->{controller=>“foo”,action=>“baz”}#{controller=>'foo',action=>'bar'}我的$foo=$r->under('/foo')->to('foo#baz');$foo->get('/bar')->to('#bar');

此目的地的实际操作代码需要返回一个真值,否则调度链将断开,这可能是一个非常强大的身份验证工具。

#/blackjack->{cb=>sub{…}}#{controller=>“隐藏”,action=>“21点”}我的$auth=$r->under('/'=>sub($c){#已验证身份如果$c->req->headers->header('X-Bender'),则返回1;#未验证$c->render(text=>“You're not Bender”,status=>401);返回undef;});$auth->get('/blackjack')->to('hideout#blackjack]);

断开的调度链可以通过调用继续Mojolicious::Controller中的“continue”例如,这允许在到达下一个调度周期之前完成非阻塞操作。

my$maybe=$r->在('/maybe'=>sub($c)下{#等待3秒钟,然后给访客50%的机会继续Mojo::IOLoop->计时器(3=>sub{#失败者return$c->render(text=>'No luck.'),除非int rand 2;#优胜者$c->继续;});返回undef;});$maybe->get('/')->to('maybe#winner');

每个目的地都只是路线匹配时隐藏的快照,只有格式他们都有共同的价值。要获得更多动力,您可以使用Mojolicious::Controller中的“match”.

#第四个调度周期的操作我的$action=$c->match->stack->[3]{action};

格式

文件扩展名,如.html格式.txt文件在路线末端可以检测到并存储在stash值中格式。使用限制性占位符来声明可能的值。

#/foo.txt->取消定义#/foo.rss->{controller=>'foo',action=>'bar',format=>'rss'}#/foo.xml->{controller=>'foo',action=>'bar',format=>'xml'}$r->get('/foo'=>[format=>['rss','xml']])->to('fo#bar');

例如,允许不同格式的多个模板共享相同的操作代码。就像占位符一样,您可以使用默认值使格式可选。

#/foo->{controller=>'foo',action=>'bar'}#/foo.html->{controller=>“foo”,action=>“bar”,format=>“html”}#/foo.txt->{controller=>“foo”,action=>“bar”,format=>“txt”}$r->get('/foo'=>[format=>['html','txt']])->to('foo#bar',format=>undef);

格式可以由嵌套路由继承。

#/foo->{controller=>'foo',action=>'one',format=>undef}#/foo.html->{controller=>“foo”,action=>“one”,format=>“html”}#/foo.json->{controller=>'foo',action=>'one',format=>'json'}#/bar->{controller=>'bar',action=>'two',format=>undef}#/bar.html->{controller=>“bar”,action=>“two”,format=>“html”}#/bar.json->{controller=>'bar',action=>'two',format=>'json'}my$with_format=$r->any('/'=>[format=>['html','json']])->to(format=>undef);$with_format->get('/foo')->to('foo#one');$with_format->get('/bar')->to('bar#two');

A类格式值也可以传递给Mojolicious::Controller中的“url_for”.

#/foo/23.txt->{controller=>“foo”,action=>“bar”,id=>23,format=>“txt”}$r->get('/foo/:id')->to('foo#bar')->name('baz');#为路由“baz”生成URL“/foo/24.txt”我的$url=$c->url_for('baz',id=>24,format=>'txt');

Web套接字

用这个方法Mojolicious::Routes::Route中的“网络套接字”您可以限制对WebSocket握手的访问,这是正常的得到带有一些附加信息的请求。

#/echo(WebSocket握手)$r->websocket('/echo')->to('foo#echo');#控制器包MyApp::控制器::Foo;使用Mojo::Base“Mojolicious::Controller”,-签名;#行动子回波($self){$self->打开(消息=>sub($self,$msg){$self->send(“回声:$msg”);});}1;

当您使用101响应状态,如果您使用Mojoliques::控制器中的“on”或发送消息Mojolicious::Controller中的“send”马上。

GET/echo HTTP/1.1主持人:mojolique.org用户代理:Mojolicious(Perl)连接:升级升级:websocketSec-WebSocket密钥:IDM3ODE4NDk2MjA1OTcxOQ==Sec-WebSocket-Version:13HTTP/1.1 101交换协议服务器:Mojolicious(Perl)日期:2015年2月3日星期二17:08:24 GMT连接:升级升级:websocketSec-WEB插座验收:SWsp5N2iNxPbHlcOTIw8ERvyVPY=

全面路线

由于路由按照定义的顺序匹配,因此可以使用可选的通配符占位符捕获上一个路由中不匹配的所有请求。

# * /*$r->any(“/*whatever”=>{whatever=>''}=>sub($c){my$whatever=$c->param(“whatever”);$c->render(text=>“/$whatever不匹配。”,status=>404);});

条件

条件,如标题,代理人主办Mojolicious::插件::HeaderCondition可以使用该方法应用于任何路线Mojolicious::Routes::Route中的“requires”,并允许更强大的路由构造。

#/(来源:http://perl.org)$r->get('/')->需要(headers=>{Origin=>qr/perl\.org/})->to('foo#bar');#/(Firefox)$r->get('/')->需要(agent=>qr/Firefox/)->to('browser-test#Firefox');#/(Internet Explorer)$r->get('/')->需要(agent=>qr/Internet Explorer/)->to('browser-test#ie');# http://docs.mojolicious.org/mojolicious网站$r->get('/')->需要(host=>'docs.mojolicious.org')->to('perldoc#index');

请注意,路由缓存的条件太复杂,通常会加快重复请求的速度,从而降低性能。

挂钩

钩子在路由系统之外运行,允许您通过不加区别地与所有请求共享代码来扩展框架本身Mojolicious中的“钩子”,这使得它们成为一个非常强大的工具,特别是对于插件。

#应用程序包MyApp;使用Mojo::Base“Mojolicious”,-签名;子启动($self){#检查所有“/test”前缀请求$self->hook(before_dispatch=>sub($c){如果$c->req->url->path->contains('/test');});#如果上面的钩子呈现响应,则无法达到这些目标我的$r=$self->路线;$r->get('/welcome')->to('foo#welcome'');$r->post('/bey')->to('foo#bye');}1;

对响应进行后处理以添加或删除标头是一种非常常见的用法。

#确保缓存静态文件$app->hook(after_static=>sub($c)){$c->res->headers->cache_control('max-age=3600,必须重新验证');});#删除默认标题$app->hook(after_dispatch=>sub($c)){$c->res->headers->remove(“服务器”);});

预处理请求也是如此。

#根据请求标头选择模板变量$app->hook(before_dispatch=>sub($c)){除非我的$agent=$c->req->headers->user_agent,否则返回;如果$agent=~/Internet Explorer/;,$c->stash(variant=>'ie');});

或者更高级的扩展,为您的应用程序添加监控功能。

#将异常转发到web服务$app->hook(after_dispatch=>sub($c)){返回,除非我的$e=$c->stash('exception');$c->ua->帖子('https://example.com/bug'=>form=>{exception=>$e});});

您甚至可以扩展大部分核心功能。

#使控制器对象可用于操作$_$app->hook(around_action=>sub($next,$c,$action,$last){本地$_=$c;返回$next->();});#将路由名称作为参数传递给操作$app->hook(around_action=>sub($next,$c,$action,$last){返回$c->$action($c->current_route);});

有关可用挂钩的完整列表,请参阅Mojolicious中的“挂钩”.

高级

不太常用,功能更强大。

快捷方式

为了使路线生成更具表现力,您还可以使用添加自己的快捷方式Mojolicus中的“add_shortcut”::路线.

#简单的“资源”快捷方式$r->add_shortcut(资源=>sub($r,$name){#资源的前缀my$resource=$r->any(“/$name”)->到(“$name#”);#呈现资源列表$resource->get('/')->to('#index')->name($name);#呈现表单以创建新资源(提交到“存储”)$resource->get('/create')->to('#create')->name(“create_$name”);#存储新创建的资源(由“create”提交)$resource->发布->到(“#store”)->名称(“store_$name”);#呈现特定资源$resource->get('/:id')->to('#show')->name(“show_$name”);#呈现表单以编辑资源(提交给“更新”)$resource->get('/:id/edit')->to('#edit')->name(“edit_$name”);#存储更新的资源(由“编辑”提交)$resource->put('/:id')->to('#update')->name(“update_$name”);#删除资源$resource->delete('/:id')->to('#remove')->name(“remove_$name”);返回$resource;});#GET/users->{controller=>'users',action=>'index'}#获取/用户/创建->{controller=>“用户”,action=>“创建”}#POST/users->{controller=>'users',action=>'store'}#GET/users/23->{controller=>'users',action=>'show',id=>23}#GET/users/23/edit->{controller=>'users',action=>'edit',id=>23}#PUT/users/23->{controller=>'users',action=>'update',id=>23}#DELETE/users/23->{controller=>'users',action=>'remove',id=>23}$r->资源(“用户”);

重新安排路线

从应用程序启动到第一个请求到达,仍然可以使用以下方法移动甚至删除所有路由Mojolicious::Routes::Route中的“add_child”Mojolicious::Routes::Route中的“删除”.

#GET/example/show->{controller=>'example',action=>'show'}我的$show=$r->get('/show')->to('example#show');$r->any('/example')->add_child($show);#什么都没有$r->get('/secrets/show')->to('secrets#show';$r->find('show_secrets')->删除;

特别是对于重新排列插件创建的路由,这可能非常有用,可以通过它们的名称来查找您可以使用的路由Mojolicious::Routes::Route中的“find”.

#GET/example/test->{controller=>'example',action=>'test'}$r->get('/othing/else')->to('something#else')->name('test');我的$test=$r->find(“测试”);$test->pattern->parse('/example/test');$test->pattern->defaults({controller=>'example',action=>'test'});

即使路线模式和目的地仍然可以更改Mojolicious::Routes::Pattern中的“parse”Mojolicious::Routes::Pattern中的“defaults”.

添加条件

您还可以使用该方法添加自己的条件Mojolicious::Routes中的“add_condition”。所有条件基本上都是每次新请求到达时运行的路由器插件,需要返回一个真实值才能匹配路由。

#随机允许路由匹配的条件$r->add_condition(随机=>sub($route,$c,$captures,$num){#失败者如果int rand$num;则返回undef;#优胜者返回1;});#/可能(25%的可能性)$r->get('/maybe')->需要(random=>4)->to('foo#bar');

使用您需要的任何请求信息。

#检查查询参数的条件(对模拟web服务有用)$r->add_condition(查询=>sub($route,$c,$captures,$hash){对于我的$key(keys%$hash){我的$param=$c->req->url->query->param($key);返回undef,除非定义了$param&&$param eq$hash->{$key};}返回1;});#/你好?to=世界测试=1$r->get('/hello')->需要(query=>{test=>1,to=>'world'})->to('foo#bar');

条件插件

您还可以将条件打包为可重用插件。

#插件软件包Mojolicious::Plugin::WerewolfCondition;使用Mojo::Base“Mojolicious::Plugin”,-signatures;使用Astro::MoonPhase;子寄存器($self、$app、$conf){#添加“狼人”条件$app->routes->add_condition(狼人=>sub($route,$c,$captures,$days){#把狼人挡在外面!如果abs(14-(阶段(时间))[2])>($days/2),则返回undef;#没关系,没有狼人返回1;});}1;

现在只需加载插件,您就可以在所有应用程序中使用该条件了。

#应用程序包MyApp;使用Mojo::Base“Mojolicious”,-签名;子启动($self){#插件$self->插件('WerewolfCondition');#/藏身处(满月后将其隔离4天)$self->routes->get('/hideout')->requires(狼人=>4)->to(controller=>'foo',action=>'bar');}1;

装载应用程序

将一个应用程序嵌入到另一个中的最简单方法是Mojolicous::插件::Mount,它允许您在域和/或前缀下装载整个自包含的应用程序。

使用Mojolicious::Lite签名;#安装在“/prefix”下的整个应用程序插件安装=>{'/prefix'=>'/home/sri/myapp/script/myapp'};#使用子域装载应用程序插件安装=>{“test.example.com”=>“/home/sri/myapp2.pl”};#正常路线获取“/”=>子($c){$c->render(text=>“你好,世界!”);};应用程序->启动;

嵌入式应用程序

为了获得更多的功能,您还可以通过使用应用程序而不是控制器来嵌入应用程序。例如,这允许使用Mojolicious::精简normal中的领域特定语言Mojolicious公司控制器。

#控制器程序包MyApp::Controller::Bar;使用Mojolicious::Lite签名;#/你好获取'/hello'=>sub($c){my$name=$c->param('name');$c->render(text=>“Hello$name”);};1;

使用属性Mojolicious::Routes::Route中的“部分”,您可以允许路由部分匹配并仅使用嵌入应用程序中的剩余路径,则基本路径将在路径存储值。

#/foo个/*$r->any('/foo')->partial(1)->to('bar#',name=>'Mojo');

最小可嵌入应用程序只不过是Mojolicious公司,包含处理程序方法接受Mojolicious::控制器物体。

程序包MyApp::Controller::Bar;使用Mojo::Base“Mojolicious”,-签名;子处理程序($self,$c){$c->res->code(200);my$name=$c->param('name');$c->res->body(“Hello$name.”);}1;

主机应用程序通过存储与嵌入式应用程序共享的信息很少。因此,当前无法在通向嵌入式应用程序的路由中使用路由占位符,因为这会导致Mojolicious::Controller中的“url_for”.

应用程序插件

您甚至可以将应用程序打包为独立的可重用插件。

#插件软件包Mojolicious::Plugin::MyEmbeddedApp;使用Mojo::Base“Mojolicious::Plugin”,-signatures;子寄存器($self、$app、$conf){#自动添加路由$app->routes->any('/foo')->partial(1)->to(app=>EmbeddedApp::app());}包EmbeddedApp;使用Mojolicious::Lite;获取'/bar'=>'bar';1;__数据__@@条形图html.ep你好,世界!

这个应用程序stash值不会被嵌套路由继承,可以用于已经实例化的应用程序。现在只需加载插件即可。

#应用程序包MyApp;使用Mojo::Base“Mojolicious”,-签名;子启动($self){#插件$self->插件(“MyEmbeddedApp”);}1;

更多

您可以继续Mojolicious::指南现在或者看看Mojolicious维基,其中包含许多不同作者编写的更多文档和示例。

支持

如果您有任何文档可能还没有回答的问题,请毫不犹豫地在论坛,上的IRC公司,或矩阵.