一、什么是Web过滤器
Servlet API 很久以前就已成为企业应用开发的基石,而 Servlet 过滤器则是对 J2EE 家族的相对较新的补充。
Servlet 过滤器是可插入的 Web 组件,它允许我们实现 Web 应用程序中的预处理和后期处理逻辑。过滤器支持 servlet 和 JSP 页面的基本请求处理功能,比如日志记录、性能、安全、会话处理、XSLT 转换,等等。 过滤器最初是随 Java Servlet 2.3 规范发布的。
Servlet 过滤器是什么?
Servlet 过滤器是小型的 Web
组件,它们拦截请求和响应,以便查看、提取或以某种方式操作正在客户机和服务器之间交换的数据。过滤器是通常封装了一些功能的 Web
组件,这些功能虽然很重要,但是对于处理客户机请求或发送响应来说不是决定性的。典型的例子包括记录关于请求和响应的数据、处理安全协议、管理会话属性,
等等。过滤器提供一种面向对象的模块化机制,用以将公共任务封装到可插入的组件中,这些组件通过一个配置文件来声明,并动态地处理。
Servlet 过滤器中结合了许多元素,从而使得过滤器成为独特、强大和模块化的 Web 组件。也就是说,Servlet 过滤器是:
声明式的:过滤器通过 Web 部署描述符(web.xml)中的 XML 标签来声明。这样允许添加和删除过滤器,而无需改动任何应用程序代码或 JSP 页面。
动态的:过滤器在运行时由 Servlet 容器调用来拦截和处理请求和响应。
灵活的:过滤器在 Web
处理环境中的应用很广泛,涵盖诸如日志记录和安全等许多最公共的辅助任务。过滤器还是灵活的,因为它们可用于对来自客户机的直接调用执行预处理和后期处
理,以及处理在防火墙之后的 Web 组件之间调度的请求。最后,可以将过滤器链接起来以提供必需的功能。
模块化的:通过把应用程序处理逻辑封装到单个类文件中,过滤器从而定义了可容易地从请求/响应链中添加或删除的模块化单元。
可移植的:与 Java 平台的其他许多方面一样,Servlet 过滤器是跨平台和跨容器可移植的,从而进一步支持了 Servler 过滤器的模块化和可重用本质。
可重用的:归功于过滤器实现类的模块化设计,以及声明式的过滤器配置方式,过滤器可以容易地跨越不同的项目和应用程序使用。
透明的:在请求/响应链中包括过滤器,这种设计是为了补充(而不是以任何方式替代)servlet 或 JSP 页面提供的核心处理。因而,过滤器可以根据需要添加或删除,而不会破坏 servlet 或 JSP 页面。
所以 Servlet
过滤器是通过一个配置文件来灵活声明的模块化可重用组件。过滤器动态地处理传入的请求和传出的响应,并且无需修改应用程序代码就可以透明地添加或删除它们。最后,过滤器独立于任何平台或者 Servlet 容器,从而允许将它们容易地部署到任何相容的 J2EE 环境中。
二、第一个过滤器
package com.po; 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() {
System.out.println("destroy");
} @Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
System.out.println("doFilter: " + request.toString());
chain.doFilter(request, response);
} @Override
public void init(FilterConfig filterConfig) throws ServletException {
System.out.println("init: " + filterConfig.toString());
}
}
过滤器需要实现 Filter 接口:
init():这个方法在容器实例化过滤器时被调用,它主要设计用于使过滤器为处理做准备。该方法接受一个 FilterConfig 类型的对象作为输入。
doFilter():
与 servlet 拥有一个 service() 方法(这个方法又调用 doPost() 或者
doGet())来处理请求一样,过滤器拥有单个用于处理请求和响应的方法——doFilter()。这个方法接受三个输入参数:一个
ServletRequest、response 和一个 FilterChain 对象。
destroy():正如您想像的那样,这个方法执行任何清理操作,这些操作可能需要在自动垃圾收集之前进行。展示了一个非常简单的过滤器,它跟踪满足一个客户机的 Web 请求所花的大致时间。
三、配置 web.xml ,启用过滤器
先来看下这个图:
现在,我们在 web.xml 中,添加这些 xml 内容:
<!-- 过滤器配置 -->
<filter>
<filter-name>FirstFilter</filter-name>
<filter-class>com.po.FirstFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>FirstFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
filter 标签用来声明一个过滤器,每个过滤器只能有一个filter标签。
filter-mapping 标签用来指定过滤器的作用对象。上面的示例中 url-pattern 设定为了 "/*", 代表对所有jsp请求有效。
更改为 web.xml 后,需要重启 tomcat 服务器。
在重启服务器时,我们可以在控制台日志中看到我们的过滤器 init() 被调用了。
在浏览器 中访问一个页面,doFilter 会被执行。
四、 常见问题
1. 过滤器是否能够改变用户请求的WEB资源呢? 也就是能否改变用户请求的路径?
回答: 能。比如检测到用户没有登录,可以请WEB资源指向到登录页面。
2. 过滤器能否直接返回数据,能不能直接处理用户请求?
回答: 不能。因为过滤器不是一样标准的 Servlet ,它不能直接返回数据。它要是么指向一个WEB资源,要么是重定向到其它的WEB资源。
五、多个过滤器
WEB服务程序是可以支持多个过滤器的。
假如一个URL和多个过滤器指定的URL相符时,会生成一个过滤器链。
服务器会按照web.xml中过滤器定义的先后顺序组装成过滤器链。
过滤器链的执行过程:
六、过滤器的分类
过滤器默认是 Request 类型。
FORWARD 过滤器:
<filter>
<filter-name>FirstFilter</filter-name>
<filter-class>com.po.FirstFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>FirstFilter</filter-name>
<url-pattern>/index.jsp</url-pattern>
<dispatcher>FORWARD</dispatcher>
</filter-mapping>
INCLUDE 过滤器和 FORWARD 声明类似,将dispatcher改为INCLUDE就可以了。
错误过滤器:
<!-- 错误过滤器 -->
<error-page>
<error-code>404</error-code>
<location>/error.jsp</location>
</error-page> <filter>
<filter-name>ErrorFilter</filter-name>
<filter-class>com.po.ErrorFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>ErrorFilter</filter-name>
<url-pattern>/error.jsp</url-pattern>
<dispatcher>ERROR</dispatcher>
</filter-mapping>
在 Servlet 3.0 及之后的版本中,增加了异步支持。还增加使用注解的方式来定义过滤器(也就是说不需要我们修改 web.xml)了。
七、 @WebFilter 注解定义过滤器
我们先来看看 @WebFilter的常用属性。
示例: (错误过滤器)
package com.po; import java.io.IOException; import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.annotation.WebFilter; @WebFilter(
filterName="ErrorFilter",
value={"/error.jsp"},
dispatcherTypes={javax.servlet.DispatcherType.ERROR})
public class ErrorFilter implements Filter { @Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
System.out.println("doFilter start.");
chain.doFilter(request, response);
System.out.println("doFilter end.");
} }
上面的代码,使用注解来定义过滤器。
下面是异步过滤的示例:
首先是新建一个Servlet,这个Servlet用来处理复杂的异步事务。
package servlet; import java.io.IOException;
import javax.servlet.AsyncContext;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; @WebServlet(name="AsyncServlet",asyncSupported=true,urlPatterns={"/servlet/AsyncServlet"},description="异步过滤器示例Servlet")
public class AsyncServlet extends HttpServlet {
private static final long serialVersionUID = 1L; @Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("业务请求开始.");
AsyncContext context = req.startAsync();
// 开启异步线程
new Thread(new Executor(context)).start();
// req.getRequestDispatcher("/index.jsp").forward(req, resp);
// resp.getWriter().close();
System.out.println("业务请求结束.");
} public class Executor implements Runnable {
private AsyncContext context; public Executor(AsyncContext context) {
this.context = context;
} @Override
public void run() {
try {
// 复杂业务处理
System.out.println(context.getRequest().getScheme());
Thread.sleep(10 * 1000);
System.out.println("业务执行完成.");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
} }
接下来,建立一个异步过滤器。
package servlet; import java.io.IOException; import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.annotation.WebFilter; @WebFilter(filterName="AsyncFilter",
urlPatterns={"/servlet/AsyncServlet"},
asyncSupported=true,
dispatcherTypes={javax.servlet.DispatcherType.ASYNC}
)
public class AsyncFilter implements Filter { @Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
chain.doFilter(request, response);
} }
异步过滤器的特性就是能很快的响应用户请求,复杂的业务处理过程放到新的线程中执行。
当然了,在我们上面的示例代码中, AsyncServlet.onGet里面只是启动一个业务处理线程,并没写响应的代码,所以会导致客户端出现一个 500 错误。实际业务中,输出
【感谢】
[Java] JSP笔记 - Filter 过滤器的更多相关文章
-
Java 中的 Filter 过滤器详解
Filter简介 Filter也称之为过滤器,它是Servlet技术中最实用的技术,WEB开发人员通过Filter技术,对web服务器管理的所有web资源:例如Jsp, Servlet, 静态图片文件 ...
-
Java中的Filter过滤器
Filter简介 Filter也称之为过滤器,它是Servlet技术中最实用的技术,Web开发人员通过Filter技术,对web服务器管理的所有web资源:例如Jsp, Servlet, 静态图片文件 ...
-
j2ee学习笔记 Filter过滤器
作用:过滤response和request对象的内容 使用: Filter是J2EE的一个接口,自定义Filter需要实现该接口,并重写所有的方法. Filter提供的方法: init() doFil ...
-
Java精选笔记_Filter(过滤器)
Filter(过滤器) Filter入门 什么是Filter Filter被称作过滤器或者拦截器,其基本功能就是对Servlet容器调用Servlet的过程进行拦截,从而在Servlet进行响应处理前 ...
-
Java Web进阶——Filter过滤器
一.过滤器的介绍: 在Servlet规范2.3中定义了过滤器,它是一个服务器端的组件,可以截取用户端的请求与响应信息,并且对这些信息进行过滤. Servlet过滤器本身并不生成请求和响应对象,只是提供 ...
-
JAVA JSP笔记
一.jsp加载项目中资源图片 如果直接将静态页面写的代码copy到jsp中,你会发现图片都无法加载. 获取代码: String path = request.getContextPath(); Str ...
-
[Java] JSP笔记 - 自定义标签
自定义标签的创建步骤: 自定义标签的四大功能: 自定义标签的类结构: 在 1.0 中呢, 可以将 <body-content> 的值设置为 JSP, 2.0中则不允许在自定义标签体中出现j ...
-
[Java] JSP笔记 - Listener 监听器
Java Web 开发时,可以使用 Listener 来监听来监听一些事件,从而实现一些功能.实际上这个监听器,原理就是 Delphi 中大家常用的各种事件. 1. 那么,监听器的主要用途用哪些呢: ...
-
[Java] JSP笔记 - EL、JSTL 常用标签
一. 什么是 EL 语言 表达式语言(EL)是 JSP 2.0 引入的一种计算和输出 Java 对象的简单语言. 二.EL 语言的作用 为了使JSP写起来更加简单.表达式语言的灵感来自于 ECMASc ...
随机推荐
-
JMeter学习(三十五)使用jmeter来发送json/gzip格式数据
一.使用jmeter来发送gzip数据 有时候我们需要模拟在客户端将数据压缩后, 发送(post)到服务器端. 通常这种情况,会发生在移动终端上. 这样做的好处, 是可以节省流量. 当然, 服务器返 ...
-
HTML5 History 模式
vue-router 默认 hash 模式 -- 使用 URL 的 hash 来模拟一个完整的 URL,于是当 URL 改变时,页面不会重新加载. 如果不想要很丑的 hash,我们可以用路由的 his ...
-
WAS集群服务的关闭与启动
WAS集群服务的关闭与启动 欢迎转载,转载时请务必注明出处(http://blog.csdn.net/huangyanlong),否则作者保留追究版权法律责任. 表述有错误之处,请您留言或邮件(hyl ...
-
初始Android-配置环境
最近闲来无事自学了一下Android,今天没事想整理一下思绪,简单的介绍一下我自己对环境配置的认识,仅供参考,欢迎提出意见. 1.首先打开Eclipse,然后安装ADT,准备好ADTjar包或者zip ...
-
thinkpaidE480office安装文件夹
C:\Program Files (x86)\Microsoft Office\root\Office16 需要嵌入office的小伙伴自行百度吧教程吧,网上有很多的
-
HTML第三耍 图像标签
复习一下第二耍: <!doctype html> <html> <head> <meta charset="utf-8"> < ...
-
精简版自定义 jquery
function $(id) { var el = 'string' == typeof id ? document.getElementById(id) : id; el.on = function ...
-
emptyDir与hostPath
目录 Volume类型 emptyDir hostPath Volume类型 volume是kubernetes Pod中多个容器访问的共享目录.volume被定义在pod上,被这个pod的多个容器挂 ...
-
编写Shell脚本
1.脚本的编写 Shell脚本本身是一个文本文件,这里编写一个简单的程序,在屏幕上显示一行helloworld! 脚本内容如下: #!/bin/bash #显示“Hello world!" ...
-
ArcGIS三种方式打断相交线------Feature To Line工具
有多个layer图层相交线时,选用”Feature To Line“工具,将多个图层相交线打断,然后合并成一个图层. (1) 选择工具栏”Geoprocessing“中的”ArcToolb ...