Struts2学习——拦截器(interceptor)学习

版权声明: https://blog.csdn.net/hu18315778112/article/details/84855024
  • 拦截器(interceptor)是struts2框架的又一主要功能,他是基于过滤器(Filter)来开发的,主要功能就是对用户的请求进行包装,处理等等。

  • 例如,前面学习的Action中获取参数的几种方式,都是在请求到达Action之前,在拦截器中进行获取并封装的,我们在Action类中创建属性,只不过是给获取的参数创建一个容器,好让前面的拦截器可以将参数封装进去。

  • Struts2框架自带了一堆拦截器(20个左右)

  •  这是Struts2默认的拦截器栈,也就是请求到达action默认要经过这些拦截器。可以看到其中有一个叫做
    • <interceptor-ref name="modelDriven"/>
  • 的拦截器,他的功能就是实现模型驱动封装参数。
<interceptor-stack name="defaultStack">
    <interceptor-ref name="exception"/>
    <interceptor-ref name="alias"/>
    <interceptor-ref name="servletConfig"/>
    <interceptor-ref name="i18n"/>
    <interceptor-ref name="prepare"/>
    <interceptor-ref name="chain"/>
    <interceptor-ref name="scopedModelDriven"/>
    <interceptor-ref name="modelDriven"/>
    <interceptor-ref name="fileUpload"/>
    <interceptor-ref name="checkbox"/>
    <interceptor-ref name="datetime"/>
    <interceptor-ref name="multiselect"/>
    <interceptor-ref name="staticParams"/>
    <interceptor-ref name="actionMappingParams"/>
    <interceptor-ref name="params"/>
    <interceptor-ref name="conversionError"/>
    <interceptor-ref name="validation">
        <param name="excludeMethods">input,back,cancel,browse</param>
    </interceptor-ref>
    <interceptor-ref name="workflow">
        <param name="excludeMethods">input,back,cancel,browse</param>
    </interceptor-ref>
    <interceptor-ref name="debugging"/>
</interceptor-stack>

我们知道有的系统(网站)、会要求用户必须登录,否则就无法使用网站中的各种功能,这就可以使用拦截器来实现,想要使用拦截器实现,当然要回创建并配置拦截器,接下来就学习了拦截器的基本用法:

  • 1. 如何创建拦截器interceptor

创建拦截器又有三种方式:

  • 方式一:实现Interceptor接口(最原始的方式)
// 接口中有三个方法需要实现,分别是创建时执行的方式、销毁时执行的方法,和拦截器具体行为
// 这里介绍一下拦截器的生命周期:随项目工程部署而创建(开启服务器)、随项目关闭而销毁
public class MyInterceptor1 implements Interceptor{

	@Override
	public void destroy() {
	}
	@Override
	public void init() {	
	}
	@Override
    // intercept方法,参数顾名思义:Action调用,用于执行action类的对象
	public String intercept(ActionInvocation invocation) throws Exception {
        /*
         * 放行之前书写在action执行之前的操作
         */
        // 放行
        String str =i nvocation.invoke();
        /*
         * 放行之后书写在action执行之后的操作
         */	
        return str;

        // 如果不想放行(不执行后续拦截器及Action类),可以直接返回一个结果字符创,如error
        // return "error"; // 当然前面的放行代码可以删掉,这样他会直接去到配置的中
                            // 查找name为error的result元素,并执行相应的跳转操作
	}
}
  • 方式二:继承AbstractInterceptor 类
// AbstractInterceptor类也是实现的Interceptor接口,他只是方便开发者书写代码,
// 因为init方法与destroy方法基本用不到,所以他就简化了需要实现的方法。
public class MyInterceptor1 extends AbstractInterceptor{

	@Override
	public String intercept(ActionInvocation arg0) throws Exception {
		return null;
	}
}
  • 方式三:继承MethodFilterInterceptor 类
// MethodFilterInterceptor类可以说是方法过滤拦截器。
// 他的功能就是:定制拦截器拦截的方法——拦截哪些方法、不拦截哪些方法
// 具体代码与其他几种方式相同
public class MyInterceptor1 extends MethodFilterInterceptor{

	@Override
	protected String doIntercept(ActionInvocation arg0) throws Exception {
		return null;
	}
}
  • 2. 如何使用(配置)拦截器

  • 写好了拦截器后,当然要使其生效,所以需要对拦截器进行具体配置,有优秀基础的人,拦截器配置的步骤可以参照struts-default.xml中的配置来写。

拦截器配置步骤:

  • 1. 注册拦截器
<!-- 拦截器主元素:位置:package元素里面,action元素前面 -->
<interceptors>
    <!-- interceptor元素:用于注册拦截器
             name属性:为该拦截器起个名称;
             class属性:填写该拦截器类的全包名
     -->
	<interceptor name="login" class="com.huhu.web.interceptor.MyInterceptor"></interceptor>
</interceptors>
  • 2. 创建拦截器栈
<!-- 该元素创建拦截器栈,放在interceptors元素里面,interceptor元素后面。name属性,为栈起个名称-->
<interceptor-stack name="loginStack">
    <!-- 将自己书写的拦截器栈引入进来,并引入struts2默认的拦截器 -->
	<interceptor-ref name="login"></interceptor-ref>
	<interceptor-ref name="defaultStack"></interceptor-ref>
</interceptor-stack>
  • 3. 指定拦截器工作范围
<!-- 直接在package元素里配置此元素,意思是该package下的所有action都要走name为loginStack的拦截
        器栈 -->
<default-interceptor-ref name="loginStack"></default-interceptor-ref>

<!-- 也可以指定某个action元素适用的拦截器栈(不常用) 
        将interceptor-ref元素配置在action里面,即指定该action适用的拦截器栈
-->
<action>
    <interceptor-ref name="loginStack"></interceptor-ref>
</action>
  • 到这里,技术点都学完了,之后就是适用这些知识实现效果:

  • 访问功能时,未登录,则跳转到登录页面。

详细实现:这里就简单的将代码贴出来。

  • 拦截器具体代码:
public class LoginInterceptor extends MethodFilterInterceptor{

	@Override
	protected String doIntercept(ActionInvocation invocation) throws Exception {
		// 获取session域,获取user
		Object user = ActionContext.getContext().getSession().get("user");
		// 判断用户是否登录(user是否存在)
		if (user == null) {
			// 未登录,跳转到登录页面
			return "toLogin";
		}
		// 登录放行
		return invocation.invoke();
	}
}
  • 配置文件详细代码:
<package name="sh" namespace="/" extends="struts-default">
	<!-- 配置程序员自定义拦截器,放在package元素的最前面 -->
	<interceptors>
		<!-- 注册拦截器 -->
		<interceptor name="login" class="com.huhu.web.interceptor.LoginInterceptor"></interceptor>
		<interceptor-stack name="loginStack">
			<!-- 将注册的拦截器添加到自定义拦截器栈 -->
			<interceptor-ref name="login">
                            <!-- 配置不执行此拦截器栈的方法 -->
				<param name="excludeMethods">login</param>
			</interceptor-ref>
			<!-- 引入struts2默认拦截器栈 -->
			<interceptor-ref name="defaultStack"></interceptor-ref>
		</interceptor-stack>
	</interceptors>
	<!-- 设置package默认拦截器栈 -->
	<default-interceptor-ref name="loginStack"></default-interceptor-ref>
	
	<!-- 配置全局结果集,整个工程都可以使用的结果集 ,放在全局异常处理之前-->
	<global-results>
		<result name="toLogin" type="redirect">/login.jsp</result>
	</global-results>

	<action name="custAction_*" class="com.huhu.web.action.CustomerAction" method="{1}">
		<result name="custlist" >/jsp/customer/list.jsp</result>

		<result name="success" type="redirectAction">
		    <param name="actionName">custAction_findCust</param>
                    <param name="namespace">/customer</param>
		</result>
		<!-- 配置可以动态调用的方法名,多个方法用,逗号隔开 -->
		<allowed-methods>findCust,add</allowed-methods>
	</action>

	<action name="userAction_*"	class="com.huhu.web.action.UserAction" method="{1}">
		<interceptor-ref name="loginStack"></interceptor-ref>
		<result name="login" type="redirect">/index.jsp</result>
		<result name="error" type="dispatcher">/login.jsp</result>
		<!-- 不知道为啥,以转发的方式到页面,页面加载不到资源,原因:资源路径前没加工程名 -->
		<!-- <result name="error" >/login.jsp</result> -->
		<allowed-methods>login</allowed-methods>
	</action>
</package>

这也可以说是已经实现了登录校验的功能(校验用户是否登录)

拓展:

  • 1. 拦截器无法拦截页面的显示,只能拦截action中的元素,所以想要实现拦截页面的功能需要使用其他的技术。或者,每个页面的显示都是使用action的某个方法跳转到的,则可以用拦截器拦截这些方法,来起到拦截页面显示的作用,不过这种方式可能不太常用。

 

  • 2. 如果页面使用的是frame框架布局的页面,未登录时,跳转到登录页面可能只是框架中的某一部分跳转,如:

  •  如果想让跳转到的登录页只显示登录页信息,可以使用js的一段简单代码解决:

  • 注意:此段代码实在想要显示的页面的文件中书写的,如:我的登录页面文件名为login.jsp,则在该文件中书写
<script type="text/javascript">
	window.onload=function(){
		if(window.parent != window){
			window.parent.location.href="${pageContext.request.contextPath}/login.jsp";
		}
	};
</script>
  • 书写一个页面加载完毕事件,作用是,页面加载完毕后,判断当前页面的父窗口是不是浏览器的主窗口,如果不是,则将父窗口重新跳转到当前页面。

猜你喜欢

转载自blog.csdn.net/hu18315778112/article/details/84855024