6 Stimmen

Wie konfiguriere ich einen RESTful Controller in Spring 3 mit Annotationen?

Ich versuche, eine RESTful Controller mit Frühling 3.0. Der Controller ist für eine Verwaltungs-API für eine Portalanwendung gedacht. Die Operationen, die ich durchführen möchte, sind:

  • GET /api/portals zum Auflisten aller Portale
  • POST /api/portals zum Erstellen eines neuen Portals
  • GET /api/portals/{id} zum Abrufen eines vorhandenen Portals
  • PUT /api/portals/{id} zur Aktualisierung eines bestehenden Portals
  • DELETE /api/portal/{id} zum Löschen eines bestehenden Portals

Nachdem ich den Controller wie unten dargestellt kommentiert habe, stelle ich fest, dass die Operationen zum Auflisten aller Portale oder zum Erstellen eines neuen Portals nicht zugeordnet werden.

Meine Fragen lauten also:

  • Habe ich die Klasse richtig kommentiert?
  • Befolge ich die richtigen Konventionen für die Implementierung eines RESTful-Webdienstes?
  • Könnte im Frühling etwas kaputt sein?

Der nachstehende Codeauszug zeigt, wie ich meine Klasse mit Anmerkungen versehen habe:

@Controller
@RequestMapping("/api/portals")
public final class PortalAPIController
{
    private final static Logger LOGGER = LoggerFactory.getLogger(PortalAPIController.class);

    @RequestMapping(value = "/", method = RequestMethod.GET)
    public String listPortals(final Model model)
    {
         PortalAPIController.LOGGER.debug("Portal API: listPortals()");
         .
         .
         return "portals";
    }

    @RequestMapping(value = "/", method = RequestMethod.POST)
    public String createPortal(@RequestBody final MultiValueMap<String, String> portalData, final Model model)
    {
        PortalAPIController.LOGGER.debug("Portal API: createPortal()");
        .
        .
        return "portal";
    }

    @RequestMapping(value = "/{id}", method = RequestMethod.GET)
    public String getPortal(@PathVariable("id") final String portalId, final Model model, final HttpServletResponse response)
        throws IOException
    {
        PortalAPIController.LOGGER.debug("Portal API: getPortal()");
        .
        .
        return "portal";
    }

    @RequestMapping(value = "/{id}", method = RequestMethod.PUT)
    public String updatePortal(@PathVariable("id") final String portalId,
        @RequestBody final MultiValueMap<String, String> portalData, final Model model, final HttpServletResponse response)
        throws IOException
    {
        PortalAPIController.LOGGER.debug("Portal API: updatePortal()");
        .
        .
        return "portal";
    }

    @RequestMapping(value = "/{id}", method = RequestMethod.DELETE)
    public String deletePortal(@PathVariable("id") final String portalId, final Model model, final HttpServletResponse response)
        throws IOException
    {
        PortalAPIController.LOGGER.debug("Portal API: deletePortal()");
        .
        .
        return "portal";
    }

    .
    .
}

Beim Start sehe ich, dass Spring die Endpunkte registriert hat:

2010-02-19 01:18:41,733 INFO [org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping] - Mapped URL path [/api/portals/] onto handler [com.btmatthews.mars.portal.web.controller.PortalAPIController@141717f]
2010-02-19 01:18:41,734 INFO [org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping] - Mapped URL path [/api/portals/{id}] onto handler [com.btmatthews.mars.portal.web.controller.PortalAPIController@141717f]
2010-02-19 01:18:41,734 INFO [org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping] - Mapped URL path [/api/portals/{id}.*] onto handler [com.btmatthews.mars.portal.web.controller.PortalAPIController@141717f]
2010-02-19 01:18:41,735 INFO [org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping] - Mapped URL path [/api/portals/{id}/] onto handler [com.btmatthews.mars.portal.web.controller.PortalAPIController@141717f]
2010-02-19 01:18:41,735 INFO [org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping] - Mapped URL path [/api/portals] onto handler [com.btmatthews.mars.portal.web.controller.PortalAPIController@141717f]
2010-02-19 01:18:41,735 INFO [org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping] - Mapped URL path [/api/portals.*] onto handler [com.btmatthews.mars.portal.web.controller.PortalAPIController@141717f]

Aber wenn ich versuche, meine API mit cURL aufzurufen

curl http://localhost:8080/com.btmatthews.minerva.portal/api/portals/

o

curl http://localhost:8080/com.btmatthews.minerva.portal/api/portals

Ich erhalte die folgenden Fehler:

2010-02-19 01:19:20,199 WARN [org.springframework.web.servlet.PageNotFound] - No mapping found for HTTP request with URI [/com.btmatthews.minerva.portal/api/portals] in DispatcherServlet with name 'portal'
2010-02-19 01:19:32,360 WARN [org.springframework.web.servlet.PageNotFound] - No mapping found for HTTP request with URI [/com.btmatthews.minerva.portal/api/portals/] in DispatcherServlet with name 'portal'

Ich habe das gleiche Problem, wenn ich versuche, eine Datei zu erstellen:

curl -F ...... --request POST http://localhost:8080/com.btmatthtews.minerva/api/portals

Wenn Sie jedoch versuchen, eine vorhandene Ressource zu bearbeiten (abrufen, aktualisieren oder löschen), funktioniert dies problemlos.

Aktualisierung: Die Lösung fand sich in einem Kommentar von @axtavt . Ich habe <url-pattern>/api/*</url-pattern> in meiner web.xml Servlet-Zuordnung verwendet. Es musste in <url-pattern>/</url-pattern> geändert werden.

4voto

earldouglas Punkte 13012

Überprüfen Sie die url-pattern in Ihrem web.xml und vergleichen Sie es mit Ihrem Curl-Argument.

Hier ein Beispiel die ich geschrieben habe und die Sie durch den gesamten Spring MVC-Prozess führt.

0voto

matt b Punkte 135206

Die URL, die Sie in Ihrem Curl-Auszug angeben

http://localhost:8080/portal/api/portals

nicht mit der URL in der Spring-Warnung übereinstimmt

/com.btmatthews.minerva.portal/api/portals

Ohne zu wissen, wie Ihre Webapp eingerichtet ist, welcher Kontextpfad es ist, wie der Spring-Kontext aussieht, usw., ist es ziemlich schwer zu diagnostizieren, aber das klingt für mich wie ein großer Hinweis.

0voto

Sagarrj Punkte 11

Sie haben einige Fehler gemacht.

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

public String listPortals(final Model model)
{
}

Hier muss die Methode einen Parameter Model akzeptieren, der aber nicht übergeben wird. Sie müssen das innerhalb der Methode schreiben. oder wenn Sie das übergeben wollen, müssen Sie es als Pfadvariable oder als Request Param senden.

@RequestMapping(value = "/{id}", method = RequestMethod.GET)

public String getPortal(@PathVariable("id") 

Die korrekte Syntax lautet hier @PathVariable(value="id")

Und wenn das nicht klappt dann versuchen Sie dies:

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

0voto

Dean Punkte 334

In Spring 3 ist der Rest Controller nicht mehr als ein normaler Controller (@Component) und der einzige Unterschied ist, dass ein Rest Controller JSON/XML anstelle von "Views" zurückgibt. Ich denke also, dass Sie in Bezug auf die Annotationen alles richtig machen. Allerdings kann ich zwei fehlende Dinge nicht sehen: 1- Jede Methode muss einen "produce"-Wert haben (für Content Negotiation): @RequestMapping(value = "/{id}", method = RequestMethod.GET, produces = "application/json")

2- Sie benötigen einen ObjectMapper irgendeiner Art (z. B. Marshaller und Unmarshaller), um Objekte auf JSON/XML und umgekehrt abbilden zu können. Diese beiden sollten in Ihrer Servlet-Konfiguration enthalten sein, anstatt einen View Resolver zu konfigurieren. Und das sollte alles sein.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X