如何在 JAX-RS 客户端获取直接的异常堆栈跟踪
How to get straight exception stack trace at JAX-RS client side
我在我的项目中使用 REST 服务,我创建了一个过滤器来记录服务调用不成功时的错误,但是如何使用 resteasy 客户端捕获错误堆栈跟踪。
public class MyLogResponseFilter implements ClientResponseFilter {
...
@Override
public void filter(ClientRequestContext requestContext,
ClientResponseContext responseContext) throws IOException {
if (responseContext.getStatus() != Response.Status.OK.getStatusCode()) {
if (responseContext.hasEntity()) {
String body = IOUtils.toString(responseContext.getEntityStream(), "UTF-8");
log.error("Error with status={}, statusInfo={}, message={}",
responseContext.getStatus(),
responseContext.getStatusInfo(),
body);
}
}
}
}
此代码有效,但 resteasy 将错误堆栈包装到 html 主体中,例如从 responseContext.getEntityStream() 读出的内容是这样的:
Error with status=500, statusInfo=Internal Server Error, message=<html><head><title>ERROR</title><style>body {
font-family: "Lucida Grande", "Lucida Sans Unicode", "Trebuchet MS", Helvetica, Arial, Verdana, sans-serif;
margin: 5px;
}
.header {
background-image: linear-gradient(bottom, rgb(153,151,153) 8%, rgb(199,199,199) 54%);
background-image: -o-linear-gradient(bottom, rgb(153,151,153) 8%, rgb(199,199,199) 54%);
background-image: -moz-linear-gradient(bottom, rgb(153,151,153) 8%, rgb(199,199,199) 54%);
background-image: -webkit-linear-gradient(bottom, rgb(153,151,153) 8%, rgb(199,199,199) 54%);
background-image: -ms-linear-gradient(bottom, rgb(153,151,153) 8%, rgb(199,199,199) 54%);
background-image: -webkit-gradient(
linear,
left bottom,
left top,
color-stop(0.08, rgb(153,151,153)),
color-stop(0.54, rgb(199,199,199))
);
color: black;
padding: 2px;
font-weight: normal;
border: solid 1px;
font-size: 170%;
text-align: left;
vertical-align: middle;
height: 32px;
}
.error-div {
display: inline-block; width: 32px; height: 32px; background: url('data:image/png;base64,longEncryptedPath') left center no-repeat;
}.error-text-div {
display: inline-block; vertical-align: top; height: 32px;}.label { font-weight:bold; display: inline-block;}.value { display: inline-block;}</style></head><body><div class="header"><div class="error-div"></div><div class="error-text-div">Error processing request</div></div><div class="label">Context Path:</div><div class="value">/my-webservice</div><br/><div class="label">Servlet Path:</div><div class="value">/services</div><br/><div class="label">Path Info:</div><div class="value">/mypath</div><br/><div class="label">Query String:</div><div class="value">usridNbr=1000001</div><br/><b>Stack Trace</b><br/>org.jboss.resteasy.spi.UnhandledException: javax.ejb.EJBException: java.lang.RuntimeException: ====test it<br/>org.jboss.resteasy.core.ExceptionHandler.handleApplicationException(ExceptionHandler.java:76)...Long stack trace</body></html>
我只需要捕获错误消息和错误堆栈跟踪,无需解析 html 正文即可轻松实现的任何建议。提前致谢。
注册一个 ExceptionMapper 将您的异常映射到可以轻松解析的实体。这是一个快速+肮脏的示例,将 RuntimeException 映射到 JSON:
@Provider
public class RuntimeExceptionMapper implements ExceptionMapper<RuntimeException> {
@Override
public Response toResponse(RuntimeException exception) {
Map<String, String> map = new HashMap<>();
map.put("exception", exception.getClass().getName());
map.put("message", exception.getMessage());
return Response.status(500).entity(map).type(MediaType.APPLICATION_JSON_TYPE).build();
}
}
在客户端你可以像这样过滤它:
@Override
public void filter(ClientRequestContext requestContext, ClientResponseContext responseContext) throws IOException {
if (responseContext.getStatus() == 500 && responseContext.hasEntity()) {
Map error = new ObjectMapper().readValue(responseContext.getEntityStream(), Map.class);
LOG.error("Status: {}, Exception: {}, Message: {}",
responseContext.getStatus(), error.get("exception"), error.get("message"));
}
}
我在我的项目中使用 REST 服务,我创建了一个过滤器来记录服务调用不成功时的错误,但是如何使用 resteasy 客户端捕获错误堆栈跟踪。
public class MyLogResponseFilter implements ClientResponseFilter {
...
@Override
public void filter(ClientRequestContext requestContext,
ClientResponseContext responseContext) throws IOException {
if (responseContext.getStatus() != Response.Status.OK.getStatusCode()) {
if (responseContext.hasEntity()) {
String body = IOUtils.toString(responseContext.getEntityStream(), "UTF-8");
log.error("Error with status={}, statusInfo={}, message={}",
responseContext.getStatus(),
responseContext.getStatusInfo(),
body);
}
}
}
}
此代码有效,但 resteasy 将错误堆栈包装到 html 主体中,例如从 responseContext.getEntityStream() 读出的内容是这样的:
Error with status=500, statusInfo=Internal Server Error, message=<html><head><title>ERROR</title><style>body {
font-family: "Lucida Grande", "Lucida Sans Unicode", "Trebuchet MS", Helvetica, Arial, Verdana, sans-serif;
margin: 5px;
}
.header {
background-image: linear-gradient(bottom, rgb(153,151,153) 8%, rgb(199,199,199) 54%);
background-image: -o-linear-gradient(bottom, rgb(153,151,153) 8%, rgb(199,199,199) 54%);
background-image: -moz-linear-gradient(bottom, rgb(153,151,153) 8%, rgb(199,199,199) 54%);
background-image: -webkit-linear-gradient(bottom, rgb(153,151,153) 8%, rgb(199,199,199) 54%);
background-image: -ms-linear-gradient(bottom, rgb(153,151,153) 8%, rgb(199,199,199) 54%);
background-image: -webkit-gradient(
linear,
left bottom,
left top,
color-stop(0.08, rgb(153,151,153)),
color-stop(0.54, rgb(199,199,199))
);
color: black;
padding: 2px;
font-weight: normal;
border: solid 1px;
font-size: 170%;
text-align: left;
vertical-align: middle;
height: 32px;
}
.error-div {
display: inline-block; width: 32px; height: 32px; background: url('data:image/png;base64,longEncryptedPath') left center no-repeat;
}.error-text-div {
display: inline-block; vertical-align: top; height: 32px;}.label { font-weight:bold; display: inline-block;}.value { display: inline-block;}</style></head><body><div class="header"><div class="error-div"></div><div class="error-text-div">Error processing request</div></div><div class="label">Context Path:</div><div class="value">/my-webservice</div><br/><div class="label">Servlet Path:</div><div class="value">/services</div><br/><div class="label">Path Info:</div><div class="value">/mypath</div><br/><div class="label">Query String:</div><div class="value">usridNbr=1000001</div><br/><b>Stack Trace</b><br/>org.jboss.resteasy.spi.UnhandledException: javax.ejb.EJBException: java.lang.RuntimeException: ====test it<br/>org.jboss.resteasy.core.ExceptionHandler.handleApplicationException(ExceptionHandler.java:76)...Long stack trace</body></html>
我只需要捕获错误消息和错误堆栈跟踪,无需解析 html 正文即可轻松实现的任何建议。提前致谢。
注册一个 ExceptionMapper 将您的异常映射到可以轻松解析的实体。这是一个快速+肮脏的示例,将 RuntimeException 映射到 JSON:
@Provider
public class RuntimeExceptionMapper implements ExceptionMapper<RuntimeException> {
@Override
public Response toResponse(RuntimeException exception) {
Map<String, String> map = new HashMap<>();
map.put("exception", exception.getClass().getName());
map.put("message", exception.getMessage());
return Response.status(500).entity(map).type(MediaType.APPLICATION_JSON_TYPE).build();
}
}
在客户端你可以像这样过滤它:
@Override
public void filter(ClientRequestContext requestContext, ClientResponseContext responseContext) throws IOException {
if (responseContext.getStatus() == 500 && responseContext.hasEntity()) {
Map error = new ObjectMapper().readValue(responseContext.getEntityStream(), Map.class);
LOG.error("Status: {}, Exception: {}, Message: {}",
responseContext.getStatus(), error.get("exception"), error.get("message"));
}
}