JavaWeb-Filter

1 过滤器概述

oa项目还有什么缺陷?

目前oa项目的功能不多,Servlet也不多,但若功能很多,假如还有EmpServlet、OrderServlet等等,每一个Servlet都是处理自己相关的业务。但它们有相同的地方,在执行之前都要判断用户是否登录了,如果用户登录可以继续操作,如果没有需要登录。这段处理是固定的,大家都一样,怎么解决这个问题??可以使用Filter过滤器。

Filter过滤器是什么,有什么用,执行原理是什么?

  • Filter是过滤器
  • 可以在Servlet这个目标程序执行之前添加代码,也可以在执行之后添加代码,之前之后都可以过滤
  • 一般情况下都是在过滤器当中编写公共代码。

一个过滤器怎么写?

第一步:编写一个Java类实现一个接口:jakarta.servlet.Filter。并且实现这个接口中的所有方法。

  • init方法:在Filter对象第一次被创建之后调用,并且只调用一次
  • doFilter方法:只要用户发送一次请求,则执行一次,发送N此执行N次,在这个方法中编写过滤规则。
  • destroy方法:在Filter对象被释放/销毁之前调用,并且只调用一次。

第二步:在web.xml文件对FIlter进行配置,和Servlet类似,或者使用注解进行配置。

注意:

  • Servlet对象默认情况下,在服务器启动的时候是不会创建对象的。
  • Filter对象默认情况下,在服务器启动的时候会创建对象
  • Servlet是单例的

小小演示一波:

随便写两个Servlet,然后写个Filter,Filter如下:

package com.itzw.javaweb.servlet;

import jakarta.servlet.*;
import jakarta.servlet.annotation.WebFilter;

import java.io.IOException;

@WebFilter("*.do")
public class Filter1 implements Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        System.out.println("init方法执行了。。");
    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain)
            throws IOException, ServletException {
        System.out.println("doFilter执行了。。");
        //执行下一个过滤器,如果下一个不是过滤器则执行目标程序servlet
        filterChain.doFilter(servletRequest,servletResponse);
        System.out.println("doFilter结束了。。");
    }

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

注意要想执行Servlet,在doFilter方法中要写上chain.doFilter,它会接着执行下面的程序。而在注解中,可以进行模糊匹配比如在Servlet的注解可以在后面加个“.do”,就可以使用“*/”进行模糊匹配或者像之前一样“/dept/*”,或者可以匹配所有路径“/*”,根据需求来。

在web.xml文件中进行配置的时候,Filter的执行顺序是什么?

  • 依靠filter-mapping标签的配置位置,越靠上优先级越高。
  • 过滤器的调用顺序遵循栈数据结构

使用注解@WebFilter的时候,执行顺序是怎样的?

  • 执行顺序是比较Filter的类名
  • 比如Filter1和Filter2,优先执行Filter1

Filter的声明周期:

  • 和Servlet的声明周期一致
  • 唯一的区别是:Filter默认情况下,在服务器启动阶段就实例化,Servlet不会。

Filter过滤器这里有一个设计模式:

  • 责任链设计模式
  • 过滤器的最大优点:在编译阶段不会确定调用顺序,因为顺序是web.xml文件中的配置决定的,我们可以随时更改,不需要改代码。
  • 配置格式如下:
  •     <!--Filter1-->
        <filter>
            <filter-name>filter1</filter-name>
            <filter-class>com.itzw.javaweb.servlet.Filter1</filter-class>
        </filter>
        <filter-mapping>
            <filter-name>filter1</filter-name>
            <url-pattern>*.do</url-pattern>
        </filter-mapping>
    
        <!--Filter2-->
        <filter>
            <filter-name>filter2</filter-name>
            <filter-class>com.itzw.javaweb.servlet.Filter2</filter-class>
        </filter>
        <filter-mapping>
            <filter-name>filter2</filter-name>
            <url-pattern>*.do</url-pattern>
        </filter-mapping>

    只要将Filter2中的filter-mapping放到上面就可以改变顺序

2 使用过滤器改造oa项目

本次我们对是否能访问资源进行过滤,也就是当访问一个资源时是否需要登录,因为这种情况很多,一个网站的资源数量相当多,每次都要我们自己判断太麻烦,不如放在过滤器:

package com.itzw.oa.web.action;

import jakarta.servlet.*;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.servlet.http.HttpSession;

import java.io.IOException;

public class LoginCheckFilter implements Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
    }

    @Override
    public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)
            throws IOException, ServletException {
        HttpServletRequest request = (HttpServletRequest) req;
        HttpServletResponse response = (HttpServletResponse) res;

        //获取请求路径
        String servletPath = request.getServletPath();
        HttpSession session = request.getSession(false);
        if ("/index.jsp".equals(servletPath) || "/welcome".equals(servletPath) ||
               "/user/login".equals(servletPath) || "/user/exit".equals(servletPath) ||
                "/error.jsp".equals(servletPath) ||
                session != null && session.getAttribute("username") != null){
            //有这个用户才能进行下面的操作
            chain.doFilter(request,response);
        }else {
            //没有这个用户,跳转到登录界面
            response.sendRedirect(request.getContextPath() + "/index.jsp");
        }
    }

    @Override
    public void destroy() {
    }
}

本次的过滤路径写的是:“/*”,也就是全部路径,注意,并不是全部路径都要过滤,比如登录界面,错误界面,欢迎页面等等。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值