Java体系知识之过滤器Filter

162 阅读5分钟

Java体系知识之过滤器Filter

1 技术简介

 (1)过滤器:
     净水器
     空气净化器
     ...
 (2)JavaWeb组件:
     Servlet
     Filter
     Listener
 (3)作用:
     适合做一些通用的操作
     
     A.普通意义的公共代码:
         跨域请求处理;
         字符编码;
     B.逻辑方面的公共代码:
         登录访问控制:根据是否登录判断
             若已登录过,可允许继续访问;
             若未登录,不允许继续访问;
         权限访问控制:根据是否拥有权限判断
             若已拥有权限,可允许访问;
             若不拥有权限,不允许访问;

2 过滤器使用步骤(重点)

2.1 使用步骤

 (1)创建一个类,实现Filter接口
 (2)重写方法
 (3)配置过滤器:
     web.xml;
     注解;

2.2 案例

 package com.javasm.filter.basic;
 ​
 import javax.servlet.*;
 import javax.servlet.annotation.WebFilter;
 import java.io.IOException;
 ​
 /**
  * @author: ShangMa
  * @className: MyFilterDemo01
  * @description: 过滤器使用步骤
  * @date: 2022/8/31 11:22
  */
 @WebFilter("/demo01")
 public class MyFilterDemo01 implements Filter {
     /**
      * 过滤器使用步骤:
      * (1)创建一个类,实现Filter接口
      * (2)重写方法
      * (3)配置过滤器:
      *  web.xml;
      *  注解;
      *
      */
     @Override
     public void init(FilterConfig filterConfig) throws ServletException {
     }
 ​
     @Override
     public void destroy() {
     }
 ​
     @Override
     public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
         System.out.println("执行MyFilterDemo01.doFilter()");
 ​
     }
 }

3 过滤器执行过程(重点)

3.1 内容概述

 (1)当请求过来时,先进入过滤器执行
 (2)若过滤器有放行代码,再找对应的Servlet执行
 (3)最后执行放行代码下面的语句

3.2 案例

 package com.javasm.filter.basic;
 ​
 import javax.servlet.*;
 import javax.servlet.annotation.WebFilter;
 import java.io.IOException;
 ​
 /**
  * @author: ShangMa
  * @className: MyFilterDemo02
  * @description: 过滤器执行过程
  * @date: 2022/8/31 11:22
  */
 @WebFilter("/demo02")
 public class MyFilterDemo02 implements Filter {
     /**
      * 过滤器执行过程:
      *  当请求过来时,先进入过滤器执行;
      *  若过滤器有放行代码,再找对应的Servlet执行;
      *  最后执行放行代码下面的语句;
      */
 ​
     @Override
     public void init(FilterConfig filterConfig) throws ServletException {
     }
 ​
     @Override
     public void destroy() {
     }
 ​
     @Override
     public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
         System.out.println("执行MyFilterDemo02.doFilter()");
         // 放行代码
         filterChain.doFilter(servletRequest,servletResponse);
         System.out.println("执行MyFilterDemo02过滤器放行代码下面的语句");
     }
 }

4 过滤器生命周期

4.1 内容概述

 (1)服务器启动时,创建Filter实例,触发init方法执行
 (2)当有请求访问时,执行doFilter方法
 (3)服务器正常关闭时,销毁Filter实例,触发destroy方法执行

4.2 案例

 package com.javasm.filter.basic;
 ​
 import javax.servlet.*;
 import javax.servlet.annotation.WebFilter;
 import java.io.IOException;
 ​
 /**
  * @author: ShangMa
  * @className: MyFilterDemo03
  * @description: 过滤器生命周期
  * @date: 2022/8/31 15:21
  */
 @WebFilter("/demo03")
 public class MyFilterDemo03 implements Filter {
     /**
      * 过滤器生命周期:
      *  服务器启动时,创建Filter实例,触发init方法执行;
      *  当有请求访问时,执行doFilter方法;
      *  服务器正常关闭时,销毁Filter实例,触发destroy方法执行;
      */
     @Override
     public void init(FilterConfig filterConfig) throws ServletException {
         System.out.println("服务器启动时,创建Filter实例,触发init方法执行");
     }
 ​
     @Override
     public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
         System.out.println("执行MyFilterDemo03.doFilter()");
         // 放行代码
         // filterChain.doFilter(servletRequest, servletResponse);
 ​
     }
 ​
     @Override
     public void destroy() {
         System.out.println("服务器正常关闭时,销毁Filter实例,触发destroy方法执行");
     }
 }

5 过滤器配置详解

5.1 内容概述

 (1)拦截具体资源:比如 /demo04
 (2)拦截指定目录:比如 /menu/*
 (3)拦截指定后缀:比如 *.do
 (4)拦截所有请求资源:比如 /*

6 过滤器链

 (1)当经过分析,发现该案例中需要使用多个过滤器时,则配置多个多滤器即可
 (2)当给多个过滤器配置相同的访问路径后,执行顺序:
     注解配置:按照类名的字符串比较规则比较,值小的先执行;
     web.xml:哪个过滤器的配置代码在前面,先执行哪个过滤器;

7 综合案例(重点)

7.1 处理请求数据乱码

7.1.1 MyFilter1

 package com.javasm.filter.case1;
 ​
 import javax.servlet.*;
 import javax.servlet.annotation.WebFilter;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 import java.io.IOException;
 ​
 /**
  * @author: ShangMa
  * @className: MyFilter1
  * @description: 处理中文乱码
  * @date: 2022/8/31 16:19
  */
 @WebFilter("/*")
 public class MyFilter implements Filter {
     @Override
     public void init(FilterConfig filterConfig) throws ServletException {
     }
 ​
     @Override
     public void destroy() {
     }
 ​
     @Override
     public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
         servletRequest.setCharacterEncoding("utf-8");
         filterChain.doFilter(servletRequest,servletResponse);
     }
 }

7.2 登录访问控制&权限访问控制

(1)场景:
	用户执行登录->访问其他模块
	
	问题:
		未登录->不能访问其他模块   给用户设置提示信息
		无权限->不能访问对应模块   给用户设置提示信息
(2)过滤器:
	未登录->不能访问其他模块   给用户设置提示信息
	无权限->不能访问对应模块   给用户设置提示信息
(3)过程:
	模拟:
		filter
		servlet:假设用户登录成功,设置基础用户数据和用户权限数据绑定到session对象

7.2.1 案例实现

7.2.1 MyFilter1

package com.javasm.filter.case2.filter;

import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * @author: ShangMa
 * @className: MyFilter1
 * @description: 处理中文乱码
 * @date: 2022/8/31 16:19
 */
@WebFilter("/*")
public class MyFilter1 implements Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
    }

    @Override
    public void destroy() {
    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        System.out.println("1111");
        HttpServletRequest req = (HttpServletRequest) servletRequest;
        HttpServletResponse resp = (HttpServletResponse) servletResponse;
        servletRequest.setCharacterEncoding("utf-8");
        String requestURI = req.getRequestURI();
        if("/login".equals(requestURI) || requestURI.endsWith(".html")){
            filterChain.doFilter(servletRequest,servletResponse);
        }
    }
}

7.2.2 MyFilter2

package com.javasm.filter.case2.filter;

import com.alibaba.fastjson.JSON;
import com.javasm.filter.entity.CodeAndMsg;
import com.javasm.filter.entity.ReturnEntity;

import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
import java.io.PrintWriter;

/**
 * @author: ShangMa
 * @className: MyFilter2
 * @description: 处理用户是否登录
 * @date: 2022/8/31 16:20
 */
@WebFilter("/*")
public class MyFilter2 implements Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
    }

    @Override
    public void destroy() {
    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        HttpServletRequest req = (HttpServletRequest) servletRequest;
        HttpServletResponse resp = (HttpServletResponse) servletResponse;
        // 获取值
        HttpSession session = req.getSession();
        String userName = (String) session.getAttribute("userName");
        // 根据路径判断
        String requestURI = req.getRequestURI();
        // 白名单
        if ("/login".equals(requestURI) || requestURI.endsWith(".html")) {
            // 执行登录  放行
            filterChain.doFilter(servletRequest, servletResponse);
        } else {
            // 不是执行登录 是否已登录
            if (userName != null) {
                filterChain.doFilter(servletRequest, servletResponse);
            } else {
                // 未登录 设置提示信息
                ReturnEntity re = new ReturnEntity();
                re.setReturnCode(CodeAndMsg.NO_LOGIN.getReturnCode());
                re.setReturnMsg(CodeAndMsg.NO_LOGIN.getReturnMsg());
                resp.setContentType("application/json;charset=utf-8");
                PrintWriter writer = resp.getWriter();
                writer.print(JSON.toJSONString(re));
                writer.flush();
                writer.close();
            }
        }
    }
}

7.2.3 MyFilter3

package com.javasm.filter.case2.filter;

import com.alibaba.fastjson.JSON;
import com.javasm.filter.entity.CodeAndMsg;
import com.javasm.filter.entity.ReturnEntity;

import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.List;

/**
 * @author: ShangMa
 * @className: MyFilter3
 * @description: 处理用户是否有权限
 * @date: 2022/8/31 16:20
 */
@WebFilter("/*")
public class MyFilter3 implements Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
    }

    @Override
    public void destroy() {
    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        HttpServletRequest req = (HttpServletRequest) servletRequest;
        HttpServletResponse resp = (HttpServletResponse) servletResponse;
        HttpSession session = req.getSession();
        List<String> authList = (List<String>) session.getAttribute("authList");
        // 获取请求路径
        String requestURI = req.getRequestURI();
        // 判断
        if ("/login".equals(requestURI)) {
            filterChain.doFilter(servletRequest, servletResponse);
        } else {
            // 判断是否有权限
            if(authList.contains(requestURI)){
                // 有权限
                filterChain.doFilter(servletRequest, servletResponse);
            }else{
                // 无权限  设置提示信息
                ReturnEntity re = new ReturnEntity();
                re.setReturnCode(CodeAndMsg.NO_AUTH.getReturnCode());
                re.setReturnMsg(CodeAndMsg.NO_AUTH.getReturnMsg());
                resp.setContentType("application/json;charset=utf-8");
                PrintWriter writer = resp.getWriter();
                writer.print(JSON.toJSONString(re));
                writer.flush();
                writer.close();
            }
        }
    }
}

7.2.4 LoginServlet

package com.javasm.filter.case2.servlet;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

/**
 * @author: ShangMa
 * @className: LoginServlet
 * @description: 控制层-用户注册
 * @date: 2022/8/31 16:13
 */
@WebServlet("/login")
public class LoginServlet extends HttpServlet {
    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println(req.getParameter("userName"));
        // 假设通过判断,该用户可以登录
        boolean isLogin = true;
        if (isLogin) {
            HttpSession session = req.getSession();
            // 往session对象上绑定基础的用户数据->该用户是否已登录
            session.setAttribute("userName", "tom");
            // 往session对象上绑定用户权限数据->该用户是否有对应权限
            List<String> authList = new ArrayList<>();
            authList.add("/menu/query");
            authList.add("/menu/queryOneMenu");
            session.setAttribute("authList", authList);
        }
    }
}