Spring Web Header 解析常见错误

URL 的长度有限,所能携带的信息也因此受到了制约,如果想提供更多的信息,Header 往往是不二之举
例如 Content-Type 指定了我们的请求或者响应的内容类型,便于我们去做解码。

1.接受 Header 使用错 Map 类型

解析header的常见做法:

@RequestMapping(path = "/hi", method = RequestMethod.GET)
public String hi(@RequestHeader("myHeaderName") String name){
   //省略 body 处理
};
// 当header信息较多时可以如下方式

@RequestMapping(path = "/hi1", method = RequestMethod.GET)
public String hi1(@RequestHeader() Map map){
    return map.toString();
};

当header中,一个key有多个值时就不符合我们需求了
Key: value1,value2

Key:value1
Key:value2

源码中执行:HandlerMethodArgumentResolver#resolveArgument方法进行参数的解析
修正:

//方式 1
@RequestHeader() MultiValueMap map
//方式 2
@RequestHeader() HttpHeaders map

2.错认为 Header 名称首字母可以一直忽略大小写

在 HTTP 协议中,Header 的名称是无所谓大小写的


@RequestMapping(path = "/hi2", method = RequestMethod.GET)
public String hi2(@RequestHeader("MyHeader") String myHeader){
    return myHeader;
};

// 当我们从MultiValueMap获取header的值无法忽略大小写获取值
@RequestMapping(path = "/hi2", method = RequestMethod.GET)
public String hi2(@RequestHeader("MyHeader") String myHeader, @RequestHeader MultiValueMap map){
    return myHeader + " compare with : " + map.get("MyHeader");
};

源码解析:RequestHeaderMethodArgumentResolver#resolveName

  • 存取 Map 的 Header 是没有忽略大小写的
  • 从 Map 中获取的 Header 也没有忽略大小写
  • 从HttpHeaders map中获取key是忽略大小写的
    在实际使用时,虽然 HTTP 协议规范可以忽略大小写,但是不是所有框架提供的接口方法都是可以忽略大小写的

3.试图在 Controller 中随意自定义 CONTENT_TYPE

@RequestMapping(path = "/hi3", method = RequestMethod.GET)
public String hi3(HttpServletResponse httpServletResponse){
  httpServletResponse.addHeader("myheader", "myheadervalue");
  httpServletResponse.addHeader(HttpHeaders.CONTENT_TYPE, "application/json");
    return "ok";
};

在这里插入图片描述
虽然我们在 Controller 设置了 Content-Type,但是它是一种特殊的 Header,所以在 Spring Boot 基于内嵌 Tomcat 开发时并不一定能设置成功,最终返回的 Content-Type 是根据实际的返回值及类型等多个因素来决定的

修正:

  • 修改请求中的 Accept 头,约束返回类型。带上 Accept 头,这样服务器在最终决定 MediaType 时,会选择 Accept 的值。具体执行可参考方法 AbstractMessageConverterMethodProcessor#getAcceptableMediaTypes
  • 标记返回类型
@RequestMapping(path = "/hi3", method = RequestMethod.GET, produces = {"application/json"})

使用 produces 属性来指明即可。这样的方式影响的是可以返回的 Media 类型,一旦设置,下面的方法就可以只返回一个指明的类型了。参考 AbstractMessageConverterMethodProcessor#getProducibleMediaTypes

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值