多个CGI Perl脚本

时间:2016-08-30 12:48:51

标签: perl cgi

这是一个理论问题。我正在尝试基于生产者 - 消费者范例开发Perl应用程序。其中一个脚本创建一个包含数据的文件,而另一个脚本读取数据并且必须在HTML中显示。还有第三个文件,一个HTML表单,它启动了生产者perl文件。

我不知道如何使用CGI同时运行生产者和消费者,我无法在线查找有关它的信息(至少不是我如何搜索它。)

我想知道您是否可以告诉我在哪里可以找到这种信息,以便我可以在Apache服务器上测试该应用程序。

提前致谢

2 个答案:

答案 0 :(得分:0)

您可以在CGI脚本中导入use Module_Name;require Module_Name;的模块。 http://perldoc.perl.org/functions/use.html http://perldoc.perl.org/functions/require.html

普拉克网络框架不是银弹,CGI并没有死,而且FCGI是所有速度所在的地方。

不要买入普拉克炒作。了解它的第一个!

答案 1 :(得分:0)

免责声明:我认为这个问题归结为如何让程序的两个不同组件相互交互以创建一个可从Web访问的应用程序。如果这不是你想要的,那就把它作为思考的食物。

通用网关接口

您在谈论问题中的CGI脚本。 (强调我的)。

  

我正在尝试基于生产者 - 消费者范例开发Perl 应用程序。其中一个脚本创建一个包含数据的文件,而另一个读取数据并且必须在HTML中显示它。

通常,CGI以请求通过Web服务器的方式工作,并传递给应用程序。该应用程序可能是用Perl编写的。如果它是Perl脚本,则该脚本由perl解释器运行。 Web服务器启动该过程。它可以通过CGI访问请求信息,CGI主要是环境变量。完成此过程后,它会将数据写入STDOUT,Web服务器将其作为响应并发回。

+-----------+        +-------------+                     +----------------+
|           | +----> |             | +-----Request-----> |                |
|  Browser  |        | Web server  |                     |  perl foo.cgi  |
|           | <----+ |             | <-----Response----+ |                |
+-----------+        +-------------+                     +----------------+

现在因为Web服务器后面只涉及一个进程,所以不能有两个脚本。服务器无法同时与两件事进行通信。这不是CGI的工作方式。

综合方法

相反,您需要将两个脚本包装到单个入口点并将它们转换为某种组件。然后你可以让他们在内部互相交谈,而在外面,网络服务器只等待一个程序完成。

+-----------+        +-------------+                     +-----------------+
|           | +----> |             | +-----Request-----> |                 |
|  Browser  |        | Web server  |                     |  perl foo.cgi   |
|           | <----+ |             | <-----Response----+ |                 |
+-----------+        +-------------+                     | +-------------+ |
                                                         | |  Producer   | |
                                                         | +-----+-------+ |
                                                         |       |         |
                                                         |       |         |
                                                         |       V         |
                                                         | +-------------+ |
                                                         | | Consumer    | |
                                                         | +-------------+ |
                                                         |                 |
                                                         +-----------------+

要将其转换为Perl,请先确定一些术语。

  • script :一个位于.pl文件中的Perl程序,它没有自己的package
  • 模块:位于.pm文件中的Perl模块,其package具有适合文件名的命名空间

假设您有两个我们称之为 producer.pl consumer.pl 的Perl脚本。它们大大简化,不考虑任何争论。

<强> producer.pl

#!/usr/bin/perl
use strict;
use warnings 'all';
use CGI;

open my $fh, '>', 'product.data' or die $!;
print $fh "lots of data\n";
close $fh;

<强> consumer.pl

#!/usr/bin/perl
use strict;
use warnings 'all';
use CGI;

my $q = CGI->new;
print $q->header('text/plain');

open my $fh, '<', 'product.data' or die $!;
while my $line (<$fh>) {
    print $line;
}

exit;

这是简化得到的。有一个脚本可以创建数据,另一个脚本可以使用它。现在我们需要在不实际运行它们的情况下进行这两个交互。

让我们前进并假设我们已经重构了这两个脚本并将它们转换为模块。我们稍后会看到它是如何工作的。我们现在可以在新的 foo.pl 脚本中使用这些模块。它将处理请求,向生产者询问数据并让消费者将数据转换为读者想要的格式。

<强> foo.pl

#!/usr/bin/perl
use strict;
use warnings 'all';
use Producer; # this was producer.pl
use Consumer; # this was consumer.pl
use CGI;

my $q = CGI->new;

my $params; # those would come from $q and are the parameters for the producer

my $product = Producer::produce($params);
my $output = Consumer::consume($product);

print $q->header;
print $output;

exit;

这非常简单。我们从CGI读取参数,将它们传递给生产者,并将产品传递给消费者。这给了我们输出,我们打印输出,然后返回到服务器,发送响应。

让我们来看看我们如何将两个脚本转换为简单的模块。那些不需要面向对象,尽管这可能是首选。请注意,文件名的拼写现在是不同的。模块名称通常以大写字母开头。

<强> Producer.pm

package Producer;
use strict;
use warnings 'all';

sub produce {
    my @args = @_;

    return "lots of data\n";
}

1;

<强> Consumer.pm

package Consumer;
use strict;
use warnings 'all';

sub consume {
    my ($data) = @_;

    return $data; # this is really simple
}

1;

现在,如果调用正确的函数,我们有两个与脚本相同的模块。我所做的就是在顶部放置一个名称空间(package)并将代码包装在sub中。我也删除了CGI部分。

在我们的示例中,生产者不必写入文件。它只能返回数据结构。消费者反过来不需要从文件中读取。它只需要一个带有数据结构的变量,并为它提供东西来呈现它。

如果您坚持使用一致的函数名称(例如produceconsume,更好),您甚至可以编写多个生产者或消费者。我们在这里基本上定义了一个接口。这使我们有可能在不破坏兼容性的情况下重构代码的内部,但也可以坚持完全不同的生产者或消费者。只要您坚持使用界面,就可以从单行字符串生成器切换到在心跳中查找数据库中的内容的生成器。

基本上,我们刚才所做的也可以这样显示:

+--foo.pl---------------------------+
|                                   |
|  +------+        +-------------+  |
|  |      | +----> |             |  |
|  |      |        |  Producer   |  |
|  |      | <----+ |             |  |
|  | main |        +-------------+  |
|  | foo  |                         |
|  | body |        +-------------+  |
|  |      | +----> |             |  |
|  |      |        |  Consumer   |  |
|  |      | <----+ |             |  |
|  +------+        +-------------+  |
|                                   |
+-----------------------------------+

这可能看起来有点熟悉。它本质上是Model-View-Controller(MVC)模式。在网络环境中,模型和视图通常只通过控制器相互通信,但它几乎相同。

我们的制作人是数据模型。消费者将数据转换为用户可以看到的网站,因此它是视图。 foo.pl中的主程序将两者粘合在一起控制着数据流。它是控制器

触发整个事物的初始网站可以是程序的一部分,如果没有传递参数则显示,或者可以是独立的.html文件。这取决于你。

使用普通的旧CGI可以实现所有这一切。您不需要使用任何Web框架。但随着您的应用程序的发展,您将看到现代化的框架让您的生活更轻松。

使用http://asciiflow.com/

创建的图表