Die Registrierungs-API wird RESTful

Die Registrierungs-API wird RESTful

1. Überblick

In den letzten Artikeln vonthe Registration series here on example haben wir den größten Teil der benötigten Funktionalität auf MVC-Weise erstellt.

Wir werden jetzt einige dieser APIs auf einen RESTful-Ansatz umstellen.

2. DieRegister Operation

Beginnen wir mit der Hauptregisteroperation:

@RequestMapping(value = "/user/registration", method = RequestMethod.POST)
@ResponseBody
public GenericResponse registerUserAccount(
      @Valid UserDto accountDto, HttpServletRequest request) {
    logger.debug("Registering user account with information: {}", accountDto);
    User registered = createUserAccount(accountDto);
    if (registered == null) {
        throw new UserAlreadyExistException();
    }
    String appUrl = "http://" + request.getServerName() + ":" +
      request.getServerPort() + request.getContextPath();

    eventPublisher.publishEvent(
      new OnRegistrationCompleteEvent(registered, request.getLocale(), appUrl));

    return new GenericResponse("success");
}

Wie unterscheidet sich das von der ursprünglichen MVC-fokussierten Implementierung?

Hier geht:

  • Die Anforderung ist jetzt korrekt einem HTTP-POST zugeordnet

  • Wir geben jetzt ein ordnungsgemäßes DTO zurück und leiten es über die Annotation@ResponseBodydirekt in den Hauptteil der Antwort ein

  • Wir beschäftigen uns überhaupt nicht mehr mit der Fehlerbehandlung in der Methode

Wir entfernen auch die altenshowRegistrationPage(), da dies nicht erforderlich ist, um einfach die Registrierungsseite anzuzeigen.

3. Dieregistration.html

Mit diesen Änderungen müssen wir nun dieregistration.html ändern in:

  • Verwenden Sie Ajax, um das Registrierungsformular einzureichen

  • Erhalten Sie die Ergebnisse der Operation als JSON

Hier geht:



form


4. Ausnahmebehandlung

Neben der RESTful-API wird natürlich auch die Ausnahmebehandlungslogik ausgereifter.

Wir verwenden denselben@ControllerAdvice-Mechanismus, um von der Anwendung ausgelöste Ausnahmen sauber zu behandeln - und jetzt müssen wir einen neuen Ausnahmetyp verwenden.

Dies istBindException - wird ausgelöst, wennUserDtovalidiert wird (falls ungültig). Wir überschreiben die StandardmethodeResponseEntityExceptionHandlerhandleBindException(), um die Fehler im Antworttext hinzuzufügen:

@Override
protected ResponseEntity handleBindException
  (BindException ex, HttpHeaders headers, HttpStatus status, WebRequest request) {
    logger.error("400 Status Code", ex);
    BindingResult result = ex.getBindingResult();
    GenericResponse bodyOfResponse =
      new GenericResponse(result.getFieldErrors(), result.getGlobalErrors());

    return handleExceptionInternal(
      ex, bodyOfResponse, new HttpHeaders(), HttpStatus.BAD_REQUEST, request);
}


Wir müssen auch unsere benutzerdefiniertenExceptionUserAlreadyExistException verarbeiten - die ausgelöst werden, wenn sich der Benutzer mit einer bereits vorhandenen E-Mail registriert:

@ExceptionHandler({ UserAlreadyExistException.class })
public ResponseEntity handleUserAlreadyExist(RuntimeException ex, WebRequest request) {
    logger.error("409 Status Code", ex);
    GenericResponse bodyOfResponse = new GenericResponse(
      messages.getMessage("message.regError", null, request.getLocale()), "UserAlreadyExist");

    return handleExceptionInternal(
      ex, bodyOfResponse, new HttpHeaders(), HttpStatus.CONFLICT, request);
}




5. DieGenericResponse

Wir müssen auch die Implementierung vonGenericResponseverbessern, um diese Validierungsfehler zu beheben:

public class GenericResponse {

    public GenericResponse(List fieldErrors, List globalErrors) {
        super();
        ObjectMapper mapper = new ObjectMapper();
        try {
            this.message = mapper.writeValueAsString(fieldErrors);
            this.error = mapper.writeValueAsString(globalErrors);
        } catch (JsonProcessingException e) {
            this.message = "";
            this.error = "";
        }
    }
}

6. UI - Feld- und globale Fehler

Lassen Sie uns abschließend sehen, wie Sie mit jQuery sowohl Feld- als auch globale Fehler behandeln:

var serverContext = [[function register(){
    $(".alert").html("").hide();
    var formData= $('form').serialize();
    $.post(serverContext + "/user/registration",formData ,function(data){
        if(data.message == "success"){
            window.location.href = serverContext +"/successRegister.html";
        }
    })
    .fail(function(data) {
        if(data.responseJSON.error.indexOf("MailError") > -1)
        {
            window.location.href = serverContext + "/emailError.html";
        }
        else if(data.responseJSON.error.indexOf("InternalError") > -1){
            window.location.href = serverContext +
              "/login.html?message=" + data.responseJSON.message;
        }
        else if(data.responseJSON.error == "UserAlreadyExist"){
            $("#emailError").show().html(data.responseJSON.message);
        }
        else{
            var errors = $.parseJSON(data.responseJSON.message);
            $.each( errors, function( index,item ){
                $("#"+item.field+"Error").show().html(item.defaultMessage);
            });
            errors = $.parseJSON(data.responseJSON.error);
            $.each( errors, function( index,item ){
                $("#globalError").show().append(item.defaultMessage+"
"); }); } }

Beachten Sie, dass:

  • Wenn Validierungsfehler vorliegen, enthält das Objektmessagedie Feldfehler und das Objekterrorglobale Fehler

  • Wir zeigen jeden Feldfehler neben seinem Feld an

  • Wir zeigen alle globalen Fehler an einer Stelle am Ende des Formulars an

7. Fazit

Der Fokus dieses kurzen Artikels liegt darauf, die API in eine REST-konformere Richtung zu lenken und eine einfache Art des Umgangs mit dieser API im Front-End zu zeigen.

Das jQuery-Front-End selbst steht nicht im Mittelpunkt - es ist lediglich ein grundlegender potenzieller Client, der in einer beliebigen Anzahl von JS-Frameworks implementiert werden kann, während die API genau gleich bleibt.

Diefull implementation dieses Tutorials finden Sie inthe github project - dies ist ein Eclipse-basiertes Projekt, daher sollte es einfach zu importieren und auszuführen sein.