过滤器和拦截器的相似之处就是拦截请求,做一些预处理或者后处理。

而过滤器和拦截器的区别在于过滤器是相对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中的过滤器和拦截器的更多相关文章

  1. Java中的过滤器,拦截器,监听器---------简单易懂的介绍

    过滤器: 过滤器其主要特点在于:取你需要的东西,忽视那些不需要的东西!在程序中,你希望选择中篇文章中的所有数字,你就可以针对性的挑选数字! 拦截器: 拦截器其主要特点在于:针对你不要的东西进行拦截,比 ...

  2. springboot中使用过滤器、拦截器、监听器

    监听器:listener是servlet规范中定义的一种特殊类.用于监听servletContext.HttpSession和servletRequest等域对象的创建和销毁事件.监听域对象的属性发生 ...

  3. Struts2中过滤器和拦截器的区别

    拦截器和过滤器的区别: 1.拦截器是基于java的反射机制的,而过滤器是基于函数回调 2.过滤器依赖与servlet容器,而拦截器不依赖与servlet容器 3.拦截器只能对action请求起作用,而 ...

  4. spring中的监视器,过滤器,拦截器

    1.监视器 (1)首先监视器是观察者模式的实现,在我之前的博客中有关于监视器模式的解释.监视器相当于观察者 (2)我们在springMvc中最常见的监视器 ContextLoaderlistener ...

  5. 过滤器、拦截器和AOP的分析与对比

    目录 一.过滤器(Filter) 1.1 简介 1.2 应用场景 1.3 源码分析 二.拦截器(Interceptor) 2.1 简介 2.2 应用场景 2.2 源码分析 三.面向切面编程(AOP) ...

  6. Struts2之过滤器和拦截器的区别

    刚学习Struts2这个框架不久,心中依然有一个疑惑未解那就是过滤器和拦截器的区别,相信也有不少人跟我一样对于这个问题没有太多的深入了解 那么下面我们就一起来探讨探讨 过滤器,是在java web中, ...

  7. Struts2 过滤器与拦截器

    学习Struts2时,发现有过滤器和拦截器,他们貌似都是一样的功能,但是为什么会有2个不同的名称呢?肯定是有区别的,所以打算自己整理一下. 过滤器,是在java web中,你传入的request,re ...

  8. springBoot之配置文件的读取以及过滤器和拦截器的使用

    前言 在之前的学习springBoot中,成功的实现了Restful风格的基本服务.但是想将之前的工程作为一个项目来说,那些是仅仅不够的.可能还需要获取自定义的配置以及添加过滤器和拦截器.至于为什么将 ...

  9. Servlet 过滤器、拦截器、监听器以及文件上传下载

    在学习之初,总是对过滤器.拦截器.监听器这三个搞不清楚,现在进行一些记录,方便大家交流,也为了提高自身的学习能力! 如果想要了解这三个的作用,首先对servlet流程进行熟悉了解,servlet是客户 ...

随机推荐

  1. Pandas入门系列(一)-- Series

    Series的创建 ##数据分析汇总学习 https://blog.csdn.net/weixin_39778570/article/details/81157884 # 使用列表创建 >> ...

  2. python做中学(一)全局变量的用法

    一段时间没有使用python来写代码,就发现以前学习的很多语法都忘了.看来还是当初这方面的项目做的好不够多,没有系统性的运用和学习,导致了很多语法不能顺手拈来.在接下来的这个项目中, 一定要把遇到的一 ...

  3. js 根据url 下载图片 前端js 实现文件下载

    1.H5 download属性 function downFile(content, filename) { // 创建隐藏的可下载链接 var eleLink = document.createEl ...

  4. git 清除远程仓库已经删除的本地分支 清除已经合并到master的本地分支

    在gitlab中执行deleted merged.也是可以在本地看到这些分支的 查看本地分支和追踪情况: git remote show origin 可以发现远程分支已被删除的分支,根据提示可以使用 ...

  5. layui confirm 嵌套使用 (随笔记)

    使用layui confirm时不要使用aspx控件,使用html的button按钮 借用一下 官方例子 layer.confirm('您是如何看待前端开发?', { btn: ['重要', '奇葩' ...

  6. 机器学习实战:基于Scikit-Learn和TensorFlow 读书笔记 第6章 决策树

    数据挖掘作业,要实现决策树,现记录学习过程 win10系统,Python 3.7.0 构建一个决策树,在鸢尾花数据集上训练一个DecisionTreeClassifier: from sklearn. ...

  7. windows下dubbo-admin2.6.x之后版本的安装

    安装zookeeper(单机) 下载bin.tar.gz的版本,解压 conf下的zoo_sample.cfg改zoo.cfg zoo.cfg里添加配置 dataDir=G:/zookeeper-/d ...

  8. querySelectorAll和getElementsByClassName获取元素的区别

    querySelectorAll()方法是HTML5新增的方法,通过传入一个css选择符,返回所有匹配的元素而不仅仅是一个元素.这个方法返回的是一个NodeList的实例.那么它和通过getEleme ...

  9. window启动webpack打包的三种方法

    1.在cmd终端执行 npx webpack命令 2.在package.json文件同级建立webpack.config.js文件,内容如下: const path = require('path') ...

  10. 【转载】更简单的学习Android事件分发

    事件分发是Android中非常重要的机制,是用户与界面交互的基础.这篇文章将通过示例打印出的Log,绘制出事件分发的流程图,让大家更容易的去理解Android的事件分发机制. 一.必要的基础知识 1. ...