JAX-RS mit Jersey: Eine Einführung

Die Spezifikation JAX-RS (JSR 311: Die Java-API für RESTful Web Services) bietet einen standardisierten Java-basierten Ansatz für die Implementierung von Webdiensten im REST-Stil. Jersey ist die Referenzimplementierung von JAX-RS und ich gebe in diesem Blog-Beitrag eine kurze Einführung in JAX-RS über Jersey.

Obwohl Jersey die Verwendung von GlassFish nicht erfordert, verwende ich Jersey in Verbindung mit GlassFish v3 in diesem Beitrag. GlassFish v3 bietet die Referenzimplementierung für Java EE 6. Ich habe den Windows Installer von GlassFish v3 heruntergeladen und zur Installation ausgeführt. Nach der Installation habe ich die Umgebungsvariable so festgelegt, dass GLASSFISH_HOMEsie auf das Stammverzeichnis der Installation verweist, und sie %GLASSFISH_HOME%zu meinem hinzugefügt PATH. GlassFish kann dann mit dem Befehl ausgeführt werden asadmin start-domain(startet die Standarddomäne), wie im nächsten Screenshot gezeigt.

Da ich bei der Installation von GlassFish die Standardeinstellungen verwendet habe, ist die webbasierte Administrationskonsole auf meinem Computer unter URI // localhost: 4848 / verfügbar (Standardport ist 4848). Wenn GlassFish ausgeführt wird, führt dieser URI zur Anmeldeseite für die Administrationskonsole. Der administrative Benutzername und das Passwort wurden in der Installation angegeben. Dieser Bildschirm wird im nächsten Bildschirmschnappschuss angezeigt.

Nachdem GlassFish eingerichtet ist, entwickle ich jetzt eine sehr einfache REST-Anwendung mit Jersey. Ich beginne mit einer ordnungsgemäß mit JAX-RS kommentierten Klasse namens MovieOfTheDay:

MovieOfTheDay.java

package rmoug.td2010.rest; import java.util.Calendar; import java.util.HashMap; import java.util.Map; import java.util.logging.Logger; import javax.ws.rs.GET; import javax.ws.rs.Path; import javax.ws.rs.PathParam; import javax.ws.rs.Consumes; import javax.ws.rs.Produces; /** * Simple class that provides a movie for the provided month and day of that * month. */ @Path("/movies") public class MovieOfTheDay { private static final Logger LOGGER = Logger.getLogger("rmoug.td2010.rest.MovieOfTheDay"); private static final Map
    
      MOVIE_OF_THE_DAY; static { MOVIE_OF_THE_DAY = new HashMap
     
      (); final Map janMovies = new HashMap(); MOVIE_OF_THE_DAY.put(Integer.valueOf(Calendar.JANUARY), janMovies); final Map febMovies = new HashMap(); febMovies.put(2, "Groundhog Day"); MOVIE_OF_THE_DAY.put(Integer.valueOf(Calendar.FEBRUARY), febMovies); final Map marMovies = new HashMap(); marMovies.put(16, "The Fugitive"); marMovies.put(17, "Darby O'Gill and the Little People"); MOVIE_OF_THE_DAY.put(Integer.valueOf(Calendar.MARCH), marMovies); final Map aprMovies = new HashMap(); MOVIE_OF_THE_DAY.put(Integer.valueOf(Calendar.APRIL), aprMovies); final Map mayMovies = new HashMap(); MOVIE_OF_THE_DAY.put(Integer.valueOf(Calendar.MAY), mayMovies); final Map junMovies = new HashMap(); MOVIE_OF_THE_DAY.put(Integer.valueOf(Calendar.JUNE), junMovies); final Map julMovies = new HashMap(); julMovies.put(4, "Independence Day"); MOVIE_OF_THE_DAY.put(Integer.valueOf(Calendar.JULY), julMovies); final Map augMovies = new HashMap(); MOVIE_OF_THE_DAY.put(Integer.valueOf(Calendar.AUGUST), augMovies); final Map sepMovies = new HashMap(); MOVIE_OF_THE_DAY.put(Integer.valueOf(Calendar.SEPTEMBER), sepMovies); final Map octMovies = new HashMap(); MOVIE_OF_THE_DAY.put(Integer.valueOf(Calendar.OCTOBER), octMovies); final Map novMovies = new HashMap(); MOVIE_OF_THE_DAY.put(Integer.valueOf(Calendar.NOVEMBER), novMovies); final Map decMovies = new HashMap(); decMovies.put(24, "It's A Wonderful Life"); decMovies.put(25, "A Christmas Carol"); decMovies.put(26, "A Christmas Story"); MOVIE_OF_THE_DAY.put(Integer.valueOf(Calendar.DECEMBER), decMovies); } @GET @Path("/") @Produces("text/plain") public String getMovie() { return "To see the movie of the day, provide URL with month and day: " + "\t//localhost:8080/rest/resources/movies/<>/<>"; } /** * Obtain the movie of the day as indicated by the provided month and date. * * @param month Month for which movie of the day is desired. * @param date Date for which movie of the day is desired. * @return Title of the movie of the day for provided month and date. */ @GET @Path("/{month}/{date}") @Consumes("text/plain") @Produces("text/html") public String getMovieOfTheDay( @PathParam("month") final Integer month, @PathParam("date") final Integer date) { final Map moviesOfTheMonth = MOVIE_OF_THE_DAY.get(month-1); final String movieOfTheDay = moviesOfTheMonth != null ? moviesOfTheMonth.get(date) : "Fletch"; return movieOfTheDay != null ? generateHtml(movieOfTheDay, month, date) : generateHtml("Fletch Lives!", month, date); } private String generateHtml( final String movieTitle, final int movieMonth, final int movieDay) { final StringBuilder builder = new StringBuilder(); builder.append("") .append("Movie of the Day") .append("Movie of the Day") .append("
      

The movie of the day for ") .append(movieMonth) .append("/") .append(movieDay) .append(" is '") .append(movieTitle) .append("'.

"); return builder.toString(); } }

Der statische Initialisierungsblock ist nicht JAX-RS-spezifisch, sondern wird stattdessen zur Simulation einer Datenbank verwendet. In einer echten REST-Anwendung hätte ich mit ziemlicher Sicherheit eine Datenbank im Back-End, aber die statische In-Memory-Map simuliert dies hier.

Obwohl einfach, zeigt die obige Klasse die wichtigsten JAX-RS-Funktionen. Die interessantesten JAX-RS-Teile der Klasse sind die JAX-RS-Anmerkungen wie @Path, @GET, @Consumes, @Produces und @PathParam. Ich werde in diesem Beitrag nicht näher auf die Funktionsweise dieser JAX-RS-Anmerkungen eingehen, da mein Schwerpunkt auf der Verwendung von Jersey liegt. Weitere Hintergrundinformationen zu diesen Anmerkungen finden Sie im Kapitel zum Java EE 6-Lernprogramm zu REST mit Jersey.

Ich werde die mit JAX-RS annotierte Klasse in einer WAR-Datei mit der entsprechenden web.xmlDatei für GlassFish bereitstellen, wie im Folgenden gezeigt:

web.xml


    
      ServletAdaptor com.sun.jersey.spi.container.servlet.ServletContainer 1 ServletAdaptor /resources/* 30 
    

In meinem Fall hat NetBeans 6.8 diese web.xmlDatei automatisch für mich generiert, als ich die entsprechenden JAX-RS- und Jersey-JAR-Dateien zu den Bibliotheken meines Projekts hinzugefügt habe. Dies ist eine relativ einfache web.xmlDatei, da GlassFish JAX-RS kennt. (Auffallend ähnlich web.xmlfunktioniert die Bereitstellung von REST-Anwendungen auf Jersey-Basis für Tomcat, wie in Jason Drakes Blog-Beitrag Deploying Jersey in Tomcat 6.0 gezeigt.)

In meinem Beispiel wird eine aufgerufene WAR-Datei Rest1.wargeneriert. Der Inhalt wird im nächsten Screenshot angezeigt.

Wie aus dem Screenshot hervorgeht, sind in der generierten WAR-Datei JAX-RS- und Jersey-JAR-Dateien enthalten. Die Klasse MovieRestApplicationkann ignoriert werden, da sie nicht mit Jersey auf GlassFish verwendet wird. Dies bedeutet, dass die einzigen benutzerdefinierten Dateien in WAR die mit JAX-RS kommentierte Klasse MovieOfTheDay, die web.xmlDatei und die Indexseite ( index.jsp) sind. Der Inhalt der index.jspSeite wird als nächstes angezeigt.

index.jsp

    REST with JAX-RS Example   

Der nächste Screenshot zeigt die Bereitstellung der generierten WAR-Datei über die webbasierte Glass Administrative Console:

Das wichtigste Detail im Image der Bereitstellung der WAR-Datei ist, dass ich den Kontextstamm "rest" genannt habe. Dies ist Teil der URIs, über die auf meine bereitgestellten REST-Services zugegriffen wird. Die frühere web.xmlDatei hat auch gezeigt, dass resources/dies auch Teil dieses REST-Service-Zugriffs-URI sein wird. Der Rest des geeigneten URI basiert auf den Stücken des URI , die in den JAX-RS Anmerkungen auf der Java - Klasse ( /movies, /, und /{month}/{date}). Die mit geschweiften Klammern gekennzeichneten Teile des URI geben an, dass den Platzhaltern Werte aus der JAX-RS-Implementierung injiziert werden, die sich im aufrufenden URI befinden. Zum Beispiel, wenn der relevante Teil der URI war/7/4Dies würde in diesem Fall einen Monat von 7 (Juli, da Javas nullbasierter Monatsindex in der URI nicht verwendet wird) und einen Tag von 4 anzeigen.

When deployment is successful, the administrative console appears as shown in the next screen snapshot.

With the JAX-RS application deployed, I can now access it from a myriad of different clients. JAX-RS does not spell out a standardized approach for clients, but Jersey and most other popular JAX-RS implementations provide their own approach for building clients. Other HTTP/REST clients are also available such as RESTClient. For now, I'll simply use a web browser.

Placing the URI //localhost:8080/ in my browser displays the main page indicating that GlassFish is running:

If I add the web context (rest) to the URI, I see my index.jsp page:

To access the JAX-RS-powered REST applications, I need to add the resources portion of the URI as specified in the web.xml file. When I add this plus the /movies portion (as specified in the @Path annotation), I see the following page.

The above screen snapshot indicates that the GET access was invoked with the path "/" and the getMovie method was called. At this point, I can add a month and date to the URI to get a movie for that specific day. The next two screen snapshots demonstrate this for Groundhog Day and for Christmas Day.

As the above screen snapshots demonstrate, the months and days provided in the URIs are automatically injected by the JAX-RS provider into the parameters to the appropriate method. Now that's easy!

Conclusion

Die Bereitstellung eines JAX-RS-basierten Webdienstes mit Jersey und GlassFish ist relativ einfach. Alles, was ich wirklich brauchte, war der Zugriff auf die JAAR-RS- und Jersey-JARs, die ordnungsgemäß kommentierte Java-Klasse und die kurze web.xmlDatei, mit der Jersey als Servlet verwendet werden konnte. In diesem Blogbeitrag wurde versucht, die grundlegenden Schritte aufzuzeigen, die mit dem Schreiben einer einfachen, mit JAX-RS-Anmerkungen versehenen Klasse, der Bereitstellung in GlassFish und der Nutzung der JAX-RS-Implementierung von Jersey verbunden sind.

Andere Ressourcen

⇒ RESTful Web Services-Entwicklerhandbuch

⇒ RESTful Java, einige Links

⇒ JSR 311: Eine Java-API für RESTful Web Services?

⇒ Bereitstellen und Testen einer Jersey-Anwendung ohne NetBeans

⇒ Jersey 1.0: Erste Schritte

⇒ JSR-311 Javadoc-basierte API

Diese Geschichte "JAX-RS mit Jersey: Eine Einführung" wurde ursprünglich von JavaWorld veröffentlicht.