Petstore源碼追蹤記(3)-商業邏輯處理(四)

來源:互聯網
上載者:User
Petstore 源碼記縱記 (3) -商業邏輯處理 ( 下 )
                                          ( 歐宣修 )
圖文並茂版請參考
http://www.javatwo.net/JavaPaper/Petstore-3_business_logic.pdf

接續上期 ...

我們已瞭解 SignOnFilter 在 Web tier 處理登入工作的步驟,它需要透過 EJB tier 從資料庫讀取資料進行比對,所以接下來探討在 EJB tier 的運作情形,從圖 14 、 15 可找出實際對應的 EJB ,從圖上面可知此 EJB 的屬性是 Local Stateless
Session Bean ,這很少見,大部份的書介紹到 Local Bean 的用法都用在 Entity Bean ,由此可知 Local Bean 的用法亦可用在 Session Bean 。
     SignOnEJB ,源碼在 Petstore_home/src/components/signon/src/com/sun/j2ee/blueprints/signon/ejb/SignOnEJB.java ,請讀者順便加上偵察程式碼:
    
public class SignOnEJB implements SessionBean {

    private static final String USER_HOME_ENV_NAME =
"java:comp/env/ejb/local/User";
    private InitialContext ic = null;
    private UserLocalHome ulh = null;

    public void ejbCreate() throws CreateException {
      try {
        ic = new InitialContext();
        // 取得 UserLocalHome Reference ,它是代表使用者基本資料的 Local Entity Bean
        ulh = (UserLocalHome) ic.lookup(USER_HOME_ENV_NAME);
      } catch (NamingException ne) {
         throw new EJBException("SignOnEJB Got naming exception! " +
ne.getMessage());
      }
    }

    /**
     * 此函數由 SignOnFilter 呼叫,依使用者帳號找出對應的 User 實體
    *(instance) ,然後呼叫 User 實體的密碼比對函數- user.matchPassword()
     * business method used to check if a user is allowed to sign on
     */
    public boolean authenticate(String userName, String password) {
     // 請加入偵察程式碼,方便稍候程式驗證
System.out.println("SignOnEJB 執行 authenticate() 進行使用者驗證
userName="+userName+", password="+password);
        try {
            UserLocal user = ulh.findByPrimaryKey(userName);
            return user.matchPassword(password);
        } catch (FinderException fe) {
            return false; // User not found, so authentication failed.
        }
    }
     以下略 ...
    

圖 16 SignOnEJB 的 EJB Reference
    
UserEJB ,源碼在
Petstore_home/src/components/signon/src/com/sun/j2ee/blueprints/signon/user/ejb/
UserEJB.java ,它是 Local Entity Bean ,對應資料庫中實際資料表-
UserEJBTable 在約 88 列可看到 SignOnEJB 所呼叫的函數,請讀者順便加
上偵察程式碼:
    
   
public boolean matchPassword(String password) {
   // 請加入偵察程式碼,方便稍候程式驗證
   System.out.println("UserEJB 執行 matchPassword() 進行密碼比對 ");
    return password.equals(getPassword());
}
    

圖 17 UserEJB 為 Entity Bean

點選圖 17 右下角 ”Deployment Settings” 鈕,可見到圖 18 畫面,
選擇左下角 ”Method Implementation Queries” 之 ”Container Methods”
之 ”createRow” ,即可看到圖 18 之 SQL Query :

圖 18 UserEJB 對應資料表為 UserEJBTable

由上述所列程式碼及圖,讀者應該可以瞭解使用者登入在 EJBz tier 的運作情形,在 UserEJB 也看到一個不一樣的用法,就是在 Entity Bean 上使用商業邏輯- matchPassword() 函數,在大部份的 EJB 書籍或檔案都告訴我們商業邏輯應該用 Session Bean 去實作,資料則用 Entity Bean 來實作,但在這裡密碼比較的商業邏輯是非常簡單的,只用了一行程式就解決了,所以也不需為了它另外再做一個 Session Bean ,
也許讀者會問為什麼不將此函數寫在 SignOnEJB 。筆者認為密碼比對不只在登入流程上會使用,在使用者基本資料編輯時也可能會用到,所以還是放在 UserEJB 比較適合: )     我們能夠知道使用者基本資料是存於 UserEJBTable ,我們要如何知道此資料表所存內容是什麼。請參閱注 4 。

現在請重複第一階段驗證步驟將程式重新編輯及部署,可發現程式如我們所預期般執行。

圖 19 第二階段程式驗證結果

第三階段
大家還記得在 SignOnFilter 之 validateSignOn() 函數,驗證成功會將
SIGNED_ON_USER 變數 ( 對應實際變數為 j_signon) 的值設為真值 (true) :

hreq.getSession().setAttribute(SIGNED_ON_USER, new Boolean(true));

當我們再次從首頁進入使用者基本資料瀏覽頁,會再度給 SignOnFilter 攔截,從 Session 取出 SIGNED_ON_USER 變數 ( 對應實際變數為 j_signon) ,經判斷為真值 (true) , SignOnFilter 則會允許存取轉導至使用者基本資料瀏覽畫面 (customer.do) ,讀者可參考下列程式碼加入偵察碼,在約 125 列 doFilter() 函數:


    boolean signedOn = false;
    if (hreq.getSession().getAttribute(SIGNED_ON_USER) != null) {
       signedOn
=((Boolean)hreq.getSession().getAttribute(SIGNED_ON_USER)).booleanValue();
        // 加入偵察碼
System.out.println("signedOn="+signedOn);
    } else {
       hreq.getSession().setAttribute(SIGNED_ON_USER, new Boolean(false));
    }
       // jump to the resource if signed on
       // 若已登入過,則結束此 Filter 工作,進入 Filter chain ,以本例來說,它為
Filter chain 中最後一個 Filter ,所以就是不做任何事,讓使用者進入他的目的畫面
       if (signedOn) {
           // 加入偵察碼
           System.out.println(" 使用者已登入過。 ");
           chain.doFilter(request,response);
           return;
       }

參考前面敘述重新編譯部署後執行,可得下圖預期結果:


圖 20 第三階段程式驗證結果


customer.do

  到這裡相信讀者能對 Petstore 登入流程式控制管有更深入的瞭解,通過登入流程就到達了使用者基本資料瀏覽畫面 (customer.do) , *.do 與前二篇介紹的 *.screen 不同, *.screen 代表的是一個畫面,如 main.screen 代表首頁,它可由多個 .jsp 所組成; *.do 代表的是一個動作, customer.do 代表對使用者基本資料相關動作,如新增、修改、刪除,它會透過 EJB tier 與資料庫互動,最後得到的結果也是要展現,運用 *.screen 的機制組成結果畫面,所以我們可以這樣想象 *.screen 是名詞, *.do 是動詞,以本例來說,只是讀取資料,雖然運用到 *.do ,但並沒有任何動作,為了能讓讀者瞭解整個架構,還是在此稍事說明。

請開 ?deploytool ,點選左邊窗格 Files > Applications > PetstoreEAR > PetstoreWAR > MainServlet ,選擇右邊 Alias 頁,可發現處理 *.do 即是 MainServlet

圖 21 *.do 對應 MainServlet

點選 General 頁可找到實際對應類別,源碼在
Petstore_home/src/waf/src/controller/com/sun/j2ee/blueprints/waf/controller/web/MainServlet.java
,在約 79 列可找到初始函數:

public void init(ServletConfig config) throws ServletException {
        // 讀取預設語系,值為 ”en_US”
        String defaultLocaleString = config.getInitParameter("default_locale");
        defaultLocale = I18nUtil.getLocaleFromString(defaultLocaleString);
        this.context = config.getServletContext();
        String requestMappingsURL = null;
        try {
            // 讀取 mapping.xml
            requestMappingsURL =
context.getResource("/WEB-INF/mappings.xml").toString();
        } catch (java.net.MalformedURLException ex) {
            System.err.println("MainServlet: initializing ScreenFlowManager
malformed URL exception: " + ex);
        }
       // 將 mappings.xml 轉成 HashMap 類別並存入 ServletContext
       urlMappings = URLMappingsXmlDAO.loadRequestMappings(requestMappingsURL);
       context.setAttribute(WebKeys.URL_MAPPINGS, urlMappings);
       eventMappings = URLMappingsXmlDAO.loadEventMappings(requestMappingsURL);
       context.setAttribute(WebKeys.EVENT_MAPPINGS, eventMappings);
       //ScreenFlowManager 初始化並存入 ServletContext
       getScreenFlowManager();
       //RequestProcessor 初始化並存入 ServletContext
       getRequestProcessor();
}

圖 22 MainServlet 實際對應類別

MainServlet 在初始化時會讀取預設語系及對應設定檔
相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.