java ee 之 filter

Servlet 过滤器是小型的 Web 组件,它们拦截请求和响应,以便查看、提取或以某种方式操作正在客户机和

服务器之间交换的数据。通俗的说是过滤器可以在用户与请求的资源之前进行一些处理,用户访问某个资源时

,先经过过滤器,过滤器有权决定是否让用户请求想要的资源。
在请求/响应链中包括过滤器,这种设计是为了补充(而不是以任何方式替代)servlet 或 JSP 页面提供的核

心处理。因而,过滤器可以根据需要添加或删除,而不会破坏 servlet 或 JSP 页面。
所以 Servlet 过滤器是通过一个配置文件来灵活声明的模块化可重用组件。过滤器动态地处理传入的请求和

传出的响应,并且无需修改应用程序代码就可以透明地添加或删除它 们。最后,过滤器独立于任何平台或者

Servlet 容器,从而允许将它们容易地部署到任何相容的 J2EE 环境中。

Servlet 过滤器体系结构
正如其名称所暗示的,Servlet 过滤器 用于拦截传入的请求和/或传出的响应,并监视、修改或以某种方式处

理正在通过的数据流。过滤器是自包含、模块化的组件,可以将它们添加到请求/响应链中, 或者在无需影响

应用程序中其他 Web 组件的情况下删除它们。过滤器仅只是改动请求和响应的运行时处理,因而不应该将它

们直接嵌入 Web 应用程序框架,除非是通过 Servlet API 中良好定义的标准接口来实现。

Web 资源可以配置为没有过滤器与之关联(这是默认情况)、与单个过滤器关联(这是典型情况),甚至是与

一个过滤器链相关联。那么过滤器究竟做什么呢? 像 servlet 一样,它接受请求并响应对象。然后过滤器会

检查请求对象,并决定将该请求转发给链中的下一个组件,或者中止该请求并直接向客户机发回一个响应。如

果请求被 转发了,它将被传递给链中的下一个资源(另一个过滤器、servlet 或 JSP 页面)。在这个请求设

法通过过滤器链并被服务器处理之后,一个响应将以相反的顺序通过该链发送回去。这样就给每个过滤器都提

供了根据需要处理响应对象的机 会。

实现一个 Servlet 过滤器要经历三个步骤。首先要编写过滤器实现类的程序,然后要把该过滤器添加到 Web

应用程序中(通过在 Web 部署描述符 /web.xml 中声明它)
1. 编写实现类的程序
过滤器 API 包含 3 个简单的接口(又是数字 3!),它们整洁地嵌套在 javax.servlet 包中。那 3 个接口

分别是 Filter、FilterChain 和 FilterConfig。对于我们编写过滤器而言,实现 Filter 接口就可以了,然

后使用这个过滤器类中的 FilterChain 和 FilterConfig 接口。该过滤器类的一个引用将传递给

FilterChain 对象,以允许过滤器把控制权传递给链中的下一个资源。FilterConfig 对象将由容器提供给过

滤器,以允许访问该过滤器的初始化数据。

过滤器必须实现接口中的三个方法,以便完全实现 Filter 接口:

init():这个方法在容器实例化过滤器时被调用,它主要设计用于使过滤器为处理做准备。该方法接受一个

FilterConfig 类型的对象作为输入。

doFilter():与 servlet 拥有一个 service() 方法(这个方法又调用 doPost() 或者 doGet())来处理请求

一样,过滤器拥有单个用于处理请求和响应的方法——doFilter()。这个方法接受三个输入参数:一个

ServletRequest、response 和一个 FilterChain 对象。

destroy():正如您想像的那样,这个方法执行任何清理操作,这些操作可能需要在自动垃圾收集之前进行。

展示了一个非常简单的过滤器,它跟踪满足一个客户机的 Web 请求所花的大致时间。

import java.io.IOException;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

public class FilterDemo implements Filter
{
    private FilterConfig filterConfig;

    @Override
    public void init(FilterConfig arg0) throws ServletException
    {
        this.filterConfig = arg0;
        System.out.println("Filter 初始化!");
    }

    @Override
    public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws

IOException, ServletException
    {
        HttpServletRequest request = (HttpServletRequest) req;
        HttpServletResponse response = (HttpServletResponse) resp;
        HttpSession session = request.getSession();

        String url = request.getRequestURL().toString();

        System.out.println("拦截URL:" + url);
        ServletContext context = filterConfig.getServletContext();
        System.out.println(context.getServletContextName());

        if (session.getAttribute("username") != null || request.getParameter("username")

!= null)
        {
            chain.doFilter(req, resp);
        }
        else
        {
            request.setAttribute("message", "请登录查看!");
            request.setAttribute("url", request.getRequestURL());
            request.getRequestDispatcher("/login.jsp").forward(request, response);
        }
    }

    @Override
    public void destroy()
    {
        this.filterConfig = null;
        System.out.println("Filter 结束!");
    }
}

这个过滤器的生命周期很简单

初始化
当容器第一次加载该过滤器时,init() 方法将被调用。该类在这个方法中包含了一个指向 FilterConfig 对

象的引用。我们的过滤器实际上并不需要这样做,因为其中没有使用初始化信息,这里只是出于演示的目的。

过滤
过滤器的大多数时间都消耗在这里。doFilter() 方法被容器调用,同时传入分别指向这个请求/响应链中的

ServletRequest、ServletResponse 和 FilterChain 对象的引用。然后过滤器就有机会处理请求,将处理任

务传递给链中的下一个资源(通过调用 FilterChain 对象引用上的 doFilter()方法),之后在处理控制权返

回该过滤器时处理响应。


销毁
容器紧跟在垃圾收集之前调用 destroy() 方法,以便能够执行任何必需的清理代码。

web.xml

    <filter>
        <filter-name>filter</filter-name>
        <filter-class>com.servlet.demo.FilterDemo</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>filter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

    <servlet>
        <servlet-name>hello</servlet-name>
        <servlet-class>com.servlet.demo.HelloServlet</servlet-class>
        <init-param>
            <param-name>name</param-name>
            <param-value>hello world</param-value>
        </init-param>
    </servlet>
    <servlet-mapping>
        <servlet-name>hello</servlet-name>
        <url-pattern>/hello</url-pattern>
    </servlet-mapping>

    <servlet>
        <servlet-name>login</servlet-name>
        <servlet-class>com.servlet.demo.LoginServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>login</servlet-name>
        <url-pattern>/login</url-pattern>
    </servlet-mapping>

filter配置方式
1。如果要映射过滤应用程序中所有资源:
<filter>
<filter-name>loggerfilter</filter-name>
<filter-class>myfilter.LoggerFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>loggerfilter</filter-name>
<url-pattern>/*</url-pattern>//映射一个路径下所有请求;
</filter-mapping>

2.过滤指定的类型文件资源
<filter>
<filter-name>loggerfilter</filter-name>
<filter-class>myfilter.LoggerFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>loggerfilter</filter-name>
<url-pattern>*.html</url-pattern>
</filter-mapping>
其中<url-pattern>*.html</url-pattern>要过滤jsp那么就改*.html为*.jsp,但是注意没有“/”斜杠

如果要同时过滤多种类型资源:
<filter>
<filter-name>loggerfilter</filter-name>
<filter-class>myfilter.LoggerFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>loggerfilter</filter-name>
<url-pattern>*.html</url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name>loggerfilter</filter-name>
<url-pattern>*.jsp</url-pattern>
</filter-mapping>

3.过滤指定的目录
<filter>
<filter-name>loggerfilter</filter-name>
<filter-class>myfilter.LoggerFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>loggerfilter</filter-name>
<url-pattern>/folder_name/*</url-pattern>
</filter-mapping>

4.过滤指定的servlet
<filter>
<filter-name>loggerfilter</filter-name>
<filter-class>myfilter.LoggerFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>loggerfilter</filter-name>
<servlet-name>loggerservlet</servlet-name>
</filter-mapping>
<servlet>
<servlet-name>loggerservlet</servlet-name>
<servlet-class>myfilter.LoggerServlet</servlet-class>
</servlet>

5.过滤指定文件
<filter>
<filter-name>loggerfilter</filter-name>
<filter-class>myfilter.LoggerFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>loggerfilter</filter-name>
<url-pattern>/simplefilter.html</url-pattern>
</filter-mapping>

以上都要注意是否有斜杠“/”
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值