Url и обработчикиПервоначально web сайты целиком состояли из статических HTML страниц. Затем появился CGI, и сайты стали обзаводиться формами отправки данных и прочими динамическими станицами. Постепенно процент динамических страниц все увеличивался и увеличивался. Но url вида http://www.server.com/cgi-bin/foo.cgi не индексировались поисковиками, а также страдала эстетика, поэтому динамические страницы стали маскировать под обычные html: http://www.server.com/foo.html.
В то же время шло усложнение CGI скриптов, и повторяющийся код стали выносить в общие модули. Но не весь такой код можно было вынести в модули, в скриптах оставался код простой инициализации. Проще иметь одну точку входа, в которой посредством диспетчера вызывались обработчики конкретных команд, url.
Кстати, одну точку входа имели изначально те, что прятал статику за динамикой при помощи назначения обработчиков в Apache, а не при помощи mod_rewrite. Для тех, кто не прятал динамику за статикой, единая точка входа приводила к не слишком красивым url: http://www.server.com/index.php?action=foo, хотя при помощи mod_rewrite этого можно избежать.
Далее в статье web сайты являются лишь частным случаем.
Обработчики и диспетчераВ perl есть несколько возможностей сообщить диспетчеру какой код необходимо выполнять для каждой конкретной команды (url).
Можно просто вручную прописать таблицу диспетчеризации. Но при создании нового обработчика, можно забыть его зарегистрировать в таблице диспетчеризации, поэтому желательно чтобы эта регистрации происходила автоматически.
Автоматизации можно добиться при помощи задания необходимого атрибута подпрограммам-обработчикам и определения подпрограммы MODIFY_CODE_ATTRIBUTES. Например, модуль с обработчиками может иметь следующий вид:
package Foo::C::Too;
use base qw(Foo::C);
sub foo : Handler(foo) { '...' }
sub too { '...' }
sub baz : Handler(abc) { '...' }
Где подпрограммы foo и baz являются обработчиками команд foo и abc или обработчиками url http://www.server.com/foo.html и http://www.server.com/abc.html, а подпрограмма too не является обработчиком.
Модуль Foo::C::Too унаследован от Foo::C, в котором определена MODIFY_CODE_ATTRIBUTES:
package Foo::C;
sub MODIFY_CODE_ATTRIBUTES {
my ($package, $sub, @attr) = @_;
foreach (@attr) {
if (m/^Handler\((.+)\)$/) {
# Регистрация в таблице диспетчеризации
# подпрограммы $sub для команды $1.
# ...
last;
}
}
return ();
}
При запуске ядро просматривает каталог Foo/C/ и загружает все модули Foo::C::*, а perl уже сам, вызывает Foo::C::MODIFY_CODE_ATTRIBUTES для каждой подпрограммы модуля, унаследованного от Foo::C.
Подробности работы с атрибутами смотрите в perldoc attributes.
Другим способом создания таблицы диспетчеризации является использования таблицы символов. После загрузки всех модулей с обработчиками, диспетчер ищет в них подпрограммы, имена которых соответствуют определенным правилам. В нижеприведенном примере осуществляет поиск обработчиков, имена подпрограмм которых начинаются с префикса "h_":
no strict "refs";
foreach (keys %INC) {
if (m/(Foo\/C\/.+)\.pm$/) {
my $p = $1;
$p =~ s/\//::/g;
while (my ($key, $val) = each(%{*{"$p\::"}})) {
if ($key =~ m/^h_(.+)/ and my $sub = *$val{CODE}) {
# Регистрация в таблице диспетчеризации
# подпрограммы $sub для команды $1.
# ...
}
}
}
}
Соответственно в модуле Foo::C::Too, обработчиками являются h_foo и h_baz:
package Foo::C::Too;
sub h_foo { '...' }
sub too { '...' }
sub h_baz { '...' }
На практике вместо префикса "h_" лучше использовать набор префиксов, например: "u_" - пользовательские команды, "a_" - команды администраторов, "o_" - команды доступные всем.
Дополнительные свойства обработчиков можно помещать в our переменные с именами, идентичными именам подпрограмм-обработчиков.
Последний способ: имя обработчика соответствует имени модуля. Этот способ хорошо подходит тогда, когда обработчики являются не просто подпрограммами, а целыми классами. Обычно такие обработчики находятся глубоко в системе и запрятаны за каким-то простым обработчиком.
Как видим, каждый из перечисленных способов имеет свои особенности, и в зависимости от цели стоит использовать наиболее подходящий.
А если вы занимаетесь просто созданием сайтов, то посмотрите готовые фреймворки.