Filter 可认为是 Servlet 的一种加强版,它主要用于对用户请求进行预处理,也可以对 HttpServletResponse 进行后处理,是个典型的处理链。

Filter 也可对用户请求生成响应,这一点与 Servlet 相同,但实际上很少会使用 Filter 向用户请求生成响应。使用 Filter 完整的流程是:Filter 对用户请求进行预处理,接着将请求交给 Servlet 进行处理并生成响应,最后 Filter 再对服务器响应进行后处理。

Filter 有如下几个用处:

1、在 HttpServletRequest 到达 Servlet 之前,拦截用户的 HttpServletRequest

2、根据需要检查 HttpServletRequest,也可以修改 HttpServletRequest 头和数据

3、在 HttpServletResponse 到达客户端之前,拦截 HttpServletResponse

4、根据需要检查 HttpServletResponse,也可以修改 HttpServletResponse 头和数据

Filter 主要有如下几个种类:

1、用户授权的 Filter:Filter 负责检查用户请求,根据请求过滤用户非法请求。

2、日志 Filter:详细记录某些特殊的用户请求。

3、负责解码的 Filter:包括对非标准编码的请求解码。

4、能改变 XML 内容的 XSLT Filter 等。

5、Filter 可负责拦截多个请求或响应:一个请求或响应也可被多个 Filter 拦截。

创建一个 Filter 只需两个步骤:

1、创建 Filter 处理类

2、web.xml 中配置 Filter

创建 Filter 类

创建 Filter 必须实现 javax.servlet.Filter 接口,在该接口中定义了如下三个方法:

1、void init(FilterConfig config):用于完成 Filter 的初始化

2、void destroy():用于 Filter 销毁前,完成某些资源的回收

3、void doFilter(ServletRequest request, ServletResponse response, FilterChain chain):实现过滤功能,该方法就是对每个请求及响应增加的额外处理。

LogFilter.java

package com.baiguiren;

import java.io.IOException;

import javax.servlet.*;

@WebFilter(filterName="log", urlPatterns={"/*"})
public class LogFilter implements Filter
{
// FilterConfig 可用于访问 Filter 的配置信息
private FilterConfig config; // 实现初始化方法
public void init(FilterConfig config)
{
this.config = config;
} // 实现销毁方法
public void destroy()
{
this.config = null;
} // 执行过滤的核心方法
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException
{
// 下面代码用于对用户请求进行预处理
// 获取 ServletContext 对象,用于记录日志
ServletContext context = this.config.getServletContext();
long before = System.currentTimeMillis();
System.out.println("开始过滤...");
// 将请求转换成 HttpServletRequest 请求
HttpServletRequest hRequest = (HttpServletRequest)request;
// 输出提示信息
System.out.println("Filter 已经拦截到用户请求的地址: " + hRequest.getServletPath()); // Filter 只是链式处理,请求依然放行到目的地址
chain.doFilter(request, response); // 下面代码用于对服务器响应执行后处理
long after = System.currentTimeMillis();
// 输出提示信息
System.out.println("过滤结束");
System.out.println("请求被定位到" + hRequest.gerRequestURI() + " 所花的时间为:" + (after - before));
}
}

  

配置 Filter

配置 FIlter 与配置 Servlet 非常相似,都需要配置如下两个部分。

1、配置 Filter 名

2、配置 Filter 拦截 URL 模式

区别在于:Servlet 通常只配置一个 URL,而 Filter 可以同时拦截多个请求的 URL。因此,在配置 Filter 的 URL 模式时通常会使用模式字符串,使得 Filter 可以拦截多个请求。与配置 Servlet 相似的是,配置 Filter 同样有两种方式。

1、在 Filter 中通过注解进行配置

2、在 web.xml 文件中通过配置文件进行配置。

上面 Filter 类使用了 @WebFilter 配置该 Filter 的名字为 log,它会拦截向 /* 发送的所有的请求。

@WebFilter 属性:

asyncSupported:指定该 Filter 是否支持异步操作模式。

dispatcherTypes:指定该 Filter 仅对哪种 dispatcher 模式的请求进行过滤。该属性支持 ASYNC、ERROR、FORWARD、INCLUDE、REQUEST 这 5 个值得任意组合。默认为同时过滤 5 种模式的请求。

displayName:指定该 FIlter 的显示名

filterName:指定该 FIlter 的名称

initParams:用于为该 FIlter 配置参数

servletNames:该属性值可指定多个 Servlet 的名称,用于指定该 FIlter 仅对这几个 Servlet 执行过滤

urlPatterns/value:这两个属性的作用完全相同。都指定该 FIlter 所拦截的 URL。

web.xml 配置

<!-- 配置 Filter -->
<filter>
<!-- Filter 的名字,相当于指定 @WebFilter 的 filterName 属性 -->
<filter-name>log</filter-name>
<!-- Filter 的实现类 -->
<filter-class>com.baiguiren.LogFilter</filter-class>
</filter>
<!-- 定义 Filter 拦截的 URL 地址 -->
<filter-mapping>
<!-- Filter 的名字 -->
<filter-name>log</filter-name>
<!-- Filter 负责拦截的 URL,相当于指定 @WebFilter 的 urlPatterns 属性 -->
<url-pattern>/*</url-pattern>
</filter-mapping>

  

在实际项目中,Filter 里 doFilter() 方法里的代码就是从多个 Servlet 的 service() 方法里抽取的通用代码,通过使用 Filter 可以实现更好的代码复用。

假设系统包含多个 Servlet,这些 Servlet 都需要进行的一些通用处理:比如权限控制、记录日志等,这将导致在这些 Servlet 的 service 方法中有部分代码是相同的 -- 为了解决这种代码重复的问题,可以考虑把这些通用处理提取到 FIlter 中完成,这样各 Servlet 中剩下的只是特定请求相关的处理代码,而通用处理则交给 FIlter 完成。

Filter 与 Servlet 具有完全相同的生命周期。

下面将定义一个 Filter,该 Filter 对用户请求进行过滤,Filter 将通过 doFilter 方法来设置 request 编码的字符集,从而避免每个 JSP、Servlet 都需要设置;而且还会验证用户是否登录,没有登录则跳转到登录页:

AuthorityFilter.java

package com.baiguiren;

import java.io.IOException;

import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.jsp.*; import javax.servlet.annotation.*; @WebFilter(filterName="authority", urlPatterns={"/*"},
initParams={
@WebInitParam(name="encoding", value="UTF-8"),
@WebInitParam(name="loginPage", value="/login.jsp"),
@WebInitParam(name="proLogin", value="/proLogin.jsp")
}
)
public class AuthorityFilter implements Filter
{
// FilterConfig 可用于访问 Filter 的配置信息
private FilterConfig config; // 实现初始化方法
public void init(FilterConfig config)
{
this.config = config;
} // 实现销毁方法
public void destroy()
{
this.config = null;
} // 执行过滤的核心方法
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException
{
// 获取该 Filter 的配置参数
String encoding = config.getInitParameter("encoding");
String loginPage = config.getInitParameter("loginPage");
String proLogin = config.getInitParameter("proLogin"); // 设置 request 字符集
request.setCharacterEncoding(encoding);
HttpServletRequest requ = (HttpServletRequest)request;
HttpSession session = requ.getSession(true); // 获取客户端请求的页面
String requestPath = requ.getServletPath();
// 如果 session 范围的 user 为 null,即表明没有登录
// 且用户的请求既不是登录页面,也不是处理登录的页面
if (session.getAttribute("user") == null
&& !requestPath.endsWith(loginPage)
&& !requestPath.endsWith(proLogin))
{
// forward 到登录页
request.setAttribute("tip", "你还没有登录!");
request.getRequestDispatcher(loginPage).forward(request, response);
} else {
// 放行请求
chain.doFilter(request, response);
}
}
}

  

上面的代码使用注解配置,也可以在 web.xml 中配置:

<filter>
<filter-name>authority</filter-name>
<filter-class>com.baiguiren.Authority</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
<init-param>
<param-name>loginPage</param-name>
<param-value>/login.jsp</param-value>
</init-param>
<init-param>
<param-name>proLogin</param-name>
<param-value>/proLogin.jsp</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>authority</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>

  

上面的配置保证了普通用户只能访问 login.jsp 和 proLogin.jsp,其他页面都需要登录之后才能访问。

使用 URL Rewrite 实现网站伪静态

对于以 JSP 为表现层开发的动态网站来说,用户访问的 URL 通常有如下形式:

xxx.jsp?name=value...

大部分搜索引擎都会优先考虑收录静态的 HTML 页面,而不是这种动态的 *.jsp、*.php 页面。但实际上大部分网站都是动态的,不可能全部都是静态的 HTML 页面,因此大部分网站都会考虑使用伪静态 -- 就是将 *.jsp 这种动态 URL 伪装成静态的 HTML 页面。

对于 JavaWeb 应用来说,要实现这种伪静态非常简单:可以通过 Filter 拦截所有发向 *.html 的请求,然后按某种规则将请求 forward 到实际的 *.jsp 页面即可。

实现伪静态步骤:

1、到 http://www.tuckey.org/urlrewrite/ 下载 URL Rewrite 的最新版本

2、把上一步下载的 jar 包放在 WEB-INF/lib 目录下

3、在 web.xml 文件中配置启用 URLRewrite Filter,在 web.xml 中增加如下配置片段

4、在应用的 WEB-INF 路径下增加 urlrewrite.xml 文件,该文件定义了伪静态映射规则,这份伪静态规则是基于正则表达式的

urlwrite.xml

<?xml version="1.0" encoding="UTF-8"?>

<urlrewrite>
<rule>
<!-- 所有配置如下正则表达式的请求 -->
<from>/userinf-(\w*).html</from>
<!-- 将被 forward 到如下 JSP 页面,其中 $1 代表上面第一个正则表达式所匹配的字符串 -->
<to type="forward">/userinf.jsp?username=$1</to>
</rule>
</urlrewrite>

  

上面的规则文件中只定义了一个简单的规则:所有发向 /userinf-(\w*).html 的请求都被 forward 到 userinf.jsp 页面,并将 (\w*) 正则表达式所匹配的内容作为 username 参数值。

<%@ page contentType="text/html; charset=UTF-8" %>

<%
// 获取请求参数
String user = request.getParameter("username");
%> <html>
<head>
<title><%=user%>的个人信息</title>
</head>
<body>
<%
out.println("现在时间是: " + new java.util.Date() + "<br/>");
out.println("用户名: " + user);
%>
</body>
</html>

  

Filter 介绍的更多相关文章

  1. Vue filter介绍及详细使用

    Vue filter介绍及其使用 VueJs 提供了强大的过滤器API,能够对数据进行各种过滤处理,返回需要的结果. Vue.js自带了一些默认过滤器例如: capitalize 首字母大写 uppe ...

  2. Filter介绍,运行顺序,实例

    Filter介绍 Filter可觉得是Servlet的一种"变种",它主要用于对用户请求进行预处理,也能够对HttpServletResponse进行后处理,是个典型的处理链. 它 ...

  3. LogStash filter介绍(九)

    LogStash plugins-filters-grok介绍 官方文档:https://www.elastic.co/guide/en/logstash/current/plugins-filter ...

  4. Spring注解驱动第三讲--@Filter介绍

    上一讲主要针对@ComponentScan注解做了一些说明,本文主要对@Filter的扫描条件,再做一些详细的介绍 1,FilterType.ANNOTATION 按照注解的方式进行扫描.后面clas ...

  5. Filter介绍

    Filter可人为是Servlet的一种“加强版”,它重要用于对用户请求进行预处理,也可以对HttpServletResponse进行后处理,是个典型的处理链.使用Filter的完整的流程是:Filt ...

  6. 【solr filter 介绍--转】http://blog.csdn.net/jiangchao858/article/details/54989025

    Solr的Analyzer分析器.Tokenizer分词器.Filter过滤器的区别/联系 Analyzer负责把文本字段转成token stream,然后自己处理.或调用Tokenzier和Filt ...

  7. Kalman Filter、Extended Kalman Filter以及Unscented Kalman Filter介绍

    模型定义 如上图所示,卡尔曼滤波(Kalman Filter)的基本模型和隐马尔可夫模型类似,不同的是隐马尔科夫模型考虑离散的状态空间,而卡尔曼滤波的状态空间以及观测空间都是连续的,并且都属于高斯分布 ...

  8. ASP.NET MVC5学习笔记之Filter基本介绍

    Filter是ASP.NET MVC框架提供的基于AOP(面向方面)设计,提供在Action执行前后做一些非业务逻辑通用处理,如用户验证,缓存等.现在来看看Filter相关的一些类型信息. 一.基本类 ...

  9. Filter的执行顺序及实例

    学习中的收藏,该文出自http://www.cnblogs.com/Fskjb/archive/2010/03/27/1698448.html 在此,非常感谢该文章作者的分享,本文完全转载自上面链接, ...

随机推荐

  1. JavaScript学习笔记(三)——对象

    第四章 理解对象 1 说明 对象的状态:属性,行为:方法: 对象定义放在花括号内: 用冒号分隔属性名和属性值: 用逗号分隔属性名和属性值对,包括方法: 最后一个属性值后面不加逗号: 属性名可以是任何字 ...

  2. 《Cocos2d-x游戏开发实战精解》学习笔记3--在Cocos2d-x中播放声音

    <Cocos2d-x游戏开发实战精解>学习笔记1--在Cocos2d中显示图像 <Cocos2d-x游戏开发实战精解>学习笔记2--在Cocos2d-x中显示一行文字 之前的内 ...

  3. [转]C#学习笔记15——C#多线程编程

    一.基本概念进程:当一个程序开始运行时,它就是一个进程,进程包括运行中的程序和程序所使用到的内存和系统资源.而一个进程又是由多个线程所组成的.线程:线程是程序中的一个执行流,每个线程都有自己的专有寄存 ...

  4. Centos 7 zabbix 实战应用

    实际需求:公司已经有了100台服务器,现在需要使用zabbix全部监控起来. 先出个方案(规划) 常规监控:cpu,内存,磁盘,网卡 问题:怎样快速添加100台机器         方法1:使用克隆的 ...

  5. 第四周 实验一 Java开发环境的熟悉 报告

    Java开发环境的熟悉 实验内容 1.IDEA的安装过程 2.使用IDEA代替虚拟机运行.编译.调试Java程序 实验要求 1.没有Linux基础的同学建议先学习<Linux基础入门(新版)&g ...

  6. Python:模块学习——os模块

    os模块提供了多个访问操作系统服务的功能 os模块中一些重要的函数和变量 os.name 显示当前使用平台 os.getcwd() 显示当前Python脚本工作路径 os.listdir('dirna ...

  7. Educational Codeforces Round 16 E. Generate a String dp

    题目链接: http://codeforces.com/problemset/problem/710/E E. Generate a String time limit per test 2 seco ...

  8. 一些有趣的erlang项目

    这里会收集一些erlang项目,有需可以转. erlang-bookmarks Scaling Erlang High Performance Erlang - Finding Bottlenecks ...

  9. C语言文法推导

  10. QJsonDocument实现Qt下JSON文档读写

    版权声明:若无来源注明,Techie亮博客文章均为原创. 转载请以链接形式标明本文标题和地址: 本文标题:QJsonDocument实现Qt下JSON文档读写     本文地址:http://tech ...