Struts2拦截器的简单应用,登录权限拦截器及与过滤器的区别(八)上

简介: Struts2拦截器的简单应用,登录权限拦截器及与过滤器的区别(八)

Struts2的拦截器,功能非常强大,很多强有力的功能都是通过拦截器实现的。我们输入一个网址,为什么只配置了过滤器和struts.xml文件中的action,就会去执行Action呢? 就是因为拦截器的存在。


Struts2框架已经默认为我们的每一个自定义的action都实现了一个拦截器default-stack。 其中拦截器的相关配置在struts-core核心包下的struts-default.xml文件中。


20200609114244493.png


拦截器是在Action执行方法前被调用,在方法执行后被销毁。


一. Struts2提供的关于拦截器的接口和类


一.一 Struts2官方提供的拦截器Interceptor接口


package com.opensymphony.xwork2.interceptor;
import com.opensymphony.xwork2.ActionInvocation;
import java.io.Serializable;
public abstract interface Interceptor
  extends Serializable
{
  public abstract void destroy();
  public abstract void init();
  public abstract String intercept(ActionInvocation paramActionInvocation)
    throws Exception;
}


destroy()方法是销毁,init()是初始化, intercept() 方法才是我们真正要关注的方法。


我们编写拦截器,一般不使用实现这个接口,而是继承它的实现类AbstractInterceptor


一.二 抽象类AbstractInterceptor


package com.opensymphony.xwork2.interceptor;
import com.opensymphony.xwork2.ActionInvocation;
public abstract class AbstractInterceptor
  implements Interceptor
{
  public void init() {}
  public void destroy() {}
  public abstract String intercept(ActionInvocation paramActionInvocation)
    throws Exception;
}


这个抽象类AbstractInterceptor实现了Interceptor接口,并且重写了init()方法和destroy()方法,用户只需要实现interceptor()方法即可。


我们用这个抽象类做一个简单的拦截器,实际开发中也并不用这一个抽象类AbstractInterceptor。


二. 简单自定义一个拦截器


二.一 新建拦截器类MyInterceptor ,继承AbstractInterceptor类


前堤已经有了一个基本的Struts2的运行环境,延用上一章的struts2的配置和Action


在com.yjl.web.interceptor包下新建一个MyInterceptor类,让其继承AbstractInterceptor类


package com.yjl.web.interceptor;
import org.apache.log4j.Logger;
import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.interceptor.AbstractInterceptor;
/**
* @author 两个蝴蝶飞
* @version 创建时间:Aug 25, 2018 4:03:21 PM
* 类说明
*/
public class MyInterceptor extends AbstractInterceptor{
  private static final long serialVersionUID = -6424208964705287809L;
  private Logger logger=Logger.getLogger(MyInterceptor.class);
  @Override
  public String intercept(ActionInvocation actionInvocation)
      throws Exception {
    logger.info("******开始执行拦截器*******");
    String result=actionInvocation.invoke();
    logger.info("执行后的结果为:"+result);
    logger.info("********结束执行拦截器**********");
    return result;
  }
}


二.二 创建Action控制器,MyInterceptorAction


在MyInterceptorAction中,返回SUCCESS字符串


public class MyInterceptorAction extends ActionSupport{
  private static final long serialVersionUID = 8278845997106407817L;
  public String getForm(){
    return SUCCESS;
  }
}


二.三 在struts.xml中package标签下实例化拦截器


自定义的拦截器,刚开始定义好后,并不知道属于哪一个action,所以实例化拦截器放在 包下,用一个标签包起来,里面放置标签,这个标签有name和class两个属性,通过反射可以自己实例化自定义的拦截器。


<package name="interceptor" extends="struts-default" namespace="/">
    <interceptors>
      <!-- 定义单个拦截器 -->
      <interceptor name="myInterceptor" class="com.yjl.web.interceptor.MyInterceptor">
      </interceptor>
    </interceptors>
    <!-- 配置跳转页面 -->
    <action name="*">
      <result>/WEB-INF/content/{1}.jsp</result>
    </action>
</package>


二. 四 在struts.xml中action标签下引用具体的拦截器


<package name="interceptor" extends="struts-default" namespace="/">
    <interceptors>
      <!-- 定义单个拦截器 -->
      <interceptor name="myInterceptor" class="com.yjl.web.interceptor.MyInterceptor">
      </interceptor>
    </interceptors>
    <action name="Interceptor_*" class="com.yjl.web.action.MyInterceptorAction" method="{1}">
      <!-- 引入自定义拦截器 -->
      <interceptor-ref name="myInterceptor"></interceptor-ref>
      <!-- 配置跳转页面  -->
      <result name="success">/WEB-INF/content/form.jsp</result>
    </action>
    <!-- 配置跳转页面 -->
    <action name="*">
      <result>/WEB-INF/content/{1}.jsp</result>
    </action>
</package>


二.五 编写 /content/form.jsp 页面


<body>
拦截器跳转后页面
</body>


二.六 测试验证拦截器


重启服务器,输入网址:http://localhost:8080/Struts_Interceptor/Interceptor_getForm

查看控制台日志打印:


202006091143157.png


可以发现拦截器配置完成.


提示: (在操作时,不要忘记配置web.xml中struts的过滤器)


三. 拦截器配置过程中的扩展


上面例子只是一个简单的拦截器,在实际项目中可能会配置多个拦截器,每个拦截器有不同的功能。复杂的拦截器该如何配置呢?


三.一 默认拦截器 defaultStack


可以查看struts-core.jar包下的struts-default.xml中的配置,注意查看示例. 这里简单一下里面的配置


<!--注意名称: defaultStack-->
<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="multiselect"/>
        <interceptor-ref name="staticParams"/>
        <interceptor-ref name="actionMappingParams"/>
        <interceptor-ref name="params">
            <param name="excludeParams">^action:.*,^method:.*</param>
        </interceptor-ref>
        <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-ref name="deprecation"/>
    </interceptor-stack>
<!--留意这一个-->
  <default-interceptor-ref name="defaultStack"/>
  <!--每一个继承ActionSupport类的Action都具有基本拦截器的功能-->
  <default-class-ref class="com.opensymphony.xwork2.ActionSupport" />


三.二 自定义配置多个拦截器


<interceptors>
  <!-- 定义单个拦截器 -->
  <interceptor name="myInterceptor1" class="com.yjl.web.interceptor.MyInterceptor1">
  </interceptor>
  <interceptor name="myInterceptor2" class="com.yjl.web.interceptor.MyInterceptor2">
  </interceptor>
  <interceptor name="myInterceptor3" class="com.yjl.web.interceptor.MyInterceptor3">
  </interceptor>
</interceptors>


那么在Action中引用中,用到了哪一个拦截器,就用哪一个拦截器.


假如 MyInterceptorAction中用了第二个和第三个。


        <action name="Form_*" class="com.yjl.web.action.MyInterceptorAction" method="{1}">
        <!-- 引入自定义拦截器 -->
        <interceptor-ref name="myInterceptor2"></interceptor-ref>
        <interceptor-ref name="myInterceptor3"></interceptor-ref>
        <result name="success">/WEB-INF/content/form.jsp/result>
    </action>


用到哪一个就配置哪一个。


三.三 拦截器栈 <interceptor-stack> </interceptor-stack>


我们的package包下开发中有多个Action(当然前堤也是interceptor拦截器多的情况下如1~30),


现在情况是 Form1Action引入了111拦截器,Form2Action引入了212拦截器,

Form3Action引入了3~13拦截器,


要是按照上面的样式配置的话,4~11会被配置成3遍,很显然不太好。


这个时候,可以将4~11配置成一个拦截器栈, 这样在引用了就比较容易引用了。


拦截器栈放在package标签下,用的是 <interceptor-stack > </interceptor-stack>


<interceptors>
  <!-- 定义单个拦截器 -->
  <interceptor name="myInterceptor1" class="com.yjl.web.interceptor.MyInterceptor1">
  </interceptor>
  <interceptor name="myInterceptor2" class="com.yjl.web.interceptor.MyInterceptor2">
  </interceptor>
  <interceptor name="myInterceptor3" class="com.yjl.web.interceptor.MyInterceptor3">
  </interceptor>
  <!-- 配置拦截器栈,里面有三个拦截器 -->
  <interceptor-stack name="myInterceptor">
    <interceptor-ref name="myInterceptor1"></interceptor-ref>
    <interceptor-ref name="myInterceptor2"></interceptor-ref>
    <interceptor-ref name="myInterceptor3"></interceptor-ref>
  </interceptor-stack>
</interceptors>


可以根据不同的action,配置不同的interceptor-stack, 可以配置多个。


这样在配置MyInterceptorAction时,只需要简单一句


<action name="Interceptor_*" class="com.yjl.web.action.MyInterceptorAction" method="{1}">
  <!-- 引入自定义拦截器栈 -->
  <interceptor-ref name="myInterceptor"></interceptor-ref>
  <result name="success">/WEB-INF/content/form.jsp</result>
</action>


便具有1,2,3三个拦截器的功能了。


配置FormAction 时,也同样引用:


<action name="Form_*" class="com.yjl.web.action.FormAction" method="{1}">
  <!-- 引入自定义拦截器栈 -->
  <interceptor-ref name="myInterceptor"></interceptor-ref>
  <result name="success">/WEB-INF/content/form2.jsp</result>
</action>


也就具有了1,2,3三个拦截器的功能了。


三.四 默认拦截器栈 default-stack


如同Java中默认构造函数一样,Struts2提供了一个默认的拦截器栈default-stack,


如果用户自己引用了一个拦截器,无论是框架提供的,还是自定义的,


原有的拦截器栈将不在起作用了,将失效了。


默认的拦截器 default-stack中有很多的功能,如异常,别名,国际化,参数,文件上传等。 所以这些功能很重要,所以,默认的拦截器不能丢掉。


我们在引入自定义拦截器后,还需要引入默认的拦截器


<action name="Interceptor_*" class="com.yjl.web.action.MyInterceptorAction" method="{1}">
    <!-- 引入自定义拦截器 -->
    <interceptor-ref name="myInterceptor"></interceptor-ref>
    <!-- 放置原有的默认的拦截器 -->
    <interceptor-ref name="defaultStack"></interceptor-ref>
    <result name="success">/WEB-INF/content/form.jsp</result>
</action>


这样, MyInterceptorAction 将具有原先拦截器的功能,也具有自定义拦截器的功能。


三.五 将新的拦截器配置成默认的拦截器


可以利用 将原有的默认的defaultStack给其改变。


  <interceptors>
    <!-- 定义单个拦截器 -->
    <interceptor name="myInterceptor1" class="com.yjl.web.interceptor.MyInterceptor1">
    </interceptor>
    <interceptor name="myInterceptor2" class="com.yjl.web.interceptor.MyInterceptor2">
    </interceptor>
    <interceptor name="myInterceptor3" class="com.yjl.web.interceptor.MyInterceptor3">
    </interceptor>
    <!-- 注意看拦截器的配置 -->
    <interceptor-stack name="myInterceptor">
      <interceptor-ref name="myInterceptor1"></interceptor-ref>
      <interceptor-ref name="myInterceptor2"></interceptor-ref>
      <interceptor-ref name="myInterceptor3"></interceptor-ref>
      <interceptor-ref name="defaultStack"></interceptor-ref>
    </interceptor-stack>
  </interceptors>
  <!-- 写在Action外面 -->
  <default-interceptor-ref name="myInterceptor"></default-interceptor-ref>


这样,就改变了默认的拦截器的值。


在Action中就不用在配置拦截器了


<action name="Interceptor_*" class="com.yjl.web.action.MyInterceptorAction" method="{1}">
      <result name="success">/WEB-INF/content/form.jsp</result>
</action>


注意,这个新定义的默认拦截器的作用范围是 package.


Struts2以 package 包 作为划分区域。


三.六 拦截器配置参数


用<param> </param> 进行引用。


<interceptor name="myInterceptor" class="com.yjl.web.interceptor.MyInterceptor">
    <!--添加参数-->
    <param name="charset">UTF-8</param>
</interceptor>


在MyInterceptor拦截器中,添加这个charset属性,实现setter和getter方法即可。


public class MyInterceptor extends AbstractInterceptor{
  private static final long serialVersionUID = -6424208964705287809L;
  private Logger logger=Logger.getLogger(MyInterceptor.class);
  private String charset;
  public String getCharset() {
    return charset;
  }
  public void setCharset(String charset) {
    this.charset = charset;
  }
    //后面还有很多代码,没有复制


这样,在 struts.xml 中定义传入参数值,在过滤器中就可以引用这个参数了。


这个参数可以在拦截器定义时注入,也可以在拦截器被Action引入时注入。


**拦截器定义时引入: **


<interceptor-ref name="myInterceptor">
  <param name="charset">UTF-8</param>
</interceptor-ref>


拦截器被Action 引入时注入:


<interceptor name="myInterceptor" class="com.yjl.web.interceptor.MyInterceptor">
    <!--添加参数-->
    <param name="charset">UTF-8</param>
</interceptor>


三.七 公共功能拦截器配置


在项目中,常常有登录拦截器,权限验证拦截器,日志拦截器等,对于这些公共的拦截器配置,


推荐将新的拦截器栈名变成 defaultStack, 与原先的保持一致。


<interceptors>
  <interceptor name="loginInterceptor" class="com.yjl.web.interceptor.LoginInterceptor">
  </interceptor>
  <interceptor-stack name="defaultStack">
    <interceptor-ref name="loginInterceptor">
    <interceptor-ref name="logInterceptor">
    <interceptor-ref name="defaultStack"></interceptor-ref>
  </interceptor-stack>
</interceptors>



相关文章
|
4月前
SpringMVC-拦截器参数及拦截器链配置
SpringMVC-拦截器参数及拦截器链配置
32 0
|
6月前
|
Java 容器
过滤器和拦截器的区别
Filter 也称为过滤器,基于Servlet实现,拦截器(Interceptor)是一种动态拦截方法调用的机制,在SpringMVC中动态拦截控制器方法的执行,基于AOP思想,对方法进行增强。和servlet 中的过滤器类似,都是对用户请求进行处理。
49 0
|
8月前
|
JSON 缓存 安全
自定义配置拦截器
自定义配置拦截器
80 0
|
XML 存储 前端开发
struts2中的拦截器Interceptor,拦截器栈,Token口令拦截
struts2中的拦截器Interceptor,拦截器栈,Token口令拦截
118 0
struts2中的拦截器Interceptor,拦截器栈,Token口令拦截
|
前端开发 Java 数据安全/隐私保护
SpringMVC拦截器实现登录权限控制
SpringMVC的处理器拦截器,类似于Servlet开发中的过滤器Filter,用于对处理器进行预处理和后处理。 依赖于web框架,在实现上基于Java的反射机制,属于面向切面编程(AOP)的一种运用。由于拦截器是基于 web框架的调用,因此可以使用Spring的依赖注入(DI)进行一些业务操作,同时一个拦截器实例在一个 controller生命周期之内可以多次调用。
boot 中自定义shiro过滤器的拦截顺序
@boot 中filter SecurityUtils.getSubject()No SecurityManager accessible
boot 中自定义shiro过滤器的拦截顺序
|
JSON 运维 数据格式
[SpringMVC]拦截器②(拦截器参数、拦截器链配置)
拦截器②(拦截器参数、拦截器链配置)
[SpringMVC]拦截器②(拦截器参数、拦截器链配置)
SpringMVC:拦截器和过滤器的区别
SpringMVC:拦截器和过滤器的区别
103 0
SpringMVC:拦截器和过滤器的区别
|
Java 数据安全/隐私保护 容器
Struts2拦截器的简单应用,登录权限拦截器及与过滤器的区别(八)下
Struts2拦截器的简单应用,登录权限拦截器及与过滤器的区别(八)
145 0
Struts2拦截器的简单应用,登录权限拦截器及与过滤器的区别(八)下
SpringMVC 拦截器拦截 /* 和 /** 的区别:
SpringMVC 拦截器拦截 /* 和 /** 的区别:
165 0