从服务器抛出的自定义错误未在客户端的 HttpErrorResponse 中返回

Posted

技术标签:

【中文标题】从服务器抛出的自定义错误未在客户端的 HttpErrorResponse 中返回【英文标题】:CustomError throw from server not return in HttpErrorResponse in clientside 【发布时间】:2019-06-22 00:00:35 【问题描述】:

您好,我对 Spring 和 Angular 还是很陌生。我正在构建一个 Spring Java 服务器和一个 Angular 客户端。基本上,我希望客户端能够捕获服务器抛出的异常。我定义了一个 CustomExeption.java 类并在服务器端有一个 CustomRestExcepotionHandler.java。现在我不确定我应该在服务器中的哪里抛出异常以供客户端捕获。

我正在学习教程:https://www.baeldung.com/global-error-handler-in-a-spring-rest-api

现在它在 HttpErrorResponse 中向客户端返回 500 Internal Server Error 错误消息。

我希望它返回我的自定义异常消息。有人可以帮我看看服务器端代码是否有任何问题。为什么 HttpErrorResponse 没有捕捉到 CustomException 抛出?谢谢!

 public class ApiError 

    private HttpStatus status;
    private String message;
    private List<String> errors;

    public ApiError(HttpStatus status, String message, List<String> errors) 
        super();
        this.status = status;
        this.message = message;
        this.errors = errors;
    

    public ApiError(HttpStatus status, String message, String error) 
        super();
        this.status = status;
        this.message = message;
        errors = Arrays.asList(error);
    

    public HttpStatus getStatus() 
        // TODO Auto-generated method stub
        return status;
    

    public String getMessage() 
        // TODO Auto-generated method stub
        return message;
    

---

--------异常处理程序

@ControllerAdvice
public class CustomRestExceptionHandler extends ResponseEntityExceptionHandler 
    @Override
    protected ResponseEntity<Object> handleExceptionInternal(Exception ex, Object body, HttpHeaders headers,
            HttpStatus status, WebRequest request) 

         ApiError apiError = 
                  new ApiError(status, ex.getMessage(), ex.getMessage());
                return handleExceptionInternal(
                  ex, apiError, headers, apiError.getStatus(), request);
            

    protected ResponseEntity<Object> handleResponseStatusException(ResponseStatusException ex,Object body, HttpHeaders headers,
            HttpStatus status, WebRequest request )
         ApiError apiError = 
                  new ApiError(status, ex.getMessage(), ex.getMessage());
         return handleExceptionInternal(
                  ex, apiError, headers, apiError.getStatus(), request);
            



public ResponseEntity<AtlasJWT> signInUser(String userName, String password) String userId = "(uid=" + userName + ")";
if (ldapTemplate.authenticate("", userId, password)) 
                log.info("ldapTemplate.authenticate returned true");

                Optional<AtlasUser> optLoggedInUser = userRepository.findByUsername(userName);
                AtlasJWT atlasJwtToken = jwtTokenProvider.createAtlasJwtToken(optLoggedInUser.get());
                if (optLoggedInUser.isPresent()) 
                    log.info("Atlas JWT: ", atlasJwtToken);
                    return new ResponseEntity<AtlasJWT>(atlasJwtToken, HttpStatus.OK);
                 else 
                    //ApiError error = new ApiError(HttpStatus.BAD_REQUEST,"No such User found in the Atlas Database","No such User found in the Atlas Database");
                    throw new CustomException("No such User found in the Atlas Database",HttpStatus.FORBIDDEN);
                

             else 
                //ApiError error = new ApiError(HttpStatus.FORBIDDEN,"Invalid username/password supplied","Invalid username/password supplied");
                throw new CustomException("Invalid username/password supplied", HttpStatus.FORBIDDEN);

            

    

我的客户端登录组件如下:

  login(username: string, password: string) 
    console.log('Inside AuthenticationService. Username: ', username);

    // const body = `username=$encodeURIComponent(username)&password=$encodeURIComponent(password)&grant_type=password`;

    const body = 
      'username': username,
      'password': password
    ;

    const httpOptions = 
      headers: new HttpHeaders(
          'Content-Type': 'application/json',
      )
    ;

    console.log('Invoking server authentication for username', username);

    return this.http.post<AtlasJWT>('/auth/api/signin', body, httpOptions).pipe(catchError(this.handleError));
  

   private handleError(err: HttpErrorResponse) 
    // in a real world app, we may send the server to some remote logging infrastructure
    // instead of just logging it to the console
    let errorMessage = '';
    if (err.error instanceof ErrorEvent) 
      // A client-side or network error occurred. Handle it accordingly.
      errorMessage = err.message;
      // console.log(err);
     else 
      // The backend returned an unsuccessful response code.
      // The response body may contain clues as to what went wrong,
      errorMessage = `Server returned code: $err.status, error message is: $err.message`;
      console.log(err);
    
    console.error(errorMessage);
    return throwError(errorMessage);
  

【问题讨论】:

【参考方案1】:

我觉得这很有帮助。增加了@ResponseBody 和@ResponseStatus 的注解。

我也尝试了这段代码,添加到我的控制器类中。两者都在工作

@ExceptionHandler(CustomException.class)
public HttpEntity<String> exceptionHandler(CustomException custEx ) 
    return new HttpEntity<String>(custEx.getMessage()) ;

【讨论】:

以上是关于从服务器抛出的自定义错误未在客户端的 HttpErrorResponse 中返回的主要内容,如果未能解决你的问题,请参考以下文章

React Native、GraphQL、Apollo - 突变期间抛出的错误

如何从 MFP 8 Java 适配器向客户端抛出用户异常?

客户端的 WCF Web 服务自定义异常错误

如何从 keycloak 中的自定义客户端获取角色?

在Swift 2中使用自定义消息抛出错误/异常的最简单方法?

为啥我的自定义 UICollectionViewLayout 在单元格之间添加空格时会抛出错误?