JavaWeb 10 Filter

1、概念

Filter,过滤器。其主要用于过滤请求,是服务器端的三大组件之一

服务器端的三大组件:Servlet、Filter、Listener

三大组件的特点:
⑴ 都需要运行在服务器端
⑵ 都需要实现某个接口
⑶ 都需要在web.xml中注册

2、创建Filter的步骤

⑴ 创建一个类,让其实现Filter接口,并实现抽象方法
⑵ 在web.xml中进行注册

服务器会根据web.xml中配置的Filter的全类名,来创建实例,并过滤请求

示例:
【创建一个类,实现Filter接口】

public class MyFilter implements Filter {}

【在web.xml中进行注册】

<filter>
    <filter-name>MyFilter</filter-name>
    <filter-class>com.test.filter.MyFilter</filter-class>
</filter>
<filter-mapping>
    <filter-name>MyFilter</filter-name>
    <!-- 映射请求的路径 -->
    <url-pattern>/hellofilter.jsp</url-pattern>
</filter-mapping>

3、Filter的作用

⑴ 在请求到达目标资源之前,拦截该请求
⑵ 放行请求
⑶ 在响应到达浏览器之前,做一些其他的操作

4、Filter的声明周期

Filter从创建到销毁,体现在4个方法中:

⑴ 构造方法

① 服务器一启动,就会调用该方法,并创建Filter对象。说明Filter对象是在服务器启动时被创建的
② 该方法在Filter的整个生命周期中,只会被调用一次。说明Filter是单例的

⑵ init方法

public void init(FilterConfig filterConfig);

① 该方法在Filter的构造方法被调用后,就立即被调用。其主要用于对Filter对象做一些初始化的操作
② 该方法在Filter的整个生命周期中,只会被调用一次

参数FilterConfig对象的作用


和Servlet的init方法中的ServletConfig对象类似

⑴ 获取Filter在web.xml中注册的名字
public String getFilterName();

⑵ 获取ServletContext对象
public ServletContext getServletContext();

⑶ 获取初始化参数
public String getInitParameter(String name);
根据param-name,获取在web.xml中的filter标签中的init-param里的param-value的值

 <filter>
       <init-param>
           <param-name>key</param-name>
           <param-value>value</param-value>
       </init-param>
 </filter>

示例:

@Override
public void init(FilterConfig filterConfig) throws ServletException {
    // 获取FilterName
    String filterName = filterConfig.getFilterName();
    System.out.println(filterName);

    // 获取ServletContext对象
    ServletContext servletContext = filterConfig.getServletContext();
    System.out.println(servletContext);

    // 获取初始化参数
    String value = filterConfig.getInitParameter("key");
    System.out.println(value);
}

⑶ doFilter方法
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain);

① 该方法,在每次访问Filter在web.xml中注册的,映射的请求路径【url-pattern】时,都会被调用。其用来拦截请求
② 该方法在Filter的整个生命周期中,会被调用多次

    ⒈ ServletRequest和ServletResponse对象,和Servlet的service方法中的ServletRequest和ServletResponse对象一样
    ⒉ FilterChain对象是用来放行请求的。需要调用其doFilter方法
public void doFilter(ServletRequest request, ServletResponse response);
将request和response对象传进去

⑷ destroy方法
public void destroy();

① 该方法在服务器关闭前被调用,用于销毁Filter对象
② 该方法在Filter的整个生命周期中,只会被调用一次

5、多个过滤器的执行顺序

可以为同一个资源设置多个过滤器,多个过滤器组成一个过滤器链。
多个过滤器的执行顺序,由在web.xml中的

  <filter-mapping>

标签决定

Tips:
⑴ 声明在前的,先执行;声明在后的,后执行
⑵ 如果多个过滤器都放行了请求,则FilterChain对象的doFilter方法,上面的代码按照声明的先后顺序被执行;而下面的代码的执行顺序,则跟声明的顺序相反

注意:tomcat6.0中,filter-mapping标签必须在对应的filter标签的下面,否则会报错。而在tomcat7.0中,filter-mapping则可以在filter的上面

示例:
【OrderFilter1】

@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
        throws IOException, ServletException {
    System.out.println("第1被执行");
    chain.doFilter(request, response);
    System.out.println("第5被执行");
}

【OrderFilter2】

@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
        throws IOException, ServletException {
    System.out.println("第2被执行");
    chain.doFilter(request, response);
    System.out.println("第4被执行");
}

【index.jsp】

<body>
    <% System.out.println("第3被执行"); %>
</body>

【web.xml配置文件】

<filter>
    <filter-name>OrderFilter1</filter-name>
    <filter-class>com.test.filter.OrderFilter1</filter-class>
</filter>
<filter-mapping>
    <!-- 先注册的 -->
    <filter-name>OrderFilter1</filter-name>
    <url-pattern>/index.jsp</url-pattern>
</filter-mapping>

<filter>
    <filter-name>OrderFilter2</filter-name>
    <filter-class>com.test.filter.OrderFilter2</filter-class>
</filter>
<filter-mapping>
    <!-- 后注册的 -->
    <filter-name>OrderFilter2</filter-name>
    <url-pattern>/index.jsp</url-pattern>
</filter-mapping>

6、url-pattern的配置规则

精确匹配

配置一个完整的路径

<url-pattern>/index.jsp</url-pattern>

只有访问index.jsp时,过滤器才会拦截请求

Tips:/ 代表当前项目的根路径
注意:一定要在路径前加上/ ,否则tomcat无法正常启动

模糊匹配

前缀匹配


拦截以指定路径开头的资源

  <url-pattern>/pages/*</url-pattern>

只有访问pages路径下的资源时,过滤器才会拦截请求

后缀匹配


拦截以指定字符结尾的资源

   <url-pattern>*.jsp</url-pattern>

当访问的是jsp页面时,过滤器才会拦截请求

注意事项

不能同时添加前缀匹配和后缀匹配,例如

  <url-pattern>/pages/*.jsp</url-pattern>

这样配置是无效的,会导致tomcat无法正常启动,会报错:IllegalArgumentException: Invalid /pages/*.jsp in filter mapping

拦截Servlet

在filter-mapping中加url-pattern标签


示例:

 <filter-mapping>
     <url-pattern>/loginServlet</url-pattern>
 </filter-mapping>

注意:该url-pattern必须和要拦截的Servlet在web.xml中注册的url-pattern一致

在filter-mapping中加servlet-name标签


示例:

  <filter-mapping>
      <servlet-name>LoginServlet</servlet-name>
  </filter-mapping>

注意:该servlet-name必须和要拦截的Servlet在web.xml中注册的servlet-name一致

7、dispatcher的配置

概念

Filter默认只会拦截直接请求,即直接访问某页面的请求。但是像请求的转发就不能拦截,要想拦截这样的请求,就必须在filter-mapping的子标签dispatcher中配置

<filter-mapping>
    <dispatcher></dispatcher>
</filter-mapping>

REQUEST

默认值。只能拦截直接请求【直接访问页面的请求】

注意:如果配置了其他想要拦截的请求,同时还想拦截直接访问的请求,则需要同时配置该请求

示例:【拦截对page.jsp页面的直接请求】

<filter>
    <filter-name>TestFilter</filter-name>
    <filter-class>com.test.filter.TestFilter</filter-class>
</filter>
<filter-mapping>
    <filter-name>TestFilter</filter-name>
    <url-pattern>/page.jsp</url-pattern>

    <dispatcher>REQUEST</dispatcher>
</filter-mapping>

FORWARD

拦截转发的请求
包括通过getRequestDispatcher().forward(); 方法或动作标签转发的请求

示例:【拦截对page.jsp的转发请求和直接请求】
【index.jsp】

<jsp:forward page="/page.jsp"></jsp:forward>

【web.xml】

<filter>
    <filter-name>TestFilter</filter-name>
    <filter-class>com.test.filter.TestFilter</filter-class>
</filter>
<filter-mapping>
    <filter-name>TestFilter</filter-name>
    <url-pattern>/page.jsp</url-pattern>

    <dispatcher>REQUEST</dispatcher>
    <dispatcher>FORWARD</dispatcher>
</filter-mapping>

INCLUDE

拦截动态包含

即通过动作标签,动态包含的页面,会被拦截。因为它调用了org.apache.jasper.runtime.JspRuntimeLibrary.include(request, response, “/动态包含的页面”, out, false); 方法
但是通过<%@ include %>指令标签,静态包含的页面,无法被拦截。因为它是直接将页面的内容复制过来的

示例:【拦截对page.jsp的动态包含】
【index.jsp】

<jsp:include page="/page.jsp"></jsp:include>

【web.xml】

<filter>
    <filter-name>TestFilter</filter-name>
    <filter-class>com.test.filter.TestFilter</filter-class>
</filter>
<filter-mapping>
    <filter-name>TestFilter</filter-name>
    <url-pattern>/page.jsp</url-pattern>

    <dispatcher>INCLUDE</dispatcher>
</filter-mapping>

ERROR

拦截在web.xml中配置的错误页面

注意:url-pattern标签的路径和error-page标签的子标签location的路径要一致

在web.xml中配置错误页面

 <error-page>
     <error-code></error-code>
     <location></location>
 </error-page>

error-code:错误状态码
location:错误页面的地址
注意:该地址需要以/ 开头【由服务器解析】

使用示例

<filter>
    <filter-name>TestFilter</filter-name>
    <filter-class>com.test.filter.TestFilter</filter-class>
</filter>
<filter-mapping>
    <filter-name>TestFilter</filter-name>
    <!-- 要拦截的错误页面的地址 -->
    <url-pattern>/404.jsp</url-pattern>

    <dispatcher>ERROR</dispatcher>
</filter-mapping>

<error-page>
    <error-code>404</error-code>
    <!-- 错误页面的地址 -->
    <location>/404.jsp</location>
</error-page>

8、HttpFilter

系统并没有提供doFilter方法中的request和response的对象是HttpServletRequest和HttpServletResponse,所以我们可以自己写一个,以便子Filter来继承,减少代码量

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;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public abstract class HttpFilter implements Filter {
    // FilterConfig属性
    private FilterConfig filterConfig;

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        this.filterConfig = filterConfig;
        init();
    }

    // 供子类重写的init方法
    public void init() {
    }

    // 提供公共的获取FilterConfig的get方法
    public FilterConfig getFilterConfig() {
        return filterConfig;
    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException {
        // 向下转型
        HttpServletRequest req = (HttpServletRequest) request;
        HttpServletResponse resp = (HttpServletResponse) response;

        // 调用重载的抽象方法
        doFilter(req, resp, chain);
    }

    // 供子类重写的抽象方法
    public abstract void doFilter(HttpServletRequest request, HttpServletResponse response, FilterChain chain)
            throws IOException, ServletException;

    @Override
    public void destroy() {
    }

}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值