有没有简单的方法可以使用Rest api在JSON中返回异常?
我已经用Google搜索了这个问题,但我看到的所有解决方案都是关于在某些计算过程中抛出异常。但如果收入参数错误呢?我的意思是如果有sone字符串而不是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'字段的内容,我会看到像运行时一样的错误消息。有可能以某种方式处理它吗?我的意思是用这种结构在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();
}
}
答案 0 :(得分:4)
由于您是否对检查有效负载的字段或值是否正确感兴趣尚不清楚,以下是一些可以同时使用这两种方法的方法。
如果要检查字段的value
是否正确(即,字段字段值应大于零等),请查看bean validation。 This在您要验证的字段上使用注释。
// for example
@Min(value = 0, message = "invalid message")
private double range;
要在其中一个验证失败时将ExceptionDTO用作错误响应,您可以通过创建ExceptionMapper<ConstraintViolationException>
来执行此操作。检查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();
}
}
答案 1 :(得分:0)
如果要验证请求中的输入参数,则应返回状态码400(错误请求)以及错误详细信息。你可以简单地发送json
{ "error": { "message": "string received for parameter x, where as int expected" }
,响应状态代码为400。
`
答案 2 :(得分:0)
我做了一些研究,并确定在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.wordpress.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;
}