Java 如何为rest服务中的异常返回http状态码

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/30996740/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-11 10:29:42  来源:igfitidea点击:

How to return http status code for exceptions in rest services

javaresthttpcxf

提问by Sunil Rk

In my application I have different layers like the rest layer, service layer and DB layer, according to business scenarios I am trowing different business exceptions from the service layer.

在我的应用程序中,我有不同的层,如休息层、服务层和数据库层,根据业务场景,我从服务层中抛出不同的业务异常。

But now, I have to set different HTTP codes like 400, 403, 409, 412.. to REST responses.

但是现在,我必须为 REST 响应设置不同的 HTTP 代码,例如 400、403、409、412……。

How can I set different HTTP status codes based on different scenarios?

如何根据不同的场景设置不同的HTTP状态码?

Which is the most feasible way like: aspect, exception mapper, or ....?

哪种方式最可行,例如方面、异常映射器或....?

Since I can set HTTP status only once in rest layer ( referred this), I am not able to map to different HTTP codes because my exception is from service layer.

由于我只能在 rest 层中设置一次 HTTP 状态( 参考这个),我无法映射到不同的 HTTP 代码,因为我的异常来自服务层。

My exception class looks like this:

我的异常类如下所示:

public class BusinessException extends RuntimeException {
    private static final long serialVersionUID = 1L;

    public BusinessException(ErrorEnumeration error) {

    }
    public BusinessException(Exception e, ErrorEnumeration error) {

    }
}

and the exception will be thrown from the service like this:

并且将从服务中抛出异常,如下所示:

 throw new BusinessException(ErrorEnumeration.VALIDATION_FAILED);

Please help by suggesting a solution

请帮助提出解决方案

回答by bhdrkn

You can use exceptions defined in jax-rs or you can use your own exceptions. Fist catch your business exceptions and convert them to jax-rs versions. For example, for 404 you can throw javax.ws.rs.NotFoundException.

您可以使用 jax-rs 中定义的异常,也可以使用自己的异常。Fist 捕获您的业务异常并将它们转换为 jax-rs 版本。例如,对于 404,您可以抛出javax.ws.rs.NotFoundException.

You can also write your own exceptions by extending them from javax.ws.rs.ClientErrorException

您还可以通过扩展它们来编写自己的异常 javax.ws.rs.ClientErrorException

Here is an example for 409-Conflict status exception

这是 409-Conflict 状态异常的示例

import javax.ws.rs.ClientErrorException;
import javax.ws.rs.core.Response;

public class ConflictException extends ClientErrorException{

    public ConflictException(Response.Status status) {
        super(Response.Status.CONFLICT); // 409
    }
}

Update

更新

Most simple and feasible way is catching your business exceptions and re-throw them with jax-rs exceptions.

最简单可行的方法是捕获您的业务异常并使用 jax-rs 异常重新抛出它们。

try{
  businessService.executeBusinessRule();
}catch (BusinessException e){
  // It is better if your BusinessException has some child class to handle
  if(e.getError() == ErrorEnumeration.VALIDATION_FAILED){
    throw new BadRequestException();
  }else{
    throw new ConflictException();
  }
}

If you are using spring you can always catch these exceptions using aop.

如果您使用的是 spring,您总是可以使用 aop 捕获这些异常。

@Aspect
public class BusinessExceptionInterceptor{
@AfterThrowing(pointcut = "execution(* com.your.service.packge..* (..))", throwing = "e")
public void errorInterceptor(BusinessException e) {
   // re-throw again...
}

Update 2

更新 2

Also it is better to define a new exception instead of reusing same exception with different state. You can define a new ValidationException which extends from BusinessException like this.

此外,最好定义一个新的异常,而不是重用不同状态的相同异常。您可以像这样定义一个从 BusinessException 扩展的新 ValidationException。

public class ValidationException extends BusinessException{

    public ValidationException() {
        super(ErrorEnumeration.VALIDATION_FAILED);
    }
}

By using this way you can still handle all the BusinessException but it is easier to identify or map them to Jax-rs exceptions.

通过使用这种方式,您仍然可以处理所有 BusinessException,但更容易识别或将它们映射到 Jax-rs 异常。