Spring MVC 获取请求头参数详解
Spring MVC 获取请求头参数详解
1. 核心方法与注解
在 Spring MVC 中,可以通过以下方式获取请求头参数:
- 直接使用
HttpServletRequest
对象 - 使用
@RequestHeader
注解 - 在拦截器或过滤器中处理
2. 完整代码示例
2.1 使用 @RequestHeader
注解
import org.springframework.web.bind.annotation.*;
import java.util.Arrays;
@RestController
public class HeaderController {
// 1. 获取单个请求头(必填)
@GetMapping("/get-header")
public String getHeader(
@RequestHeader("User-Agent") String userAgent
) {
return "User-Agent: " + userAgent;
}
// 2. 获取可选头(设置默认值)
@GetMapping("/optional-header")
public String getOptionalHeader(
@RequestHeader(name = "X-Custom-Header", required = false, defaultValue = "default") String customHeader
) {
return "Custom Header: " + customHeader;
}
// 3. 获取多个同名头(返回数组)
@GetMapping("/multiple-headers")
public String getMultipleHeaders(
@RequestHeader("Accept-Language") String[] acceptLanguages
) {
return "Languages: " + String.join(", ", acceptLanguages);
}
}
2.2 使用 HttpServletRequest
对象
import javax.servlet.http.HttpServletRequest;
@RestController
public class HeaderController {
@GetMapping("/servlet-request")
public String getHeaders(HttpServletRequest request) {
// 1. 获取单个头
String userAgent = request.getHeader("User-Agent");
// 2. 获取所有头名称
Enumeration<String> headerNames = request.getHeaderNames();
StringBuilder sb = new StringBuilder("All Headers:\n");
while (headerNames.hasMoreElements()) {
String name = headerNames.nextElement();
sb.append(name).append(": ").append(request.getHeader(name)).append("\n");
}
return sb.toString();
}
}
2.3 处理复杂请求头(如 Authorization)
@GetMapping("/auth-header")
public String getAuthorizationHeader(
@RequestHeader("Authorization") String authHeader
) {
// 提取 Bearer Token
if (authHeader != null && authHeader.startsWith("Bearer ")) {
String token = authHeader.substring(7);
return "Token: " + token;
}
return "No token found";
}
2.4 在拦截器中获取请求头
import org.springframework.web.servlet.HandlerInterceptor;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class HeaderInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(
HttpServletRequest request,
HttpServletResponse response,
Object handler
) throws Exception {
// 检查请求头
String token = request.getHeader("Authorization");
if (token == null) {
response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "Missing token");
return false;
}
return true;
}
}
2.5 配置拦截器(需在配置类中注册)
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new HeaderInterceptor());
}
}
3. 核心注解 @RequestHeader
详解
参数选项 | 作用 |
---|---|
name | 请求头名称(区分大小写,但 Spring 默认不敏感) |
required | 是否必填(默认 true ,不存在时抛出 MissingRequestHeaderException ) |
defaultValue | 当 required=false 时,头不存在时返回的默认值 |
4. 常见问题与解决方案
Q1:请求头名称大小写敏感吗?
A:
- Spring 的
@RequestHeader
默认不区分大小写(例如User-Agent
和user-agent
视为相同)。 - 直接使用
HttpServletRequest.getHeader(name)
时,需注意服务器可能将头名称转为小写(具体行为依赖容器,如 Tomcat)。
Q2:如何获取所有请求头?
A:
- 使用
HttpServletRequest.getHeaderNames()
遍历所有头名称:Enumeration<String> headerNames = request.getHeaderNames(); while (headerNames.hasMoreElements()) { String name = headerNames.nextElement(); String value = request.getHeader(name); // 处理每个头 }
Q3:如何处理多个同名请求头?
A:
- 使用
@RequestHeader
注解返回数组:@GetMapping("/languages") public String getLanguages( @RequestHeader("Accept-Language") String[] languages ) { return "Languages: " + Arrays.toString(languages); }
Q4:如何避免空指针异常?
A:
- 设置
required=false
并提供默认值:@RequestHeader(name = "X-Optional-Header", required = false, defaultValue = "not-set") String header
Q5:如何验证请求头格式?
A:
- 结合
@RequestHeader
和自定义注解(如@Pattern
):@GetMapping("/validate") public String validateToken( @RequestHeader("Authorization") @Pattern(regexp = "Bearer .+") String token ) { // 验证通过后处理 return "Valid token"; }
5. 总结表格:获取请求头的方法对比
方法类型 | 实现方式 | 适用场景 | 示例代码片段 |
---|---|---|---|
@RequestHeader | 方法参数注解 | 单个/多个头,需类型安全 | @RequestHeader("User-Agent") String ua |
HttpServletRequest | 直接访问原生对象 | 复杂操作、遍历所有头 | request.getHeader("Authorization") |
拦截器/过滤器 | 全局或特定路径拦截 | 预处理(如 Token 验证) | HeaderInterceptor 中检查 Authorization 头 |
6. 最佳实践
- 优先使用
@RequestHeader
:代码简洁且类型安全。 - 避免硬编码头名称:定义常量类存储头名称(如
public static final String AUTH_HEADER = "Authorization"
)。 - 处理可选头时设置默认值:减少
null
判断。 - 复杂验证使用拦截器:如 Token 校验、权限检查等。
- 注意头名称大小写:建议使用小写或与 API 文档一致的格式(如
x-custom-header
)。
总结
通过 @RequestHeader
、HttpServletRequest
或拦截器,可以灵活获取和处理请求头参数。根据需求选择合适的方式:
- 简单场景:直接使用
@RequestHeader
。 - 复杂场景:结合
HttpServletRequest
或拦截器实现高级逻辑。
掌握这些方法,可以有效处理认证、多语言、客户端信息等常见需求。