IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> Java知识库 -> 深度好文之Servlet技术详解(十一)Filter过滤器 -> 正文阅读

[Java知识库]深度好文之Servlet技术详解(十一)Filter过滤器

目录

一.过滤器作用

二.Filter对象的创建

三.在Filter中设置请求编码

四.FilterConfig对象的使用

五.FilterChain(过滤器链)

六.基于注解式开发Filter

?七.Filter的生命周期 ?


一.过滤器作用

Filter 过滤器是 Servlet2.3 中所提供的一个过滤请求与响应的对象。
Filter 过滤器既可以对客户端向服务器端发送的请求进行过滤,也可以对服务器端向客户端产生的响应进行过滤处理。

二.Filter对象的创建

创建一个 Class 实现 Filter 接口,并实现接口中三个抽象方法。
  • init()方法:初始化方法,在创建Filter后立即调用。可用于完成初始化动作。
  • doFilter()方法:拦截请求与响应方法,可用于对请求和响应实现预处理。
  • destroy()方法:销毁方法,在销毁Filter之前自动调用。可用于完成资源释放等动作。

容器启动时,就会创建Filter对象,Filter对象被实例化后会立即调用init函数,容器关闭时,才会销毁Filter对象。

FirstFilter.java:
package com.first.filter;

import javax.servlet.*;
import java.io.IOException;

public class FirstFilter implements Filter {
    /*
    当Filter对象被实例化后,会立即调用的一个方法
     */
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        System.out.println("Init......");
    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        //对请求进行处理
        System.out.println("请求被过滤");
        //对请求做放行处理
        filterChain.doFilter(servletRequest,servletResponse);
        //对响应进行处理
        System.out.println("响应被过滤");
    }

    /*
    当Filter对象在销毁之前会调用一次该方法
     */
    @Override
    public void destroy() {

    }
}

配置web.xml:

配置和servlet的配置差不多,放在<web-app>标签内

路径配置为/test/*,和上节的AnnotationServlet.java路径一样,给此servlet过滤

    <filter>
        <filter-name>firstFilter</filter-name>
        <filter-class>com.first.filter.FirstFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>firstFilter</filter-name>
        <url-pattern>/test/*</url-pattern>
    </filter-mapping>

输出:

控制台输出:

请求被过滤
响应被过滤

三.Filter中设置请求编码

需求:在 Filter 中实现对请求的编码的设置。
实际应用原因:因为当有多个servlet接受客户端请求时,而此时客户端的数据都包含了中文,如果一个个servlet去单独设置编码的话效率太低,所以可以直接在过滤器中设置编码!

控制台如果乱码的话那就是请求编码没设置。

以之前添加用户的例子(戳这里)稍加修改做演示:

getRequestDataServlet.java:

package com.first.servlet;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.*;

/*
获取请求数据
 */
public class getRequestDataServlet extends HttpServlet {
    @Override
    //客户端是以post方式传递的数据,所以这里要用doPost函数
    //Tomcat拿到请求后会对请求做解析,解析出的数据会放到req对象当中
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //设置请求编码,这个必须放在获取请求数据之前,否则无效
        //将请求编码注释掉,检测Filter的作用
        //req.setCharacterEncoding("utf-8");

        //获取用户名
        String username=req.getParameter("username");
        //获取用户密码
        String password=req.getParameter("password");

        //获取复选框中被选中的数据
        String[] hobbies=req.getParameterValues("hobbies");
        //转化为列表
        List<String> list= Arrays.asList(hobbies);

        //获取表单中的所有的key
        Enumeration<String> parameterNames=req.getParameterNames();
        List<String> paraList=new ArrayList<>();
        while(parameterNames.hasMoreElements()){
            paraList.add(parameterNames.nextElement());
        }

        //使用Map结构获取提交数据
        Map<String,String[]> parameterMap=req.getParameterMap();
        Iterator<Map.Entry<String,String[]>> iterator=parameterMap.entrySet().iterator();

        resp.setContentType("text/plain;charset=utf-8");
        PrintWriter pw=resp.getWriter();
        pw.println("username:"+username);
        //在控制台输出username,看是否乱码
        //System.out.println(username);

        pw.println("password:"+password);
        pw.println("hobbies:"+list);
        pw.println("all_key:"+paraList);
        while(iterator.hasNext()){
            Map.Entry<String,String[]> entry=iterator.next();
            String key=entry.getKey();
            String[] value=entry.getValue();
            //要转化成列表再输出,直接输出value输出的是数组的地址
            pw.println(key+" = "+Arrays.asList(value));
        }
        pw.flush();
        pw.close();
    }
}

addUser.html:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<!--action加个../是为了从test目录里跳出,最前面加个/是因为Context Path用了绝对路径/,
所以在最前面才可以加/,也可以不加/-->
<form action="getRequestData.do" method="post">
    用户名:<input type="text" name="username"><br>
    密码:<input type="password" name="password"><br>

    爱好:<input type="checkbox" name="hobbies" value="sports">体育
    <input type="checkbox" name="hobbies" value="music">音乐
    <input type="checkbox" name="hobbies" value="art">艺术<br>
    <input type="submit" value="OK">
</form>
</body>
</html>

配置web.xml:

路径配置为/*,即匹配所有路径

    <filter>
        <filter-name>EncodingFilter</filter-name>
        <filter-class>com.first.filter.EncodingFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>EncodingFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

EncodingFilter.java:

package com.first.filter;

import javax.servlet.*;
import java.io.IOException;

public class EncodingFilter implements Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {

    }

    @Override
    public void destroy() {

    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        //设置请求编码
        servletRequest.setCharacterEncoding("utf-8");
        //对请求做放行处理
        filterChain.doFilter(servletRequest,servletResponse);
    }
}

输出:

控制台输出的username也没乱码,可见配置成功!

四.FilterConfig对象的使用

FilterConfig对象是用来读取<filter> <init-param> 初始化参数的对象。该对象通过参数传递到init方法中,用于读取初始化参数。
filterConfig.getInitParameter("name")
通过 name 获取对应的 value
filterConfig.getInitParameterNames()
返回该 Filter中所有<param-name> 中的值。

?

对上一个编码的例子进行改造

    <filter>
        <filter-name>EncodingFilter</filter-name>
        <filter-class>com.first.filter.EncodingFilter</filter-class>
<!--        通过修改<param-value>达到灵活设置请求编码的功能-->
        <init-param>
            <param-name>code</param-name>
            <param-value>utf-8</param-value>
        </init-param>
    </filter>
    <filter-mapping>
        <filter-name>EncodingFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

EncodingFilter.java:

package com.first.filter;

import javax.servlet.*;
import java.io.IOException;

public class EncodingFilter implements Filter {

    //设置默认编码
    private String defaultCode = "utf-8";
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        String code=filterConfig.getInitParameter("code");
//        如果web.xml中没有配置编码,那么就使用默认编码
        if (code!=null && code.length()>0){
            this.defaultCode = code;
        }
    }

    @Override
    public void destroy() {

    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        //设置请求编码
        servletRequest.setCharacterEncoding(this.defaultCode);
        //对请求做放行处理
        filterChain.doFilter(servletRequest,servletResponse);
    }
}

可以再运行addUser.html测试一下。

五.FilterChain(过滤器链)

Filter 技术的特点是在对请求或响应做预处理时,可实现 插拔式 的程序设计。我们可以根据自己需求添加多个 Filter ,也可以根据需求 去掉某个 Filter ,通过修改 web.xml 文件即可实现。那么如果有多个 过滤器对某个请求及响应进行过滤,那么这组过滤器就称为过滤器 链。

Filter 执行顺序
则按照在 web.xml 文件中配置的上下顺序来决定先后。在上的先执行,在下的后执行。

?

六.基于注解式开发Filter

Filter 支持注解式开发,通过 @WebFilter 注解替代 web.xml Filter的配置。

使用注解式开发 Filter 时,执行顺序会根据 Filter 名称 进行排序的结果决定调用的顺序,即按字典序的是顺序排序。
当web.xml文件和注解都配置了Filter时,web.xml文件里面的配置优先级更高。
配置示例:
和servlet注解配置大同小异

?

?七.Filter的生命周期 ?

Filter 的生命周期是由容器管理的。当容器启动时会实例化 Filter 并调用 init 方法完成初始化动作。当客户端浏览器发送请求时,容器会 启动一个新的线程来处理请求,如果请求的 URL 能够被过滤器所匹 配,那么则先调用过滤器中 的 doFilter 方法,再根据是否有 chain.doFilter 的指令,决定是否继续请求目标资源。当容器关闭时 会销毁 Filter 对象,在销毁之前会调用 destroy 方法。

?

  Java知识库 最新文章
计算距离春节还有多长时间
系统开发系列 之WebService(spring框架+ma
springBoot+Cache(自定义有效时间配置)
SpringBoot整合mybatis实现增删改查、分页查
spring教程
SpringBoot+Vue实现美食交流网站的设计与实
虚拟机内存结构以及虚拟机中销毁和新建对象
SpringMVC---原理
小李同学: Java如何按多个字段分组
打印票据--java
上一篇文章      下一篇文章      查看所有文章
加:2022-05-07 11:02:36  更:2022-05-07 11:04:34 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/23 23:48:55-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码