区别
Interceptor | Filter | |
|---|---|---|
应用范围 | 拦截器是Web框架中的一部分,例如Spring MVC框架,用于拦截请求和响应,可以在方法调用之前和之后执行指定的操作 | 过滤器是Servlet规范的一部分,可以在请求进入Servlet容器之前或者离开容器之后进行处理。 |
处理顺序 | 拦截器是基于Java的反射机制,在方法调用前后进行拦截,可以自定义拦截顺序。 | 过滤器是根据元素在web.xml文件中的顺序来决定的。 |
生命周期 | 拦截器是在每次请求时都会创建新的实例,并在处理完成后销毁 | 而过滤器是在应用启动时创建,并在应用关闭时销毁。 |
功能 | 拦截器主要用于拦截和处理请求和响应,例如日志记录、权限验证等 | 过滤器主要用于过滤请求和响应,例如对请求进行字符编码、防止跨站点脚本攻击等。 |
总的来说,拦截器更加灵活和强大,可以作用于具体的方法调用,对请求和响应进行处理。
过滤器更加通用,可以对请求进行过滤和预处理,不局限于某个具体的方法。
案例
我们假设有一个Web应用,其中包含一个登录功能。
当用户登录成功后,需要记录用户的登录信息,并在每个请求中验证用户是否已登录。
首先,可以使用拦截器来实现这个功能。在用户登录成功后记录登录信息,并在每个请求之前验证用户是否已登录。以下是拦截器的示例代码:
public class LoginInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
// 在请求之前进行处理,判断用户是否已登录
if (userIsLoggedIn()) {
// 用户已登录,继续处理请求
return true;
} else {
// 用户未登录,跳转到登录页面
response.sendRedirect("/login");
return false;
}
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
// 在请求之后进行处理,记录用户登录信息
logUserLoginInfo();
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
// 请求完成之后进行处理
}
private boolean userIsLoggedIn() {
// 判断用户是否已登录的逻辑
// ...
}
private void logUserLoginInfo() {
// 记录用户登录信息的逻辑
// ...
}
}
然后,可以在配置文件中将拦截器应用到特定的URL路径上,例如
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new LoginInterceptor()).addPathPatterns("/secure/**");
}
}
在上述例子中,通过拦截器实现了在用户登录成功后记录登录信息,并在每个请求中验证用户是否已登录。
接下来,也可以使用过滤器来实现相同的功能:
public class LoginFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
// 过滤器的初始化逻辑
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
HttpServletRequest httpRequest = (HttpServletRequest) request;
HttpServletResponse httpResponse = (HttpServletResponse) response;
// 在请求之前进行处理,判断用户是否已登录
if (userIsLoggedIn(httpRequest)) {
// 用户已登录,继续处理请求
chain.doFilter(request, response);
} else {
// 用户未登录,跳转到登录页面
httpResponse.sendRedirect(httpRequest.getContextPath() + "/login");
}
// 在请求之后进行处理,记录用户登录信息
logUserLoginInfo(httpRequest);
}
@Override
public void destroy() {
// 过滤器的销毁逻辑
}
private boolean userIsLoggedIn(HttpServletRequest request) {
// 判断用户是否已登录的逻辑
// ...
}
private void logUserLoginInfo(HttpServletRequest request) {
// 记录用户登录信息的逻辑
// ...
}
}
通过这个例子,可以看到使用拦截器和过滤器都能够实现相似的功能,都可以在请求前后进行处理。
拦截器更适合在业务逻辑层面进行拦截和处理,而过滤器更适合在Web容器层面进行拦截和处理。
可以根据具体的需求和框架选择合适的方法来实现功能。
执行顺序
如果拦截器和过滤器同时使用,那么他们执行的顺序谁先谁后呢?
在Java Web应用中,拦截器和过滤器的执行顺序如下:
- 过滤器先于拦截器执行。
- 拦截器在进入处理器(Controller)之前执行。
- 拦截器在离开处理器之后执行。
- 过滤器在进入目标资源之前执行。
- 过滤器在离开目标资源之后执行。
具体的执行顺序如下:
-
过滤器的
doFilter()方法被调用。 -
拦截器的
preHandle()方法被调用。 -
控制器的处理方法执行。
-
拦截器的
postHandle()方法被调用。 -
视图渲染之前,拦截器的
afterCompletion()方法被调用。 -
过滤器的
doFilter()方法继续执行。
在过滤器和拦截器同时使用的情况下,过滤器先于拦截器执行,而拦截器则在进入和离开处理器之前执行。
这样可以先进行一些通用的请求过滤或修改,然后再执行特定操作。
拦截器则专注于处理器的执行过程,例如记录日志、权限验证等。
通过组合使用过滤器和拦截器,可以实现更加灵活和全面的请求处理机制。