给出以下dto和控制器
public class PasswordCredentials implements AuthenticationProvider {
@NotNull
@NotEmpty
@JsonProperty( access = JsonProperty.Access.WRITE_ONLY )
private String user;
@NotNull
@NotEmpty
@JsonProperty( access = JsonProperty.Access.WRITE_ONLY )
private CharSequence pass;
public void setPass( final CharSequence pass ) {
this.pass = pass;
}
public void setUser( final String user ) {
this.user = user;
}
@Override
public Authentication toAuthentication() {
return new UsernamePasswordAuthenticationToken( user, pass );
}
}
@RestController
@RequestMapping( path = "authentication" )
class AuthenticationController {
private final AuthenticationManager am;
AuthenticationController( final AuthenticationManager am ) {
this.am = am;
}
@RequestMapping( path = "password", method = RequestMethod.POST, consumes = {
"!" + MediaType.APPLICATION_FORM_URLENCODED_VALUE
} )
ResponseEntity<?> login( @Valid @RequestBody final PasswordCredentials credentials ) {
Authentication authenticate = am.authenticate( credentials.toAuthentication() );
if ( authenticate.isAuthenticated() ) {
return ResponseEntity.status( HttpStatus.NO_CONTENT ).build();
}
return ResponseEntity.status( HttpStatus.FORBIDDEN ).build();
}
}
如果例如pass
为空,则会出现验证错误,并且在没有调用我的控制器的情况下会发生400,这很好。然而,400有没有内容,有没有办法让控制器BindResults
作为内容输出,以便API的消费者知道导致问题的原因?理想情况下我不会这样做控制器方法,以便它会发生在所有控制器上?
我能够通过如下弹簧数据休息获得此行为,但我喜欢所有API控制器。
class RestConfig extends RepositoryRestConfigurerAdapter {
@Bean
Validator validator() {
return new LocalValidatorFactoryBean();
}
@Override
public void configureValidatingRepositoryEventListener(
final ValidatingRepositoryEventListener validatingListener ) {
Validator validator = validator();
//bean validation always before save and create
validatingListener.addValidator( "beforeCreate", validator );
validatingListener.addValidator( "beforeSave", validator );
}
@Override
public void configureRepositoryRestConfiguration( final RepositoryRestConfiguration config ) {
config.setBasePath( "/v0" );
config.setReturnBodyOnCreate( false );
config.setReturnBodyOnUpdate( false );
}
答案 0 :(得分:0)
Spring有@ControllerAdvice
和@ExceptionHandler
注释来处理控制器中的错误。
@ControllerAdvice
public class ExceptionTranslator {
@ExceptionHandler(MethodArgumentNotValidException.class)
@ResponseStatus(HttpStatus.BAD_REQUEST)
@ResponseBody
public Error processValidationError(MethodArgumentNotValidException ex) {
BindingResult result = ex.getBindingResult();
.....
return new Error();
}
// Other exceptions
}
答案 1 :(得分:0)
我想改进Anton Novopashin的答案:只返回响应实体中的错误。
@ControllerAdvice
public class ExceptionTranslator {
@ExceptionHandler(MethodArgumentNotValidException.class)
@ResponseBody
public ResponseEntity<String> processValidationError(MethodArgumentNotValidException ex) {
return new ResponseEntity(ex.getMessage, HttpStatus.BAD_REQUEST);
}
// Other exceptions
}
答案 2 :(得分:0)
我不确定是谁或为什么对现有答案进行了低估,但它们都是正确的 - 处理验证错误的最佳方法是声明@ControllerAdvice
然后处理那里的例外。这是我的全局错误处理程序的片段,取自现有项目:
@ControllerAdvice
@ResponseBody
public class RestfulErrorHandler {
@ResponseStatus(HttpStatus.BAD_REQUEST)
@ExceptionHandler(MethodArgumentNotValidException.class)
public ErrorResponse methodValidationError(MethodArgumentNotValidException e) {
final ErrorResponse response = new ErrorResponse();
for (ObjectError error : e.getBindingResult().getAllErrors()) {
if (error instanceof FieldError) {
response.addFieldError((FieldError) error);
} else {
response.addGeneralError(error.getDefaultMessage());
}
}
return response;
}
@ResponseStatus(HttpStatus.BAD_REQUEST)
@ExceptionHandler(ConstraintViolationException.class)
public ErrorResponse constraintViolationError(ConstraintViolationException e) {
final ErrorResponse response = new ErrorResponse();
for (ConstraintViolation<?> v : e.getConstraintViolations()) {
response.addFieldError(v.getPropertyPath(), v.getMessage());
}
return response;
}
}
您也应该处理ConstraintViolationException
,因为它们也可能被抛出。这是a link to my ErrorResponse
class,我将其作为一个要点包括在内,以免模糊主要观点。
您还应该处理RepositoryConstraintViolationException
,我不确定spring-data-rest
是否已经处理过它们。