Struts2的fliter与interceptor

struts2   fliter与interceptor的区别

1、拦截器是基于java反射机制的,而过滤器是基于函数回调的。
2、过滤器依赖于servlet容器,而拦截器不依赖于servlet容器。
3、拦截器只能对Action请求起作用,而过滤器则可以对几乎所有请求起作用。
4、拦截器可以访问Action上下文、值栈里的对象,而过滤器不能。
5、在Action的生命周期中,拦截器可以多次调用,而过滤器只能在容器初始化时被调用一次。

struts2拦截器对请求的处理顺序

请求路径-action名称搜索顺序
1、获得请求路径的URI,例如url是:http://server/struts2/path1/path2/path3/test.action

2、首先寻找namespace为/path1/path2/path3的package,如果不存在这个 package则执行步骤3;如果存在这个package,则在这个package中寻找名字为test的action,当在该package下寻找不到 action 时就会直接跑到默认namaspace的package里面去寻找action(默认的命名空间为空字符串“”),如果在默认namaspace的 package里面还寻找不到该action,页面提示找不到action。

3、寻找namespace为/path1/path2的package,如果不存在这个package,则转至步骤4;如果存在这个package,则 在这个package中寻找名字为test的action,当在该package中寻找不到action 时就会直接跑到默认namaspace的package里面去找名字为test的action,在默认namaspace的package里面还寻找不到 该action,页面提示找不到action。

4、寻找namespace为/path1的package,如果不存在这个package则执行步骤5;如果存在这个package,则在这个 package中寻找名字为test的action,当在该package中寻找不到action 时就会直接跑到默认namaspace的package里面去找名字为test的action ,在默认namaspace的package里面还寻找不到该action,页面提示找不到action。

5、寻找namespace为/的package,如果存在这个package,则在这个package中寻找名字为test的action,当在 package中寻找不到action或者不存在这个package时,都会去默认namaspace的package里面寻找action,如果还是找 不到,页面提示找不到action。

6、如果某package的namespace=“”,则该package被视为默认namespace的package。


filter处理机制&
StrutsPrepareAndExecuteFilter

web.xml中:

<filter> 
        <filter-name>struts2</filter-name> 
        <filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>struts2</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

从该文件可以看出struts2框架中,StrutsPrepareAndExecuteFilter是核心控制器。它负责拦截由<url- pattern>/*</url-pattern>指定的所有用户请求,当用户请求到达时,该Filter会过滤用户的请求。当请求转 入Struts 2框架处理时会先经过一系列的拦截器,然后再到Action。与Struts1不同,Struts2对用户的每一次请求都会创建一个Action,所以 Struts2中的Action是线程安全的。

StrutsPrepareAndExecuteFilter是对struts2较早版本的核心控制器FilterDispatcher(文档建议,从 struts2.1.3起不再使用该类)的替代,结合了StrutsPrepareFilter与StrutsExecuteFilter的功能。

在struts2中,请求--other filters--StrutsPrepareAndExecuteFilter--other filters--响应。可以看出:
1、StrutsPrepareAndExecuteFilter是放在处理“请求”的其他filters之后的;
2、StrutsPrepareAndExecuteFilter处理之后对结果数据和信息不会直接放行。
因为StrutsPrepareAndExecuteFilter直接放行的话,“响应”是在(例如)tomcat容器中直接解析路径所得结果,如果前面的filters定义路径时用到了struts2自己的机制,那么tomcat解析路径时就会出错。

如果其他的Filter要访问Struts的特性,这时候不要使用StrutsPrepareAndExecuteFilter ,而是使用StrutsPrepareFilter与StrutsExecuteFilter,并让其他的Filter应位于两者之间。

 

(struts2.1.2及以前的版本)struts2的FilterDispatcher

org.apache.struts2.dispatcher.FilterDispatcher是Struts2的主要的Filter,负责四个方面的功能:
(1)执行Actions
(2)清除
ActionContext
(3)维护静态内容

(4)清除request生命周期内的XWork的interceptors

另注:该过滤器应该过滤所有的请求URL。一般被设置为/*.(过滤所有的请求!)
    具体:
        (1)执行Actions
            过滤器通过ActionMapper对象,来判断是否应该被映射到Action.如果mapper对象指示他应该被映射,过滤链将会被终止,然后Action被调用。这一点非常重要,如果同时使用SiteMesh filter,则SiteMesh filter应该放到该过滤器前,否则Action的输出将不会被装饰。
        (2)清除ActionContext
            过滤器为了确保内存溢出,会自动的清除ActionContext。这可能会存在一些问题,在和其它的框架集成时,例如SiteMesh。ActionContextCleanUp提供了怎么处理这些问题的一些信息。
        (3)维护静态内容
            过滤器也会维护在Struts2中使用的一些公共的静态的内容,例如JavaScript文件,CSS文件等。搜索/struts/*范围内的请求,然后将/struts/后面的值映射到一些struts的公共包中,也可以在你的类路径中搜索。默认情况下会去查找以下包:org.apache.struts2.static.template。这样你只用请求/struts/xhtml/styles.css,XHTML UI主题默认的样式表将会被返回。同样,AJAX UI组件需要的JavaScript文件,也可以在org.apache.struts2.static包中被找到。如果你想加入其它被搜索的包,在web.xml中设置filter时,通过给"actionPackages"初始参数一个逗号隔开的包列表值来设定。
            需注意的是:他会暴露一些比较敏感的信息例如,properites文件中的数据库连接信息。
    注:过滤器支持以下初始参数:
         config - 被调入的逗号隔开的XML文件列表。
         actionPackages - 被actions扫描的逗号隔开的packages列表。
         configProviders - 逗号分隔的实现了ConfigurationProvider接口(建造Configuration时被使用)的实现类。
         * - 任意的struts常量。
    通过重载createDispatcher()方法,可以自定义dispather。
    
    属性列表:
         (1)actionMapper:通过注入,提供一个ActionMapper实例。
         (2)dispatcher:暴露给子类一个Dispatcher实例。
         (3)encoding:存储StrutsConstants.STRUTS_I18N_ENCODING的设置。
         (4)filterConfig:通过初始参数,提供一个FilterConfig实例。
         (5)lastModifiedCal:在缓存静态content,提供一个格化的日期用于设定头信息。
         (6)log:提供一个logging实例。
         (7)patchPrefixs:存储静态资源的路径前缀信息。
         (8)serveStatic:存储StrutsConstants.STRUTS_SERVE_STATIC_CONTENT的设置。
         (9)serveStaticBrowserCache:存储StrutsConstants.STRUTS_SERVE_STATIC_BROWSER_CACHE的设置。
    方法列表:
         (1)copy(InputStream input, OutputStream output):从input复制数据到output。
         (2)createDispatcher(FilterConfig filterConfig):创建默认的dispatcher对象,如果需要的话,子类可以重载此方法,自定义一个dispatcher对象。
         (3)destory():调用dispatcher.cleanup(),依次释放本地线程,销毁dispatcher对象。
         (4)doFilter(ServletRequest request, ServeltResponse response, FilterChain chain):处理一个action或处理一个请求的静态内容。
         (5)findInputStream(String name, String packagePrefix):搜索类路径下的静态资源。
         (6)findStaticResoruce(String name, HttpServletRequest request, HttpServletResponse response):搜索静态的资源,直接复制到相应response的头信息中。
         (7)getContentType(String name):获取指定资源的contentType。
         (8)getFilterConfig():获取FilterConfig实例。
         (9)getServletContext():给WebLogic的一些版本提供一个工作区。

        (9)init(FilterConfig filterCongfig):创建默认的dispatcher对象和设置静态资源的默认包信息来初始化filter。
         (10)parse(String packages):返回一个数组通过解析一个指定逗号分隔的packages列表。
         (11)prepareDispatcherAndWrapRequest(HttpServletRequest request, HttpServletResponse response):对给定的request对象进行封装返回一个封装HttpServletRequest对象。例如显示的处理multipart数据。
         (12)setMapper(ActionMapper actionMapper)
         (13)setEncoding(String val)
         (14)setServeStaticContent(String val)
         (15)setServeStaticBrowserCache(String val)

 

FilterDispatcher和StrutsPrepareAndExecuteFilter

FilterDispatcher是struts2.0.x到2.1.2版本的核心过滤器.! 
StrutsPrepareAndExecuteFilter是自2.1.3开始就替代了FilterDispatcher的.! 
这样的改革当然是有好处的.! 
为什么这么说.? 应该知道如果我们自己定义过滤器的话, 是要放在strtus2的过滤器之前的, 如果放在struts2过滤器之后,你自己的过滤器对action的过滤作用就废了,不会有效!除非你是访问jsp/html! 
那我现在有需求, 我必须使用Action的环境,而又想在执行action之前拿filter做一些事, 用FilterDispatcher是做不到的.! 
那么StrutsPrepareAndExecuteFilter可以把他拆分成StrutsPrepareFilter和StrutsExecuteFilter,可以在这两个过滤器之间加上我们自己的过滤器.! 
给你打个比喻, 现在有病人要做手术, 现在struts2要做两件事, 搭病床(环境),执行手术.! 那么打麻药的工作呢.? 不可能要病人站着打吧, 所以必须有病床的环境,打完麻药之后再动手术.! 这个比喻非常形象了.!

 

Struts2拦截器

拦截器(interceptor)是Struts2最强大的特性之一,拦截器可以让你在Action和result被执行之前或之后进行一些处理。同时,拦截器也可以让你将通用的代码模块化并作为可重用的类。Struts2中的很多特性都是由拦截器来完成的。例如params拦截器将HTTP请求中的参数解析出来,并设置为Action的属性。servlet-config拦截器直接将HTTP请求中的HttpServletRequest对象化HttpServletResponse对象传给Action。

image

Struts2中内置类许多的拦截器,它们提供了许多Struts2的核心功能和可选的高级特性。这些内置的拦截器在struts-default.xml中配置。只有配置了拦截器,拦截器才可以正常的工作和运行。在struts-default.xml中拦截器的配置片段为:

<package name="struts-default" abstract="true">  ①
    <interceptors>
        <interceptor name="alias" class="com.opensymphony.xwork2.interceptor.AliasInterceptor"/>  ②
        <interceptor name="autowiring" class="com.opensymphony.xwork2.spring.interceptor.ActionAutowiringInterceptor"/>
        //…其他拦截器配置
        <interceptor-stack name="defaultStack">  ③
              <interceptor-ref name="exception"/>
              <interceptor-ref name="alias"/>
                <interceptor-ref name="servletConfig"/>
                <interceptor-ref name="i18n"/>
                //…其他拦截器的引用
          </interceptor-stack>    
    </interceptors>
    <default-interceptor-ref name="defaultStack"/>  ④
</package>

package将属性abstract设置为true,代表此package为一个抽象的package。抽象package和非抽象package的区别在于抽象的package中不能配置action。

② name属性指定拦截器的名字,class属性指定拦截器的完全限定名。

③ 多个拦截器可以组成拦截器栈。name属性为拦截器栈的名字。

④ 指定当前package的默认拦截器(栈)。当前指定的默认拦截器栈为defaultStack,该拦截器栈是Struts2运行的一个基本拦截器栈,一般我们不用在自己配置它,因为在大多数情况下,我们自定义的package是继承自struts-default这个package的。

我们以Struts2内置的timer拦截器为例,来学习如何在我们的应用中添加其他的拦截器。timer拦截器可以统计action执行的时间。我们可以修改package中默认的拦截器,那么将替换掉struts-default中配置的defaultStack拦截器栈,导致Struts2无法正常运行,比如无法获取表单的值等等。那么该如何正确的配置呢?可以在添加新的拦截器的基础上加入defaultStack拦截器栈,这样就可以保证defaultStack拦截器栈的存在。

<package name="myStruts" extends="struts-default">
	<interceptors>
		<interceptor-stack name="myInterceptor">  ①
			<interceptor-ref name="timer"/>  
			<interceptor-ref name="defaultStack"/>  
		</interceptor-stack>
	</interceptors>
	<default-interceptor-ref name="myInterceptor"/>  ②
	<action name="userAction"
		class="com.kay.action.UserAction">
		<result name="success">suc.jsp</result>
		<result name="input">index.jsp</result>
		<result name="error">err.jsp</result>
	</action>
</package>

① 添加一个自定义的拦截器栈,并在其中包含time拦截器和defaultStack拦截器栈。

② 设置当前的package的默认拦截器栈为自定义的拦截器栈。

 

修改package的默认拦截器会应用的package中的所有Action中,如果只想给其中一个Action添加拦截器,则可以这样来做:

<package name="myStruts" extends="struts-default">
	<interceptors>
		<interceptor-stack name="myInterceptor">
			<interceptor-ref name="timer"/>
			<interceptor-ref name="defaultStack"/>
		</interceptor-stack>
	</interceptors>
	<action name="userAction"
		class="com.kay.action.UserAction">
		<interceptor-ref name="myInterceptor"/>  ①
		<result name="success">suc.jsp</result>
		<result name="input">index.jsp</result>
		<result name="error">err.jsp</result>
	</action>
</package>

 

① 给UserAction添加拦截器。

 

如果要创建自己的拦截器,只需要实现Interceptor接口,该接口中定义了以下三个方法:

void init():

在拦截器初始化之后,在执行拦截之前,系统调用该方法。对于一个拦截器而言,init方法只会被调用一次。

String intercept(ActionInvocation invocation) throws Exception:

该方法是拦截器的拦截方法,返回一个字符串,系统将会跳转到该字符串对应的视图资源。该方法的ActionInvocation参数包含了被拦截的Action的引用,可以通过该对象的invoke方法,将控制权转给下一个拦截器或者转给Action的execute方法。

void destroy():

该方法与init方法对应,在拦截器示例被销毁之前,系统将会调用该方法。

除了Interceptor接口外,Struts2中还提供了一个AbStractInterceptor类,该类提供了一个init和destroy方法的空实现。如果不需要就不用重写这两个方法,可见继承自AbstractInterceptor类可以让我们构建拦截器时变得简单。

下面我们构建自己的拦截器,实现timer拦截器的效果。

public class MyInterceptor extends AbstractInterceptor {
	public String intercept(ActionInvocation invocation) throws Exception {
		long startTime = System.currentTimeMillis();  ①
		String result = invocation.invoke();  ②
		long endTime = System.currentTimeMillis();  ③
		System.out.println("Action执行共需要" + (endTime - startTime) + "毫秒");
		return result; 
	}
}

① 获得Action执行的开始时间。

② 将控制权交给下一个拦截器,如果该拦截器是最后一个拦截器,则调用Action的execute方法。

③ 获得Action执行的结束时间。

 

在配置文件struts.xml中配置拦截器:

<package name="myStruts" extends="struts-default">
	<interceptors>
		<interceptor name="myTimer" class="com.kay.interceptor.MyInterceptor"></interceptor>  ①
		<interceptor-stack name="myInterceptor">
			<interceptor-ref name="myTimer"/>  ②
			<interceptor-ref name="defaultStack"/>
		</interceptor-stack>
	</interceptors>
	<action name="userAction"
		class="com.kay.action.UserAction">
		<interceptor-ref name="myInterceptor"/>
		<result name="success">suc.jsp</result>
		<result name="input">index.jsp</result>
		<result name="error">err.jsp</result>
	</action>
</package>

 

① 定义一个新的拦截器,name属性为拦截器的名字,class属性为拦截器的完全限定名。

② 在拦截器栈中加入新的拦截器。

 

从拦截器的运行原理上和我们以前学习的Servlet中的过滤器是不是很相像呢?其实它们只有一个重要的区别,就是拦截器的工作是不依赖容器的,这会在进行单元测试时变得简单。

 

执行顺序 :过滤前 - 拦截前 - Action处理 - 拦截后 - 过滤后。个人认为过滤是一个横向的过程,首先把客户端提交的内容进行过滤(例如未登录用户不能访问内部页面的处理);过滤通过后,拦截器将检查用户提交数据的验证,做一些前期的数据处理,接着把处理后的数据发给对应的Action;Action处理完成返回后,拦截器还可以做其他过程(还没想到要做啥),再向上返回到过滤器的后续操作。

 

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

创建一个Filter 只需两个步骤: 
(1)创建Filter 处理类: 

(2)在web.xml 文件中配置Filter 。 
创建Filter 必须实现javax.servlet.Filter 接口,在该接口中定义了三个方法。 
• void init(FilterConfig config): 用于完成Filter 的初始化。 
• void destroy(): 用于Filter 销毁前,完成某些资源的回收。 
• void doFilter(ServletRequest request, ServletResponse response,FilterChain chain): 实现过滤功能,该方法就是对每个请求及响应增加的额外处理。 

过滤器Filter也具有生命周期:init()->doFilter()->destroy(),由部署文件中的filter元素驱动。在servlet2.4中,过滤器同样可以用于请求分派器,但须在web.xml中声明,<dispatcher>INCLUDE或FORWARD或REQUEST或ERROR</dispatcher>该元素位于filter-mapping中。 

Filter常用的场景:

例一、  日志的记录,当有请求到达时,在该过滤器中进行日志的记录。处理完成后,进入后续的Filter或者处理。

步骤1:编写Filter类

package test.filter;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletContext;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
 
public class LogFilter implements 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) { 
        // 获取ServletContext 对象,用于记录日志 
        ServletContext context = this.config.getServletContext(); 
        long before = System.currentTimeMillis(); 
        System.out.println("开始过滤... "); 
        // 将请求转换成HttpServletRequest 请求 
        HttpServletRequest hrequest = (HttpServletRequest) request; 
        // 记录日志 
        context.log("Filter已经截获到用户的请求的地址: " + hrequest.getServletPath()); 
        try { 
            // Filter 只是链式处理,请求依然转发到目的地址。 
            chain.doFilter(request, response); 
        } catch (Exception e) { 
            e.printStackTrace(); 
        } 
        long after = System.currentTimeMillis(); 
        // 记录日志 
        context.log("过滤结束"); 
        // 再次记录日志 
        context.log(" 请求被定位到" + ((HttpServletRequest) request).getRequestURI() 
                + "所花的时间为: " + (after - before)); 
    } 
} 

在上面的请求Filter中,仅在日志中记录请求的URL,对所有的请求都执行chain.doFilter(request,reponse)方法,当Filter 对请求过滤后,依然将请求发送到目的地址。

步骤2:在web.xml中配置Filter

<!-- 定义Filter --> 
<filter> 
        <!-- Filter 的名字 --> 
        <filter-name>log</filter-name> 
        <!-- Filter 的实现类 --> 
        <filter-class> test.filter.LogFilter</filter-class> 
</filter> 
    <!-- 定义Filter 拦截地址 --> 
<filter-mapping> 
        <!-- Filter 的名字 --> 
        <filter-name>log</filter-name> 
        <!-- Filter 负责拦截的URL --> 
        <url-pattern>/filter/*</url-pattern>
</filter-mapping>

 

filter生命周期

Filter的生命周期同servlet的生命周期是一样的。它们都提供了init(FilterConfig arg0)和destroy()方法来控制。当web容器启动的时候,就会自动调用init(FilterConfig arg0)来对filter进行初始化,当关闭web容器,关机,或者reload整个应用时,都会调用destroy()来关闭filter。也就是说,当web容器启动时,filter就被加载到内存,并在destroy()调用之前都常驻内存。

附:

Struts2(XWork)提供的拦截器的功能说明:

 

 

 

拦截器

名字

说明

Alias Interceptor

alias

在不同请求之间将请求参数在不同名字件转换,请求内容不变

Chaining Interceptor

chain

让前一个Action的属性可以被后一个Action访问,现在和chain类型的result(<result type=”chain”>)结合使用。

Checkbox Interceptor

checkbox

添加了checkbox自动处理代码,将没有选中的checkbox的内容设定为false,而html默认情况下不提交没有选中的checkbox。

Cookies Interceptor

cookies

使用配置的name,value来是指cookies

Conversion Error Interceptor

conversionError

将错误从ActionContext中添加到Action的属性字段中。

Create Session Interceptor

createSession

自动的创建HttpSession,用来为需要使用到HttpSession的拦截器服务。

Debugging Interceptor

debugging

提供不同的调试用的页面来展现内部的数据状况。

Execute and Wait Interceptor

execAndWait

在后台执行Action,同时将用户带到一个中间的等待页面。

Exception Interceptor

exception

将异常定位到一个画面

File Upload Interceptor

fileUpload

提供文件上传功能

I18n Interceptor

i18n

记录用户选择的locale

Logger Interceptor

logger

输出Action的名字

Message Store Interceptor

store

存储或者访问实现ValidationAware接口的Action类出现的消息,错误,字段错误等。

Model Driven Interceptor

model-driven

如果一个类实现了ModelDriven,将getModel得到的结果放在Value Stack中。

Scoped Model Driven

scoped-model-driven

如果一个Action实现了ScopedModelDriven,则这个拦截器会从相应的Scope中取出model调用Action的setModel方法将其放入Action内部。

Parameters Interceptor

params

将请求中的参数设置到Action中去。

Prepare Interceptor

prepare

如果Acton实现了Preparable,则该拦截器调用Action类的prepare方法。

Scope Interceptor

scope

Action状态存入session和application的简单方法。

Servlet Config Interceptor

servletConfig

提供访问HttpServletRequest和HttpServletResponse的方法,以Map的方式访问。

Static Parameters Interceptor

staticParams

struts.xml文件中将<action>中的<param>中的内容设置到对应的Action中。

Roles Interceptor

roles

确定用户是否具有JAAS指定的Role,否则不予执行。

Timer Interceptor

timer

输出Action执行的时间

Token Interceptor

token

通过Token来避免双击

Token Session Interceptor

tokenSession

Token Interceptor一样,不过双击的时候把请求的数据存储在Session中

Validation Interceptor

validation

使用action-validation.xml文件中定义的内容校验提交的数据。

Workflow Interceptor

workflow

调用Action的validate方法,一旦有错误返回,重新定位到INPUT画面

Parameter Filter Interceptor

N/A

从参数列表中删除不必要的参数

Profiling Interceptor

profiling

通过参数激活profile

拦截器示例 : 实现权限控制

权限检查,当浏览者需要请求执行某个操作时,应用首先需要检查浏览者是否登录,以及是否有足够的权限来执行该操作

 实现拦截器

   本示例应用要求用户登录,且必须为指定用户名才可以查看系统中某个视图资源: 否则,系统直接转入登录页面。

   对于上述的需求,可以在每个 Action 的执行实际处理逻辑之前,先执行权限检查逻辑,为了代码复用,可以使用拦截器。

   个人认为判断 session 用 过滤器比较好 如下:

web.xml

Xml代码  
  1. <filter>  
        <filter-name>SessionInvalidate</filter-name>  
        <filter-class>com.sysoft.baselib.web.SessionCheckFilter</filter-class>  
        <init-param>  
            <param-name>checkSessionKey</param-name>  
            <param-value>APP_SESSION_TOKEN</param-value>  
        </init-param>  
        <init-param>  
            <param-name>redirectURL</param-name>  
            <param-value>/sessionInvalidate.jsp</param-value>  
        </init-param>  
        <init-param>  
            <param-name>notCheckURLList</param-name>  
            <param-value>/login.jsp,/logon.do,/logout.jsp,/Index2/index.jsp,/sessionInvalidate.jsp,/Index2/maintop.jsp,/html.jsp</param-value>  
        </init-param>  
     </filter>  
     <filter-mapping>  
        <filter-name>SessionInvalidate</filter-name>  
        <url-pattern>*.do</url-pattern>       
     </filter-mapping>  
    <filter-mapping>  
        <filter-name>SessionInvalidate</filter-name>  
        <url-pattern>*.jsp</url-pattern>      
     </filter-mapping>

 SessionCheckFilter.java

Java代码  
package com.sysoft.baselib.web;  
  
import java.io.IOException;  
import java.util.HashSet;  
import java.util.Set;  
  
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.http.HttpServletRequest;  
import javax.servlet.http.HttpServletResponse;  
import javax.servlet.http.HttpSession;  
/**       
* 用于检测用户是否登陆的过滤器,如果未登录,则重定向到指的登录页面        
* 配置参数             
* checkSessionKey 需检查的在 Session 中保存的关键字       
* redirectURL 如果用户未登录,则重定向到指定的页面,URL不包括 ContextPath        
* notCheckURLList 不做检查的URL列表,以分号分开,并且 URL 中不包括 ContextPath   
*/      
public class SessionCheckFilter implements Filter {  
    protected FilterConfig filterConfig = null;  
    private String redirectURL = null;  
    private Set notCheckURLList = new HashSet();  
    private String sessionKey = null;  
  
    public void doFilter(ServletRequest servletRequest,  
            ServletResponse servletResponse, FilterChain filterChain)  
            throws IOException, ServletException {  
        HttpServletRequest request = (HttpServletRequest) servletRequest;  
        HttpServletResponse response = (HttpServletResponse) servletResponse;  
  
        HttpSession session = request.getSession();  
        if (sessionKey == null) {  
            filterChain.doFilter(request, response);  
            return;  
        }  
        if ((!checkRequestURIIntNotFilterList(request))  
                && session.getAttribute(sessionKey) == null) {  
            response.sendRedirect(request.getContextPath() +redirectURL);  
            return;  
        }  
        filterChain.doFilter(servletRequest, servletResponse);  
    }  
  
    public void destroy() {  
        notCheckURLList.clear();  
    }  
  
    private boolean checkRequestURIIntNotFilterList(HttpServletRequest request) {  
        String uri = request.getServletPath()  
                + (request.getPathInfo() == null ? "" : request.getPathInfo());  
        String temp = request.getRequestURI();  
        temp= temp.substring(request.getContextPath().length()+1);  
        //System.out.println("是否包括:"+uri+";"+notCheckURLList+"=="+notCheckURLList.contains(uri));  
        return notCheckURLList.contains(uri);  
          
    }  
  
    public void init(FilterConfig filterConfig) throws ServletException {  
        this.filterConfig = filterConfig;  
        redirectURL = filterConfig.getInitParameter("redirectURL");  
        sessionKey = filterConfig.getInitParameter("checkSessionKey");  
  
        String notCheckURLListStr = filterConfig  
                .getInitParameter("notCheckURLList");  
        if(notCheckURLListStr != null){  
            System.out.println(notCheckURLListStr);  
            String[] params = notCheckURLListStr.split(",");  
            for(int i=0;i<params.length;i++){  
                notCheckURLList.add(params[i].trim());  
            }  
        }  
          
    }  
} 

    检查用户是否登录,通常都是通过跟踪用户的 HTTPSession 来完成的,通过 ActionContext 即可访问到 Session 中的属性,拦截器的 intercepte(ActionInvocation invocation) 的 invocation 参数可以访问到请求相关的 ActionContext 实例

posted on 2013-07-03 10:17  duanxz  阅读(1161)  评论(0编辑  收藏  举报