【问题标题】:JAX-RS jersey ExceptionMappers User-Defined ExceptionJAX-RS jersey ExceptionMappers 用户定义的异常
【发布时间】:2013-02-17 13:57:13
【问题描述】:

我是新手,试图阅读一些文档但它不起作用,请多多包涵。

我使用ExceptionMappers 创建了一个UserNotFoundMapper,如下所示:

public class UserNotFoundMapper implements ExceptionMapper<UserNotFoundException> {

@Override
public Response toResponse(UserNotFoundException ex) {
    return Response.status(404).entity(ex.getMessage()).type("text/plain").build();
}

}

这在我的服务中:

@GET
@Path("/user")
public Response getUser(@QueryParam("id") String id) throws UserNotFoundException{
    //Some user validation code with DB hit, if not found then
    throw new UserNotFoundException();
}

UserNotFoundException 是一个 User-Defined 异常。

我试过了:

public class UserNotFoundException extends Exception {
       //SOME block of code 
}

但是当我调用服务时,UserDefinedExceptionMapper 没有被调用。看来我可能在UserDefinedException 中遗漏了一些东西。那么如何定义这个异常呢?

请告诉我如何定义UserNotFoundException

【问题讨论】:

    标签: java web-services rest jersey jax-rs


    【解决方案1】:

    您需要使用 @Provider 注释您的异常映射器,否则它将永远不会注册到 JAX-RS 运行时。

    @Provider
    public class UserNotFoundMapper implements
            ExceptionMapper<UserNotFoundException> {
        @Override
        public Response toResponse(UserNotFoundException ex) {
            return Response.status(404).entity(ex.getMessage()).type("text/plain")
                    .build();
        }
    }
    

    【讨论】:

    • 感谢您的回复。我需要知道一些与此相关的事情:使用 WebApplicationException 和使用 ExceptionMapper 的区别在哪里?我不确定在什么情况下应该使用:(你能提供你的意见吗?
    • @WhoAmI - Web 应用程序异常由 JAX-RS 提供程序自动映射。因此,例如,与使用异常映射器相反,您可以扩展 WebApplicationException 并覆盖它的 getResponse 方法。有些人更喜欢对他们专门为其 JAX-RS 实现定义的所有异常执行此操作。映射器非常棒,用于映射不从 WebApplicationException 扩展的异常(例如,所有标准 Java 异常、来自第三方库的异常等)。
    • @WhoAmI:Jersey User Guide 的布局非常清晰,即使不是非常详细。这意味着 WebApplicationException 在其中包含一个 Response,当你抛出其中一个时,Response 就是返回给用户的内容。
    • @WhoAmI:使用哪种异常方法取决于您。 ExceptionMapper 的优势在于您的代码可以保持独立于 Jersey,并且您还可以映射您无法控制的异常(框架异常)。 WebApplicationException 的优势在于它更易于使用。
    • @ryanstewart - 实际上 WebApplicationException 的映射行为是 JAX-RS 规范的一部分,因此它可以跨提供者移植。这是一件很棒的事情。
    【解决方案2】:

    我在创建 API 时通常会创建自己的异常,该异常从 RuntimeException 扩展而来,因此我不必捕获我的异常。

    这是一个例子:

    注意:我在 Jersey 中使用 JAX-RS

    首先:创建我自己的从 RuntimeException 扩展的异常。

    public class ExceptionName extends RuntimeException {
    
    private int code;
    private String message;
    
    public int getCode(){
        return code;
    }
    
    public String getMessage(){
        return message;
    }
    
    public ExceptionName(int code, String message) {
        this.code = code;
        this.message = message;
    }
    
    }
    

    同时实现ExceptionMapper

    @Provider
    public class ExceptionName implements ExceptionMapper<ExceptionName>{
    
        @Override
        public Response toResponse(ExceptionName exception) {
            return Response.status(exception.getCode()).entity(exception.getMessage()).build();
        }
    
    }
    

    每次我想抛出异常时,我都会在任何地方这样做,异常映射器会负责向使用 API 的客户端返回响应

    throw new ExceptionName(500,"there was an error with something here");
    

    【讨论】:

      【解决方案3】:

      一个小评论,尝试使用 Response.Status.NOT_FOUND 而不是使用 404 等。代码将更具可读性并且不易出现拼写错误,“text/plain”也是如此。下面是处理您提到的异常的代码。 还有一件事记得在你的界面中注释你的方法@Produces(MediaType.TEXT_PLAIN)

      公共类 UserNotFoundException 扩展异常 { //... } 公共类 UserServiceImpl 实现 UserService { @覆盖 公共响应 getUser(@QueryParam("id") String id) { 最终响应响应; 尝试{ // 调用用户方法 //如果一切正常 response = Response.status(Response.Status.OK).entity(whateverYouWant).type(MediaType.TEXT_PLAIN).build(); } 捕捉(UserNotFoundException ex){ response = new UserNotFoundMapper().toResponse(ex); } 返回响应; } } 在客户幻灯片中,您可以检查 public static boolean isUserExists(final Response serverResp) { return serverResp != null && serverResp.getStatus() == Response.Status.NOT_FOUND.getStatusCode(); }

      【讨论】:

      • 您不会手动调用映射器,也不会在服务层中使用特定于 Jersey 的类。这就是映射器的全部意义所在。
      • @RyanStewart 感谢您的意见。我对此很陌生,并试图学习它。在上面发布的代码中;如果我用throw new UserNotFoundException(); 删除映射器调用行,那没问题吧?我无法理解您所说的you wouldn't use Jersey-specific classes in your service layer 是什么意思。能详细解释一下吗?
      • @WhoAmI 你所在的类叫做 UserServiceImpl 并且是服务层的一部分,而不是控制器层。您不想将 jax-rs 之类的特定实现强加到代码的其余部分中。它的使用应该在控制器层终止。 ExceptionMapper 为您提供了一种通过球衣处理异常的方法,而无需在整个代码中添加Response.status...。服务层代码应该只做业务逻辑。
      猜你喜欢
      • 2015-02-09
      • 2011-03-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-12-18
      • 2014-01-24
      • 2016-12-02
      • 1970-01-01
      相关资源
      最近更新 更多