Java 开发:过滤器(Filter)与拦截器(Interceptor)深度解析 + CORS 跨域完整解决方案
在 Java Web 开发(Spring Boot / Spring MVC)中,过滤器(Filter) 、拦截器(Interceptor) 是请求处理流程的两大核心组件,也是面试高频考点;而跨域(CORS) 更是前后端分离项目中必踩、必解决的核心问题。
很多开发者容易混淆过滤器与拦截器的执行时机、适用场景,也常常被跨域报错困扰:No 'Access-Control-Allow-Origin' header、预检请求失败、自定义 header 跨域、Cookie 跨域不携带等。
本文将从底层原理、核心区别、实战代码、执行顺序四个维度,精讲过滤器与拦截器;并提供覆盖所有场景的一站式 CORS 跨域解决方案,包含配置类、注解、过滤器 / 拦截器实现方式,真正做到一次学会、项目直接落地。
一、核心概念
1. 执行顺序
#mermaid-svg-2Bnw60IbemVishG9{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-2Bnw60IbemVishG9 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-2Bnw60IbemVishG9 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-2Bnw60IbemVishG9 .error-icon{fill:#552222;}#mermaid-svg-2Bnw60IbemVishG9 .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-2Bnw60IbemVishG9 .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-2Bnw60IbemVishG9 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-2Bnw60IbemVishG9 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-2Bnw60IbemVishG9 .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-2Bnw60IbemVishG9 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-2Bnw60IbemVishG9 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-2Bnw60IbemVishG9 .marker{fill:#333333;stroke:#333333;}#mermaid-svg-2Bnw60IbemVishG9 .marker.cross{stroke:#333333;}#mermaid-svg-2Bnw60IbemVishG9 svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-2Bnw60IbemVishG9 p{margin:0;}#mermaid-svg-2Bnw60IbemVishG9 .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-2Bnw60IbemVishG9 .cluster-label text{fill:#333;}#mermaid-svg-2Bnw60IbemVishG9 .cluster-label span{color:#333;}#mermaid-svg-2Bnw60IbemVishG9 .cluster-label span p{background-color:transparent;}#mermaid-svg-2Bnw60IbemVishG9 .label text,#mermaid-svg-2Bnw60IbemVishG9 span{fill:#333;color:#333;}#mermaid-svg-2Bnw60IbemVishG9 .node rect,#mermaid-svg-2Bnw60IbemVishG9 .node circle,#mermaid-svg-2Bnw60IbemVishG9 .node ellipse,#mermaid-svg-2Bnw60IbemVishG9 .node polygon,#mermaid-svg-2Bnw60IbemVishG9 .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-2Bnw60IbemVishG9 .rough-node .label text,#mermaid-svg-2Bnw60IbemVishG9 .node .label text,#mermaid-svg-2Bnw60IbemVishG9 .image-shape .label,#mermaid-svg-2Bnw60IbemVishG9 .icon-shape .label{text-anchor:middle;}#mermaid-svg-2Bnw60IbemVishG9 .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-2Bnw60IbemVishG9 .rough-node .label,#mermaid-svg-2Bnw60IbemVishG9 .node .label,#mermaid-svg-2Bnw60IbemVishG9 .image-shape .label,#mermaid-svg-2Bnw60IbemVishG9 .icon-shape .label{text-align:center;}#mermaid-svg-2Bnw60IbemVishG9 .node.clickable{cursor:pointer;}#mermaid-svg-2Bnw60IbemVishG9 .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-2Bnw60IbemVishG9 .arrowheadPath{fill:#333333;}#mermaid-svg-2Bnw60IbemVishG9 .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-2Bnw60IbemVishG9 .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-2Bnw60IbemVishG9 .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-2Bnw60IbemVishG9 .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-2Bnw60IbemVishG9 .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-2Bnw60IbemVishG9 .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-2Bnw60IbemVishG9 .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-2Bnw60IbemVishG9 .cluster text{fill:#333;}#mermaid-svg-2Bnw60IbemVishG9 .cluster span{color:#333;}#mermaid-svg-2Bnw60IbemVishG9 div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-2Bnw60IbemVishG9 .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-2Bnw60IbemVishG9 rect.text{fill:none;stroke-width:0;}#mermaid-svg-2Bnw60IbemVishG9 .icon-shape,#mermaid-svg-2Bnw60IbemVishG9 .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-2Bnw60IbemVishG9 .icon-shape p,#mermaid-svg-2Bnw60IbemVishG9 .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-2Bnw60IbemVishG9 .icon-shape .label rect,#mermaid-svg-2Bnw60IbemVishG9 .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-2Bnw60IbemVishG9 .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-2Bnw60IbemVishG9 .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-2Bnw60IbemVishG9 :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 响应方向
Controller
Interceptor
Servlet
Filter
响应
请求方向
请求
Filter 过滤器
Servlet
Interceptor 拦截器
Controller
2. 本质区别
| 特性 | Filter 过滤器 | Interceptor 拦截器 |
|---|---|---|
| 归属 | Servlet 规范(Tomcat 容器) | Spring MVC 框架 |
| 作用范围 | 所有请求(静态资源、Servlet、Controller) | 只拦截 Spring 管理的请求(Controller) |
| 依赖容器 | 依赖 Tomcat 等 Web 容器 | 依赖 Spring 容器 |
| 能获取的对象 | 只能获取 Request/Response,拿不到 Bean | 能获取 Controller、Method、Spring Bean |
| 执行时机 | 最外层,进入 Spring 之前 | Spring 容器内,Controller 执行前后 |
| 使用场景 | 编码、跨域、限流、请求头过滤、黑白名单 | 日志、权限、参数校验、统一业务处理 |
3. 生命周期
#mermaid-svg-miZ1fx74CqFvpWiw{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-miZ1fx74CqFvpWiw .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-miZ1fx74CqFvpWiw .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-miZ1fx74CqFvpWiw .error-icon{fill:#552222;}#mermaid-svg-miZ1fx74CqFvpWiw .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-miZ1fx74CqFvpWiw .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-miZ1fx74CqFvpWiw .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-miZ1fx74CqFvpWiw .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-miZ1fx74CqFvpWiw .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-miZ1fx74CqFvpWiw .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-miZ1fx74CqFvpWiw .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-miZ1fx74CqFvpWiw .marker{fill:#333333;stroke:#333333;}#mermaid-svg-miZ1fx74CqFvpWiw .marker.cross{stroke:#333333;}#mermaid-svg-miZ1fx74CqFvpWiw svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-miZ1fx74CqFvpWiw p{margin:0;}#mermaid-svg-miZ1fx74CqFvpWiw .edge{stroke-width:3;}#mermaid-svg-miZ1fx74CqFvpWiw .section--1 rect,#mermaid-svg-miZ1fx74CqFvpWiw .section--1 path,#mermaid-svg-miZ1fx74CqFvpWiw .section--1 circle,#mermaid-svg-miZ1fx74CqFvpWiw .section--1 path{fill:hsl(240, 100%, 76.2745098039%);}#mermaid-svg-miZ1fx74CqFvpWiw .section--1 text{fill:#ffffff;}#mermaid-svg-miZ1fx74CqFvpWiw .node-icon--1{font-size:40px;color:#ffffff;}#mermaid-svg-miZ1fx74CqFvpWiw .section-edge--1{stroke:hsl(240, 100%, 76.2745098039%);}#mermaid-svg-miZ1fx74CqFvpWiw .edge-depth--1{stroke-width:17;}#mermaid-svg-miZ1fx74CqFvpWiw .section--1 line{stroke:hsl(60, 100%, 86.2745098039%);stroke-width:3;}#mermaid-svg-miZ1fx74CqFvpWiw .lineWrapper line{stroke:#ffffff;}#mermaid-svg-miZ1fx74CqFvpWiw .disabled,#mermaid-svg-miZ1fx74CqFvpWiw .disabled circle,#mermaid-svg-miZ1fx74CqFvpWiw .disabled text{fill:lightgray;}#mermaid-svg-miZ1fx74CqFvpWiw .disabled text{fill:#efefef;}#mermaid-svg-miZ1fx74CqFvpWiw .section-0 rect,#mermaid-svg-miZ1fx74CqFvpWiw .section-0 path,#mermaid-svg-miZ1fx74CqFvpWiw .section-0 circle,#mermaid-svg-miZ1fx74CqFvpWiw .section-0 path{fill:hsl(60, 100%, 73.5294117647%);}#mermaid-svg-miZ1fx74CqFvpWiw .section-0 text{fill:black;}#mermaid-svg-miZ1fx74CqFvpWiw .node-icon-0{font-size:40px;color:black;}#mermaid-svg-miZ1fx74CqFvpWiw .section-edge-0{stroke:hsl(60, 100%, 73.5294117647%);}#mermaid-svg-miZ1fx74CqFvpWiw .edge-depth-0{stroke-width:14;}#mermaid-svg-miZ1fx74CqFvpWiw .section-0 line{stroke:hsl(240, 100%, 83.5294117647%);stroke-width:3;}#mermaid-svg-miZ1fx74CqFvpWiw .lineWrapper line{stroke:black;}#mermaid-svg-miZ1fx74CqFvpWiw .disabled,#mermaid-svg-miZ1fx74CqFvpWiw .disabled circle,#mermaid-svg-miZ1fx74CqFvpWiw .disabled text{fill:lightgray;}#mermaid-svg-miZ1fx74CqFvpWiw .disabled text{fill:#efefef;}#mermaid-svg-miZ1fx74CqFvpWiw .section-1 rect,#mermaid-svg-miZ1fx74CqFvpWiw .section-1 path,#mermaid-svg-miZ1fx74CqFvpWiw .section-1 circle,#mermaid-svg-miZ1fx74CqFvpWiw .section-1 path{fill:hsl(80, 100%, 76.2745098039%);}#mermaid-svg-miZ1fx74CqFvpWiw .section-1 text{fill:black;}#mermaid-svg-miZ1fx74CqFvpWiw .node-icon-1{font-size:40px;color:black;}#mermaid-svg-miZ1fx74CqFvpWiw .section-edge-1{stroke:hsl(80, 100%, 76.2745098039%);}#mermaid-svg-miZ1fx74CqFvpWiw .edge-depth-1{stroke-width:11;}#mermaid-svg-miZ1fx74CqFvpWiw .section-1 line{stroke:hsl(260, 100%, 86.2745098039%);stroke-width:3;}#mermaid-svg-miZ1fx74CqFvpWiw .lineWrapper line{stroke:black;}#mermaid-svg-miZ1fx74CqFvpWiw .disabled,#mermaid-svg-miZ1fx74CqFvpWiw .disabled circle,#mermaid-svg-miZ1fx74CqFvpWiw .disabled text{fill:lightgray;}#mermaid-svg-miZ1fx74CqFvpWiw .disabled text{fill:#efefef;}#mermaid-svg-miZ1fx74CqFvpWiw .section-2 rect,#mermaid-svg-miZ1fx74CqFvpWiw .section-2 path,#mermaid-svg-miZ1fx74CqFvpWiw .section-2 circle,#mermaid-svg-miZ1fx74CqFvpWiw .section-2 path{fill:hsl(270, 100%, 76.2745098039%);}#mermaid-svg-miZ1fx74CqFvpWiw .section-2 text{fill:#ffffff;}#mermaid-svg-miZ1fx74CqFvpWiw .node-icon-2{font-size:40px;color:#ffffff;}#mermaid-svg-miZ1fx74CqFvpWiw .section-edge-2{stroke:hsl(270, 100%, 76.2745098039%);}#mermaid-svg-miZ1fx74CqFvpWiw .edge-depth-2{stroke-width:8;}#mermaid-svg-miZ1fx74CqFvpWiw .section-2 line{stroke:hsl(90, 100%, 86.2745098039%);stroke-width:3;}#mermaid-svg-miZ1fx74CqFvpWiw .lineWrapper line{stroke:#ffffff;}#mermaid-svg-miZ1fx74CqFvpWiw .disabled,#mermaid-svg-miZ1fx74CqFvpWiw .disabled circle,#mermaid-svg-miZ1fx74CqFvpWiw .disabled text{fill:lightgray;}#mermaid-svg-miZ1fx74CqFvpWiw .disabled text{fill:#efefef;}#mermaid-svg-miZ1fx74CqFvpWiw .section-3 rect,#mermaid-svg-miZ1fx74CqFvpWiw .section-3 path,#mermaid-svg-miZ1fx74CqFvpWiw .section-3 circle,#mermaid-svg-miZ1fx74CqFvpWiw .section-3 path{fill:hsl(300, 100%, 76.2745098039%);}#mermaid-svg-miZ1fx74CqFvpWiw .section-3 text{fill:black;}#mermaid-svg-miZ1fx74CqFvpWiw .node-icon-3{font-size:40px;color:black;}#mermaid-svg-miZ1fx74CqFvpWiw .section-edge-3{stroke:hsl(300, 100%, 76.2745098039%);}#mermaid-svg-miZ1fx74CqFvpWiw .edge-depth-3{stroke-width:5;}#mermaid-svg-miZ1fx74CqFvpWiw .section-3 line{stroke:hsl(120, 100%, 86.2745098039%);stroke-width:3;}#mermaid-svg-miZ1fx74CqFvpWiw .lineWrapper line{stroke:black;}#mermaid-svg-miZ1fx74CqFvpWiw .disabled,#mermaid-svg-miZ1fx74CqFvpWiw .disabled circle,#mermaid-svg-miZ1fx74CqFvpWiw .disabled text{fill:lightgray;}#mermaid-svg-miZ1fx74CqFvpWiw .disabled text{fill:#efefef;}#mermaid-svg-miZ1fx74CqFvpWiw .section-4 rect,#mermaid-svg-miZ1fx74CqFvpWiw .section-4 path,#mermaid-svg-miZ1fx74CqFvpWiw .section-4 circle,#mermaid-svg-miZ1fx74CqFvpWiw .section-4 path{fill:hsl(330, 100%, 76.2745098039%);}#mermaid-svg-miZ1fx74CqFvpWiw .section-4 text{fill:black;}#mermaid-svg-miZ1fx74CqFvpWiw .node-icon-4{font-size:40px;color:black;}#mermaid-svg-miZ1fx74CqFvpWiw .section-edge-4{stroke:hsl(330, 100%, 76.2745098039%);}#mermaid-svg-miZ1fx74CqFvpWiw .edge-depth-4{stroke-width:2;}#mermaid-svg-miZ1fx74CqFvpWiw .section-4 line{stroke:hsl(150, 100%, 86.2745098039%);stroke-width:3;}#mermaid-svg-miZ1fx74CqFvpWiw .lineWrapper line{stroke:black;}#mermaid-svg-miZ1fx74CqFvpWiw .disabled,#mermaid-svg-miZ1fx74CqFvpWiw .disabled circle,#mermaid-svg-miZ1fx74CqFvpWiw .disabled text{fill:lightgray;}#mermaid-svg-miZ1fx74CqFvpWiw .disabled text{fill:#efefef;}#mermaid-svg-miZ1fx74CqFvpWiw .section-5 rect,#mermaid-svg-miZ1fx74CqFvpWiw .section-5 path,#mermaid-svg-miZ1fx74CqFvpWiw .section-5 circle,#mermaid-svg-miZ1fx74CqFvpWiw .section-5 path{fill:hsl(0, 100%, 76.2745098039%);}#mermaid-svg-miZ1fx74CqFvpWiw .section-5 text{fill:black;}#mermaid-svg-miZ1fx74CqFvpWiw .node-icon-5{font-size:40px;color:black;}#mermaid-svg-miZ1fx74CqFvpWiw .section-edge-5{stroke:hsl(0, 100%, 76.2745098039%);}#mermaid-svg-miZ1fx74CqFvpWiw .edge-depth-5{stroke-width:-1;}#mermaid-svg-miZ1fx74CqFvpWiw .section-5 line{stroke:hsl(180, 100%, 86.2745098039%);stroke-width:3;}#mermaid-svg-miZ1fx74CqFvpWiw .lineWrapper line{stroke:black;}#mermaid-svg-miZ1fx74CqFvpWiw .disabled,#mermaid-svg-miZ1fx74CqFvpWiw .disabled circle,#mermaid-svg-miZ1fx74CqFvpWiw .disabled text{fill:lightgray;}#mermaid-svg-miZ1fx74CqFvpWiw .disabled text{fill:#efefef;}#mermaid-svg-miZ1fx74CqFvpWiw .section-6 rect,#mermaid-svg-miZ1fx74CqFvpWiw .section-6 path,#mermaid-svg-miZ1fx74CqFvpWiw .section-6 circle,#mermaid-svg-miZ1fx74CqFvpWiw .section-6 path{fill:hsl(30, 100%, 76.2745098039%);}#mermaid-svg-miZ1fx74CqFvpWiw .section-6 text{fill:black;}#mermaid-svg-miZ1fx74CqFvpWiw .node-icon-6{font-size:40px;color:black;}#mermaid-svg-miZ1fx74CqFvpWiw .section-edge-6{stroke:hsl(30, 100%, 76.2745098039%);}#mermaid-svg-miZ1fx74CqFvpWiw .edge-depth-6{stroke-width:-4;}#mermaid-svg-miZ1fx74CqFvpWiw .section-6 line{stroke:hsl(210, 100%, 86.2745098039%);stroke-width:3;}#mermaid-svg-miZ1fx74CqFvpWiw .lineWrapper line{stroke:black;}#mermaid-svg-miZ1fx74CqFvpWiw .disabled,#mermaid-svg-miZ1fx74CqFvpWiw .disabled circle,#mermaid-svg-miZ1fx74CqFvpWiw .disabled text{fill:lightgray;}#mermaid-svg-miZ1fx74CqFvpWiw .disabled text{fill:#efefef;}#mermaid-svg-miZ1fx74CqFvpWiw .section-7 rect,#mermaid-svg-miZ1fx74CqFvpWiw .section-7 path,#mermaid-svg-miZ1fx74CqFvpWiw .section-7 circle,#mermaid-svg-miZ1fx74CqFvpWiw .section-7 path{fill:hsl(90, 100%, 76.2745098039%);}#mermaid-svg-miZ1fx74CqFvpWiw .section-7 text{fill:black;}#mermaid-svg-miZ1fx74CqFvpWiw .node-icon-7{font-size:40px;color:black;}#mermaid-svg-miZ1fx74CqFvpWiw .section-edge-7{stroke:hsl(90, 100%, 76.2745098039%);}#mermaid-svg-miZ1fx74CqFvpWiw .edge-depth-7{stroke-width:-7;}#mermaid-svg-miZ1fx74CqFvpWiw .section-7 line{stroke:hsl(270, 100%, 86.2745098039%);stroke-width:3;}#mermaid-svg-miZ1fx74CqFvpWiw .lineWrapper line{stroke:black;}#mermaid-svg-miZ1fx74CqFvpWiw .disabled,#mermaid-svg-miZ1fx74CqFvpWiw .disabled circle,#mermaid-svg-miZ1fx74CqFvpWiw .disabled text{fill:lightgray;}#mermaid-svg-miZ1fx74CqFvpWiw .disabled text{fill:#efefef;}#mermaid-svg-miZ1fx74CqFvpWiw .section-8 rect,#mermaid-svg-miZ1fx74CqFvpWiw .section-8 path,#mermaid-svg-miZ1fx74CqFvpWiw .section-8 circle,#mermaid-svg-miZ1fx74CqFvpWiw .section-8 path{fill:hsl(150, 100%, 76.2745098039%);}#mermaid-svg-miZ1fx74CqFvpWiw .section-8 text{fill:black;}#mermaid-svg-miZ1fx74CqFvpWiw .node-icon-8{font-size:40px;color:black;}#mermaid-svg-miZ1fx74CqFvpWiw .section-edge-8{stroke:hsl(150, 100%, 76.2745098039%);}#mermaid-svg-miZ1fx74CqFvpWiw .edge-depth-8{stroke-width:-10;}#mermaid-svg-miZ1fx74CqFvpWiw .section-8 line{stroke:hsl(330, 100%, 86.2745098039%);stroke-width:3;}#mermaid-svg-miZ1fx74CqFvpWiw .lineWrapper line{stroke:black;}#mermaid-svg-miZ1fx74CqFvpWiw .disabled,#mermaid-svg-miZ1fx74CqFvpWiw .disabled circle,#mermaid-svg-miZ1fx74CqFvpWiw .disabled text{fill:lightgray;}#mermaid-svg-miZ1fx74CqFvpWiw .disabled text{fill:#efefef;}#mermaid-svg-miZ1fx74CqFvpWiw .section-9 rect,#mermaid-svg-miZ1fx74CqFvpWiw .section-9 path,#mermaid-svg-miZ1fx74CqFvpWiw .section-9 circle,#mermaid-svg-miZ1fx74CqFvpWiw .section-9 path{fill:hsl(180, 100%, 76.2745098039%);}#mermaid-svg-miZ1fx74CqFvpWiw .section-9 text{fill:black;}#mermaid-svg-miZ1fx74CqFvpWiw .node-icon-9{font-size:40px;color:black;}#mermaid-svg-miZ1fx74CqFvpWiw .section-edge-9{stroke:hsl(180, 100%, 76.2745098039%);}#mermaid-svg-miZ1fx74CqFvpWiw .edge-depth-9{stroke-width:-13;}#mermaid-svg-miZ1fx74CqFvpWiw .section-9 line{stroke:hsl(0, 100%, 86.2745098039%);stroke-width:3;}#mermaid-svg-miZ1fx74CqFvpWiw .lineWrapper line{stroke:black;}#mermaid-svg-miZ1fx74CqFvpWiw .disabled,#mermaid-svg-miZ1fx74CqFvpWiw .disabled circle,#mermaid-svg-miZ1fx74CqFvpWiw .disabled text{fill:lightgray;}#mermaid-svg-miZ1fx74CqFvpWiw .disabled text{fill:#efefef;}#mermaid-svg-miZ1fx74CqFvpWiw .section-10 rect,#mermaid-svg-miZ1fx74CqFvpWiw .section-10 path,#mermaid-svg-miZ1fx74CqFvpWiw .section-10 circle,#mermaid-svg-miZ1fx74CqFvpWiw .section-10 path{fill:hsl(210, 100%, 76.2745098039%);}#mermaid-svg-miZ1fx74CqFvpWiw .section-10 text{fill:black;}#mermaid-svg-miZ1fx74CqFvpWiw .node-icon-10{font-size:40px;color:black;}#mermaid-svg-miZ1fx74CqFvpWiw .section-edge-10{stroke:hsl(210, 100%, 76.2745098039%);}#mermaid-svg-miZ1fx74CqFvpWiw .edge-depth-10{stroke-width:-16;}#mermaid-svg-miZ1fx74CqFvpWiw .section-10 line{stroke:hsl(30, 100%, 86.2745098039%);stroke-width:3;}#mermaid-svg-miZ1fx74CqFvpWiw .lineWrapper line{stroke:black;}#mermaid-svg-miZ1fx74CqFvpWiw .disabled,#mermaid-svg-miZ1fx74CqFvpWiw .disabled circle,#mermaid-svg-miZ1fx74CqFvpWiw .disabled text{fill:lightgray;}#mermaid-svg-miZ1fx74CqFvpWiw .disabled text{fill:#efefef;}#mermaid-svg-miZ1fx74CqFvpWiw .section-root rect,#mermaid-svg-miZ1fx74CqFvpWiw .section-root path,#mermaid-svg-miZ1fx74CqFvpWiw .section-root circle{fill:hsl(240, 100%, 46.2745098039%);}#mermaid-svg-miZ1fx74CqFvpWiw .section-root text{fill:#ffffff;}#mermaid-svg-miZ1fx74CqFvpWiw .icon-container{height:100%;display:flex;justify-content:center;align-items:center;}#mermaid-svg-miZ1fx74CqFvpWiw .edge{fill:none;}#mermaid-svg-miZ1fx74CqFvpWiw .eventWrapper{filter:brightness(120%);}#mermaid-svg-miZ1fx74CqFvpWiw :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} Filter 生命周期 容器启动 init() 执行一次 每次请求 doFilter() 执行 容器关闭 destroy() 执行一次 Interceptor 生命周期 Spring 启动 创建 Bean 实例 匹配请求 preHandlepostHandleafterCompletion Spring 关闭 销毁 Bean Filter vs Interceptor 生命周期对比
二、Filter 过滤器
1. 作用
- 统一编码处理
- CORS 跨域(最常用)
- 黑白名单 IP 过滤
- 请求头、响应头统一处理
- 静态资源访问控制
2. 三种注册方式对比
#mermaid-svg-22M6nEPDtUNlC6Ny{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-22M6nEPDtUNlC6Ny .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-22M6nEPDtUNlC6Ny .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-22M6nEPDtUNlC6Ny .error-icon{fill:#552222;}#mermaid-svg-22M6nEPDtUNlC6Ny .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-22M6nEPDtUNlC6Ny .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-22M6nEPDtUNlC6Ny .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-22M6nEPDtUNlC6Ny .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-22M6nEPDtUNlC6Ny .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-22M6nEPDtUNlC6Ny .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-22M6nEPDtUNlC6Ny .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-22M6nEPDtUNlC6Ny .marker{fill:#333333;stroke:#333333;}#mermaid-svg-22M6nEPDtUNlC6Ny .marker.cross{stroke:#333333;}#mermaid-svg-22M6nEPDtUNlC6Ny svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-22M6nEPDtUNlC6Ny p{margin:0;}#mermaid-svg-22M6nEPDtUNlC6Ny .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-22M6nEPDtUNlC6Ny .cluster-label text{fill:#333;}#mermaid-svg-22M6nEPDtUNlC6Ny .cluster-label span{color:#333;}#mermaid-svg-22M6nEPDtUNlC6Ny .cluster-label span p{background-color:transparent;}#mermaid-svg-22M6nEPDtUNlC6Ny .label text,#mermaid-svg-22M6nEPDtUNlC6Ny span{fill:#333;color:#333;}#mermaid-svg-22M6nEPDtUNlC6Ny .node rect,#mermaid-svg-22M6nEPDtUNlC6Ny .node circle,#mermaid-svg-22M6nEPDtUNlC6Ny .node ellipse,#mermaid-svg-22M6nEPDtUNlC6Ny .node polygon,#mermaid-svg-22M6nEPDtUNlC6Ny .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-22M6nEPDtUNlC6Ny .rough-node .label text,#mermaid-svg-22M6nEPDtUNlC6Ny .node .label text,#mermaid-svg-22M6nEPDtUNlC6Ny .image-shape .label,#mermaid-svg-22M6nEPDtUNlC6Ny .icon-shape .label{text-anchor:middle;}#mermaid-svg-22M6nEPDtUNlC6Ny .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-22M6nEPDtUNlC6Ny .rough-node .label,#mermaid-svg-22M6nEPDtUNlC6Ny .node .label,#mermaid-svg-22M6nEPDtUNlC6Ny .image-shape .label,#mermaid-svg-22M6nEPDtUNlC6Ny .icon-shape .label{text-align:center;}#mermaid-svg-22M6nEPDtUNlC6Ny .node.clickable{cursor:pointer;}#mermaid-svg-22M6nEPDtUNlC6Ny .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-22M6nEPDtUNlC6Ny .arrowheadPath{fill:#333333;}#mermaid-svg-22M6nEPDtUNlC6Ny .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-22M6nEPDtUNlC6Ny .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-22M6nEPDtUNlC6Ny .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-22M6nEPDtUNlC6Ny .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-22M6nEPDtUNlC6Ny .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-22M6nEPDtUNlC6Ny .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-22M6nEPDtUNlC6Ny .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-22M6nEPDtUNlC6Ny .cluster text{fill:#333;}#mermaid-svg-22M6nEPDtUNlC6Ny .cluster span{color:#333;}#mermaid-svg-22M6nEPDtUNlC6Ny div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-22M6nEPDtUNlC6Ny .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-22M6nEPDtUNlC6Ny rect.text{fill:none;stroke-width:0;}#mermaid-svg-22M6nEPDtUNlC6Ny .icon-shape,#mermaid-svg-22M6nEPDtUNlC6Ny .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-22M6nEPDtUNlC6Ny .icon-shape p,#mermaid-svg-22M6nEPDtUNlC6Ny .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-22M6nEPDtUNlC6Ny .icon-shape .label rect,#mermaid-svg-22M6nEPDtUNlC6Ny .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-22M6nEPDtUNlC6Ny .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-22M6nEPDtUNlC6Ny .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-22M6nEPDtUNlC6Ny :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} Filter 注册方式
方式一:JavaConfig(推荐)
方式二:@Component(极简)
方式三:web.xml(过时)
可精确控制 URL 模式和顺序
Spring Boot 自动注册
仅兼容老旧项目
(1)自定义 Filter
java
public class MyFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) {
}
@Override
public void doFilter(ServletRequest request,
ServletResponse response,
FilterChain chain) {
try {
System.out.println("Filter 请求前执行");
chain.doFilter(request, response);
System.out.println("Filter 响应后执行");
} catch (Exception e) {
e.printStackTrace();
}
}
@Override
public void destroy() {
}
}
(2)注册 Filter(JavaConfig 方式,推荐)
java
@Configuration
public class FilterConfig {
@Bean
public FilterRegistrationBean<MyFilter> myFilter() {
FilterRegistrationBean<MyFilter> bean = new FilterRegistrationBean<>();
bean.setFilter(new MyFilter());
bean.addUrlPatterns("/*");
bean.setOrder(1);
return bean;
}
}
3. Spring Boot 使用(极简)
java
@Component
@Order(1)
public class MyFilter implements Filter {
// 直接加 @Component 自动注册
}
4. Spring Cloud Gateway(特殊)
Gateway 不使用 Servlet,没有传统 Filter,用 Gateway Filter / GlobalFilter 替代(功能更强)。
#mermaid-svg-xGqT3PiX3HeiuCRL{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-xGqT3PiX3HeiuCRL .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-xGqT3PiX3HeiuCRL .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-xGqT3PiX3HeiuCRL .error-icon{fill:#552222;}#mermaid-svg-xGqT3PiX3HeiuCRL .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-xGqT3PiX3HeiuCRL .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-xGqT3PiX3HeiuCRL .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-xGqT3PiX3HeiuCRL .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-xGqT3PiX3HeiuCRL .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-xGqT3PiX3HeiuCRL .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-xGqT3PiX3HeiuCRL .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-xGqT3PiX3HeiuCRL .marker{fill:#333333;stroke:#333333;}#mermaid-svg-xGqT3PiX3HeiuCRL .marker.cross{stroke:#333333;}#mermaid-svg-xGqT3PiX3HeiuCRL svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-xGqT3PiX3HeiuCRL p{margin:0;}#mermaid-svg-xGqT3PiX3HeiuCRL .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-xGqT3PiX3HeiuCRL .cluster-label text{fill:#333;}#mermaid-svg-xGqT3PiX3HeiuCRL .cluster-label span{color:#333;}#mermaid-svg-xGqT3PiX3HeiuCRL .cluster-label span p{background-color:transparent;}#mermaid-svg-xGqT3PiX3HeiuCRL .label text,#mermaid-svg-xGqT3PiX3HeiuCRL span{fill:#333;color:#333;}#mermaid-svg-xGqT3PiX3HeiuCRL .node rect,#mermaid-svg-xGqT3PiX3HeiuCRL .node circle,#mermaid-svg-xGqT3PiX3HeiuCRL .node ellipse,#mermaid-svg-xGqT3PiX3HeiuCRL .node polygon,#mermaid-svg-xGqT3PiX3HeiuCRL .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-xGqT3PiX3HeiuCRL .rough-node .label text,#mermaid-svg-xGqT3PiX3HeiuCRL .node .label text,#mermaid-svg-xGqT3PiX3HeiuCRL .image-shape .label,#mermaid-svg-xGqT3PiX3HeiuCRL .icon-shape .label{text-anchor:middle;}#mermaid-svg-xGqT3PiX3HeiuCRL .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-xGqT3PiX3HeiuCRL .rough-node .label,#mermaid-svg-xGqT3PiX3HeiuCRL .node .label,#mermaid-svg-xGqT3PiX3HeiuCRL .image-shape .label,#mermaid-svg-xGqT3PiX3HeiuCRL .icon-shape .label{text-align:center;}#mermaid-svg-xGqT3PiX3HeiuCRL .node.clickable{cursor:pointer;}#mermaid-svg-xGqT3PiX3HeiuCRL .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-xGqT3PiX3HeiuCRL .arrowheadPath{fill:#333333;}#mermaid-svg-xGqT3PiX3HeiuCRL .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-xGqT3PiX3HeiuCRL .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-xGqT3PiX3HeiuCRL .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-xGqT3PiX3HeiuCRL .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-xGqT3PiX3HeiuCRL .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-xGqT3PiX3HeiuCRL .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-xGqT3PiX3HeiuCRL .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-xGqT3PiX3HeiuCRL .cluster text{fill:#333;}#mermaid-svg-xGqT3PiX3HeiuCRL .cluster span{color:#333;}#mermaid-svg-xGqT3PiX3HeiuCRL div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-xGqT3PiX3HeiuCRL .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-xGqT3PiX3HeiuCRL rect.text{fill:none;stroke-width:0;}#mermaid-svg-xGqT3PiX3HeiuCRL .icon-shape,#mermaid-svg-xGqT3PiX3HeiuCRL .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-xGqT3PiX3HeiuCRL .icon-shape p,#mermaid-svg-xGqT3PiX3HeiuCRL .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-xGqT3PiX3HeiuCRL .icon-shape .label rect,#mermaid-svg-xGqT3PiX3HeiuCRL .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-xGqT3PiX3HeiuCRL .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-xGqT3PiX3HeiuCRL .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-xGqT3PiX3HeiuCRL :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} Spring Cloud Gateway
请求
Gateway Filter 链
GlobalFilter
下游服务
传统单体
请求
Filter 链
Controller
三、Interceptor 拦截器
1. 作用
- Controller 接口日志
- 登录状态校验
- 权限校验
- 统一参数封装
- 接口耗时统计
2. 核心方法流程图
#mermaid-svg-EyP3XvgErrhtvACc{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-EyP3XvgErrhtvACc .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-EyP3XvgErrhtvACc .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-EyP3XvgErrhtvACc .error-icon{fill:#552222;}#mermaid-svg-EyP3XvgErrhtvACc .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-EyP3XvgErrhtvACc .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-EyP3XvgErrhtvACc .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-EyP3XvgErrhtvACc .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-EyP3XvgErrhtvACc .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-EyP3XvgErrhtvACc .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-EyP3XvgErrhtvACc .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-EyP3XvgErrhtvACc .marker{fill:#333333;stroke:#333333;}#mermaid-svg-EyP3XvgErrhtvACc .marker.cross{stroke:#333333;}#mermaid-svg-EyP3XvgErrhtvACc svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-EyP3XvgErrhtvACc p{margin:0;}#mermaid-svg-EyP3XvgErrhtvACc .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-EyP3XvgErrhtvACc .cluster-label text{fill:#333;}#mermaid-svg-EyP3XvgErrhtvACc .cluster-label span{color:#333;}#mermaid-svg-EyP3XvgErrhtvACc .cluster-label span p{background-color:transparent;}#mermaid-svg-EyP3XvgErrhtvACc .label text,#mermaid-svg-EyP3XvgErrhtvACc span{fill:#333;color:#333;}#mermaid-svg-EyP3XvgErrhtvACc .node rect,#mermaid-svg-EyP3XvgErrhtvACc .node circle,#mermaid-svg-EyP3XvgErrhtvACc .node ellipse,#mermaid-svg-EyP3XvgErrhtvACc .node polygon,#mermaid-svg-EyP3XvgErrhtvACc .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-EyP3XvgErrhtvACc .rough-node .label text,#mermaid-svg-EyP3XvgErrhtvACc .node .label text,#mermaid-svg-EyP3XvgErrhtvACc .image-shape .label,#mermaid-svg-EyP3XvgErrhtvACc .icon-shape .label{text-anchor:middle;}#mermaid-svg-EyP3XvgErrhtvACc .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-EyP3XvgErrhtvACc .rough-node .label,#mermaid-svg-EyP3XvgErrhtvACc .node .label,#mermaid-svg-EyP3XvgErrhtvACc .image-shape .label,#mermaid-svg-EyP3XvgErrhtvACc .icon-shape .label{text-align:center;}#mermaid-svg-EyP3XvgErrhtvACc .node.clickable{cursor:pointer;}#mermaid-svg-EyP3XvgErrhtvACc .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-EyP3XvgErrhtvACc .arrowheadPath{fill:#333333;}#mermaid-svg-EyP3XvgErrhtvACc .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-EyP3XvgErrhtvACc .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-EyP3XvgErrhtvACc .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-EyP3XvgErrhtvACc .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-EyP3XvgErrhtvACc .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-EyP3XvgErrhtvACc .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-EyP3XvgErrhtvACc .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-EyP3XvgErrhtvACc .cluster text{fill:#333;}#mermaid-svg-EyP3XvgErrhtvACc .cluster span{color:#333;}#mermaid-svg-EyP3XvgErrhtvACc div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-EyP3XvgErrhtvACc .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-EyP3XvgErrhtvACc rect.text{fill:none;stroke-width:0;}#mermaid-svg-EyP3XvgErrhtvACc .icon-shape,#mermaid-svg-EyP3XvgErrhtvACc .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-EyP3XvgErrhtvACc .icon-shape p,#mermaid-svg-EyP3XvgErrhtvACc .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-EyP3XvgErrhtvACc .icon-shape .label rect,#mermaid-svg-EyP3XvgErrhtvACc .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-EyP3XvgErrhtvACc .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-EyP3XvgErrhtvACc .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-EyP3XvgErrhtvACc :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} true 放行
false 拦截
请求进入
preHandle
Controller 执行前
返回 true?
执行 Controller
请求终止
postHandle
Controller 执行后
afterCompletion
请求完全结束后
响应返回
java
// 1. 请求进入 Controller 之前执行
preHandle() // 返回 true 放行,false 拦截
// 2. Controller 执行完毕,视图渲染之前执行
postHandle()
// 3. 整个请求完全结束后执行(最终清理)
afterCompletion()
3. Spring MVC / Boot 通用实现
(1)自定义拦截器
java
@Component
public class MyInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request,
HttpServletResponse response,
Object handler) {
System.out.println("Controller 执行前");
return true;
}
@Override
public void postHandle(HttpServletRequest request,
HttpServletResponse response,
Object handler,
ModelAndView modelAndView) {
System.out.println("Controller 执行后");
}
@Override
public void afterCompletion(HttpServletRequest request,
HttpServletResponse response,
Object handler,
Exception ex) {
System.out.println("请求完成");
}
}
(2)注册拦截器
java
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Autowired
private MyInterceptor myInterceptor;
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(myInterceptor)
.addPathPatterns("/**")
.excludePathPatterns("/login");
}
}
四、Filter 与 Interceptor 详细对比
1. 基础定位:容器级 vs 框架级
#mermaid-svg-TlRtcIxC1c34AABn{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-TlRtcIxC1c34AABn .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-TlRtcIxC1c34AABn .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-TlRtcIxC1c34AABn .error-icon{fill:#552222;}#mermaid-svg-TlRtcIxC1c34AABn .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-TlRtcIxC1c34AABn .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-TlRtcIxC1c34AABn .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-TlRtcIxC1c34AABn .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-TlRtcIxC1c34AABn .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-TlRtcIxC1c34AABn .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-TlRtcIxC1c34AABn .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-TlRtcIxC1c34AABn .marker{fill:#333333;stroke:#333333;}#mermaid-svg-TlRtcIxC1c34AABn .marker.cross{stroke:#333333;}#mermaid-svg-TlRtcIxC1c34AABn svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-TlRtcIxC1c34AABn p{margin:0;}#mermaid-svg-TlRtcIxC1c34AABn .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-TlRtcIxC1c34AABn .cluster-label text{fill:#333;}#mermaid-svg-TlRtcIxC1c34AABn .cluster-label span{color:#333;}#mermaid-svg-TlRtcIxC1c34AABn .cluster-label span p{background-color:transparent;}#mermaid-svg-TlRtcIxC1c34AABn .label text,#mermaid-svg-TlRtcIxC1c34AABn span{fill:#333;color:#333;}#mermaid-svg-TlRtcIxC1c34AABn .node rect,#mermaid-svg-TlRtcIxC1c34AABn .node circle,#mermaid-svg-TlRtcIxC1c34AABn .node ellipse,#mermaid-svg-TlRtcIxC1c34AABn .node polygon,#mermaid-svg-TlRtcIxC1c34AABn .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-TlRtcIxC1c34AABn .rough-node .label text,#mermaid-svg-TlRtcIxC1c34AABn .node .label text,#mermaid-svg-TlRtcIxC1c34AABn .image-shape .label,#mermaid-svg-TlRtcIxC1c34AABn .icon-shape .label{text-anchor:middle;}#mermaid-svg-TlRtcIxC1c34AABn .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-TlRtcIxC1c34AABn .rough-node .label,#mermaid-svg-TlRtcIxC1c34AABn .node .label,#mermaid-svg-TlRtcIxC1c34AABn .image-shape .label,#mermaid-svg-TlRtcIxC1c34AABn .icon-shape .label{text-align:center;}#mermaid-svg-TlRtcIxC1c34AABn .node.clickable{cursor:pointer;}#mermaid-svg-TlRtcIxC1c34AABn .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-TlRtcIxC1c34AABn .arrowheadPath{fill:#333333;}#mermaid-svg-TlRtcIxC1c34AABn .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-TlRtcIxC1c34AABn .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-TlRtcIxC1c34AABn .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-TlRtcIxC1c34AABn .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-TlRtcIxC1c34AABn .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-TlRtcIxC1c34AABn .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-TlRtcIxC1c34AABn .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-TlRtcIxC1c34AABn .cluster text{fill:#333;}#mermaid-svg-TlRtcIxC1c34AABn .cluster span{color:#333;}#mermaid-svg-TlRtcIxC1c34AABn div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-TlRtcIxC1c34AABn .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-TlRtcIxC1c34AABn rect.text{fill:none;stroke-width:0;}#mermaid-svg-TlRtcIxC1c34AABn .icon-shape,#mermaid-svg-TlRtcIxC1c34AABn .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-TlRtcIxC1c34AABn .icon-shape p,#mermaid-svg-TlRtcIxC1c34AABn .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-TlRtcIxC1c34AABn .icon-shape .label rect,#mermaid-svg-TlRtcIxC1c34AABn .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-TlRtcIxC1c34AABn .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-TlRtcIxC1c34AABn .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-TlRtcIxC1c34AABn :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} Spring 框架层
Web 容器层
Filter 过滤器
归属:Servlet 规范
加载:容器启动时 init
范围:全部请求
Interceptor 拦截器
归属:Spring MVC
加载:IoC 初始化时创建
范围:仅 Controller
请求
Controller
- Filter:Java Servlet 标准规范,属于 Web 容器原生组件,仅依赖 Servlet API
- Interceptor:Spring MVC 自定义组件,仅 Spring 体系生效,强依赖 Spring
Filter 是容器 管的,管所有 请求;
Interceptor 是 Spring 管的,只管 Spring MVC 处理的请求。
2. 拦截范围:所有请求 vs 仅 Controller 请求
#mermaid-svg-0DDPrE7ZienKBQkH{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-0DDPrE7ZienKBQkH .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-0DDPrE7ZienKBQkH .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-0DDPrE7ZienKBQkH .error-icon{fill:#552222;}#mermaid-svg-0DDPrE7ZienKBQkH .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-0DDPrE7ZienKBQkH .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-0DDPrE7ZienKBQkH .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-0DDPrE7ZienKBQkH .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-0DDPrE7ZienKBQkH .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-0DDPrE7ZienKBQkH .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-0DDPrE7ZienKBQkH .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-0DDPrE7ZienKBQkH .marker{fill:#333333;stroke:#333333;}#mermaid-svg-0DDPrE7ZienKBQkH .marker.cross{stroke:#333333;}#mermaid-svg-0DDPrE7ZienKBQkH svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-0DDPrE7ZienKBQkH p{margin:0;}#mermaid-svg-0DDPrE7ZienKBQkH .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-0DDPrE7ZienKBQkH .cluster-label text{fill:#333;}#mermaid-svg-0DDPrE7ZienKBQkH .cluster-label span{color:#333;}#mermaid-svg-0DDPrE7ZienKBQkH .cluster-label span p{background-color:transparent;}#mermaid-svg-0DDPrE7ZienKBQkH .label text,#mermaid-svg-0DDPrE7ZienKBQkH span{fill:#333;color:#333;}#mermaid-svg-0DDPrE7ZienKBQkH .node rect,#mermaid-svg-0DDPrE7ZienKBQkH .node circle,#mermaid-svg-0DDPrE7ZienKBQkH .node ellipse,#mermaid-svg-0DDPrE7ZienKBQkH .node polygon,#mermaid-svg-0DDPrE7ZienKBQkH .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-0DDPrE7ZienKBQkH .rough-node .label text,#mermaid-svg-0DDPrE7ZienKBQkH .node .label text,#mermaid-svg-0DDPrE7ZienKBQkH .image-shape .label,#mermaid-svg-0DDPrE7ZienKBQkH .icon-shape .label{text-anchor:middle;}#mermaid-svg-0DDPrE7ZienKBQkH .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-0DDPrE7ZienKBQkH .rough-node .label,#mermaid-svg-0DDPrE7ZienKBQkH .node .label,#mermaid-svg-0DDPrE7ZienKBQkH .image-shape .label,#mermaid-svg-0DDPrE7ZienKBQkH .icon-shape .label{text-align:center;}#mermaid-svg-0DDPrE7ZienKBQkH .node.clickable{cursor:pointer;}#mermaid-svg-0DDPrE7ZienKBQkH .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-0DDPrE7ZienKBQkH .arrowheadPath{fill:#333333;}#mermaid-svg-0DDPrE7ZienKBQkH .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-0DDPrE7ZienKBQkH .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-0DDPrE7ZienKBQkH .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-0DDPrE7ZienKBQkH .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-0DDPrE7ZienKBQkH .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-0DDPrE7ZienKBQkH .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-0DDPrE7ZienKBQkH .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-0DDPrE7ZienKBQkH .cluster text{fill:#333;}#mermaid-svg-0DDPrE7ZienKBQkH .cluster span{color:#333;}#mermaid-svg-0DDPrE7ZienKBQkH div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-0DDPrE7ZienKBQkH .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-0DDPrE7ZienKBQkH rect.text{fill:none;stroke-width:0;}#mermaid-svg-0DDPrE7ZienKBQkH .icon-shape,#mermaid-svg-0DDPrE7ZienKBQkH .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-0DDPrE7ZienKBQkH .icon-shape p,#mermaid-svg-0DDPrE7ZienKBQkH .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-0DDPrE7ZienKBQkH .icon-shape .label rect,#mermaid-svg-0DDPrE7ZienKBQkH .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-0DDPrE7ZienKBQkH .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-0DDPrE7ZienKBQkH .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-0DDPrE7ZienKBQkH :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} Interceptor 拦截范围
仅 Controller 请求
Controller 接口
静态资源:不拦截
原生 Servlet:不拦截
脱离 HandlerMapping:不拦截
Filter 拦截范围
全部请求(无差别)
Controller 接口
静态资源 html/css/js
原生 Servlet/JSP
错误页面/转发
| 请求路径 | Filter | Interceptor |
|---|---|---|
/static/1.jpg |
走 | 不走 |
/api/test |
走 | 走 |
3. Spring Bean 注入能力
#mermaid-svg-u9teZ56p84iRoPNj{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-u9teZ56p84iRoPNj .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-u9teZ56p84iRoPNj .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-u9teZ56p84iRoPNj .error-icon{fill:#552222;}#mermaid-svg-u9teZ56p84iRoPNj .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-u9teZ56p84iRoPNj .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-u9teZ56p84iRoPNj .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-u9teZ56p84iRoPNj .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-u9teZ56p84iRoPNj .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-u9teZ56p84iRoPNj .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-u9teZ56p84iRoPNj .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-u9teZ56p84iRoPNj .marker{fill:#333333;stroke:#333333;}#mermaid-svg-u9teZ56p84iRoPNj .marker.cross{stroke:#333333;}#mermaid-svg-u9teZ56p84iRoPNj svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-u9teZ56p84iRoPNj p{margin:0;}#mermaid-svg-u9teZ56p84iRoPNj .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-u9teZ56p84iRoPNj .cluster-label text{fill:#333;}#mermaid-svg-u9teZ56p84iRoPNj .cluster-label span{color:#333;}#mermaid-svg-u9teZ56p84iRoPNj .cluster-label span p{background-color:transparent;}#mermaid-svg-u9teZ56p84iRoPNj .label text,#mermaid-svg-u9teZ56p84iRoPNj span{fill:#333;color:#333;}#mermaid-svg-u9teZ56p84iRoPNj .node rect,#mermaid-svg-u9teZ56p84iRoPNj .node circle,#mermaid-svg-u9teZ56p84iRoPNj .node ellipse,#mermaid-svg-u9teZ56p84iRoPNj .node polygon,#mermaid-svg-u9teZ56p84iRoPNj .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-u9teZ56p84iRoPNj .rough-node .label text,#mermaid-svg-u9teZ56p84iRoPNj .node .label text,#mermaid-svg-u9teZ56p84iRoPNj .image-shape .label,#mermaid-svg-u9teZ56p84iRoPNj .icon-shape .label{text-anchor:middle;}#mermaid-svg-u9teZ56p84iRoPNj .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-u9teZ56p84iRoPNj .rough-node .label,#mermaid-svg-u9teZ56p84iRoPNj .node .label,#mermaid-svg-u9teZ56p84iRoPNj .image-shape .label,#mermaid-svg-u9teZ56p84iRoPNj .icon-shape .label{text-align:center;}#mermaid-svg-u9teZ56p84iRoPNj .node.clickable{cursor:pointer;}#mermaid-svg-u9teZ56p84iRoPNj .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-u9teZ56p84iRoPNj .arrowheadPath{fill:#333333;}#mermaid-svg-u9teZ56p84iRoPNj .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-u9teZ56p84iRoPNj .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-u9teZ56p84iRoPNj .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-u9teZ56p84iRoPNj .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-u9teZ56p84iRoPNj .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-u9teZ56p84iRoPNj .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-u9teZ56p84iRoPNj .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-u9teZ56p84iRoPNj .cluster text{fill:#333;}#mermaid-svg-u9teZ56p84iRoPNj .cluster span{color:#333;}#mermaid-svg-u9teZ56p84iRoPNj div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-u9teZ56p84iRoPNj .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-u9teZ56p84iRoPNj rect.text{fill:none;stroke-width:0;}#mermaid-svg-u9teZ56p84iRoPNj .icon-shape,#mermaid-svg-u9teZ56p84iRoPNj .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-u9teZ56p84iRoPNj .icon-shape p,#mermaid-svg-u9teZ56p84iRoPNj .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-u9teZ56p84iRoPNj .icon-shape .label rect,#mermaid-svg-u9teZ56p84iRoPNj .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-u9teZ56p84iRoPNj .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-u9teZ56p84iRoPNj .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-u9teZ56p84iRoPNj :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} Interceptor
Spring 启动
① 加载 IoC 容器
② 创建 Interceptor Bean
③ 自动注入依赖
Interceptor 由 Spring 管理
可自由 @Autowired
Filter
Tomcat 启动
① 容器启动 ② 初始化 Filter
③ 初始化 DispatcherServlet
④ 加载 Spring IoC
Filter 创建时 IoC 未就绪
无法 @Autowired
Filter 无法注入的原因 :Tomcat 启动顺序为 容器 → Filter → DispatcherServlet → Spring IoC,Filter 创建时 IoC 尚未初始化。
Interceptor 可自由注入的原因:Interceptor 本身就是 Spring Bean,由 IoC 统一管理。
实战原则:纯请求底层处理(编码、跨域、IP 拦截)放 Filter;业务逻辑、权限、登录校验、日志统计放 Interceptor。
4. 性能与功能对比
#mermaid-svg-YxWKhIfvfF8eanxX{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-YxWKhIfvfF8eanxX .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-YxWKhIfvfF8eanxX .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-YxWKhIfvfF8eanxX .error-icon{fill:#552222;}#mermaid-svg-YxWKhIfvfF8eanxX .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-YxWKhIfvfF8eanxX .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-YxWKhIfvfF8eanxX .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-YxWKhIfvfF8eanxX .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-YxWKhIfvfF8eanxX .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-YxWKhIfvfF8eanxX .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-YxWKhIfvfF8eanxX .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-YxWKhIfvfF8eanxX .marker{fill:#333333;stroke:#333333;}#mermaid-svg-YxWKhIfvfF8eanxX .marker.cross{stroke:#333333;}#mermaid-svg-YxWKhIfvfF8eanxX svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-YxWKhIfvfF8eanxX p{margin:0;}#mermaid-svg-YxWKhIfvfF8eanxX .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-YxWKhIfvfF8eanxX .cluster-label text{fill:#333;}#mermaid-svg-YxWKhIfvfF8eanxX .cluster-label span{color:#333;}#mermaid-svg-YxWKhIfvfF8eanxX .cluster-label span p{background-color:transparent;}#mermaid-svg-YxWKhIfvfF8eanxX .label text,#mermaid-svg-YxWKhIfvfF8eanxX span{fill:#333;color:#333;}#mermaid-svg-YxWKhIfvfF8eanxX .node rect,#mermaid-svg-YxWKhIfvfF8eanxX .node circle,#mermaid-svg-YxWKhIfvfF8eanxX .node ellipse,#mermaid-svg-YxWKhIfvfF8eanxX .node polygon,#mermaid-svg-YxWKhIfvfF8eanxX .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-YxWKhIfvfF8eanxX .rough-node .label text,#mermaid-svg-YxWKhIfvfF8eanxX .node .label text,#mermaid-svg-YxWKhIfvfF8eanxX .image-shape .label,#mermaid-svg-YxWKhIfvfF8eanxX .icon-shape .label{text-anchor:middle;}#mermaid-svg-YxWKhIfvfF8eanxX .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-YxWKhIfvfF8eanxX .rough-node .label,#mermaid-svg-YxWKhIfvfF8eanxX .node .label,#mermaid-svg-YxWKhIfvfF8eanxX .image-shape .label,#mermaid-svg-YxWKhIfvfF8eanxX .icon-shape .label{text-align:center;}#mermaid-svg-YxWKhIfvfF8eanxX .node.clickable{cursor:pointer;}#mermaid-svg-YxWKhIfvfF8eanxX .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-YxWKhIfvfF8eanxX .arrowheadPath{fill:#333333;}#mermaid-svg-YxWKhIfvfF8eanxX .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-YxWKhIfvfF8eanxX .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-YxWKhIfvfF8eanxX .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-YxWKhIfvfF8eanxX .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-YxWKhIfvfF8eanxX .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-YxWKhIfvfF8eanxX .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-YxWKhIfvfF8eanxX .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-YxWKhIfvfF8eanxX .cluster text{fill:#333;}#mermaid-svg-YxWKhIfvfF8eanxX .cluster span{color:#333;}#mermaid-svg-YxWKhIfvfF8eanxX div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-YxWKhIfvfF8eanxX .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-YxWKhIfvfF8eanxX rect.text{fill:none;stroke-width:0;}#mermaid-svg-YxWKhIfvfF8eanxX .icon-shape,#mermaid-svg-YxWKhIfvfF8eanxX .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-YxWKhIfvfF8eanxX .icon-shape p,#mermaid-svg-YxWKhIfvfF8eanxX .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-YxWKhIfvfF8eanxX .icon-shape .label rect,#mermaid-svg-YxWKhIfvfF8eanxX .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-YxWKhIfvfF8eanxX .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-YxWKhIfvfF8eanxX .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-YxWKhIfvfF8eanxX :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} Interceptor 优势
功能更强
可获取 Controller/方法/注解
权限/日志/限流
Filter 优势
性能更优
链路短 / 原生 API
适合高吞吐场景
| 维度 | Filter | Interceptor |
|---|---|---|
| 可获取对象 | ServletRequest / ServletResponse / FilterChain | HttpServletRequest / HttpServletResponse / Object handler |
| 能力范围 | 请求头、响应头基础操作 | 拿到目标 Controller、方法、注解、参数 |
| 无法做到 | 无法感知目标 Controller 和方法 | --- |
5. 完整执行流程
#mermaid-svg-XxuZR84wQmEsr18g{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-XxuZR84wQmEsr18g .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-XxuZR84wQmEsr18g .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-XxuZR84wQmEsr18g .error-icon{fill:#552222;}#mermaid-svg-XxuZR84wQmEsr18g .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-XxuZR84wQmEsr18g .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-XxuZR84wQmEsr18g .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-XxuZR84wQmEsr18g .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-XxuZR84wQmEsr18g .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-XxuZR84wQmEsr18g .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-XxuZR84wQmEsr18g .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-XxuZR84wQmEsr18g .marker{fill:#333333;stroke:#333333;}#mermaid-svg-XxuZR84wQmEsr18g .marker.cross{stroke:#333333;}#mermaid-svg-XxuZR84wQmEsr18g svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-XxuZR84wQmEsr18g p{margin:0;}#mermaid-svg-XxuZR84wQmEsr18g .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-XxuZR84wQmEsr18g .cluster-label text{fill:#333;}#mermaid-svg-XxuZR84wQmEsr18g .cluster-label span{color:#333;}#mermaid-svg-XxuZR84wQmEsr18g .cluster-label span p{background-color:transparent;}#mermaid-svg-XxuZR84wQmEsr18g .label text,#mermaid-svg-XxuZR84wQmEsr18g span{fill:#333;color:#333;}#mermaid-svg-XxuZR84wQmEsr18g .node rect,#mermaid-svg-XxuZR84wQmEsr18g .node circle,#mermaid-svg-XxuZR84wQmEsr18g .node ellipse,#mermaid-svg-XxuZR84wQmEsr18g .node polygon,#mermaid-svg-XxuZR84wQmEsr18g .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-XxuZR84wQmEsr18g .rough-node .label text,#mermaid-svg-XxuZR84wQmEsr18g .node .label text,#mermaid-svg-XxuZR84wQmEsr18g .image-shape .label,#mermaid-svg-XxuZR84wQmEsr18g .icon-shape .label{text-anchor:middle;}#mermaid-svg-XxuZR84wQmEsr18g .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-XxuZR84wQmEsr18g .rough-node .label,#mermaid-svg-XxuZR84wQmEsr18g .node .label,#mermaid-svg-XxuZR84wQmEsr18g .image-shape .label,#mermaid-svg-XxuZR84wQmEsr18g .icon-shape .label{text-align:center;}#mermaid-svg-XxuZR84wQmEsr18g .node.clickable{cursor:pointer;}#mermaid-svg-XxuZR84wQmEsr18g .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-XxuZR84wQmEsr18g .arrowheadPath{fill:#333333;}#mermaid-svg-XxuZR84wQmEsr18g .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-XxuZR84wQmEsr18g .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-XxuZR84wQmEsr18g .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-XxuZR84wQmEsr18g .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-XxuZR84wQmEsr18g .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-XxuZR84wQmEsr18g .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-XxuZR84wQmEsr18g .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-XxuZR84wQmEsr18g .cluster text{fill:#333;}#mermaid-svg-XxuZR84wQmEsr18g .cluster span{color:#333;}#mermaid-svg-XxuZR84wQmEsr18g div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-XxuZR84wQmEsr18g .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-XxuZR84wQmEsr18g rect.text{fill:none;stroke-width:0;}#mermaid-svg-XxuZR84wQmEsr18g .icon-shape,#mermaid-svg-XxuZR84wQmEsr18g .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-XxuZR84wQmEsr18g .icon-shape p,#mermaid-svg-XxuZR84wQmEsr18g .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-XxuZR84wQmEsr18g .icon-shape .label rect,#mermaid-svg-XxuZR84wQmEsr18g .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-XxuZR84wQmEsr18g .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-XxuZR84wQmEsr18g .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-XxuZR84wQmEsr18g :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} true
false
客户端请求
Tomcat 容器
Filter pre 逻辑
DispatcherServlet
Interceptor preHandle
返回 true?
执行 Controller
请求终止
Interceptor postHandle
Interceptor afterCompletion
Filter post 逻辑
响应返回客户端
逐阶段说明
| 阶段 | 说明 |
|---|---|
| Filter pre | chain.doFilter() 之前的代码 |
| Interceptor preHandle | 进入 Controller 前,返回 false 截断请求 |
| Controller 执行 | 目标接口业务代码 |
| Interceptor postHandle | Controller 执行后、视图渲染前 |
| Interceptor afterCompletion | 请求结束(正常/异常都执行) |
| Filter post | chain.doFilter() 之后的代码 |
6. 异常场景行为
| 场景 | Filter | Interceptor |
|---|---|---|
| Controller 抛异常 | 前后逻辑完整执行 | postHandle 不执行,afterCompletion 执行 |
| preHandle 返回 false | 后置逻辑仍执行 | 请求终止,不走 Controller |
| Filter 不执行 chain.doFilter() | 请求截断 | 后续流程全不执行 |
7. 适用场景决策树
#mermaid-svg-N7AwpymTa3IHrIbj{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-N7AwpymTa3IHrIbj .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-N7AwpymTa3IHrIbj .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-N7AwpymTa3IHrIbj .error-icon{fill:#552222;}#mermaid-svg-N7AwpymTa3IHrIbj .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-N7AwpymTa3IHrIbj .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-N7AwpymTa3IHrIbj .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-N7AwpymTa3IHrIbj .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-N7AwpymTa3IHrIbj .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-N7AwpymTa3IHrIbj .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-N7AwpymTa3IHrIbj .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-N7AwpymTa3IHrIbj .marker{fill:#333333;stroke:#333333;}#mermaid-svg-N7AwpymTa3IHrIbj .marker.cross{stroke:#333333;}#mermaid-svg-N7AwpymTa3IHrIbj svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-N7AwpymTa3IHrIbj p{margin:0;}#mermaid-svg-N7AwpymTa3IHrIbj .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-N7AwpymTa3IHrIbj .cluster-label text{fill:#333;}#mermaid-svg-N7AwpymTa3IHrIbj .cluster-label span{color:#333;}#mermaid-svg-N7AwpymTa3IHrIbj .cluster-label span p{background-color:transparent;}#mermaid-svg-N7AwpymTa3IHrIbj .label text,#mermaid-svg-N7AwpymTa3IHrIbj span{fill:#333;color:#333;}#mermaid-svg-N7AwpymTa3IHrIbj .node rect,#mermaid-svg-N7AwpymTa3IHrIbj .node circle,#mermaid-svg-N7AwpymTa3IHrIbj .node ellipse,#mermaid-svg-N7AwpymTa3IHrIbj .node polygon,#mermaid-svg-N7AwpymTa3IHrIbj .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-N7AwpymTa3IHrIbj .rough-node .label text,#mermaid-svg-N7AwpymTa3IHrIbj .node .label text,#mermaid-svg-N7AwpymTa3IHrIbj .image-shape .label,#mermaid-svg-N7AwpymTa3IHrIbj .icon-shape .label{text-anchor:middle;}#mermaid-svg-N7AwpymTa3IHrIbj .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-N7AwpymTa3IHrIbj .rough-node .label,#mermaid-svg-N7AwpymTa3IHrIbj .node .label,#mermaid-svg-N7AwpymTa3IHrIbj .image-shape .label,#mermaid-svg-N7AwpymTa3IHrIbj .icon-shape .label{text-align:center;}#mermaid-svg-N7AwpymTa3IHrIbj .node.clickable{cursor:pointer;}#mermaid-svg-N7AwpymTa3IHrIbj .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-N7AwpymTa3IHrIbj .arrowheadPath{fill:#333333;}#mermaid-svg-N7AwpymTa3IHrIbj .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-N7AwpymTa3IHrIbj .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-N7AwpymTa3IHrIbj .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-N7AwpymTa3IHrIbj .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-N7AwpymTa3IHrIbj .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-N7AwpymTa3IHrIbj .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-N7AwpymTa3IHrIbj .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-N7AwpymTa3IHrIbj .cluster text{fill:#333;}#mermaid-svg-N7AwpymTa3IHrIbj .cluster span{color:#333;}#mermaid-svg-N7AwpymTa3IHrIbj div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-N7AwpymTa3IHrIbj .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-N7AwpymTa3IHrIbj rect.text{fill:none;stroke-width:0;}#mermaid-svg-N7AwpymTa3IHrIbj .icon-shape,#mermaid-svg-N7AwpymTa3IHrIbj .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-N7AwpymTa3IHrIbj .icon-shape p,#mermaid-svg-N7AwpymTa3IHrIbj .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-N7AwpymTa3IHrIbj .icon-shape .label rect,#mermaid-svg-N7AwpymTa3IHrIbj .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-N7AwpymTa3IHrIbj .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-N7AwpymTa3IHrIbj .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-N7AwpymTa3IHrIbj :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} Interceptor 场景
Filter 场景
不需要
需要
是
否
需要拦截请求
需要感知
Controller/方法/注解?
属于底层通用处理?
使用 Interceptor
使用 Filter
编码 / 跨域 / IP黑白名单
静态资源控制 / 请求头设置
登录校验 / 权限控制
操作日志 / 接口监控
参数预处理 / 注解解析
五、CORS 跨域完整解决方案
1. 跨域产生原因
#mermaid-svg-qaaLCgcz6JrQOu3A{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-qaaLCgcz6JrQOu3A .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-qaaLCgcz6JrQOu3A .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-qaaLCgcz6JrQOu3A .error-icon{fill:#552222;}#mermaid-svg-qaaLCgcz6JrQOu3A .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-qaaLCgcz6JrQOu3A .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-qaaLCgcz6JrQOu3A .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-qaaLCgcz6JrQOu3A .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-qaaLCgcz6JrQOu3A .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-qaaLCgcz6JrQOu3A .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-qaaLCgcz6JrQOu3A .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-qaaLCgcz6JrQOu3A .marker{fill:#333333;stroke:#333333;}#mermaid-svg-qaaLCgcz6JrQOu3A .marker.cross{stroke:#333333;}#mermaid-svg-qaaLCgcz6JrQOu3A svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-qaaLCgcz6JrQOu3A p{margin:0;}#mermaid-svg-qaaLCgcz6JrQOu3A .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-qaaLCgcz6JrQOu3A .cluster-label text{fill:#333;}#mermaid-svg-qaaLCgcz6JrQOu3A .cluster-label span{color:#333;}#mermaid-svg-qaaLCgcz6JrQOu3A .cluster-label span p{background-color:transparent;}#mermaid-svg-qaaLCgcz6JrQOu3A .label text,#mermaid-svg-qaaLCgcz6JrQOu3A span{fill:#333;color:#333;}#mermaid-svg-qaaLCgcz6JrQOu3A .node rect,#mermaid-svg-qaaLCgcz6JrQOu3A .node circle,#mermaid-svg-qaaLCgcz6JrQOu3A .node ellipse,#mermaid-svg-qaaLCgcz6JrQOu3A .node polygon,#mermaid-svg-qaaLCgcz6JrQOu3A .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-qaaLCgcz6JrQOu3A .rough-node .label text,#mermaid-svg-qaaLCgcz6JrQOu3A .node .label text,#mermaid-svg-qaaLCgcz6JrQOu3A .image-shape .label,#mermaid-svg-qaaLCgcz6JrQOu3A .icon-shape .label{text-anchor:middle;}#mermaid-svg-qaaLCgcz6JrQOu3A .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-qaaLCgcz6JrQOu3A .rough-node .label,#mermaid-svg-qaaLCgcz6JrQOu3A .node .label,#mermaid-svg-qaaLCgcz6JrQOu3A .image-shape .label,#mermaid-svg-qaaLCgcz6JrQOu3A .icon-shape .label{text-align:center;}#mermaid-svg-qaaLCgcz6JrQOu3A .node.clickable{cursor:pointer;}#mermaid-svg-qaaLCgcz6JrQOu3A .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-qaaLCgcz6JrQOu3A .arrowheadPath{fill:#333333;}#mermaid-svg-qaaLCgcz6JrQOu3A .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-qaaLCgcz6JrQOu3A .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-qaaLCgcz6JrQOu3A .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-qaaLCgcz6JrQOu3A .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-qaaLCgcz6JrQOu3A .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-qaaLCgcz6JrQOu3A .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-qaaLCgcz6JrQOu3A .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-qaaLCgcz6JrQOu3A .cluster text{fill:#333;}#mermaid-svg-qaaLCgcz6JrQOu3A .cluster span{color:#333;}#mermaid-svg-qaaLCgcz6JrQOu3A div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-qaaLCgcz6JrQOu3A .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-qaaLCgcz6JrQOu3A rect.text{fill:none;stroke-width:0;}#mermaid-svg-qaaLCgcz6JrQOu3A .icon-shape,#mermaid-svg-qaaLCgcz6JrQOu3A .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-qaaLCgcz6JrQOu3A .icon-shape p,#mermaid-svg-qaaLCgcz6JrQOu3A .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-qaaLCgcz6JrQOu3A .icon-shape .label rect,#mermaid-svg-qaaLCgcz6JrQOu3A .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-qaaLCgcz6JrQOu3A .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-qaaLCgcz6JrQOu3A .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-qaaLCgcz6JrQOu3A :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 同源策略
是
否
浏览器
协议/域名/端口
完全相同?
正常访问
跨域拦截
No Access-Control-Allow-Origin
浏览器同源策略:协议、域名、端口任意一个不同,就会跨域,阻止前端直接调用接口。
2. 解决方案优先级
#mermaid-svg-Af6LlFpBZhRBnM9h{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-Af6LlFpBZhRBnM9h .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-Af6LlFpBZhRBnM9h .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-Af6LlFpBZhRBnM9h .error-icon{fill:#552222;}#mermaid-svg-Af6LlFpBZhRBnM9h .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-Af6LlFpBZhRBnM9h .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-Af6LlFpBZhRBnM9h .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-Af6LlFpBZhRBnM9h .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-Af6LlFpBZhRBnM9h .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-Af6LlFpBZhRBnM9h .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-Af6LlFpBZhRBnM9h .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-Af6LlFpBZhRBnM9h .marker{fill:#333333;stroke:#333333;}#mermaid-svg-Af6LlFpBZhRBnM9h .marker.cross{stroke:#333333;}#mermaid-svg-Af6LlFpBZhRBnM9h svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-Af6LlFpBZhRBnM9h p{margin:0;}#mermaid-svg-Af6LlFpBZhRBnM9h .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-Af6LlFpBZhRBnM9h .cluster-label text{fill:#333;}#mermaid-svg-Af6LlFpBZhRBnM9h .cluster-label span{color:#333;}#mermaid-svg-Af6LlFpBZhRBnM9h .cluster-label span p{background-color:transparent;}#mermaid-svg-Af6LlFpBZhRBnM9h .label text,#mermaid-svg-Af6LlFpBZhRBnM9h span{fill:#333;color:#333;}#mermaid-svg-Af6LlFpBZhRBnM9h .node rect,#mermaid-svg-Af6LlFpBZhRBnM9h .node circle,#mermaid-svg-Af6LlFpBZhRBnM9h .node ellipse,#mermaid-svg-Af6LlFpBZhRBnM9h .node polygon,#mermaid-svg-Af6LlFpBZhRBnM9h .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-Af6LlFpBZhRBnM9h .rough-node .label text,#mermaid-svg-Af6LlFpBZhRBnM9h .node .label text,#mermaid-svg-Af6LlFpBZhRBnM9h .image-shape .label,#mermaid-svg-Af6LlFpBZhRBnM9h .icon-shape .label{text-anchor:middle;}#mermaid-svg-Af6LlFpBZhRBnM9h .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-Af6LlFpBZhRBnM9h .rough-node .label,#mermaid-svg-Af6LlFpBZhRBnM9h .node .label,#mermaid-svg-Af6LlFpBZhRBnM9h .image-shape .label,#mermaid-svg-Af6LlFpBZhRBnM9h .icon-shape .label{text-align:center;}#mermaid-svg-Af6LlFpBZhRBnM9h .node.clickable{cursor:pointer;}#mermaid-svg-Af6LlFpBZhRBnM9h .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-Af6LlFpBZhRBnM9h .arrowheadPath{fill:#333333;}#mermaid-svg-Af6LlFpBZhRBnM9h .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-Af6LlFpBZhRBnM9h .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-Af6LlFpBZhRBnM9h .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-Af6LlFpBZhRBnM9h .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-Af6LlFpBZhRBnM9h .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-Af6LlFpBZhRBnM9h .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-Af6LlFpBZhRBnM9h .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-Af6LlFpBZhRBnM9h .cluster text{fill:#333;}#mermaid-svg-Af6LlFpBZhRBnM9h .cluster span{color:#333;}#mermaid-svg-Af6LlFpBZhRBnM9h div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-Af6LlFpBZhRBnM9h .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-Af6LlFpBZhRBnM9h rect.text{fill:none;stroke-width:0;}#mermaid-svg-Af6LlFpBZhRBnM9h .icon-shape,#mermaid-svg-Af6LlFpBZhRBnM9h .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-Af6LlFpBZhRBnM9h .icon-shape p,#mermaid-svg-Af6LlFpBZhRBnM9h .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-Af6LlFpBZhRBnM9h .icon-shape .label rect,#mermaid-svg-Af6LlFpBZhRBnM9h .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-Af6LlFpBZhRBnM9h .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-Af6LlFpBZhRBnM9h .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-Af6LlFpBZhRBnM9h :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 方案推荐度
① Nginx 反向代理
(生产首选)
② Filter 全局跨域
(通用稳定)
③ Spring MVC 配置
(Boot 推荐)
④ @CrossOrigin 注解
(单接口)
⑤ Gateway 全局跨域
(微服务)
3. 四种跨域实现方案
(1)Filter 方式(最通用)
#mermaid-svg-xwkxgVTl5tyoHtET{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-xwkxgVTl5tyoHtET .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-xwkxgVTl5tyoHtET .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-xwkxgVTl5tyoHtET .error-icon{fill:#552222;}#mermaid-svg-xwkxgVTl5tyoHtET .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-xwkxgVTl5tyoHtET .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-xwkxgVTl5tyoHtET .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-xwkxgVTl5tyoHtET .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-xwkxgVTl5tyoHtET .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-xwkxgVTl5tyoHtET .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-xwkxgVTl5tyoHtET .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-xwkxgVTl5tyoHtET .marker{fill:#333333;stroke:#333333;}#mermaid-svg-xwkxgVTl5tyoHtET .marker.cross{stroke:#333333;}#mermaid-svg-xwkxgVTl5tyoHtET svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-xwkxgVTl5tyoHtET p{margin:0;}#mermaid-svg-xwkxgVTl5tyoHtET .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-xwkxgVTl5tyoHtET .cluster-label text{fill:#333;}#mermaid-svg-xwkxgVTl5tyoHtET .cluster-label span{color:#333;}#mermaid-svg-xwkxgVTl5tyoHtET .cluster-label span p{background-color:transparent;}#mermaid-svg-xwkxgVTl5tyoHtET .label text,#mermaid-svg-xwkxgVTl5tyoHtET span{fill:#333;color:#333;}#mermaid-svg-xwkxgVTl5tyoHtET .node rect,#mermaid-svg-xwkxgVTl5tyoHtET .node circle,#mermaid-svg-xwkxgVTl5tyoHtET .node ellipse,#mermaid-svg-xwkxgVTl5tyoHtET .node polygon,#mermaid-svg-xwkxgVTl5tyoHtET .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-xwkxgVTl5tyoHtET .rough-node .label text,#mermaid-svg-xwkxgVTl5tyoHtET .node .label text,#mermaid-svg-xwkxgVTl5tyoHtET .image-shape .label,#mermaid-svg-xwkxgVTl5tyoHtET .icon-shape .label{text-anchor:middle;}#mermaid-svg-xwkxgVTl5tyoHtET .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-xwkxgVTl5tyoHtET .rough-node .label,#mermaid-svg-xwkxgVTl5tyoHtET .node .label,#mermaid-svg-xwkxgVTl5tyoHtET .image-shape .label,#mermaid-svg-xwkxgVTl5tyoHtET .icon-shape .label{text-align:center;}#mermaid-svg-xwkxgVTl5tyoHtET .node.clickable{cursor:pointer;}#mermaid-svg-xwkxgVTl5tyoHtET .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-xwkxgVTl5tyoHtET .arrowheadPath{fill:#333333;}#mermaid-svg-xwkxgVTl5tyoHtET .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-xwkxgVTl5tyoHtET .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-xwkxgVTl5tyoHtET .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-xwkxgVTl5tyoHtET .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-xwkxgVTl5tyoHtET .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-xwkxgVTl5tyoHtET .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-xwkxgVTl5tyoHtET .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-xwkxgVTl5tyoHtET .cluster text{fill:#333;}#mermaid-svg-xwkxgVTl5tyoHtET .cluster span{color:#333;}#mermaid-svg-xwkxgVTl5tyoHtET div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-xwkxgVTl5tyoHtET .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-xwkxgVTl5tyoHtET rect.text{fill:none;stroke-width:0;}#mermaid-svg-xwkxgVTl5tyoHtET .icon-shape,#mermaid-svg-xwkxgVTl5tyoHtET .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-xwkxgVTl5tyoHtET .icon-shape p,#mermaid-svg-xwkxgVTl5tyoHtET .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-xwkxgVTl5tyoHtET .icon-shape .label rect,#mermaid-svg-xwkxgVTl5tyoHtET .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-xwkxgVTl5tyoHtET .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-xwkxgVTl5tyoHtET .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-xwkxgVTl5tyoHtET :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} OPTIONS 预检
非预检
浏览器请求
CORS Filter
处理预检请求
返回 200
设置跨域响应头
放行到业务接口
java
@Component
@Order(Ordered.HIGHEST_PRECEDENCE)
public class CorsFilter implements Filter {
@Override
public void doFilter(ServletRequest request,
ServletResponse response,
FilterChain chain)
throws IOException, ServletException {
HttpServletResponse resp = (HttpServletResponse) response;
HttpServletRequest req = (HttpServletRequest) request;
resp.setHeader("Access-Control-Allow-Origin", "*");
resp.setHeader("Access-Control-Allow-Methods", "POST,GET,PUT,DELETE,OPTIONS");
resp.setHeader("Access-Control-Allow-Headers", "*");
resp.setHeader("Access-Control-Max-Age", "3600");
resp.setHeader("Access-Control-Allow-Credentials", "true");
if ("OPTIONS".equalsIgnoreCase(req.getMethod())) {
response.setStatus(HttpServletResponse.SC_OK);
return;
}
chain.doFilter(request, response);
}
}
(2)Spring Boot 配置方式
java
@Configuration
public class CorsConfig {
@Bean
public WebMvcConfigurer corsConfigurer() {
return new WebMvcConfigurer() {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedOrigins("*")
.allowedMethods("GET", "POST", "PUT", "DELETE")
.allowedHeaders("*")
.allowCredentials(true)
.maxAge(3600);
}
};
}
}
(3)Spring Cloud Gateway 方式
java
@Configuration
public class GatewayCorsConfig {
@Bean
public CorsWebFilter corsFilter() {
CorsConfiguration config = new CorsConfiguration();
config.addAllowedOrigin("*");
config.addAllowedHeader("*");
config.addAllowedMethod("*");
config.setAllowCredentials(true);
config.setMaxAge(3600L);
UrlBasedCorsConfigurationSource source =
new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", config);
return new CorsWebFilter(source);
}
}
(4)注解方式(单接口)
java
@RestController
public class TestController {
@CrossOrigin(origins = "*")
@GetMapping("/test")
public String test() {
return "ok";
}
}
六、写在最后
#mermaid-svg-ZwgTYGebCY6IspxQ{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-ZwgTYGebCY6IspxQ .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-ZwgTYGebCY6IspxQ .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-ZwgTYGebCY6IspxQ .error-icon{fill:#552222;}#mermaid-svg-ZwgTYGebCY6IspxQ .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-ZwgTYGebCY6IspxQ .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-ZwgTYGebCY6IspxQ .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-ZwgTYGebCY6IspxQ .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-ZwgTYGebCY6IspxQ .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-ZwgTYGebCY6IspxQ .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-ZwgTYGebCY6IspxQ .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-ZwgTYGebCY6IspxQ .marker{fill:#333333;stroke:#333333;}#mermaid-svg-ZwgTYGebCY6IspxQ .marker.cross{stroke:#333333;}#mermaid-svg-ZwgTYGebCY6IspxQ svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-ZwgTYGebCY6IspxQ p{margin:0;}#mermaid-svg-ZwgTYGebCY6IspxQ .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-ZwgTYGebCY6IspxQ .cluster-label text{fill:#333;}#mermaid-svg-ZwgTYGebCY6IspxQ .cluster-label span{color:#333;}#mermaid-svg-ZwgTYGebCY6IspxQ .cluster-label span p{background-color:transparent;}#mermaid-svg-ZwgTYGebCY6IspxQ .label text,#mermaid-svg-ZwgTYGebCY6IspxQ span{fill:#333;color:#333;}#mermaid-svg-ZwgTYGebCY6IspxQ .node rect,#mermaid-svg-ZwgTYGebCY6IspxQ .node circle,#mermaid-svg-ZwgTYGebCY6IspxQ .node ellipse,#mermaid-svg-ZwgTYGebCY6IspxQ .node polygon,#mermaid-svg-ZwgTYGebCY6IspxQ .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-ZwgTYGebCY6IspxQ .rough-node .label text,#mermaid-svg-ZwgTYGebCY6IspxQ .node .label text,#mermaid-svg-ZwgTYGebCY6IspxQ .image-shape .label,#mermaid-svg-ZwgTYGebCY6IspxQ .icon-shape .label{text-anchor:middle;}#mermaid-svg-ZwgTYGebCY6IspxQ .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-ZwgTYGebCY6IspxQ .rough-node .label,#mermaid-svg-ZwgTYGebCY6IspxQ .node .label,#mermaid-svg-ZwgTYGebCY6IspxQ .image-shape .label,#mermaid-svg-ZwgTYGebCY6IspxQ .icon-shape .label{text-align:center;}#mermaid-svg-ZwgTYGebCY6IspxQ .node.clickable{cursor:pointer;}#mermaid-svg-ZwgTYGebCY6IspxQ .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-ZwgTYGebCY6IspxQ .arrowheadPath{fill:#333333;}#mermaid-svg-ZwgTYGebCY6IspxQ .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-ZwgTYGebCY6IspxQ .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-ZwgTYGebCY6IspxQ .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-ZwgTYGebCY6IspxQ .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-ZwgTYGebCY6IspxQ .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-ZwgTYGebCY6IspxQ .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-ZwgTYGebCY6IspxQ .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-ZwgTYGebCY6IspxQ .cluster text{fill:#333;}#mermaid-svg-ZwgTYGebCY6IspxQ .cluster span{color:#333;}#mermaid-svg-ZwgTYGebCY6IspxQ div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-ZwgTYGebCY6IspxQ .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-ZwgTYGebCY6IspxQ rect.text{fill:none;stroke-width:0;}#mermaid-svg-ZwgTYGebCY6IspxQ .icon-shape,#mermaid-svg-ZwgTYGebCY6IspxQ .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-ZwgTYGebCY6IspxQ .icon-shape p,#mermaid-svg-ZwgTYGebCY6IspxQ .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-ZwgTYGebCY6IspxQ .icon-shape .label rect,#mermaid-svg-ZwgTYGebCY6IspxQ .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-ZwgTYGebCY6IspxQ .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-ZwgTYGebCY6IspxQ .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-ZwgTYGebCY6IspxQ :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} Filter vs Interceptor 核心要点
Filter:容器级 | 全部请求 | 无法注入 Bean | 性能优
Interceptor:框架级 | 仅 Controller | 自由注入 Bean | 功能强
执行顺序:Filter pre Interceptor pre Controller Interceptor post Filter post
异常:Interceptor postHandle 不执行,afterCompletion 必执行
CORS 跨域优先用:Nginx > Filter > Spring MVC > 注解 > Gateway
- Filter 属于 Servlet 容器 组件,Interceptor 属于 Spring MVC 框架组件。
- Filter 拦截容器接收的全部请求 ,Interceptor 仅拦截走向 Controller 的请求。
- Filter 原生无法注入 Spring Bean,Interceptor 可正常使用依赖注入。
- Filter 执行开销更小、性能更优,Interceptor 依托框架具备更强的业务处理能力。
- 请求执行顺序:Filter 前置逻辑 → Interceptor 前置处理 → Controller 执行 → Interceptor 后置与收尾处理 → Filter 后置逻辑。
- Filter 适合编码、跨域、IP 管控等底层通用处理,Interceptor 适合权限、日志、接口校验等业务相关处理。
- 多组件场景下,执行优先级由
@Order或注册顺序决定,前置正序 执行,后置逆序执行。 - 项目异常时,Interceptor 的
postHandle方法不会执行,afterCompletion仍会正常触发。