Пользовательские веб-статьи серии SpringBoot возвращают n положений Http-кода

Spring Boot

Пользовательские веб-статьи серии SpringBoot возвращают n положений Http-кода

Хотя http предоставляет полный набор четко определенных кодов состояния, в реальной бизнес-поддержке серверная часть не всегда соблюдает этот набор правил. Чаще всего к возвращаемому результату добавляется поле кода для настройки бизнес-статуса. если серверная часть 5xx, код http, возвращаемый на переднюю часть, по-прежнему равен 200.

Итак, если я хочу соответствовать спецификации http, что можно сделать в Spring, чтобы возвращать разные коды http в разных случаях?

В этой статье будут представлены четыре способа установки возвращаемого HTTP-КОДА.

  • @ResponseStatusМетод аннотации
  • HttpServletResponse#sendError
  • HttpServletResponse#setStatus
  • ResponseEntity

I. Вернуть n позиций Http-кода

0. Окружающая среда

Прежде чем вводить текст, создайте проект SpringBoot Все версии примеров в этой статьеspring-boot.2.1.2.RELEASE

(Для тех, кому нужно протестировать, создайте проект maven локально, вpom.xmlфайл, скопируйте конфигурацию ниже)

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.2.1.RELEASE</version>
    <relativePath/> <!-- lookup parent from repository -->
</parent>

<properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
    <java.version>1.8</java.version>
</properties>

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
</dependencies>

<build>
    <pluginManagement>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </pluginManagement>
</build>
<repositories>
    <repository>
        <id>spring-snapshots</id>
        <name>Spring Snapshots</name>
        <url>https://repo.spring.io/libs-snapshot-local</url>
        <snapshots>
            <enabled>true</enabled>
        </snapshots>
    </repository>
    <repository>
        <id>spring-milestones</id>
        <name>Spring Milestones</name>
        <url>https://repo.spring.io/libs-milestone-local</url>
        <snapshots>
            <enabled>false</enabled>
        </snapshots>
    </repository>
    <repository>
        <id>spring-releases</id>
        <name>Spring Releases</name>
        <url>https://repo.spring.io/libs-release-local</url>
        <snapshots>
            <enabled>false</enabled>
        </snapshots>
    </repository>
</repositories>

Все следующие методы помещены в класс ErrorCodeRest.

@RestController
@RequestMapping(path = "code")
public class ErrorCodeRest {
}

1. Состояние использования ResponseStatus

через аннотацию@ResponseStatus, чтобы указать возвращаемый http код, в общем случае есть два способа его использования, один добавляется напрямую в метод, другой добавляется в класс исключения

А. Метод украшения

Добавьте аннотации непосредственно к методу и сформулируйте соответствующий код

/**
 * 注解方式,只支持标准http状态码
 *
 * @return
 */
@GetMapping("ano")
@ResponseStatus(code = HttpStatus.BAD_REQUEST, reason = "请求参数异常!")
public String ano() {
    return "{\"code\": 400, \"msg\": \"bad request!\"}";
}

Протестируйте, результаты следующие

➜  ~ curl 'http://127.0.0.1:8080/code/ano' -i
HTTP/1.1 400
Content-Type: application/json;charset=UTF-8
Transfer-Encoding: chunked
Date: Sun, 05 Jan 2020 01:29:04 GMT
Connection: close

{"timestamp":"2020-01-05T01:29:04.673+0000","status":400,"error":"Bad Request","message":"请求参数异常!","path":"/code/ano"}%

Когда мы инициируем запрос, возвращаемый код состояния равен 400, а возвращаемые данные представляют собой формат сообщения об ошибке по умолчанию для Springboot.

Хотя приведенная выше поза может устанавливать код http, в чем смысл этой позы?

Если вы видели веб-серию руководств:Глобальная обработка исключений в веб-главе серии учебных пособий SpringBootТам могут быть некоторые изображения, с@ExceptionHandlerчтобы вернуть соответствующий код состояния в соответствии с исключением

Рекомендуемая позиция. Следующее указывает на то, что когда в вашей бизнес-логике происходит выход за пределы массива, возвращается код состояния 500 и полная информация о стеке.

@ResponseBody
@ExceptionHandler(value = ArrayIndexOutOfBoundsException.class)
@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
public String handleArrayIndexOutBounds(HttpServletRequest request, HttpServletResponse response,
        ArrayIndexOutOfBoundsException e) throws IOException {
    log.info("array index out conf!");
    return "aryIndexOutOfBounds: " + getThrowableStackInfo(e);
}

Б. Украсьте классы исключений

Другой способ его использования — напрямую декорировать класс исключения, а затем, когда в вашем бизнес-коде создается определенный класс исключения, возвращаемый http-код будет установлен на значение в аннотации.

/**
 * 异常类 + 注解方式,只支持标准http状态码
 *
 * @return
 */
@GetMapping("exception/500")
public String serverException() {
    throw new ServerException("内部异常哦");
}

@GetMapping("exception/400")
public String clientException() {
    throw new ClientException("客户端异常哦");
}

@ResponseStatus(code = HttpStatus.INTERNAL_SERVER_ERROR, reason = "服务器失联了,请到月球上呼叫试试~~")
public static class ServerException extends RuntimeException {
    public ServerException(String message) {
        super(message);
    }
}

@ResponseStatus(code = HttpStatus.BAD_REQUEST, reason = "老哥,你的请求有问题~~")
public static class ClientException extends RuntimeException {
    public ClientException(String message) {
        super(message);
    }
}

Результаты теста следующие: Преимущество добавления аннотаций к классам исключений заключается в том, что не требуется сотрудничества.@ExceptionHandlerНапишите дополнительную логику; недостаток в том, что вам нужно определить множество пользовательских типов исключений

➜  ~ curl 'http://127.0.0.1:8080/code/exception/400' -i
HTTP/1.1 400
Content-Type: application/json;charset=UTF-8
Transfer-Encoding: chunked
Date: Sun, 05 Jan 2020 01:37:07 GMT
Connection: close

{"timestamp":"2020-01-05T01:37:07.662+0000","status":400,"error":"Bad Request","message":"老哥,你的请求有问题~~","path":"/code/exception/400"}%

➜  ~ curl 'http://127.0.0.1:8080/code/exception/500' -i
HTTP/1.1 500
Content-Type: application/json;charset=UTF-8
Transfer-Encoding: chunked
Date: Sun, 05 Jan 2020 01:37:09 GMT
Connection: close

{"timestamp":"2020-01-05T01:37:09.389+0000","status":500,"error":"Internal Server Error","message":"服务器失联了,请到月球上呼叫试试~~","path":"/code/exception/500"}%

Уведомление

  • Положение использования аннотации ResponseStatus поддерживает только стандартный Http-код (должен быть классом перечисленияorg.springframework.http.HttpStatus)

2. ResponseEntity

Эта поза относительно проста, возвращаемый результат метода должен бытьResponseEntity, два реальных случая приведены ниже

@GetMapping("401")
public ResponseEntity<String> _401() {
    return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body("{\"code\": 401, \"msg\": \"未授权!\"}");
}

@GetMapping("451")
public ResponseEntity<String> _451() {
    return ResponseEntity.status(451).body("{\"code\": 451, \"msg\": \"自定义异常!\"}");
}

результаты тестирования

➜  ~ curl 'http://127.0.0.1:8080/code/401' -i
HTTP/1.1 401
Content-Type: text/plain;charset=UTF-8
Content-Length: 34
Date: Sun, 05 Jan 2020 01:40:10 GMT

{"code": 401, "msg": "未授权!"}

➜  ~ curl 'http://127.0.0.1:8080/code/451' -i
HTTP/1.1 451
Content-Type: text/plain;charset=UTF-8
Content-Length: 40
Date: Sun, 05 Jan 2020 01:40:19 GMT

{"code": 451, "msg": "自定义异常!"}

Из приведенного выше примера использования вы можете узнать, что этот метод использования не только поддерживает стандартный код http, но также поддерживает пользовательский код (например, код возврата 451).

3. HttpServletResponse

Эта поза использования является прямой операциейHttpServletResponseОбъект, результат, возвращаемый ручным вводом

a. setStatus

/**
 * response.setStatus 支持自定义http code,并可以返回结果
 *
 * @param response
 * @return
 */
@GetMapping("525")
public String _525(HttpServletResponse response) {
    response.setStatus(525);
    return "{\"code\": 525, \"msg\": \"自定义错误码 525!\"}";
}

выходной результат

➜  ~ curl 'http://127.0.0.1:8080/code/525' -i
HTTP/1.1 525
Content-Type: text/plain;charset=UTF-8
Content-Length: 47
Date: Sun, 05 Jan 2020 01:45:38 GMT

{"code": 525, "msg": "自定义错误码 525!"}%

Метод использования относительно прост, просто установите статус напрямую и поддерживайте возврат пользовательского кода Http.

b. sendError

При использовании этой позы нужно обратить внимание, поддерживается только стандартный http-код, и в теле ответа не будет возвращаемых данных от вашего бизнеса, таких как

/**
 * send error 方式,只支持标准http状态码; 且不会带上返回的结果
 *
 * @param response
 * @return
 * @throws IOException
 */
@GetMapping("410")
public String _410(HttpServletResponse response) throws IOException {
    response.sendError(410, "send 410");
    return "{\"code\": 410, \"msg\": \"Gone 410!\"}";
}

@GetMapping("460")
public String _460(HttpServletResponse response) throws IOException {
    response.sendError(460, "send 460");
    return "{\"code\": 460, \"msg\": \"Gone 460!\"}";
}

выходной результат

➜  ~ curl 'http://127.0.0.1:8080/code/410' -i
HTTP/1.1 410
Content-Type: application/json;charset=UTF-8
Transfer-Encoding: chunked
Date: Sun, 05 Jan 2020 01:47:52 GMT

{"timestamp":"2020-01-05T01:47:52.300+0000","status":410,"error":"Gone","message":"send 410","path":"/code/410"}%

➜  ~ curl 'http://127.0.0.1:8080/code/460' -i
HTTP/1.1 500
Content-Type: application/json;charset=UTF-8
Transfer-Encoding: chunked
Date: Sun, 05 Jan 2020 01:47:54 GMT
Connection: close

{"timestamp":"2020-01-05T01:47:54.719+0000","status":460,"error":"Http Status 460","message":"send 460","path":"/code/460"}%

Из приведенного выше случая также видно, что когда мы используем ошибку отправки, если это стандартный код http, будет установлен заголовок ответа; если это пользовательский нераспознанный код, возвращаемый код http равен 500.

4. Резюме

Выше представлено несколько общих положений для настройки ответа на http-код.Ниже приводится сводка мер предосторожности при его использовании.

ResponseStatus

  • Поддерживает только стандартный http-код
  • Украсьте пользовательские классы исключений и создайте соответствующие классы исключений при использовании, чтобы добиться эффекта установки кода ответа.
    • Недостаток недоступен для неконтролируемых классов исключений
  • комбинировать@ExceptionHandler, используемый для украшения метода

ResponseEntity

В форме:

return ResponseEntity.status(451).body("{\"code\": 451, \"msg\": \"自定义异常!\"}");
  • Я лично считаю, что это самая мощная поза для использования, но она не так лаконична в письменной форме.
  • Поддержка пользовательского кода, поддержка настройки тела ответа

HttpServletResponse

  • setStatus: установка кода ответа, поддержка пользовательского кода, поддержка возврата тела ответа
  • sendError: Поддерживается только стандартный http-код. Если передан пользовательский код, возвращенный http-код будет 500

II. Другое

веб-сериал

Исходный код проекта

1. Блог одного пепла

Это не так хорошо, как письмо. Вышеупомянутое содержание чисто из семьи. Из-за ограниченных личных способностей неизбежно есть упущения и ошибки. Если вы найдете ошибки или у вас есть лучшие предложения, вы можете критиковать и исправлять их. Спасибо ты

Ниже представлен серый личный блог, в котором записываются все посты в блоге по учебе и работе, приглашаю всех посетить

一灰灰blog