(二十一)Strtus2.x拦截器

        拦截器是现在开发之中最为重要的特色,是基于AOP的设计思想(AOP是基于代理设计模式思想),面向切面设计思想实现的.

1.清楚拦截器的基本作用;

2.开发自己的拦截器

3.实现登录检查拦截器

4.实现服务器端数据验证拦截器(工具类);

5.拦截器栈的定义及使用

        在Strut2.x里面为了方便用户进行数据的验证,专门提供有validate()方法以及验证框架,但是这两个验证操作都有一个最致命的问题--永远都要在其赋值完成之后才能够验证,赋值之前无法验证,所以后台会一直出现错误,为了解决这样的问题,或者说为了解决所有辅助性的检测的功能.那么可以利用拦截器完成

认识拦截器

        在Struts2.x里面所有的客户端发送过来的请求都交给Filter进行处理,而后由Filter再去决定执行哪个Action.而拦截器是在某一个Action之前做的数据拦截操作

        

        实际上在之前也有拦截器出现,表单参数类型自动变为vo类型对象,这个就是拦截器的功能,

范例:定义一个Action,手工配置一个拦截器

package cn.mldn.action;
import com.opensymphony.xwork2.ActionSupport;
@SuppressWarnings("serial")
public class MessageAction extends ActionSupport{
	public void insert(){
		System.out.println("插入信息~~~~~~~~");
	}
}
范例:配置一个计算处理事件的拦截器


<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE struts PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 2.1//EN" "http://struts.apache.org/dtds/struts-2.1.dtd">
<struts>
	<package name="root" namespace="/" extends="struts-default">
		<action name="MessageAction" class="cn.mldn.action.MessageAction">
			<interceptor-ref name="timer"></interceptor-ref>
		</action>
	</package>
</struts>    

        此时会计算出当前操作的执行时间,而后台的输出效果如下

Executed action [//MessageAction!insert] took 1 ms.

        此时拦截器自动执行了,但是timer这个拦截器默认是在Action之后执行,

开发自定义拦截器

        如果要想开发自定义拦截器,那么在Struts2.x里面是由要求的这个拦截器的类必须继承自"com.opensymphony.xwork2.interceptor.AbstractInterceptor"父类,这个类是一个抽象类;

public abstract class AbstractInterceptor
extends Object
implements Interceptor

        在这个类之中存在有三个方法, 但是有一个抽象方法

○拦截:

public abstract class AbstractInterceptor
extends Object
implements Interceptor

        这个方法参数里面接受了一个ActionInvocation的对象,这个类对象可以取得一切的发送及执行信息.

范例:实现一个最基础的拦截器

package cn.mldn.interceptor;
import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.interceptor.AbstractInterceptor;
@SuppressWarnings("serial")
public class MyInterceptor extends AbstractInterceptor{
	@Override
	public void init() {
		System.out.println("-------拦截器初始化------");
	}
	@Override
	public String intercept(ActionInvocation arg0) throws Exception {
		System.out.println("---------拦截器执行----------");
		return arg0.invoke();  //将请求向下传递
	}
	@Override
	public void destroy() {
		System.out.println("----------拦截器销毁---------");
	}
}

        拦截器定义完成固然是一件好事,但是拦截器必须在strtus.xml文件中进行配置.

范例:配置strtus.xml文件

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE struts PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 2.1//EN" "http://struts.apache.org/dtds/struts-2.1.dtd">
<struts>
	<package name="root" namespace="/" extends="struts-default">
			<interceptors>
				<interceptor name="mldn" class="cn.mldn.interceptor.MyInterceptor"></interceptor>
			</interceptors>
		<action name="MessageAction" class="cn.mldn.action.MessageAction">
			<interceptor-ref name="timer"></interceptor-ref>
			<interceptor-ref name="mldn"></interceptor-ref>
		</action>
	</package>
</struts>    

        此时在MessageAction执行的时候挂了两个拦截器执行结果如下:

---------拦截器执行----------
插入信息~~~~~~~~
六月 05, 2018 10:19:06 下午 com.opensymphony.xwork2.util.logging.commons.CommonsLogger info

信息: Executed action [//MessageAction!insert] took 0 ms.

        此时的拦截器是在Action执行之前进行了处理,等于是说当前已经拦截下来了

范例:现在在Message中定义News类型进行数据接收

package cn.mldn.action;
import com.opensymphony.xwork2.ActionSupport;

import cn.mldn.vo.News;
@SuppressWarnings("serial")
public class MessageAction extends ActionSupport{
	private News news=new News();
	public News getNews() {
		return news;
	}
	public void insert(){
		System.out.println(this.news);
		System.out.println("插入信息~~~~~~~~");
	}
}

        发现一旦编写了自定义拦截器之后,非常遗憾的问题出现了,自动赋值操作不会出现了,因为在Struts2.x里面你没有使用拦截器,会自动使用赋值的拦截器,而一旦使用了拦截器,那么就需要手工来配置拦截器.

范例:修改配置

<action name="MessageAction" class="cn.mldn.action.MessageAction">
			<interceptor-ref name="timer"/>
			<interceptor-ref name="mldn"/>
			<interceptor-ref name="defaultStack"></interceptor-ref>
		</action>

        如果开始编写自定义拦截器,所有的操作必须采用手工的模式进行.

利用拦截器检测登录

            如果要进行登录检测,那么肯定是用过滤器是最合适的,不过遗憾的是Struts2.x为了Struts1.x区别所以使用了过滤器进行整个的分发处理.那么自己写的过滤器自然无法进行session的登录检查.如果要想实现登录检查,那么只能够依靠拦截器完成,也就是说现在必须要对ActionInvocation做进一步研究

这是一个接口com.opensymphony.xwork2.interceptor.AliasInterceptor

请求继续向下传递给Action:

String invoke()
              throws Exception

取得上下文对象内容:

ActionContext getInvocationContext()

使用此方法返回的是一个“com.opensymphony.xwork2.ActionContext”类的对象,这个类包含有如下方法:

取得全部的参数:public HttpParameters getParameters()

取得全部Session保存的数据

public Map<String,Object> getSession()

取得全部Application保存的属性数据

public Map<String,Object> getSession()

范例:假设登陆的session属性名称为“mid”,所以本次验证如下

package cn.mldn.interceptor;
import java.util.Map;
import org.apache.struts2.ServletActionContext;
import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.interceptor.AbstractInterceptor;
@SuppressWarnings("serial")
public class Logininterceptor extends AbstractInterceptor{
	@Override
	public String intercept(ActionInvocation arg0) throws Exception {
		Map<String, Object> map = arg0.getInvocationContext().getSession();
		if(map.get("mid")!=null){
			return arg0.invoke();
		}else{
			ServletActionContext.getRequest().setAttribute("msg", "您还未登录请先登录!");
			ServletActionContext.getRequest().setAttribute("url", "login.jsp");
		}
		return "forward.page";  //全局跳转提示页面
	}
}

        但是使用了一个“forward.page”的页面面对于这个页面需要提醒注意,几乎所有的开发之中都需要统一的信息提示页,那么可以定义为全局跳转资源.

范例:修改strtus.xml文件,配置拦截器使用

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE struts PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 2.1//EN" "http://struts.apache.org/dtds/struts-2.1.dtd">
<struts>
	<package name="root" namespace="/" extends="struts-default">
			<interceptors>
				<interceptor name="mldn" class="cn.mldn.interceptor.MyInterceptor"></interceptor>
				<interceptor name="login" class="cn.mldn.interceptor.Logininterceptor"></interceptor>
			</interceptors>
			<global-results >
				<result name="forward.page">forward.jsp</result>
			</global-results>
		<action name="MessageAction" class="cn.mldn.action.MessageAction">
			<interceptor-ref name="timer"/>
			<interceptor-ref name="mldn"/>
			<interceptor-ref name="login"></interceptor-ref>
			<interceptor-ref name="defaultStack"></interceptor-ref>
		</action>
	</package>
</struts>    

        此时已经彻底实现了拦截器的实际使用.

        所有的拦截器都会按照既定的顺序依次向下执行,这一点的控制是非常方便的,因为很多时候是先进行登录验证后再进行其他操作.

        

猜你喜欢

转载自blog.csdn.net/qq1019648709/article/details/80583040