HATEOAS (Hypermedia as the Engine of Application State) ist ein zentrales Prinzip des REST-Architekturstils. Es besagt, dass ein Client die Navigation durch die Anwendung mithilfe von Hypermedia steuern soll, die vom Server in den Antworten bereitgestellt wird. Dies ermöglicht es, dass der Client keine Kenntnisse über die interne Struktur oder die verfügbaren Endpunkte des Servers haben muss. Stattdessen entdeckt er diese dynamisch über die erhaltenen Hypermedia-Links.
Hypermedia als Navigationsmittel
Der Server liefert zusammen mit den Daten Links, die dem Client erlauben, weitere Aktionen auszuführen oder zu verwandten Ressourcen zu navigieren.
Entkopplung von Client und Server
Änderungen an der API-Struktur oder den Endpunkten auf Serverseite beeinträchtigen den Client nicht, da er die verfügbaren Aktionen dynamisch aus den erhaltenen Links ableitet.
Selbstbeschreibende Nachrichten
Jede Antwort enthält genügend Informationen, damit der Client den aktuellen Zustand versteht und mögliche nächste Schritte kennt.
Flexibilität
Der Client passt sich automatisch an Änderungen der API an, solange die bereitgestellten Links aktualisiert werden.
Erweiterbarkeit
Neue Funktionen können hinzugefügt werden, ohne den Client zu aktualisieren, da diese über neue Links bekannt gemacht werden.
Reduzierte Kopplung
Weniger Abhängigkeiten zwischen Client und Server erleichtern Wartung und Weiterentwicklung.
Spring Boot bietet mit dem Projekt Spring HATEOAS Unterstützung für die Erstellung von Hypermedia-getriebenen RESTful Services.
Fügen Sie in Ihrer pom.xml oder
build.gradle die folgende Abhängigkeit hinzu:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-hateoas</artifactId>
</dependency>implementation 'org.springframework.boot:spring-boot-starter-hateoas'Verwenden Sie EntityModel oder
CollectionModel, um Ressourcen mit Links zu versehen.
Angenommen, wir haben ein Employee-Objekt und möchten
einen RESTful Service erstellen.
public class Employee {
private Long id;
private String name;
private String role;
// Konstruktoren, Getter und Setter
}import org.springframework.hateoas.EntityModel;
import org.springframework.hateoas.server.mvc.WebMvcLinkBuilder;
import org.springframework.web.bind.annotation.*;
import java.util.*;
@RestController
@RequestMapping("/employees")
public class EmployeeController {
private Map<Long, Employee> employeeRepository = new HashMap<>();
@GetMapping("/{id}")
public EntityModel<Employee> getEmployee(@PathVariable Long id) {
Employee employee = employeeRepository.get(id);
if (employee == null) {
throw new EmployeeNotFoundException(id);
}
EntityModel<Employee> employeeModel = EntityModel.of(employee,
WebMvcLinkBuilder.linkTo(WebMvcLinkBuilder.methodOn(EmployeeController.class).getEmployee(id)).withSelfRel(),
WebMvcLinkBuilder.linkTo(WebMvcLinkBuilder.methodOn(EmployeeController.class).getAllEmployees()).withRel("employees"));
return employeeModel;
}
@GetMapping
public CollectionModel<EntityModel<Employee>> getAllEmployees() {
List<EntityModel<Employee>> employees = employeeRepository.values().stream()
.map(employee -> EntityModel.of(employee,
WebMvcLinkBuilder.linkTo(WebMvcLinkBuilder.methodOn(EmployeeController.class).getEmployee(employee.getId())).withSelfRel()))
.collect(Collectors.toList());
return CollectionModel.of(employees,
WebMvcLinkBuilder.linkTo(WebMvcLinkBuilder.methodOn(EmployeeController.class).getAllEmployees()).withSelfRel());
}
// Weitere Methoden wie createEmployee, updateEmployee etc.
}T und ermöglicht das Hinzufügen von Links.Erstellen Sie eine benutzerdefinierte Ausnahme für den Fall, dass ein Mitarbeiter nicht gefunden wird.
@ResponseStatus(HttpStatus.NOT_FOUND)
public class EmployeeNotFoundException extends RuntimeException {
public EmployeeNotFoundException(Long id) {
super("Mitarbeiter mit ID " + id + " nicht gefunden.");
}
}GET /employees/1
{
"id": 1,
"name": "Max Mustermann",
"role": "Entwickler",
"_links": {
"self": {
"href": "http://localhost:8080/employees/1"
},
"employees": {
"href": "http://localhost:8080/employees"
}
}
}Der Client kann die erhaltenen Links verwenden, um weitere Aktionen durchzuführen, z. B.:
"employees"."self"-Link.Konsistente Verwendung von Relations
Verwenden Sie standardisierte oder gut dokumentierte Relationsnamen für Ihre Links.
Vermeiden von Hardcodierten URLs im Client
Der Client sollte ausschließlich die vom Server bereitgestellten Links nutzen.
Dokumentation der API
Obwohl HATEOAS die Entdeckung von Endpunkten erleichtert, ist eine gute Dokumentation unerlässlich.
Komplexität für Client-Implementierung
Clients müssen in der Lage sein, die Hypermedia-Links zu interpretieren und zu verarbeiten.
Performance-Overhead
Zusätzliche Links können die Größe der Antworten erhöhen, was bei sehr großen Datenmengen relevant sein kann.
Durch die Verwendung von HATEOAS kann die Notwendigkeit expliziter Versionsangaben in den URIs reduziert werden, da der Client die verfügbaren Aktionen und Ressourcen über die Links entdeckt.
HAL (Hypertext Application Language)
Ein häufig verwendetes Hypermedia-Format, das eine einfache Struktur für die Einbindung von Links in JSON-Daten bietet.
Spring Data REST
Automatisiert die Erstellung von HATEOAS-konformen REST-Endpunkten für Spring Data Repositories.
Beispiel: Verwendung von HAL in der Antwort
{
"_embedded": {
"employees": [
{
"id": 1,
"name": "Max Mustermann",
"role": "Entwickler",
"_links": {
"self": {
"href": "http://localhost:8080/employees/1"
}
}
},
{
"id": 2,
"name": "Erika Musterfrau",
"role": "Managerin",
"_links": {
"self": {
"href": "http://localhost:8080/employees/2"
}
}
}
]
},
"_links": {
"self": {
"href": "http://localhost:8080/employees"
}
}
}Dynamische API
Erlaubt es dem Server, die API zu verändern, ohne den Client zu beeinflussen.
Bessere Benutzererfahrung
Clients können den Benutzern kontextbezogene Aktionen anbieten.
Zukunftssicherheit
Erleichtert die Erweiterung der API und die Einführung neuer Funktionen.
HATEOAS ist ein REST-Prinzip, das die Navigation eines Clients durch Hypermedia-Links ermöglicht, die in Serverantworten eingebettet sind. Dies fördert eine lose Kopplung zwischen Client und Server und ermöglicht flexible und erweiterbare APIs. Mit Spring Boot und Spring HATEOAS können Entwickler effizient Hypermedia-getriebene RESTful Services erstellen.