凌峰创科服务平台

Delphi Web服务器源码如何实现核心功能?

我们将使用 Delphi 中最现代、功能最强大的 Web 服务器框架:WebBroker

Delphi Web服务器源码如何实现核心功能?-图1
(图片来源网络,侵删)

什么是 WebBroker?

WebBroker 是 Delphi 自带的、用于创建 Web 应用程序的框架,它诞生于 CGI 时代,但现在已经演变得非常强大,可以创建 ISAPI/NSAPI 模块、Windows 服务以及独立的 HTTP 服务器,它的工作流程可以概括为:

  1. HTTP 服务器:接收来自浏览器的 HTTP 请求。
  2. 分发器:根据请求的 URL 路径,将请求分发给对应的 Web 模块
  3. Web 模块:这是核心容器,它包含一个或多个页面生成器
  4. 页面生成器:通常是一个 TWebActionItem,它根据请求执行特定逻辑,并生成响应内容(HTML、JSON、XML 等)。
  5. 响应:将生成的内容通过 HTTP 协议返回给浏览器。

第一步:创建项目

我们将创建一个独立的 HTTP 服务器,这样最简单,无需配置 IIS 或 Apache。

  1. 打开 Delphi (以 RAD Studio 11 Alexandria 为例,其他版本类似)。
  2. 选择 File -> New -> VCL Forms Application - Delphi
  3. 在窗体上,从 Internet 选项卡中拖拽一个 THTTPApp 组件到窗体上,这个组件是 WebBroker 应用的核心。
  4. 选中窗体上的 THTTPApp 组件,在对象检查器中找到 Dispatcher 属性,点击其省略号 按钮。
  5. 这将打开 Web 调度编辑器,这是我们配置 URL 路由和响应逻辑的地方。
  6. 点击 Add 按钮,添加一个新的 TWebActionItem
    • Name: actHelloWorld
    • PathInfo: /hello (这是用户需要访问的路径)
    • MethodType: mtGET (表示这个路径只响应 GET 请求)
  7. 双击 actHelloWorld,在代码编辑器中会自动生成 actHelloWorldAction 事件处理程序,这是我们的核心逻辑。

第二步:编写服务器端源码

我们将编写完整的代码,这包括主窗体、Web 调度逻辑以及一个简单的数据访问示例。

主窗体单元 (Unit1.pas)

这是程序的入口点,负责启动 Web 服务器。

Delphi Web服务器源码如何实现核心功能?-图2
(图片来源网络,侵删)
unit Unit1;
interface
uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, IdHTTPWebBrokerBridge, Web.HTTPApp;
type
  TForm1 = class(TForm)
    HTTPApp1: THTTPApp;
    procedure FormCreate(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
  private
    { Private declarations }
    FServer: TIdHTTPWebBrokerBridge;
  public
    { Public declarations }
  end;
var
  Form1: TForm1;
implementation
{$R *.dfm}
uses
  WebModuleUnit1; // 引入我们的 Web 模块单元
procedure TForm1.FormCreate(Sender: TObject);
begin
  FServer := TIdHTTPWebBrokerBridge.Create(Self);
  FServer.DefaultPort := 8080; // 设置服务器监听端口
  FServer.Active := True;      // 启动服务器
  ShowMessage('Web Server started on http://localhost:8080');
end;
procedure TForm1.FormDestroy(Sender: TObject);
begin
  if Assigned(FServer) then
  begin
    FServer.Active := False;
    FServer.Free;
  end;
end;
end.

Web 模块单元 (WebModuleUnit1.pas)

这是处理所有 Web 请求的核心模块,Delphi 在创建项目时通常会自动生成这个文件。

unit WebModuleUnit1;
interface
uses
  System.SysUtils, System.Classes, Web.HTTPApp, Web.HTTPProd;
type
  TWebModule1 = class(TWebModule)
    WebDispatcher1: TWebDispatcher;
    procedure WebModule1DefaultHandlerAction(Sender: TObject; Request: TWebRequest; Response: TWebResponse; var Handled: Boolean);
    procedure WebModule1actHelloWorldAction(Sender: TObject; Request: TWebRequest; Response: TWebResponse; var Handled: Boolean);
    procedure WebModule1actUsersAction(Sender: TObject; Request: TWebRequest; Response: TWebResponse; var Handled: Boolean);
  private
    { Private declarations }
  public
    { Public declarations }
  end;
var
  WebModule1: TWebModule1;
implementation
{$R *.dfm}
uses
  System.JSON; // 用于生成 JSON 响应
// 默认处理器,当访问的路径不存在时触发
procedure TWebModule1.WebModule1DefaultHandlerAction(Sender: TObject; Request: TWebRequest; Response: TWebResponse; var Handled: Boolean);
begin
  Response.Content := '<h1>Delphi Web Server</h1>' +
                      '<p>Welcome to the Delphi WebBroker server.</p>' +
                      '<p>Available endpoints:</p>' +
                      '<ul>' +
                      '  <li><a href="/hello">/hello</a> - A simple HTML page.</li>' +
                      '  <li><a href="/users">/users</a> - A JSON list of users.</li>' +
                      '</ul>';
end;
// 处理 /hello 路径
procedure TWebModule1.WebModule1actHelloWorldAction(Sender: TObject; Request: TWebRequest; Response: TWebResponse; var Handled: Boolean);
begin
  Response.ContentType := 'text/html';
  Response.Content := '<!DOCTYPE html>' +
                      '<html>' +
                      '<head><title>Hello from Delphi!</title></head>' +
                      '<body>' +
                      '  <h1>Hello, World!</h1>' +
                      '  <p>This page was served by a Delphi WebBroker server.</p>' +
                      '  <p>The current time is: ' + FormatDateTime('yyyy-mm-dd hh:nn:ss', Now) + '</p>' +
                      '</body>' +
                      '</html>';
end;
// 处理 /users 路径,返回 JSON 数据
procedure TWebModule1.WebModule1actUsersAction(Sender: TObject; Request: TWebRequest; Response: TWebResponse; var Handled: Boolean);
var
  jsonList: TJSONArray;
  jsonObj: TJSONObject;
  i: Integer;
begin
  // 创建一个 JSON 数组
  jsonList := TJSONArray.Create;
  // 模拟从数据库获取数据
  for i := 1 to 5 do
  begin
    jsonObj := TJSONObject.Create;
    jsonObj.AddPair('id', TJSONNumber.Create(i));
    jsonObj.AddPair('name', TJSONString.Create('User ' + IntToStr(i)));
    jsonObj.AddPair('email', TJSONString.Format('user%d@example.com', [i]));
    jsonList.AddElement(jsonObj);
  end;
  // 设置响应内容类型为 JSON
  Response.ContentType := 'application/json';
  // 将 JSON 数组转换为字符串并设置为响应内容
  Response.Content := jsonList.ToString;
  // 释放 JSON 对象 (在实际应用中,你可能需要更复杂的生命周期管理)
  jsonList.Free;
end;
end.

窗体文件 (Unit1.dfm)

这个文件是自动生成的,通常不需要修改。

object Form1: TForm1
  Left = 0
  Top = 0
  Caption = 'Delphi Web Server'
  ClientHeight = 299
  ClientWidth = 647
  Color = clBtnFace
  Font.Charset = DEFAULT_CHARSET
  Font.Color = clWindowText
  Font.Height = -11
  Font.Name = 'Tahoma'
  Font.Style = []
  OldCreateOrder = False
  OnCreate = FormCreate
  OnDestroy = FormDestroy
  PixelsPerInch = 96
  TextHeight = 13
  object HTTPApp1: THTTPApp
    Left = 48
    Top = 24
  end
end

第三步:运行和测试

  1. F9 运行项目。

  2. 程序会弹出一个消息框:“Web Server started on http://localhost:8080”,并在后台启动服务器。

    Delphi Web服务器源码如何实现核心功能?-图3
    (图片来源网络,侵删)
  3. 打开你的网页浏览器,访问以下地址:

    • http://localhost:8080 你会看到默认的欢迎页面,列出了可用的 API 端点。

    • http://localhost:8080/hello 你会看到一个动态生成的 HTML 页面,显示 "Hello, World!" 和当前服务器时间。

    • http://localhost:8080/users 你会看到一个 JSON 格式的用户列表,这是典型的 API 响应。


第四步:进阶与扩展

这个简单的例子展示了 WebBroker 的基本功能,一个真实的 Web 服务器还需要更多功能:

集成数据库

要连接数据库(如 Firebird, MySQL, SQL Server, SQLite),你需要:

  1. uses 子句中添加数据库连接组件的单元,FireDAC.Comp.Client, FireDAC.Comp.DataSet
  2. TWebActionItem 的事件处理程序中,创建 TFDConnection, TFDQuery 等组件。
  3. 执行 SQL 查询,并将结果集转换为 JSON。

示例代码片段 (在 actUsersAction 中):

// 在 uses 中加入 FireDAC 单元
// uses ..., FireDAC.Comp.Client, FireDAC.Comp.DataSet, FireDAC.Stan.Def;
// ... 在 actUsersAction 中 ...
var
  jsonList: TJSONArray;
  jsonObj: TJSONObject;
  qry: TFDQuery;
begin
  jsonList := TJSONArray.Create;
  qry := TFDQuery.Create(nil);
  try
    qry.Connection := FDConnection1; // 假设你已经配置好了 FDConnection1
    qry.SQL.Text := 'SELECT id, name, email FROM users';
    qry.Open;
    while not qry.Eof do
    begin
      jsonObj := TJSONObject.Create;
      jsonObj.AddPair('id', TJSONNumber.Create(qry.FieldByName('id').AsInteger));
      jsonObj.AddPair('name', TJSONString.Create(qry.FieldByName('name').AsString));
      jsonObj.AddPair('email', TJSONString.Create(qry.FieldByName('email').AsString));
      jsonList.AddElement(jsonObj);
      qry.Next;
    end;
  finally
    qry.Free;
  end;
  Response.ContentType := 'application/json';
  Response.Content := jsonList.ToString;
  jsonList.Free;
end;

使用 REST 格式 (更现代的 API)

现代 API 通常使用 RESTful 风格,URL 如 /api/users/123,你可以通过修改 TWebActionItemPathInfo 来实现。

  • PathInfo: /api/users/* (星号是通配符)
  • 在事件处理程序中,你可以从 Request.PathInfo 中获取 123 这个 ID。
procedure TWebModule1.WebModule1actUserDetailAction(Sender: TObject; Request: TWebRequest; Response: TWebResponse; var Handled: Boolean);
var
  userId: string;
  // ... 数据库查询逻辑
begin
  // 从 /api/users/123 中提取 ID
  userId := Request.PathInfo.Substring(11); // 跳过 "/api/users/" 部分
  Response.Content := 'Fetching details for User ID: ' + userId;
end;

静态文件服务

WebBroker 默认不提供静态文件(如 CSS, JS, 图片)服务,你需要自己实现一个处理程序来检查文件是否存在,如果存在就读取并返回。

procedure TWebModule1.WebModule1StaticFileAction(Sender: TObject; Request: TWebRequest; Response: TWebResponse; var Handled: Boolean);
var
  filePath: string;
  fileStream: TFileStream;
begin
  // 假设所有静态文件都在 "public" 文件夹下
  filePath := ExtractFilePath(ParamStr(0)) + 'public' + Request.PathInfo;
  if FileExists(filePath) then
  begin
    fileStream := TFileStream.Create(filePath, fmOpenRead or fmShareDenyNone);
    try
      Response.ContentType := GetMIMEType(filePath); // 需要一个函数来根据扩展名返回 MIME 类型
      Response.ContentStream := fileStream;
      fileStream := nil; // 转移所有权给 Response
    finally
      if Assigned(fileStream) then
        fileStream.Free;
    end;
  end
  else
  begin
    Response.StatusCode := 404; // Not Found
    Response.Content := 'File not found.';
  end;
  Handled := True;
end;

部署

  • 独立服务器: 你可以直接编译 .exe 文件,在任何 Windows 机器上运行。
  • Windows 服务: 将程序打包成 Windows 服务,可以实现开机自启,并在后台稳定运行。
  • ISAPI/NSAPI 模块: 将程序编译成 .dll 文件,部署在 IIS 或 Apache 上,这是高性能的部署方式。

这份 Delphi Web 服务器源码为你提供了一个坚实的基础,WebBroker 框架虽然看起来有些“传统”,但它非常稳定、高效,并且完全集成在 Delphi 生态中,通过它,你可以构建从简单的网页到复杂的 RESTful API 各种各样的 Web 应用,随着你对 Delphi 更深入的了解,你可以进一步探索 DataSnap(用于构建多层应用)和 MS-Graph(用于构建现代化的 Web 客户端应用)等更高级的主题。

分享:
扫描分享到社交APP
上一篇
下一篇