Filter过滤器技术详解

前言

有这样一个常见的开发场景,我们编写一套系统,或者分析一套系统如何实现的过程中,我们肯定会发现这套系统的拦截机制.比如说京东或者淘宝之类的,存在这种拦截机制,这套拦截机制能够过滤掉哪些错误的登录注册请求,或者是一些其他非法请求.这样就在很大的程度上保证了系统的安全性.可以想到,类似的应用场景肯定还有很多,我这里就不一一列举了. 这个场景应用的最基本的技术就是拦截器(Filter)技术,当然我们这里介绍的拦截器只是Servlet技术中的一部分,不涉及到任何框架之类的.要记住,这些最基本的技术是相当重要的,学好基本的东西才能更好的掌握更加高级的东西!

Filter的其他应用

上面我们讲了Filter的基本应用,作为拦截器,拦截哪些错误的或者有攻击性的请求,实际上,过滤器技术还有很多实用性的功能,我们来简单介绍一下:

  • 减少重复代码 比如说之前我们介绍的POST和GET方法的乱码解决方案,显然这种代码如果不进行封装,则会出现在每一个Servlet之中,代码复用率低得很,这时候Filter就能够大显身手了.
  • 实际项目中:判断用户是否登录,只有登录的用户才能进行相应的操作
  • 记录传入的请求
  • 加密和解密(应用在密码上,提高安全性)
  • 例子还有很多,就不再过多列举

Filter在Servlet架构中所处的位置

可以看到,来自用户的请求是率先发送给过滤器的,经过过滤器判断,才能决定是否将请求放行到Servlet之中.到了这一步还不算完成整个过程,请求到达Servlet中后,经过处理,会将相应返回到Filter之中,最后再到达用户.整个工作过程就是这样的.

好了,说了这么多基本的知识,马上就开始我们的实际开发吧

从一个简单的例子开始

下面的这个例子来自于我的小型项目中的一部分,我做了一些删减,力求初学者能够看明白,其他的暂时先不用管,你只需要看doFilter方法中的代码即可.

package com.roobtyan.cn.login;

import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

@WebFilter(filterName = "LoginFilter",urlPatterns = {"/*"})
public class LoginFilter implements Filter {
    private FilterConfig config;

    public void destroy() {
    }

    public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
        //开始一个过滤器
        //取出当前的servlet上下文对象
        ServletContext context = this.config.getServletContext();
        //开始计时
        long startTime = System.currentTimeMillis();
        System.out.println("过滤器开始工作....");
        //let request cast to HttpServletRequest
        HttpServletRequest request = (HttpServletRequest)req;
        request.setCharacterEncoding("utf8");
        //print message
        System.out.println("请求的地址是:" + request.getServletPath());
        //System.out.println(request.getRequestURI());
        //放行
        chain.doFilter(req, resp);
        long endTime = System.currentTimeMillis();
        //print all time
        System.out.println("过滤器工作结束...");
        System.out.println("总计工作时常是: " + (endTime-startTime) + "ms");
    }

    public void init(FilterConfig config) throws ServletException {
        this.config = config;
    }

}

可以看到,这个例子是很简单的,主要的工作就是记录下客户端请求的URL,拿到后直接放行到相应的Servlet中进行处理. 由于servlet3.0之后可以对Filter,Listener,Servlet使用注解配置,我这里就是用了注解配置,个人比较喜欢用这种方法,当然也可以使用web.xml进行配置,我们下面就来介绍一下这两配置方法,以及相应的作用.(对代码进行从上到下的分析)

配置方法

注解配置

@WebFilter(filterName = "LoginFilter",urlPatterns = {"/*"})
......

这种方法,非常简单,filterName就是自定义的过滤器的名字,而urlPatterns就是你到底想要对哪个请求过滤,这里使用的/*就是对所有的请求过滤.这种方法还是非常简单的,就不过多介绍.

web.xml配置

<web-app>  

<filter>  
  <filter-name>...</filter-name>  
  <filter-class>...</filter-class>  
</filter>  

<filter-mapping>  
  <filter-name>...</filter-name>  
  <url-pattern>...</url-pattern>  
</filter-mapping>  

</web-app>

这个Filter的配置和Servlet的配置方法其实是一样的.一个是对Filter类的配置,另外一个就是Filterl类的映射,两个filter-name的值必须是一样的.url-pattern自然也就是拦截的请求地址了. 好了,分析完如何对Filter配置,接下来要做的就是分析一下这几个方法.也就是常用的Filter API. 当然,不论是第一种方法或者第二种方法,都能对指定的URL进行拦截,并且可以是多个.第一种配置方法直接按照这种格式 {“/login”,”/welcome.jsp”};第二种直接在url-pattern下再写上多个url-pattern参数就可以了.

常用的Filter API

Filter

这个接口是过滤器的核心接口,必不可少 常用方法如下:

  • void init(filterConfig) 初始化方法,此方法会在服务器启动的时候运行
  • void doFilter(request,response,filterChain) 过滤器拦截的业务处理方法
  • void destroy() 销毁过滤器时使用.

FilterConfig

这个接口用于获取初始化参数信息 - String getInitParameter(java.lang.String name) - Enumeration getInitParameterNames()

第一个方法是获取特定的初始化参数,第二个是获取全部的初始化参数.

FilterChain

过滤器链参数;一个个过滤器形成一个执行链; 这句话你可能看不太明白,简单的说,这个对象负责调用

用户-过滤器-servlet

这条链中的servlet资源或者是下一个过滤器的. 再简单的说,就是这货能够将过滤操作停止,并将全部的信息向下传送. 仅有的一个方法如下:

public void doFilter(HttpServletRequest request,HttpServletResponse response)
它将控件传递给下一个过滤器或资源。

结语

感谢您的阅读,欢迎指正博客中存在的问题,也可以跟我联系,一起进步,一起交流!

微信公众号:进击的程序狗 邮箱:roobtyan@outlook.com 个人博客:http://roobtyan.cn

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏IT技术精选文摘

基于ZooKeeper的分布式Session实现

1242
来自专栏别先生

基于jsp+servlet图书管理系统之后台用户信息插入操作

前奏:   刚开始接触博客园写博客,就是写写平时学的基础知识,慢慢发现大神写的博客思路很清晰,知识很丰富,非常又价值,反思自己写的,顿时感觉非常low,有相当长...

3886
来自专栏玩转JavaEE

SpringBoot+Vue前后端分离,使用SpringSecurity完美处理权限问题(二)

当前后端分离时,权限问题的处理也和我们传统的处理方式有一点差异。笔者前几天刚好在负责一个项目的权限管理模块,现在权限管理模块已经做完了,我想通过5-6篇文章,来...

1K9
来自专栏有趣的django

35.Django2.0文档

第四章 模板  1.标签 (1)if/else {% if %} 标签检查(evaluate)一个变量,如果这个变量为真(即,变量存在,非空,不是布尔值假),系...

59010
来自专栏安恒网络空间安全讲武堂

Sniper-OJ 练习平台多题WriteUp

题目 ### 图书管理系统(200) ### as fast as you can(50) ### md5-vs-injection(50) ### 2048...

7827
来自专栏技术博文

URI与URL的区别

Web上可用的每种资源 - HTML文档、图像、视频片段、程序等 - 由一个通过通用资源标志符(Universal Resource Identifier, 简...

3316
来自专栏大内老A

EndpointAddress——不只是一个Uri[下篇]

《上篇》对AddressHeader在服务端和客户端的作用,以及如何通过配置和编成的方式设置AddressHeader进行了详细介绍。现在我们通过一个实例来演示...

2107
来自专栏有趣的django

Django rest framework源码分析(1)----认证

一、基础 1.1.安装 两种方式: github pip直接安装 pip install django-rest-framework 1.2.需要先了解的一...

66011
来自专栏alexqdjay

分布式共享Session之SpringSession源码细节

3325
来自专栏编程思想之路

WiFiAp探究实录--功能实现与源码分析

Android虐我千百遍,我待Android如初恋。 ——————编辑于2017-08-02——————— wifi热点说的是wifiAp相...

1.7K9

扫码关注云+社区

领取腾讯云代金券