直接学习SSH虽然立竿见影,但是不如脚踏实地的学习JavaWeb的一些基础内容,毕竟SSH相关的内容总是绕不开基础的东西。

前面的文章叙述了Servlet的相关内容,这章将叙述Servlet中的Filter内容,该内容会在Struts中反复使用。

Filter:中文名为过滤器。

作用:开发人员通过Filter可以对web服务器的资源进行管理,例如Jsp,Servlet, 静态图片文件等进行拦截,从而实现一些特殊的功能。

例如实现URL级别的权限访问控制、过滤敏感词汇、压缩响应信息等一些高级功能

若想创建一个Filter类,需要实现Filter接口,即显式实现API提供的Filter接口,只要实现了该接口,这个java类就为过滤器类。

这个类就可以让用户在访问某个目标资源之前,对访问的请求和响应进行拦截。

Filter源码:

public interface Filter {

  public void init(FilterConfig filterConfig) throws ServletException;

  public void doFilter(ServletRequest request, ServletResponse response,
                         FilterChain chain)
            throws IOException, ServletException;

  public void destroy();
}



该接口和Servlet类似,都有一个初始化方法、销毁方法,执行方法,只不过httpServlet里面的执行方法是Service,这个里面是doFilter。

HttpService中的service方法的作用:每次执行url请求时,都会执行一次service方法。

doFilter方法的作用:在url请求想要获取目标资源前,或调用目标后,以及是否调用资源目标,都要执行一次doFilter方法对其进行处理。

doFilter中的ServletRequest/ServletResponse声明是接口,并非实现类,而传递给我们的request、Response参数可以是该接口的实现类。

我们这里主要用到FilterChain接口的doFilter这个方法,这个参数决定目标资源是否可以被访问。

FilterChain是一个接口,该接口里面只有一个方法,其代码如下:


public interface FilterChain {
	
    public void doFilter ( ServletRequest request, ServletResponse response ) throws IOException, ServletException;

}

什么意思呢?

假如我们编写了Filter的实现类FilterA,然后FilterA实现了Filter接口的doFilter方法,接下来doFilter方法里面的FilterChain可以从doFilter方法里形参中获取其ServletRequest和ServletResopnse参数,再执行doFilter方法。

FilterChain接口的doFilter方法会调用servlet的service方法,

代码如下:

import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;

public class FilterTest implements Filter{

    public void destroy() {
        System.out.println("----Filter销毁----");
    }

    public void doFilter(ServletRequest request, ServletResponse response,FilterChain filterChain) throws IOException, ServletException {
        // 对request、response进行一些预处理
        request.setCharacterEncoding("UTF-8");
        response.setCharacterEncoding("UTF-8");
        response.setContentType("text/html;charset=UTF-8");
        System.out.println("----调用service之前执行一段代码----");
        filterChain.doFilter(request, response); // 执行目标资源,放行
        System.out.println("----调用service之后执行一段代码----");
    }

    public void init(FilterConfig arg0) throws ServletException {
        System.out.println("----Filter初始化----");
    }
}

web.XML


<?xml version="1.0" encoding="UTF-8"?>
<web-app version="3.0" 
    xmlns="http://java.sun.com/xml/ns/javaee" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee 
    http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd">
  <display-name></display-name>    
  <welcome-file-list>
    <welcome-file>index.jsp</welcome-file>
  </welcome-file-list>
  <!--配置过滤器-->
  <filter>
      <filter-name>FilterA</filter-name>
      <filter-class>com.filter.FilterA</filter-class>
  </filter>
  <!--映射过滤器-->
  <filter-mapping>
      <filter-name>FilterA</filter-name>
      <!--“/*”表示拦截所有的请求 -->
      <url-pattern>/*</url-pattern>
  </filter-mapping>
</web-app>

我们将web.xml和FilterA结合起来:

先在web.xml中声明了一个过滤器,该过滤器命名为FilterA,其路径为com.filter.FilterA,至于FilterA怎么被web服务器创建的,无需知道,只需要知道是tomcat通过反射创建的即可。

然后又在web.xml里面写了一个过滤器表,该表表示有哪些过滤器,以及过滤器要过滤那些请求,一般的我们都拦截所以请求,学过Struts2的会发现,这里很类似。

当一个url请求经过我们的过滤器FilterA时,过滤器的doFilter拦截到了。

我们将在doFilter方法中进行处理,我们可以获取到request中得相关数据,也可以获取到response中的相关数据。

如果request中获取到的数据和我们所要的一样,就要执行 filterChain.doFilter(request, response); 语句,该语句会直接跳转到HttpServlet的实现类的Service方法里。

在这之前,你如果不调用该方法,他就走不到Servlet的Service这里,换句话说,接下来就不会执行servlet的Service方法。

跳转到Service方法里面后,然后就会执行Servlet的doget和dopost方法。

执行完Servlet的相关方法后,就执行ilterChain.doFilter(request, response);语句后面的语句。

所以他的执行顺序是:

Filter的init()方法,Filter的doFilter()方法,doFilter()方法里面的FilterChain接口的doFilter方法,

Servlet的init()方法,Servlet的doService()方法,Servlet的doget()方法,Servlet的dopost()方法

doFilter()方法里面的剩余语句。

Filter的destroy方法,不明白Servlet看我的Servlet概述。

对上述进行总结(即Filter的功能):

在servlet被调用之前截获;

在servlet被调用之前检查servlet request;

根据需要修改request头和request数据;

根据需要修改response头和response数据;

在servlet被调用之后截获.