索引文档, 查看 perldoc Mojolicious::Guides
Mojolicious 的结构为:
controller
从 用户处获取 request
controller
将数据传递给 Model
, 并从其获取处理后的数据
controller
将数据传递给 View
, 并获取 response
Sessions 一般来说, 所有的 session 数据存储在服务器端, 浏览器通过 session IDs 来和服务器交换数据.
在 Mojolicious 中:
1 Set -Cookie: session =hmac-sha256(base64(json ($session )))
Prototype 一个完整的 Mojolicious 应用的结构为:
可以用下列命令构建出这个目录结构:
1 2 mojo generate lite-app myapp.pl mojo generate app MyAppName
Foundation 在构建的目录下开始编写:
1 2 3 4 mkdir myappcd myapptouch myapp.plchmod 744 myapp.pl
在 myall.pl
中写入:
1 2 3 4 5 6 7 8 !/usr/ bin/env perluse Mojolicious::Lite -signatures; get '/' => sub ($c ) { $c->render(text => 'Hello World!' ); }; app->start;
-signatures
用于启用 subroutine
的新语法支持.
运行程序:
模块 model 在 Mojolicious 中的模块处理:
1 2 3 mkdir -p lib/MyApp/Modeltouch lib/MyApp/Model/Users.pmchmod 644 lib/Myapp/Model/Users.pm
在 lib/Myapp/Model/Users.pm
文件中添加:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 package MyApp::Model::Users;use strict;use warnings;use experimental qw(signatures) ;use Mojo::Util qw(secure_compare) ;my $USERS = { joel => 'las3rs' , marcus => 'lulz' , sebastian => 'secr3t' };sub new ($class ) { bless {}, $class }sub check ($self , $user , $pass ) { return 1 if $USERS->{$user} && secure_compare $USERS->{$user}, $pass; return undef ; }1 ;
用 helper
来注册一个函数, 来让这个 model 对所有的模板起作用:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 !/usr/ bin/env perluse Mojolicious::Lite -signatures;use lib qw(lib) ;use MyApp::Model::Users; Helper to lazy initialize and store our model object helper users => sub { state $users = MyApp::Model::Users->new }; /?user=sebastian&pass=secr3t any '/ ' => sub ($c) { # Query parameters my $user = $c->param(' user') || ' '; my $pass = $c->param(' pass') || ' '; # Check password return $c->render(text => "Welcome $user.") if $c->users->check($user, $pass); # Failed $c->render(text => ' Wrong username or password.'); }; app->start;
注册的函数为 users
, 所有的 $c
都可以调用这个 helper 函数.
关于 $c
对象
在Mojolicious中,$c
是一个代表当前请求的控制器对象 (Controller object). 它是在Mojolicious应用程序中处理HTTP请求的关键对象之一,可以访问请求和响应对象,路由参数,模板引擎等。它提供了许多方法来处理HTTP请求和响应,例如$c->param
用于获取查询参数,$c->render
用于呈现视图模板或返回响应,$c->redirect_to
用于重定向到其他URL等。在你的代码中,$c
对象被用于获取查询参数和呈现响应。
param()
用于获取查询参数.
any
用于匹配 HTTP 请求方法, 如 POST
, GET
.
测试 Testing 创建测试目录:
1 2 3 mkdir ttouch t/login.tchmod 644 t/login.t
使用 Test::Mojo
模块, 如:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 use Test::More;use Test::Mojo; Include applicationuse Mojo::File qw(curfile) ;require (curfile->dirname->sibling('myapp.pl' )); Allow 302 redirect responsesmy $t = Test::Mojo->new; $t->ua->max_redirects(1 ); Test if the HTML login form exists $t->get_ok('/' ) ->status_is(200 ) ->element_exists('form input[name="user"]' ) ->element_exists('form input[name="pass"]' ) ->element_exists('form input[type="submit"]' ); Test login with valid credentials $t->post_ok('/' => form => {user => 'sebastian' , pass => 'secr3t' }) ->status_is(200 ) ->text_like('html body' => qr/Welcome sebastian/ ); Test accessing a protected page $t->get_ok('/protected' )->status_is(200 )->text_like('a' => qr/Logout/ ); Test if HTML login form shows up again after logout $t->get_ok('/logout' ) ->status_is(200 ) ->element_exists('form input[name="user"]' ) ->element_exists('form input[name="pass"]' ) ->element_exists('form input[type="submit"]' ); done_testing();
要检测的文件用 require(curfile->dirname->sibling('myapp.pl'));
这一行指定.
测试如:
1 2 3 prove -l prove -l t/login.t prove -l -v t/login.t
用 request
来调试:
1 2 ./myapp.pl get / ./myapp.pl get -v '/?user=sebastian&pass=secr3t'
保持状态 State keeping 创建 session, 以及获取 session 的用户:
1 2 $c->session(user => 'sebastian' );my $user = $c->session('user' );
$c->session('user');
中的 user
应该是 hash 的键值.
可以为 session 创建 secure passphrase:
1 $app->secrets(['Mojolicious rocks' ]);
设置 sessions 的 expiration 时限:
1 $c->session(expiration => 3600 );
删除一个 session:
1 $c->session(expires => 1 );
一个较为完整的示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 !/usr/ bin/env perluse Mojolicious::Lite -signatures;use lib qw(lib) ;use MyApp::Model::Users; Make signed cookies tamper resistant app->secrets(['Mojolicious rocks' ]); helper users => sub { state $users = MyApp::Model::Users->new }; Main login action any '/' => sub ($c ) { my $user = $c->param('user' ) || '' ; my $pass = $c->param('pass' ) || '' ; return $c->render unless $c->users->check($user, $pass); $c->session(user => $user); $c->flash(message => 'Thanks for logging in.' ); $c->redirect_to('protected' ); } => 'index' ; Make sure user is logged in for actions in this group group { under sub ($c ) { return 1 if $c->session('user' ); $c->redirect_to('index' ); return undef ; }; get '/protected' ; }; Logout action get '/logout' => sub ($c ) { $c->session(expires => 1 ); $c->redirect_to('index' ); }; app->start;__DATA__ % layout 'default' ; %= form_for index => begin % if (param 'user' ) { <b > Wrong name or password, please try again.</b > <br > % } Name:<br > %= text_field 'user' <br > Password:<br > %= password_field 'pass' <br > %= submit_button 'Login' % end % layout 'default' ; % if (my $msg = flash 'message' ) { <b > <%= $msg %></b > <br > % } Welcome <%= session 'user' %>.<br > %= link_to Logout => 'logout' <!DOCTYPE html > <html > <head > <title > Login Manager</title > </head > <body > <%= content %></body > </html >
Inflating templates 将 __DATA__
section 的内容以不同文件的方式转换到 templates
和 public
目录下, 如:
应该可以自定义.