Java >> Java Tutorial >  >> Tag >> Spring

Erstellen einer REST-API mit Spring Boot und MongoDB

Dieses Jahr habe ich Weihnachten anders begrüßt:Ich war Teil des Java-Adventskalenders. Lassen Sie uns Weihnachten hochfahren:

Spring Boot ist ein eigenständiges Framework, das die Entwicklung von Spring-Anwendungen vereinfacht. Es befreit uns von der Sklaverei komplexer Konfigurationsdateien und hilft uns, eigenständige Spring-Anwendungen zu erstellen, die keinen externen Servlet-Container benötigen.

Das klingt fast zu schön, um wahr zu sein, aber Spring Boot kann all das wirklich .

Dieser Blogbeitrag zeigt, wie einfach es ist, eine REST-API zu implementieren, die CRUD-Vorgänge für Aufgabeneinträge bereitstellt, die in der MongoDB-Datenbank gespeichert werden.

Beginnen wir mit der Erstellung unseres Maven-Projekts.

Erstellen unseres Maven-Projekts

Wir können unser Maven-Projekt erstellen, indem wir diesen Schritten folgen:

  1. Verwenden Sie den spring-boot-starter-parent POM als übergeordnetes POM unseres Maven-Projekts. Dadurch wird sichergestellt, dass unser Projekt sinnvolle Standardeinstellungen von Spring Boot erbt.
  2. Fügen Sie das Spring Boot Maven Plugin zu unserem Projekt hinzu. Dieses Plugin ermöglicht es uns, unsere Anwendung in eine ausführbare JAR-Datei zu packen, sie in ein Kriegsarchiv zu packen und die Anwendung auszuführen.
  3. Konfigurieren Sie die Abhängigkeiten unseres Projekts. Wir müssen die folgenden Abhängigkeiten konfigurieren:
    • Das spring-boot-starter-web Abhängigkeit stellt die Abhängigkeiten einer Webanwendung bereit.
    • Die spring-data-mongodb Abhängigkeit bietet Integration mit der MongoDB-Dokumentendatenbank.
  4. Aktivieren Sie die Java 8-Unterstützung von Spring Boot.
  5. Konfigurieren Sie die Hauptklasse unserer Anwendung. Diese Klasse ist für die Konfiguration und den Start unserer Anwendung verantwortlich.

Der relevante Teil unserer pom.xml Datei sieht wie folgt aus:

<properties>
    <!-- Enable Java 8 -->
    <java.version>1.8</java.version>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <!-- Configure the main class of our Spring Boot application -->
    <start-class>com.javaadvent.bootrest.TodoAppConfig</start-class>
</properties>
        
<!-- Inherit defaults from Spring Boot -->
<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>1.1.9.RELEASE</version>
</parent>

<dependencies>
    <!-- Get the dependencies of a web application -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>

    <!-- Spring Data MongoDB-->
    <dependency>
        <groupId>org.springframework.data</groupId>
        <artifactId>spring-data-mongodb</artifactId>
    </dependency>
</dependencies>

<build>
    <plugins>
        <!-- Spring Boot Maven Support -->
        <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
        </plugin>
    </plugins>
</build>

Lassen Sie uns weitermachen und herausfinden, wie wir unsere Anwendung konfigurieren können.

Konfigurieren unserer Anwendung

Wir können unsere Spring Boot-Anwendung konfigurieren, indem wir diesen Schritten folgen:

  1. Erstellen Sie eine TodoAppConfig Klasse zu com.javaadvent.bootrest Paket.
  2. Automatische Spring Boot-Konfiguration aktivieren.
  3. Konfigurieren Sie den Spring-Container, um Komponenten zu scannen, die in den untergeordneten Paketen von com.javaadvent.bootrest gefunden wurden Paket.
  4. Fügen Sie main() hinzu -Methode zu TodoAppConfig Klasse und implementieren, indem Sie unsere Anwendung ausführen.

Der Quellcode der TodoAppConfig Klasse sieht wie folgt aus:

package com.javaadvent.bootrest;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;

@Configuration
@EnableAutoConfiguration
@ComponentScan
public class TodoAppConfig {
    
    public static void main(String[] args) {
        SpringApplication.run(TodoAppConfig.class, args);
    }
}

Wir haben jetzt die Konfigurationsklasse erstellt, die unsere Spring Boot-Anwendung konfiguriert und ausführt. Da die MongoDB-JAR-Dateien im Klassenpfad gefunden werden, konfiguriert Spring Boot die MongoDB-Verbindung mithilfe der Standardeinstellungen.

Fahren wir fort und implementieren unsere REST-API.

Implementieren unserer REST-API

Wir müssen eine REST-API implementieren, die CRUD-Operationen für Aufgabeneinträge bereitstellt. Die Anforderungen unserer REST-API sind:

  • Ein POST Eine Anfrage, die an die URL „/api/todo“ gesendet wird, muss einen neuen Todo-Eintrag erstellen, indem sie die Informationen aus dem Anfragetext verwendet und die Informationen des erstellten Todo-Eintrags zurückgibt.
  • Ein LÖSCHEN Die an die URL „/api/todo/{id}“ gesendete Anfrage muss den ToDo-Eintrag löschen, dessen ID aus der URL gefunden wird, und die Informationen des gelöschten ToDo-Eintrags zurückgeben.
  • Ein GET Request send to the url ‘/api/todo’ muss alle todo-Einträge zurückgeben, die aus der Datenbank gefunden werden.
  • Ein GET Die an die URL „/api/todo/{id}“ gesendete Anfrage muss die Informationen des Aufgabeneintrags zurückgeben, dessen ID aus der URL gefunden wird.
  • Ein PUT Eine an die URL „/api/todo/{id}“ gesendete Anforderung muss die Informationen eines vorhandenen Todo-Eintrags aktualisieren, indem sie die Informationen aus dem Anfragetext verwendet und die Informationen des aktualisierten Todo-Eintrags zurückgibt.

Wir können diese Anforderungen erfüllen, indem wir diesen Schritten folgen:

  1. Erstellen Sie die Entität, die die Informationen eines einzelnen Aufgabeneintrags enthält.
  2. Erstellen Sie das Repository, das zum Speichern von Todo-Einträgen in der MongoDB-Datenbank verwendet wird, und suchen Sie darin Todo-Einträge.
  3. Erstellen Sie die Dienstschicht, die für die Zuordnung von DTOs zu Domänenobjekten und umgekehrt verantwortlich ist. Der Zweck unserer Dienstschicht besteht darin, unser Domänenmodell von der Webschicht zu isolieren.
  4. Erstellen Sie die Controller-Klasse, die HTTP-Anforderungen verarbeitet und die richtige Antwort an den Client zurücksendet.

Fangen wir an.

Erstellen der Entität

Wir müssen die Entitätsklasse erstellen, die die Informationen eines einzelnen Aufgabeneintrags enthält. Wir können dies tun, indem wir diesen Schritten folgen:

  1. Fügen Sie die ID hinzu , Beschreibung , und Titel Felder in die erstellte Entitätsklasse. Konfigurieren Sie das ID-Feld der Entität, indem Sie die id kommentieren Feld mit der @Id Anmerkung.
  2. Geben Sie die Konstanten an (MAX_LENGTH_DESCRIPTION und MAX_LENGTH_TITLE ), die die maximale Länge der Beschreibung angeben und Titel Felder.
  3. Fügen Sie der Entitätsklasse eine statische Builder-Klasse hinzu. Diese Klasse wird verwendet, um neue Todo zu erstellen Objekte.
  4. Fügen Sie ein Update() hinzu Methode zur Entitätsklasse. Diese Methode aktualisiert einfach den Titel und Beschreibung der Entität, wenn gültige Werte als Methodenparameter angegeben werden.

Der Quellcode des Todo Klasse sieht wie folgt aus:

import org.springframework.data.annotation.Id;

import static com.javaadvent.bootrest.util.PreCondition.isTrue;
import static com.javaadvent.bootrest.util.PreCondition.notEmpty;
import static com.javaadvent.bootrest.util.PreCondition.notNull;

final class Todo {

    static final int MAX_LENGTH_DESCRIPTION = 500;
    static final int MAX_LENGTH_TITLE = 100;

    @Id
    private String id;

    private String description;

    private String title;

    public Todo() {}

    private Todo(Builder builder) {
        this.description = builder.description;
        this.title = builder.title;
    }

    static Builder getBuilder() {
        return new Builder();
    }

    //Other getters are omitted

    public void update(String title, String description) {
        checkTitleAndDescription(title, description);

        this.title = title;
        this.description = description;
    }

    /**
     * We don't have to use the builder pattern here because the constructed 
     * class has only two String fields. However, I use the builder pattern 
     * in this example because it makes the code a bit easier to read.
     */
    static class Builder {

        private String description;

        private String title;

        private Builder() {}

        Builder description(String description) {
            this.description = description;
            return this;
        }

        Builder title(String title) {
            this.title = title;
            return this;
        }

        Todo build() {
            Todo build = new Todo(this);

            build.checkTitleAndDescription(build.getTitle(), build.getDescription());

            return build;
        }
    }

    private void checkTitleAndDescription(String title, String description) {
        notNull(title, "Title cannot be null");
        notEmpty(title, "Title cannot be empty");
        isTrue(title.length() <= MAX_LENGTH_TITLE,
                "Title cannot be longer than %d characters",
                MAX_LENGTH_TITLE
        );

        if (description != null) {
            isTrue(description.length() <= MAX_LENGTH_DESCRIPTION,
                    "Description cannot be longer than %d characters",
                    MAX_LENGTH_DESCRIPTION
            );
        }
    }
}

Fahren wir fort und erstellen das Repository, das mit der MongoDB-Datenbank kommuniziert.

Das Repository erstellen

Wir müssen die Repository-Schnittstelle erstellen, die zum Speichern von Todo verwendet wird Objekte in die MondoDB-Datenbank und rufen Sie Todo ab Objekte daraus.

Wenn wir die Java 8-Unterstützung von Spring Data nicht nutzen möchten, könnten wir unser Repository erstellen, indem wir eine Schnittstelle erstellen, die das CrudRepository erweitert Schnittstelle. Da wir jedoch die Java 8-Unterstützung nutzen möchten, müssen wir diese Schritte befolgen:

  1. Erstellen Sie eine Schnittstelle, die das Repository erweitert Schnittstelle.
  2. Fügen Sie der erstellten Schnittstelle die folgenden Repository-Methoden hinzu:
    1. Das ungültige Löschen (Todo gelöscht) method löscht den ToDo-Eintrag, der als Methodenparameter angegeben ist.
    2. Die Liste findAll() -Methode gibt alle Aufgabeneinträge zurück, die in der Datenbank gefunden werden.
    3. Das Optionale findOne(String id) -Methode gibt die Informationen eines einzelnen Aufgabeneintrags zurück. Wenn kein Aufgabeneintrag gefunden wird, gibt diese Methode ein leeres Optional zurück .
    4. Der Todo speichern(Todo gespeichert) -Methode speichert einen neuen Aufgabeneintrag in der Datenbank und gibt den gespeicherten Aufgabeneintrag zurück.

Der Quellcode des TodoRepository Die Benutzeroberfläche sieht wie folgt aus:

import org.springframework.data.repository.Repository;

import java.util.List;
import java.util.Optional;

interface TodoRepository extends Repository<Todo, String> {

    void delete(Todo deleted);

    List<Todo> findAll();

    Optional<Todo> findOne(String id);

    Todo save(Todo saved);
}

Fahren wir fort und erstellen die Serviceschicht unserer Beispielanwendung.

Service-Layer erstellen

Zuerst , müssen wir eine Dienstschnittstelle erstellen, die CRUD-Operationen für Aufgabeneinträge bereitstellt. Der Quellcode des TodoService Die Benutzeroberfläche sieht wie folgt aus:

import java.util.List;

interface TodoService {

    TodoDTO create(TodoDTO todo);

    TodoDTO delete(String id);

    List<TodoDTO> findAll();

    TodoDTO findById(String id);

    TodoDTO update(TodoDTO todo);
}

Zweiter , müssen wir die TodoService-Schnittstelle implementieren. Wir können dies tun, indem wir diesen Schritten folgen:

  1. Fügen Sie unser Repository mithilfe der Konstruktorinjektion in die Dienstklasse ein.
  2. Fügen Sie ein privates Todo findTodoById(String id) hinzu -Methode an die Dienstklasse und implementieren Sie sie, indem Sie entweder die gefundene Todo -Objekt oder das Auslösen der TodoNotFoundException .
  3. Hinzufügen eines privaten TodoDTO convertToDTO(Todo-Modell) Methode die Dienstklasse und implementieren Sie sie, indem Sie Todo konvertieren Objekt in ein TodoDTO Objekt und Rückgabe des erstellten Objekts.
  4. Fügen Sie eine private Liste convertToDTOs(List models) hinzu und implementieren Sie es, indem Sie die Liste von Todo konvertieren Objekte in eine Liste von TodoDTO Objekte und Rückgabe der erstellten Liste.
  5. Implementieren Sie TodoDTO create(TodoDTO todo) Methode. Diese Methode erstellt ein neues Todo Objekt, speichert das erstellte Objekt in der MongoDB-Datenbank und gibt die Informationen des erstellten Aufgabeneintrags zurück.
  6. Implementieren Sie TodoDTO delete(String id) Methode. Diese Methode findet das gelöschte Todo -Objekt, löscht es und gibt die Informationen des gelöschten Aufgabeneintrags zurück. Wenn kein Todo Objekt mit der angegebenen ID gefunden wird, löst diese Methode die TodoNotFoundException aus .
  7. Implementieren Sie die ListefindAll() Methode. Diese Methode ruft alle Todo ab Objekte aus der Datenbank, wandelt sie in eine Liste von TodoDTO um Objekte und gibt die erstellte Liste zurück.
  8. Implementieren Sie das TodoDTO findById(String id) Methode. Diese Methode findet die Todo Objekt aus der Datenbank, wandelt es in ein TodoDTO um -Objekt und gibt das erstellte TodoDTO zurück Objekt. Wenn kein Aufgabeneintrag gefunden wird, löst diese Methode die TodoNotFoundException aus .
  9. Implementieren Sie das TodoDTO-Update(TodoDTO todo) Methode. Diese Methode findet das aktualisierte Todo Objekt aus der Datenbank, aktualisiert seinen Titel und Beschreibung , speichert sie und gibt die aktualisierten Informationen zurück. Wenn die aktualisierte Todo Objekt nicht gefunden wird, löst diese Methode die TodoNotFoundException aus .

Der Quellcode des MongoDBTodoService sieht wie folgt aus:

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.Optional;

import static java.util.stream.Collectors.toList;

@Service
final class MongoDBTodoService implements TodoService {

    private final TodoRepository repository;

    @Autowired
    MongoDBTodoService(TodoRepository repository) {
        this.repository = repository;
    }

    @Override
    public TodoDTO create(TodoDTO todo) {
        Todo persisted = Todo.getBuilder()
                .title(todo.getTitle())
                .description(todo.getDescription())
                .build();
        persisted = repository.save(persisted);
        return convertToDTO(persisted);
    }

    @Override
    public TodoDTO delete(String id) {
        Todo deleted = findTodoById(id);
        repository.delete(deleted);
        return convertToDTO(deleted);
    }

    @Override
    public List<TodoDTO> findAll() {
        List<Todo> todoEntries = repository.findAll();
        return convertToDTOs(todoEntries);
    }

    private List<TodoDTO> convertToDTOs(List<Todo> models) {
        return models.stream()
                .map(this::convertToDTO)
                .collect(toList());
    }

    @Override
    public TodoDTO findById(String id) {
        Todo found = findTodoById(id);
        return convertToDTO(found);
    }

    @Override
    public TodoDTO update(TodoDTO todo) {
        Todo updated = findTodoById(todo.getId());
        updated.update(todo.getTitle(), todo.getDescription());
        updated = repository.save(updated);
        return convertToDTO(updated);
    }

    private Todo findTodoById(String id) {
        Optional<Todo> result = repository.findOne(id);
        return result.orElseThrow(() -> new TodoNotFoundException(id));

    }

    private TodoDTO convertToDTO(Todo model) {
        TodoDTO dto = new TodoDTO();

        dto.setId(model.getId());
        dto.setTitle(model.getTitle());
        dto.setDescription(model.getDescription());

        return dto;
    }
}

Wir haben nun den Service Layer unserer Beispielanwendung erstellt. Fahren wir fort und erstellen die Controller-Klasse.

Erstellen der Controller-Klasse

Zuerst , müssen wir die DTO-Klasse erstellen, die die Informationen eines einzelnen Aufgabeneintrags enthält und die Validierungsregeln angibt, die verwendet werden, um sicherzustellen, dass nur gültige Informationen in der Datenbank gespeichert werden können. Der Quellcode des TodoDTO Klasse sieht wie folgt aus:

import org.hibernate.validator.constraints.NotEmpty;

import javax.validation.constraints.Size;

public final class TodoDTO {

    private String id;

    @Size(max = Todo.MAX_LENGTH_DESCRIPTION)
    private String description;

    @NotEmpty
    @Size(max = Todo.MAX_LENGTH_TITLE)
    private String title;

    //Constructor, getters, and setters are omitted
}

Zweiter , müssen wir die Controller-Klasse erstellen, die die an unsere REST-API gesendeten HTTP-Anforderungen verarbeitet und die korrekte Antwort an den Client zurücksendet. Wir können dies tun, indem wir diesen Schritten folgen:

  1. Injizieren Sie unseren Dienst mithilfe der Konstruktorinjektion in unseren Controller.
  2. Fügen Sie ein create() hinzu -Methode an unseren Controller und implementieren Sie sie, indem Sie die folgenden Schritte ausführen:
    1. Lesen Sie die Informationen des erstellten Aufgabeneintrags aus dem Anforderungstext.
    2. Überprüfen Sie die Informationen des erstellten Aufgabeneintrags.
    3. Erstellen Sie einen neuen Aufgabeneintrag und geben Sie den erstellten Aufgabeneintrag zurück. Setzen Sie den Antwortstatus auf 201.
  3. Implementieren Sie delete() Methode, indem die ID des gelöschten Aufgabeneintrags an unseren Dienst weitergeleitet und der gelöschte Aufgabeneintrag zurückgegeben wird.
  4. Implementieren Sie findAll() -Methode, indem die ToDo-Einträge aus der Datenbank gesucht und die gefundenen ToDo-Einträge zurückgegeben werden.
  5. Implementieren Sie findById() Methode, indem sie den Todo-Eintrag aus der Datenbank findet und den gefundenen Todo-Eintrag zurückgibt.
  6. Implementieren Sie das update() Methode, indem Sie die folgenden Schritte ausführen:
    1. Lesen Sie die Informationen des aktualisierten Aufgabeneintrags aus dem Anfragetext.
    2. Überprüfen Sie die Informationen des aktualisierten Aufgabeneintrags.
    3. Aktualisieren Sie die Informationen des Aufgabeneintrags und geben Sie den aktualisierten Aufgabeneintrag zurück.
  7. Erstellen Sie einen @ExceptionHandler Methode, die den Antwortstatus auf 404 setzt, wenn der Aufgabeneintrag nicht gefunden wurde (TodoNotFoundException wurde geworfen).

Der Quellcode des TodoController Klasse sieht wie folgt aus:

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestController;

import javax.validation.Valid;
import java.util.List;

@RestController
@RequestMapping("/api/todo")
final class TodoController {

    private final TodoService service;

    @Autowired
    TodoController(TodoService service) {
        this.service = service;
    }

    @RequestMapping(method = RequestMethod.POST)
    @ResponseStatus(HttpStatus.CREATED)
    TodoDTO create(@RequestBody @Valid TodoDTO todoEntry) {
        return service.create(todoEntry);
    }

    @RequestMapping(value = "{id}", method = RequestMethod.DELETE)
    TodoDTO delete(@PathVariable("id") String id) {
        return service.delete(id);
    }

    @RequestMapping(method = RequestMethod.GET)
    List<TodoDTO> findAll() {
        return service.findAll();
    }

    @RequestMapping(value = "{id}", method = RequestMethod.GET)
    TodoDTO findById(@PathVariable("id") String id) {
        return service.findById(id);
    }

    @RequestMapping(value = "{id}", method = RequestMethod.PUT)
    TodoDTO update(@RequestBody @Valid TodoDTO todoEntry) {
        return service.update(todoEntry);
    }

    @ExceptionHandler
    @ResponseStatus(HttpStatus.NOT_FOUND)
    public void handleTodoNotFound(TodoNotFoundException ex) {
    }
}

Das ist es. Wir haben jetzt eine REST-API erstellt, die CRUD-Operationen für Aufgabeneinträge bereitstellt und sie in der MongoDB-Datenbank speichert. Fassen wir zusammen, was wir aus diesem Blogbeitrag gelernt haben.

Zusammenfassung

Dieser Blogpost hat uns drei Dinge gelehrt:

  • Wir können die erforderlichen Abhängigkeiten mit Maven erhalten, indem wir nur zwei Abhängigkeiten deklarieren:spring-boot-starter-web und spring-data-mongodb .
  • Wenn wir mit der Standardkonfiguration von Spring Boot zufrieden sind, können wir unsere Webanwendung konfigurieren, indem wir die Unterstützung für die automatische Konfiguration nutzen und neue JAR-Dateien in den Klassenpfad „ablegen“.
  • Wir haben gelernt, eine einfache REST-API zu erstellen, die Informationen in der MongoDB-Datenbank speichert und Informationen daraus findet.

P.S. Sie können die Beispielanwendung dieses Blogbeitrags von Github herunterladen.


Java-Tag