假设我在Dropwizard中有一个端点,比如说
@GET
public Response foo() { throw new NullPointerException(); }
当我点击此端点时,它会记录异常和所有内容,这很棒!我喜欢它。我更喜欢的是它向用户返回一个大状态对象status: ERROR
(这很好)以及一个巨大的堆栈跟踪,我对此并不感兴趣。
显然,最好是自己捕捉和处理异常,但有时他们会不知所措。每次在整个资源周围编写一个try catch块都很好,但是(a)它很麻烦,(b)我总是喜欢自动解决方案,而且你必须记住"的解决方案。
所以我想要的是做以下事情:
我觉得必须有一种内置的方法来实现这一点 - 它已经以相对不错的方式处理异常 - 但搜索文档并没有发现任何东西。对此有一个很好的解决方案吗?
答案 0 :(得分:1)
正如评论中提到的那样,答案是ExceptionMapper
。你需要这样一个类:
@Provider
public class RuntimeExceptionMapper implements ExceptionMapper<RuntimeException> {
@Override
public Response toResponse(RuntimeException runtime) {
// ...
}
}
您可以在toResponse
方法中执行您喜欢的任何日志记录等操作,返回值是实际发送给请求者的内容。通过这种方式,您可以完全控制,并且应该设置合理的默认值 - 请记住这是因为错过了,而不是您实际希望看到的错误!这也是根据您获得的异常类型设置不同行为的好时机。
要实际执行此操作,只需在主dropwizard应用程序的run
方法中插入以下行(或类似内容):
environment.jersey().register(new RuntimeExceptionMapper());
其中environment
是应用程序的Environment
方法的run
参数。现在当你在某个地方有一个未被捕获的RuntimeException
时,这将触发,而不是之前的任何投掷蜥蜴。
注意:这仍然不是不小心捕捉和处理你的例外的借口!
答案 1 :(得分:1)
将以下内容添加到yaml文件中。请注意,它将删除dropwizard添加的所有默认异常映射器。
<head>
<link href="https://ajax.googleapis.com/ajax/libs/dojo/1.10.4/dijit/themes/claro/claro.css" rel="stylesheet" />
<script src="https://ajax.googleapis.com/ajax/libs/dojo/1.10.4/dojo/dojo.js" data-dojo-config="async: false"></script>
</head>
<body class="claro">
<button id="btn">Click me</button>
<input type="checkbox" />Can you still select me?
</body>
编写自定义异常映射器,如下所示:
server:
registerDefaultExceptionMappers: false
然后在泽西注册异常映射器:
public class CustomExceptionMapper implements ExceptionMapper<RuntimeException> {
@Override
public Response toResponse(RuntimeException runtime) {
// ...
}
}
答案 2 :(得分:0)
在评论中已经提到过这个问题,但后来认为我会试一试用例。
建议您开始区分您要投掷的Exception
。对您知道的故障使用自定义异常,并抛出那些具有漂亮记录的故障。实际应该修复RuntimeException
public class ErrorResponse {
private int code;
private String message;
public ErrorResponse() {
}
public ErrorResponse(int code, String message) {
this.code = code;
this.message = message;
}
... setters and getters
}
。无论如何,如果您不想向最终用户显示堆栈跟踪,您可能会捕获一般异常,记录详细信息并相应地自定义响应和实体。
您可以定义
@GET
public Response foo() {
try {
...
return Response.status(HttpStatus.SC_OK).entity(response).build();
} catch (CustomBadRequestException ce) {
log.error(ce.printStackTrace());
return Response.status(HttpStatus.SC_BAD_REQUEST).entity(new ErrorResponse(HttpStatus.SC_BAD_REQUEST, ce.getMessage())).build();
} catch (Exception e) {
log.error(e.printStackTrace(e));
return Response.status(HttpStatus.SC_INTERNAL_SERVER_ERROR).entity(new ErrorResponse(HttpStatus.SC_INTERNAL_SERVER_ERROR, e.getMessage())).build();
}
}
然后在您的资源代码中,您可以将方法修改为 -
PageTabBarController
答案 3 :(得分:0)
本文详细介绍了具有自定义 ExceptionMapper 的Jersey的已检查和未检查的异常实现:
https://www.codepedia.org/ama/error-handling-in-rest-api-with-jersey/
Dropwizard官方文档还介绍了一种更简单的方法,只需使用 WebApplicationException 进行捕获:
@GET
@Path("/{collection}")
public Saying reduceCols(@PathParam("collection") String collection) {
if (!collectionMap.containsKey(collection)) {
final String msg = String.format("Collection %s does not exist", collection);
throw new WebApplicationException(msg, Status.NOT_FOUND)
}
// ...
}
https://www.dropwizard.io/en/stable/manual/core.html#responses
答案 4 :(得分:0)
它对我有用,只需注册在主类的 run 方法中创建的自定义异常映射器。
environment.jersey().register(new CustomExceptionMapper());
CustomExceptionMapper 可以像这样实现 ExceptionMapper 类的地方
public class CustomExceptionMapperimplements ExceptionMapper<Exception>