首先给出Struts2的内部运行图

gateway routes怎么拦截请求做认证_java


从图中我们可以看出来,一个请求要到达Action需要经过很多的拦截器,也就是这些拦截器帮我们实现了struts当中的很多功能,例如表单登录,实例化成为一个javabean对象等等的功能。其中拦截器的实现就跟我们的servlet当中的过滤器Filter的实现是一样的。我们需要看编写一个我们自己的拦截器实现一个功能就是只有登录的用户才能访问我们的主页,以及主页里面的连接,没有登录的用户需要登录才能访问。实现的方式的原理就是,当用户在登录页面登录并成功后跳转到showMain.action,通过showMain.action这个动作方法转发到主页界面,在主页界面的其他页面也是这样通过一个这个方法来访问其他页面。

当然了这里的重点是创建拦截器。一下是struts2的连接器的关系图

gateway routes怎么拦截请求做认证_struts_02


从图中可以看出,拦截器都继承自一个接口Interceptor,Interceptor有一个实现了的抽象类AbstractInterceptor,我们使用的所有的拦截器都直接或者间接的继承自这个类。

拦截器验证
实现之一:使用继承AbstractInterceptor

import javax.servlet.http.HttpSession;
import org.apache.struts2.ServletActionContext;
import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.interceptor.AbstractInterceptor;

public class CheckLoginInterceptor extends AbstractInterceptor {
    public String intercept(ActionInvocation invocation) throws Exception {
        //1.获取HttpSession
        HttpSession session = ServletActionContext.getRequest().getSession();
        //2.获取session域中的登录标记
        Object obj = session.getAttribute("user");
        //3.判断是否有登录标记
        if(obj == null){
            //用户没有登录
            return "input";
        }
        //4.用户登录了,放行
        String rtValue = invocation.invoke();
        return rtValue;
    }
}

拦截器需要在struts.xml中配置才能使用,而且,如果我们配置了拦截器,默认的拦截器就不会工作,所以,我们需要创建一个我们自己的拦截器栈,继承默认的拦截器栈。实现如下

<package name="p2" extends="struts-default">
        <interceptors>
            <interceptor name="checkLoginInterceptor" class="com.xxx.web.interceptor.CheckLoginInterceptor" />
            <!--定义一个拦截器栈,把我们自定义的拦截器和默认的拦截器栈放到一起.-->
            <interceptor-stack name="myDefaultStack">
                <interceptor-ref name="defaultStack"></interceptor-ref>
                <interceptor-ref name="checkLoginInterceptor"></interceptor-ref>
            </interceptor-stack>
        </interceptors>
        <!--配置全局的结果视图-->
        <global-results>
            <result name="input">/login.jsp</result>
        </global-results>
        <action name="login" class="com.xxx.web.action.Demo2Action" method="login">
            <result type="redirectAction">showMain</result>
        </action>
        <action name="showMain" class="com.xxx.web.action.Demo2Action" >
            <!--直接引入我们自己定义的拦截器栈,里面已经包含了默认的拦截器栈-->
            <interceptor-ref name="myDefaultStack"></interceptor-ref>
            <result>/main.jsp</result>
        </action>
        <action name="showOther" class="com.xxx.web.action.Demo2Action" >
            <!--直接引入我们自己定义的拦截器栈,里面已经包含了默认的拦截器栈-->
            <interceptor-ref name="myDefaultStack"></interceptor-ref>
            <result>/otherpage.jsp</result>
        </action>
    </package>

缺点:这样写,太麻烦,如果我们可以在需要不拦截的动作中写就方便很多
这个时候我们就要用AbstractInterceptor的子类MethodFilterInterceptor,MethodFilterInterceptor它里面提供了两个属性。
excludeMethods:哪些方法不需要拦截
includeMethods:哪些方法需要拦截

实现如下:

package com.zeroyoung.web.actioninterceptor;

import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.ModelDriven;
import com.opensymphony.xwork2.interceptor.AbstractInterceptor;
import com.opensymphony.xwork2.interceptor.MethodFilterInterceptor;
import org.apache.struts2.ServletActionContext;

import javax.servlet.http.HttpSession;

/**
 * Created by yanglin on 2016/11/3.
 */
public class CheckLoginInterceptor2 extends MethodFilterInterceptor {

    public String doIntercept(ActionInvocation actionInvocation) throws Exception {
        //1.获取HttpSession
        HttpSession session = ServletActionContext.getRequest().getSession();
        //2.获取session域中的登录标记
        Object obj = session.getAttribute("user");
        //3.判断是否有登录标记
        if(obj == null){
            //用户没有登录
            return "input";
        }
        //4.用户登录了,放行
        String rtValue = actionInvocation.invoke();
        return rtValue;
    }

}

配置如下:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE struts PUBLIC
    "-//Apache Software Foundation//DTD Struts Configuration 2.3//EN"
    "http://struts.apache.org/dtds/struts-2.3.dtd">
<struts>
    <constant name="struts-devMode" value="true"></constant>
    <!--<package name="p1" extends="struts-default">
        <interceptors>
            <interceptor name="CheckLoginInterceptor" class="com.zeroyoung.web.actioninterceptor.CheckLoginInterceptor">

            </interceptor>
        </interceptors>
        <global-results>
            <result name="input" >/login.jsp</result>
        </global-results>

        <action name="login" class="com.zeroyoung.web.action.UserAction" method="login">
            <result name="success" type="redirectAction">showMain</result>
        </action>
        <action name="showMain" class="com.zeroyoung.web.action.UserAction" >
            <interceptor-ref name="defaultStack"></interceptor-ref>
            <interceptor-ref name="CheckLoginInterceptor"></interceptor-ref>
            <result>/main.jsp</result>
        </action>
        <action name="showOther" class="com.zeroyoung.web.action.UserAction" >
            <interceptor-ref name="defaultStack"></interceptor-ref>
            <interceptor-ref name="CheckLoginInterceptor"></interceptor-ref>
            <result>/other.jsp</result>
        </action>
    </package>-->

<!--    <package name="p1" extends="struts-default">
        <interceptors>
            <interceptor name="CheckLoginInterceptor" class="com.zeroyoung.web.actioninterceptor.CheckLoginInterceptor">
            </interceptor>
            <interceptor-stack name="MydefaultStack">
                <interceptor-ref name="defaultStack"></interceptor-ref>
                <interceptor-ref name="CheckLoginInterceptor"></interceptor-ref>
            </interceptor-stack>
        </interceptors>
        <global-results>
            <result name="input" >/login.jsp</result>
        </global-results>

        <action name="login" class="com.zeroyoung.web.action.UserAction" method="login">
            <result name="success" type="redirectAction">showMain</result>
        </action>
        <action name="showMain" class="com.zeroyoung.web.action.UserAction" >
            <interceptor-ref name="MydefaultStack"/>
            <result>/main.jsp</result>
        </action>
        <action name="showOther" class="com.zeroyoung.web.action.UserAction" >
            <interceptor-ref name="MydefaultStack"/>
            <result>/other.jsp</result>
        </action>
    </package>-->
    <package name="p1" extends="struts-default">
        <interceptors>
            <interceptor name="CheckLoginInterceptor" class="com.zeroyoung.web.actioninterceptor.CheckLoginInterceptor2">
            </interceptor>
            <interceptor-stack name="myDefaultStack">
                <interceptor-ref name="CheckLoginInterceptor"></interceptor-ref>
                <interceptor-ref name="defaultStack"></interceptor-ref>
            </interceptor-stack>
        </interceptors>
        <!--配置我们的拦截器作为默认的拦截器,其中把默认的拦截器也添加进来了-->
        <default-interceptor-ref name="myDefaultStack"></default-interceptor-ref>
        <global-results>
            <result name="input" >/login.jsp</result>
        </global-results>
        <action name="login" class="com.zeroyoung.web.action.UserAction" method="login">
            <interceptor-ref name="myDefaultStack">
                <!-- 在引用自定义拦截器栈的时候,给指定的拦截器注入参数。方式就是:拦截器名称.属性名称 -->
                <param name="CheckLoginInterceptor.excludeMethods">login</param>
            </interceptor-ref>
            <result name="success" type="redirectAction">showMain</result>
        </action>
        <action name="showMain" class="com.zeroyoung.web.action.UserAction" >
            <result>/main.jsp</result>
        </action>
        <action name="showOther" class="com.zeroyoung.web.action.UserAction" >
            <result>/other.jsp</result>
        </action>
    </package>
</struts>