Erstellen der EMS Pets-Ressource

Aus RAD Studio
Wechseln zu: Navigation, Suche

Nach oben zu Tutorial: Verwenden eines EMS-Clients für den Zugriff auf eine benutzerdefinierte EMS-Ressource

Erstellen Sie für dieses Tutorial zunächst eine neue EMS-Ressource, die alle verfügbaren Methoden bereitstellt (weitere Informationen dazu finden Sie unter Übersicht über EMS-Ressourcen), und implementieren Sie sie.

Die EMS Pets-Ressource dieses Tutorials speichert Informationen über Haustiere (wie Name und Art) in einer Datei auf dem EMS-Server. Die EMS Pets-Ressource implementiert die verfügbaren Endpunkte, und die EMS Pets-Client-Anwendung kann die Liste der Haustiere abrufen oder die zu den Tieren gespeicherten Informationen durch Aufruf dieser EMS Pets-Ressourcenendpunkte ändern.

Erstellen der EMS Pets-Ressource

Sie müssen eine neue EMS-Ressource erstellen und die bereitgestellten EMS-Ressourcenendpunkte festlegen. Weitere Informationen finden Sie unter Übersicht über EMS-Ressourcen.

  1. Öffnen Sie in RAD Studio den EMS-Package-Experten.
    • Für Delphi: Datei > Neu > Weitere > Delphi-Projekte > EMS > EMS-Package.
  2. Wählen Sie "Package mit Ressource erstellen".
    EMSPackageWizard1.png
  3. Fügen Sie den Namen und den Dateityp für die EMS-Ressource hinzu:
    • Ressourcenname: Pets
    • Dateityp: Unit
    EMSPackageWizard2.png
  4. Wählen Sie die EMS-Endpunkte aus, die die EMS-Ressource bereitstellt. Wählen Sie für dieses Tutorial alle Endpunkte aus.
    EMSPackageWizard3.png
  5. Klicken Sie auf die Schaltfläche Fertig stellen.
  6. Benennen Sie in der Projektverwaltung die Unit in PetsResource um.
  7. Speichern Sie das Projekt.

Die Registerkarte "Code" enthält den Code für die erstellte EMS-Ressource:

  • Für Delphi:
  [ResourceName('Pets')]
{$METHODINFO ON}

  TPetsResource = class
  private
    FPetsManager: TPetsManager;
    function GetModuleDirectory: string;
    procedure CheckManager;
    function IdFromRequest(const ARequest: TEndpointRequest): Integer;
  public
    destructor Destroy; override;
  published
    [EndpointName('GetPets')]
    procedure Get(const AContext: TEndpointContext; const ARequest: TEndpointRequest; const AResponse: TEndpointResponse);
    [EndpointName('GetPet')]
    [ResourceSuffix('{item}')]
    procedure GetItem(const AContext: TEndpointContext; const ARequest: TEndpointRequest; const AResponse: TEndpointResponse);
    [EndpointName('AddPet')]
    procedure Post(const AContext: TEndpointContext; const ARequest: TEndpointRequest; const AResponse: TEndpointResponse);
    [EndpointName('UpdatePet')]
    [ResourceSuffix('{item}')]
    procedure PutItem(const AContext: TEndpointContext; const ARequest: TEndpointRequest; const AResponse: TEndpointResponse);
    [EndpointName('DeletePet')]
    [ResourceSuffix('{item}')]
    procedure DeleteItem(const AContext: TEndpointContext; const ARequest: TEndpointRequest; const AResponse: TEndpointResponse);
  end;
{$METHODINFO OFF}

procedure Register;

Erstellen des Pet-Typs

Sie müssen ein benutzerdefiniertes Objekt erstellen, das zwischen dem EMS-Client und den EMS-Server-Endpunktmethoden anhand von JSON-Objekten übergeben wird.

Hinweis: Sie müssen diese Daten-Unit in der EMS-Client-Anwendung verwenden, um die Daten zu serialisieren.

Erstellen Sie wie folgt eine neue Pet type-Unit für Ihre Anwendung:

  1. Klicken Sie in der Projektverwaltung mit der rechten Maustaste auf das Projekt, und wählen Sie | Neue hinzufügen > Unit.
  2. Benennen Sie die Unit in PetType um.
  3. Erstellen Sie wie folgt den neuen Record TPet:
    • Für Delphi:
     TPet = record
      private
        FId: integer;
        FKind: string;
        FName: string;
      public
        constructor Create(const AId: Integer; const AName, AKind: string);
        property Name: string read FName write FName;
        property Kind: string read FKind write FKind;
        property Id: integer read FId write FId;
      end;
    
  4. Fügen Sie der Unit den folgenden Code hinzu:
    • Für Delphi:
    constructor TPet.Create(const AId: integer; const AName, AKind: string);
    begin
      FName := AName;
      FKind := AKind;
      FId := AId;
    end;
    
  5. Sie müssen in Ihrer Unit die Klasse TPetJSON erstellen, um das Pet-Objekt zu serialisieren. Definieren Sie es wie folgt:
    • Für Delphi:
     TPetJSON = class
      public
       class function JSONToPet(const AJSON: TJSONValue): TPet; static;
       class function JSONToPets(const AJSON: TJSONArray): TArray<TPet>; static;
       class procedure PetsToJSON(const APets: TArray<TPet>; const AJSON: TJSONArray); static;
       class procedure PetToJSON(const APet: TPet; const AJSON: TJSONObject); static;
      end;
    
  6. Fügen Sie die folgenden uses-Klauseln hinzu:
    • Für Delphi:
    	uses System.JSON, System.Generics.Collections;
    
  7. Implementieren Sie die Methoden Ihrer Unit.
    • Für Delphi:
    class function TPetJSON.JSONToPet(const AJSON: TJSONValue): TPet;
    begin
      Result := TPet.Create(AJSON.GetValue<integer>('id'),
        AJSON.GetValue<string>('kind'), AJSON.GetValue<string>('name'));
    end;
    
    class procedure TPetJSON.PetToJSON(const APet: TPet; const AJSON: TJSONObject);
    begin
      AJSON.AddPair('id', TJSONNumber.Create(APet.FId));
      AJSON.AddPair('kind', TJSONString.Create(APet.FKind));
      AJSON.AddPair('name', TJSONString.Create(APet.FName));
    end;
    
    class function TPetJSON.JSONToPets(const AJSON: TJSONArray)
      : TArray<TPet>;
    var
      LValue: TJSONValue;
      LList: TList<TPet>;
    begin
      LList := TList<TPet>.Create;
      try
        for LValue in AJSON do
          LList.Add(TPetJSON.JSONToPet(LValue));
        Result := LList.ToArray;
      finally
        LList.Free;
      end;
    end;
    
    class procedure TPetJSON.PetsToJSON(const APets: TArray<TPet>;
      const AJSON: TJSONArray);
    var
      LPet: TPet;
      LJSONObject: TJSONObject;
    begin
      for LPet in APets do
      begin
        LJSONObject := TJSONObject.Create;
        PetToJSON(LPet, LJSONObject);
        AJSON.Add(LJSONObject);
      end;
    end;
    

Hinzufügen des Pets-Managers

In diesem Tutorial werden die Pets-Daten in einer Datei (pets.ini) auf dem EMS-Server gespeichert. Um auf die Daten dieser Datei zuzugreifen und sie zu verwalten, wird die neue Unit PetsManager in der EMS Pets-Ressource erstellt.

  1. Klicken Sie in der Projektverwaltung mit der rechten Maustaste auf das Projekt, und wählen Sie Neue hinzufügen > Unit
  2. Benennen Sie die Unit in PetsManager um.
  3. Erstellen Sie wie folgt die neue Klasse TPetsManager:
    • Für Delphi:
    type
      TPetsManager = class
        FUserID: string;
        FIniFile: TIniFile;
      private
        function EncodePet(const AName: string; const AKind: string): string;
        function DecodePetLine(const ALine: string; const AField: integer): string;
      public
        constructor Create(const ADirectory: string);
        destructor Destroy; override;
        function GetPets: TArray<TPet>;
        function GetPet(const AId: Integer; out APet: TPet): Boolean;
        procedure UpdatePet(const AId: Integer; const APet: TPet);
        procedure AddPet(const APet: TPet);
        function DeletePet(const AId: Integer): Boolean;
        function PetExists(const AId: Integer): Boolean;
      end;
    
  4. Fügen Sie die folgenden uses-Klauseln hinzu:
    • Für Delphi:
    uses
      System.SysUtils, System.IniFiles, System.Generics.Collections, PetType,
      System.Classes, System.StrUtils, System.Types;
    
  5. Fügen Sie der Unit den folgenden Code hinzu:
    • Für Delphi:
    constructor TPetsManager.Create(const ADirectory: string);
    var
      LPath: string;
    begin
      LPath := IncludeTrailingPathDelimiter(ExpandFileName(ADirectory)) + 'pets.ini';
      FIniFile := TIniFile.Create(LPath);
      FUserID := '0000';
    end;
    
    // Procedure to add a pet to the pets.ini file
    procedure TPetsManager.AddPet(const APet: TPet);
    begin
      FIniFile.WriteString(FUserID, APet.Id.ToString, EncodePet(APet.Name, APet.Kind));
    end;
    
    // Function to check if a pet exists in the pets.ini file
    function TPetsManager.PetExists(const AId: Integer): Boolean;
    begin
      Result := FIniFile.ValueExists(FUserID, AId.ToString);
    end;
    
    // Function to delete a pet from the pets.ini file
    function TPetsManager.DeletePet(const AId: Integer): Boolean;
    begin
      Result := PetExists(AId);
      if Result then
        FIniFile.DeleteKey(FUserID, AId.ToString);
    end;
    
    // Destructor
    destructor TPetsManager.Destroy;
    begin
      FIniFile.Free;
      inherited;
    end;
    
    // Function to get a specific pet from the pets.ini file
    function TPetsManager.GetPet(const AId: Integer; out APet: TPet): Boolean;
    var
      LName: string;
      LKind: string;
    begin
      Result := PetExists(AId);
      if Result then
      begin
        LName := DecodePetLine(FIniFile.ReadString(FUserID, AId.ToString, ''), 1);
        LKind := DecodePetLine(FIniFile.ReadString(FUserID, AId.ToString, ''), 0);
        APet := TPet.Create(AId, LName, LKind);
      end;
    end;
    
    // Function to get all pets from the pets.ini file
    function TPetsManager.GetPets: TArray<TPet>;
    var
      LList: TList<TPet>;
      LPet: TPet;
      LSection: TStrings;
      I: integer;
    begin
      LSection := nil;
      LList := nil;
      try
        LSection := TStringList.Create;
        LList := TList<TPet>.Create;
        FIniFile.ReadSectionValues(FUserID, LSection);
        for I := 0 to LSection.Count - 1 do
        begin
          LPet := TPet.Create(LSection.Names[I].ToInteger,
            DecodePetLine(LSection.ValueFromIndex[I], 1),
            DecodePetLine(LSection.ValueFromIndex[I], 0));
          LList.Add(LPet);
        end;
        Result := LList.ToArray;
      finally
        LList.Free;
        LSection.Free;
      end;
    end;
    
    // Function to update a pet from the pets.ini file
    procedure TPetsManager.UpdatePet(const AId: Integer; const APet: TPet);
    begin
      if PetExists(AId) then
        FIniFile.DeleteKey(FUserID, AId.ToString);
      FIniFile.WriteString(FUserID, AId.ToString, EncodePet(APet.Name, APet.Kind));
    end;
    
    // Function to encode the data (to be saved in the pets.ini file)
    function TPetsManager.EncodePet(const AName: string;
      const AKind: string): string;
    var
      LPet: string;
    begin
      LPet := AName + ',' + AKind;
      Result := LPet;
    end;
    // Function to decode a line from the pets.ini file
    function TPetsManager.DecodePetLine(const ALine: string;
      const AField: integer): string;
    var
      LPetField: TStringDynArray;
    begin
      LPetField := SplitString(ALine, ',');
      Result := LPetField[AField];
    end;
    

Hinzufügen der Implementierung zu den EMS-Ressourcenendpunkten

Sie müssen die Implementierung der EMS-Endpunktmethoden hinzufügen.

  1. Fügen Sie die folgenden uses-Klauseln hinzu:
    • Für Delphi:
       uses PetType, PetsManager;
    
  2. Erstellen Sie in Ihrer EMS-Ressource die folgende private-Variable:
    • Für Delphi:
    private
        FPetsManager: TPetsManager;
    
  3. Fügen Sie der Unit den folgenden Code hinzu:
    • Für Delphi:
    procedure TPetsResource.Get(const AContext: TEndpointContext; const ARequest: TEndpointRequest; const AResponse: TEndpointResponse);
    var
      LPets: TArray<TPet>;
      LJSON: TJSONArray;
    begin
      LJSON := nil;
      try
        CheckManager;
        LPets := FPetsManager.GetPets;
        LJSON := TJSONArray.Create;
        TPetJSON.PetsToJSON(LPets, LJSON);
        AResponse.Body.SetValue(LJSON, True)
      except
        LJSON.Free;
        raise;
      end;
    end;
    
    
    procedure TPetsResource.GetItem(const AContext: TEndpointContext; const ARequest: TEndpointRequest; const AResponse: TEndpointResponse);
    var
      LId: Integer;
      LPet: TPet;
      LJSON: TJSONObject;
    begin
      LId := IdFromRequest(ARequest);
      CheckManager;
      if FPetsManager.GetPet(LId, LPet) then
      begin
        LJSON := TJSONObject.Create;
        try
          TPetJSON.PetToJSON(LPet, LJSON);
          AResponse.Body.SetValue(LJSON, True);
        except
          LJSON.Free;
          raise;
        end;
      end
      else
        AResponse.RaiseNotFound('', Format('Id not found: %d', [LId]));
    end;
    
    procedure TPetsResource.Post(const AContext: TEndpointContext; const ARequest: TEndpointRequest; const AResponse: TEndpointResponse);
    var
      LJSON: TJSONObject;
      LPet: TPet;
    begin
      if ARequest.Body.TryGetObject(LJSON) then
      begin
        CheckManager;
        LPet := TPetJSON.JSONToPet(LJSON);
        if FPetsManager.PetExists(LPet.Id) then
          AResponse.RaiseDuplicate('', Format('Can not add duplicate Id: %d', [LPet.Id]));
        FPetsManager.AddPet(LPet);
      end
      else
        AResponse.RaiseBadRequest('', 'JSON expected');
    end;
    
    procedure TPetsResource.PutItem(const AContext: TEndpointContext; const ARequest: TEndpointRequest; const AResponse: TEndpointResponse);
    var
      LId: Integer;
      LPet: TPet;
      LJSON: TJSONObject;
    begin
      LId := IdFromRequest(ARequest);
      if ARequest.Body.TryGetObject(LJSON) then
      begin
        CheckManager;
        LPet := TPetJSON.JSONToPet(LJSON);
        if not FPetsManager.PetExists(LId) then
          AResponse.RaiseNotFound('', Format('Can not update unknown Id: %d', [LId]));
        FPetsManager.UpdatePet(LId, LPet);
      end
      else
        AResponse.RaiseBadRequest('', 'JSON expected');
    end;
    
    procedure TPetsResource.CheckManager;
    begin
      if FPetsManager = nil then
        FPetsManager := TPetsManager.Create(GetModuleDirectory);
    end;
    
    procedure TPetsResource.DeleteItem(const AContext: TEndpointContext; const ARequest: TEndpointRequest; const AResponse: TEndpointResponse);
    var
      LId: Integer;
    begin
      LId := IdFromRequest(ARequest);
      CheckManager;
      if not FPetsManager.DeletePet(LId) then
        AResponse.RaiseNotFound('', Format('Can not delete unknown Id: %d', [LId]));
    end;
    
    destructor TPetsResource.Destroy;
    begin
      FPetsManager.Free;
      inherited;
    end;
    
    function TPetsResource.GetModuleDirectory: string;
    begin
      Result := ExtractFilePath(StringReplace(GetModuleName(HInstance), '\\?\', '', [rfReplaceAll]));
    end;
    
    function TPetsResource.IdFromRequest(const ARequest: TEndpointRequest): Integer;
    var
      LItem: string;
    begin
      LItem := ARequest.Params.Values['item'];
      if not TryStrToInt(LItem, Result) then
        EEMSHTTPError.RaiseBadRequest('', Format('Id is not an integer: "%s"', [LItem]));
    end;
    
    procedure Register;
    begin
      RegisterResource(TypeInfo(TPetsResource));
    end;
    

Laden der EMS-Ressource auf den EMS-Server

Der EMS-Server lädt die EMS Pets-Ressource und stellt die EMS Pets-Ressourcenendpunkt für die EMS-Client-Anwendungen bereit.

  1. Überprüfen Sie, ob der EMS-Server in Ihrem System eingerichtet ist.
  2. Drücken Sie F9, oder wählen Sie Start > Start, um die EMS Pets-Ressource zu laden.

Das Fenster des EMS-Entwicklungsservers wird geöffnet. Im Protokollbereich können Sie das Laden der EMS Pets-Ressource verfolgen.

{"Load":{"Filename":"C:\Users\Public\Documents\Embarcadero\Studio\15.0\Bpl\PetsResourcePackage.bpl","Thread":4072}}
{"RegUnit":{"Filename":"C:\Users\Public\Documents\Embarcadero\Studio\15.0\Bpl\PetsResourcePackage.bpl","Filename":"PetsResource","Thread":4072}}
{"RegResource":{"Resource":"Pets","Endpoints":["GetPets","GetPet","AddPet","UpdatePet","DeletePet"],"Thread":4072}}
EMSServerPetsResource.png

Siehe auch