filter过滤器基本使用

2019-10-04  本文已影响0人  _FireFly_

1.Filter Tomcat提供的一个组件
2.Filter是一个特殊的Servlet
3.基本使用
创建一个类 继承HttpFilter(Tomcat9之后) 实现Filter接口(Tomcat9之前)
重写方法doFilter方法
三个参数HttpServletRequest HttpServletResponse FilterChain
配置xml文件
4.管理机制
继承或实现的关系
filter对象是单例 生命周期托管的方式 立即加载的方式
发送请求 从浏览器出发 会经过filter
从服务器内部出发 转发默认是不经过filter(设置) 重定向经过filter
5.过滤器链
好多个filter对象 都处理相同的请求 /*
我们经过filter不是目的 找到真实的资源
经过的filter会在真实资源执行之前做些事情 之后也会做事情

1.先自定义一个class类,继承HttpFilter(在Tomcat9.0之后是继承HttpFilter,在Tomcat9.0之前是实现Filter接口)这里以Tomcat9.0为例

package filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
import java.util.Enumeration;

//小护士
public class FilterOne extends HttpFilter {

    public void init(FilterConfig filterConfig) throws ServletException {
        Enumeration en = filterConfig.getInitParameterNames();
        while(en.hasMoreElements()){
            String key = (String)en.nextElement();
            String value = filterConfig.getInitParameter(key);
            System.out.println(key+"--"+value);
        }
    }

    protected void doFilter(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws IOException, ServletException {
        System.out.println("我是filter 找我干嘛呀");

        HttpSession session = request.getSession();
        String aname = (String)session.getAttribute("aname");
        //获取请求路径
        String uri = request.getRequestURI();
        //先判断大前提  请求的时候 是否包含index login
        if(uri.contains("index") || uri.contains("login")){
             //这俩个请求是登陆请求,所以直接放行,要不然死循环,session中永远不会有值
            //放行 此时还没有真正做登录判断
            chain.doFilter(request,response);
        }else{
            //应该是登录成功之后的某一个功能
            if(aname!=null){
                chain.doFilter(request,response);
            }else{
                request.setAttribute("result","登录已超时,请重新登录");
                request.getRequestDispatcher("index.jsp").forward(request,response);
            }
        }

        //1.直接给予响应  自己拼接字符串
        //response.getWriter().write("<>");
        //2.可以(请求)转发
        //request.getRequestDispatcher("路径").forward(request,response);
        //3.可以(请求)重定向
        //response.sendRedirect("路径");
        //4.可以放行
        //chain.doFilter(request,response);
    }
}

2.自定义一个class类,继承HttpServlet

package controller;

import service.AtmService;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;

//目标
public class LoginController extends HttpServlet {

    private AtmService service = new AtmService();

    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        request.setCharacterEncoding("UTF-8");
        //1.获取请求参数
        String aname = request.getParameter("aname");
        String apassword = request.getParameter("apassword");
        //2.调用业务方法干活儿
        String result = service.login(aname,apassword);
        //3.给予响应    转发
        if(result.equals("登录成功")) {
            //将人名存储在session作用域内啦
            HttpSession session = request.getSession();
            session.setAttribute("aname",aname);
            session.setMaxInactiveInterval(8);  <!--设置session的有效期-->
            request.getRequestDispatcher("welcome.jsp").forward(request, response);
        }else {
            request.setAttribute("result",result);
            request.getRequestDispatcher("index.jsp").forward(request,response);
        }
    }
}

3.在web.xml中配置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">


       <!--处理login请求的servlet-->
    <servlet>
        <servlet-name>login</servlet-name>
        <servlet-class>controller.LoginController</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>login</servlet-name>
        <url-pattern>/login</url-pattern>
    </servlet-mapping>

       <!--处理项目下所有请求的filter-->
    <filter>
        <filter-name>filterOne</filter-name>
        <filter-class>filter.FilterOne</filter-class>
        <init-param>
            <param-name>key1</param-name>
            <param-value>value1</param-value>
        </init-param>
        <init-param>
            <param-name>key2</param-name>
            <param-value>value2</param-value>
        </init-param>
        <init-param>
            <param-name>key3</param-name>
            <param-value>value3</param-value>
        </init-param>
    </filter>
    <filter-mapping>
        <filter-name>filterOne</filter-name>
        <url-pattern>/*</url-pattern>                  <!--/代码项目根目录的意思,/*代表项目根目录下的所有请求-->
        <!--<dispatcher>REQUEST</dispatcher>-->        <!-- 默认不填写是这个-->
        <!--<dispatcher>FORWARD</dispatcher>-->        <!-- 如果填写了这个,则只拦截forward请求-->
        <!-- 如果俩个请求都想拦截,则两个都需要写,只写一个会默认覆盖其他的-->
         <dispatcher>REQUEST</dispatcher>
         <dispatcher>FORWARD</dispatcher>
    </filter-mapping>
</web-app>

请求转发和重定向在过滤器中的过程

转发和重定向经过过滤器的过程

当同时存在多个filter时候:

web.xml

<?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>three</filter-name>
        <filter-class>filter.FilterThree</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>three</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
    <filter>
        <filter-name>one</filter-name>
        <filter-class>filter.FilterOne</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>one</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
    <filter>
        <filter-name>two</filter-name>
        <filter-class>filter.FilterTwo</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>two</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

    <servlet>
        <servlet-name>login</servlet-name>
        <servlet-class>controller.LoginController</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>login</servlet-name>
        <url-pattern>/login</url-pattern>
    </servlet-mapping>
</web-app>
过滤器链
在控制台的输出结果
在控制台的输出结果

FilterOne.java

public class FilterOne extends HttpFilter {

    protected void doFilter(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws IOException, ServletException {
        System.out.println("我是FilterOne放行之前的事情,我执行啦");
        chain.doFilter(request,response);
        System.out.println("我是FilterOne放行之后的事情,啦啦啦");
    }
}

FilterTwo.java

public class FilterTwo extends HttpFilter {

    protected void doFilter(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws IOException, ServletException {
        System.out.println("我是FilterTwo放行之前的事情,我执行啦");
        chain.doFilter(request,response);
        System.out.println("我是FilterTwo放行之后的事情,啦啦啦");
    }
}

FilterThree.java

public class FilterThree extends HttpFilter {

    protected void doFilter(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws IOException, ServletException {
        System.out.println("我是FilterThree放行之前的事情,我执行啦");
        chain.doFilter(request,response);
        System.out.println("我是FilterThree放行之后的事情,啦啦啦");
    }
}

如果有多个过滤器,则chain.doFilter(request,response)会调用下一个过滤器,如果没有,则调用目标方法
过滤器链在执行的时候,他的本质是方法的压栈和弹栈,也就是只有dofilter方法中的chain.doFilter(request,response)执行完之后,才会执行后续的代码。在此期间,过滤器会一个等一个。

上一篇下一篇

猜你喜欢

热点阅读