03 拦截器和过滤器的区别

vvEcho 2024-01-20 14:08:36
Categories: Tags:

区别:

  1. 拦截器是SpringMVC提供的,过滤器是Servlet提供的。
  2. 过滤器与servlet是绑定的,仅限于web应用。而拦截器可作用于其他的应用,例如swing应用
  3. 对所有请求生效(包括静态资源、Servlet、JSP等),可修改请求/响应内容(如编码、敏感词过滤)
  4. 拦截器仅拦截SpringMVC处理的请求(如Controller方法),无法作用于静态资源或非Spring管理的请
  5. filter在servlet之前执行doFilter(),在servlet执行之后执行chain.doFilter()
  6. 拦截器在controller之前执行preHandle(),在controller执行之后执行postHandle();在视图渲染之后afterCompletion()
  7. 过滤器:主要用于通用预处理(如URL过滤、字符编码设置),无法直接干预业务逻辑;
    拦截器:支持更细粒度的业务逻辑(如权限验证、日志记录),且可通过preHandle返回值终止请求

应用场景对比:

场景 使用 示例
全局请求处理(如编码设置) 过滤器 统一设置请求/响应字符集 UTF-8
静态资源访问控制 过滤器 限制未授权用户访问图片、CSS等资源
敏感词过滤 过滤器 过滤请求参数中的非法内容
权限验证与登录检查 拦截器 验证用户Token,拦截未登录请求
日志记录与性能监控 拦截器 记录Controller方法执行时间
业务异常统一处理 拦截器 捕获Controller异常并返回标准化错误响应

拦截器代码示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
@Component
public class AuthInterceptor implements HandlerInterceptor {

// Controller方法执行前调用
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("拦截器 preHandle:验证用户权限");
String token = request.getHeader("token");
if (token == null || !token.equals("valid_token")) {
response.sendError(401, "Unauthorized");
return false; // 终止请求
}
return true; // 继续执行后续逻辑
}

// Controller方法执行后、视图渲染前调用
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
System.out.println("拦截器 postHandle:记录请求完成时间");
modelAndView.addObject("timestamp", System.currentTimeMillis());
}

// 视图渲染后调用(无论是否异常)
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
System.out.println("拦截器 afterCompletion:清理资源");
if (ex != null) {
System.err.println("请求异常:" + ex.getMessage());
}
}
}

@Configuration
public class WebConfig implements WebMvcConfigurer {

@Autowired
private AuthInterceptor authInterceptor;

@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(authInterceptor) // 注册拦截器
.addPathPatterns("/api/**") // 拦截的路径
.excludePathPatterns("/api/login"); // 排除的路径
}
}

过滤器代码示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
@WebFilter(urlPatterns = "/*") // 拦截所有请求
public class LogFilter implements Filter {

@Override
public void init(FilterConfig filterConfig) {
System.out.println("过滤器初始化");
}

@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
System.out.println("过滤器 doFilter:记录请求开始时间");
long startTime = System.currentTimeMillis();

// 处理请求(如修改请求/响应编码)
HttpServletRequest httpRequest = (HttpServletRequest) request;
HttpServletResponse httpResponse = (HttpServletResponse) response;
httpRequest.setCharacterEncoding("UTF-8");
httpResponse.setCharacterEncoding("UTF-8");

// 继续执行后续过滤器或Servlet
chain.doFilter(request, response);

// 处理响应
long duration = System.currentTimeMillis() - startTime;
System.out.println("请求耗时:" + duration + "ms");
}

@Override
public void destroy() {
System.out.println("过滤器销毁");
}
}