• Filter


    2 Servlet规范中的过滤器-Filter

    2.1 过滤器入门

    2.1.1 过滤器概念及作用

    过滤器——Filter,它是JavaWeb三大组件之一。另外两个是Servlet和Listener。

    它是在2000年发布的Servlet2.3规范中加入的一个接口。是Servlet规范中非常实用的技术。

    它可以对web应用中的所有资源进行拦截,并且在拦截之后进行一些特殊的操作。

    常见应用场景:URL级别的权限控制;过滤敏感词汇;中文乱码问题等等。

    过滤器介绍

    在程序中访问服务器资源时,当一个请求到来,服务器首先判断是否有过滤器与请求资源相关联,如果有,过滤器可以将请求拦截下来,完成一些特定的功能,再由过滤器决定是否交给请求资源。如果没有则像之前那样直接请求资源了,响应也是类似的。

     

    Filter介绍

    Filter是一个接口。如果想实现过滤器的功能,必须实现该接口

    核心方法

    返回值 方法名 作用
    void         init(FilterConfig config) 初始化方法
    void   doFilter(ServletRequest request,ServletResponse,FilterChain chain) 对请求资源和响应资源过滤
    void destroy() 销毁方法

    配置方式

    注解方式

    配置文件

    FilterChain介绍

     FilterChain是一个接口,代表过滤器链对象。由Servlet容器提供实现类对象

    过滤器可以定义很多个,就会组成过滤器链

    如果有多个过滤器,在第一个过滤器中调用下一个过滤器,以此类推。直到到达最终访问资源

    如果只有一个过滤器,放行时,就会直接到达最终访问资源

     

    2.1.2 过滤器的入门案例

    需求说明

      通过Filter过滤器解决多个资源写出中文乱码的问题。

    最终目的

      通过本需求,最终掌握Filter过滤器的使用。

    1)前期准备

    创建JavaWeb工程

    创建两个Servlet功能类,都向客户端写出中文数据

    创建一个Filter过滤器实现类,重写doFilter核心方法

    在方法内解决中文乱码,并放行

    部署并启动项目

    通过浏览器测试

     

    处理中文乱码问题(过滤器拦截 处理完在放行)

    先创建两个Servlet

     

    ServletDemo01

    package com.itheima.servlet;
    
    import javax.servlet.ServletException;
    import javax.servlet.annotation.WebServlet;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import java.io.IOException;
    
    @WebServlet("/servletDemo01")
    public class ServletDemo01 extends HttpServlet {
        @Override
        protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            System.out.println("servletDemo01执行了。。。");
            //resp.setContentType("text/html;charset=UTF-8");
    
            resp.getWriter().write("servletDemo01执行了。。。");
        }
    
        @Override
        protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            doGet(req, resp);
        }
    }
    

      ServletDemo02

    package com.itheima.servlet;
    
    import javax.servlet.ServletException;
    import javax.servlet.annotation.WebServlet;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import java.io.IOException;
    
    @WebServlet("/servletDemo02")
    public class ServletDemo02 extends HttpServlet {
        @Override
        protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            System.out.println("servletDemo02执行了。。。");
            //resp.setContentType("text/html;charset=UTF-8");
            resp.getWriter().write("servletDemo02执行了。。。");
        }
    
        @Override
        protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            doGet(req, resp);
        }
    }
    

      过滤器

    FilterDemo01

    package com.itheima.filter;
    
    import javax.servlet.*;
    import javax.servlet.annotation.WebFilter;
    import java.io.IOException;
    
    /*
    * 过滤器的基本使用
    * */
    @WebFilter("/*")
    public class FilterDemo01 implements Filter {
    
        @Override
        public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
            System.out.println("filterDemo01执行了");
    
            //处理乱码
            servletResponse.setContentType("text/html;charset=UTF-8");
    
            //放行
            filterChain.doFilter(servletRequest,servletResponse);
        }
    }
    

      运行结果如图

     控制台输出如下

     

    过滤器使用细节

    配置方式

      注解方式@WebFilter(拦截路径)

    配置文件方式

    <!--配置过滤器-->
    <filter>
        <filter-name>filterDemo1</filter-name>
        <filter-class>com.itheima.web.filter.FilterDemo1</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>filterDemo1</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
    

      多个过滤器使用顺序

    如果有多个过滤器,取决于过滤器映射的顺序

    <filter-mapping>的配置前后顺序决定过滤器的调用顺序,也就是由映射配置顺序决定。

    过滤器生命周期

    创建

      当应用加载时实例化对象并执行init 初始化方法

    服务

      对象提供服务的过程,执行doFilter方法

    销毁

      当应用卸载时或服务器停止时对象销毁,执行destory方法。

    package com.itheima.filter;
    
    import javax.servlet.*;
    import java.io.IOException;
    
    /*
    * 过滤器的生命周期
    * */
    //@WebFilter("/*")
    public class FilterDemo03 implements Filter {
        /*
        * 初始化方法
        * */
        @Override
        public void init(FilterConfig filterConfig) throws ServletException {
            System.out.println("对象初始化成功了");
        }
        /*
        * 提供服务的方法
        * */
        @Override
        public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
            System.out.println("filterDemo03执行了");
    
            //处理乱码
            servletResponse.setContentType("text/html;charset=UTF-8");
    
            //放行
            filterChain.doFilter(servletRequest,servletResponse);
        }
    
        @Override
        public void destroy() {
            System.out.println("对象销毁了");
        }
    }
    

      最后停止服务器的时候销毁

    2.2.4 过滤器与Servlet的区别

    方法/类型ServletFilter备注
    初始化 方法 void init(ServletConfig); void init(FilterConfig); 几乎一样,都是在web.xml中配置参数,用该对象的方法可以获取到。
    提供服务方法 void service(request,response); void dofilter(request,response,FilterChain); Filter比Servlet多了一个FilterChain,它不仅能完成Servlet的功能,而且还可以决定程序是否能继续执行。所以过滤器比Servlet更为强大。 在Struts2中,核心控制器就是一个过滤器。
    销毁方法 void destroy(); void destroy();  

    FilterConfig介绍

    FilterConfig是一个接口,代表过滤器的配置对象,可以加载一些初始化参数。

     

    FilterDemo04 
    package com.itheima.filter;
    
    import javax.servlet.*;
    import java.io.IOException;
    import java.net.Socket;
    
    /*
    * 过滤器的配置对象的使用
    * */
    //@WebFilter("/*")
    public class FilterDemo04 implements Filter {
        @Override
        public void init(FilterConfig filterConfig) throws ServletException {
            System.out.println("对象初始化成功了。。。");
    
            //获取过滤器名称
            String filterName = filterConfig.getFilterName();
            System.out.println(filterName);
    
            //根据name获取value
            String username = filterConfig.getInitParameter("username");
            System.out.println(username);
    
        }
    
        @Override
        public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
            System.out.println("filterDemo04执行了");
    
            //处理乱码
            servletResponse.setContentType("text/html;charset=UTF-8");
    
            //放行
            filterChain.doFilter(servletRequest,servletResponse);
        }
    }
    

      web.xml

    <filter>
            <filter-name>filterDemo04</filter-name>
            <filter-class>com.itheima.filter.FilterDemo04</filter-class>
            <init-param>
                <param-name>username</param-name>
                <param-value>zhangsan</param-value>
            </init-param>
        </filter>
        <filter-mapping>
            <filter-name>filterDemo04</filter-name>
            <url-pattern>/*</url-pattern>
        </filter-mapping>
    

     过滤器五种拦截行为

    我们的过滤器目前拦截的是请求,但是在实际开发中,我们还有请求转发和请求包含,以及由服务器触发调用的全局错误页面。默认情况下过滤器是不参与过滤的,要想使用,需要我们配置。配置的方式如下:

    拦截方式

    <!--配置过滤器-->
    <filter>
        <filter-name>FilterDemo1</filter-name>
        <filter-class>com.itheima.web.filter.FilterDemo1</filter-class>
        <!--配置开启异步支持,当dispatcher配置ASYNC时,需要配置此行-->
        <async-supported>true</async-supported>
    </filter>
    <filter-mapping>
        <filter-name>FilterDemo1</filter-name>
        <url-pattern>/ServletDemo1</url-pattern>
        <!--过滤请求:默认值。-->
        <dispatcher>REQUEST</dispatcher>
        <!--过滤全局错误页面:当由服务器调用全局错误页面时,过滤器工作-->
        <dispatcher>ERROR</dispatcher>
        <!--过滤请求转发:当请求转发时,过滤器工作。-->
        <dispatcher>FORWARD</dispatcher>
        <!--过滤请求包含:当请求包含时,过滤器工作。它只能过滤动态包含,jsp的include指令是静态包含-->
        <dispatcher>INCLUDE</dispatcher>
        <!--过滤异步类型,它要求我们在filter标签中配置开启异步支持-->
        <dispatcher>ASYNC</dispatcher>
    </filter-mapping>
    

    2.3过滤器的使用案例  

    2.3.2 特殊字符过滤器

    1)需求说明

    在实际开发中,可能会面临一个问题,就是很多输入框都会遇到特殊字符。此时,我们也可以通过过滤器来解决。

    例如:

    我们模拟一个论坛,有人发帖问:“在HTML中表示水平线的标签是哪个?”。

    如果我们在文本框中直接输入<hr/>就会出现一条水平线,这个会让发帖人一脸懵。

    我们接下来就用过滤器来解决一下。

    2)编写步骤

    第一步:创建JavaWeb工程

    沿用第一个案例的工程

    第二步:编写Servlet和JSP

    package com.itheima.servlet;
    
    import javax.servlet.ServletException;
    import javax.servlet.annotation.WebServlet;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import java.io.IOException;
    
    @WebServlet("/servletDemo01")
    public class ServletDemo01 extends HttpServlet {
        @Override
        protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            String content = req.getParameter("content");
            resp.getWriter().write(content);
        }
    
        @Override
        protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            doGet(req, resp);
        }
    }
    

      jsp页面

    <%--
      Created by IntelliJ IDEA.
      User: 12270
      Date: 2021/3/22
      Time: 22:24
      To change this template use File | Settings | File Templates.
    --%>
    <%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
    <html>
      <head>
        <title>$Title$</title>
      </head>
      <body>
      <form action="${pageContext.request.contextPath}/servletDemo01" method="get">
        回帖:<textarea rows="5" cols="25" name="content"></textarea><br/>
        <input type="submit" value="发言">
      </form>
      </body>
    </html>
    

      第三步:编写过滤器

    package com.itheima.filter;
    
    import javax.servlet.*;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletRequestWrapper;
    import javax.servlet.http.HttpServletResponse;
    import java.io.IOException;
    
    public class HTMLFilter implements Filter {
    
        public void init(FilterConfig filterConfig) throws ServletException {
    
        }
    
    
        public void doFilter(ServletRequest req, ServletResponse res,
                             FilterChain chain) throws IOException, ServletException {
            HttpServletRequest request;
            HttpServletResponse response;
            try {
                request = (HttpServletRequest) req;
                response = (HttpServletResponse) res;
            } catch (ClassCastException e) {
                throw new ServletException("non-HTTP request or response");
            }
            //创建一个自己的Request类
            MyHttpServletRequest2 myrequest = new MyHttpServletRequest2(request);
            //放行:
            chain.doFilter(myrequest, response);
        }
    
        public void destroy() {
        }
    }
    class MyHttpServletRequest2 extends HttpServletRequestWrapper {
        //提供一个构造方法
        public MyHttpServletRequest2(HttpServletRequest request){
            super(request);
        }
    
        //重写getParameter方法
        public String getParameter(String name) {
            //1.获取出请求正文: 调用父类的获取方法
            String value = super.getParameter(name);
            //2.判断value是否有值
            if(value == null){
                return null;
            }
            return htmlfilter(value);
        }
    
        private String htmlfilter(String message){
            if (message == null)
                return (null);
    
            char content[] = new char[message.length()];
            message.getChars(0, message.length(), content, 0);
            StringBuilder result = new StringBuilder(content.length + 50);
            for (int i = 0; i < content.length; i++) {
                switch (content[i]) {
                    case '<':
                        result.append("<");
                        break;
                    case '>':
                        result.append(">");
                        break;
                    case '&':
                        result.append("&");
                        break;
                    case '"':
                        result.append(""");
                        break;
                    default:
                        result.append(content[i]);
                }
            }
            return (result.toString());
        }
    
    }
    

      第四步:配置过滤器

    <?xml version="1.0" encoding="UTF-8"?>
    <web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
             version="4.0">
        <filter>
            <filter-name>HTMLFilter</filter-name>
            <filter-class>com.itheima.filter.HTMLFilter</filter-class>
        </filter>
        <filter-mapping>
            <filter-name>HTMLFilter</filter-name>
            <url-pattern>/*</url-pattern>
        </filter-mapping>
    </web-app>
    

     测试效果 

     

      

     

     

     

     

    2.3.2 特殊字符过滤器

    1)需求说明

    在实际开发中,可能会面临一个问题,就是很多输入框都会遇到特殊字符。此时,我们也可以通过过滤器来解决。

    例如:

    我们模拟一个论坛,有人发帖问:“在HTML中表示水平线的标签是哪个?”。

    如果我们在文本框中直接输入<hr/>就会出现一条水平线,这个会让发帖人一脸懵。

    我们接下来就用过滤器来解决一下。

    2)编写步骤

    第一步:创建JavaWeb工程

    沿用第一个案例的工程

    第二步:编写Servlet和JSP

    /**
    * @author 黑马程序员
    * @Company http://www.itheima.com
    */
    public class ServletDemo1 extends HttpServlet {

       public void doGet(HttpServletRequest request, HttpServletResponse response)
               throws ServletException, IOException {
           String content = request.getParameter("content");
           response.getWriter().write(content);
      }

       public void doPost(HttpServletRequest request, HttpServletResponse response)
               throws ServletException, IOException {
           doGet(request, response);
      }

    }
    <servlet>
       <servlet-name>ServletDemo1</servlet-name>
       <servlet-class>com.itheima.web.servlet.ServletDemo1</servlet-class>
    </servlet>
    <servlet-mapping>
       <servlet-name>ServletDemo1</servlet-name>
       <url-pattern>/ServletDemo1</url-pattern>
    </servlet-mapping>
    <%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
    <html>
    <head>
       <title></title>
    </head>
    <body>
    <form action="${pageContext.request.contextPath}/ServletDemo1" method="POST">
      回帖:<textarea rows="5" cols="25" name="content"></textarea><br/>
       <input type="submit" value="发言">
    </form>
    </body>
    </html>

    第三步:编写过滤器


    /**
    * @author 黑马程序员
    * @Company http://www.itheima.com
    */
    public class HTMLFilter implements Filter {

       public void init(FilterConfig filterConfig) throws ServletException {

      }


       public void doFilter(ServletRequest req, ServletResponse res,
                            FilterChain chain) throws IOException, ServletException {
           HttpServletRequest request;
           HttpServletResponse response;
           try {
               request = (HttpServletRequest) req;
               response = (HttpServletResponse) res;
          } catch (ClassCastException e) {
               throw new ServletException("non-HTTP request or response");
          }
           //创建一个自己的Request类
           MyHttpServletRequest2 myrequest = new MyHttpServletRequest2(request);
           //放行:
           chain.doFilter(myrequest, response);
      }

       public void destroy() {
      }
    }
    class MyHttpServletRequest2 extends HttpServletRequestWrapper {
       //提供一个构造方法
       public MyHttpServletRequest2(HttpServletRequest request){
           super(request);
      }

       //重写getParameter方法
       public String getParameter(String name) {
           //1.获取出请求正文: 调用父类的获取方法
           String value = super.getParameter(name);
           //2.判断value是否有值
           if(value == null){
               return null;
          }
           return htmlfilter(value);
      }

       private String htmlfilter(String message){
           if (message == null)
               return (null);

           char content[] = new char[message.length()];
           message.getChars(0, message.length(), content, 0);
           StringBuilder result = new StringBuilder(content.length + 50);
           for (int i = 0; i < content.length; i++) {
               switch (content[i]) {
                   case '<':
                       result.append("&lt;");
                       break;
                   case '>':
                       result.append("&gt;");
                       break;
                   case '&':
                       result.append("&amp;");
                       break;
                   case '"':
                       result.append("&quot;");
                       break;
                   default:
                       result.append(content[i]);
              }
          }
           return (result.toString());
      }

    }

    第四步:配置过滤器

    <filter>
       <filter-name>HTMLFilter</filter-name>
       <filter-class>com.itheima.web.filter.HTMLFilter</filter-class>
    </filter>
    <filter-mapping>
       <filter-name>HTMLFilter</filter-name>
       <url-pattern>/*</url-pattern>
    </filter-mapping>

    3)测试结果

  • 相关阅读:
    API
    API
    for in
    event flow
    object
    Report of program history
    正则表达式
    伪类与伪元素
    Position
    js学习之原型(补充)
  • 原文地址:https://www.cnblogs.com/faded8679/p/14568048.html
Copyright © 2020-2023  润新知