Manchmal braucht man in Java einen REST Server oder Client oder beides. Das ist mit dem Restlet Framework schnell implementiert.
Es kann entweder das ganze Beispielprojekt von Github geladen werden oder diese Schritte ausgeführt werden:
Zuerst richten wir in Eclipse ein neues Maven Projekt ein und fügen der pom.xml diese Einträge hinzu:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 |
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>de.wenzlaff.umgebung</groupId> <artifactId>de.wenzlaff.umgebung</artifactId> <packaging>jar</packaging> <version>1.0-SNAPSHOT</version> <name>RestUmgebung</name> <url>http://www.wenzlaff.info</url> <repositories> <repository> <id>maven-restlet</id> <name>Public online Restlet repository</name> <url>http://maven.restlet.org</url> </repository> </repositories> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <restlet-version>2.3.10</restlet-version> <maven.compiler.source>1.8</maven.compiler.source> <maven.compiler.target>1.8</maven.compiler.target> </properties> <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>3.6.1</version> <configuration> <source>1.8</source> <target>1.8</target> </configuration> </plugin> </plugins> </build> <dependencies> <!-- Java Standalone --> <dependency> <groupId>org.restlet.jse</groupId> <artifactId>org.restlet</artifactId> <version>${restlet-version}</version> </dependency> <dependency> <groupId>org.restlet.jse</groupId> <artifactId>org.restlet.ext.simple</artifactId> <version>${restlet-version}</version> </dependency> <!-- Java Jackson unterstüzung um Objekte zu serialisieren --> <dependency> <groupId>org.restlet.jee</groupId> <artifactId>org.restlet.ext.jackson</artifactId> <version>${restlet-version}</version> </dependency> <!-- Testframework JUnit --> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.12</version> <scope>test</scope> </dependency> </dependencies> </project> |
Den Standalone Server machen wir mit zwei Klassen:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 |
package de.wenzlaff.umgebung; import org.restlet.Component; import org.restlet.data.Protocol; /** * Ein Beispiel Standalone Server. * * @author Thomas Wenzlaff * */ public class StandaloneServer { public static final Integer PORT = 6969; public static final String HOST = "http://localhost:" + PORT; public static void main(String[] args) throws Exception { Thread t = new Thread(new Runnable() { @Override public void run() { try { StandaloneServer.start(); } catch (Exception e) { System.err.println(e.getMessage()); } } }); t.start(); } /** * Der Server mit der Hauptanwendung. * * Aufruf über * * http://localhost:9696/umgebung/ * * http://localhost:9696/umgebung/service * * http://localhost:9696/umgebung/version * * @param args * @throws Exception */ public static void start() throws Exception { Component component = new Component(); component.getServers().add(Protocol.HTTP, PORT); component.getDefaultHost().attach("/umgebung", new UmgebungsZiele()); component.start(); } } |
Und noch eine Klasse von Application erben und die Routen bzw. die URLs angeben:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 |
package de.wenzlaff.umgebung; import org.restlet.Application; import org.restlet.Restlet; import org.restlet.routing.Router; import de.wenzlaff.umgebung.resource.InfoResource; import de.wenzlaff.umgebung.resource.MindmapResource; import de.wenzlaff.umgebung.resource.UmgebungResource; import de.wenzlaff.umgebung.resource.VersionResource; /** * Bearbeitet alle Aufrufe für den Server. * * @author Thomas Wenzlaff * */ public class UmgebungsZiele extends Application { /** * Erzeugt den root Restlet der alle eingehende Aufrufe bearbeitet. * * http://localhost:9696/umgebung/ * * http://localhost:9696/umgebung/service * * http://localhost:9696/umgebung/version * */ @Override public synchronized Restlet createInboundRoot() { Router router = new Router(getContext()); router.attach("/", InfoResource.class); router.attach("/service", UmgebungResource.class); router.attach("/version", VersionResource.class); router.attach("/mindmap", MindmapResource.class); return router; } } |
Dann noch eine UmgebungResource anlegen, die von ServerResource erbt.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
package de.wenzlaff.umgebung.resource; import org.restlet.resource.Get; import org.restlet.resource.ServerResource; /** * Liefert die Systemumgebung. * * @author Thomas Wenzlaff * */ public class UmgebungResource extends ServerResource implements Umgebung { @Override @Get public String getUmgebung() { return "Umgebung:\n" + System.getProperties().toString().replaceAll(",", "\n"); } } |
Dafür auch gleich noch ein Interface mit Klassennamen Umgebung und der Annotation @get anlegen:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
package de.wenzlaff.umgebung.resource; import org.restlet.resource.Get; /** * Interface für die Umgebung. * * @author Thomas Wenzlaff * */ public interface Umgebung { @Get String getUmgebung(); } |
Das ist schon alles für den Server. Wir wollen das aber ja nicht nur über den Browser testen. Deshalb einen Client in einer JUnit Testklasse verpackt:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 |
package de.wenzlaff.umgebung; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; import org.junit.BeforeClass; import org.junit.Test; import org.restlet.resource.ClientResource; import de.wenzlaff.umgebung.resource.Mindmap; import de.wenzlaff.umgebung.resource.MindmapModell; import de.wenzlaff.umgebung.resource.Umgebung; import de.wenzlaff.umgebung.resource.Version; /** * Testklasse für den Server. * * @author Thomas Wenzlaff * */ public class ServerAppTest { @BeforeClass public static void startServer() throws Exception { StandaloneServer.start(); } @Test public void testGetUmgebungVersion() throws Exception { String hostUrl = StandaloneServer.HOST + "/umgebung/version"; System.out.println("Anfrage von: " + hostUrl); ClientResource clientResource = new ClientResource(hostUrl); Version resource = clientResource.wrap(Version.class); String vers = resource.getVersion(); System.out.println(vers); assertEquals("0.0.1", vers); } @Test public void testGetUmgebungService() throws Exception { String hostUrl = StandaloneServer.HOST + "/umgebung/service"; System.out.println("Anfrage von: " + hostUrl); ClientResource clientResource = new ClientResource(hostUrl); Umgebung resource = clientResource.wrap(Umgebung.class); String vers = resource.getUmgebung(); System.out.println(vers); assertTrue(vers.length() > 10); } /** * Benötigt org.restlet.ext.jackson in der pom.xml * * @throws Exception */ @Test public void testGetUmgebungMindmap() throws Exception { String hostUrl = StandaloneServer.HOST + "/umgebung/mindmap"; System.out.println("Anfrage von: " + hostUrl); ClientResource clientResource = new ClientResource(hostUrl); Mindmap resource = clientResource.wrap(Mindmap.class); MindmapModell m = resource.getMindmap(); if (m == null) { System.err.println("Es fehlt evl. die org.restlet.ext.jackson unterstüzung in der pom.xml"); return; } assertEquals("0.0.1", m.getVersion()); System.out.println("Mindmap Version: " + m.getVersion()); System.out.println("Mindmap Name: " + m.getName()); System.out.println("Erstellungs Datum: " + m.getErstellungsDatum()); System.out.println(m); } } |
Ist die Beschreibung ausführlich genug? Weitere Details siehe auch im Beispielprojekt auf Github.