2017-07-16 4 views
0

Wir müssen eine große Anzahl von JSON API-Aufrufen in einer Grails 3.3 Web App implementieren.grails 3: Gibt es eine Möglichkeit, den Duplikat-Code in diesem API-Beispiel zu extrahieren?

Leider ist der Build jeder Methode Fehlerbehandlung, und derzeit kopieren wir diesen Code in jeder Methode, die ein Maintenance Kopfschmerz ist (wenn wir Fehlerbehandlung verbessern, müssen wir 70 + Methoden zu aktualisieren). Gibt es einen besseren Weg mit weniger doppelten Fehlercode? Ein Muster, das den Fehlerprüfcode an einer Stelle extrahieren kann?

FYI Wir verwenden den super einfachen und effektiven Objekt Marshaller, um den JSON in der Art und Weise zu rendern, wie wir brauchen. Leider ignoriert das render() {...} -Muster Objekt-Marshaller, daher müssen wir in diesem Fall JSONBuilder verwenden.

A wird richtig Login so etwas wie diese geben:

{"result":"0","user":{"username":"bob","userId":"123"},"accounts":[{"balance":"0.00","currencyIso":"USD","id":1}]} 

Ein Fehler würde wie folgt aussehen:

{"result":"9999","message":"exception in xxx"} 

Wir haben eine lange Liste von Ergebniscodes (ca. 70), so dass der Kunde weiß, genau das, was war der Fehler (Wir HTTP-Statuscodes für diese nicht verwenden, da sie nicht überhaupt Karte)

class LoginCommand implements grails.validation.Validateable { 
    String username 
    String password 
    static constraints = { 
     username nullable:false, blank: false, size: 3..32 
     password nullable:false, blank: false, size: 3..32 
    } 

} 

class UserApiController { 
def login(LoginCommand cmd) { 
    try { 
     if (cmd.hasErrors()) { 
      log.error("invalid parameters") 
      render(status: 400, contentType: 'application/json') { 
        result 10 
        message "errors in parameters" 
      return 
      } 
     } else { 
      User user = User.findByUsernameAndPassword(cmd.username, cmd.password) 
      def userAccounts = Account.findAllByUser(user) 

      if (user == null) { 
       render(status: 404, contentType: 'application/json') { 
        result 100 
        message "could not find user with that username and pass" 
       } 
      } else { 

       def builder = new JSONBuilder() 
       def json = builder.build { 
        result= "0" 
        user= { 
         username=user.username 
         userId=user.id 
        } 
        accounts=playerAccounts 
       } 
       render(status: 200, contentType: 'application/json', text: json)     
      } // else all good 
     } // else params ok 

    } catch (Exception e) { 
     log.error("Caught Exception in UserApiController.login()", e) 
     render(status: 500, contentType: 'application/json') { 
       result 9999 
       message e.toString() 
     } 
    } 
} 

Wir haben uns kurz die Ansichten von json angeschaut, aber wir glauben nicht, dass uns das weiterhilft, es ist komplex und da unser Projekt nicht mit der Rest-API erstellt wurde, haben wir keinen Zugriff darauf.

Antwort

0

Ein paar Hinweise, die dir helfen könnten:

  • Wenn Sie die gesamte Login-Funktionalität wollen von mehreren Anwendungen wiederverwendet werden, sollten Sie eine Grails Plugin zu schaffen. Ein Plugin ist ein Grails-spezifisches JAR-Projekt, das wiederverwendbare Artefakte wie Controller und Dienste hosten kann.

http://docs.grails.org/latest/guide/plugins.html

  • Sie sollten einen globalen Fehlerhandler, anstatt tun eine allgemeine try...catch() in Ihrem gesamten Controller-Methode einrichten. Siehe:

Exception handling in Grails controllers

  • Wenn Sie JSON Ansichten möchten, können Sie es auf eine bestehende App installieren können, auch wenn die App nicht gebaut wurde das REST-Profil. Die JSON-Ansichten sind sehr nützlich, wenn Sie Ihre Ausgabe anpassen möchten, aber Sie möchten auch, dass Probleme zwischen dem Controller und der Ansicht getrennt werden.

http://views.grails.org/latest/#_installation

  • Für diesen speziellen Anwendungsfall haben, können Sie auch einen Blick auf die Spring Security Grails Plugins haben.

https://plugins.grails.org/q/spring-security

  • Ihre Controller-Code, um aufzuräumen, betrachten Sie Ihre Business-Logik zu einem Service-Methode zu extrahieren.Sie können entweder ein standardisiertes Befehlsobjekt für Ihre Ausgabe erstellen oder einen benutzerdefinierten RuntimeException-Subtyp (MyLoginFailureException) verwenden, um eine fehlgeschlagene Anmeldung zu signalisieren und den Grund- und Ergebniscode zurückzugeben.
Verwandte Themen