前言
面试当中经常会被问道拦截器和过滤器的区别在此做个记录
一、拦截器Interceptor
顾名思义拦截器可以作为拦截请求,对请求进行一系列操作的工具,是spring里面的,使用动态代理技术在请求进入servlet后controller前 进行处理。通常可用于拦截用户登录检查用户token等。通过实现Interceptor接口 例如:
public class UserTokenInterceptor implements HandlerInterceptor
HandlerInterceptor 接口有三个方法 注意传递的是HttpServletRequest 对象
public interface HandlerInterceptor {
default boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
return true;
}
default void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable ModelAndView modelAndView) throws Exception {
}
default void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable Exception ex) throws Exception {
}
}
二、过滤器Filter
过滤器是需要依赖web容器的,所有只有在web项目中可以使用,例如tomcat,拦截进入容器后进入servlet前的请求,通过实现Filter接口
代码如下(示例):
public class UserTokenInterceptor implements Filter {
public interface Filter {
default void init(FilterConfig filterConfig) throws ServletException {
}
void doFilter(ServletRequest var1, ServletResponse var2, FilterChain var3) throws IOException, ServletException;
default void destroy() {
}
}
FilterChain 是一个接口 ,ApplicationFilterChain 是其实现类 因为在我们平常写法中重写了doFilter方法
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
xxxx,业务逻辑
filterChain.doFilter(servletRequest,servletResponse);
}
filterChain.doFilter(servletRequest,servletResponse); 就是需要调用 ApplicationFilterChain 的doFilter 方法,进行回调,多个过滤器,开始计数一个个回调,执行doFilter方法
public void doFilter(ServletRequest request, ServletResponse response)
throws IOException, ServletException {
if( Globals.IS_SECURITY_ENABLED ) {
final ServletRequest req = request;
final ServletResponse res = response;
try {
java.security.AccessController.doPrivileged(
(java.security.PrivilegedExceptionAction<Void>) () -> {
internalDoFilter(req,res);
return null;
}
);
} catch( PrivilegedActionException pe) {
Exception e = pe.getException();
if (e instanceof ServletException)
throw (ServletException) e;
else if (e instanceof IOException)
throw (IOException) e;
else if (e instanceof RuntimeException)
throw (RuntimeException) e;
else
throw new ServletException(e.getMessage(), e);
}
} else {
internalDoFilter(request,response);
}
}
private void internalDoFilter(ServletRequest request,
ServletResponse response)
throws IOException, ServletException {
if (pos < n) {
ApplicationFilterConfig filterConfig = filters[pos++];
try {
Filter filter = filterConfig.getFilter();
if (request.isAsyncSupported() && "false".equalsIgnoreCase(
filterConfig.getFilterDef().getAsyncSupported())) {
request.setAttribute(Globals.ASYNC_SUPPORTED_ATTR, Boolean.FALSE);
}
if( Globals.IS_SECURITY_ENABLED ) {
final ServletRequest req = request;
final ServletResponse res = response;
Principal principal =
((HttpServletRequest) req).getUserPrincipal();
Object[] args = new Object[]{req, res, this};
SecurityUtil.doAsPrivilege ("doFilter", filter, classType, args, principal);
} else {
filter.doFilter(request, response, this);
}
} catch (IOException | ServletException | RuntimeException e) {
throw e;
} catch (Throwable e) {
e = ExceptionUtils.unwrapInvocationTargetException(e);
ExceptionUtils.handleThrowable(e);
throw new ServletException(sm.getString("filterChain.filter"), e);
}
return;
}
.......
}
总结
二者的区别: 关系
- 过滤器是依赖容器,针对进入servlet前的请求,处理这些request,而拦截器是针对进入容器以后controller前的,可以说是过滤器包含了拦截器,拦截器是spring里面的
实现 - 过滤器是基于doFilter方法里面
filterChain.doFilter(servletRequest,servletResponse);
进行回调,实际上是调用ApplicationFilterChain 的doFilter方法,里面记录了一个有多少个过滤器,每次调用每次计数器加1,执行下一个过滤器。
|