Verwenden begrenzter Kontexte zum Erstellen einer Java-Anwendung
Was sind begrenzte Kontexte?
Ein begrenzter Kontext ist eines der Kernmuster im Domain-Driven Design (DDD). Es stellt dar, wie ein großes Projekt in Domänen unterteilt wird. Diese Trennung ermöglicht Flexibilität und einfachere Wartung.
Was ist eine sechseckige Architektur?
Die sechseckige Architektur trennt den Kern der Anwendung von ihren externen Abhängigkeiten. Es verwendet Ports und Adapter, um die Geschäftslogik von externen Diensten zu entkoppeln. Durch die Unabhängigkeit der Geschäftslogik von Frameworks, Datenbanken oder Benutzeroberflächen kann die Anwendung problemlos an zukünftige Anforderungen angepasst werden.
Die Architektur besteht aus drei Hauptkomponenten:
- Geschäftsmodell: die Geschäftsregeln und die Kernlogik. Es ist vollständig von externen Abhängigkeiten isoliert und kommuniziert nur über Ports.
- Häfen: Ausstieg und Einstieg in das Geschäftsmodell. Sie trennen den Kern von den äußeren Schichten.
- Adapter: Übersetzen Sie externe Interaktionen (HTTP-Anfragen, Datenbankoperationen) in etwas, das der Kern versteht. Es gibt Eingangsadapter für die eingehende Kommunikation und Ausgangsadapter für die ausgehende Kommunikation.
Warum sechseckige Architektur verwenden?
- Testbarkeit: Sie können Komponententests für die Geschäftslogik schreiben, ohne Datenbanken, externe APIs oder Frameworks zu verspotten.
- Wartbarkeit: Sie können Abhängigkeiten problemlos austauschen, ohne die Kerngeschäftslogik zu beeinträchtigen.
- Skalierbarkeit: unabhängige Skalierung der Ebenen, wodurch die Gesamtleistung verbessert wird.
- Flexibilität: Verschiedene externe Systeme können mit derselben Kernlogik interagieren.
Erstellen einer Anwendung mit Hexagonal Architecture in Java
Dieses Walk-through-Projekt verwendet begrenzte Kontexte und hexagonale Architektur in Java.
Ziel ist die Schaffung eines Ticketingsystems für einen Vergnügungspark namens Techtopia. Das Projekt hat drei Hauptkontexte: Tickets, Attraktionen und Eingangstore. Jeder begrenzte Kontext hat sein Verzeichnis und enthält Komponenten wie in und unsere Ports, Adapter, Anwendungsfälle usw.
Wir werden den Code-Prozess zum Kauf eines Tickets für den Park durchgehen.
- Definieren Sie die Domäne
Erstellen Sie ein „Domänen“-Verzeichnis und schließen Sie die Geschäftslogik ein, frei von jeglichem Framework oder externen Abhängigkeiten.
Erstellen Sie die Entität „Ticket“.
package java.boundedContextA.domain; import lombok.Getter; import lombok.Setter; import lombok.ToString; import java.time.Duration; import java.time.LocalDateTime; import java.util.UUID; @Getter @Setter @ToString public class Ticket { private TicketUUID ticketUUID; private LocalDateTime start; private LocalDateTime end; private double price; private TicketAction ticketAction; private final Guest.GuestUUID owner; private ActivityWindow activityWindow; public record TicketUUID(UUID uuid) { } public Ticket(TicketUUID ticketUUID, Guest.GuestUUID owner) { this.ticketUUID = ticketUUID; this.owner = owner; } public Ticket(TicketUUID ticketUUID, LocalDateTime start, LocalDateTime end, double price, TicketAction ticketAction, Guest.GuestUUID owner) { this.ticketUUID = ticketUUID; this.start = start; this.end = end; this.price = price; this.ticketAction = ticketAction; this.owner = owner; } public Ticket(TicketUUID ticketUUID, LocalDateTime start, LocalDateTime end, double price, Guest.GuestUUID owner, ActivityWindow activityWindow) { this.ticketUUID = ticketUUID; this.start = start; this.end = end; this.price = price; this.owner = owner; this.activityWindow = activityWindow; } public void addTicketActivity(TicketActivity ticketActivity) { this.activityWindow.add(ticketActivity); } }
Erstellen Sie außerdem eine weitere Domänenklasse mit dem Namen "BuyTicket".
package java.boundedContextA.domain; import lombok.Getter; import lombok.Setter; import lombok.ToString; import java.time.Duration; import java.time.LocalDateTime; import java.util.UUID; @Getter @Setter @ToString public class Ticket { private TicketUUID ticketUUID; private LocalDateTime start; private LocalDateTime end; private double price; private TicketAction ticketAction; private final Guest.GuestUUID owner; private ActivityWindow activityWindow; public record TicketUUID(UUID uuid) { } public Ticket(TicketUUID ticketUUID, Guest.GuestUUID owner) { this.ticketUUID = ticketUUID; this.owner = owner; } public Ticket(TicketUUID ticketUUID, LocalDateTime start, LocalDateTime end, double price, TicketAction ticketAction, Guest.GuestUUID owner) { this.ticketUUID = ticketUUID; this.start = start; this.end = end; this.price = price; this.ticketAction = ticketAction; this.owner = owner; } public Ticket(TicketUUID ticketUUID, LocalDateTime start, LocalDateTime end, double price, Guest.GuestUUID owner, ActivityWindow activityWindow) { this.ticketUUID = ticketUUID; this.start = start; this.end = end; this.price = price; this.owner = owner; this.activityWindow = activityWindow; } public void addTicketActivity(TicketActivity ticketActivity) { this.activityWindow.add(ticketActivity); } }
*BuyTicket * stellt die Logik für den Kauf eines Tickets dar. Indem Sie es zu einer separaten Spring-Komponente machen, können Sie die Ticketkauflogik in seiner Klasse isolieren, die sich unabhängig von anderen Komponenten weiterentwickeln kann. Diese Trennung verbessert die Wartbarkeit und macht die Codebasis modularer.
- Ports erstellen
Im Verzeichnis „ports/in“ erstellen Sie Anwendungsfälle. Hier werden wir den Anwendungsfall behandeln, bei dem ein Ticket gekauft wird.
package java.boundedContextA.domain; import org.springframework.stereotype.Component; import java.time.LocalDateTime; import java.util.UUID; @Component public class BuyTicket { public Ticket buyTicket(TicketAction ticketAction, LocalDateTime start, LocalDateTime end, double price, Guest.GuestUUID owner) { return new Ticket(new Ticket.TicketUUID(UUID.randomUUID()), start, end, price, ticketAction, owner); } }
Erstellen Sie einen Datensatz eines Tickets, um es zu speichern.
package java.boundedContextA.ports.in; public interface BuyingATicketUseCase { void buyTicket(BuyTicketsAmountCommand buyTicketsAmountCommand); }
Als nächstes erstellen Sie im Verzeichnis "ports/out" Ports, die jeden Schritt des Ticketkaufs darstellen. Erstellen Sie Schnittstellen wie "CreateTicketPort", "TicketLoadPort", "TicketUpdatePort".
package java.boundedContextA.ports.in; import java.boundedContextA.domain.Guest; import java.boundedContextA.domain.TicketAction; import java.time.LocalDateTime; public record BuyTicketsAmountCommand(double price, TicketAction action, LocalDateTime start, LocalDateTime end, Guest.GuestUUID owner) {}
- Portschnittstellen erstellen
Implementieren Sie in einem separaten Verzeichnis mit dem Namen „core“ die Schnittstelle des Anwendungsfalls „Ticketkauf“.
package java.boundedContextA.ports.out; import java.boundedContextA.domain.Ticket; public interface TicketCreatePort { void createTicket(Ticket ticket); }
- Adapter erstellen
Erstellen Sie im Verzeichnis „adapters/out“ JPA-Entitäten des Tickets, um die Domäne zu spiegeln. Auf diese Weise kommuniziert die Anwendung mit der Datenbank und erstellt eine Tabelle der Tickets.
package java.boundedContextA.core; import java.boundedContextA.domain.BuyTicket; import java.boundedContextA.ports.in.BuyTicketsAmountCommand; import java.boundedContextA.ports.in.BuyingATicketUseCase; import java.boundedContextA.ports.out.TicketCreatePort; import lombok.AllArgsConstructor; import org.springframework.stereotype.Service; import java.util.List; @Service @AllArgsConstructor public class DefaultBuyingATicketUseCase implements BuyingATicketUseCase { final BuyTicket buyTicket; private final List<TicketCreatePort> ticketCreatePorts; @Override public void buyTicket(BuyTicketsAmountCommand buyTicketsAmountCommand) { var ticket = buyTicket.buyTicket(buyTicketsAmountCommand.action(), buyTicketsAmountCommand.start(), buyTicketsAmountCommand.end(), buyTicketsAmountCommand.price(), buyTicketsAmountCommand.owner()); ticketCreatePorts.stream().forEach(ticketCreatedPort -> ticketCreatedPort.createTicket(ticket)); } }
Vergessen Sie nicht, ein Repository der Entität zu erstellen. Dieses Repository kommuniziert wie jede andere Architektur mit dem Dienst.
package java.adapters.out.db; import java.boundedContextA.domain.TicketAction; import jakarta.persistence.*; import lombok.Getter; import lombok.NoArgsConstructor; import lombok.Setter; import org.hibernate.annotations.JdbcTypeCode; import java.sql.Types; import java.time.LocalDateTime; import java.util.UUID; @Entity @Table(schema="boundedContextA",name = "boundedContextA.tickets") @Getter @Setter @NoArgsConstructor public class TicketBoughtJpaEntity { @Id @JdbcTypeCode(Types.VARCHAR) private UUID uuid; public TicketBoughtJpaEntity(UUID uuid) { this.uuid = uuid; } @JdbcTypeCode(Types.VARCHAR) private UUID owner; @Column private LocalDateTime start; @Column private LocalDateTime end; @Column private double price; }
Erstellen Sie im Verzeichnis „adapters/in“ einen Controller des Tickets. Diese Anwendung kommuniziert mit externen Quellen.
package java.boundedContextA.adapters.out.db; import org.springframework.data.jpa.repository.JpaRepository; import java.util.Optional; import java.util.UUID; public interface TicketRepository extends JpaRepository<TicketBoughtJpaEntity, UUID> { Optional<TicketBoughtJpaEntity> findByOwner(UUID uuid); }
- Schließen Sie den Ticketkaufvorgang ab
Um anzuzeigen, dass das Ticket gekauft wurde, erstellen Sie einen Datensatz der Veranstaltung in einem Verzeichnis „Veranstaltungen“.
Ereignisse stellen bedeutende Ereignisse in der Anwendung dar, die für die Kommunikation des Systems mit anderen Systemen oder Komponenten wichtig sind. Sie dienen als weitere Möglichkeit, mit der Außenwelt über einen abgeschlossenen Prozess, einen veränderten Zustand oder die Notwendigkeit weiterer Maßnahmen zu kommunizieren.
package java.boundedContextA.adapters.in; import java.boundedContextA.ports.in.BuyTicketsAmountCommand; import java.boundedContextA.ports.in.BuyingATicketUseCase; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; @RestController @RequestMapping("/api") public class TicketsController { private final BuyingATicketUseCase buyingATicketUseCase; public TicketsController(BuyingATicketUseCase buyingATicketUseCase) { this.buyingATicketUseCase = buyingATicketUseCase; } @PostMapping("/ticket") public void receiveMoney(@RequestBody BuyTicketsAmountCommand command) { try { buyingATicketUseCase.buyTicket(command); } catch (IllegalArgumentException e) { System.out.println("An IllegalArgumentException occurred: " + e.getMessage()); } } }
Vergessen Sie nicht, eine Hauptklasse einzuschließen, um alles auf einmal auszuführen.
package java.boundedContextA.events; import java.time.LocalDateTime; import java.util.UUID; public record TicketIsBoughtEvent(UUID uuid, LocalDateTime start, LocalDateTime end) { }
**Dies ist eine sehr kurze Erklärung. Für einen ausführlicheren Code und wie man eine Verbindung zu einer React-Schnittstelle herstellt, schauen Sie sich dieses GitHub-Repository an: https://github.com/alexiacismaru/techtopia.
Abschluss
Um diese Architektur in Java zu implementieren, müssen Sie eine saubere Kerndomäne mit Geschäftslogik und Schnittstellen definieren, Adapter für die Interaktion mit externen Systemen erstellen und alles zusammen schreiben, während der Kern isoliert bleibt.
Durch die Einhaltung dieser Architektur werden Ihre Java-Anwendungen besser strukturiert, einfacher zu warten und flexibel genug, um sich an zukünftige Änderungen anzupassen.
Das obige ist der detaillierte Inhalt vonVerwenden begrenzter Kontexte zum Erstellen einer Java-Anwendung. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Heiße KI -Werkzeuge

Undresser.AI Undress
KI-gestützte App zum Erstellen realistischer Aktfotos

AI Clothes Remover
Online-KI-Tool zum Entfernen von Kleidung aus Fotos.

Undress AI Tool
Ausziehbilder kostenlos

Clothoff.io
KI-Kleiderentferner

Video Face Swap
Tauschen Sie Gesichter in jedem Video mühelos mit unserem völlig kostenlosen KI-Gesichtstausch-Tool aus!

Heißer Artikel

Heiße Werkzeuge

Notepad++7.3.1
Einfach zu bedienender und kostenloser Code-Editor

SublimeText3 chinesische Version
Chinesische Version, sehr einfach zu bedienen

Senden Sie Studio 13.0.1
Leistungsstarke integrierte PHP-Entwicklungsumgebung

Dreamweaver CS6
Visuelle Webentwicklungstools

SublimeText3 Mac-Version
Codebearbeitungssoftware auf Gottesniveau (SublimeText3)

Heiße Themen











Fehlerbehebung und Lösungen für die Sicherheitssoftware des Unternehmens, die dazu führt, dass einige Anwendungen nicht ordnungsgemäß funktionieren. Viele Unternehmen werden Sicherheitssoftware bereitstellen, um die interne Netzwerksicherheit zu gewährleisten. ...

Lösungen zum Umwandeln von Namen in Zahlen zur Implementierung der Sortierung in vielen Anwendungsszenarien müssen Benutzer möglicherweise in Gruppen sortieren, insbesondere in einem ...

Die Verarbeitung von Feldzuordnungen im Systemdocken stößt häufig auf ein schwieriges Problem bei der Durchführung von Systemdocken: So kartieren Sie die Schnittstellenfelder des Systems und ...

Beginnen Sie den Frühling mit der Intellijideaultimate -Version ...

Bei Verwendung von MyBatis-Plus oder anderen ORM-Frameworks für Datenbankvorgänge müssen häufig Abfragebedingungen basierend auf dem Attributnamen der Entitätsklasse erstellt werden. Wenn Sie jedes Mal manuell ...

Konvertierung von Java-Objekten und -Arrays: Eingehende Diskussion der Risiken und korrekten Methoden zur Konvertierung des Guss-Typs Viele Java-Anfänger werden auf die Umwandlung eines Objekts in ein Array stoßen ...

Detaillierte Erläuterung des Designs von SKU- und SPU-Tabellen auf E-Commerce-Plattformen In diesem Artikel werden die Datenbankdesignprobleme von SKU und SPU in E-Commerce-Plattformen erörtert, insbesondere wie man mit benutzerdefinierten Verkäufen umgeht ...

Wie erkennt die Redis -Caching -Lösung die Anforderungen der Produktranking -Liste? Während des Entwicklungsprozesses müssen wir uns häufig mit den Anforderungen der Ranglisten befassen, z. B. das Anzeigen eines ...
