当前位置: 首页 > news >正文

Spring MVC 获取请求头参数详解


Spring MVC 获取请求头参数详解


1. 核心方法与注解

在 Spring MVC 中,可以通过以下方式获取请求头参数:

  1. 直接使用 HttpServletRequest 对象
  2. 使用 @RequestHeader 注解
  3. 在拦截器或过滤器中处理

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
defaultValuerequired=false 时,头不存在时返回的默认值

4. 常见问题与解决方案

Q1:请求头名称大小写敏感吗?

A:

  • Spring 的 @RequestHeader 默认不区分大小写(例如 User-Agentuser-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. 最佳实践
  1. 优先使用 @RequestHeader:代码简洁且类型安全。
  2. 避免硬编码头名称:定义常量类存储头名称(如 public static final String AUTH_HEADER = "Authorization")。
  3. 处理可选头时设置默认值:减少 null 判断。
  4. 复杂验证使用拦截器:如 Token 校验、权限检查等。
  5. 注意头名称大小写:建议使用小写或与 API 文档一致的格式(如 x-custom-header)。

总结

通过 @RequestHeaderHttpServletRequest 或拦截器,可以灵活获取和处理请求头参数。根据需求选择合适的方式:

  • 简单场景:直接使用 @RequestHeader
  • 复杂场景:结合 HttpServletRequest 或拦截器实现高级逻辑。
    掌握这些方法,可以有效处理认证、多语言、客户端信息等常见需求。

相关文章:

  • 【HarmonyOS 5】敏感信息本地存储详解
  • 数据结构---B树
  • decompiled.class file bytecode version50(java 6)
  • 分页查询列表每页1000条的优化
  • day1 初识MySQL
  • 词袋模型和TF-IDF(数学公式推导、手动实现、调库使用、示例:使用词袋模型处理多个文档)详解
  • 【前端工程化】-【vue2-ele项目升级】
  • error: failed to run custom build command for `yeslogic-fontconfig-sys v6.0.0`
  • docker 安装 Gitlab
  • 【go】--编译
  • Android基础教程 - 学习完成记录
  • UI基础(1)
  • 【双指针】专题:LeetCode 1089题解——复写零
  • 202527 | RabbitMQ-基础 | 队列 | Direct + Fanout + Topic 交换机 | 消息转换器
  • linux系统安装docker及Qdrant
  • LeetCode 解题思路 38(前 K 个高频元素、数据流的中位数)
  • centos7 yum安装mysql8.0详细步骤(图文教程)
  • java和c#的相似及区别基础对比
  • 如何实现语音智能客服(一)
  • Linux上位机开发实践(OpenCV算法硬件加速)
  • A股三大股指收涨:军工股掀涨停潮,两市成交近1.5万亿元
  • 多个“网约摩托车”平台上线,工人日报:安全与监管不能掉队
  • 科技日报刊文批院士专家“赶场式”跑会:助长浮躁之气功利之心
  • 特朗普:不谋求第三个总统任期,中意万斯鲁比奥“接棒”
  • 中南财经政法大学法学院党委副书记易育去世,终年45岁
  • 莫斯科一机场实施临时限制措施