Рубрики
Без рубрики

API регистрации становится спокойным

Сделать API регистрации более спокойным и адаптировать интерфейс для его правильного использования.

Автор оригинала: Eugen Paraschiv.

1. Обзор

В последних нескольких статьях серии регистрации здесь , на Baeldung, мы построили большую часть необходимой нам функциональности в стиле MVC.

Теперь мы собираемся перевести некоторые из этих API на более спокойный подход.

2. Операция Регистрации

Давайте начнем с основной операции с регистром:

@PostMapping("/user/registration")
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");
}

Итак, как это отличается от первоначальной реализации, ориентированной на MVC?

Вот так:

  • теперь запрос правильно сопоставлен с HTTP-сообщением
  • теперь мы возвращаем правильный DTO и сортируем его непосредственно в тело ответа
  • мы больше не имеем дело с обработкой ошибок в методе вообще

Мы также удаляем старую showRegistrationPage() – поскольку это не нужно для простого отображения страницы регистрации.

3. registration.html

С учетом этих изменений нам теперь необходимо изменить registration.html к:

  • используйте Ajax для отправки регистрационной формы
  • получите результаты операции в формате JSON

Вот так:

4. Обработка исключений

Наряду с более спокойным API, логика обработки исключений, конечно, также станет более зрелой.

Мы используем один и тот же механизм @ControllerAdvice для чистой обработки исключений, создаваемых приложением, – и теперь нам нужен новый тип исключений.

Это исключение BindException – которое возникает при проверке UserDTO (если оно неверно). Мы переопределим по умолчанию ResponseEntityExceptionHandler метод handleBindException () , чтобы добавить ошибки в тело ответа:

@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);
}

Нам также нужно будет обработать наше пользовательское Исключение | UserAlreadyExistException – которое возникает, когда пользователь регистрируется по электронной почте, которая уже существует:

@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. Общий Ответ

Нам также необходимо улучшить реализацию Generic Response , чтобы избежать этих ошибок проверки:

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 – Поле и глобальные ошибки

Наконец, давайте посмотрим, как обрабатывать как полевые, так и глобальные ошибки с помощью jQuery:

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+"
"); }); } }

Обратите внимание, что:

  • Если есть ошибки проверки – то объект message содержит ошибки полей, а объект error содержит глобальные ошибки
  • Мы показываем каждую ошибку поля рядом с его полем
  • Мы показываем все глобальные ошибки в одном месте в конце формы

7. Заключение

Цель этой краткой статьи-перевести API в более спокойное русло и показать простой способ работы с этим API в интерфейсе.

Сам интерфейс jQuery не является фокусом – просто базовый потенциальный клиент, который может быть реализован в любом количестве фреймворков JS, в то время как API остается точно таким же.

полную реализацию этого учебника можно найти в проекте github – это проект на основе Eclipse, поэтому его должно быть легко импортировать и запускать как есть.