背景:修改一个http请求的Header。希望把Header中的X-Biz-App根据properties中的配置进行截断一部分(截断第二个’|'往后的字符)。
开发:修改Header第一时间想到过滤器。但是过滤器不能访问通过@value加载配置参数,手动加载代价又太高不合适。所以采用FilterRegistrationBean动态的注册Filter。并在自定义的Filter类中通过重写getHeader方法进行实现。
代码如下:
- 注册Filter配置类
TeslaFilterConfig
:
@Configuration
public class TeslaFilterConfig {
@Value("${filter.biz-app:}")
private String bizAppEnv;
@Bean
public FilterRegistrationBean regBizAppFilter() {
FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean();
filterRegistrationBean.setFilter(new BizAppFilter());
filterRegistrationBean.addUrlPatterns("/*");
filterRegistrationBean.addInitParameter("bizAppEnv", bizAppEnv);
filterRegistrationBean.setOrder(-1);
filterRegistrationBean.setEnabled(true);
return filterRegistrationBean;
}
}
- 自定义Filter类
BizAppFilter
:
public class BizAppFilter extends OncePerRequestFilter {
@Override
protected void doFilterInternal(HttpServletRequest httpServletRequest,
HttpServletResponse httpServletResponse, FilterChain filterChain)
throws ServletException, IOException {
String bizAppEnv = getFilterConfig().getInitParameter("bizAppEnv");
HttpServletRequestWrapper httpServletRequestWrapper = new HttpServletRequestWrapper(httpServletRequest) {
@Override
public String getHeader(String name) {
if (StringUtils.isNotEmpty(name) && name.equalsIgnoreCase(HttpHeaderNames.X_BIZ_APP)) {
if (StringUtils.isNotEmpty(bizAppEnv) && bizAppEnv.equalsIgnoreCase("env-group")) {
String bizApp = super.getHeader(HttpHeaderNames.X_BIZ_APP);
if(StringUtils.isNotEmpty(bizApp)){
StringBuilder resBizApp = new StringBuilder();
int flag = 0;
for (Character c : bizApp.toCharArray()) {
if (c == '|' && flag == 1) {
return resBizApp.toString();
} else if (c == '|') {
flag += 1;
}
resBizApp.append(c);
}
return resBizApp.toString();
}
}
return super.getHeader(name);
} else {
return super.getHeader(name);
}
}
};
filterChain.doFilter(httpServletRequestWrapper, httpServletResponse);
}
}
- 定义Controller:
@RequestMapping(value = "/filter1", method = {RequestMethod.GET})
@ResponseBody
public TeslaBaseResult getAdminApplications(
@RequestHeader(value = "X-Biz-App") String bizApp
) {
// return buildSucceedResult(applicationService.getAdminApplications(userEmpid));
return buildSucceedResult(bizApp);
}
@RequestMapping(value = "/filter2")
@ResponseBody
public TeslaBaseResult testFilter(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse){
String res = httpServletRequest.getHeader("X-Biz-App");
return buildSucceedResult(res);
}
测试:
自定义请求头:X-Biz-App: platform|group|test|111
分别发给filter1和filter2接口,所得:
filter1结果:
{
"code": 200,
"message": "OK",
"data": "platform|group|test|111"
}
filter2结果:
{
"code": 200,
"message": "OK",
"data": "platform|group"
}
可见,通过@RequestHeader
注解获取的值并没有被过滤器截断,而通过httpServletRequest
的getHeader方法却可以正确获取。
分析:Filter不是应该在请求进入spring容器之前生效吗?注解获取header参数的方式又是什么样的,为什么会绕开Filter?