现在的位置: 首页 > 综合 > 正文

Struts拦截器精讲

2017年03月27日 ⁄ 综合 ⁄ 共 18067字 ⁄ 字号 评论关闭

关于Struts的Interceptor,可以参考官网,解释非常清楚,英文比较容易看懂:http://struts.apache.org/docs/interceptors.html

        下面主要从实现拦截器类、使用拦截器、拦截方法的拦截器、拦截器的执行顺序、拦截结果的监听器、覆盖拦截器栈里特定拦截器的参数和使用拦截器完成权限控制来进一步理解拦截器。


下面是官方Understanding,非常精准:

Understanding Interceptors

Interceptors can execute code before and after an Action is invoked. Most of the framework's core functionality is implemented as Interceptors. Features like double-submit guards, type conversion, object population, validation, file upload, page preparation,
and more, are all implemented with the help of Interceptors. Each and every Interceptor is pluggable, so you can decide exactly which features an Action needs to support.

Interceptors can be configured on a per-action basis. Your own custom Interceptors can be mixed-and-matched with the Interceptors bundled with the framework. Interceptors "set the stage" for the Action classes, doing much of the "heavy lifting" before the Action
executes.

In some cases, an Interceptor might keep an Action from firing, because of a double-submit or because validation failed. Interceptors can also change the state of an Action before it executes.

The Interceptors are defined in a stack that specifies the execution order. In some cases, the order of the Interceptors on the stack can be very important.

实现拦截器:

如果用户要开发自己的拦截器类,应该实现com.opensymphony.xwork2.interceptor.Interceptor接口,该接口源码如下:

public interface Interceptor
    extends Serializable
{

    public abstract void destroy();

    public abstract void init();

    public abstract String intercept(ActionInvocation actioninvocation)
        throws Exception;
}

可以看出接口中包含如下三个方法

-->init():在该拦截器被实例化后,在该拦截器执行拦截之前,系统回调该方法。每个拦截器只执行init()方法一次。一般用于初始化资源。

-->destroy()与init()方法对应。在拦截器实例销毁之前,系统回调该方法,用于销毁init()方法里打开的资源。

intercept(ActionInvocation actioninvocation):使用户需要实现的拦截的动作。就像Action的excecute方法一样,intercept方法返回一个字符串作为逻辑视图。如果该方法直接返回一个字符串,系统将会跳转到该逻辑视图对应的时机视图资源,不会调用被拦截的Action。该方法的ActionInvocation参数包含了被拦截的Action的引用,可以通过该参数的invoke方法,将控制权转交给下一个拦截器,或者转给Action的execute方法。

除此之外,Struts2提加工了一个AbstractInterceptor类,该类提供了一个init和destory方法的空实现如果我们实现的拦截器不需要打开资源,则可以无需实现这两个 方法。可见,继承AbstractInterceptor类实现自定义拦截器更加简单。

AbstractInterceptor源码如下:

public abstract class AbstractInterceptor
    implements Interceptor
{

    public AbstractInterceptor()
    {
    }

    public void init()
    {
    }

    public void destroy()
    {
    }

    public abstract String intercept(ActionInvocation actioninvocation)
        throws Exception;
}

自定义一个简单的拦截器:

public class SimpleInterceptor
	extends AbstractInterceptor
{
	//简单拦截器的名字
	private String name;
	//为该简单拦截器设置名字的setter方法
	public void setName(String name)
	{
		this.name = name;
	}
	public String intercept(ActionInvocation invocation)
		throws Exception
	{
		//取得被拦截的Action实例
		LoginAction action = (LoginAction)invocation.getAction();
		//打印执行开始的实现
		System.out.println(name + " 拦截器的动作---------" + 
			"开始执行登录Action的时间为:" + new Date());
		//取得开始执行Action的时间
		long start = System.currentTimeMillis();
		//执行该拦截器的后一个拦截器
		//如果该拦截器后没有其他拦截器,则直接执行Action的execute方法
		String result = invocation.invoke();
		//打印执行结束的时间
		System.out.println(name + " 拦截器的动作---------" + 
			"执行完登录Action的时间为:" + new Date());
		long end = System.currentTimeMillis();
		System.out.println(name + " 拦截器的动作---------" + 
			"执行完该Action的事件为" + (end - start) + "毫秒");
		return result;
	}
}

拦截器已经实现了,那么怎么使用呢?

使用拦截器:

-----1)通过<interceptor.../>元素来定义拦截器

-----2)通过<interceptor-ref...../>元素来使用拦截器

struts.xml

<pre name="code" class="plain"><struts>
	<!-- 通过常量配置Struts 2的国际化资源信息 -->
	<constant name="struts.custom.i18n.resources" value="mess"/>
	<!-- 通过常量配置Struts 2所使用的解码集-->
	<constant name="struts.i18n.encoding" value="GBK"/>
	<!-- 配置本系统所使用的包 -->
	<package name="lee" extends="struts-default">
		<!-- 应用所需使用的拦截器都在该元素下配置 -->
		<strong><strong><interceptors>
			<!-- 配置mysimple拦截器 -->
			<interceptor name="mysimple"
			class="org.crazyit.app.interceptor.SimpleInterceptor">
				<!-- 为拦截器指定参数值 -->
				<param name="name">简单拦截器</param>
			</interceptor></strong>
		</interceptors></strong>

		<action name="loginPro" class="org.crazyit.app.action.LoginAction">
			<result name="error">/content/error.jsp</result>
			<result name="success">/content/welcome.jsp</result> 
			<!-- 配置系统的默认拦截器 -->
			<strong><interceptor-ref name="defaultStack"/>
			<!-- 应用自定义的mysimple拦截器 -->
			<strong><interceptor-ref name="mysimple">
				<param name="name">改名后的拦截器</param>
			</interceptor-ref></strong></strong>
		</action>
		<action name="*">
			<result>a.jsp</result>
		</action>
	</package>
</struts>  

浏览器发送Action请求时结果如下:

从上面的结果可以看出,SimpleInterceptor拦截器已经获得了执行的机会,取得了系统中该Action处理用户请求的时间。不仅如此我们还可以看到,系统中的拦截器name属性的值是“动态参数”,在<interceptor-ref.../>元素中的属性值覆盖了<interceptor....../>元素中指定的值。

Struts2拦截器功能非常强大,它既可以在Action的execute方法之前执行代码,也可以在execute方法之后执行代码【还可以对Action中的方法过滤】,这种方法的试纸就是AOP的思想。

拦截方法的拦截器:

      默认情况下,我们为某个Action定义了拦截器,则这个拦截器会拦截Action内的所有的方法,但在某些情况下我们只希望拦截指定的方法,此时就需要拦截器拦截方法的过滤特性。

    为了实现这个功能,Struts2提供了一个MethodFilterInterceptor类,该类是AbstractInterceptor类的子类,如果用户需要实现拦截器支持方法过滤特性,则应该继承MethodFilterInterceptor.

   MethodFilterInterceptor类重写了AbstractInterceptor类的intercept(ActionInvocation invocation)方法,但提供了一个doIntercept(ActionInvocation invocation)抽象方法。程序员通过回调doIntercept方法来实现业务逻辑即可。

方法过滤拦截器代码:

//拦截方法的拦截器,应该继承MethodFilterInterceptor抽象类
public class MyFilterInterceptor
	extends MethodFilterInterceptor
{
	//简单拦截器的名字
	private String name;
	//为该简单拦截器设置名字的setter方法
	public void setName(String name)
	{
		this.name = name;
	}
	//重写doIntercept方法,实现对Action的拦截逻辑
	public String doIntercept(ActionInvocation invocation)
		throws Exception
	{
		//取得被拦截的Action实例
		LoginAction action = (LoginAction)invocation.getAction();
		//打印执行开始的时间
		System.out.println(name + " 拦截器的动作---------"
			+ "开始执行登录Action的时间为:" + new Date());
		//取得开始执行Action的时间
		long start = System.currentTimeMillis();
		//执行该拦截器的后一个拦截器,或者直接指定Action的execute方法
		String result = invocation.invoke();
		//打印执行结束的时间
		System.out.println(name + " 拦截器的动作---------" 
			+ "执行完登录Action的时间为:" + new Date());
		long end = System.currentTimeMillis();
		//打印执行该Action所花费的时间
		System.out.println(name + " 拦截器的动作---------"
			+ "执行完该Action的事件为" + (end - start) + "毫秒");
		return result;
	}
}

上面的代码可看出,方法过滤的拦截器和简单拦截器区别非常相似,知识之前是需要重写intercept方法,现在重写的是doIntercept方法。


对MethodFilterInterceptor理解:

 针对MethodFilterInterceptor:
excludeMethods表示排除指定的方法,即不对标记为excludeMethods的方法进行拦截,【拦截是说在Action的基础上执行拦截器里面的逻辑】
includeMethods表示包含指定的方法,即对标记为includeMethods的方法进行拦截,      【不拦截是说在Action的基础上不执行拦截器里面的逻辑代码】
 
在struts.xml中关于excludeMethods和includeMethods有两种实现方式,一种相当于全局,另一种相当于局部,即<interceptors>
          <interceptor name="method"class="com.yxl.interceptor.MethodInterceptor">
               <paramname="includeMethods">method1,method2</param>
          </interceptor>
       </interceptors>为全局
而 <interceptor-refname="method">
               <paramname="excludeMethods">method1,method2</param>
     </interceptor-ref> 
为局部,若全局中的param定义为excludeMethods同样局部中的param也定义为excludeMethods,则局部中的param生效,全局中的param无效,即被局部中的param覆盖,同样,若全局中的param定义为includeMethods同样局部中的param也定义为includeMethods,则局部中的param生效,全局中的param无效,即被局部中的param覆盖。
当全局中的param与局部中的param不相同的时,即当全局中param为excludeMethods而局部中的param为includeMethods和全局中的param为includeMethods而局部中param为excludeMethods,则标志为includeMethods生效,即若是全局中的param定义为includeMethods,则全局屏蔽局部,以全局为准,反之,以局部为准。

尤其值得注意的是,自定义的拦截器类一定要继承MethodFilterInterceptor
struts2MethodFilterInterceptor类,该类是AbstractInerceptor的子类,可以实现对Action方法的拦截.实现MethodFilterInterceptor才能使用方法拦截
    MethodFilterInterceptor中有两个方法
   setExcludeMethods:排除需要过滤的方法
    setIncludeMethods:设置需要过滤的方法
    如果一个方法同时在excludeMethods和includeMethods中出现,则会被拦截


实例:<param name="excludeMethods">execute</param>

后台打印如下:



<param name="includeMethods">execute</param>



拦截器的执行顺序:

配置文件更改如下:

<struts>
	<!-- 通过常量配置Struts 2的国际化资源信息 -->
	<constant name="struts.custom.i18n.resources" value="mess"/>
	<!-- 通过常量配置Struts 2所使用的解码集-->
	<constant name="struts.i18n.encoding" value="GBK"/>
	<!-- 配置本系统所使用的包 -->
	<package name="lee" extends="struts-default">
		<!-- 应用所需使用的拦截器都在该元素下配置 -->
		<interceptors>
			<!-- 配置mysimple拦截器 -->
			<interceptor name="mysimple"
			class="org.crazyit.app.interceptor.SimpleInterceptor">
				<!-- 为拦截器指定参数值 -->
				<param name="name">简单拦截器</param>
			</interceptor>
		</interceptors>

		<action name="loginPro" class="org.crazyit.app.action.LoginAction">
			<result name="error">/WEB-INF/content/error.jsp</result>
			<result name="success">/WEB-INF/content/welcome.jsp</result> 
			<!-- 配置系统的默认拦截器 -->
			<interceptor-ref name="defaultStack"/>
			<!-- 应用自定义的mysimple拦截器 -->
			<interceptor-ref name="mysimple">
				<param name="name">第一个</param>
			</interceptor-ref>
			<interceptor-ref name="mysimple">
				<param name="name">第二个</param>
			</interceptor-ref>
		</action>
		<action name="*">
			<result>/WEB-INF/content/{1}.jsp</result>
		</action>
	</package>
</struts>

打印结果如下:

对于在execute方法之前的动作,第一个拦截器先起作用,也就是说配置在前面的拦截器先起作用;对于在execute方法后的动作,则第二个拦截器先起作用,也就是说配置在后面的拦截器先起作用。

具体案例:使用拦截器完成全线控制

原理:当浏览者需要请求执行某个操作的时候,应用需要检查浏览者是否登陆,以及是否有足够的权限执行该操作。可以再每个Action的执行实际处理逻辑之前,先执行权限检查逻辑,但这种做法不利于代码复用。可以将这些权限检查逻辑放在拦截器中进行更加优雅。

权限检查拦截器代码:

//权限检查拦截器继承AbstractInterceptor类
public class AuthorityInterceptor
	extends AbstractInterceptor
{
	//拦截Action处理的拦截方法
	public String intercept(ActionInvocation invocation)
		throws Exception
	{
		<strong>//取得请求相关的ActionContext实例
		ActionContext ctx = invocation.getInvocationContext();
		Map session = ctx.getSession();
		//取出名为user的Session属性
		String user = (String)session.get("user");
		//如果没有登录,或者登录所用的用户名不是scott,都返回重新登录</strong>
		if (user != null && user.equals("wfc") )
		{
			return invocation.invoke();
		}
		//没有登录,将服务器提示设置成一个HttpServletRequest属性
		ctx.put("tip" ,
			"您还没有登录,请输入wfc,wfc登录系统");
		//直接返回login的逻辑视图
		return Action.LOGIN;
	}
}

配置文件:stuts.xml

<struts>
	<constant name="struts.custom.i18n.resources" value="mess"/>
	<constant name="struts.i18n.encoding" value="GBK"/>

	<package name="lee" extends="struts-default">
		<!-- 用户拦截器定义在该元素下 -->
		<interceptors>
			<!-- 定义了一个名为authority的拦截器 -->
			<interceptor name="authority" 
			class="org.crazyit.app.interceptor.AuthorityInterceptor"/>
		</interceptors>

		<!-- 定义全局Result -->
		<global-results>
			<!-- 当返回login视图名时,转入login.jsp页面 -->
			<result name="login">/content/login.jsp</result>
		</global-results>

		<action name="loginPro" class="org.crazyit.app.action.LoginAction">
			<result name="error">/content//error.jsp</result>
			<result name="success">/content/welcome.jsp</result>
		</action>
		<!-- 定义一个名为viewBook的Action,其实现类为ActionSupport -->
		<action name="viewBook">
			<!-- 返回success视图名时,
				转入/WEB-INF/content/viewBook.jsp页面 -->
			<result>/content/viewBook.jsp</result>
			<interceptor-ref name="defaultStack"/>
			<!-- 应用自定义拦截器 -->
			<interceptor-ref name="authority"/>
		</action>
		<action name="*">
			<result>/content/{1}.jsp</result>
		</action>
	</package>
</struts>

登陆的Login【Action】

public class LoginAction extends ActionSupport
{
	private String username;
	private String password;
	
	//username属性的setter和getter方法
	public void setUsername(String username)
	{
		this.username = username;
	}
	public String getUsername()
	{
		return this.username;
	}

	//password属性的setter和getter方法
	public void setPassword(String password)
	{
		this.password = password;
	}
	public String getPassword()
	{
		return this.password;
	}
	
	public String execute() throws Exception
	{
		System.out.println("进入execute方法执行体..........");
		if (getUsername().equals("wfc")
			&& getPassword().equals("wfc"))
		{
			<strong>ActionContext ctx = ActionContext.getContext();
			Map session = ctx.getSession();
			session.put("user" , getUsername());</strong>
			return SUCCESS;
		}
		else
		{
			return ERROR;
		}
	}
}

login.action中,将user放入Session中,在Interceptor中验证,给其它|Action配置拦截器,提交到其它Action时,拦截器中检查是否登陆。

看看企业级应用是怎么用的,在权限、日志、异常

public class ExceptionFilter extends AbstractInterceptor{
	
	public Logger LOGGER = Logger.getLogger(this.getClass());

	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;

	@Override
	public String intercept(ActionInvocation arg0) throws Exception {
		
		 String result = "";
		 String error = "";
		 Throwable err_obj = null;
		 
	       try {
	    	   
	           result = arg0.invoke();
	           
	       } catch (DataAccessException ex) {
	    	   
	    	   error = "数据库操作失败: " + ex.getMessage();
	    	   err_obj = ex;
	    	   
	       } catch (NullPointerException ex) {

	    	   error = "空指针,调用了未经初始化或者是不存在的对象: " + ex.getMessage();
	    	   err_obj = ex;

	       } catch (IOException ex) {

	    	   error = "IO读写异常: " + ex.getMessage();
	    	   err_obj = ex;
	    	   
	       } catch (ClassNotFoundException ex) {

	    	   error = "指定的类不存在: " + ex.getMessage();
	    	   err_obj = ex;

	       } catch (ArithmeticException ex) {
	    	   
	    	   error = "数学运算异常: " + ex.getMessage();
	    	   err_obj = ex;
	  
	       } catch (ArrayIndexOutOfBoundsException ex) {

	    	   error = "数组下标越界: " + ex.getMessage();
	    	   err_obj = ex;
	   
	       } catch (IllegalArgumentException ex) {

	    	   error = "调用方法的参数错误: " + ex.getMessage();
	    	   err_obj = ex;
	    
	       } catch (ClassCastException ex) {

	    	   error = "类型强制转换错误: " + ex.getMessage();
	    	   err_obj = ex;

	       } catch (SecurityException ex) {

	    	   error = "违背安全原则异常: " + ex.getMessage();
	    	   err_obj = ex;
	    
	       } catch (SQLException ex) {

	    	   error = "操作数据库异常: " + ex.getMessage();
	    	   err_obj = ex;
	   
	       } catch (NoSuchMethodError ex) {

	    	   error = "调用了未定义的方法: " + ex.getMessage();
	    	   err_obj = ex;
	    
	       } catch (InternalError ex) {

	    	   error = "Java虚拟机发生了内部错误: " + ex.getMessage();
	    	   err_obj = ex;
	  
	       } catch (Exception ex) {

	    	   error = ex.getMessage()==null?"系统错误":ex.getMessage();
	    	   err_obj = ex;
	 
	       }
	       
	      if(error.length() >0){
	    	  //记录错误日志。
	    	  LOGGER.error(error, err_obj);

		      HttpServletResponse resp = ServletActionContext.getResponse();
			  resp.setContentType("text/json;charset=UTF-8");
			  resp.setHeader("Cache-Control", "no-cache");
			  PrintWriter pw = null;
			  try {
				  pw = resp.getWriter();
				  pw.write(error);
			  } catch (IOException e) {
				  throw new EVoucherException("获取http写入流异常" + e.getMessage());
			  } finally {
				  if (pw != null) {
					  pw.close();
				  }
			  }
			  return null;
			   
		  }else{
			  return result;
		  }
	}
	


}

HessianLogFilter.java

public class HessianLogFilter extends AbstractInterceptor{

	private static final Logger logger = Logger.getLogger(HessianLogFilter.class);
	
	private static final long serialVersionUID = 1L;
	private static IHessianLog hessianLogService;
	static{
		if(hessianLogService == null){
			hessianLogService = (IHessianLog) BeanFactoryUtil.getBean("gap.hessianLogService");
		}
	}


	@SuppressWarnings("static-access")
	@Override
	public String intercept(ActionInvocation arg0) throws Exception {
		
		//取得请求的action实例
		ActionContext ctx = arg0.getInvocationContext();
		//取得提交URI
		HttpServletRequest request = (HttpServletRequest)ctx.get(ServletActionContext.HTTP_REQUEST);
		HttpSession session = request.getSession();
		
		User user = (User) session.getAttribute("user");
		
		if(user == null){
			return arg0.invoke();
		}
		

		String actionName = ctx.getContext().getName();
		
			
		//拦截的日志方法
		if(actionName.indexOf("add")==0 || actionName.contains("_add") || actionName.contains("enumadd") ||
				actionName.indexOf("create")==0 || actionName.contains("_create") ||
				actionName.indexOf("insert")==0 || actionName.contains("_create") ||
				actionName.indexOf("update")==0 || actionName.contains("_update") ||
				actionName.indexOf("save")==0 ||  actionName.contains("_save") ||
				actionName.indexOf("modify")==0 || actionName.contains("_modify") ||
				actionName.indexOf("batch")==0 || actionName.contains("_batch") ||
				actionName.indexOf("grant")==0 || actionName.contains("_grant") ||
				actionName.indexOf("import")==0 || actionName.contains("_import") ||
				actionName.indexOf("edit")==0 || actionName.contains("_edit") ||
				actionName.indexOf("remove")==0 || actionName.contains("_remove") ||
				actionName.indexOf("delete")==0 || actionName.contains("_delete") ||
				actionName.indexOf("init")==0 || actionName.contains("_init") || actionName.contains("_set") ||
				actionName.indexOf("del")==0 || actionName.contains("_del")) {
			
			/** modify by LY 2014-5-12 添加针对CSRF攻击控制 **/
			String referer = "";
			String jsp = "";
			List<Long> list1 = null;
			if(!actionName.equalsIgnoreCase("voucherType_updateVoucherModel")){ //模板编辑用的OCX提交, 没有Referer
				referer = request.getHeader("Referer");
				if(!referer.contains("realware")){
					throw new EVoucherException("CSRF攻击错误");
				}
				String random_form = request.getParameter("randomKey");
				if(random_form != null && random_form.contains("&")){
					String[] array = random_form.split("&");
					String random_session = (String)request.getSession().getAttribute(array[0]);
					logger.debug("random_form:"+random_form);
					logger.debug("random_session:"+random_session);
					if(random_session==null || !array[1].equals(random_session)){
						throw new EVoucherException("CSRF攻击错误");
					}
				}else{
					throw new EVoucherException("CSRF攻击错误");
				}
				//获取modelID  referer
				jsp = referer.substring(referer.indexOf("jsp/")+4, referer.length());
				
				//保证【日志管理】中的“菜单名称”字段能够显示
				if(jsp.equals("EVoucher/VoucherModelInfo.jsp") ||jsp.equals("EVoucher/VoucherModelEdit.jsp")
						|| jsp.equals("EVoucher/VoucherModelShow.jsp")){
					jsp="EVoucher/VoucherModelForm.jsp";
				}
				if(jsp.equals("common/voucherCertSendForm.jsp")){
					jsp="common/asspVoucherCertManage.jsp";
				}
				
				list1 = hessianLogService.queryMenuId(jsp);
			}

			String result = null;
			
			//如果服务器使用了反向代理软件无法取到真实客户端ip,需要添加其他方法。
			String ip = this.getIpAddr(request);
			
			String actionClassName = arg0.getAction().getClass().getName();
			String error_msg = "";
			int is_error_log = 0;
			
			HessianLog log = new HessianLog();
			log.setClientip(ip);
			log.setDatetimenow(new Timestamp(System.currentTimeMillis()));
			log.setFullclassname(actionClassName);
			log.setMethodname(actionName);
			log.setUserid(user.getId());
			log.setUsername(user.getName());
			log.setOrg_id(user.getBelong_org());
			if( list1!= null && list1.size()>0){
				log.setMenu_id(list1.get(0));
			}
			
			
			try {
				result = arg0.invoke();
			} catch (Exception e) {
				is_error_log = 1;
				error_msg = e.getMessage();
				throw  e;
			} finally {
				log.setError_message(error_msg);
				log.setIs_error_log(is_error_log);
				List<HessianLog> list = new ArrayList<HessianLog>();
				list.add(log);
  				hessianLogService.saveHessianLog(list);
				
			}
			return result;
			
		}
		
		
		return arg0.invoke();
		
	}
	
	public String getIpAddr(HttpServletRequest request) { 
		String ip = request.getHeader("x-forwarded-for"); 
		if(ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { 
		ip = request.getHeader("Proxy-Client-IP"); 
		} 
		if(ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { 
		ip = request.getHeader("WL-Proxy-Client-IP"); 
		} 
		if(ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { 
		ip = request.getRemoteAddr(); 
		} 
		return ip; 
		} 
	
}

public class LoginFilter extends AbstractInterceptor{

	private static final long serialVersionUID = 1L;
	
	private Logger logger =Logger.getLogger(LoginFilter.class.getName());
	
	private static String Error = "errorLogin";
	private String msg ;

	public String getMsg() {
		return msg;
	}
	public void setMsg(String msg) {
		this.msg = msg;
	}
	
	@Override
	public String intercept(ActionInvocation arg0) throws Exception {
		
		logger.debug("...LoginFilter开始载拦...");
		
		//取得请求的action实例
		ActionContext ctx = arg0.getInvocationContext();
		//取得提交URI
		HttpServletRequest request = (HttpServletRequest)ctx.get(ServletActionContext.HTTP_REQUEST);
		HttpServletResponse response = (HttpServletResponse)ctx.get(ServletActionContext.HTTP_RESPONSE);
		String actionName = ctx.getContext().getName();
		if("goAIOPortal".equals(actionName)||"goRealware".equals(actionName)||"loginCheck".equals(actionName)||"loginCh".equals(actionName)||"ukeyloginCheck".equals(actionName)||"loginCheckPass".equals(actionName)) {
			return arg0.invoke();
		}

		//获取session
		logger.debug("...LoginFilter:判断用户登录...");
		Map<String,Object> session =ctx.getSession();
		
		//异步传输
		if (request.getHeader("x-requested-with") != null && 
				request.getHeader("x-requested-with").equalsIgnoreCase("XMLHttpRequest")) {  
			if (session.get("user") == null) 
			{
				//if(!autoLogin(session,request)){
					msg = "用户未登录或登录超时,请重新登录!";
					logger.debug("用户未登录,重新登录!");
					//request.setAttribute("msg", msg);
					response.setContentType("text/json;charset=UTF-8");
					response.setHeader("Cache-Control", "no-cache");
					PrintWriter pw = null;
					try {
						pw = response.getWriter();
						pw.write("overdue");
					} catch (IOException e) {
						throw new EVoucherException("获取http写入流异常" + e.getMessage());
					} finally {
						if (pw != null) {
							pw.close();
						}
					}

					return null;
				//}
			}else{

				return arg0.invoke();
			}
			
		//同步传输
		}else{
			if (session.get("user") == null) 
			{
				logger.debug("用户未登录,重新登录!");	
				return Action.LOGIN;
				
			}else{
				return arg0.invoke();
			}
		}
		
		
	}
	
	//自动登陆
	private boolean autoLogin(Map<String,Object> session, HttpServletRequest request){
		return false;
	}

}

练习的Demo:http://download.csdn.net/detail/itjavawfc/8279169

抱歉!评论已关闭.