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>
以上都要注意是否有斜杠“/”
服务器之间交换的数据。通俗的说是过滤器可以在用户与请求的资源之前进行一些处理,用户访问某个资源时
,先经过过滤器,过滤器有权决定是否让用户请求想要的资源。
在请求/响应链中包括过滤器,这种设计是为了补充(而不是以任何方式替代)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>
以上都要注意是否有斜杠“/”