【问题标题】:Handling and Mapping Runtime Exceptions in REST Resource to JAX-RS Response处理 REST 资源中的运行时异常并将其映射到 JAX-RS 响应
【发布时间】:2013-11-20 02:31:17
【问题描述】:

我有一个 RESTful Web 应用程序,它连接到数据库并具有正常的 REST、业务逻辑服务和持久层。在 RESTful 层中处理运行时错误(如数据库连接不可用)的 JAX-RS 标准方法是什么?我相信我在下面使用的方法,其中我使用 Throwable 的 try/catch 包装对我的服务/持久层的任何调用并抛出我的自定义 MyAppRuntimeException 有点尴尬。有什么建议吗?

RESTful 服务:

@Path("service")
@Consumes({"application/json"})
@Produces({"application/json"})
public class MyResource {
  @GET
  @Path("/{id}")
  public Response getPage(@PathParam("id") long id){
    Object test=null;
    try {
         test = ...
      //call business logic service method here which makes a call to database and populates test instance
    } catch (Throwable e) {
      throw new MyAppRuntimeException("custom error message string");
    }

    if(test != null){
        return Response.ok(test).build();
    }else{
        return Response.status(Status.NOT_FOUND).build();
    }

  }
}

自定义异常:

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


  public MyAppRuntimeException(String message) {
    super(message);
  }

  public MyAppRuntimeException(String message, Throwable cause) {
    super(message, cause);
  }


} 

异常 JAX-RS 响应映射器:

@Provider
public class MyAppRuntimeExceptionMapper implements ExceptionMapper<MyAppRuntimeException> {

  private static final String ERROR_KEY = "DATA_ERROR";

  @Override
  public Response toResponse(MyAppRuntimeException exception) {

    ErrorMessage errorMessage = new ErrorMessage(ERROR_KEY, exception.getMessage(), null);
    return Response.status(Status.INTERNAL_SERVER_ERROR).entity(errorMessageDTO).build();
  }

}

【问题讨论】:

  • 您是否可以控制来自业务逻辑的异常?您可以直接映射这些异常,并避免可能隐藏代码(例如空指针异常)和性能(例如内存不足错误)的 catch Throwable。与说“服务不可用”相反,禁止也是对响应代码状态的适当描述吗?您的要求将决定这样,但需要考虑一些事情。 :)
  • 默认情况下,我认为未捕获的异常应该会导致内部服务器错误,这也可以根据您的需求/您想与您的休息客户端定义的合同。
  • 如果test = null,你也可以抛出WebApplicationException,从而允许你在OK的情况下只返回值test。
  • @Charlie - 我确实可以控制业务逻辑中可能发生的一些已知异常,这些异常是使用不同的异常和映射器类抛出和映射的。我想 Status.INTERNAL_SERVER_ERROR 比 Forbidden 或 service不可用更合适,因为 NullPointerException 并不意味着它不可用。
  • @c12 你为什么不声明自己的ExceptionMapper 处理通用Exception。然后只声明getPage(..) throws Exception 并让mapper 处理抛出的异常?

标签: java rest jax-rs


【解决方案1】:

只需让您的异常类扩展 WebApplicationException 并将其扔到您喜欢的任何地方。您可以在下面的示例中看到,您可以以任何必要的方式自定义响应。编码愉快!

注意:此示例处理403 错误,但您可以轻松创建异常来处理500503 等。

package my.package.name;

import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import java.io.Serializable;

public class Http401NotAuthorizedException extends WebApplicationException implements Serializable {
  private static final long serialVersionUID = 1L;
  public Http401NotAuthorizedException(String msg){
    super(
      Response
        .status(Response.Status.FORBIDDEN)
        .header("Pragma", "no-cache, no-store")
        .header("Cache-Control", "no-cache, no-store")
        .header("Expires", "0")
        .entity(msg)
        .build()
    );
  }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-03-18
    • 1970-01-01
    • 1970-01-01
    • 2017-05-21
    • 1970-01-01
    • 2014-12-26
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多