用 18 行代码实现的数据库驱动的 Web 应用程序
Linux、Apache、MySQL 和编程技术(通常是 Perl、Python 或 PHP)的 LAMP 组合非常强大。但是,一旦您构建了一个基于 Web 的数据库应用程序,您就构建了所有这些应用程序。从程序员的角度来看,事情很快变得枯燥和重复。
我最近从事我的第一个 Web 应用程序。当然,我是在 Linux 上构建的,通过 Apache 运行并与 MySQL 通信。我使用 Perl 作为我的粘合剂语言,CGI 在其中占据重要地位。我创建了所有代码来与 MySQL 表通信,根据需要添加/编辑/更新。而且一切都正常工作,这很好。糟糕的是,我面临着为数据库中的其余每个表重复这项活动(和努力)。在 Perl 程序员的悠久传统中,我开始寻找建设性偷懒的方法。一定有更好的方法。经过几次错误的开始和一些搜索,我找到了 Maypole。
Maypole 最初由 Simon Cozens 创建并由 Sebastian Riedel 维护,是一个用于 Web 应用程序的快速应用程序开发框架。Maypole 的主页承诺用大约 20 行 Perl 代码实现一个功能齐全的应用程序。这听起来太好了,不能不尝试。
在尝试了 Maypole 之后,我可以确认 Simon 和 Sebastian 没有撒谎。只需要几行代码就可以构建一个非常实用的应用程序。需要进行一些设置,但至关重要的是,此活动不是编程。一旦设置完成,就可以创建任意数量的应用程序,每个应用程序只需几行代码。在本文的其余部分,我将逐步指导您使用 Maypole 构建应用程序。
这一步过去需要整篇文章来描述。今天,一句话概括了。选择您最喜欢的发行版并安装它。
最近收到一台新 PC 后,我抓取了 Fedora Core 3 并自定义安装了所有内容。如果您没有这种奢侈,请务必从您选择的发行版中安装以下软件包:httpd、httpd-devel、mod_perl、mod_perl-devel、mysql(客户端和服务器)和 Perl。
现代发行版越来越多地发布 Apache 版本 2 和 mod_perl 版本 1.99,而不是根深蒂固的 Apache 1.3.x 版本。值得庆幸的是,Maypole 可以与任何版本的 Apache 一起使用,也可以配置为使用 CGI(如果 mod_perl 不可用)。我的 Fedora 安装附带了 Apache 2.0.52 版本和 mod_perl 1.99_16-3 版本,所以这就是我在这里使用的。Maypole 邮件列表上的用户报告说,在绝大多数 Linux 平台上都成功安装了,包括 SuSE、Debian 和 Red Hat。Maypole 也可以安装在 Apple 的 Mac OS X 上,并且通过一些额外的努力,也可以安装在 Microsoft 的 Windows 上。
作为 root 用户,我编辑了 Fedora 的 Apache 配置文件 /etc/httpd/conf/httpd.conf 并注释掉了 ServerTokens 指令。然后,我安排在启动时自动启动 Apache,并使用以下命令启动了 Web 服务器
chkconfig httpd on service httpd start
lynx 基于文本的浏览器可用于使用以下命令检查服务器状态
lynx -head -dump https://127.0.0.1/
结果确认 Apache 和 mod_perl 正在运行,如该输出的第三行所示
HTTP/1.1 403 Forbidden Date: Wed, 17 Nov 2004 23:30:01 GMT Server: Apache/2.0.52 (Fedora) mod_perl/1.99_16 Perl/v5.8.5 DAV/2 Accept-Ranges: bytes Content-Length: 3931 Connection: close Content-Type: text/html; charset=UTF-8
很高兴一切正常,我重新编辑了 httpd.conf 并取消注释了 ServerTokens 指令,因为最好不要过多泄露有关您的 Web 服务器内部信息给潜在的攻击者。在 httpd.conf 中,我将 ServerAdmin 指令更改为更合适的电子邮件地址,然后将 ServerName 设置为我的服务器的 DNS 名称。我还记下了 DocumentRoot 设置的值,在我的机器上是 /var/www/html。
根据您运行的发行版,可能已经安装了 MySQL。如果缺少 MySQL,请从您发行版的下载区域下载它,或者访问 MySQL 网站。在我的 Fedora 机器上,我以 root 用户身份登录并发出常用命令来准备 MySQL 以供使用
chkconfig mysqld on service mysqld start
MySQL 运行后,我设置了 MySQL 管理员密码
mysqladmin -u root password 'passwordhere'
Maypole 通过 mod_perl 直接与 Apache 交互。为了与 Apache 2 一起使用,需要从 CPAN 存储库获取一个名为 libapreq2 的开发库并将其安装到 Perl 中。我从 CPAN 下载了 libapreq2-2.04_03-dev.tar.gz。在安装该库之前,我升级了 Perl 附带的 ExtUtils::XSBuilder 模块。只需一个命令,以 root 用户身份发出即可
perl -MCPAN -e "install ExtUtils::XSBuilder"
如果这是 CPAN shell 首次执行,系统将提示您配置本地 CPAN 模块。当被问及是否获取先决模块时,请务必选择 follow。模块升级后,我使用常用的一组 Perl 模块安装命令安装了 libapreq2 库
tar zxvf libapreq2-2.04_03-dev.tar.gz cd libapreq2-2.04-dev/ perl Makefile.PL make make test su make install <Ctrl-D>
Maypole 的实际安装首先以 root 用户身份调用 CPAN shell
perl -MCPAN -e "shell"
由于 Maypole 依赖于大量的先决 CPAN 模块,因此安装可能需要一段时间。在实际要求 CPAN shell 为您安装 Maypole 之前,请发出以下命令以确保处理一些更麻烦的模块
cpan> install CGI::Untaint::date cpan> force install Class::DBI::mysql
我不得不强制安装 Class::DBI::mysql,因为许多测试失败,有效地中止了自动安装。通过强制安装,将忽略损坏的测试,从而允许安装继续进行。处理完先决条件后,使用此 CPAN 命令安装 Maypole
cpan> install Maypole
在此步骤之后,将开始一系列与 CPAN 存储库的自动交互。密切关注正在发生的事情,因为在某些时候,您必须响应一些不言自明的提示。当一切都完成时,最新版本的 Maypole(在撰写本文时为 2.04)已安装在我的机器上。
返回到 MySQL,我以管理员身份登录并发出以下命令以删除任何默认帐户
mysql -u root -p mysql> use mysql; mysql> delete from user where User = ''; mysql> flush privileges;
然后我创建了一个新数据库,以及一个用户作为数据的所有者
mysql> create database CLUB; mysql> grant all on CLUB.* to manager identified by 'passwordhere'; mysql> quit
这些命令创建了名为 CLUB 的数据库,并将一个名为 manager 的用户添加到数据库系统中。就本文而言,这个简单的应用程序管理有关未成年人足球俱乐部的数据。除了存储每个球员的个人详细信息外,该系统还维护有关哪些球员在哪些球队以及球员可能有的任何医疗状况的数据。
以下是我用于定义 CLUB 数据库中使用的表的 SQL 文件。第一个文件 create_player.sql 创建了 player 表
create table player ( id int not null auto_increment primary key, name varchar (64) not null, date_of_birth date, address varchar (255), contact_tel_no varchar (64), squad int, medical_condition int );
第二个文件 create_squad.sql 创建了球队的初始列表
create table squad ( id int not null auto_increment primary key, name varchar (32) not null ); insert into squad (name) values ('--'); insert into squad (name) values ('Under 8'); insert into squad (name) values ('Under 9'); insert into squad (name) values ('Under 10'); insert into squad (name) values ('Under 11'); insert into squad (name) values ('Under 12');
squad 表初始化为一组合理的默认值。第三个也是最后一个文件 create_condition.sql 创建了可能的医疗状况列表
create table condition ( id int not null auto_increment primary key, name varchar (64) not null ); insert into condition (name) values ('--'); insert into condition (name) values ('Asthma'); insert into condition (name) values ('Epilepsy');
与 squad 表一样,condition 表也使用一些默认数据进行初始化。squad 和 condition 表中的数据项称为 name。本文稍后将返回此点的意义。
使用 SQL 文件在数据库中创建表
mysql -u manager -p CLUB < create_player.sql mysql -u manager -p CLUB < create_squad.sql mysql -u manager -p CLUB < create_condition.sql
可以猜测,CLUB 数据库维护有关球员的数据。球员属于一个球队,并且可能有医疗状况。
数据库准备就绪且 Maypole 安装完成后,就该配置应用程序了。需要在 Apache httpd.conf 配置文件中添加一个指令,以设置 Maypole 应用程序的 mod_perl 处理程序。我在配置文件的末尾添加了以下内容
<Location /Club> SetHandler perl-script PerlHandler ClubDB </Location>
这些行告诉 Apache,当请求 /Club URL 时,应将其交给 ClubDB Perl 脚本,我们将在下一步编写该脚本。使用以下命令(以 root 用户身份)设置 URL 位置
mkdir /var/www/html/Club cd /var/www/html/Club cp -r ~/.cpan/build/Maypole-2.04/templates/* . cp maypole.css ../club.css
首先在 Apache 的根目录下创建了一个目录来包含我的应用程序的 URL,然后我将 Maypole 附带的默认模板复制到此位置。我还将 Maypole 的 CSS 文件复制到我的 Web 服务器的 DocumentRoot 中,并为其指定了一个与我的应用程序对应的名称。
最后一个设置活动涉及在 Apache 的 /etc/httpd/conf 目录中创建一个配置文件,以保存应用程序的 MySQL 用户 ID 和密码。名为 ClubDB.conf 的文件包含以下行
[client] user=manager password=passwordhere
足球俱乐部数据库的代码位于 ClubDB.pm 文件中。每个 Maypole 应用程序都以声明 Perl 命名空间的 package 语句开头。开启 strictness,然后使用名为 Apache::MVC 的基本 Maypole 模块
package ClubDB; use strict; use base 'Apache::MVC';
然后,代码使用命名配置文件中的用户 ID 和密码建立与数据库的连接
ClubDB->setup( "dbi:mysql:CLUB; mysql_read_default_file= /etc/httpd/conf/ClubDB.conf" );
还有几行代码通知 Maypole 应用程序的基本 Web 地址,以及数据库中要提供访问权限的表的列表。对于这个简单的应用程序,为所有表提供访问权限是有意义的
ClubDB->config->{uri_base} = "http://webmason.itcarlow.ie/Club/"; ClubDB->config->{display_tables} = [ qw[ player squad condition ] ];
当涉及到球队时,我的应用程序允许用户查看、编辑或删除球队名称。指定此项需要几行代码,其中一行代码设置了另一个命名空间
package ClubDB::Squad; sub display_columns{ "name" }; ClubDB::Player->untaint_columns( printable => [ "name" ] );
untaint_columns 方法标识了列中预期的数据类型,并向 Maypole 指示可以使用 Web 界面编辑列。医疗状况的处理方式相同
package ClubDB::Condition; sub display_columns{ "name" }; ClubDB::Condition->untaint_columns( printable => [ "name" ] );
player 表的代码更复杂,但也没复杂多少。在声明另一个命名空间之后,对 has_a 方法的两次调用建立了 player 表与其他表之间的链接。链接仅根据声明的命名空间指定
package ClubDB::Player; ClubDB::Player->has_a( squad => "ClubDB::Squad" ); ClubDB::Player->has_a( medical_condition => "ClubDB::Condition" );
对于球员,我们使用 display_columns 方法列出要显示的列。这样做允许程序员控制列在 Web 界面中出现的顺序。如果未使用 display_columns,Maypole 会按字母顺序显示列,这可能并不总是满足您的需求。untaint_columns 的调用标识了可以在每个列中编辑的数据类型。代码以 Perl 熟悉的 1; 结尾,这是所有 Perl 模块都需要的
sub display_columns{ qw( name address date_of_birth contact_tel_no squad medical_condition ) }; ClubDB::Player->untaint_columns( integer => [ "squad", "medical_condition" ], printable => [ "name", "address", "contact_tel_no" ], date => [ "date_of_birth" ] ); 1;
数一下分号。请记住,呈现的代码已格式化为适合印刷页面,总共只有 18 行代码。剩下的就是将 Perl 模块复制到 Apache 和 mod_perl 可以找到它的位置
mkdir -p /etc/httpd/lib/perl/ cp ClubDB.pm /etc/httpd/lib/perl/
在访问 Maypole 应用程序之前重新启动 Apache
service httpd restart
我在 Firefox 位置栏中输入了 http://webmason.itcarlow.ie/Club/,弹出了图 1,虽然是某种东西,但与我期望的并不完全一样。
首先,我期望看到一些漂亮的 CSS 输出,而不是我看到的纯 HTML。为了解决这个问题,我探索了在步骤 6 中复制到 Web 服务器中的默认模板文件。通过更改这些文件,可以更改应用程序的外观,而无需更改应用程序的源代码。最后这句话的重要性怎么强调都不为过。本质上,应用程序的外观由 CSS 模板控制。应用程序的行为由代码控制。应用程序使用的数据由 MySQL 控制。所有这些职责分离创造了一个非常高效的开发环境,因为更改应用程序的一部分不应对其他任何部分产生不利影响。
模板位于名为 factory 的子目录中,该子目录位于应用程序的 URL 下,在本例中为 Club/。工厂模板是 Maypole 默认模板,除非在另一个名为 custom 的目录中找到覆盖模板,否则将使用它们。
在 Club/ URL 下创建 custom 目录后,我将 header 文件从 factory 复制到 custom 并使用 vi 编辑了它。我将 /maypole.css 更改为读取 /club.css,此外还将“配置不当”消息替换为更合适的应用程序描述。我还将 frontpage 文件从 factory 复制到 custom 并对其进行编辑,以使用更好的应用程序描述。然后,我更改了 custom/frontpage 中的锚标记,使其读取“处理球员数据”而不是默认的“按球员列表”文本。完成这些更改后,我单击 Firefox 中的“重新加载”按钮,结果如图 2 所示,我想您会同意,这看起来好多了。
单击任何菜单选项都会生成一个格式精美的输入屏幕,如图 3 和图 4 所示。
图 4 显示了输入两个虚构球员后的显示。请注意免费提供的所有功能。每个表的选项卡都位于显示屏的顶部。只需单击选项卡即可显示该表的数据。每行数据都有一个关联的编辑和删除按钮。单击任何列标题以按该列中的数据对显示进行排序。使用提供的搜索表单执行搜索。使用添加表单添加更多球员。请注意球员球队和医疗状况的下拉菜单。单击字段,将出现一个下拉框,其中包含可供您选择的选项。发生这种奇迹是因为 Maypole 已被告知每个球员“有一个”球队和“有一个”状况。默认情况下,Maypole 使用所引用表中的 name 数据列来为这些下拉框提供数据。
就是这样 - 一个功能齐全的 Web 界面,用于底层数据库,只需八个简单的步骤。
尽管 Maypole 是一个相当新的框架,但一个活跃的社区已经围绕它聚集起来。邮件列表最近已拆分,一个用于开发人员,另一个用于用户,Maypole 网站现在由 perl.org 托管。
正如我希望我已经证明的那样,Maypole(一旦设置好)使用起来非常容易。任何 Web 应用程序的大部分核心功能都是免费提供的。也可以添加其他功能。Maypole 也不仅仅局限于 MySQL,因为可以使用任何 SQL DBMS。有关更多详细信息,请参阅 Maypole 网站上引用的文章和文档。
本文的资源: /article/7964。
Paul Barry (paul.barry@itcarlow.ie) 在爱尔兰卡洛理工学院任教。有关他教授的课程以及他撰写的书籍和文章的信息,可以在他的网站 glasnost.itcarlow.ie/~barryp 上找到。