当您使用JAX-RS创建REST服务时,通常要么不返回任何内容(例如HTTP 201/2/4等),要么返回某些数据(可能采用JSON格式(因此HTTP 200),或者返回某些异常/错误(例如HTTP 4xx或5xx) )。
我们通常将运行时异常转换为某些HTTP 5xx,将已检查异常转换为某些4xx。
因为我们要保持边界整洁,所以当我们将Exception转换为HTTP响应时,我们不会在响应的主体中包含完整的Java stacktrace。 我们通常只添加带有HTTP 5xx(有时是4xx)响应的“ REASON”标头。 但是,这意味着我们的大多数ExceptionMappers看起来都差不多(类似这样):
@Provider
public class SomeExceptionMapper implements ExceptionMapper<SomeException> {
@Override
public Response toResponse(SomeException exception) {
return Response.status(500).header("reason", exception.getMessage()).build();
}
}
使用MicroProfile Config API
我们可以使用MicroProfile Config API创建一个可配置的Exception Mapper,它允许使用者将Exception配置为HTTP响应代码映射。
我们的@Provider
将处理所有运行时异常:
@Provider
public class RuntimeExceptionMapper implements ExceptionMapper<RuntimeException> {
// ...
}
我们@ @Inject
配置和提供程序:
@Inject
private Config config;
@Context
private Providers providers;
当我们实现toResponse
方法时,我们会在配置中查看此Exception类的映射:
@Override
@Produces({MediaType.APPLICATION_JSON,MediaType.APPLICATION_XML})
public Response toResponse(RuntimeException exception) {
return handleThrowable(exception);
}
private Response handleThrowable(Throwable exception) {
if(exception instanceof WebApplicationException) {
return ((WebApplicationException) exception).getResponse();
}
if(exception!=null){
String configkey = exception.getClass().getName() + STATUS_CODE_KEY;
Optional<Integer> possibleDynamicMapperValue = config.getOptionalValue(configkey,Integer.class);
if(possibleDynamicMapperValue.isPresent()){
int status = possibleDynamicMapperValue.get();
// You switched it off
if(status<0)return handleNotMapped(exception);
String reason = getReason(exception);
log.log(Level.FINEST, reason, exception);
return Response.status(status).header(REASON, reason).build();
} else if(exception.getCause()!=null && exception.getCause()!=null && providers!=null){
final Throwable cause = exception.getCause();
return handleThrowable(cause);
} else {
return handleNotMapped(exception);
}
}
return handleNullException();
}
( 这里有完整的示例)
我们还将向上处理异常链,直到获得映射,或者默认为正常的500错误。
因此,我们可以为映射添加配置,如下所示:
## 503 Service Unavailable: The server is currently unavailable (because it is overloaded or down for maintenance). Generally, this is a temporary state.
org.eclipse.microprofile.faulttolerance.exceptions.CircuitBreakerOpenException/mp-jaxrs-ext/statuscode=503
## 401 Unauthorized (RFC 7235): Similar to 403 Forbidden, but specifically for use when authentication is required and has failed or has not yet been provided.
javax.ws.rs.NotAuthorizedException/mp-jaxrs-ext/statuscode=401
在上面的示例中,我们将CircuitBreakerOpenException(来自MicroProfile容错API)映射到503,将NotAuthorizedException映射到401。
屏幕截图示例
用作库。
您还可以将所有这些捆绑在一个jar文件中,以供您的任何项目使用。 我在maven Central和github中提供了上述内容,因此您也可以直接使用它。
只需将其添加到您的pom.xml
<dependency>
<groupId>com.github.phillip-kruger.microprofile-extensions</groupId>
<artifactId>jaxrs-ext</artifactId>
<version>1.0.9</version>
</dependency>
它带有一些预定义的映射,但是您可以在配置中覆盖它。
翻译自: https://www.javacodegeeks.com/2018/08/jax-rs-exceptionmapper-config.html