Когда вы создаете сервисы REST с JAX-RS, вы обычно либо ничего не возвращаете (например, HTTP 201/2/4 и т. Д.), Либо некоторые данные, возможно в формате JSON (например, HTTP 200), или некоторые исключения / ошибки (например, HTTP 4xx или 5xx). ).
Обычно мы переводим исключение времени выполнения в какой-то HTTP 5xx, а проверенное исключение — в 4xx.
Поскольку мы хотим сохранить нашу границу чистой, мы не включаем полную трассировку стека Java в тело ответа, когда переводим исключение в ответ HTTP. Обычно мы просто добавляем заголовок «REASON» с ответом HTTP 5xx (или иногда 4xx). Однако это означает, что большинство наших ExceptionMappers выглядит примерно одинаково (примерно так):
1
2
3
4
5
6
7
8
9
|
@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 для создания настраиваемого сопоставления исключений, которое позволяет потребителю настраивать сопоставление кода ответа исключения и HTTP.
Наш @Provider
будет обрабатывать все исключения времени выполнения:
1
2
3
4
|
@Provider public class RuntimeExceptionMapper implements ExceptionMapper<RuntimeException> { // ... } |
Мы @Inject
и Config и провайдеров:
1
2
3
4
5
|
@Inject private Config config; @Context private Providers providers; |
Когда мы реализуем метод toResponse
, мы видим, есть ли отображение для этого класса Exception в нашей конфигурации:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
|
@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
Таким образом, мы можем добавить конфигурацию для сопоставлений следующим образом:
1
2
3
4
5
|
## 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 (из API отказоустойчивости MicroProfile) в 503, а NotAuthorizedException — в 401.
Пример скриншота
Используйте это как библиотеку.
Вы также можете объединить все это в jar-файл, который будет использоваться любым вашим проектом. Я сделал вышеперечисленное доступным в Maven Central и GitHub , так что вы также можете использовать это напрямую.
Просто добавьте это в ваш pom.xml
1
2
3
4
5
|
<dependency> <groupId>com.github.phillip-kruger.microprofile-extensions</groupId> <artifactId>jaxrs-ext</artifactId> <version> 1.0 . 9 </version> </dependency> |
Он поставляется с несколькими предопределенными сопоставлениями, но вы можете переопределить его в своей конфигурации.
Опубликовано на Java Code Geeks с разрешения Филиппа Крюгера, партнера нашей программы JCG . Смотрите оригинальную статью здесь: Настраиваемый JAX-RS ExceptionMapper с MicroProfile Config
Мнения, высказанные участниками Java Code Geeks, являются их собственными. |