过滤器
-
实现
implements javax.servlet.Filter、XML中配置filter信息。
重写init、doFilter、destroy三个方法
-
void init(FilterConfig var1) throws ServletException:初始化Filter,在servlet容器启动时执行且只在此时启动一次。(后续 不过滤指定请求 会用到) -
void doFilter(ServletRequest var1, ServletResponse var2, FilterChain var3) throws IOException, ServletException:实现过滤功能,可以在请求前预处理,也可以请求后处理,分界线是chain.doFilter()。 -
void destroy():用于Filter销毁前,可用于资源回收。
-
-
使用
public class TestFilter implements Filter { private String excluded; private String[] excludedPages; @Override public void init(FilterConfig filterConfig) throws ServletException { excluded = filterConfig.getInitParameter("excluded"); //System.out.println(excluded); if (excluded!=null && excluded.length()>0){ excludedPages = excluded.split(","); } } @Override public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { HttpServletRequest httpServletRequest = (HttpServletRequest) servletRequest; HttpServletResponse httpServletResponse = (HttpServletResponse) servletResponse; boolean flag = false; for (String page : excludedPages){ if (httpServletRequest.getRequestURI().equals(page)){ flag = true; } } if (flag){ filterChain.doFilter(servletRequest, servletResponse); }else { HttpSession session = httpServletRequest.getSession(); Object curUser = session.getAttribute("curUser"); if (curUser==null){ httpServletResponse.sendRedirect("/user/login"); }else { filterChain.doFilter(servletRequest, servletResponse); } } } @Override public void destroy() { } }
拦截器
-
实现
implements org.springframework.web.servlet.HandlerInterceptor、spring-mvc.xml配置重写3个方法
boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception:如果返回true,则继续后续Interceptor的preHandle方法和controller;如果返回false,则后面的都不会执行。void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable ModelAndView modelAndView) throws Exception:如果preHandle返回false,这个方法不会执行。该方法执行在preHandle之后,视图渲染之前。多个Interceptor的postHandle的执行顺序,是:先声明的后执行。void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable Exception ex) throws Exception:该方法执行前提也是preHandle返回true。执行在请求结束之后,也就是渲染了视图之后才执行,可用于资源清理。类似于Filter的destroy。
-
使用
public class TestInterceptor implements HandlerInterceptor { @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { Object user = request.getSession().getAttribute("member"); if (user==null){ response.sendRedirect("/user/login"); return false; } return true; } @Override public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable ModelAndView modelAndView) throws Exception { } @Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable Exception ex) throws Exception { } }
拦截器和过滤器对比
| 对比 | 拦截器 | 过滤器 |
|---|---|---|
| 处理的目标 | 所有web请求 | Action-部分web请求 |
| 实现原理 | 函数回调 | Java反射(动态代理) |
| 应用场景 | 字符编码 | 拦截未登录用户 |
| URL级别的权限访问 | 审计日志 | |
| 过滤敏感词 | ||
| 压缩响应信息 | ||
| 执行顺序 | 根据filter-mapping配置的先后 | 按配置的顺序,可通过order控制 |
| 规范 | 在Servlet规范中定义,servlet容器支持 | spring容器内,spring框架支持 |
| 使用范围 | 只能用于Web程序 | 不仅Web程序,Application、swing都可以。 |
| 深度 | 只能在servlet前后使用 | 可以深入到方法前后,抛出异常前后。 |
Filter使用更加方便,Interceptor功能可以更细致的处理需求。
举例:计算请求响应时间。
Filter:
```
void doFilter() throw Exception{
long time = System.currentTimeMillis();
chain.doFilter();
System.out.println("请求时间为:"+ (System.currentTimeMillis()-time));
}
```
interceptor:
```
long time = System.currentTimeMillis();
@Override
public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o) throws Exception {
time = System.currentTimeMillis();
return true;
}
@Override
public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception {
System.out.println("Interceptor cost="+(System.currentTimeMillis()-start));
}
```
Interceptor需要一个提前声明全局变量来存值,这就有可能引起线程问题。可以通过TreadLocal解决。
相关