Mojolicious::Lite中能否使用->to()实现控制器请求转发?
解决Mojolicious::Lite中路由转发控制器404的问题
看起来你的问题出在控制器命名空间和路由映射不匹配上,Mojolicious没找到你定义的bar方法,所以才会尝试去渲染模板(这就是日志里找不到route/bar.html.ep的原因)。
问题根源
你定义的控制器包名是Route::Controller::Route,但你在路由里用的是->to('Route#bar')。Mojolicious默认会按照$app->controller_namespace + :: + 控制器名的规则去查找控制器类:
- 对于Mojolicious::Lite应用,默认的
controller_namespace是main(或者你的Lite应用的匿名类命名空间),所以它会尝试找main::Route这个类,而不是你写的Route::Controller::Route,自然找不到对应的bar方法。
解决方法(任选其一即可)
方法1:修正控制器包名,适配默认命名空间
把你的控制器包名改成Route(比如放在lib/Route.pm里):
package Route; use Mojo::Base 'Mojolicious::Controller'; sub bar { my $self = shift; $self->render(json => { hello => 'simone' }); } 1;
然后在你的Lite应用代码开头加上use lib 'lib';(确保能找到lib目录下的控制器),路由保持不变:
use Mojolicious::Lite; use lib 'lib'; (get '/x')->to('Route#bar'); get '/y' => sub { my $c = shift; $c->render(text => 'here') } => 'y'; app->start;
方法2:在路由里指定完整的控制器类名
如果你想保留现有的Route::Controller::Route包名,直接在to()里写完整的类名即可:
(get '/x')->to('Route::Controller::Route#bar');
这样Mojolicious会直接定位到你定义的控制器类,不需要依赖默认命名空间。
方法3:修改应用的控制器命名空间
在Lite应用里设置controller_namespace为你的控制器所在的父命名空间,这样Route#bar就能映射到Route::Controller::Route->bar:
use Mojolicious::Lite; app->controller_namespace('Route::Controller'); (get '/x')->to('Route#bar'); get '/y' => sub { my $c = shift; $c->render(text => 'here') } => 'y'; app->start;
测试一下,访问http://localhost:3000/x应该就能正常返回{"hello":"simone"}了。
内容的提问来源于stack exchange,提问作者simone
相关产品推荐
相关产品推荐

