servlet中Filter过滤器源码解析

本文详细介绍了Servlet中Filter过滤器的工作原理,包括Filter接口、FilterConfig和FilterChain的核心概念,并提供了过滤器的注册方式及示例代码,帮助读者深入理解过滤器在请求处理中的角色和功能。

servlet中Filter过滤器源码解析

一、简介

在servlet开发中,对于请求的拦截,常使用filter过滤器,这里结合源码对Filter过滤器进行介绍。

二、Filter过滤器

Filter过滤器是实现特殊接口的java类,由servlet容器调用执行,可用于权限过滤、日志记录、图片转换、加密、数据压缩等操作。

2.1 核心类

Filter过滤器核心类是Filter,关联的还有有FilterConfig、FilterChain,其实是三个接口,。下面结合源码分别介绍。

2.1.1 Filter接口

Filter是在请求到响应(servlet或静态资源),或者一个响应到另一个响应中间,执行过滤任务的对象。Filter执行过滤任务是在方法doFilter中。源码如下:

package javax.servlet;

import java.io.IOException;
public interface Filter {
    //初始化方法,容器创建Filter对象后,立即调用init方法,整个生命周期中只执行一次。
    //在init方法成功(失败如抛异常等)执行完前,不能提供过滤服务。
    //参数FilterConfig用于获取初始化参数
    public void init(FilterConfig filterConfig) throws ServletException;

    //执行过滤任务的方法,参数FilterChain表示Filter链,doFilter方法中只有执行FilterChain只有执行了doFilter方法,
    //才能将请求交经下一个Filter或Servlet执行
    public void doFilter(ServletRequest request, ServletResponse response,
                         FilterChain chain)
            throws IOException, ServletException;

    //销毁方法,当移出服务时由web容器调用。整个生命周期中destroy方法只会执行一次
    //destroy方法可用于释放持有的资源,如内存、文件句柄等
    public void destroy();
}
2.1.2 FilterConfig

FilterConfig用于获取过滤器的初始化参数。源码如下:

package javax.servlet;
import java.util.Enumeration;
public interface FilterConfig {
    //获取过滤器名称
    public String getFilterName();

    //获取关联的ServletContext
    public ServletContext getServletContext();

    //获取指定名称的初始化参数
    public String getInitParameter(String name);

    //获取初始化参数名称集合
    public Enumeration<String> getInitParameterNames();
}
2.1.3 FilterChain

FilterChain是容器提供给开发者的,用于调用Filter链上的下一个Filter或最终servlet服务。

package javax.servlet;
import java.io.IOException;

public interface FilterChain {
    //调用引用链的下一个filter或最终servlet服务
    public void doFilter ( ServletRequest request, ServletResponse response ) throws IOException, ServletException;
}
2.2 注册

过滤器注册有两种方式,使用常规的xml注册和使用注解注册(会在示例代码中以注释的方式体现)。这里以常规xml注册为例。xml注册是在项目的web.xml上注册的,可以对指定访问路径或指定servlet进行拦截,示例如下:

    <filter-name>demoFitler</filter-name>
    <filter-class>filter.DemoFilter</filter-class>
    <init-param>
      <!-- 初始化参数-->
      <param-name>forbidIds</param-name>
      <param-value>002,003,004</param-value>
    </init-param>
  </filter>
  <filter-mapping>
    <filter-name>demoFitler</filter-name>
    <url-pattern>/*</url-pattern>
    <!--指定拦截的servlet-->
    <!--<servlet-name>demoServlet</servlet-name>-->
  </filter-mapping>

三、示例

资源servlet类DemoServlet.java如下:

package filter;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

@WebServlet(name="DemoServlet", urlPatterns = "/demoServlet")
public class DemoServlet extends HttpServlet {
    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.setContentType("application/json;charset=utf-8");
        resp.getWriter().write("this is a demo test");
    }
}

过滤器DemoFilter.java

package filter;
import org.apache.commons.lang3.StringUtils;

import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.annotation.WebInitParam;
import java.io.IOException;
import java.util.Objects;

//可以使用下面注解方式注册Filter,其中urlPatterns拦截指定路径,demoServlet拦截指定servlet
//@WebFilter(filterName = "demoFilter", urlPatterns = "/*", servletNames = "demoServlet",
//        initParams = {@WebInitParam(name = "forbidIds", value = "002,003,004")})
public class DemoFilter implements Filter {
    private FilterConfig filterConfig;
    private String forbidIds;

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        this.filterConfig = filterConfig;
        //获取初始化参数
        forbidIds = filterConfig.getInitParameter("forbidIds");
        System.out.println("forbidIds:" + forbidIds);
    }

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

        String id = request.getParameter("id");
        if (StringUtils.isBlank(forbidIds) || !forbidIds.contains(Objects.toString(id, "001"))) {
            //不拦截,调用后续访问
            chain.doFilter(request, response);
        } else {
            //拦截,输出错误信息
            response.setContentType("application/json;charset=utf-8");
            response.getWriter().write("forbid");
        }
    }

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

响应:

请求:http://localhost:8080/demoServlet?id=001
响应:this is a demo test

请求:http://localhost:8080/demoServlet?id=002
响应:forbid
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值