mojo lite学习笔记之自身用法
2015-11-18 17:50:04 阿炯

本站赞助商链接,请多关照。 Mojolicious::Lite - Real-time micro web framework

Mojolicious::Lite简写为mojo::lite,为Mojolicious框架的简化版,包含了最基本的功能特点。Mojolicious::Lite继承全部的属性从Mojolicious,一个实用的实时web框架。个人一向对框架敬而远之,主要出于两点:个人能力有限;其二是框架能帮你快速开发也能让人绊上一跤。多年前学习过Catalyst,后来发现它越来越大,功能也很丰富,但我学习起来比较困难就直接放弃了;Mojolicious开发也很快,作者对它注入了大量的心血和精力,真心不希望它布Catalyst的后尘。mojo::lite中有该框架的核心功能,可通过'plugin'指令引入Mojolicious中的功能模块,加之Perl有CPAN做支持,整合一系列的模块便可以开发出相应的功能,本人一直坚持认为:开源的意义在于整合。好了,我们盘点它的一些特性:
 基于http方法、占位符、返回格式内容等的路由
 perl风格的模板
 异常处理
 会话与Useragent
 WebSockets支持


感谢"扶凯"引入介绍了这个框架,下面将从几个方面来介绍这个mini框架的基本使用方法:
-------------------
1、Url路由

2、模板技术

3、mojo lite 本身相关(功能扩展、异常与会话处理、WebSockets),即本文。


-------------------

运行模式
在生产环境我们想要禁用 debug 的信息,可以直接通过 Mojolicious 操作的命令行选项和修改 MOJO_MODE 这个环境变量,默认是使用的 development。
$ ./myapp.pl daemon -m production

这也影响到模板其它的地方,如 exception 和 not_found 的模板。

Logging
使用 Mojo::Log 时信息会自动的写到标准错误输入和 log/$mode.log 的文件中,当然必须 log 目录存在。在'production'模式下貌似没有日志文件生成。

$ mkdir log
更多的控制可以直接访问 Mojolicious 的对象.

use Mojolicious::Lite;
app->log->level('error');
app->routes->get('/foo/:bar' => sub {
 my $self = shift;
 $self->app->log->debug('Got a request for "Hello Mojo!".');
 $self->render(text => 'Hello Mojo!');
});

app->start;

这是通过 Mojo::Log 中的 "log" in Mojo 方法收集调试信息, 并通过 Mojolicious 修改模式为 production 来禁用这个. 也可以通过 "mode" in Mojolicious 来取到属性。默认模式是使用的 development,这个可以通过命令行参数或者 MOJO_MODE and PLACK_ENV 的环境变量的值来修改它, 模式修改后它的改变是日志级别由 debug 变成 info。

$ ./myapp.pl daemon -m production

全部的日志信息默认会写到标准输出或者如果存在 log 目录就会写到 log/$mode.log 中.

修改代码后自动加载

如果你想你的应用在修改后能自动的 reload 加载你的修改的程序, 建议你使用 morbo 的开发用的 web 服务器, 这样你就不用每次修改后重起。
$ morbo myapp.pl -l http://*:8000
Server available at http://127.0.0.1:8000.

译者注: 默认只监控 "lib" 和 "templates" 的文件夹内的改变, 如果你想加入指定的路径的文件进行监控修改后自动重起, 可以使用 -w 参数

$ morbo -w /myhome/lib myapp.pl

--------------
异常处理
内置异常 exception 和 not_found 网页

在开发的时候, 有时会因为我们的一些错误我们需要用到这些网页, 这个中包含着很多有利于我们 debug 的信息。如果部署在生产环境中,只要存在"templates/not_found.html.ep"文件,则会在出现404的时候,展示该文件的内容。

use Mojolicious::Lite;

# Not found (404)
get '/missing' => sub { shift->render('does_not_exist') };

# Exception (500)
get '/dies' => sub { die 'Intentional error' };

app->start;

--------------
功能扩展

Helpers
你可以扩展内置的 Mojolicious 的这个 helpers, 全部内置的所有的原生的可以在 Mojolicious::Plugin::DefaultHelpers 和 Mojolicious::Plugin::TagHelpers 中来查看.
use Mojolicious::Lite;

# "whois" helper
helper whois => sub {
 my $self  = shift;
 my $agent = $self->req->headers->user_agent || 'Anonymous';
 my $ip = $self->tx->remote_address;
 return "$agent ($ip)";
};

# /secret
get '/secret' => sub {
 my $self = shift;
 my $user = $self->whois;
 $self->app->log->debug("Request from $user.");
};

app->start;
__DATA__

@@ secret.html.ep
We know who you are <%= whois %>.

Sessions
签名 cookie 基于你的 session ,这个原生可以使用。直接通过 helper "session" in Mojolicious::Plugin::DefaultHelpers,所以的全部的 session 的数据序列化是通过 Mojo::JSON 实现的。
use Mojolicious::Lite;

get '/counter' => sub {
 my $self = shift;
 $self->session->{counter}++;
};

app->start;
__DATA__

@@ counter.html.ep
Counter: <%= session 'counter' %>

只需要意识到,所有的会话数据需要通过 Mojo::JSON 序列化。需要注意的是, 你应该使用一个自定义的 "secret" in Mojolicious 来签署 Cookie 才会真正的安全。
app->secrets(['my secret passphrase here']);

Secret
用来签署 Cookie ,提高安全性。
app->secret('My secret passphrase here');

文件上传(File uploads)
所有上传的文件只要是 multipart/form-data 的请求会自动转为 Mojo::Upload 对象处理。你不用担心内存的使用,因为超过 250KB 的所有文件将被自动到一个临时文件。
use Mojolicious::Lite;

# Upload form in DATA section
get '/' => 'form';

# Multipart upload handler
post '/upload' => sub {
my $self = shift;

# Check file size
return $self->render(text => 'File is too big.', status => 200) if $self->req->is_limit_exceeded;

# Process uploaded file
return $self->redirect_to('form')
 unless my $example = $self->param('example');
 my $size = $example->size;
 my $name = $example->filename;
 $example->move_to("/tmp/$name");
 $self->render(text => "Thanks for uploading $size byte file $name.");
};

app->start;
__DATA__

@@ form.html.ep
<!DOCTYPE html>
<html>
<head><title>Upload</title></head>
<body>
 %= form_for upload => (enctype => 'multipart/form-data') => begin
  %= file_field 'example'
  %= submit_button 'Upload'
 % end
</body>
</html>

为了保护您避免过大的文件, 这也有一个默认极限的值 10MB。你可以使用 MOJO_MAX_MESSAGE_SIZE 的环境变量来修改这个。
# Increase limit to 1GB
$ENV{MOJO_MAX_MESSAGE_SIZE} = 1073741824;

User agent
"ua" in Mojolicious::Controller 是一个全功能的 HTTP 和 WebSocket 的 user agent,当你和 Mojo::JSON、Mojo::DOM 组合使用时非常的强大。

use Mojolicious::Lite;
get '/uaget' => sub {
 my $self = shift;
 $self->render(data => $self->ua->get('http://mojolicio.us')->res->body);
};

app->start;

---------------
WebSockets
WebSocket的应用程序从未如此简单。接收信息通过 "on" in Mojolicious::Controller 中的事件订阅 "json" in Mojo::Transaction::WebSocket,并通过 "send" in Mojolicious::Controller 返回就行。

use Mojolicious::Lite;
websocket '/echo' => sub {
 my $self = shift;
 $self->on(message => sub {
  my ($self, $msg) = @_;
  $self->send("echo: $msg");
 });
};

app->start;

在 "message" in Mojo::Transaction::WebSocket 的事件中,我们可以对 "on" in Mojolicious::Controller 的回调进行订阅,当每次有 WebSocket 的信息时会接收到。

--------------
mojo lite 函数小结


--------------
mojo lite 本身

----------------------------
脚本程序的启动
mojo的CGI和PSGI的环境可以自动检查出来.可以不提供参数.

$ ./myapp.pl daemon
Server available at http://127.0.0.1:3000.

$ ./myapp.pl daemon -l http://*:8080
Server available at http://127.0.0.1:8080.

$ ./myapp.pl cgi
...CGI output...

$ ./myapp.pl
...List of available commands (or automatically detected environment)...

Start
你可以在 app->start 的调用中加入参数,来替换掉标准的从 @ARGV 中接收参数。

app->start('cgi');

Auto-Reloading
如果你想你的应用在修改后能自动的 reload 的话,建议你使用 morbo 的开发用的 web 服务器,这样你就不用每次修改后重起。它会将访问日志及程序运行中的一些信息打印到屏幕上,供调试使用时是很方便的。

$ morbo myapp.pl
Server available at http://127.0.0.1:3000.

-----------------------------
Mojolicious http服务器标志修改

Server:Mojolicious (Perl)
X-Powered-By:FreeOA (Perl)

/usr/local/share/perl/5.10.1/Mojolicious/Plugin/PoweredBy.pm
sub register {
  my ($self, $app, $conf) = @_;
  my $name = $conf->{name} || 'FreeOA (Perl)';

Mojo/Server/Daemon.pm
sub _build_tx {
...
$tx->res->headers->server('Mojolicious (Perl)');

-----------------------------
与Perl其它模块的冲突

use List::Util qw(any sum) 这个里面的any函数与mojo中的any方法发生冲突!