1. 程式人生 > >分享知識-快樂自己:Struts2框架 工作原理及執行流程圖(攔截器的使用)

分享知識-快樂自己:Struts2框架 工作原理及執行流程圖(攔截器的使用)

Struts2 架構圖:

1):提交請求

客戶端通過 HttpServletRequest 向 Servlet (即Tomcat)提交一個請求。

請求經過一系列的過濾器,例如圖中的 ActionContextCleanUp 和 Other filer (SlterMesh,etc)等,最後被 Struts 的核心過濾器 FilterDispatcher 控制到。

注:核心控制器 2.1.3 版本之後  Struts FileterDispatcher 核心控制器變成了 StrutsPrepareAndExcuteFilte

下圖所示:

 

被核心控制器控制到 才會訪問 ActionMapper 來決定是否呼叫某個 action (即使用者是否要求某個action)。

如果是其他資源請求例如 jsp 頁面,不會用到 action。

2):移交控制權

如果要用 action ,核心控制器將控制權 給 ActionProxy (即是 action 的代理)。

ActionProxy 獲得控制權之後通過 ConfigurationManager 物件載入核心配置檔案 struts.xml。

Struts 的 action 在這個配置檔案進行配置 , 所以要載入它。

3):建立 ActionInvocation 的例項

如果在 struts.xml 找到需要呼叫的action ,ActionProxy 會建立一個 ActionInvocation 的例項。

4):呼叫 action 錢的攔截器

攔截器是 struts2 非常重要的概念,是核心功能實現,Struts 中的大部分功能通過攔截器實現。

Actioninvocation 包括建立的 action 例項,同時包括另外非常重要的一部分====攔截器。

呼叫 action 前後還會呼叫很多的攔截器

在呼叫 action 之前會依此呼叫使用者所定義的攔截器。

5):呼叫 action 的業務方法進行業務處理

當把 action 前的攔截器執行完之後才會呼叫 action 的業務方法進行業務處理,

然後返回一個 Result (業務方法對應 String 型別的返回值,即使字串,例如 SUCCESS,INPUT,REEOR,NONE,LOGIN 和使用者自己在 Struts 對應定義 result標籤name屬性的值)。

6):匹配 result

然後根據返回的字串來排程我們的試圖來匹配我們的 struts.xml 中對應 action 標籤中的result 標籤。

一般來說返回一個 jsp 頁面,或者呼叫另某一個 action

7):反向執行攔截器

當返回檢視之後並沒有真正響應使用者,還需要把執行過的攔截器倒過來反向執行一遍。

8):響應客戶端

當這些攔截器被反向執行後,通過 HttpServletResponse 響應客戶端的請求。

簡單實現 登陸 驗證:點我下載原始碼

訪問路徑:沒有登陸直接訪問 localhost:8080/success  主頁面的時候會跳轉到登入頁

目錄結構:

UserAction:

package com.gdbd.action;

import com.gdbd.bean.UserInfo;
import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionSupport;
import com.opensymphony.xwork2.ModelDriven;

import java.util.Map;

/**
 * @author asus
 */
public class UserAction extends ActionSupport implements ModelDriven<UserInfo> {

    private UserInfo userInfo = new UserInfo();

    public UserInfo getUserInfo() {
        return userInfo;
    }

    public void setUserInfo(UserInfo userInfo) {
        this.userInfo = userInfo;
    }


    public String loginAction() {
        Map<String, Object> session = ActionContext.getContext().getSession();
        Map<String, Object> context = ActionContext.getContext().getValueStack().getContext();
        try {
            //再次訪問登陸頁面的時候判斷是否已經登陸了
            UserInfo userInfo = (UserInfo) context.get("userInfo");
            if (userInfo != null) {
                return "success";
            }
            if (!("admin".equals(userInfo.getUserName()))) {
                context.put("errorName", "使用者名稱錯誤");
            } else if (!("admin".equals(userInfo.getUserPwd()))) {
                context.put("errorPwd", "密碼錯誤");
            } else {
                session.put("userInfo", userInfo);
                return "success";
            }
        } catch (Exception ex) {
            ex.printStackTrace();
        }
        return "input";
    }

    public String success() {
        return SUCCESS;
    }


    @Override
    public UserInfo getModel() {
        return userInfo;
    }
}
View Code

UserInfo:

package com.gdbd.bean;

import java.io.Serializable;

/**
 * user 實體類
 * @author asus
 */
public class UserInfo implements Serializable {

    private String userName;
    private String userPwd;

    public String getUserName() {
        return userName;
    }

    public void setUserName(String userName) {
        this.userName = userName;
    }

    public String getUserPwd() {
        return userPwd;
    }

    public void setUserPwd(String userPwd) {
        this.userPwd = userPwd;
    }
}
View Code

UserInterceptor:

package com.gdbd.util;


import com.gdbd.bean.UserInfo;
import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.interceptor.Interceptor;

import java.util.Map;

/**
 * @author asus
 */
public class UserInterceptor implements Interceptor {
    @Override
    public void destroy() {
        System.out.println("===============銷燬==================");
    }

    @Override
    public void init() {
        System.out.println("===============初始化==================");
    }

    @Override
    public String intercept(ActionInvocation invocation) throws Exception {
        System.out.println("=======進入攔截器=======");
        System.out.println(invocation.getProxy().getActionName()+"======");
        Map<String, Object> session = invocation.getInvocationContext().getSession();
        UserInfo userInfo = (UserInfo) session.get("userInfo");
        if (userInfo != null) {
            String invoke = invocation.invoke();
            System.out.println("===========" + invoke);
            return invoke;
        }
        return "input";

    }
}
View Code

struts.xml:

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE struts PUBLIC  "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
        "http://struts.apache.org/dtds/struts-2.0.dtd">
<struts>

    <!--全域性配置:修改預設的日期提示資訊-->
    <!--<constant name="struts.i18n.encoding" value="UTF-8"/>-->
    <!--<constant name="struts.custom.i18n.resources" value="message"></constant>-->

    <package name="user" namespace="/user" extends="struts-default">

        <!--定義攔截器-->
        <interceptors>
            <!--自定義的攔截器-->
            <interceptor name="author" class="com.mlq.uitl.AuthorizationInterceptor"></interceptor>
            <!--定義攔截器棧-->
            <interceptor-stack name="myStack">
                <interceptor-ref name="defaultStack"/>
                <interceptor-ref name="author"/>
            </interceptor-stack>
        </interceptors>

        <!--<default-interceptor-ref name="myStack"></default-interceptor-ref>-->

        <!--沒有找到頁面預設顯示(故意把路徑寫錯可以測試效果)-->
        <default-action-ref name="defaultAction"/>
        <!--定義一個全域性結果-->
        <global-results>
            <result name="input">/fail.jsp</result>
        </global-results>
        <action name="defaultAction">
            <result>/error.jsp</result>
        </action>
        <action name="login" class="com.mlq.action.LoginegisterRActionG" method="login">
            <result type="redirectAction">${message}</result>
            <result name="input">/login.jsp</result>
        </action>
        <action name="suc">
            <result name="success">/success.jsp</result>
            <result name="input">/login.jsp</result>
            <interceptor-ref name="myStack"/>
        </action>

    </package>


</struts>
View Code

login.jsp:

<%@ taglib prefix="s" uri="/struts-tags" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>登入</title>
</head>
<body>
<h2>登入</h2>
<s:debug/>
<s:form method="post" action="login">

    <s:textfield label="請輸入使用者名稱" name="userName"></s:textfield>
    <s:password label="請輸入密碼" name="userPwd"></s:password>
    <s:property value="#errorName"/><s:property value="#errorPwd"/>
    <s:submit value="登陸"></s:submit>
</s:form>
</body>
</html>
View Code

success.jsp:

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Success</title>
</head>
<body>
 <h2>Success</h2>
</body>
</html>
View Code

web.xml:

<!DOCTYPE web-app PUBLIC
 "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
 "http://java.sun.com/dtd/web-app_2_3.dtd" >

<web-app>
  <display-name>Archetype Created Web Application</display-name>

  <!--核心控制器-->
  <filter>
    <filter-name>Struts2</filter-name>
    <filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class>
  </filter>
  <filter-mapping>
    <filter-name>Struts2</filter-name>
    <url-pattern>/*</url-pattern>
  </filter-mapping>
  
  <welcome-file-list>
    <welcome-file>login.jsp</welcome-file>
  </welcome-file-list>


</web-app>
View Code

Face your past without regret. Handle your present with confidence.Prepare for future without fear. keep the faith and drop the fear.

面對過去無怨無悔,把握現在充滿信心,備戰未來無所畏懼。保持信念,克服恐懼!一點一滴的積累,一點一滴的沉澱,學技術需要不斷的積澱!