01CharacterEncodingFilter —— 乱码终结者
关键词:UTF-8、forceEncoding、Ordered.HIGHEST_PRECEDENCE
只要出现中文、emoji、阿拉伯文,就用它!
@Bean
public FilterRegistrationBean<CharacterEncodingFilter> characterEncodingFilter() {
CharacterEncodingFilter filter = new CharacterEncodingFilter();
filter.setEncoding("UTF-8"); // ① 指定编码
filter.setForceEncoding(true); // ② 强制覆盖已有编码
FilterRegistrationBean<CharacterEncodingFilter> bean = new FilterRegistrationBean<>(filter);
bean.addUrlPatterns("/*"); // ③ 拦截所有请求
bean.setOrder(Ordered.HIGHEST_PRECEDENCE);// ④ 最先执行,防止其他过滤器捣蛋
return bean;
}
注解:
- setEncoding 解决请求/响应乱码;
- setForceEncoding(true) 覆盖 Tomcat 默认 ISO-8859-1;
- addUrlPatterns(“/*”) 全局生效;
- 最高优先级,保证后续过滤器拿到的就是 UTF-8。
02HiddenHttpMethodFilter —— 把 POST 伪装成 PUT/DELETE
关键词:RESTful、_method、HTML 表单
<form action="/books/7" method="post">
<input type="hidden" name="_method" value="DELETE"/>
<button type="submit">删除图书</button>
</form>
spring.mvc.hiddenmethod.filter.enabled=true # application.yml 一行搞定
注解:
- 表单必须是 POST;
- 隐藏字段 _method 的值就是真实 HTTP 方法;
- Spring MVC 会自动路由到 @DeleteMapping。
03FormContentFilter —— PUT/PATCH 也能玩表单
关键词:application/x-www-form-urlencoded、非 POST 表单
spring.mvc.formcontent.filter.enabled: true # 同样一行配置
场景:老项目前端不会发 application/json,但接口想用 PUT 更新。
@PutMapping("/users/{id}")
public String updateUser(@PathVariable Long id, UserForm form) {
// 表单字段自动封装进 UserForm
userService.update(id, form);
return "redirect:/users";
}
注解:
- 过滤器把 PUT 请求体解析成 Map<String,String[]>;
- Spring 数据绑定无缝衔接。
04RequestContextFilter —— 随时随地拿 Request
关键词:RequestContextHolder、非 Controller 取 IP
@Service
public class ClientInfoService {
public String whoami() {
ServletRequestAttributes attrs = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
HttpServletRequest req = attrs.getRequest();
return String.format("IP: %s, UA: %s",
req.getRemoteAddr(),
req.getHeader("User-Agent"));
}
}
注解:
- 任何地方都能拿到当前线程的 HttpServletRequest;
- 适用于日志、审计、灰度路由。
05CorsFilter —— 跨域通行证
关键词:Access-Control-Allow-Origin、Credentials、预检
@Bean
public CorsFilter corsFilter() {
CorsConfiguration cfg = new CorsConfiguration();
cfg.setAllowCredentials(true); // ① 允许携带 Cookie
cfg.addAllowedOrigin("https://spa.xxx.com"); // ② 白名单域名
cfg.addAllowedHeader("*"); // ③ 任意请求头
cfg.addAllowedMethod("*"); // ④ 任意方法
UrlBasedCorsConfigurationSource src = new UrlBasedCorsConfigurationSource();
src.registerCorsConfiguration("/api/**", cfg);
return new CorsFilter(src);
}
注解:
- 精准控制哪些接口、哪些域名可以跨域;
- 支持 Authorization 头与 Cookie;
- 比 @CrossOrigin 粒度更细,可集中管理。
06ShallowEtagHeaderFilter —— 让 304 飞起来
关键词:ETag、缓存、节省带宽
@Bean
public FilterRegistrationBean<ShallowEtagHeaderFilter> etag() {
FilterRegistrationBean<ShallowEtagHeaderFilter> bean = new FilterRegistrationBean<>();
bean.setFilter(new ShallowEtagHeaderFilter());
bean.addUrlPatterns("/static/*", "/api/report/*");
return bean;
}
第一次 200 + ETag,第二次 304,直接省 80% 流量!
注解:
- 计算响应体 MD5 作为 ETag;
- 客户端带 If-None-Match 对比即可;
- 静态资源、报表接口效果最佳。
07ForwardedHeaderFilter —— 反向代理小棉袄
关键词:X-Forwarded-Proto、Nginx、ELB、HTTPS
@Bean
public FilterRegistrationBean<ForwardedHeaderFilter> forwarded() {
FilterRegistrationBean<ForwardedHeaderFilter> bean = new FilterRegistrationBean<>();
bean.setFilter(new ForwardedHeaderFilter());
bean.setOrder(Ordered.HIGHEST_PRECEDENCE); // 越早越好
return bean;
}
注解:
- 自动重写 request.getScheme()、getServerName();
- 解决 HTTPS 终止在 Nginx 时,重定向变成 http 的尴尬。
08OrderedRequestContextFilter —— 顺序可控的 RequestContext
如果你写了 10+ 个自定义 Filter,谁先谁后就是生命线。
// 默认优先级:REQUEST_WRAPPER_FILTER_MAX_ORDER - 10000
// 想插队?直接实现 Ordered 接口
09ResourceUrlEncodingFilter —— 静态资源“带版本号”
关键词:缓存破坏、内容哈希、Thymeleaf 自动替换
@Configuration
public class WebCfg implements WebMvcConfigurer {
@Bean
public ResourceUrlEncodingFilter resourceUrlEncodingFilter() {
return new ResourceUrlEncodingFilter();
}
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/static/**")
.addResourceLocations("classpath:/static/")
.setCacheControl(CacheControl.maxAge(365, TimeUnit.DAYS))
.resourceChain(true)
.addResolver(new VersionResourceResolver()
.addContentVersionStrategy("/**")); // ① 哈希指纹
}
}
Thymeleaf 模板:
<link rel="stylesheet" th:href="@{/static/css/app.css}" />
<!-- 实际输出:/static/css/app-8a9b2c3.css -->
注解:
- 文件内容变动 → 指纹变化 → 浏览器重新下载;
- 365 天强缓存,更新即发版,用户无感知。