【问题标题】:return any exception in json in rest api在rest api中返回json中的任何异常
【发布时间】:2016-07-22 07:13:00
【问题描述】:

有没有使用 Rest api 在 JSON 中返回异常的简单方法?
我已经用谷歌搜索了这个问题,但我看到的所有解决方案都是关于在某些计算过程中抛出异常。但如果收入参数错误怎么办?我的意思是如果有一个字符串而不是 int 输入参数怎么办?

我为输入数据创建了一些 DTO 类:

@XmlRootElement
public class RequestDTO implements Serializable{

private static final long serialVersionUID = 1L;

@XmlElement(name = "request_id")
private String requestId;

@XmlElement(name = "site")
private List<String> sitesIds;

@XmlElement(name = "date_begin")
@JsonSerialize(using = DateSerializer.class)
@JsonDeserialize(using = DateDeserializer.class)
private Date dateBegin;

@XmlElement(name = "date_end")
@JsonSerialize(using = JsonDateSerializer.class)
@JsonDeserialize(using = JsonDateDeserializer.class)
private Date dateEnd;


@XmlElement(name = "volume")
private double volume;

// there is getters and setters
}

如果我在我的 json 请求中发送了类似“qwerty”而不是“volume”字段的内容,我会看到类似 Runtime 的错误消息。是否有可能以某种方式处理它?我的意思是用这种结构在json中返回错误?

public class ExceptionDTO {

private String shortExceptionMessage;
private String stackTrace;

public ExceptionDTO(String shotExceptionMessage, String stackTrace){
    this.shortExceptionMessage = shotExceptionMessage;
    this.stackTrace = stackTrace;
}

public String getShortExceptionMessage() {
    return shortExceptionMessage;
}

public String getStackTrace() {
    return stackTrace;
}
}

UPD1:

@Provider
@Singleton
public class ExceptionMapperProvider implements ExceptionMapper<Exception>{

    @Override
    public Response toResponse(final Exception e) {

        StringBuilder trace = new StringBuilder();
        IntStream.range(0, e.getStackTrace().length)
            .forEach(i -> trace.append(e.getStackTrace()[i]).append('\n'));


        ExceptionDTO exceptionMessage = new ExceptionDTO(
                e.toString(),
                trace.toString()
         );

        return Response.status(500).entity(exceptionMessage).build();
    }
}

【问题讨论】:

  • 休息API?您使用的是哪个特定的 jax-rs 实现,所以我可以提供更具体的答案?
  • @geneqew,我在春季项目中使用球衣

标签: java json api rest exception


【解决方案1】:

由于您是否有兴趣检查有效负载的字段或值是否正确并不清楚,所以这里有一些方法可以同时使用这两种方法。

如果您想检查某个字段的value 是否正确(即音量字段值应大于零等),请查看bean validationThis 在您要验证的字段上使用注释。

// for example
@Min(value = 0, message = "invalid message")
private double range;

要在其中一项验证失败时使用 ExceptionDTO 作为错误响应,您可以通过创建ExceptionMapper&lt;ConstraintViolationException&gt; 来实现。查看here了解更多详情。

如果您正在检查无效字段(即客户端发送 ragne 字段而不是范围),请查看堆栈跟踪以了解引发的异常。然后使用您的ExceptionDTO 作为主体注册一个异常映射器。

例如,如果抛出UnrecognizedPropertyException,那么你可以添加:

@Provider
public class UnrecognizedPropertyExceptionMapper implements ExceptionMapper<UnrecognizedPropertyException> {

   @Override
   public Response toResponse(UnrecognizedPropertyException e) {
      ExceptionDTO myDTO = // build response
      return Response.status(BAD_REQUEST).entity(myDTO).build();
   }
}

【讨论】:

  • 感谢您的回答。但对我来说主要目的是如何从字段验证中返回任何 json 格式的异常。我创建了一些异常映射器(您可以在主题更新中看到它),但我应该如何处理它?什么时候执行?
  • 顺便说一句...是否可以在某个 try-catch 块中舍入所有 rest api 以捕获任何异常?
  • 基本上,流程是客户端调用您的资源端点,将您的 RequestDTO 作为有效负载传递,如果存在违规并引发异常,该异常将由您的异常映射器映射。您的异常映射器将产生响应(在您的情况下为 ExceptionDTO)。不要忘记包含依赖 jersey-bean-validation 并启用 bean 验证。阅读here 了解如何操作。
【解决方案2】:

如果您想验证请求中的输入参数,您应该返回状态代码 400(错误请求)以及错误详细信息。您可以简单地发送 json { "error": { "message": "string received for parameter x, where as int expected" },响应状态码为 400。

`

【讨论】:

  • 我知道在一些计算过程中可以用我的 ExceptionDTO 返回 Resonse。但问题是如何在反序列化参数期间捕获异常?
【解决方案3】:

我做了一些研究,并确定在 JSON 中编码 Java 异常的最佳方法是使用由 Oasis 开发的约定,如下所示:

{
   "error": {
      "code": "400",
      "message": "main error message here",
      "target": "approx what the error came from",
      "details": [
         {
            "code": "23-098a",
            "message": "Disk drive has frozen up again.  It needs to be replaced",
            "target": "not sure what the target is"
         }
      ],
      "innererror": {
         "trace": [ ... ],
         "context": [ ... ]
      }
   }
}

details 是一个列表,对于链中的每个嵌套原因异常都应该有一个条目。

innererror.trace 应根据需要包含堆栈跟踪,作为字符串值列表。

响应状态代码应该是 400,除非您有充分的理由将其设置为其他内容,并且结构中的代码应该与您发送的任何内容相匹配。

编写一个方法来将 Java 异常转换为这种格式,你就完成了。始终使用它,您的 JS 代码将能够处理和显示异常值。

关于评估和取消的其他方法的更多详细信息在这篇关于JSON REST API - 异常处理的博客文章中进行了介绍 https://agiletribe.purplehillsbooks.com/2015/09/16/json-rest-api-exception-handling/

这是将异常转换为这种格式的java方法:

public static JSONObject convertToJSON(Exception e, String context) throws Exception {
    JSONObject responseBody = new JSONObject();
    JSONObject errorTag = new JSONObject();
    responseBody.put("error", errorTag);

    errorTag.put("code", 400);
    errorTag.put("target", context);

    JSONArray detailList = new JSONArray();
    errorTag.put("details", detailList);

    String lastMessage = "";
    Throwable runner = e;
    while (runner!=null) {
        String className =  runner.getClass().getName();
        String msg =  runner.toString();

        runner = runner.getCause();

        JSONObject detailObj = new JSONObject();
        detailObj.put("message",msg);
        int dotPos = className.lastIndexOf(".");
        if (dotPos>0) {
            className = className.substring(dotPos+1);
        }
        detailObj.put("code",className);
        System.out.println("          ERR: "+msg);
        detailList.put(detailObj);
    }

    JSONObject innerError = new JSONObject();
    errorTag.put("innerError", innerError);

    JSONArray stackList = new JSONArray();
    runner = e;
    while (runner != null) {
        for (StackTraceElement ste : runner.getStackTrace()) {
            String line = ste.getFileName() + ":" + ste.getMethodName() + ":" + ste.getLineNumber();
            stackList.put(line);
        }
        stackList.put("----------------");
        runner = runner.getCause();
    }
    errorTag.put("stack", stackList);
    return responseBody;
}

【讨论】:

    猜你喜欢
    • 2021-10-09
    • 1970-01-01
    • 1970-01-01
    • 2012-10-27
    • 2018-08-11
    • 2016-07-27
    • 2017-03-01
    • 1970-01-01
    • 2021-05-16
    相关资源
    最近更新 更多