«1. Обзор

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

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

2. Заголовки для нереактивных компонентов

Если мы хотим установить заголовки для отдельных ответов, мы можем использовать объекты HttpServletResponse или ResponseEntity.

С другой стороны, если наша цель — добавить фильтр ко всем или нескольким ответам, нам потребуется настроить фильтр.

2.1. Использование HttpServletResponse

Нам просто нужно добавить объект HttpServletResponse в нашу конечную точку REST в качестве аргумента, а затем использовать метод addHeader():

@GetMapping("/http-servlet-response")
public String usingHttpServletResponse(HttpServletResponse response) {
    response.addHeader("Baeldung-Example-Header", "Value-HttpServletResponse");
    return "Response with header using HttpServletResponse";
}

Как показано в примере, нам не нужно возвращать ответ объект.

2.2. Использование ResponseEntity

В этом случае воспользуемся BodyBuilder, предоставляемым классом ResponseEntity:

@GetMapping("/response-entity-builder-with-http-headers")
public ResponseEntity<String> usingResponseEntityBuilderAndHttpHeaders() {
    HttpHeaders responseHeaders = new HttpHeaders();
    responseHeaders.set("Baeldung-Example-Header", 
      "Value-ResponseEntityBuilderWithHttpHeaders");

    return ResponseEntity.ok()
      .headers(responseHeaders)
      .body("Response with header using ResponseEntity");
}

Класс HttpHeaders предлагает множество удобных методов для установки наиболее распространенных заголовков.

Мы можем увидеть больше примеров, иллюстрирующих эти моменты, в нашем репозитории Github.

2.3. Добавление заголовка для всех ответов

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

Конечно, было бы неприятно, если бы нам пришлось реплицировать предыдущий код для каждого метода сопоставления.

Лучший способ сделать это — настроить фильтр в нашем сервисе:

@WebFilter("/filter-response-header/*")
public class AddResponseHeaderFilter implements Filter {

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, 
      FilterChain chain) throws IOException, ServletException {
        HttpServletResponse httpServletResponse = (HttpServletResponse) response;
        httpServletResponse.setHeader(
          "Baeldung-Example-Filter-Header", "Value-Filter");
        chain.doFilter(request, response);
    }

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        // ...
    }

    @Override
    public void destroy() {
        // ...
    }
}

Аннотация @WebFilter позволяет нам указать шаблоны URL, для которых этот фильтр станет эффективным.

Как мы указывали в этой статье, чтобы сделать наш фильтр доступным для обнаружения Spring, нам нужно добавить аннотацию @ServletComponentScan к нашему классу приложения Spring:

@ServletComponentScan
@SpringBootApplication
public class ResponseHeadersApplication {

    public static void main(String[] args) {
        SpringApplication.run(ResponseHeadersApplication.class, args);
    }
}

Мы можем избежать этого последнего шага, если нам не нужны какие-либо функции, предоставляемые @WebFilter, вместо этого мы используем аннотацию @Component в нашем классе Filter.

3. Заголовки для реактивных конечных точек

Опять же, мы увидим, как устанавливать заголовки для ответов одной конечной точки, используя классы и интерфейсы ServerHttpResponse, ResponseEntity или ServerResponse (для функциональных конечных точек).

Мы также узнаем, как реализовать Spring 5 WebFilter, чтобы добавить заголовок ко всем нашим ответам.

3.1. Использование ServerHttpResponse

Этот подход очень похож на аналог HttpServletResponse:

@GetMapping("/server-http-response")
public Mono<String> usingServerHttpResponse(ServerHttpResponse response) {
    response.getHeaders().add("Baeldung-Example-Header", "Value-ServerHttpResponse");
    return Mono.just("Response with header using ServerHttpResponse");
}

3.2. Использование ResponseEntity

Мы можем использовать класс ResponseEntity точно так же, как и для нереактивных конечных точек:

@GetMapping("/response-entity")
public Mono<ResponseEntity<String>> usingResponseEntityBuilder() {
    String responseHeaderKey = "Baeldung-Example-Header";
    String responseHeaderValue = "Value-ResponseEntityBuilder";
    String responseBody = "Response with header using ResponseEntity (builder)";

    return Mono.just(ResponseEntity.ok()
      .header(responseHeaderKey, responseHeaderValue)
      .body(responseBody));
}

3.3. Использование ServerResponse

Классы и интерфейсы, представленные в двух последних подразделах, можно использовать в аннотированных классах @Controller, но они не подходят для новой функциональной веб-инфраструктуры Spring 5.

Если мы хотим установить заголовок для HandlerFunction, нам нужно получить доступ к интерфейсу ServerResponse:

public Mono<ServerResponse> useHandler(final ServerRequest request) {
     return ServerResponse.ok()
        .header("Baeldung-Example-Header", "Value-Handler")
        .body(Mono.just("Response with header using Handler"),String.class);
}

3.4. Добавление заголовка для всех ответов

Наконец, Spring 5 предоставляет интерфейс WebFilter для установки заголовка для всех ответов, полученных службой:

@Component
public class AddResponseHeaderWebFilter implements WebFilter {

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) {
        exchange.getResponse()
          .getHeaders()
          .add("Baeldung-Example-Filter-Header", "Value-Filter");
        return chain.filter(exchange);
    }
}

4. Заключение

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

Как всегда, все примеры доступны в нашем репозитории Github, как нереактивные, так и использующие специфические функции Spring 5.