Статьи

Пользовательская фраза причины в ответе на сообщение об ошибке состояния HTTP с JAX-RS (Джерси)

В некоторых из моих недавних работ я получил запрос на создание пользовательской фразы причины в ответе о статусе HTTP, который был доставлен одному из наших клиентов, использующих REST API, при возникновении ошибки. В этом посте я покажу, как этого добиться с помощью Джерси.

1. Определите проверенное исключение и отображение исключений

Как вы, наверное, узнали из моего поста Обработка ошибок в REST API с Джерси , мне нравится обрабатывать проверенные исключения, используя возможность Джерси ExceptionMapper .

Для этой демонстрации я определил CustomReasonPhraseException :

CustomReasonPhraseException

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
package org.codingpedia.demo.rest.errorhandling;
 
public class CustomReasonPhraseException extends Exception {
         
    private static final long serialVersionUID = -271582074543512905L;
     
    private final int businessCode;
 
    public CustomReasonPhraseException(int businessCode, String message) {
        super(message);
        this.businessCode = businessCode;
    }
 
    public int getBusinessCode() {
        return businessCode;
    }
         
}

и CustomReasonPhraseExceptionMapper для обработки сопоставления с ответом, если возникает CustomReasonPhraseException :

CustomReasonPhraseExceptionMapper

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
package org.codingpedia.demo.rest.errorhandling;
 
import javax.ws.rs.core.Response;
import javax.ws.rs.core.Response.Status;
import javax.ws.rs.ext.ExceptionMapper;
import javax.ws.rs.ext.Provider;
 
@Provider
public class CustomReasonPhraseExceptionMapper implements ExceptionMapper<CustomReasonPhraseException> {
 
    public Response toResponse(CustomReasonPhraseException bex) {
        return Response.status(new CustomReasonPhraseExceptionStatusType(Status.BAD_REQUEST))
                .entity("Custom Reason Phrase exception occured : " + bex.getMessage())
                .build();
    }
 
}

Напоминание: когда приложение CustomReasonPhraseException toResponse CustomReasonPhraseException toResponse метод CustomReasonPhraseExceptionMapper экземпляра CustomReasonPhraseExceptionMapper .

В строке примечания к коду ExceptionMapper 12:

CustomReasonPhraseExceptionStatusType

1
return Response.status(new CustomReasonPhraseExceptionStatusType(Status.BAD_REQUEST))

В Джерси ResponseBuilder вас есть возможность определять свои собственные типы статуса, реализуя интерфейс javax.ws.rs.core.Response.StatusType .

2. Реализуйте пользовательский StatusType

Чтобы сделать его немного более расширяемым, я создал класс AbstractStatusType :

AbstractStatusType

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
30
31
32
33
34
35
36
37
38
39
package org.codingpedia.demo.rest.errorhandling;
 
import javax.ws.rs.core.Response.Status;
import javax.ws.rs.core.Response.Status.Family;
import javax.ws.rs.core.Response.StatusType;
 
/**
 * Class used to provide custom StatusTypes, especially for the the Reason Phrase that appears in the HTTP Status Response
 */
public abstract class AbstractStatusType implements StatusType {
 
    public AbstractStatusType(final Family family, final int statusCode,
                          final String reasonPhrase) {
        super();
     
        this.family = family;
        this.statusCode = statusCode;
        this.reasonPhrase = reasonPhrase;
    }
     
    protected AbstractStatusType(final Status status,
                                 final String reasonPhrase) {
        this(status.getFamily(), status.getStatusCode(), reasonPhrase);
    }
     
    @Override
    public Family getFamily() { return family; }
     
    @Override
    public String getReasonPhrase() { return reasonPhrase; }
     
    @Override
    public int getStatusCode() { return statusCode; }
 
    private final Family family;
    private final int statusCode;
    private final String reasonPhrase;
     
}

который я позже CustomReasonPhraseExceptionStatusType с помощью CustomReasonPhraseExceptionStatusType чтобы предоставить пользовательскую Reason Phrase CustomReasonPhraseExceptionStatusType я желаю ( например, «Пользовательское сообщение об ошибке» ) в ответе:

CustomReasonPhraseExceptionStatusType расширяет AbstractStatusType

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
package org.codingpedia.demo.rest.errorhandling;
 
import javax.ws.rs.core.Response.Status;
 
/**
 * Implementation of StatusType for CustomReasonPhraseException.
 * The Reason Phrase is set in this case to "Custom error message"
 */
public class CustomReasonPhraseExceptionStatusType extends AbstractStatusType{
     
    private static final String CUSTOM_EXCEPTION_REASON_PHRASE = "Custom error message";
     
    public CustomReasonPhraseExceptionStatusType(Status httpStatus) {
        super(httpStatus, CUSTOM_EXCEPTION_REASON_PHRASE);
    }
 
}

3. Проверьте пользовательскую фразу причины в ответе статуса HTTP

3.1. Запрос

Пример запроса

1
2
3
4
5
GET http://localhost:8888/demo-rest-jersey-spring/mocked-custom-reason-phrase-exception HTTP/1.1
Accept-Encoding: gzip,deflate
Host: localhost:8888
Connection: Keep-Alive
User-Agent: Apache-HttpClient/4.1.1 (java 1.5)

3.2. отклик

И вуаля:

Пример ответа

1
2
3
4
5
6
HTTP/1.1 400 Custom error message
Content-Type: text/plain
Content-Length: 95
Server: Jetty(9.0.7.v20131107)
 
Custom Reason Phrase exception occured : message attached to the Custom Reason Phrase Exception

пользовательская фраза причины появляется в ответе, как и ожидалось.

Совет: Если вы действительно хотите научиться проектировать и реализовывать REST API в Java, прочитайте следующее руководство — Разработка и реализация REST API на Java с использованием Jersey и Spring

Резюме

В этом посте вы видели, как создать собственную фразу причины в ответе о статусе HTTP, если вы хотите пометить «особую» ошибку. Конечно, вы можете использовать этот механизм для определения ваших собственных фраз причины для других HTTP-статусов. На самом деле вы не должны злоупотреблять этой функцией Reason Phrase, поскольку в HTTP 1.1 rfc2616 указано следующее:

«Элемент Status-Code представляет собой трехзначный целочисленный код результата попытки понять и удовлетворить запрос. Эти коды полностью определены в разделе 10. Фраза разума предназначена для краткого текстового описания кода статуса. Код состояния предназначен для использования автоматами, а фраза разума предназначена для пользователя. От клиента не требуется проверять или отображать фразу-причину ». [1]

Ну вот и все. Продолжайте кодировать и продолжайте делиться знаниями в области кодирования.