码神之路:Perl篇

Mojolicious

2017-10-13  本文已影响56人  JSON_NULL

简介

# Application
package MyApp;
use Mojo::Base 'Mojolicious';

# Route
sub startup {
  my $self = shift;
  $self->routes->get('/hello')->to('foo#hello');
}

# Controller
package MyApp::Controller::Foo;
use Mojo::Base 'Mojolicious::Controller';

# Action
sub hello {
  my $self = shift;
  $self->render(text => 'Hello World!');
}

这个包实现基于Mojo工具包,实现了一个实时WEB框架。支持RESTful路由,插件功能、命令管理、Perl-ish模板、内容协商、会话管理、表单验证、测试框架、静态文件服务、CGI/PSGI检测、Unicode 等。

事件钩子

Mojolicious中实现了以下事件,下面按照他们被触发的顺序一一介绍。

after_build_tx

这个点是工作在 HTTP 的请求还没有被解析, 但连接已经建立的时候。

$app->hook(after_build_tx => sub {
  my ($tx, $app) = @_;
  ...
});

这个hook的功能非常强大,但一般情况下是用不到的。可以使用它来完成诸如上传进度条等高级功能。
注:这个事件不适用于嵌入式应用程序,因为只有主机应用程序可以构建事务。( 默认参数送的是 transaction 和 application object )

around_dispatch

在接收到“请求”并且对所有“dispatch”过程包装完成之后触发。如果你需要继续执行后面的控制链,则需要手动地执行$next->();在$next->()被调用的前后的代码会在不同的时机被运行。

$app->hook(around_dispatch => sub {
  my ($next, $c) = @_;
  ...
  $next->();
  ...
});

这个hook也不常用,但它的功能非常强大,可以让你定制程序中的所有异常行为(404,500等都可以在这个hook点返回)。 (传送的参数是下一个 hook 点的回调和 controller 的对象)

before_dispatch

这个点是工作在静态文件调度和路由选择之前。

$app->hook(before_dispatch => sub {
  my $c = shift;
  ...
});

如果你要重写进来的请求和提前做一些处理,这个hook点非常有用。 ( 默认参数送的是 controller 控制器对象 )

after_static

这个hook在静态响应已经由静态文件服务生成之后触发。

$app->hook(after_static => sub {
  my $c = shift;
  ...
});

主要用来对静态响应做些后处理 ( post-processing )。 默认参数送的是 controller 对象 。

before_routes

这个hook在静态文件服务器确定是否应该提供静态文件并在路由启动之前触发。

$app->hook(before_routes => sub {
  my $c = shift;
  ...
});

多用于自定义调度器和收集度量用。( 默认参数是 controller 对象 )

around_action

当一个 action 被调用的时候, 触发这个hook。 如果你需要继续执行后面的控制链,则需要手动地执行$next->();默认情况下 对action的调用是最控制链中的后一个hook,所以你的代码需要放在$next->()之前。

$app->hook(around_action => sub {
  my ($next, $c, $action, $last) = @_;
  ...
  return $next->();
});

这个hook功能强大但并不常用,它可以让你传递额外的一些参数给 action 并对不同的处理方式返回不同的值。参数为:下一个hook点,当前控制器对象,action,是否为最后一个hook。

注:如果有嵌套路由,该hook可以针对相同的请求多次触发。

before_render

在内容由渲染器生成之前触发。

$app->hook(before_render => sub {
  my ($c, $args) = @_;
  ...
});

主要用于预处理传递给渲染器的参数。接收的参数有:当前控制器对象,将要传递给渲染器的参数。

注:这个hook可能会触发失败。

after_render

在内容由渲染器生成并分配给响应之后触发。

$app->hook(after_render => sub {
  my ($c, $output, $format) = @_;
  ...
});

主要用于后处理动态生成的内容。接收的参数有:当前控制器对象,生成内容的引用,格式。

注:这个hook可能会触发失败。

after_dispatch

在响应被生成之后以倒序触发。

$app->hook(after_dispatch => sub {
  my $c = shift;
  ...
});

这个主要用来重写响应的输出和其它的处理任务。(默认参数送的是 controller 对象)

注:这个hook可能会触发失败。

属性

Mojolicious从Mojo继承所有属性,并实现以下属性。

commands

my $commands = $app->commands;
$app         = $app->commands(Mojolicious::Commands->new);

应用程序中的命令行接口,默认为Mojolicious::Commands对象。

# Add another namespace to load commands from
push @{$app->commands->namespaces}, 'MyApp::Command';

controller_class

my $class = $app->controller_class;
$app      = $app->controller_class('Mojolicious::Controller');

默认控制器的类,默认为Mojolicious::Controller。
注:此类需要在第一个请求到达之前已经被加载。

log

my $log = $app->log;
$app    = $app->log(Mojo::Log->new);

应用程序的日志记录对象,默认为Mojo::Log对象。如果应用运行在development “模式”,则日志的等级为debug,否则日志的等级将被设置为info。

如果log目录存在,所有日志信息会被写入log/$mode.log文件中,否则日志信息会被写入STDERR流中。

# Log debug message
$app->log->debug('It works');

max_request_size

my $max = $app->max_request_size;
$app    = $app->max_request_size(16777216);

最大“请求”的大小(以字节为单位),默认为Mojo::Message中max_message_size的值。将值设置为0表示允许无限大的“请求”。

注:如果您使用Mojo::Message中的dom或json方法解析请求体,此值设置的过大会使内存使用量增加。

mode

my $mode = $app->mode;
$app     = $app->mode('production');

应用程序的运行模式,默认情况下使用环境变量MOJO_MODE和PLACK_ENV的值,如果它们不存在则给默认值development。

moniker

my $moniker = $app->moniker;
$app        = $app->moniker('foo_bar');

应用程序的 moniker,通常用作配置文件的默认文件名,默认使用Mojo::Util中的decamelize对应用程序的类进行处理得到。

plugins

my $plugins = $app->plugins;
$app        = $app->plugins(Mojolicious::Plugins->new);

应用程序的插件管理器,默认为Mojolicious::Plugins对象。如果要加载插件,请参阅plugin方法。

# Add another namespace to load plugins from
push @{$app->plugins->namespaces}, 'MyApp::Plugin';

renderer

my $renderer = $app->renderer;
$app         = $app->renderer(Mojolicious::Renderer->new);

用于内容渲染的对象,默认为Mojolicious::Renderer对象。有关如何生成内容的更多信息,请参阅Mojolicious :: Guides :: Rendering。

# Add another "templates" directory
push @{$app->renderer->paths}, '/home/sri/templates';

# Add another "templates" directory with higher precedence
unshift @{$app->renderer->paths}, '/home/sri/themes/blue/templates';

# Add another class with templates in DATA section
push @{$app->renderer->classes}, 'Mojolicious::Plugin::Fun';

routes

my $routes = $app->routes;
$app       = $app->routes(Mojolicious::Routes->new);

应用程序的路由器,默认为Mojolicious::Routes对象。您可以在startup方法中使用此对象对url的路由规则进行定义。

# Add routes
my $r = $app->routes;
$r->get('/foo/bar')->to('test#foo', title => 'Hello Mojo!');
$r->post('/baz')->to('test#baz');

# Add another namespace to load controllers from
push @{$app->routes->namespaces}, 'MyApp::MyController';

secrets

my $secrets = $app->secrets;
$app        = $app->secrets([$bytes]);

应用中用于对cookie进行签名的密码口令,默认使用的是使用的名称“moniker”。如果你没有设置而使用了默认的“moniker”应用会在日志中提示是这是不安全的,需要修改你的secrets。

你可以设置多个密码,只有第一个用于创建新的签名,但所有的密码都会被用于验证。所以当你想要更换密码时,可以把新的密码放在第一个位置,后面放老的密码。这样不会使已经签名的cookie失效。

session

my $sessions = $app->sessions;
$app         = $app->sessions(Mojolicious::Sessions->new);

基于cookie的会话管理器,默认为Mojolicious::Session对象。

# Change name of cookie used for all sessions
$app->sessions->cookie_name('mysession');

static

my $static = $app->static;
$app       = $app->static(Mojolicious::Static->new);

用于从public目录中提取静态文件,默认为Mojolicious::Static对象。

# Add another "public" directory
push @{$app->static->paths}, '/home/sri/public';

# Add another "public" directory with higher precedence
unshift @{$app->static->paths}, '/home/sri/themes/blue/public';

# Add another class with static files in DATA section
push @{$app->static->classes}, 'Mojolicious::Plugin::Fun';

# Remove built-in favicon
delete $app->static->extra->{'favicon.ico'};

types

my $types = $app->types;
$app      = $app->types(Mojolicious::Types->new);

负责对MIME类型的扩展名进行解析,默认为:Mojolicious::Types对象。

# Add custom MIME type
$app->types->type(twt => 'text/tweet');

validator

my $validator = $app->validator;
$app          = $app->validator(Mojolicious::Validator->new);

表单验证器对象,默认为Mojolicious::Validator对象。

# Add validation check
$app->validator->add_check(foo => sub {
  my ($validation, $name, $value) = @_;
  return $value ne 'foo';
});

# Add validation filter
$app->validator->add_filter(quotemeta => sub {
  my ($validation, $name, $value) = @_;
  return quotemeta $value;
});

方法

Mojolicious从Mojo继承所有方法,并实现以下方法。

build_controller

my $c = $app->build_controller;
my $c = $app->build_controller(Mojo::Transaction::HTTP->new);
my $c = $app->build_controller(Mojolicious::Controller->new);

使用controller_class构建默认的控制器对象。

# Render template from application
my $foo = $app->build_controller->render_to_string(template => 'foo');

build_tx

my $tx = $app->build_tx;

构建mojo::Trasaction::HTTP对象,并触发after_build_tx事件hook。

defaults

my $hash = $app->defaults;
my $foo  = $app->defaults('foo');
$app     = $app->defaults({foo => 'bar', baz => 23});
$app     = $app->defaults(foo => 'bar', baz => 23);

对所有“请求”绑定默认值到Mojolicious::Controller中的stash中。

# Remove value
my $foo = delete $app->defaults->{foo};

# Assign multiple values at once
$app->defaults(foo => 'test', bar => 23);

dispatch

$app->dispatch(Mojolicious::Controller->new);

这是每个Mojolicious应用程序都会有的核心,为每个请求调用“static”和“routes”调度器,并传递一个Mojoliclious::Controller对象。

handler

$app->handler(Mojo::Transaction::HTTP->new);
$app->handler(Mojolicious::Controller->new);

设置默认控制器,并为每个“请求”触发“around_dispatch”事件hook。

helper

$app->helper(foo => sub {...});

添加或替换一个在应用程序控制器和应用对象中可以调用的helper方法或对象。当然在ep模块中也可以使用。有关默认情况下可用的帮助器的完整列表,请参阅Mojolicious::Plugin::DefaultHelpers和Mojolicious::Plugin::TagHelpers。

# Helper
$app->helper(cache => sub { state $cache = {} });

# Application
$app->cache->{foo} = 'bar';
my $result = $app->cache->{foo};

# Controller
$c->cache->{foo} = 'bar';
my $result = $c->cache->{foo};

# Template
% cache->{foo} = 'bar';
%= cache->{foo}

hook

$app->hook(after_dispatch => sub {...});

使用hook来扩展Mojolicious,允许你的代码与所有请求无缝的共享。以前的“事件钩子”小节已经对可用的hook进行了详细的介绍。

# Dispatchers will not run if there's already a response code defined
$app->hook(before_dispatch => sub {
  my $c = shift;
  $c->render(text => 'Skipped static file server and router!')
    if $c->req->url->path->to_route =~ /do_not_dispatch/;
});

new

my $app = Mojolicious->new;
my $app = Mojolicious->new(moniker => 'foo_bar');
my $app = Mojolicious->new({moniker => 'foo_bar'});

构建一个新的Mojolicious应用程序并调用startup方法。会自动检测您的主目录,还会设置渲染器,静态文件服务器,一级默认的插件和一个around_dispatch钩子。并使用默认的异常处理。

plugin

$app->plugin('some_thing');
$app->plugin('some_thing', foo => 23);
$app->plugin('some_thing', {foo => 23});
$app->plugin('SomeThing');
$app->plugin('SomeThing', foo => 23);
$app->plugin('SomeThing', {foo => 23});
$app->plugin('MyApp::Plugin::SomeThing');
$app->plugin('MyApp::Plugin::SomeThing', foo => 23);
$app->plugin('MyApp::Plugin::SomeThing', {foo => 23});

加载一个插件,有关Mojolicious发行版中包含的示例插件的完整列表,请参阅Mojolicious::Plugins中的“PLUGINS”。

start

$app->start;
$app->start(@ARGV);

启动应用程序的命令行界面。有关默认可用命令的完整列表,请参阅Mojolicious::Commands中的“COMMANDS”。注意选项-h/ --help,--home和-m/ --mode,其通过所有命令共享,将在编译时对@ARGV进行解析。

# Always start daemon
$app->start('daemon', '-l', 'http://*:8080');

startup

$app->startup;

这是应用程序中最重要的一个钩子,它将在应用程序启动时调用,需要在子类中重载。

sub startup {
  my $self = shift;
  ...
}

AUTOLOAD

除了上述的“ATTRIBUTES”和“METHODS”之外,您还可以在Mojolicious对象上调用helpers。这包括Mojolicious :: Plugin :: DefaultHelpers和Mojolicious :: Plugin :: TagHelpers中的所有helpers。请注意,应用程序helpers总是使用新的默认控制器对象调用,因此它们不能依赖或更改控制器状态,包括请求,响应和存储。

# Call helper
say $app->dumper({foo => 'bar'});

# Longer version
say $app->build_controller->helpers->dumper({foo => 'bar'});

框架中捆绑的文件

该Mojolicious发布版包括了已捆绑在内部使用的一些文件。如下表所示。

名称 版权信息 开源协议
Mojolicious Artwork Copyright (C) 2010-2017, Sebastian Riedel. Licensed under the CC-SA License, Version 4.0
jQuery Copyright (C) jQuery Foundation. Licensed under the MIT License
prettify.js Copyright (C) 2006, 2013 Google Inc.. Licensed under the Apache License, Version 2.0
上一篇下一篇

猜你喜欢

热点阅读