【问题标题】:JAX-RS (Jersey) custom exception with XML or JSON带有 XML 或 JSON 的 JAX-RS (Jersey) 自定义异常
【发布时间】:2011-03-14 17:32:24
【问题描述】:

我有一个使用 Jersey 构建的 REST 服务。

我希望能够根据发送到服务器的 MIME 设置自定义异常编写器的 MIME。接收json时返回application/json,接收xml时返回application/xml

现在我对application/json 进行了硬编码,但这会让 XML 客户端一无所知。

public class MyCustomException extends WebApplicationException {
     public MyCustomException(Status status, String message, String reason, int errorCode) {
         super(Response.status(status).
           entity(new ErrorResponseConverter(message, reason, errorCode)).
           type("application/json").build());
     }
}

我可以利用什么上下文来获取当前请求Content-Type

谢谢!


根据回答更新

对于其他对完整解决方案感兴趣的人:

public class MyCustomException extends RuntimeException {

    private String reason;
    private Status status;
    private int errorCode;

    public MyCustomException(String message, String reason, Status status, int errorCode) {
        super(message);
        this.reason = reason;
        this.status = status;
        this.errorCode = errorCode;
    }

    //Getters and setters
}

ExceptionMapper一起

@Provider
public class MyCustomExceptionMapper implements ExceptionMapper<MyCustomException> {

    @Context
    private HttpHeaders headers;

    public Response toResponse(MyCustomException e) {
        return Response.status(e.getStatus()).
                entity(new ErrorResponseConverter(e.getMessage(), e.getReason(), e.getErrorCode())).
                type(headers.getMediaType()).
                build();
    }
}

ErrorResponseConverter 是一个自定义的 JAXB POJO

【问题讨论】:

  • ErrorResponseConverter 类会是什么样子?
  • @Oskar:请向我们展示您对 ErrorResponseConverter 的实现。谢谢!
  • @dreboy 这将只是一些 POJO 将返回给包含错误信息的用户。你会为 Jackson/JAXB/whatever 注释它以支持各种内容类型。
  • @ach 我想通了。不过感谢您的回复!

标签: java mime jersey jax-rs


【解决方案1】:

您可以尝试将 @javax.ws.rs.core.Context javax.ws.rs.core.HttpHeaders 字段/属性添加到您的根资源类、资源方法参数或自定义 javax.ws.rs。 ext.ExceptionMapper 并调用 HttpHeaders.getMediaType()。

【讨论】:

  • ExceptionMapper 是要走的路。谢谢!而不是: public class MyCustomException extends WebApplicationException 我做了一个: public class MyCustomException extends RuntimeException 和一个: public class MyCustomExceptionMapper implements ExceptionMapper 实现: public Response toResponse(PlacesException e) { return Response.status(e.getStatus() )。实体(新的ErrorResponseConverter(e.getMessage(),e.​​getReason(),e.​​getErrorCode()))。类型(headers.getMediaType())。建造(); }
【解决方案2】:

headers.getMediaType() 响应实体的媒体类型,而不是 Accept 标头。转换异常的适当方法是使用 Accept 标头,以便您的客户端以他们请求的格式获得响应。鉴于上述解决方案,如果您的请求如下所示(注意 JSON 接受标头,但 XML 实体),您将返回 XML。

POST http://localhost:8080/service/giftcard/invoice?draft=true HTTP/1.1 接受:应用程序/json 授权:基本 dXNlcjp1c2Vy 内容类型:应用程序/xml 用户代理:Jakarta Commons-HttpClient/3.1 主机:本地主机:8080 代理连接:保持活动 内容长度:502

正确的实现是再次使用 Accept 标头:

public Response toResponse(final CustomException e) {
    LOGGER.debug("Mapping CustomException with status + \"" + e.getStatus() + "\" and message: \"" + e.getMessage()
            + "\"");
    ResponseBuilder rb = Response.status(e.getStatus()).entity(
            new ErrorResponseConverter(e.getMessage(), e.getReason(), e.getErrorCode()));

    List<MediaType> accepts = headers.getAcceptableMediaTypes();
    if (accepts!=null && accepts.size() > 0) {
        //just pick the first one
        MediaType m = accepts.get(0);
        LOGGER.debug("Setting response type to " + m);
        rb = rb.type(m);
    }
    else {
        //if not specified, use the entity type
        rb = rb.type(headers.getMediaType()); // set the response type to the entity type.
    }
    return rb.build();
}

【讨论】:

  • 我同意您应该使用 Accept: 标头而不是 HttpHeaders.getMediaType()。我认为模棱两可的只是选择第一个。对我来说,尝试使用与 Jersey 与请求匹配的资源的 @Produces 注释相对应的注释更有意义。不过,我不知道如何将其连接起来。
  • JAX_RS_SPEC-323 在 java.net 上不再可用;此问题已迁移至:github.com/eclipse-ee4j/jaxrs-api/issues/328
猜你喜欢
  • 2013-02-17
  • 1970-01-01
  • 1970-01-01
  • 2018-05-08
  • 1970-01-01
  • 2014-12-18
  • 2015-10-07
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多