1. 程式人生 > >自定義攔截器實現驗證登入

自定義攔截器實現驗證登入

首先給出Struts2的內部執行圖

這裡寫圖片描述
從圖中我們可以看出來,一個請求要到達Action需要經過很多的攔截器,也就是這些攔截器幫我們實現了struts當中的很多功能,例如表單登入,例項化成為一個javabean物件等等的功能。其中攔截器的實現就跟我們的servlet當中的過濾器Filter的實現是一樣的。

我們需要看編寫一個我們自己的攔截器實現一個功能就是隻有登入的使用者才能訪問我們的主頁,以及主頁裡面的連線,沒有登入的使用者需要登入才能訪問。實現的方式的原理就是,當用戶在登入頁面登入併成功後跳轉到showMain.action,通過showMain.action這個動作方法轉發到主頁介面,在主頁介面的其他頁面也是這樣通過一個這個方法來訪問其他頁面。
當然了這裡的重點是建立攔截器。一下是struts2的聯結器的關係圖
這裡寫圖片描述


從圖中可以看出,攔截器都繼承自一個介面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>