How to Read HTTP Headers in Spring REST Controllers – 如何在Spring REST控制器中读取HTTP头信息

最后修改: 2019年 4月 8日

中文/混合/英文(键盘快捷键:t)

1. Overview

1.概述

In this quick tutorial, we’re going to look at how to access HTTP Headers in a Spring Rest Controller.

在这个快速教程中,我们将了解如何在Spring Rest控制器中访问HTTP头信息。

First, we’ll be using the @RequestHeader annotation to read headers individually as well as all together.

首先,我们将使用@RequestHeader注解来单独读取头文件,也可以一起读取。

After that, we’ll take a deeper look at the @RequestHeader attributes.

之后,我们将深入了解一下@RequestHeader属性。

2. Accessing HTTP Headers

2.访问HTTP头文件

2.1. Individually

2.1.单独的

If we need access to a specific header, we can configure @RequestHeader with the header name:

如果我们需要访问一个特定的头,我们可以用头的名字配置@RequestHeader

@GetMapping("/greeting")
public ResponseEntity<String> greeting(@RequestHeader(HttpHeaders.ACCEPT_LANGUAGE) String language) {
    // code that uses the language variable
    return new ResponseEntity<String>(greeting, HttpStatus.OK);
}

Then we can access the value using the variable passed into our method. If a header named accept-language isn’t found in the request, the method returns a “400 Bad Request” error.

然后我们可以使用传入我们方法的变量来访问这个值。如果在请求中没有找到名为accept-language的头,该方法会返回一个 “400 Bad Request “的错误。

Our headers don’t have to be strings. If we know our header is a number, we can declare our variable as a numeric type:

我们的标题不一定是字符串。如果我们知道我们的标题是一个数字,我们可以将我们的变量声明为数字类型。

@GetMapping("/double")
public ResponseEntity<String> doubleNumber(@RequestHeader("my-number") int myNumber) {
    return new ResponseEntity<String>(String.format("%d * 2 = %d", 
      myNumber, (myNumber * 2)), HttpStatus.OK);
}

2.2. All at Once

2.2.一次完成

If we’re not sure which headers will be present, or we need more of them than we want in our method’s signature, we can use the @RequestHeader annotation without a specific name.

如果我们不确定哪些头信息会出现,或者我们需要的头信息比我们方法签名中的要多,我们可以使用@RequestHeader注解,而不使用具体的名称。

We have a few choices for our variable type: a Map, a MultiValueMap, or a HttpHeaders object.

我们的变量类型有几个选择:MapMultiValueMap,或HttpHeaders对象。

First, let’s get the request headers as a Map:

首先,让我们以Map的形式获得请求头信息。

@GetMapping("/listHeaders")
public ResponseEntity<String> listAllHeaders(
  @RequestHeader Map<String, String> headers) {
    headers.forEach((key, value) -> {
        LOG.info(String.format("Header '%s' = %s", key, value));
    });

    return new ResponseEntity<String>(
      String.format("Listed %d headers", headers.size()), HttpStatus.OK);
}

If we use a Map and one of the headers has more than one value, we’ll get only the first value. This is the equivalent of using the getFirst method on a MultiValueMap.

如果我们使用一个Map,并且其中一个标题有一个以上的值,我们将只得到第一个值。这相当于在一个MultiValueMap上使用getFirst方法。

If our headers may have multiple values, we can get them as a MultiValueMap:

如果我们的标头可能有多个值,我们可以将它们作为一个MultiValueMap来获取。

@GetMapping("/multiValue")
public ResponseEntity<String> multiValue(
  @RequestHeader MultiValueMap<String, String> headers) {
    headers.forEach((key, value) -> {
        LOG.info(String.format(
          "Header '%s' = %s", key, value.stream().collect(Collectors.joining("|"))));
    });
        
    return new ResponseEntity<String>(
      String.format("Listed %d headers", headers.size()), HttpStatus.OK);
}

We can also get our headers as an HttpHeaders object:

我们也可以以HttpHeaders对象的形式获得我们的头文件。

@GetMapping("/getBaseUrl")
public ResponseEntity<String> getBaseUrl(@RequestHeader HttpHeaders headers) {
    InetSocketAddress host = headers.getHost();
    String url = "http://" + host.getHostName() + ":" + host.getPort();
    return new ResponseEntity<String>(String.format("Base URL = %s", url), HttpStatus.OK);
}

The HttpHeaders object has accessors for common application headers.

HttpHeaders对象有常见应用程序头的访问器。

When we access a header by name from a Map, MultiValueMap or the HttpHeaders object, we’ll get a null if it isn’t present.

当我们从MapMultiValueMapHttpHeaders对象中按名称访问一个头时,如果它不存在,我们会得到一个null

3. @RequestHeader Attributes

3.@RequestHeader属性

Now that we’ve gone over the basics of accessing request headers with the @RequestHeader annotation, let’s take a closer look at its attributes.

现在我们已经了解了使用@RequestHeader注解访问请求头的基本情况,让我们仔细看看它的属性。

We’ve already used the name or value attributes implicitly when we’ve specifically named our header:

我们已经在具体命名我们的头时隐含地使用了namevalue属性。

public ResponseEntity<String> greeting(@RequestHeader(HttpHeaders.ACCEPT_LANGUAGE) String language) {}

We can accomplish the same thing by using the name attribute:

我们可以通过使用name 属性来完成同样的事情。

public ResponseEntity<String> greeting(
  @RequestHeader(name = HttpHeaders.ACCEPT_LANGUAGE) String language) {}

Next, let’s use the value attribute exactly the same way:

接下来,让我们以完全相同的方式使用value属性。

public ResponseEntity<String> greeting(
  @RequestHeader(value = HttpHeaders.ACCEPT_LANGUAGE) String language) {}

When we name a header specifically, the header is required by default. If the header isn’t found in the request, the controller returns a 400 error.

当我们特别命名一个头时,该头是默认需要的。如果在请求中没有找到该头,控制器会返回一个400错误。

Let’s use the required attribute to indicate that our header isn’t required:

让我们使用required属性来表示我们的头文件不是必需的。

@GetMapping("/nonRequiredHeader")
public ResponseEntity<String> evaluateNonRequiredHeader(
  @RequestHeader(value = "optional-header", required = false) String optionalHeader) {
    return new ResponseEntity<String>(String.format(
      "Was the optional header present? %s!",
        (optionalHeader == null ? "No" : "Yes")),HttpStatus.OK);
}

Since our variable will be null if the header isn’t present in the request, we need to be sure to do the appropriate null checking.

由于如果请求中不存在头信息,我们的变量将是null,我们需要确保做适当的null检查。

Let’s use the defaultValue attribute to provide a default value for our header:

让我们使用defaultValue属性来为我们的标头提供一个默认值。

@GetMapping("/default")
public ResponseEntity<String> evaluateDefaultHeaderValue(
  @RequestHeader(value = "optional-header", defaultValue = "3600") int optionalHeader) {
    return new ResponseEntity<String>(
      String.format("Optional Header is %d", optionalHeader), HttpStatus.OK);
}

4. Conclusion

4.总结

In this short tutorial, we learned how to access request headers in Spring REST controllers.

在这个简短的教程中,我们学习了如何在Spring REST控制器中访问请求头信息。

First, we used the @RequestHeader annotation to supply request headers to our controller methods.

首先,我们使用@RequestHeader注解来为我们的控制器方法提供请求头信息。

After checking out the basics, we took a detailed look at the attributes for the @RequestHeader annotation.

在检查完基础知识后,我们详细看了一下@RequestHeader注解的属性。

The example code is available over on GitHub.

示例代码可在GitHub上获得over