zoukankan      html  css  js  c++  java
  • 第5天:servlet之Filter相关

    1. 是什么

    filter是什么?

    ①. JavaWEB 的一个重要组件, 可以对发送到 Servlet 的请求进行拦截, 并对响应也进行拦截.
    ②. Filter 是实现了 Filter 接口的 Java 类
    ③. Filter 需要在 web.xml 文件中进行配置和映射

    2. 如何创建一个 Filter

    ①. 创建一个 Filter 类: 实现 Filter 接口

    public class HelloFilter implements Filter

    ②. 在 web.xml 文件中配置并映射该 Filter.;其中 url-pattern 指定该 Filter 可以拦截哪些资源, 即可以通过哪些 url 访问到该 Filter(和servlet配置类似)

    导入的包是:

    1 import javax.servlet.*;

    在web.xml中配置:

        <!-- 注册 Filter -->
        <filter>
            <filter-name>filterTest</filter-name>
            <filter-class>com.servlet.sc.HelloFilter</filter-class>
        </filter>
        <!-- 映射 Filter -->
        <filter-mapping>
            <filter-name>filterTest</filter-name>
            <url-pattern>/index.jsp</url-pattern>
        </filter-mapping>
    import javax.servlet.*;
    import java.io.IOException;
    
    public class HelloFilter implements Filter {
        @Override
        public void init(FilterConfig filterConfig) throws ServletException {
        }
        @Override
        public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
            System.out.println("请求通过了我");
        }
        @Override
        public void destroy() {
        }
    }

    3. Filter 相关的 API

    ①.  Filter 接口:

    public void init(FilterConfig filterConfig) throws ServletException {}

    类似于 Servlet 的 init 方法. 在创建 Filter 对象(Filter 对象在 Servlet 容器加载当前 WEB 应用时即被创建)后, 立即被调用, 且只被调用一次. 该方法用于对当前的 Filter 进行初始化操作. Filter 实例是单例的

    FilterConfig 类似于 ServletConfig

    可以在 web.xml 文件中配置当前 Filter 的初始化参数. 配置方式也和 Servlet 类似。

    <filter>
        <filter-name>helloFilter</filter-name>
        <filter-class>com.servlet.sc.HelloFilter</filter-class>
        <init-param>
            <param-name>name</param-name>
            <param-value>root</param-value>
        </init-param>
    </filter>
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {}

    真正 Filter 的逻辑代码需要编写在该方法中. 每次拦截都会调用该方法. 

    FilterChain: Filter 链. 多个 Filter 可以构成一个 Filter 链. 

      - doFilter(ServletRequest request, ServletResponse response): 把请求传给 Filter 链的下一个 Filter,若当前 Filter 是 Filter 链的最后一个 Filter, 将把请求给到目标 Serlvet(或 JSP)

    多个 Filter 拦截的顺序<filter-mapping> 配置的顺序有关, 靠前先被调用.  

    public void destroy() {}

    释放当前 Filter 所占用的资源的方法. 在 Filter 被销毁之前被调用, 且只被调用一次. 

    4. <dispatcher> 元素

    <dispatcher> 元素:指定过滤器所拦截的资源被 Servlet 容器调用的方式,可以是REQUEST,INCLUDE,FORWARD和ERROR之一,默认REQUEST. 可以设置多个<dispatcher> 子元素用来指定 Filter 对资源的多种调用方式进行拦截

    ①. REQUEST:当用户直接访问页面时,Web容器将会调用过滤器。如果目标资源是通过RequestDispatcher的include()或forward()方法访问时,那么该过滤器就不会被调用。通过 GET 或 POST 请求直接访问。 

    ②. FORWARD:如果目标资源是通过RequestDispatcher的forward()方法访问时,那么该过滤器将被调用,除此之外,该过滤器不会被调用。或 <jsp:forward page="/..." /> 或 通过 page 指令的 errorPage 转发页面. <%@ page errorPage="test.jsp" %>

    ③. INCLUDE:如果目标资源是通过RequestDispatcher的include()方法访问时,那么该过滤器将被调用。除此之外,该过滤器不会被调用。或 <jsp:include file="/..." />

    ④. ERROR:如果目标资源是通过声明式异常处理机制调用时,那么该过滤器将被调用。除此之外,过滤器不会被调用。在 web.xml 文件中通过 error-page 节点进行声明:

      <error-page>
            <exception-type>java.lang.ArithmeticException</exception-type>
            <location>/error.jsp</location>
        </error-page>
    
        <filter-mapping>
            <filter-name>errorFilter</filter-name>
            <url-pattern>/error.jsp</url-pattern>
            <dispatcher>REQUEST</dispatcher>
            <dispatcher>FORWARD</dispatcher>
            <dispatcher>INCLUDE</dispatcher>
            <dispatcher>ERROR</dispatcher>
        </filter-mapping>

    5、HttpServletWrapper 和 HttpServletResponseWrapper

    1). Servlet API 中提供了一个 HttpServletRequestWrapper 类来包装原始的 request 对象,HttpServletRequestWrapper 类实现了 HttpServletRequest 接口中的所有方法, 这些方法的内部实现都是仅仅调用了一下所包装的的 request 对象的对应方法

    //包装类实现 ServletRequest 接口. 

    public class ServletRequestWrapper implements ServletRequest {
    
        //被包装的那个 ServletRequest 对象
        private ServletRequest request;
        
        //构造器传入 ServletRequest 实现类对象
        public ServletRequestWrapper(ServletRequest request) {
            if (request == null) {
                throw new IllegalArgumentException("Request cannot be null");   
            }
            this.request = request;
        }
    
        //具体实现 ServletRequest 的方法: 调用被包装的那个成员变量的方法实现。 
        public Object getAttribute(String name) {
            return this.request.getAttribute(name);
        }
    
        public Enumeration getAttributeNames() {
            return this.request.getAttributeNames();
        }    
        
        //...    
    }

    相类似 Servlet API 也提供了一个 HttpServletResponseWrapper 类来包装原始的 response 对象

    2). 作用: 用于对 HttpServletRequest 或 HttpServletResponse 的某一个方法进行修改或增强.

    public class MyHttpServletRequest extends HttpServletRequestWrapper{
    
        public MyHttpServletRequest(HttpServletRequest request) {
            super(request);
        }
        
        @Override
        public String getParameter(String name) {
            String val = super.getParameter(name);
            if(val != null && val.contains(" fuck ")){
                val = val.replace("fuck", "****");
            }
            return val;
        }
    }

    3). 使用: 在 Filter 中, 利用 MyHttpServletRequest 替换传入的 HttpServletRequest

    HttpServletRequest req = new MyHttpServletRequest(request);
      filterChain.doFilter(req, response);

    此时到达目标 Servlet 或 JSP 的 HttpServletRequest 实际上是 MyHttpServletRequest 

  • 相关阅读:
    对象的引用
    查询各个商品分类中各有多少商品的SQL语句
    将TP引擎改为smarty引擎
    图片预加载
    js中接口的声明与实现
    判断对象是否是某个类的实例
    判断变量是否为json对象
    Python 爬取淘宝商品数据挖掘分析实战
    Python 爬取淘宝商品数据挖掘分析实战
    扫盲丨关于区块链你需要了解的所有概念
  • 原文地址:https://www.cnblogs.com/lzghyh/p/14052797.html
Copyright © 2011-2022 走看看