攔截器 & Structs國際化 & Ognl

攔截器

  • 攔截器概述 :

    • 基本概念 : Intercetor, 即為攔截器僚焦。
      1. 在Struts2中把每一個功能都用一個個的攔截器實(shí)現(xiàn)助隧;用戶想用struts的哪個功能的時候,可以自由組裝使用。
      2. Struts2中為了方法用戶對攔截器的引用, 提供了攔截器棧的定義, 里面可以包含多個攔截器查辩。文件夾(文件, 文件2) 攔截器棧(攔截器, 攔截器2)
      3. Struts2中如果用戶沒有指定執(zhí)行哪些攔截器, struts2有一個默認(rèn)執(zhí)行的棧, defaultStack; 一旦如果用戶有指定執(zhí)行哪些攔截器, 默認(rèn)的攔截器棧就不會被執(zhí)行攔截器的設(shè)計(jì), 就是基于組件設(shè)計(jì)的應(yīng)用胖笛!
  • 攔截器配置舉例 : struts-default.xml文件中,定義了struts提供的所有攔截器

    // 1. 定義攔截器以及攔截器棧
<interceptors>
    // 1.1 攔截器定義
    <interceptor name="" class="" /> 
    // 1.2 攔截器棧的定義
    <interceptor-stack name="defaultStack">
    引用了上面攔截器(1.1)
    </interceptor-stack>
</interceptors>
    // 2. 默認(rèn)執(zhí)行的攔截器(棧)
<default-interceptor-ref name="defaultStack"/>
  • 攔截器API :

    • Interceptor 攔截器接口
    • AbstractInterceptor : 攔截器默認(rèn)實(shí)現(xiàn)的抽象類; 一般用戶只需要繼承此類即可繼續(xù)攔截器開發(fā)
    • ActionInvocation : 攔截器的執(zhí)行狀態(tài), 調(diào)用下一個攔截器或Action
  • 自定義一個攔截器案例

    • 步驟:
      1. 寫攔截器類 (看生命周期)
      2. 配置
      3. 代碼示例
// 自定義攔截器
public class HelloInterceptor implements Interceptor{
    // 啟動時候執(zhí)行
    public HelloInterceptor(){
        System.out.println("創(chuàng)建了攔截器對象");
    }
    // 啟動時候執(zhí)行
    @Override
    public void init() {
        System.out.println("執(zhí)行了攔截器的初始化方法");
    }
    // 攔截器業(yè)務(wù)處理方法 (在訪問action時候執(zhí)行宜岛? 在execute之前執(zhí)行长踊?)
    @Override
    public String intercept(ActionInvocation invocation) throws Exception {
        System.out.println("2. 攔截器,業(yè)務(wù)處理-開始");
        // 調(diào)用下一個攔截器或執(zhí)行Action  (相當(dāng)于chain.doFilter(..)
        // 獲取的是: execute方法的返回值
        String resultFlag = invocation.invoke();
        System.out.println("4. 攔截器萍倡,業(yè)務(wù)處理-結(jié)束");
        return resultFlag;
    }
    @Override
    public void destroy() {
        System.out.println("銷毀....");
    }
}
<?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>
    <package name="hello" extends="struts-default">

        <!-- 【攔截器配置】 -->
        <interceptors>
            <!-- 配置用戶自定義的攔截器 -->
            <interceptor name="helloInterceptor" class="cn.itcast.a_interceptor.HelloInterceptor"></interceptor>
            <!-- 自定義一個棧: 要引用默認(rèn)棧身弊、自定義的攔截器 -->
            <interceptor-stack name="helloStack">
                <!-- 引用默認(rèn)棧 (一定要放到第一行)-->
                <interceptor-ref name="defaultStack"></interceptor-ref>
                <!-- 引用自定義攔截器 -->
                <interceptor-ref name="helloInterceptor"></interceptor-ref>
            </interceptor-stack>
        </interceptors>
        
        <!-- 【執(zhí)行攔截器】 -->
        <default-interceptor-ref name="helloStack"></default-interceptor-ref>
    
        <!-- Action配置 -->
        <action name="hello" class="cn.itcast.a_interceptor.HelloAction">
            <result name="success"></result>
        </action>
    </package>
</struts>
  • 攔截器執(zhí)行流程

    • 啟動 : 創(chuàng)建所有攔截器、執(zhí)行init()
    • 訪問:
      • 先創(chuàng)建Action列敲,
      • 再執(zhí)行攔截器阱佛,
      • 最后 : 攔截器放行,執(zhí)行execute();
  • 攔截器案例

    • 需求:登陸后戴而,顯示列表凑术!
    • 案例準(zhǔn)備:
      • Struts jar文件
      • DbUtils組件
      • 數(shù)據(jù)庫連接池/ 驅(qū)動包
    • 代碼
      • login.jsp :
<body>
     <form method="post" action="${pageContext.request.contextPath }/user_login.action">
        用戶名:<input type="text" name="admin.userName"><br/>
        密碼:<input type="text" name="admin.pwd"><br/>
        <input type="submit" value="登陸"><br/>
     </form>
  </body>
- UserAction.java : 
public class UserAction extends ActionSupport {
    // ---------1. 封裝請求數(shù)據(jù)-----------
    private Admin admin;
    public Admin getAdmin() {
        return admin;
    }
    public void setAdmin(Admin admin) {
        this.admin = admin;
    }
    // ---------2. 調(diào)用的Service-----------
    private AdminService adminService = new AdminService();
    // 登陸
    public String login() {
        try {
            Admin userInfo = adminService.login(admin);
            // 判斷
            if (userInfo == null){
                // 登陸失敗
                return "input";
            }
            // 登陸成功:數(shù)據(jù)保存在session中
            ActionContext.getContext().getSession().put("userInfo", userInfo);
            // 登陸成功
            return "loginSuccess";
        } catch (Exception e) {
            return ERROR;
        }
    }
    // 列表
    public String list() {
        try {
            // 查詢?nèi)?            List<Admin> list = adminService.getAll();
            // 保存到request
            ActionContext.getContext().getContextMap().put("listAdmin", list);
            return "list";
        } catch (Exception e) {
            return ERROR;
        }
    }
    public String add() {
        return null;
    }   
}
- list.jsp : 
<body>
    <h1>歡迎你,${userInfo.userName }</h1>
    <table align="center" border="1">
        <tr>
            <td>序號</td>
            <td>編號</td>
            <td>用戶名</td>
            <td>密碼</td>
        </tr>
        <%--@taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" --%>
        <!-- 用struts標(biāo)簽迭代數(shù)據(jù) -->
        <%@taglib uri="/struts-tags" prefix="s" %>
        <s:iterator var="admin" value="#request.listAdmin" status="st">
            <tr>
                <td>
                    <s:property value="#st.count"/>
                </td>
                <td>
                    <s:property value="#admin.id"/>
                </td>
                <td>
                    <s:property value="#admin.userName"/>
                </td>
                <td>
                    <s:property value="#admin.pwd"/>
                </td>
            </tr>
        </s:iterator>
  
    </table>
  </body>
- 自定義攔截器
public class UserCheckInterceptor extends AbstractInterceptor{
    /**
     * 攔截器業(yè)務(wù)處理方法
     */
    public String intercept(ActionInvocation invocation) throws Exception {
        // 拿到當(dāng)前執(zhí)行的方法名:判斷填硕,只有當(dāng)前方法名不是login,就進(jìn)行驗(yàn)證
        
        // 獲取ActionContext對象
        ActionContext ac = invocation.getInvocationContext();
        
        // 獲取action的代理對象
         ActionProxy proxy = invocation.getProxy();
         // 獲取當(dāng)前執(zhí)行的方法名
         String methodName = proxy.getMethod();
         // 判斷
         if (!"login".equals(methodName)) {
             // 先獲取當(dāng)前登陸的用戶
             Object obj = ac.getSession().get("userInfo");
             if (obj == null) {
                 // 沒有登陸
                 return "input";
             } else {
                 // 當(dāng)前用戶有登陸
                 return invocation.invoke();
             }
         } else {
             // 說明當(dāng)前用戶正在登陸
             return invocation.invoke();
         }
    }
}
- 配置攔截器
<?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>
    <package name="user" extends="struts-default">
    
        <!-- 【攔截器配置】 -->
        <interceptors>
            <interceptor name="loginCheck" class="cn.itcast.interceptor.UserCheckInterceptor"></interceptor>
            <interceptor-stack name="myStack">
                <interceptor-ref name="defaultStack"></interceptor-ref>
                <interceptor-ref name="loginCheck"></interceptor-ref>
            </interceptor-stack>
        </interceptors>
        <!-- 【執(zhí)行攔截器:第一種寫法: 當(dāng)前包下所有的acntion都執(zhí)行myStack椔笥】
        <default-interceptor-ref name="myStack"></default-interceptor-ref>
         -->
    
        <!-- 全局配置 -->
        <global-results>
            <result name="error">/error.jsp</result>
        </global-results>
        
        <action name="user_*" class="cn.itcast.action.UserAction" method="{1}">
            
            <!--第二種寫法: 只是在這一個Action中執(zhí)行myStack棧 
            <interceptor-ref name="defaultStackt"></interceptor-ref>
            <interceptor-ref name="loginCheck"></interceptor-ref>
            -->
            
            <!-- 第三種寫法:執(zhí)行用戶棧(與第二種寫法一樣, 只在當(dāng)前aciton中執(zhí)行自定義棧) -->
            <interceptor-ref name="myStack"></interceptor-ref>
            
            <!-- 1. 登陸失敗 -->
            <result name="input">/login.jsp</result>
            
            <!-- 2. 登陸成功 -->
            <result name="loginSuccess" type="redirectAction">user_list</result>
            
            <!-- 3. 列表展示 -->
            <result name="list">/WEB-INF/list.jsp</result>
        </action>
    </package>
</struts>

Structs國際化

  • Struts2中國際化:
    1. 寫資源文件 (同servlet)
    2. 讀資源文件
    • 程序:ResourceBundle (同servlet)
    • JSP:
      1)jstl標(biāo)簽(同servlet)
      2)struts標(biāo)簽獲取資源文件內(nèi)容
  • 具體步驟 :
    1. 寫資源文件 :
    • Msg.properties : 默認(rèn)的語言環(huán)境, 找不到配置就找它
    • Msg_en_US.properties : 美國
    1. 加載 : <constant name="struts.custom.i18n.resources" value="cn.itcast.config.msg"></constant>
    2. 使用 : 標(biāo)簽name值直接寫配置文件中的key : <s:text name="title"></s:text>
    • 另外一點(diǎn)扁眯,(推薦)加載資源文件通過常量加載還可以在頁面加載, 這樣用:
<s:i18n name="cn.itcast.config.msg">
    <s:text>  標(biāo)簽必須放到標(biāo)簽體中 </s:text>
</s:i18n>

Ognl表達(dá)式語言

  • 概述 : OGNL是Object Graphic Navigation Language(對象圖導(dǎo)航語言)的縮寫, 它是一個開源項(xiàng)目, Struts2框架使用OGNL作為默認(rèn)的表達(dá)式語言

    • OGNL優(yōu)勢
      1壮莹、支持對象方法調(diào)用,如xxx.doSomeSpecial()姻檀;
      2命满、支持類靜態(tài)的方法調(diào)用和值訪問,表達(dá)式的格式:
      @[類全名(包括包路徑)]@[方法名 | 值名]绣版,例如:
      @java.lang.String@format('foo %s', 'bar')
      或@tutorial.MyConstant@APP_NAME胶台;
      3、支持賦值操作和表達(dá)式串聯(lián)杂抽,如price=100, discount=0.8, calculatePrice()诈唬,這個表達(dá)式會返回80;
      4缩麸、訪問OGNL上下文(OGNL context)和ActionContext
      5铸磅、操作集合對象
    • 總結(jié) : OGNL 有一個上下文(Context)概念,說白了上下文就是一個MAP結(jié)構(gòu), 它實(shí)現(xiàn)了 java.utils.Map 的接口杭朱。 OgnlContext對象
    • 分析:Struts框架默認(rèn)就支持Ognl表達(dá)式語言(struts必須引用的包:ognl.jar)
    • 作用 : 頁面取值用
      1> El表達(dá)式語言 : jsp頁面取值的標(biāo)準(zhǔn)阅仔。(默認(rèn)直接可以使用) (應(yīng)用范圍更廣)
      2> Ognl表達(dá)式語言 : struts標(biāo)簽?zāi)J(rèn)支持的表達(dá)式語言。必須配置struts標(biāo)簽用, 不能離開struts標(biāo)簽直接用
  • OgnlContext對象 : OgnlContext對象是ognl表達(dá)式語言的核心弧械。

    • 源碼類:public class OgnlContext extends Object implements Map{..}硬編碼方式八酒,了解OgnlContext對象:

// OgnlContext用法
public class OgnlDemo1 {

    /**
     * 1. Ognl表達(dá)式語言取值,取非根元素的值刃唐,必須用#號
     * @throws Exception
     */
    @Test
    public void testOgnl() throws Exception {
        // 創(chuàng)建一個Ognl上下文對象
        OgnlContext context = new OgnlContext();
        // 放入數(shù)據(jù)
        User user = new User();
        user.setId(100);
        user.setName("Jack");
        // 【往非根元素放入數(shù)據(jù)羞迷, 取值的時候表達(dá)式要用"#"】
        context.put("user", user);
        
        // 獲取數(shù)據(jù)(map)
        // 先構(gòu)建一個Ognl表達(dá)式, 再解析表達(dá)式
        Object ognl = Ognl.parseExpression("#user.name");
        Object value = Ognl.getValue(ognl, context, context.getRoot());
        
        System.out.println(value);
    }
    
    /**
     * 2. Ognl表達(dá)式語言語言取值界轩,取根元素的值,不用帶#號
     * @throws Exception
     */
    @Test
    public void testOgn2() throws Exception {
        // 創(chuàng)建一個Ognl上下文對象
        OgnlContext context = new OgnlContext();
        // 放入數(shù)據(jù)
        User user = new User();
        user.setId(100);
        user.setName("Jack");
        // 【往根元素放入數(shù)據(jù)】
        context.setRoot(user);
        
        // 獲取數(shù)據(jù)(map)
        // 先構(gòu)建一個Ognl表達(dá)式, 再解析表達(dá)式
        Object ognl = Ognl.parseExpression("address.province");
        Object value = Ognl.getValue(ognl, context, context.getRoot());
        
        System.out.println(value);
    }
    
    /**
     * 3.Ognl對 靜態(tài)方法調(diào)用的支持
     * @throws Exception
     */
    @Test
    public void testOgn3() throws Exception {
        // 創(chuàng)建一個Ognl上下文對象
        OgnlContext context = new OgnlContext();
        
        // Ognl表單式語言闭树,調(diào)用類的靜態(tài)方法
        //Object ognl = Ognl.parseExpression("@Math@floor(10.9)");
        // 由于Math類在開發(fā)中比較常用耸棒,所以也可以這樣寫
        Object ognl = Ognl.parseExpression("@@floor(10.9)");
        Object value = Ognl.getValue(ognl, context, context.getRoot());
        System.out.println(value);
    }
}
  • ValueStack(即值棧對象) :
    • 值棧對象:是整個struts數(shù)據(jù)存儲的核心,或者叫中轉(zhuǎn)站报辱。用戶每次訪問struts的action,都會創(chuàng)建一個Action對象单山、值棧對象碍现、ActionContext對象; 然后把Action對象放入值棧中米奸; 最后再把值棧對象放入request中昼接,傳入jsp頁面(key: struts.valueStack); 開發(fā)者只需要通過ActionContext對象就可以訪問struts的其他的關(guān)鍵對象(ActionContext是給開發(fā)者用的,便于學(xué)習(xí)與使用)
    • 問題 : OgnlContext與ValueStack對象的關(guān)系悴晰?
  • Struts標(biāo)簽 : Struts標(biāo)簽取值慢睡,就使用了Ognl表達(dá)式語言
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市铡溪,隨后出現(xiàn)的幾起案子漂辐,更是在濱河造成了極大的恐慌,老刑警劉巖棕硫,帶你破解...
    沈念sama閱讀 216,470評論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件髓涯,死亡現(xiàn)場離奇詭異,居然都是意外死亡哈扮,警方通過查閱死者的電腦和手機(jī)纬纪,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,393評論 3 392
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來滑肉,“玉大人包各,你說我怎么就攤上這事“忻恚” “怎么了问畅?”我有些...
    開封第一講書人閱讀 162,577評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長惶洲。 經(jīng)常有香客問我按声,道長,這世上最難降的妖魔是什么恬吕? 我笑而不...
    開封第一講書人閱讀 58,176評論 1 292
  • 正文 為了忘掉前任签则,我火速辦了婚禮,結(jié)果婚禮上铐料,老公的妹妹穿的比我還像新娘渐裂。我一直安慰自己豺旬,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,189評論 6 388
  • 文/花漫 我一把揭開白布柒凉。 她就那樣靜靜地躺著族阅,像睡著了一般。 火紅的嫁衣襯著肌膚如雪膝捞。 梳的紋絲不亂的頭發(fā)上坦刀,一...
    開封第一講書人閱讀 51,155評論 1 299
  • 那天,我揣著相機(jī)與錄音蔬咬,去河邊找鬼鲤遥。 笑死,一個胖子當(dāng)著我的面吹牛林艘,可吹牛的內(nèi)容都是我干的盖奈。 我是一名探鬼主播,決...
    沈念sama閱讀 40,041評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼狐援,長吁一口氣:“原來是場噩夢啊……” “哼钢坦!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起啥酱,我...
    開封第一講書人閱讀 38,903評論 0 274
  • 序言:老撾萬榮一對情侶失蹤爹凹,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后懈涛,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體逛万,經(jīng)...
    沈念sama閱讀 45,319評論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,539評論 2 332
  • 正文 我和宋清朗相戀三年批钠,在試婚紗的時候發(fā)現(xiàn)自己被綠了宇植。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,703評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡埋心,死狀恐怖指郁,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情拷呆,我是刑警寧澤闲坎,帶...
    沈念sama閱讀 35,417評論 5 343
  • 正文 年R本政府宣布,位于F島的核電站茬斧,受9級特大地震影響腰懂,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜项秉,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,013評論 3 325
  • 文/蒙蒙 一绣溜、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧娄蔼,春花似錦怖喻、人聲如沸底哗。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,664評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽跋选。三九已至,卻和暖如春哗蜈,著一層夾襖步出監(jiān)牢的瞬間前标,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,818評論 1 269
  • 我被黑心中介騙來泰國打工恬叹, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留候生,地道東北人。 一個月前我還...
    沈念sama閱讀 47,711評論 2 368
  • 正文 我出身青樓绽昼,卻偏偏與公主長得像,于是被迫代替她去往敵國和親须蜗。 傳聞我的和親對象是個殘疾皇子硅确,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,601評論 2 353

推薦閱讀更多精彩內(nèi)容