14过滤器入门

1 过滤器基本概念

1.1 引入

场景1: 

在servlet中获取用户参数数据 : request.getParameter("参数名") 遇到参数内容中文乱码问题,

post提交:

request.setCharacterEncoding("utf-8");

get提交:

手动解码: name = new String(name.getBytes("iso-8859-1"),"utf-8")

问题: 如何把这些重复的操作抽取出来呢?

这时就可以用到过滤器,把重复的操作代码写在过滤器中!!!

 

场景2:

登录页面 -> 输入用户民或密码 -》  后台检查是否成功 -》 登录成功,看到用户首页( 用户名:xxxx   )把登录数据放在session域对象中(user)

用户首页如果不登录是看不到的:

判断用户登录权限代码:

HttpSession session =    request.getSession(false);

if(session==null){

跳转到登陆页面

}else{

String user = (String)session.getAttribute("user");

if(user==null){

跳转到登录页面

}

}

 

用户资源修改页面(需要用户登录才能访问)

HttpSession session =    request.getSession(false);

if(session==null){

跳转到登陆页面

}else{

String user = (String)session.getAttribute("user");

if(user==null){

跳转到登录页面

}

}

 

 

问题:如何把这些登录权限代码抽取出???

这是用到了过滤器,把这些登录权限代码写在过滤器中.

1.2 什么是过滤器?

1)过滤器就是一个Filter接口,在javax.servlet.Filter;

2)过滤器是servlet的三大组件之一:

servlet的三大组件:

2.1  (servlet) Servlet接口: javax.servlet.Servlet; 作用:用于开发动态网页

2.2 (过滤器)Filter接口: javax.servlet.Filter; 作用:???

2.3 (监听器)Listener接口: javax.servlet.*

servlet组件的特点:

1)把组件配置到web.xml文件中

2)组件就可以交给tomcat服务器运行!!!!

3)作用:

过滤器的作用,就是一个实现了Filter接口的对象,这个对象可以在请求资源(可能是动态网页或者静态网页)时,或者在响应资源时,或者在请求和响应资源时,执行过滤任务。

1.3 体验

package cn.jxufe.a_filter;

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class TargetServlet extends HttpServlet {

    public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        System.out.println("4)执行了servlet");

        response.getWriter().write("6)用户看到响应内容");
    }

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

    }

}
package cn.jxufe.a_filter;

import java.io.IOException;
import java.util.Enumeration;

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 FirstFilter implements Filter {

    public FirstFilter() {
        System.out.println("1)过滤器对象创建了!");
    }

    /**
     * FilterConfig对象封装了所有当前过滤器配置的初始化参数 
     * 
     */
    public void init(FilterConfig filterConfig) throws ServletException {
        System.out.println("2)过滤器初始化方法");

//        /**
//         * 获取初始化参数
//         */
//        System.out.println(filterConfig.getInitParameter("AAA"));
//        // 遍历所有参数
//        Enumeration<String> enums = filterConfig.getInitParameterNames();
//        while (enums.hasMoreElements()) {
//            String paramName = enums.nextElement();
//            String paramValue = filterConfig.getInitParameter(paramName);
//            System.out.println(paramName + "=" + paramValue);
//        }

    }

    /**
     * 执行过滤任务
     */
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException {
        System.out.println("3)过滤器正在执行过滤任务-过滤请求");

        // 放行
        chain.doFilter(request, response);

        System.out.println("5)过滤器正在执行过滤任务--过滤响应");
    }

    /**
     * 过滤器对象销毁的时候才会调用
     *     web项目重新部署或者tomcat服务器停止了才会销毁过滤器对象
     */
    public void destroy() {
        System.out.println("过滤器被销毁了");
    }
}
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns="http://xmlns.jcp.org/xml/ns/javaee"
    xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
    version="3.1">
    
    <!-- 配置一个过滤器 -->
    <!-- 过滤器配置 -->
    <filter>
        <!-- 内部名称 -->
        <filter-name>FirstFilter</filter-name>
        <filter-class>cn.jxufe.a_filter.FirstFilter</filter-class>
    </filter>
    <!-- 过滤器映射配置 -->
    <filter-mapping>
        <!-- 也是内部名称,但是和上面的名称保持一致!!! -->
        <filter-name>FirstFilter</filter-name>
        <!--过滤器的url-pattern代表的是过滤的路径,而不是访问过滤器的路径 -->
        <url-pattern>/target</url-pattern>
    </filter-mapping>



    <servlet>
        <servlet-name>TargetServlet</servlet-name>
        <servlet-class>cn.jxufe.a_filter.TargetServlet</servlet-class>
    </servlet>

    <servlet-mapping>
        <servlet-name>TargetServlet</servlet-name>
        <url-pattern>/target</url-pattern>
    </servlet-mapping>
</web-app>

1.4 过滤器的生命周期

构造方法: 创建过滤器对象的时候调用。在加载当前项目的时候加载过滤器,只调用1次。单实例的多线程。

init方法: 在创建完过滤器对象之后调用。只调用1次。

doFilter方法: 过滤任务方法。会调用n次。每次访问目标资源的时候,doFilter就会被调用。

destory方法:在销毁过滤器对象的时候调用。在web项目重新部署或tomcat服务器停止的时候销毁过滤器对象。

 

2 映射配置

<!-- 配置一个过滤器 -->
    <!-- 过滤器配置 -->
    <filter>
        <!-- 内部名称 -->
        <filter-name>FirstFilter</filter-name>
        <filter-class>cn.jxufe.a_filter.FirstFilter</filter-class>
    </filter>
    <!-- 过滤器映射配置 -->
    <filter-mapping>
        <!-- 也是内部名称,但是和上面的名称保持一致!!! -->
        <filter-name>FirstFilter</filter-name>
        <!--过滤器的url-pattern代表的是过滤的路径,而不是访问过滤器的路径 -->
        <url-pattern>/target</url-pattern>
    </filter-mapping>

注意:    servlet的url-pattern指的是访问servlet的路径,而过滤器的url-pattern指的是需要过滤的路径。

    而这个过滤的路径,可以是任意资源路径(可以是静态网页路径,页可以是动态网页路径)。

    过滤器url-pattern                 访问目标资源

    精确过滤             /target                      http://localhsot:8080/day20/target

    /index.html                                           http://localhsot:8080/day20/index.html

 

 

模糊过滤                            /*                         http://localhsot:8080/day20/任意路径

/itcast/*                        http://localhsot:8080/day20/itcast/任意路径

*.后缀名                                            http://localhsot:8080/day20/任意路径.后缀名

(*.do)                    ( http://localhsot:8080/day20/任意路径.do)

3 FilteConfig对象

3.1 简介 

和servletconfig对象类似,这个FilterConfig对象加载初始化参数内容

 

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns="http://xmlns.jcp.org/xml/ns/javaee"
    xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
    version="3.1">

    <!-- 配置一个过滤器 -->
    <!-- 过滤器配置 -->
    <filter>
        <!-- 内部名称 -->
        <filter-name>FirstFilter</filter-name>
        <filter-class>cn.jxufe.a_filter.FirstFilter</filter-class>
        <!-- 初始化参数 -->
        <init-param>
            <param-name>AAA</param-name>
            <param-value>AAA' value</param-value>
        </init-param>
        <init-param>
            <param-name>BBB</param-name>
            <param-value>BBB' value</param-value>
        </init-param>
    </filter>
    
    <!-- 过滤器映射配置 -->
    <filter-mapping>
        <!-- 也是内部名称,但是和上面的名称保持一致!!! -->
        <filter-name>FirstFilter</filter-name>
        <!--过滤器的url-pattern代表的是过滤的路径,而不是访问过滤器的路径 -->
        <url-pattern>/target</url-pattern>
    </filter-mapping>



    <servlet>
        <servlet-name>TargetServlet</servlet-name>
        <servlet-class>cn.jxufe.a_filter.TargetServlet</servlet-class>
    </servlet>

    <servlet-mapping>
        <servlet-name>TargetServlet</servlet-name>
        <url-pattern>/target</url-pattern>
    </servlet-mapping>
</web-app>
package cn.jxufe.a_filter;

import java.io.IOException;
import java.util.Enumeration;

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 FirstFilter implements Filter {

    public FirstFilter() {
        System.out.println("1)过滤器对象创建了!");
    }

    /**
     * FilterConfig对象封装了所有当前过滤器配置的初始化参数 
     * 
     */
    public void init(FilterConfig filterConfig) throws ServletException {
        System.out.println("2)过滤器初始化方法");

        /**
         * 获取初始化参数
         */
        System.out.println(filterConfig.getInitParameter("AAA"));
        // 遍历所有参数
        Enumeration<String> enums = filterConfig.getInitParameterNames();
        while (enums.hasMoreElements()) {
            String paramName = enums.nextElement();
            String paramValue = filterConfig.getInitParameter(paramName);
            System.out.println(paramName + "=" + paramValue);
        }

    }

    /**
     * 执行过滤任务
     */
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException {
        System.out.println("3)过滤器正在执行过滤任务-过滤请求");

        // 放行
        chain.doFilter(request, response);

        System.out.println("5)过滤器正在执行过滤任务--过滤响应");
    }

    /**
     * 过滤器对象销毁的时候才会调用
     *     web项目重新部署或者tomcat服务器停止了才会销毁过滤器对象
     */
    public void destroy() {
        System.out.println("过滤器被销毁了");
    }
}

 

4 FilterChain对象

4.1 简介

FilterChain对象叫做过滤器链对象。

什么是过滤器链?   当一个资源被多个过滤器所过滤,那么就形成了一个过滤器链。

<filter>
        <filter-name>First</filter-name>
        <filter-class>cn.jxufe.b_chain.FirstFilter</filter-class>
    </filter>
    <filter>
        <filter-name>Second</filter-name>
        <filter-class>cn.jxufe.b_chain.SecondFilter</filter-class>
    </filter>

    <filter-mapping>
        <filter-name>First</filter-name>
        <url-pattern>/first</url-pattern>
    </filter-mapping>
    <filter-mapping>
        <filter-name>Second</filter-name>
        <url-pattern>/first</url-pattern>
    </filter-mapping>
package cn.jxufe.b_chain;

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class FirstServlet extends HttpServlet {

    public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        System.out.println("3)执行目标资源代码");
    }

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

}
package cn.jxufe.b_chain;

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 FirstFilter implements Filter {

    @Override
    public void destroy() {
        // TODO Auto-gene rated method stub

    }

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        // TODO Auto-generated method stub

    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException {
        // TODO Auto-generated method stub
        System.out.println("1)执行第一个过滤器的请求过滤");
        // 放行
        /**
         * FilterChian就是过滤器链对象,其中这个doFilter方法作用是把请求或响应交给下一个过滤器,如果没有下一个过滤器,就访问到目标资源了或返回给用户显示。
         * 过滤器链的过滤执行顺序由web.xml文件中过滤器的filter-mapping的顺序决定的,先配置的先被访问到!!!!
         * 
         */

        chain.doFilter(request, response);

        System.out.println("5)执行第二个过滤器的响应过滤");
    }

}
package cn.jxufe.b_chain;

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 SecondFilter implements Filter {

    @Override
    public void destroy() {
        // TODO Auto-gene rated method stub

    }

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        // TODO Auto-generated method stub

    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException {
        // TODO Auto-generated method stub
        System.out.println("2)执行第二个过滤器的请求过滤");
        // 放行
        /**
         * FilterChian就是过滤器链对象,其中这个doFilter方法作用是把请求或响应交给下一个过滤器,如果没有下一个过滤器,就访问到目标资源了或返回给用户显示。
         * 过滤器链的过滤执行顺序由web.xml文件中过滤器的filter-mapping的顺序决定的,先配置的先被访问到!!!!
         * 
         */

        chain.doFilter(request, response);

        System.out.println("4)执行第二个过滤器的响应过滤");
    }

}

5 装饰者模式

1)编写一个BufferedReader装饰者类,继承被装饰者类。(不能是final的)
2)在装饰类中定义一个成员变量,用于接收被装饰者类的对象。
3)在装饰者类的构造方法中传入被装饰者类,使用第二步定义的变量接收被转入的 被装饰者类。    
4)在装饰类类中重写被装饰者类方法,对其方法进行增强。
aaa.txt
123
abc
ABC

需求:对于以上文件输出时,每行增加一个序号和:

package cn.jxufe.c_decorator;

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.io.Reader;

/*
 * 装饰者模式
 */
public class Demo01 {
    /**
     *需求:使用BufferedReader读取一个文件内容
     * @throws IOException 
     */
    public static void main(String[] args) throws IOException {
        // TODO Auto-generated method stub
        BufferedReader b = new BufferedReader(new FileReader("e:/aaa.txt"));
        BufferedReader br = new MyBufferedReader(b);

        String str = null;
        while ((str = br.readLine()) != null) {
            System.out.println(str);
        }
    }
    /**
     * 改造: 在每行名字前面加上一个序号。
     * 解决方案: 希望readLine方法返回给我们的就是一个带序号的内容。对BufferedReader的readLine方法进行增强。这是就可以用到装饰者模式。
     *       装饰者模式的开发步骤:
     *           概念: 装饰者  和 被装饰者  .   BufferedReader就是被装饰者
     *             1)编写一个BufferedReader装饰者类,继承被装饰者类。(不能是final的)
     *          2)在装饰类中定义一个成员变量,用于接收被装饰者类的对象。
     *          3)在装饰者类的构造方法中传入被装饰者类,使用第二步定义的变量接收被转入的 被装饰者类。    
     *             4)在装饰类类中重写被装饰者类方法,对其方法进行增强。
     */
}

/**
 * 1)编写一个BufferedReader装饰者类,继承被装饰者类。(不能是final的) 
 *         BufferedReader(是非final的)
*/
class MyBufferedReader extends BufferedReader {
    /*public MyBufferedReader(){
    super();
    }*/

    /**
     * 2)在装饰类中定义一个成员变量,用于接收被装饰者类的对象。
     */
    private BufferedReader br;

    /**
     *  3)在装饰者类的构造方法中传入被装饰者类,使用第二步定义的变量接收被转入的 被装饰者类。    
     * @param in
     */
    public MyBufferedReader(Reader in) {
        super(in);
        this.br = (BufferedReader) in;
    }

    int count = 1;

    /**
     * 4)在装饰类类中重写被装饰者类方法,对其方法进行增强。
     */
    @Override
    public String readLine() throws IOException {
        // 得到原来的真实的内容
        String content = br.readLine();
        // 加强: 加上序号
        if (content != null) {
            content = count + ":" + content;
            count++;
        }
        return content;
    }
}

6 案例- 请求参数的中文乱码问题               

 

7 案例- 压缩网页内容

用户浏览一个网页:

服务器-> 发送一个网页的内容给用户(1k)

一个用户一天访问10页:  服务器输出10kb内容

 

网站1天10万用户:

100000 * 10kb = 1 000 000kb =  1GB

 

消耗网络带宽。

 

服务器(PC机):

存放网站(网页)

 

服务器收费的:

按流量收费的。如果尽量减少服务器向用户输出数据量,从而减少消耗带宽。

 

要求:在不影响用户浏览效果前提下,减少服务器输出的数据???

 

这时就要用到网页内容的压缩技术!!!!

 

压缩网页的技术: gzip压缩技术

 

GZIPOutputStream类进行网页内容压缩

 

 

8 案例- 登录权限过滤

 

总结:

过滤器:    在请求资源和响应资源时,执行过滤任务。

 

什么是过滤器链?

 

装饰者模式

 

 

猜你喜欢

转载自www.cnblogs.com/xinmomoyan/p/11224669.html