Filter简介

image.png
Filter也称之为过滤器,它是Servlet技术中最实用的技术,Web开发人员通过Filter技术,对web服务器管理的所有web资源:例如Jsp, Servlet, 静态图片文件或静态 html 文件等进行拦截,从而实现一些特殊的功能。例如实现URL级别的权限访问控制、过滤敏感词汇、压缩响应信息等一些高级功能。

它主要用于对用户请求进行预处理,也可以对HttpServletResponse进行后处理。使用Filter的完整流程:Filter对用户请求进行预处理,接着将请求交给Servlet进行处理并生成响应,最后Filter再对服务器响应进行后处理。

Filter功能

在HttpServletRequest到达 Servlet 之前,拦截客户的HttpServletRequest 。根据需要检查HttpServletRequest,也可以修改HttpServletRequest 头和数据。
在HttpServletResponse到达客户端之前,拦截HttpServletResponse 。根据需要检查HttpServletResponse,也可以修改HttpServletResponse头和数据。

Filter如何工作的?

Filter接口中有一个doFilter方法,当我们编写好Filter,并配置对哪个web资源进行拦截后,WEB服务器每次在调用web资源的service方法之前,都会先调用一下filter的doFilter方法,因此,在该方法内编写代码可达到如下目的:
调用目标资源之前,让一段代码执行。
是否调用目标资源(即是否让用户访问web资源)。
调用目标资源之后,让一段代码执行。
web服务器在调用doFilter方法时,会传递一个filterChain对象进来,filterChain对象是filter接口中最重要的一个对象,它也提供了一个doFilter方法,开发人员可以根据需求决定是否调用此方法,调用该方法,则web服务器就会调用web资源的service方法,即web资源就会被访问,否则web资源不会被访问。

Filter接口

  1. public interface Filter {
  2. default void init(FilterConfig filterConfig) throws ServletException {
  3. }
  4. void doFilter(ServletRequest var1, ServletResponse var2, FilterChain var3) throws IOException, ServletException;
  5. default void destroy() {
  6. }
  7. }

FIlter案例

拦截用户,检查是否登录

  1. //filterName: 过滤器名称
  2. //urlPatterns: 过滤器所拦截的资源路径URL
  3. @WebFilter(filterName = "loginCheckFilter",urlPatterns = "/*")
  4. @Slf4j
  5. public class LoginCheckFilter implements Filter{
  6. //路径匹配器,支持通配符
  7. public static final AntPathMatcher PATH_MATCHER = new AntPathMatcher();
  8. @Override
  9. public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
  10. HttpServletRequest request = (HttpServletRequest) servletRequest;
  11. HttpServletResponse response = (HttpServletResponse) servletResponse;
  12. //1、获取本次请求的URI
  13. String requestURI = request.getRequestURI();// /backend/index.html
  14. log.info("拦截到请求:{}",requestURI);
  15. //定义不需要处理的请求路径
  16. String[] urls = new String[]{
  17. "/employee/login",
  18. "/employee/logout",
  19. "/backend/**",
  20. "/front/**"
  21. };
  22. //2、判断本次请求是否需要处理
  23. boolean check = check(urls, requestURI);
  24. //3、如果不需要处理,则直接放行
  25. if(check){
  26. log.info("本次请求{}不需要处理",requestURI);
  27. filterChain.doFilter(request,response);
  28. return;
  29. }
  30. //4、判断登录状态,如果已登录,则直接放行
  31. if(request.getSession().getAttribute("employee") != null){
  32. log.info("用户已登录,用户id为:{}",request.getSession().getAttribute("employee"));
  33. BaseContext.setCurrentId((Long) request.getSession().getAttribute("employee"));
  34. filterChain.doFilter(request,response);
  35. return;
  36. }
  37. log.info("用户未登录");
  38. //5、如果未登录则返回未登录结果,通过输出流方式向客户端页面响应数据
  39. response.getWriter().write(JSON.toJSONString(R.error("NOTLOGIN")));
  40. return;
  41. }
  42. /**
  43. * 路径匹配,检查本次请求是否需要放行
  44. * @param urls
  45. * @param requestURI
  46. * @return
  47. */
  48. public boolean check(String[] urls,String requestURI){
  49. for (String url : urls) {
  50. boolean match = PATH_MATCHER.match(url, requestURI);
  51. if(match){
  52. return true;
  53. }
  54. }
  55. return false;
  56. }
  57. }