1 故事背景
- 最近项目上有个业务需求,翻译成技术需求,即:将
request.headers中的几个header入参转换成request.body(pageRequest)中的内置参数。
为便于灵活配置,header 参数名称是动态可配置的(存放于nacos配置中心),比如:
sysCode、Accept-Language
- 技术实现,主要就
springmvc的org.springframework.web.bind.WebDataBinder,并结合javax.servlet.http.HttpServletRequest,实现将header中的指定参数转发至request.body(pageRequest).params中
核心代码如下:
@RestController("cn.johnnyzen.bd.dataservice.biz.dataservice.controller.v2.CommonSearchController") @Validated @Api(tags = "DATA2API Controller # V2") public class CommonSearchController implements DataServiceOpenApi { // ... @Autowired private ServiceConfig serviceConfig; // ... @InitBinder public void forwardedHeadersToParamsDataBinder(WebDataBinder binder, HttpServletRequest request) { //判断是否启用本特性 ForwardedHeaders forwardedHeaders = serviceConfig.getForwardedHeaders(); if(ObjectUtils.isEmpty(forwardedHeaders) || forwardedHeaders.getEnable().equals(Boolean.FALSE)){ logger.warn("Fail to forward headers to body's params because that `service-config.forwardedHeaders` be empty or not enabled!"); return ; } logger.info("Start to forward request's headers to request body params with `service-config.forwardedHeaders`,config data as follows : n{}", forwardedHeaders); //获取被绑定对象----PageRequest PageRequest<Map<String,Object>> pageRequest = (PageRequest<Map<String, Object>>) binder.getTarget(); if(ObjectUtils.isEmpty(pageRequest) || ObjectUtils.isEmpty(pageRequest.getParams())){ logger.error("`request.body(pageRequest)` or `request.body(pageRequest).params` is empty!"); return; } Map<String,Object> dynamicParams = pageRequest.getParams(); List<ForwardHeaderToParamConfig> forwardHeaderToParamConfigList = forwardedHeaders.getHeaders(); forwardHeaderToParamConfigList.stream().forEach(forwardedHeaderConfig -> { //获取目标header参数值,并转发至params中 String headerName = forwardedHeaderConfig.getHeader(); String headerValue = request.getHeader( forwardedHeaderConfig.getHeader() ); String paramName = forwardedHeaderConfig.getParam(); logger.debug("headerName:{}, headerValue:{}, paramName:{}", headerName, headerValue, paramName); dynamicParams.put(paramName, headerValue); }); } // ... }
![[Servlet/Tomcat] HttpServletRequest#getHeader(headerNameWithIgnoreCase)(获取header时不区分大小写)](http://www.itfaba.com/wp-content/themes/kemi/images/loading.gif)
![[Servlet/Tomcat] HttpServletRequest#getHeader(headerNameWithIgnoreCase)(获取header时不区分大小写)](http://www.itfaba.com/wp-content/themes/kemi/images/loading.gif)
- 那么,我写这篇博客的目的是什么呢?
- 你有没有这么一个疑惑:
request.getHeader(headerName),这个基于Tomcat.catalina实现的方法,是否区分headerName的大小写?
如果不区分大小写,那还好办;如果区分大小写,就尴尬了————我将需要将
Accept-Language的每一种字母大小写的可能性都要一一进行配置!
经过源码分析,答案是:request.getHeader(headerName)不区分大小写!
感兴趣的朋友,可以进入第2章节,一起看看源码
2 源码分析
- springmvc: 5.2.15.RELEASE
- springboot: 2.3.12.RELEASE
- tomcat-embed: 9.0.46 (springboot内嵌的tomcat)
- 调试工具: IDEA
Step1 javax.servlet.http.HttpServletRequest : request.getHeader("Accept-Language")
import javax.servlet.http.HttpServletRequest; //... request.getHeader("Accept-Language") //...
![[Servlet/Tomcat] HttpServletRequest#getHeader(headerNameWithIgnoreCase)(获取header时不区分大小写)](http://www.itfaba.com/wp-content/themes/kemi/images/loading.gif)
Step2 javax.servlet.http.HttpServletRequest#getHeader
javax.servlet.http.HttpServletRequest#getHeader
![[Servlet/Tomcat] HttpServletRequest#getHeader(headerNameWithIgnoreCase)(获取header时不区分大小写)](http://www.itfaba.com/wp-content/themes/kemi/images/loading.gif)
Step3 org.apache.catalina.connector.Request#getHeader
特别说明:
org.apache.catalina.connector.Request#getHeader其实现了接口:javax.servlet.http.HttpServletRequest#getHeader
org.apache.catalina.connector.Request#getHeader
![[Servlet/Tomcat] HttpServletRequest#getHeader(headerNameWithIgnoreCase)(获取header时不区分大小写)](http://www.itfaba.com/wp-content/themes/kemi/images/loading.gif)
Step4 org.apache.coyote.Request#getHeader
org.apache.coyote.Request#getHeader
![[Servlet/Tomcat] HttpServletRequest#getHeader(headerNameWithIgnoreCase)(获取header时不区分大小写)](http://www.itfaba.com/wp-content/themes/kemi/images/loading.gif)
Step5 org.apache.tomcat.util.http.MimeHeaders#getHeader
org.apache.tomcat.util.http.MimeHeaders#getHeader
![[Servlet/Tomcat] HttpServletRequest#getHeader(headerNameWithIgnoreCase)(获取header时不区分大小写)](http://www.itfaba.com/wp-content/themes/kemi/images/loading.gif)
Step6 org.apache.tomcat.util.http.MimeHeaders#getValue(java.lang.String)
org.apache.tomcat.util.http.MimeHeaders#getValue(java.lang.String)
![[Servlet/Tomcat] HttpServletRequest#getHeader(headerNameWithIgnoreCase)(获取header时不区分大小写)](http://www.itfaba.com/wp-content/themes/kemi/images/loading.gif)
X 参考文献
无