J2EE中的过滤器和拦截器
过滤器和拦截器的相似之处就是拦截请求,做一些预处理或者后处理。
而过滤器和拦截器的区别在于过滤器是相对HTTP请求而言的,而拦截器是相对Action中的方法的。
过滤器:访问web服务器的时候,对一个请求,我们可以设置请求编码,设置请求参数,设置其是否能访问某个页面,设置相应编码等。
拦截器:访问web服务器的时候,在你调用的方法前做一个拦截,加上我想要的任意操作。比喻记录操作日志,加上某个特定业务(AOP)。
1、过滤器
过滤器需要做两部分的工作:Filter过滤类、web.xml配置
Filter类部分:
package com.chanshuyi.servlet; 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;
//import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest; /**
* Test Servlet Filter
* @author chenyr
*/
//@WebFilter(filterName = "myfilter", urlPatterns = {"/*.*"})
//你可以通过这段注释来声明这个Filter,从而不用在web.xml文件中配置,但你用的Servlet版本必须是3.0以上
public class MyServletFilter implements Filter { /** Filter Config Info **/
private FilterConfig config; public void init(FilterConfig config) throws ServletException {
this.config = config;
} public void destroy() {
this.config = null;
} public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
//-------- Preprocess --------
long before = System.currentTimeMillis();
System.out.println("Begin filtering...");
HttpServletRequest hrequest = (HttpServletRequest)request;
System.out.println("Intercept the user request address:" + hrequest.getServletPath()); //-------- Do the Servlet --------
chain.doFilter(request, response); //-------- afterprocess --------
long after = System.currentTimeMillis();
System.out.println("End filtering...");
System.out.println("Redirect To:" + hrequest.getRequestURI() + " Time Cost:" + (after - before));
}
}
web.xml部分:
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5"
xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
<filter>
<filter-name>myfilter</filter-name>
<filter-class>com.chanshuyi.servlet.MyServletFilter</filter-class>
</filter> <filter-mapping>
<filter-name>myfilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
</web-app>
2、拦截器
Struts的拦截器本质上还是通过过滤器来实现的。
拦截器实现需要做两部分的工作:Interceptor过滤类、struts.xml配置
拦截器类:
package com.chanshuyi.interceptor; import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.interceptor.AbstractInterceptor; @SuppressWarnings("serial")
public class MyInterceptor extends AbstractInterceptor { private String name; public void setName(String name) {
this.name = name;
} @Override
public String intercept(ActionInvocation invocation) throws Exception { //get the target action
//LoginAction action = (LoginAction)invocation.getAction();
System.out.println(name + "Interceptor begin to work ...");
long startMill = System.currentTimeMillis(); //execute the target action method
String result = invocation.invoke(); long endMill = System.currentTimeMillis();
System.out.println(name + "Interceptor ends, time cost:" + (endMill - startMill));
System.out.println("result is : " + result); return result;
}
}
你可以通过实现Interceptor接口来实现拦截器。但是Java为我们提供了AbstractInterceptor类,通过实现AbstractInterceptor类可以让我们减少编码(因为AbstractInterceptor已经帮我们实现了init()/destory()方法,我们只需再实现interceptor方法即可)
struts.xml配置部分:
<struts>
<package name="default" namespace="/" extends="struts-default">
<interceptors>
<interceptor name="loginInter" class="com.chanshuyi.interceptor.MyInterceptor">
<param name="name">[默认的拦截器名字]</param>
</interceptor>
</interceptors> <action name="login" class="com.chanshuyi.action.LoginAction" method="execute">
<result name="success">/hello.jsp</result>
<result name="login">/hello.jsp</result> <interceptor-ref name="defaultStack"/>
<interceptor-ref name="loginInter">
<param name="name">[修改后的拦截器名字]</param>
</interceptor-ref>
</action>
</package>
</struts>
MARK CHENYR (这里需要补充)
3、只拦截部分Action部分方法的拦截器
通过继承AbstractInterceptor的子类:MethodFilterInterceptor类,可以实现对Action中方法级的过滤。
它与继承AbstractInterceptor实现过滤在代码上的不同在于:
1).需要继承的是MethodFilterInterceptor类
2).需要实现的是doInterceptor方法,而不是interceptor方法
3).可以通过setExcludeMethod/setIncludeMethod方法或配置文件的方式实现方法的过滤
拦截器部分代码(将intercept方法换成doIntercept即可):
@SuppressWarnings("serial")
public class CopyOfMyInterceptor extends MethodFilterInterceptor { private String name; public void setName(String name) {
this.name = name;
} @Override
public String doIntercept(ActionInvocation invocation) throws Exception { //get the target action
//LoginAction action = (LoginAction)invocation.getAction();
System.out.println(name + "Interceptor begin to work ...");
long startMill = System.currentTimeMillis(); //直接调用setExcludeMethod/setIncludeMethod方法给excludeMethod/includeMethod属性赋值。这与用配置文件赋值是一样的 //execute the target action method
String result = invocation.invoke(); long endMill = System.currentTimeMillis();
System.out.println(name + "Interceptor ends, time cost:" + (endMill - startMill));
System.out.println("result is : " + result); return result;
}
}
通过配置文件实现对方法的过滤:
<struts>
<package name="default" namespace="/" extends="struts-default">
<interceptors>
<interceptor name="loginInter" class="com.chanshuyi.interceptor.MyInterceptor">
<param name="name">[默认的拦截器名字]</param>
</interceptor>
</interceptors> <action name="login" class="com.chanshuyi.action.LoginAction" method="execute">
<result name="success">/hello.jsp</result>
<result name="login">/hello.jsp</result> <interceptor-ref name="defaultStack"/>
<interceptor-ref name="loginInter">
<param name="name">[修改后的拦截器名字]</param>
<!-- 多个方法用英文逗号隔开 -->
<param name="excludeMethods">execute</param>
<!-- 通过配置文件赋值,本质上是给继承了MethodFilterInterceptor的CopyOfMyInterceptor类的excludeMethods属性复制。所以你也可以不在这里复制,而直接在CopyOfMyInterceptor类中用setExcludedMethod/setIncludeMethod赋值 -->
</interceptor-ref>
</action>
</package>
</struts>
4、关于过滤器和拦截器的执行顺序
在一般情况下,过滤器和拦截器都是先配置先执行的。
下面用过滤器的一个例子说明:
web.xml部分代码:
<!-- 第一个过滤器 -->
<filter>
<filter-name>filter1</filter-name>
<filter-class>filter.Filter1</filter-class>
</filter>
<filter-mapping>
<filter-name>filter1</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<!-- 第二个过滤器 -->
<filter>
<filter-name>filter2</filter-name>
<filter-class>filter.Filter2</filter-class>
</filter>
<filter-mapping>
<filter-name>filter2</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
Filter1类的关键代码:
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
try {
System.out.println("filter1");
chain.doFilter(request, response);
System.out.println("filter1 go back");
} catch (Exception e) {
e.printStackTrace();
}
}
Filter2类与Filter1类一样,只是输出内容变成了“filter2”以及“filter2 go back”。
运行结果为:
filter1
filter2
filter2 go back
filter1 go back
可以看出,过滤器和拦截器的执行顺序是先定义先执行,并且执行是类似于堆栈的先进后出的执行顺序。
5、关于过滤器和拦截器的思考
在说拦截器和过滤器之前,先说这两者的几点区别:
1.过滤器可以对所有HTTP请求进行拦截,但拦截器只能对Action请求进行拦截
2.过滤器是Servlet中的概念,拦截器是Struts中的概念
在Struts还没有出来的时候,拦截器这个概念是不存在的。在Struts出来之后,拦截器也来了。拦截器是通过Servlet来实现的,拦截器对过滤器进行了一层封装,使Struts框架更加好用。
在使用了Struts框架的项目中,更多人直接使用拦截器,过滤器的概念就被弱化了。这是我的一些理解。因此在使用了Struts的项目中,你可以直接使用拦截器对所有Action请求进行拦截,对他们进行权限控制。
但拦截器不能拦截直接访问的页面,那这些页面如何保障权限的控制呢?答案是将页面房在WEB-INF目录下(WEB-INF目录下的文件不能通过客户端直接访问),只将少数必要的文件放在Web-Root目录,这样就可以实现这些页面的安全。
总的来说,如果你的项目使用了Struts,那么你可以直接用Struts的拦截器实现权限控制等。
但如果你的项目是用纯Servlet写的,那么你只能用过滤器实现了。
===================== 相信美好的事情终会发生 ====================
struts.xml文件中拦截器配置集锦
<!-- 配置拦截器 -->
<interceptor name="interceptor1" class="classRoute"/>
<interceptor name="interceptor1" class="classRoute">
<param name="paraName">Param Value</param>
</interceptor>
<!-- 拦截器栈 -->
<interceptor-stack name="stackName">
<interceptor name="interceptor1" class="classRoute"/>
<interceptor-ref name="interceptorName">
<param name="paraName">Param Value</param>
</interceptor-ref>
</interceptor-stack>
<!-- 使用拦截器 -->
<action name="" class="" method="">
<result>...</result>
<!-- 一定要加上Struts的默认拦截器 -->
<interceptor-ref name="defaultStack"/>
<!-- 使用自己的拦截器 -->
<interceptor-ref name="myInterceptor"/>
</action>
<!-- 设置默认拦截器 -->
<package>
<interceptors>...</interceptors>
<!-- 设置默认拦截器 -->
<default-interceptor-ref name=""></default-interceptor-ref>
<action>...</action>
</package>
J2EE中的过滤器和拦截器的更多相关文章
- Java中的过滤器,拦截器,监听器---------简单易懂的介绍
过滤器: 过滤器其主要特点在于:取你需要的东西,忽视那些不需要的东西!在程序中,你希望选择中篇文章中的所有数字,你就可以针对性的挑选数字! 拦截器: 拦截器其主要特点在于:针对你不要的东西进行拦截,比 ...
- springboot中使用过滤器、拦截器、监听器
监听器:listener是servlet规范中定义的一种特殊类.用于监听servletContext.HttpSession和servletRequest等域对象的创建和销毁事件.监听域对象的属性发生 ...
- Struts2中过滤器和拦截器的区别
拦截器和过滤器的区别: 1.拦截器是基于java的反射机制的,而过滤器是基于函数回调 2.过滤器依赖与servlet容器,而拦截器不依赖与servlet容器 3.拦截器只能对action请求起作用,而 ...
- spring中的监视器,过滤器,拦截器
1.监视器 (1)首先监视器是观察者模式的实现,在我之前的博客中有关于监视器模式的解释.监视器相当于观察者 (2)我们在springMvc中最常见的监视器 ContextLoaderlistener ...
- 过滤器、拦截器和AOP的分析与对比
目录 一.过滤器(Filter) 1.1 简介 1.2 应用场景 1.3 源码分析 二.拦截器(Interceptor) 2.1 简介 2.2 应用场景 2.2 源码分析 三.面向切面编程(AOP) ...
- Struts2之过滤器和拦截器的区别
刚学习Struts2这个框架不久,心中依然有一个疑惑未解那就是过滤器和拦截器的区别,相信也有不少人跟我一样对于这个问题没有太多的深入了解 那么下面我们就一起来探讨探讨 过滤器,是在java web中, ...
- Struts2 过滤器与拦截器
学习Struts2时,发现有过滤器和拦截器,他们貌似都是一样的功能,但是为什么会有2个不同的名称呢?肯定是有区别的,所以打算自己整理一下. 过滤器,是在java web中,你传入的request,re ...
- springBoot之配置文件的读取以及过滤器和拦截器的使用
前言 在之前的学习springBoot中,成功的实现了Restful风格的基本服务.但是想将之前的工程作为一个项目来说,那些是仅仅不够的.可能还需要获取自定义的配置以及添加过滤器和拦截器.至于为什么将 ...
- Servlet 过滤器、拦截器、监听器以及文件上传下载
在学习之初,总是对过滤器.拦截器.监听器这三个搞不清楚,现在进行一些记录,方便大家交流,也为了提高自身的学习能力! 如果想要了解这三个的作用,首先对servlet流程进行熟悉了解,servlet是客户 ...
随机推荐
- 《细说PHP》第四版 样章 第18章 数据库抽象层PDO 5
18.5 使用PDO对象 PDO扩展类库为PHP访问数据库定义了一个轻量级.一致性的接口,它提供了一个数据访问抽象层,这样,无论使用什么数据库,都可以通过一致的函数执行查询和获取数据,大大简化了数据 ...
- 【shell脚本】nginx启动脚本
[root@localhost init.d]# cat nginx #!/bin/bash #nx Startup script for the Nginx HTTP Server # it ver ...
- 【Linux】LVM操作添加新硬盘
目录 1.查看当前硬盘及分区情况 2.初始化/dev/sdb为PV(physical volume) 3.PV加入至VG组. 4.创建lv 5.格式化逻辑分区 6.挂载硬盘/data 7.迁移zabb ...
- 获取Excel工作薄中Sheet页(工作表)名集合
#region 获取Excel工作薄中Sheet页(工作表)名集合 02./// <summary> 03./// 获取Excel工作薄中Sheet页(工作表)名集合 04./// < ...
- Python规范:提高可读性
PEP 8 规范 PEP 是 Python Enhancement Proposal 的缩写,翻译过来叫"Python 增强规范". 缩进规范 PEP 8 规范告诉我们,请选择四个 ...
- 用AI思维给成本降温,腾讯WeTest兼容性测试直击底价!
WeTest 导读 当AI成为各行业提高产业效率的动能,很多人开始疑惑,这架智能化的“无人机”何时在移动应用测试中真正落地?在今年的国际数码互动娱乐博览会(ChinaJoy)上,腾讯WeTest给出了 ...
- css利用padding-top设置等比例遇到的问题
外层盒子如果设置了左右margin,外层盒子设置对应比例的时候,是按外层盒子的宽+两边的margin算做横向总长度的,不是只算宽度的.
- C++ message queue 消息队列入门
说明:当我们有多个线程以不同的速度运行并且我们想要以特定的顺序从一个线程向另一个线程发送信息时,消息队列可能会有用. 这个想法是,发送线程将消息推送到队列中,而接收线程将消息按自己的步调弹出. 只要发 ...
- [20190910]关于降序索引问题5.txt
[20190910]关于降序索引问题5.txt --//测试了索引TERM使用0xfe表示,回想到以前遇到降序索引的特殊字符编码问题,现在可是忘得一干二净.--//现在想想当时自己怎么猜测出来的,^_ ...
- Oracle大数据解决方案》学习笔记5——Oracle大数据机的配置、部署架构和监控-1(BDA Config, Deployment Arch, and Monitoring)
原创预见未来to50 发布于2018-12-05 16:18:48 阅读数 146 收藏 展开 这章的内容很多,有的学了. 1. Oracle大数据机——灵活和可扩展的架构 2. Hadoop集群的 ...