wake-up-neo.net

Wie funktioniert die Anmerkung Spring @ResponseBody in diesem RESTful-Anwendungsbeispiel?

Ich habe eine Methode, die folgendermaßen kommentiert ist:

/**
* Provide a list of all accounts.
*/
//  TODO 02: Complete this method.  Add annotations to respond
//  to GET /accounts and return a List<Account> to be converted.
//  Save your work and restart the server.  You should get JSON results when accessing 
//  http://localhost:8080/rest-ws/app/accounts
@RequestMapping(value="/orders", method=RequestMethod.GET)
public @ResponseBody List<Account> accountSummary() {
    return accountManager.getAllAccounts();
}

So weiß ich das durch diese Anmerkung:

@RequestMapping(value="/orders", method=RequestMethod.GET)

diese Methode verarbeitet [~ # ~] get [~ # ~] HTTP-Anforderungen an die durch die URL dargestellte Ressource /orders .

Diese Methode ruft ein DAO-Objekt auf, das eine Liste zurückgibt.

wobei Konto einen Benutzer im System darstellt und einige Felder hat, die diesen Benutzer darstellen, so etwas wie:

public class Account {

    @Id
    @Column(name = "ID")
    @GeneratedValue(strategy=GenerationType.IDENTITY)
    private Long entityId;

    @Column(name = "NUMBER")
    private String number;

    @Column(name = "NAME")
    private String name;

    @OneToMany(cascade=CascadeType.ALL)
    @JoinColumn(name = "ACCOUNT_ID")
    private Set<Beneficiary> beneficiaries = new HashSet<Beneficiary>();

    ...............................
    ...............................
    ...............................
}

Meine Frage ist: Wie genau funktioniert die Annotation @ResponseBody?

Es befindet sich vor dem zurückgegebenen List<Account> - Objekt, sodass ich denke, dass es auf diese Liste verweist. Die Kursdokumentation besagt, dass diese Anmerkung die Funktion hat, um:

stellen Sie sicher, dass das Ergebnis von einem HTTP Message Converter (anstelle einer MVC-Ansicht) in die HTTP-Antwort geschrieben wird.

Lesen Sie auch die offizielle Spring-Dokumentation: http://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/web/bind/annotation/ResponseBody.html

es scheint, dass es das Objekt List<Account> nimmt und es in das Objekt Http Response schreibt. Ist das richtig oder missverstehe ich?

In den Kommentar der vorherigen accountSummary() Methode geschrieben gibt es:

Sie sollten JSON-Ergebnisse erhalten, wenn Sie auf http: // localhost: 8080/rest-ws/app/accounts zugreifen

Was genau bedeutet das? Bedeutet dies, dass das von der Methode accountSummary() zurückgegebene Objekt List<Account> Automatisch in das Format JSON konvertiert und dann in das Format Http Response Eingefügt wird? Oder was?

Wenn diese Aussage wahr ist, wo wird angegeben, dass das Objekt automatisch in das JSON -Format konvertiert wird? Wird das Standardformat verwendet, wenn die Annotation @ResponseBody Verwendet wird, oder wird es an einer anderen Stelle angegeben?

80
AndreaNobili

Erstens kommentiert die Annotation List nicht. Die Methode wird wie bei RequestMapping mit Anmerkungen versehen. Ihr Code entspricht

@RequestMapping(value="/orders", method=RequestMethod.GET)
@ResponseBody
public List<Account> accountSummary() {
    return accountManager.getAllAccounts();
}

Die Anmerkung bedeutet nun, dass der zurückgegebene Wert der Methode den Hauptteil der HTTP-Antwort bildet. Natürlich kann eine HTTP-Antwort keine Java Objekte enthalten. Daher wird diese Liste der Konten in ein Format umgewandelt, das für REST Anwendungen geeignet ist, normalerweise JSON oder XML .

Die Wahl des Formats hängt von den installierten Nachrichtenkonvertern, von den Werten des Attributs produces der RequestMapping-Annotation und vom Inhaltstyp ab, den der Client akzeptiert (der in verfügbar ist) die HTTP-Request-Header). Wenn in der Anforderung beispielsweise angegeben wird, dass XML, jedoch nicht JSON akzeptiert wird, und ein Nachrichtenkonverter installiert ist, der die Liste in XML umwandeln kann, wird XML zurückgegeben.

136
JB Nizet

Das Erste, was man verstehen muss, ist der Unterschied in der Architektur.

Am einen Ende haben Sie die MVC-Architektur, die auf Ihrer normalen Web-App basiert und Webseiten verwendet, und der Browser fordert eine Seite an:

Browser <---> Controller <---> Model
               |      |
               +-View-+

Der Browser stellt eine Anforderung, der Controller (@Controller) erhält das Modell (@Entity) und erstellt die Ansicht (JSP) aus dem Modell und die Ansicht wird an den Client zurückgegeben. Dies ist die grundlegende Web-App-Architektur.

Auf der anderen Seite haben Sie eine REST-Architektur. In diesem Fall gibt es keine Ansicht. Der Controller sendet nur das Modell (oder die Ressourcendarstellung, in mehr REST-Begriffen) zurück. Der Client kann eine JavaScript-Anwendung sein, eine Java Server-Anwendung, eine beliebige Anwendung, der wir unsere REST API aussetzen. Bei dieser Architektur entscheidet der Client, was Nehmen wir zum Beispiel Twitter. Twitter als die Web-API (REST), mit der unsere Anwendungen ihre API verwenden können, um beispielsweise Statusaktualisierungen abzurufen, damit wir diese Daten in unsere Anwendung einfügen können. Diese Daten werden in einem Format wie JSON vorliegen.

Das heißt, wenn Sie mit Spring MVC arbeiten, wurde es zuerst für die grundlegende Webanwendungsarchitektur entwickelt. Es gibt möglicherweise verschiedene Arten von Methodensignaturen, die es ermöglichen, aus unseren Methoden eine Ansicht zu erstellen. Die Methode könnte ein ModelAndView zurückgeben, in dem wir es explizit erstellen, oder es gibt implizite Möglichkeiten, in denen wir ein beliebiges Objekt zurückgeben können, das in Modellattribute gesetzt wird. Aber so oder so wird irgendwo entlang des Anfrage-Antwort-Zyklus eine Ansicht erstellt.

Aber wenn wir @ResponseBody, wir sagen, dass wir nicht wollen, dass eine Sicht produziert wird. Wir wollen nur das Rückgabeobjekt als den Körper senden, in welchem ​​Format wir auch immer angeben. Wir möchten nicht, dass es sich um ein serialisiertes Java) -Objekt handelt (obwohl dies möglich ist). Ja, es muss in einen anderen gängigen Typ konvertiert werden (dieser Typ wird normalerweise durch Inhaltsaushandlung behandelt). siehe Link unten) Ehrlich gesagt, ich arbeite nicht viel mit Spring, obwohl ich mich hier und da damit beschäftige

@RequestMapping(..., produces = MediaType.APPLICATION_JSON_VALUE)

um den Inhaltstyp festzulegen, aber möglicherweise ist JSON die Standardeinstellung. Zitiere mich nicht, aber wenn du JSON bekommst und produces nicht angegeben hast, ist es vielleicht die Standardeinstellung. JSON ist nicht das einzige Format. Zum Beispiel könnte das oben Genannte leicht in XML gesendet werden, aber Sie müssten die Zeichen produces bis MediaType.APPLICATION_XML_VALUE und ich glaube, Sie müssen HttpMessageConverter für JAXB konfigurieren. Wie für die JSON MappingJacksonHttpMessageConverter konfiguriert, wenn wir Jackson auf dem Klassenpfad haben.

Ich würde einige Zeit in Anspruch nehmen, um etwas über Content Negotiation zu lernen. Es ist ein sehr wichtiger Teil von REST. Sie lernen die verschiedenen Antwortformate kennen und können sie Ihren Methoden zuordnen.

52
Paul Samsotha

Wie von JB Nizet erwähnt,

@RequestMapping(value="/orders", method=RequestMethod.GET)
@ResponseBody
public List<Account> accountSummary() {
    return accountManager.getAllAccounts();
}

und

@RequestMapping(value="/orders", method=RequestMethod.GET)
public @ResponseBody List<Account> accountSummary() {
    return accountManager.getAllAccounts();
}

beide sind gleich. as @ResponseBody kommentiert die Methode und nicht die Liste. @GMsoF -Installierte Nachrichtenkonverter können hier wie folgt verwendet werden.

@RequestMapping(value="/orders", method=RequestMethod.GET , produces={"application/json","application/xml"})
@ResponseBody
public List<Account> accountSummary() {
    return accountManager.getAllAccounts();
}

Vielen Dank :)

4
Nupur

Darüber hinaus wird der Rückgabetyp durch bestimmt

  1. Was die HTTP-Anfrage sagt - in ihrem Accept-Header. Sehen Sie sich die erste Anfrage an, um zu sehen, auf was Accept eingestellt ist.

  2. Was HttpMessageConverters Spring einrichtet. Spring MVC richtet Konverter für XML (unter Verwendung von JAXB) und JSON ein, wenn sich Jackson-Bibliotheken im Klassenpfad befinden.

Wenn es eine Auswahl gibt, wird eine ausgewählt. In diesem Beispiel handelt es sich zufällig um JSON.

Dies wird in den Kursnotizen behandelt. Beachten Sie die Hinweise zu Message Convertors und Content Negotiation.

1
paulchapman