2012-04-04 19 views
4

Dies muss zuvor beantwortet worden sein, aber meine Google-Befugnisse sind heute deaktiviert und ich habe damit ein wenig gekämpft. Wir migrieren von einer alten PHP-Basis zu einem Jersey-basierten JVM-Stack, der letztendlich eine JSON-basierte RESTful-API bereitstellt, die von vielen Anwendungen genutzt werden kann. Die Dinge waren bisher sehr gut und wir lieben die einfache Konvertierung von POJO in JSON. Wir haben jedoch Probleme mit domainübergreifenden JSON-Anfragen. Wir haben im Wesentlichen alle unsere Antworten, die JSON (mit @Products ("application/json") und dem com.sun.jersey.api.json.POJOMappingFeature auf true) zurückgeben, aber für die JSONP-Unterstützung müssen wir unsere Methoden ändern, um ein zurückzuliefern Instanz von JSONWithPadding. Dies erfordert natürlich auch, dass wir jeder Methode einen @QueryParam ("Callback") - Parameter hinzufügen, der unsere Bemühungen im Wesentlichen vervielfältigt, sodass zwei Methoden erforderlich sind, um mit denselben Daten zu antworten, je nachdem, ob ein Callback-Parameter vorhanden ist oder nicht in der Anfrage. Das wollen wir natürlich nicht.Javas Jersey, RESTful-API und JSONP

Also haben wir im Wesentlichen ein paar verschiedene Möglichkeiten ausprobiert. Ich bin mir sicher, dass dieses Problem gelöst wurde. Ich habe von einigen Stellen gelesen, dass ich einen Anforderungsfilter schreiben könnte oder ich den JSON Provider erweitern könnte. Meine ideale Lösung ist, keinen Einfluss auf unsere Daten oder Logiklayer zu haben und stattdessen Code zu haben, der sagt: "Wenn es einen Rückrufparameter gibt, umgebe den JSON mit dem Callback, sonst gib einfach den JSON zurück". Eine Lösung wurde hier gefunden: http://jersey.576304.n2.nabble.com/JsonP-without-using-JSONWithPadding-td7015082.html

Diese Lösung erweitert jedoch das Jackson JSON-Objekt, nicht der Standard-JSON-Anbieter.

Was sind die besten Praktiken? Wenn ich auf der richtigen Spur bin, was ist die Klasse für den Standard-JSON-Filter, den ich erweitern kann? Ist eine zusätzliche Konfiguration erforderlich? Bin ich völlig verrückt?

Antwort

5

Wenn alle Ressourcenmethoden das JSONWithPadding-Objekt zurückgeben, ermittelt Jersey automatisch, ob JSON (dh nur das umschlossene Objekt) oder der Rückruf basierend auf dem angeforderten Medientyp zurückgegeben werden soll - dh ob der Medientyp angefordert wurde Wenn der Client eine Anwendung/javascript, application/x-javascript, text/ecmascript, application/ecmascript oder text/jscript verwendet, gibt Jersey das vom Callback umschlossene Objekt zurück. Wenn der angeforderte Medientyp die Anwendung/json ist, gibt Jersey das JSON-Objekt zurück (d. H. Es wird nicht mit dem Rückruf umbrochen). Eine Möglichkeit, dies zu erreichen, besteht darin, dass Sie mit Ihrer Ressourcenmethode alle oben genannten Medientypen (einschließlich application/json) erstellen, JSONWithPadding immer zurückgeben und Jersey herausfinden lassen, was zu tun ist.

Wenn dies nicht für Sie arbeiten, lassen Sie uns wissen, warum es nicht Ihren Anwendungsfall abdeckt (an Anwender bei jersey.java.net). In diesem Fall können Sie ContainerRequest/ResponseFilters verwenden. Im Anforderungsfilter können Sie die Anforderungsheader beliebig ändern (z. B. den Accept-Header anpassen), um sicherzustellen, dass sie mit der richtigen Ressourcemethode übereinstimmt. Dann können Sie im Antwortfilter die Antworteinheit mithilfe von JSONWithPadding umbrechen, je nachdem, ob der Rückrufabfrageparameter verfügbar ist, und den Inhaltstypheader anpassen.

+1

Das Problem ist, dass jQuery standardmäßig einen Akzeptiert * Header sendet, also den angeforderten MIME-Typ und sendet application/json als Anfrage, auch wenn der angegebene Typ jsonp ist. Ich tippe ein, was ich schließlich in einer anderen Antwort arbeiten konnte, aber kurz gesagt habe ich einen Filter und Wrapper außerhalb von Jersey geschrieben, um einfach nach dem Vorhandensein des Callback-Parameters für eine JSON-Anfrage zu suchen und, falls vorhanden, den Rückruf hinzuzufügen die Antwortausgabe. Danke für die Antwort! –

1

Also, was ich schließlich tun endete (vor Martins große Resonanz kam) war ein Filter und eine ResponseWrapper schaffen, die die Ausgabe abgefangen. Die Basis für den Code ist bei http://docs.oracle.com/cd/B31017_01/web.1013/b28959/filters.htm

im Wesentlichen die Filter überprüft, ob der Rückruf-Parameter vorhanden ist, um zu sehen. Wenn dies der Fall ist, wird der Rückruf an den ausgegebenen JSON vorgezogen und am Ende angehängt. Dies funktioniert bei unseren Tests sehr gut, obwohl es noch nicht gehärtet wurde. Obwohl ich es geliebt hätte, wenn Jersey automatisch damit umgehen könnte, konnte ich nicht richtig mit jQuery arbeiten (wahrscheinlich etwas auf meiner Seite, kein Problem mit Jersey). Wir haben bereits existierende jQuery-Aufrufe und wir ändern die URLs, um den neuen Jersey Server zu sehen, und wir wollten wirklich nicht in jeden $ .ajax-Aufruf gehen, um Header oder Inhaltstypen in den Aufrufen zu ändern, wenn wir dies nicht taten müssen, zu ... haben.

Abgesehen von der kleinen Frage, Jersey war großartig, mit zu arbeiten!