过滤器 Filter

一.Filter

1. Filter概述

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

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

2.过滤器的作用

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

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

3. 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才能访问目标资源
在这里插入图片描述

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 {

    }

}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值