欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

过滤器 Filter

程序员文章站 2022-05-23 08:38:34
...

一.Filter

1. Filter概述

Filter:一个实现了特殊接口(Filter)的Java类. 实现对请求资源(Servlet,JSP,HTML,CSS…)的过滤的功能.

过滤器是一个运行在服务器的程序, 优先于请求资源(Servlet或者jsp,html)之前执行. 过滤器是javaweb技术中最为实用的技术.

2.过滤器的作用

对目标资源(Servlet,jsp)进行过滤.  

应用场景:登录权限检查,解决网站乱码,过滤敏感字符 ...       

3. Filter使用

过滤器 Filter

3.1 配置文件方式

  1. 创建一个类实现Filter接口
public class FilterDemo01 implements Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {

    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        System.out.println("FilterDemo01 收到了请求...");
        filterChain.doFilter(servletRequest,servletResponse);
    }

    @Override
    public void destroy() {

    }
}
  1. 在web.xml里面进行配置
    <!--注册filter-->
    <filter>
        <filter-name>FilterDemo01</filter-name>
        <filter-class>com.filter.FilterDemo01</filter-class>
    </filter>

    <!--配置filter过滤器-->
    <filter-mapping>
        <filter-name>FilterDemo01</filter-name>
        <url-pattern>/demo01</url-pattern>
    </filter-mapping>

3.2注解方式

  1. 创建一个类实现Filter接口
  2. 在这个类上面添加@WebFilter(“拦截的路径”)
@WebFilter("/demo02")
public class FilterDemo02 implements Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {

    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        System.out.println("FilterDemo02 收到了请求...");
        filterChain.doFilter(servletRequest,servletResponse);

    }

    @Override
    public void destroy() {

    }
}

4. Filter的生命周期

4.1Filter生命周期介绍

过滤器从 创建 到 销毁 的过程   

4.2 生命周期方法

init(FilterConfig):初始化     

doFilter(ServletReqeust req,ServletResponse resp,FilterChain chain):执行过滤的方法  

destroy():销毁

4.3Filter生命周期描述

  1. 服务器启动的时候, 调用init()方法进行初始化【调用一次】
  2. 任何一次请求资源, 都会调用doFilter()方法进行过滤【前提是过滤器的路径和请求资源路径相匹配】
  3. 服务器正常关闭或者项目从服务器移除, 会调用destory()方法进行销毁【调用一次】

4.4 FilterConfig

获得过滤器的初始化参数

  • 配置初始化参数
    <filter>
        <filter-name>FilterDemo03</filter-name>
        <filter-class>com.filter.FilterDemo03</filter-class>
        <!--配置过滤器的初始化参数-->
        <init-param>
            <param-name>aKey</param-name>
            <param-value>aaa</param-value>
        </init-param>
    </filter>
    <filter-mapping>
        <filter-name>FilterDemo03</filter-name>
        <url-pattern>/demo03</url-pattern>
    </filter-mapping>
public class FilterDemo03 implements Filter {
    /**
     * 初始化的方法
     * 调用时机:服务器启动时,调用init()方法,初始化过滤器
     * 调用次数:1次
     *
     * FilterConfig 过滤器的配置对象
     * @param filterConfig
     * @throws ServletException
     */
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        System.out.println("init()...5555+"+filterConfig.getInitParameter("aKey"));
    }

    /**
     * 过滤的方法
     * 调用时机:每一次请求,且请求的路径满足过滤器的配置路径,执行doFilter()方法
     * 调用次数:请求几次调用几次
     *
     * @param servletRequest
     * @param servletResponse
     * @param filterChain
     * @throws IOException
     * @throws ServletException
     */
    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        System.out.println("FilterDemo03 收到了请求..");
        filterChain.doFilter(servletRequest,servletResponse);
    }


    /**
     * 销毁的方法
     * 调用时机:服务器正常关闭,执行destroy()方法,销毁过滤器
     * 调用次数:1次
     */
    @Override
    public void destroy() {
        System.out.println("destroy()...");
    }
}

5.映射路径

假设有一个管理员权限的过滤器,它应该对用户发出的管理员功能的请求进行条件的过滤。但是当用户发出登录、注册等请求的时候,不应该进行过滤。所以我们过滤器,应该有选择的过滤器请求。这就需要学习配置过滤器不同的映射路径,从而让过滤器过滤希望过滤器的请求。

  • 完全路径匹配, 以"/"开始

      /demo01 ---> 过滤器只能拦截路径/demo01; 
    
  • 目录匹配:以"/"开始 以 *结束 .

       /* --->当前项目下的所有的路径都可以拦截;   /aa/*  ---> 可以拦截 /aa/bb, /aa/bb/cc
    
  • 扩展名匹配:以"*"开始 例如: *.jsp *.do

      *.do--->可以拦截路径的后缀是 do的 ;  *.jsp--->拦截所有JSP
    

6.拦截方式

有了上面学习的映射路径,我们可以控制过滤器过滤指定的内容,但是我们在访问资源的时候,并不是每次都是之间访问,有时是以转发的方式访问的,这就需要我们要让过滤器可以区分不同的访问资源的方式,有不同的拦截方式。 是通过 DispatcherType 来指定的.

  • DispatcherType.REQUEST

      默认值,过滤从浏览器发送过来的请求和重定向  不过滤转发
    
  • DispatcherType.FORWARD

      只过滤转发过来的请求  
    

注意:
一般情况下, 我们不会过滤转发的, 因为转发是服务器内部行为, 使用默认值就好了

6. 过滤器链

过滤器链作用:当一个filter收到请求的时候,调用chain.doFilter才可以访问下一个匹配的filter,若当前的filter是最后一个filter,调用chain.doFilter才能访问目标资源
过滤器 Filter

7.统一全网站中文乱码的处理

在整个网站中,可能会有get请求或post请求向服务器提交参数.参数中往往有中文信息.在后台每个Servlet中都需要去处理乱码.

我们想做的是:请求到达Servlet中.就可以直接调用getParameter方法获得请求参数,请求参数已经没有乱码了.

package com.itheima.web.filter;

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

@WebFilter("/*")
public class CodeFilter implements Filter {
    public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
        //1.强转两个参数
        HttpServletRequest request = (HttpServletRequest) req;
        HttpServletResponse response = (HttpServletResponse) resp;
        //2.处理乱码(请求和响应)
        request.setCharacterEncoding("utf-8");
        response.setContentType("text/html;charset=utf-8");
        //3.放行
        chain.doFilter(request, response);
    }

    public void destroy() {
    }


    public void init(FilterConfig config) throws ServletException {

    }

}

package com.filter;

import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

@WebFilter("/*")
public class CodeFilter02 implements Filter {
    @Override
    public void destroy() {
    }

    @Override
    public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
        //强转两个参数
        HttpServletRequest request = (HttpServletRequest) req;
        HttpServletResponse response = (HttpServletResponse) resp;
        //1.使用jdk的动态代理创建request代理对象
        HttpServletRequest proxyRequest = (HttpServletRequest) Proxy.newProxyInstance(request.getClass().getClassLoader(), request.getClass().getInterfaces(), new InvocationHandler() {
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                //增强getParameter方法
                if ("getParameter".equals(method.getName())){
                    if ("post".equalsIgnoreCase(request.getMethod())){
                        request.setCharacterEncoding("utf-8");
                        response.setContentType("text/html;charset=utf-8");
                        return method.invoke(request,args);
                    }
                    return method.invoke(request,args);
                }
                return method.invoke(request,args);
            }
        });
        //放行
        chain.doFilter(proxyRequest, resp);
    }

    @Override
    public void init(FilterConfig config) throws ServletException {

    }

}

相关标签: Filter 过滤器