Method for getting request headers using @ RequestHeader in SpringBoot2

  • 2021-12-05 06:12:21
  • OfStack

Directory 1. Use @ RequestHeader to get the request header (1) Get some 1 request header
(2) Get the numeric request header
(3) Get all request headers once
2. Detailed explanation of @ RequestHeader annotation (1) name, value attributes
(2) required attribute
(3) defaultValue attribute

The @ RequestHeader annotation is provided in springMVC/SpringBoot to get the request header.

1. Use @ RequestHeader to get the request header

(1) Get some 1 request header

For example, get the accept-language request header:


@GetMapping("/getLanguage")
public Result test(@RequestHeader("accept-language") String language) {
    // ......
    
    return new Result(true, 600, language);
}

With postman, when the accept-language request header is not set, the response is:


{
    "timestamp": "2019-12-3T20:43:58.971+0000",
    "status": 400,
    "error": "Bad Request",
    "message": "Missing request header 'accept-language' for method parameter of type String",
    "path": "/getLanguage"
}

After adding the accept-language request header, the response is:


{
    "flag": true,
    "code": 600,
    "message": "en-US,en;q=0.9,zh-CN;q=0.8,zh;q=0.7"
} 

(2) Get the numeric request header


@GetMapping("/num")
public Result getNumber(@RequestHeader("my-number") int myNumber) {
    return new Result(true, HttpStatus.OK.value(), String.valueOf(myNumber));
}

Use postman to set the my-number request header value to 1 and respond:


{
    "flag": true,
    "code": 200,
    "message": "1"
}

(3) Get all request headers once

1. Receive all request headers using Map


@GetMapping("/getHeaders")
public Result listAllHeaders(@RequestHeader Map<String, String> headers) {
    headers.forEach((key, value) -> {
        //  Output all request headers in the log 
        logger.info(String.format("Header '%s' = %s", key, value));
    });
    return new Result(true, HttpStatus.OK.value(), "");
}

Request the address using postman, and the console prints:

2019-12-03 21:10:35,993 INFO [http-nio-10000-exec-9] com.chushiyan.test.controller.HttpHeaderController: Header 'user-agent' = PostmanRuntime/7.20.1
2019-12-03 21:10:35,994 INFO [http-nio-10000-exec-9] com.chushiyan.test.controller.HttpHeaderController: Header 'accept' = */*
2019-12-03 21:10:35,994 INFO [http-nio-10000-exec-9] com.chushiyan.test.controller.HttpHeaderController: Header 'cache-control' = no-cache
2019-12-03 21:10:35,995 INFO [http-nio-10000-exec-9] com.chushiyan.test.controller.HttpHeaderController: Header 'postman-token' = 47dce6dd-c082-47b0-8867-720e45205aa1
2019-12-03 21:10:35,995 INFO [http-nio-10000-exec-9] com.chushiyan.test.controller.HttpHeaderController: Header 'host' = localhost:10000
2019-12-03 21:10:35,995 INFO [http-nio-10000-exec-9] com.chushiyan.test.controller.HttpHeaderController: Header 'accept-encoding' = gzip, deflate
2019-12-03 21:10:35,996 INFO [http-nio-10000-exec-9] com.chushiyan.test.controller.HttpHeaderController: Header 'connection' = keep-alive

2. Receive all request headers using MultiValueMap

When there are multiple values for 1 request header, you can use MultiValueMap to receive all request headers


@GetMapping("/getHeaders2")
public Result multiValue(@RequestHeader MultiValueMap<String, String> headers) {
    headers.forEach((key, value) -> {
        logger.info(String.format(
                "Header '%s' = %s", key, value.stream().collect(Collectors.joining("/"))));
    });
    return new Result(true, HttpStatus.OK.value(), "");
}

3. Use HttpHeaders to receive the request header used


@GetMapping("/getBaseUrl")
public Result getBaseUrl(@RequestHeader HttpHeaders headers) {
    //  Gets all the request headers, just use the Host Request header 
    InetSocketAddress host = headers.getHost();
    String url = "http://" + host.getHostName() + ":" + host.getPort();
    return new Result(true, HttpStatus.OK.value(),url);
}

Request this address using postman and get a response:


{
    "flag": true,
    "code": 200,
    "message": "http://localhost:10000"
}

2. Detailed explanation of @ RequestHeader annotations

The @ RequestHeader source code is as follows:


package org.springframework.web.bind.annotation;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

import org.springframework.core.annotation.AliasFor;

/**
 * Annotation which indicates that a method parameter should be bound to a web request header.
 *
 * <p>Supported for annotated handler methods in Spring MVC and Spring WebFlux.
 *
 * <p>If the method parameter is {@link java.util.Map Map&lt;String, String&gt;},
 * {@link org.springframework.util.MultiValueMap MultiValueMap&lt;String, String&gt;},
 * or {@link org.springframework.http.HttpHeaders HttpHeaders} then the map is
 * populated with all header names and values.
 *
 * @author Juergen Hoeller
 * @author Sam Brannen
 * @since 3.0
 * @see RequestMapping
 * @see RequestParam
 * @see CookieValue
 */
@Target(ElementType.PARAMETER)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface RequestHeader {

   /**
    * Alias for {@link #name}.
    */
   @AliasFor("name")
   String value() default "";

   /**
    * The name of the request header to bind to.
    * @since 4.2
    */
   @AliasFor("value")
   String name() default "";

   /**
    * Whether the header is required.
    * <p>Defaults to {@code true}, leading to an exception being thrown
    * if the header is missing in the request. Switch this to
    * {@code false} if you prefer a {@code null} value if the header is
    * not present in the request.
    * <p>Alternatively, provide a {@link #defaultValue}, which implicitly
    * sets this flag to {@code false}.
    */
   boolean required() default true;

   /**
    * The default value to use as a fallback.
    * <p>Supplying a default value implicitly sets {@link #required} to
    * {@code false}.
    */
   String defaultValue() default ValueConstants.DEFAULT_NONE;

}

(1) name, value attributes


{
    "timestamp": "2019-12-3T20:43:58.971+0000",
    "status": 400,
    "error": "Bad Request",
    "message": "Missing request header 'accept-language' for method parameter of type String",
    "path": "/getLanguage"
}
0

The above two lines of code have the same effect. Of course, they can all be omitted as: (because value can be omitted)


{
    "timestamp": "2019-12-3T20:43:58.971+0000",
    "status": 400,
    "error": "Bad Request",
    "message": "Missing request header 'accept-language' for method parameter of type String",
    "path": "/getLanguage"
}
1

Because from the source code, you can see that name/value are aliases for each other:


{
    "timestamp": "2019-12-3T20:43:58.971+0000",
    "status": 400,
    "error": "Bad Request",
    "message": "Missing request header 'accept-language' for method parameter of type String",
    "path": "/getLanguage"
}
2

@ AliasFor Notes:

@ AliasFor is used in pairs in the same annotation to indicate that two attributes are aliases for each other. For example, value and name are aliases for each other. The @ AliasFor tag has one usage restriction, such as requiring the attribute value types of aliases, and the default values are all the same. Annotations that are aliases to each other must appear in pairs. For example, if @ AliasFor ("name") is added to the value attribute, then @ AliasFor ("value") must be added to the name attribute.

(2) required Attributes


@GetMapping("/getHeader3")
public Result evaluateNonRequiredHeader(
        @RequestHeader(value = "chushiyan", required = false) String header) {

    return new Result(true,HttpStatus.OK.value(),"");
}

If required = false is not added, an error will be reported if this chushiyan request header is not in the request header.

(3) defaultValue Attributes

You can specify default values using the defaultValue property


{
    "timestamp": "2019-12-3T20:43:58.971+0000",
    "status": 400,
    "error": "Bad Request",
    "message": "Missing request header 'accept-language' for method parameter of type String",
    "path": "/getLanguage"
}
4

Related articles: