Struts2拦截器

MVC框架及Struts2介绍
Struts2核心
Struts2拦截器
Struts2值栈和OGNL表达式
Struts2标签库

1 拦截器

1.1 拦截器

  拦截器(Interceptor):Struts2拦截器是在访问某个Action的方法之前或之后进行拦截,并且拦截器是可插拔的,可以通过xml配置实现。拦截器是AOP(面向切面编程)的一种实现。在Struts2中对Action的功能的实现都是通过拦截器完成的,比如参数接收、读取原生API、文件上传、异常统一处理等。
  拦截器栈(Interceptor Stack):将多个拦截器按一定的顺序组合成一条拦截器链。

1.2 拦截器特点

  特点
  1.简化Action:拦截器能把很多功能从Action中独立出来,分散到不同功能拦截器中,简化了Action代码;
  2.功能简单:拦截器和Action各自的功能更简单清晰;
  3.代码模块化:将不同功能代码封装到不同拦截器中,形成模块化管理,对不同Action根据功能需要配置相应拦截器;
  4.功能重用性:提高了拦截器实现的功能的重用性,同时实现了装配式和可插拔式的结构,使得整个系统结构更灵活。

1.3 拦截器执行原理

  拦截器原理图
  1.客户端发送请求;
  2.该请求经过一系列的过滤器(Filter):其中可选过滤器ActionContextCleanUp,帮助Struts2和其他框架集成。例如:SiteMesh Plugin;
  3.接着FilterDispatcher被调用,FilterDispatcher询问ActionMapper,来决定该请求是否需要调用某个Action;
  4.若ActionMapper决定需要调用某个Action,FilterDispatcher把请求的处理交给ActionProxy;
  5.ActionProxy通过Configuration Manager询问框架的配置文件,找到需要调用的Action类。
  6.ActionProxy创建一个ActionInvocation的实例;
  7.ActionInvocation实例调用Action的前后,涉及到相关拦截器(Intercepter)的调用;
  8.一旦Action执行完毕,ActionInvocation负责根据struts.xml中的配置找到对应的返回结果。返回结果是一个JSP或其他页面(也可以是其他的Action链)。JSP页面展现可使用Struts2框架中的标签(该过程会涉及ActionMapper);
  9.在上述过程中所有的对象(Action、Interceptors、Results等)都由xwork容器中的ObjectFactory创建。

2 默认拦截器

2.1 默认拦截器

  在struts-default.xml文件中,已经设置好了默认拦截器,在<package>继承struts-default时,就继承了预设值的默认拦截器。如果不继承struts-default就无法完成接收参数等功能。
  struts-default.xml文件中拦截器有三种配置:
  定义好的所有拦截器<interceptor>

<interceptors>
    <interceptor name="alias" class="..." />
    <interceptor name="autowiring" class="..." />
    ...
</interceptors>

  每一个拦截器都封装了一个Interceptor类

  定义好的所有拦截器栈<interceptor-stack>

<interceptors>
    <interceptor-stack name="basicStack">
        <interceptor-ref name="exception" />
        ...
        <interceptor-ref name="deprecation" />
    </interceptor-stack>

    <interceptor-stack name="validationWorkflowStack">
        <interceptor-ref name="basicStack" />
        ...
        <interceptor-ref name="workflow" />
    </interceptor-stack>
    ...
</interceptors>

  默认的拦截器(拦截器栈)<default-interceptor-ref>

<package>
    <interceptors>
        ...
    </interceptors>
    <default-interceptor-ref name="defaultStack" />
</package>
2.2 给Action设置拦截器

  在Action中设置拦截器:

<package name="default" namespace="/" extends="struts-default">
    <action name="user" class="cn.wenwen.action.UserAction" method="execute">
        <!-- 给Action设置拦截器 -->
        <interceptor-ref name="i18n">
            <param name="excludeParams">^action:.*,^method:.*</param>
        </interceptor-ref>
    </action>
</package>

  如果在Action中设置了拦截器,则默认的拦截器就会失效。

2.3 设置拦截器栈

  在<package>包中声明一个拦截器栈,然后在Action中引用。

<package name="default" namespace="/" extends="struts-default">
    <!-- 声明一个拦截器栈 -->
    <interceptors>
        <interceptor-stack name="mystack">
            <interceptor-ref name="i18n" />
            <interceptor-ref name="basicStack" />
        </interceptor-stack>
    </interceptors>
    <action name="user" class="cn.wenwen.action.UserAction" method="execute">
        <!-- Action中引用拦截器栈的name -->
        <interceptor-ref name="mystack" />
    </action>
</package>

  引用了设置的拦截器栈后,默认的拦截器就会失效。

3 自定义拦截器

  在登录功能和权限判断的时候就需要自定义拦截器。

3.1 创建拦截器

  创建一个拦截器然后实现Intercptor接口或者继承AbstractInterceptor,通常直接继承。

public class LoginInterceptor extends AbstractInterceptor {
    @Override
    public String intercept(ActionInvocation invocation) throws Exception {
        // 登录判断
        Object user = ActionContext.getContext().getSession().get("USER_IN_SESSION");
        if (user != null) {
            // 如果已经登录就放行
            return invocation.invoke();
        } else {
            // 没有登录也要返回一个视图
            return "login";
        }
    }
}

  如果作用域中能获取登录的用户,调用invocation.invoke()方法放行,如果不存在用户,跳转到login登录页面。

3.2 struts.xml中配置拦截器

  简单配置

<struts>
    <package name="default" namespace="/" extends="struts-default">
        <!-- 配置拦截器 -->
        <interceptors>
            <!-- 创建拦截器 -->
            <interceptor name="login" class="cn.wenwen.login.LoginInterceptor" />
            <!-- 创建拦截器栈 -->
            <interceptor-stack name="loginStack">
                <interceptor-ref name="login" />
                <interceptor-ref name="defaultStack" />
            </interceptor-stack>
        </interceptors>

        <!-- 全局视图:没有访问权限跳转登录页面 -->
        <global-results>
            <result name="login" type="redirect">
                /login.jsp
            </result>
        </global-results>

        <!-- 登录Action -->
        <action name="login" class="cn.wenwen.login.LoginAction"
            method="execute">
            <!-- 登录成功通过Action跳转到主页面 -->
            <result name="success" type="redirectAction">
                main
            </result>
            <!-- 登录失败,携带失败原因跳回登录页面 -->
            <result name="login">
                /login.jsp
            </result>
        </action>

        <!-- 主页面Action -->
        <action name="main" class="cn.wenwen.login.MainAction">
            <!-- 引用自定义拦截器栈 -->
            <interceptor-ref name="loginStack" />
            <result name="success">
                /main.jsp
            </result>
        </action>
    </package>
</struts>

  配置中,如果有很多Action都需要拦截器判断权限,每一个都需要引用自定义的拦截器。这时可以将自定义的拦截器栈设置为默认的,登录的Action不能做权限判断,则使用原始默认的替换掉自定义默认拦截器。

  高级配置
  通常对于项目而言,分前台和后台。前台不需要登录或权限判断就能直接访问操作,后台需要登录和权限判断以后才能访问操作。可以通过拦截器来实现登录和权限判断,将不需要做权限判断的放入一个<package>中使用默认拦截器,将需要做拦截判断的放入另一个<package>中使用自定义默认拦截器。

<struts>
    <!-- 不需要做权限判断的前台页面 -->
    <package name="default" namespace="/" extends="struts-default">
        ......
    </package>

    <!-- 需要做权限判断的后台页面 -->
    <package name="system" namespace="/system" extends="struts-default">
        <!-- 自定义拦截器栈 -->
        <interceptors>
            <interceptor name="login" class="cn.wenwen.login.LoginInterceptor" />
            <interceptor-stack name="loginStack">
                <interceptor-ref name="login" />
                <interceptor-ref name="defaultStack" />
            </interceptor-stack>
        </interceptors>
        <!-- 配置自定义默认拦截器 -->
        <default-interceptor-ref name="loginStack" />

        <!-- 全局视图:没有访问权限跳转登录页面 -->
        <global-results>
            <result name="login" type="redirect">
                /login.jsp
            </result>
        </global-results>

        <!-- 登录Action -->
        <action name="login" class="cn.wenwen.login.LoginAction"
            method="execute">
            <!-- 覆盖自定义默认拦截器 -->
            <interceptor-ref name="defaultStack" />
            <!-- 登录成功 -->
            <result name="success" type="redirectAction">
                main
            </result>
            <!-- 登录失败 -->
            <result name="login">
                /login.jsp
            </result>
        </action>

        <!-- 主页面Action -->
        <action name="main" class="cn.wenwen.login.MainAction">
            <result name="success">
                /main.jsp
            </result>
        </action>
    </package>
</struts>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值