如何在春季返回错误消息 mvc@Controller

我正在使用这样的方法

@RequestMapping(method = RequestMethod.GET)
public ResponseEntity<UserWithPhoto> getUser(@RequestHeader(value="Access-key") String accessKey,
@RequestHeader(value="Secret-key") String secretKey){
try{
return new ResponseEntity<UserWithPhoto>((UserWithPhoto)this.userService.chkCredentials(accessKey, secretKey, timestamp),
new HttpHeaders(),
HttpStatus.CREATED);
}
catch(ChekingCredentialsFailedException e){
e.printStackTrace();
return new ResponseEntity<UserWithPhoto>(null,new HttpHeaders(),HttpStatus.FORBIDDEN);
}
}

当异常发生时,我想返回一些文本消息,但是现在我只返回 status 和 null 对象。有可能做到吗?

183648 次浏览

正如 索提里奥斯 · 德里马诺利斯在评论中已经指出的,有两种选择:

返回带有错误消息的 ResponseEntity

像这样改变你的方法:

@RequestMapping(method = RequestMethod.GET)
public ResponseEntity getUser(@RequestHeader(value="Access-key") String accessKey,
@RequestHeader(value="Secret-key") String secretKey) {
try {
// see note 1
return ResponseEntity
.status(HttpStatus.CREATED)
.body(this.userService.chkCredentials(accessKey, secretKey, timestamp));
}
catch(ChekingCredentialsFailedException e) {
e.printStackTrace(); // see note 2
return ResponseEntity
.status(HttpStatus.FORBIDDEN)
.body("Error Message");
}
}

注意1 : 您不必使用 ResponseEntity构建器,但我发现它有助于保持代码的可读性。它还有助于记住,针对特定 HTTP状态码的响应应该包括哪些数据。例如,状态代码为201的响应应该包含到 Location标头中新创建的资源的链接(参见 状态码定义)。这就是为什么 Spring 提供了方便的构建方法 ResponseEntity.created(URI)

注意2 : 不要使用 printStackTrace(),而是使用日志记录器。

提供 @ExceptionHandler

从方法中移除 try-catch 块,并让它抛出异常。然后在用 @ControllerAdvice注释的类中创建另一个方法,如下所示:

@ControllerAdvice
public class ExceptionHandlerAdvice {


@ExceptionHandler(ChekingCredentialsFailedException.class)
public ResponseEntity handleException(ChekingCredentialsFailedException e) {
// log exception
return ResponseEntity
.status(HttpStatus.FORBIDDEN)
.body("Error Message");
}
}

请注意,使用 @ExceptionHandler注释的方法允许具有非常灵活的签名。

还有一个选择。创建一个带有状态代码和消息的通用异常。然后创建一个异常处理程序。使用异常处理程序从异常中检索信息并返回给服务的调用方。

Http://javaninja.net/2016/06/throwing-exceptions-messages-spring-mvc-controller/

public class ResourceException extends RuntimeException {


private HttpStatus httpStatus = HttpStatus.INTERNAL_SERVER_ERROR;


public HttpStatus getHttpStatus() {
return httpStatus;
}


/**
* Constructs a new runtime exception with the specified detail message.
* The cause is not initialized, and may subsequently be initialized by a
* call to {@link #initCause}.
* @param message the detail message. The detail message is saved for later retrieval by the {@link #getMessage()}
*                method.
*/
public ResourceException(HttpStatus httpStatus, String message) {
super(message);
this.httpStatus = httpStatus;
}
}

然后使用异常处理程序检索信息并将其返回给服务调用方。

@ControllerAdvice
public class ExceptionHandlerAdvice {


@ExceptionHandler(ResourceException.class)
public ResponseEntity handleException(ResourceException e) {
// log exception
return ResponseEntity.status(e.getHttpStatus()).body(e.getMessage());
}
}

然后在需要时创建异常。

throw new ResourceException(HttpStatus.NOT_FOUND, "We were unable to find the specified resource.");
return new ResponseEntity<>(GenericResponseBean.newGenericError("Error during the calling the service", -1L), HttpStatus.EXPECTATION_FAILED);

计算调用的另一个服务的错误响应..。

这是我评估错误的解决方案:

try {
return authenticationFeign.signIn(userDto, dataRequest);
}catch(FeignException ex){


//ex.status();


if(ex.status() == HttpStatus.UNAUTHORIZED.value()){
System.out.println("is a error 401");
return new ResponseEntity<>(HttpStatus.UNAUTHORIZED);
}
return new ResponseEntity<>(HttpStatus.OK);


}