我正在学习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)。
答案 0 :(得分:1)
我认为您感到困惑的是:错误消息如何传递到首页,因为在控制器中没有代码。我的理解正确吗?
简短答案:
的全局异常处理程序中完成的更多详细信息:
对于spring控制器来说是常见的,我们将使用全局异常处理程序来捕获从控制器方法中抛出的所有异常,但是异常本身可以来自服务代码。处理程序方法用@ExceptionHandler
注释。
因此“用户已存在”情况下错误消息的流程如下:
起初,这种流程可能不是很直观。但是一旦您了解了它,您将很高兴使用它。它可以节省很多代码来处理控制器中的错误。
我认为controllerAdvice是使用AOP实现的,这是一个非常强大的工具。如果您想了解更多,可以自己进一步研究。
关于验证错误处理:
异常处理程序继承ResponseEntityExceptionHandler,该处理程序处理来自请求有效负载验证的验证结果。请参阅处理程序的前两个重写方法。这对我也是新的,很高兴知道!