Java 开发:过滤器(Filter)与拦截器(Interceptor)深度解析 + CORS 跨域完整解决方案

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容器 管的,管所有 请求;

InterceptorSpring 管的,只管 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

  1. Filter 属于 Servlet 容器 组件,Interceptor 属于 Spring MVC 框架组件。
  2. Filter 拦截容器接收的全部请求Interceptor 仅拦截走向 Controller 的请求。
  3. Filter 原生无法注入 Spring Bean,Interceptor 可正常使用依赖注入。
  4. Filter 执行开销更小、性能更优,Interceptor 依托框架具备更强的业务处理能力。
  5. 请求执行顺序:Filter 前置逻辑 → Interceptor 前置处理 → Controller 执行 → Interceptor 后置与收尾处理 → Filter 后置逻辑。
  6. Filter 适合编码、跨域、IP 管控等底层通用处理,Interceptor 适合权限、日志、接口校验等业务相关处理。
  7. 多组件场景下,执行优先级由 @Order 或注册顺序决定,前置正序 执行,后置逆序执行。
  8. 项目异常时,Interceptor 的 postHandle 方法不会执行,afterCompletion 仍会正常触发。
相关推荐
我登哥MVP1 小时前
SpringCloud 核心组件解析:服务熔断和降级
java·spring boot·后端·spring·spring cloud·java-ee·maven
霸道流氓气质1 小时前
Spring AI Alibaba Graph 全解析:从入门到精通
java·人工智能·spring
摇滚侠1 小时前
SpringMVC 入门到实战 异常处理 83-85
java·后端·spring·maven·intellij-idea
Solis程序员1 小时前
长会话状态治理(上):问题分析、存储分层与恢复机制
java
布朗克1681 小时前
40 Redis与微服务入门
java·数据库·redis·微服务
TPBoreas2 小时前
springboot我们项目中的常见注解
java·spring boot·后端
asdfg12589632 小时前
三层架构(Controller-Service-DAO)模式中的controller 和 dao/mapper的通俗理解
java·架构模式
真实的菜2 小时前
Nacos单机部署入门:避坑指南与实战
java