Java Web--Filter,过滤器

Filter 过滤器

1.基本使用

  1. 使用的实现接口在javax.servlet包下的接口Filter
@WebFilter("/*")
public class DemoFilter1 implements Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        System.out.println("init执行");
    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        System.out.println("doFilter执行");
    }

    @Override
    public void destroy() {
        System.out.println("destroy执行");
    }
}

注意实现javax.servlet包下的接口

在这里插入图片描述

  1. 实现的三个类

    • init
    • destory
    • doFilter
  2. filter配置两种方式

    方式一:配文件

    <?xml version="1.0" encoding="UTF-8"?>
    <web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
             version="4.0">
        <filter>
            <filter-name>filter</filter-name>
            <filter-class>com.liu.filter.DemoFilter1</filter-class>
        </filter>
        <filter-mapping>
            <filter-name>filter</filter-name>
            <url-pattern>/DemoController</url-pattern>
        </filter-mapping>
        <filter>
            <filter-name>filter2</filter-name>
            <filter-class>com.liu.filter.DemoFilter2</filter-class>
        </filter>
        <filter-mapping>
            <filter-name>filter2</filter-name>
            <url-pattern>/DemoController</url-pattern>
        </filter-mapping>
    </web-app>
    

​ 方式二:注解配置

在这里插入图片描述

2.servlet与filter区别

servlet与filter 相似点

  1. 符合特定标准之后,通过url出发java类中执行特定的方法
  2. 配置方式:都可以使用注解和配置文件
  3. 接口中的方法相似
    • init
    • destory
    • doFilter

filter的不同点

  1. 声明周期不同:

    • filter在服务器启动时,创建实例是全局变量,application的作用域;
    • servlet:创建服务器对象(application)的时候才被实例化
  2. 请求地址是否可以重复:

    • filter中,配置的请求地址可以重复,
    • servlet:配置的请求地址不可以重复,
    • filter配置的请求地址与servlet的配置的请求地址重复,是先进入filter在进入servlet
  3. filter过滤器

    • 实现Filter接口的类中有**FilterChain 过滤器链**(作用可以在行代码之前作出判断,是否进入下面代码)

    • FilterChain 的作用:让进来的代码继续执行

      @Override
      public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
          System.out.println("doFilter执行");
          chain.doFilter(request,response);//过滤器链执行该行代码,才能向下执行,否则不会向下执行
      }
      
    • 在servlet中可以使用重定向实现不同servlet容器的相互跳转

  4. filter可以配置多层过滤器,进入顺序有类型加载顺序决定的

    • 注解:按照包中的类名的排列顺序执行
    • wei.xml配置文件:按照配置文件读取的上下的顺序
  5. filter中,通常来配置通用的功能(公共的功能),通常使用*****,来实现扩大请求的进入范围
    在这里插入图片描述

应用:

  • servlet用来实现单个的功能

  • filter用来配置通用的功能

  1. 在doFilter中设置utf-8请求字符编码格式
  2. 设置跨域访问
  3. 访问控制
    • 以前在每一个servlet中都要判断用户是否登陆成功,这样重复重复性代码太多,
    • 使用filter实现访问控制,通过if判断来用户是否登陆

注意:

  • 进入静态资源,也进入过滤器

在这里插入图片描述

在这里插入图片描述

3.filter配置方式

1.精准定位

执行顺序:先走DemoFilter1,再走Demoservlet1

在这里插入图片描述

2./*

//servlet容器
@WebServlet("/myService/DemoController1")//DemoController1
@WebFilter("/myService/DemoController2")//DemoController2

//Filter过滤器
@WebFilter("/myService/DemoController2")//DemoFilter1
@WebFilter("/myService/*")//DemoFilter2

//url访问
//访问  /myService/DemoController1 会走DemoFilter2和DemoController1
//访问  /myService/DemoController2 会走 DemoFilter1,DemoFilter2和DemoController2


应用:过滤器的基本配置

使用过滤器的基本配置,配置请求字符集编码utf-8,跨域设置

@WebFilter("/*")
public class MyFilter1 implements Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {

    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        //使用过滤器的基本配置,配置请求字符集编码utf-8,跨域设置
        HttpServletRequest req=(HttpServletRequest)request;
        HttpServletResponse resp=(HttpServletResponse)response;
        //1.配置请求字符集编码utf-8
        req.setCharacterEncoding("utf-8");
        //2.跨域设置
        /* 允许跨域的主机地址 */
        resp.setHeader("Access-Control-Allow-Origin", "http://localhost:5173");
        /* 允许跨域的请求⽅法GET, POST, HEAD 等 */
        resp.setHeader("Access-Control-Allow-Methods", "*");
        /* 重新预检验跨域的缓存时间 (s) */
        resp.setHeader("Access-Control-Max-Age", "3600");
        /* 允许跨域的请求头 */
        resp.setHeader("Access-Control-Allow-Headers", "*");
        /* 是否携带cookie */
        resp.setHeader("Access-Control-Allow-Credentials", "true");
        chain.doFilter(req,resp);
    }

    @Override
    public void destroy() {

    }
}

MyFilter2:

访问权限控制:

方式一:通过注解上面的请求路径实现权限控制

  1. 代码:
@WebFilter("/mysevice/*")
public class MyFilter2 implements Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {

    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        //使用过滤器的基本配置,配置请求字符集编码utf-8,跨域设置
        HttpServletRequest req = (HttpServletRequest) request;
        HttpServletResponse resp = (HttpServletResponse) response;
        //访问权限控制
        HttpSession session = req.getSession();
        PnAdminUser paUser = (PnAdminUser) session.getAttribute("paUser");
        if (paUser != null) {
            chain.doFilter(req, resp);
        } else {
            System.out.println("没有登录");
            ReturnEntity re = new ReturnEntity();
            re.setReturnCode(ReturnCodeEnum.NO_LOGIN.getCode());
            re.setReturnMsg(ReturnCodeEnum.NO_LOGIN.getMsg());
            resp.setContentType("application/json;charset=utf-8");
            PrintWriter writer = resp.getWriter();
            writer.print(JSON.toJSONString(re));
            writer.close();
        }
    }

    @Override
    public void destroy() {

    }
}

  1. 请求路径
//菜单请求路径
@WebServlet("/mysevice/menus/*")

//过滤器
@WebFilter("/mysevice/*")

//登录请求路径
@WebServlet("/login")
  1. 流程图

在这里插入图片描述

方式二:通过请求地址判断配合前端push跳转

登录访问权限

描述:

前端作出请求,在过滤器中对所有的请求作出判断,不是login的给前端作出反馈,然后让前端根据响应码作出相应的跳转

@WebFilter("/*")
public class MyFilter2 implements Filter {


    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        //使用过滤器的基本配置,配置请求字符集编码utf-8,跨域设置
        HttpServletRequest req = (HttpServletRequest) request;
        HttpServletResponse resp = (HttpServletResponse) response;
        //访问权限控制
        HttpSession session = req.getSession();
        PnAdminUser paUser = (PnAdminUser) session.getAttribute("paUser");

        //通过白名单和黑名单设置访问权限
        String requestURI = req.getRequestURI();//获取当前请求路径: /day16/menus/query  有项目的servlet的项目名,有/*
        String contextPath = req.getServletPath();//获取servlet的项目配置路径: /login    没有项目的servlet的项目名,没有/*
        System.out.println(requestURI);
        System.out.println(contextPath);
        if ("/login".equals(contextPath)) {
            chain.doFilter(req, resp);
        } else {
            if (paUser != null) {
                chain.doFilter(req, resp);
            } else {
                System.out.println("没有登录");
                ReturnEntity re = new ReturnEntity();
                re.setReturnCode(ReturnCodeEnum.NO_LOGIN.getCode());
                re.setReturnMsg(ReturnCodeEnum.NO_LOGIN.getMsg());
                resp.setContentType("application/json;charset=utf-8");
                PrintWriter writer = resp.getWriter();
                writer.print(JSON.toJSONString(re));
                writer.close();
            }
        }
    }
}

侧边栏菜单模块控制权限控制

为了登录用户在main主页面中,通过url访问不属于自己的权限模块作出控制,

在登录用户的时候,通过不同用户的menu_id的访问权限查询菜单表中的url的路径存到list中,每次到了该过滤器都要遍历该用户的访问权限的url,

/**
 * @description: 对登录用户访问侧边栏菜单权限控制
 */
@WebFilter("/*")
public class MyFilter3 implements Filter {

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {

        HttpServletRequest req = (HttpServletRequest) request;
        HttpServletResponse resp = (HttpServletResponse) response;
        //访问权限控制
        HttpSession session = req.getSession();
        PnAdminUser paUser = (PnAdminUser) session.getAttribute("paUser");
        List<String> userMenuId = (List<String>) session.getAttribute("userMenuId");


        String requestURI = req.getRequestURI();//获取当前请求路径: /day16/menus/query  有项目的servlet的项目名,有/*
        String servletPath = req.getServletPath();//获取servlet的项目配置路径: /login    没有项目的servlet的项目名,没有/*
        System.out.println(requestURI);
        System.out.println(servletPath);
        //系统中存在的功能URL,但是在数据库中不存在,每个用户可以登录,登出,访问侧边栏
        if ("/login".equals(servletPath)||"/loginOut".equals(servletPath)||"/PnAdminMenu".equals(servletPath)) {
            chain.doFilter(req, resp);
        } else {
            //如果用户登录成功进入主菜单,在url列表中有,表示有此模块权限,可以访问
            //                        在url列表中没有,表示没有此模块全新啊,不可以访问
            if (userMenuId.contains(servletPath)) {
                chain.doFilter(req, resp);
            } else {
                System.out.println("没有权限");
                ReturnEntity re = new ReturnEntity();
                re.setReturnCode(ReturnCodeEnum.NO_PERMISSION.getCode());
                re.setReturnMsg(ReturnCodeEnum.NO_PERMISSION.getMsg());
                resp.setContentType("application/json;charset=utf-8");
                PrintWriter writer = resp.getWriter();
                writer.print(JSON.toJSONString(re));
                writer.close();
            }
        }
    }
}

粒度

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值