Spring Boot用户注册-将验证错误发送到UI

时间:2018-12-21 22:27:02

标签: java spring spring-boot thymeleaf

我正在学习Springboot,并尝试遵循在Baeldung示例Registration Process中进入UI的注册错误。但是,Baeldung网站上的实施与链接的Baeldung Github项目不同。

在网页上的示例中,他们有一个注册控制器,如下所示:

@RequestMapping(value = "/user/registration", method = RequestMethod.POST)
public ModelAndView registerUserAccount
  (@ModelAttribute("user") @Valid UserDto accountDto, 
  BindingResult result, WebRequest request, Errors errors) {    
     User registered = new User();
     if (!result.hasErrors()) {
        registered = createUserAccount(accountDto, result);
      }
     if (registered == null) {
        result.rejectValue("email", "message.regError");
     }
   // rest of the implementation
}

private User createUserAccount(UserDto accountDto, BindingResult result) {
  User registered = null;
  try {
      registered = service.registerNewUserAccount(accountDto);
  } catch (EmailExistsException e) {
      return null;
  }    
  return registered;
}

具有的相应HTML:

<div>
    <label th:text="#{label.user.email}">email</label>
    <input type="email" th:field="*{email}"/>
    <p th:each="error : ${#fields.errors('email')}" h:text="${error}">Validation error</p>
</div>

我知道createUserAccount方法会引发异常并抛出错误,最终会被添加到通过百里香煮成HTML的结果对象中。

但是,在同一网页上的链接的github项目中,实现方式却大不相同,而且我不了解错误是如何导致UI出现的。

controller现在看起来像:

    @RequestMapping(value = "/user/registration", method = RequestMethod.POST)
    @ResponseBody
    public GenericResponse registerUserAccount(@Valid final UserDto accountDto, final HttpServletRequest request) {
    LOGGER.debug("Registering user account with information: {}", accountDto);
    final User registered = userService.registerNewUserAccount(accountDto);
    eventPublisher.publishEvent(new OnRegistrationCompleteEvent(registered, request.getLocale(), getAppUrl(request)));
    return new GenericResponse("success");
    }

这将调用registerNewUserAccount方法,如下所示:

    @Override
    public User registerNewUserAccount(final UserDto accountDto) {
    if (emailExist(accountDto.getEmail())) {
        throw new UserAlreadyExistException("There is an account with that email adress: " + accountDto.getEmail());
    }
    // rest of method

UserAlreadyExistException类看起来像:

public final class UserAlreadyExistException extends RuntimeException {

    public UserAlreadyExistException() {
        super();
    }

    public UserAlreadyExistException(final String message, final Throwable cause) {
        super(message, cause);
    }

    public UserAlreadyExistException(final String message) {
        super(message);
    }

    public UserAlreadyExistException(final Throwable cause) {
        super(cause);
    }
}

即使registration HTML现在有所不同,并且似乎没有使用Thymeleaf来处理错误:

<div class="form-group row">
    <label class="col-sm-3" th:text="#{label.user.email}">email</label>
    <span class="col-sm-5"><input type="email" class="form-control" name="email" value="" required="required"/></span>                    
    <span id="emailError" class="alert alert-danger col-sm-4" style="display:none"></span>
</div>
  

所有这些都构成了一个问题:如何处理此异常以及   相关消息冒泡回到UI?在原始示例的实现中,UI中会出现各种错误(例如@NotEmtpty)。

1 个答案:

答案 0 :(得分:1)

我认为您感到困惑的是:错误消息如何传递到首页,因为在控制器中没有代码。我的理解正确吗?

简短答案:

这是在位于https://github.com/Baeldung/spring-security-registration/blob/master/src/main/java/org/baeldung/web/error/RestResponseEntityExceptionHandler.java

的全局异常处理程序中完成的

更多详细信息:

对于spring控制器来说是常见的,我们将使用全局异常处理程序来捕获从控制器方法中抛出的所有异常,但是异常本身可以来自服务代码。处理程序方法用@ExceptionHandler注释。

因此“用户已存在”情况下错误消息的流程如下:

  1. 前端javascript执行所有本地验证,例如电子邮件格式,密码长度等。只有当所有这些验证都通过后,它才会调用api来注册新用户。
  2. 控制器收到注册用户的请求。
  3. 控制器调用服务方法来注册新用户。
  4. 服务方法在检测到时会引发已经存在的异常。
  5. controller没有捕获到异常,因此它被排除在controller方法之外。
  6. 全局控制器异常处理程序捕获了该异常并生成错误响应dto,填充了message.properties为错误响应的相应区域设置提供的错误消息。这些属性位于src / main / resources中,并且文件名声明了语言环境。填充错误响应后,将其返回,以便spring将这个对象响应到前端。
  7. 前端收到响应。 javascript检查是否错误。如果是,它将检查将要处理的错误类型。

起初,这种流程可能不是很直观。但是一旦您了解了它,您将很高兴使用它。它可以节省很多代码来处理控制器中的错误。

我认为controllerAdvice是使用AOP实现的,这是一个非常强大的工具。如果您想了解更多,可以自己进一步研究。

关于验证错误处理:

异常处理程序继承ResponseEntityExceptionHandler,该处理程序处理来自请求有效负载验证的验证结果。请参阅处理程序的前两个重写方法。这对我也是新的,很高兴知道!