Petstore原始碼追蹤記(3)-商業邏輯處理(二) (轉)
Petstore原始碼追蹤記(3)-商業邏輯處理(二) (轉)[@more@]使用者基本資料瀏覽流程
=======================
現在讓我們進入主題-Petstore商業邏輯,筆者以使用者基本資料瀏覽流程為例,請啟用cloudscape:
cloudscape –start
圖1 啟用資料庫
接著啟用RI Application Server(應用):
–verbose
圖2 啟用RI
Petstore啟用無誤後,請開啟,輸入
">
圖3 進入Petstore系統
進入系統看到那大大的鸚鵡頭,請點選右上角的”Account”連結,
進入使用者登入流程:
圖4 Petstore首頁
我們會看到登入畫面,直接使用預設的使用者(j2ee)及密碼(j2ee),
點選”Sign In”鈕:
圖5 登入畫面
看到以下顯示個人資訊畫面就表示我們已登入成功啦!
圖6 個人資訊畫面
若此時我們按瀏覽器之”上一頁”鈕返回首頁:
圖7 再返回首頁
再按右上角”Account”連結,會發現畫面直接跳至個人資訊畫面:
圖8 個人資訊畫面
請注意圖4 Petstore首頁畫面左下角出現的
URL:http://localhost:8080/petstore/customer.do,它其實就是圖6個人資訊畫面,但系統並沒有直接從圖4跳至圖6,而先換成圖5登入畫面,要求我們做登入動作,輸入帳號及密碼,驗證成功後才跳至圖6;若是再次從首頁進入個人資訊,系統並不會再次要求登入,在這裡有兩個重點要提:
1.SignOnFilter:若使用者進入的頁面是受到保護的,則系統會先將畫面轉至登入畫面,要求登入。
2.customer.do:它代表的是一個動作加一個畫面的組合,以本例來說,從資料庫讀取個人資訊,組成完整HTML畫面顯示。
SignOnFilter
筆者將使用者進入使用者基本資料瀏覽畫面的流程分為三個階段:
1.使用者欲進入使用者基本資料瀏覽畫面(customer.do),因未登入過,被SignOnFilter攔截,轉至登入畫面(signon.screen)。
2.使用者輸入帳號及密碼按”sumit”後,再度由SignOnFilter攔截,SignOnFilter亦負責帳號、密碼檢核工作,確認無誤後,則將網頁轉導(forward)至第一階段使用者欲進入之使用者基本資料瀏覽畫面(customer.do)。
3.重複第一階段動作,SignOnFilter檢查使用者已登入過,放行轉導至使用者基本資料瀏覽畫面(customer.do)。
第一階段
欲觀察 Filter,先要了解它的影響範圍,請開啟deploytool(注2),滑鼠點選PetstoreWAR,選擇右邊Filter Map頁,會發現此Filter的影響範圍是所有網頁。
圖9 Filter影響範圍
也可在.看到設定,請參考前面敘述,接下來請開啟SignOnFilter.
,它的原始碼位置在
Petstore_homesrccomponentssignonsrccomsunj2eeblueprintssignonwebSignOnFilter.java
。
先看SignOnFilter初始動作,約在87列:
public void init(FilterConfig config) throws ServletException {
this.config = config;
URL protectedResURL = null;
try {
//謮取signon-config.xml
protectedResourcesURL =
config.getServletContext().getResource("/WEB-INF/signon-config.xml");
SignOnDAO dao = new SignOnDAO(protectedResourcesURL);
//讀取登入失敗畫面(signon_error.screen)
signOnErrorPage = dao.getSignOnErrorPage();
//讀取登入畫面(signon.screen)
signOnPage = dao.getSignOnPage();
//讀取所有欲保護畫面,組成HashMap
protectedResources = dao.getProtectedResources();
} catch (java.MalformedURLException ex) {
System.err.println("SignonFilter: malformed URL exception: " + ex);
}
}
它在初始化時會先讀取
Petstore_homesrcappspetstoresrcdocWEB-INFsignon-config.xml
,並組成Data Access (DAO),以方便後續存取(注3),此xml檔案主
要功用記錄登入畫面、登入失敗畫面及所有需登入才能使用的畫面之URL,以下是signon-config.xml片段:
<!-- FoSign On Page(登入畫面)-->
signon.screen
<!-- Error Page When Sign On fails(登入失敗畫面)-->
signon_error.screen
<!-- A Protected Resource-->
Customer Screen
customer.screen
<!-- A Protected Resource(本例之保護畫面)-->
Customer Action
customer.do
接著請看SignOnFilter實際運作的主要函式doFilter(),約在107列:
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
HttpServletRequest hreq = (HttpServletRequest)request;
String currentURI = hreq.getRequestURL().toString();
String currentURL = hreq.getRequestURI();
// get everything after the context root
int firstSlash = currentURL.indexOf("/",1); // jump past the starting slash
String targetURL = null;
//取得使用者欲前往之URL,以本例來說,即是customer.do
if (firstSlash != -1) targetURL = currentURL.substring(firstSlash + 1,
currentURL.length());
//判斷使用者從登入畫面(signon.screen)進行驗證工作
if ((targetURL != null) && targetURL.equals(FORM_SIGNON_URL)) {
validateSignOn(request, response, chain);
// jump out of this method
return;
}
// check if the user is signed on
//檢查使用者是否登入過,從Session取出登入標記,作為判斷之用
boolean signedOn = false;
if (hreq.getSession().getAttribute(SIGNED_ON_USER) != null) {
signedOn
=((Boolean)hreq.getSession().getAttribute(SIGNED_ON_USER)).booleanValue();
} 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) {
chain.doFilter(request,response);
return;
}
// find out if the patterns match the target URL
//將使用者欲前往之URL與所有保護畫面URL做比對,若符合則匯入登入畫面
(signon.screen)
Iterator it = protectedResources.keySet().iterator();
while (it.hasNext()) {
String protectedName = (String)it.next();
ProtectedResource resource =
(ProtectedResource)protectedResources.get(protectedName);
String urlPattern = resource.getURLPattern();
// now check agains the targetURL
//若符合則將目的URL存入Session,並轉導至登入畫面,結束Filter工作
if (urlPattern.equals(targetURL)) {
// put the orginal url in the session so others can access
hreq.getSession().setAttribute(ORIGINAL_URL, targetURL);
config.getServletContext().getRequestDispatcher("/" +
signOnPage).forward(request, response);
// Jump out of the filter and go to the next page
return;
}
}
// No matches if we made it to here
chain.doFilter(request,response);
}
SignOnFilter先取得使用者的目的URL(customer.do),判斷使用者並未登入,開始比對目的URL是否在保護畫面中,發現customer.do為保護畫面,將customer.do此目的URL存入Session,將request轉導至登入畫面(signon.screen),要求使用者進行登入動作。
第一階段驗證
口說無憑,我們可加入偵察程式程式碼來驗證程式是否如筆者所述般執行,
請在SignOnFilter.init()加入兩行程式:
public void init(FilterConfig config) throws ServletException {
this.config = config;
URL protectedResourcesURL = null;
try {
//謮取signon-config.xml
protectedResourcesURL =
config.getServletContext().getResource("/WEB-INF/signon-config.xml");
SignOnDAO dao = new SignOnDAO(protectedResourcesURL);
//讀取登入失敗畫面(signon_error.screen)
signOnErrorPage = dao.getSignOnErrorPage();
//讀取登入畫面(signon.screen)
signOnPage = dao.getSignOnPage();
//請加入偵察程式程式碼
System.out.println("signOnPage="+signOnPage);
System.out.println("signErrorPage="+signOnErrorPage);
//讀取所有欲保護畫面,組成HashMap
protectedResources = dao.getProtectedResources();
} catch (java.net.MalformedURLException ex) {
System.err.println("SignonFilter: malformed URL exception: " + ex);
}
}
doFilter()亦加入偵察程式程式碼:
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
HttpServletRequest hreq = (HttpServletRequest)request;
String currentURI = hreq.getRequestURL().toString();
String currentURL = hreq.getRequestURI();
// get everything after the context root
int firstSlash = currentURL.indexOf("/",1); // jump past the starting slash
String targetURL = null;
//取得使用者欲前往之URL,以本例來說,即是customer.do
if (firstSlash != -1) targetURL = currentURL.substring(firstSlash + 1,
currentURL.length());
//請加入偵察程式程式碼
System.out.println("targetURL="+targetURL);
//判斷使用者從登入畫面(signon.screen)進行驗證工作
if ((targetURL != null) && targetURL.equals(FORM_SIGNON_URL)) {
validateSignOn(request, response, chain);
// jump out of this method
return;
}
// check if the user is signed on
//檢查使用者是否登入過,從Session取出登入標記,作為判斷之用
boolean signedOn = false;
if (hreq.getSession().getAttribute(SIGNED_ON_USER) != null) {
signedOn
=((Boolean)hreq.getSession().getAttribute(SIGNED_ON_USER)).booleanValue();
} 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) {
chain.doFilter(request,response);
return;
}
// find out if the patterns match the target URL
//將使用者欲前往之URL與所有保護畫面URL做比對,若符合則匯入登入畫面
(signon.screen)
Iterator it = protectedResources.keySet().iterator();
while (it.hasNext()) {
String protectedName = (String)it.next();
ProtectedResource resource =
(ProtectedResource)protectedResources.get(protectedName);
String urlPattern = resource.getURLPattern();
// now check agains the targetURL
//若符合則將目的URL存入Session,並轉導至登入畫面,結束Filter工作
if (urlPattern.equals(targetURL)) {
//請加入偵察程式程式碼
System.out.println("URL Matched! urlPattern="+urlPattern);
// put the orginal url in the session so others can access
hreq.getSession().setAttribute(ORIGINAL_URL, targetURL);
config.getServletContext().getRequestDispatcher("/" +
signOnPage).forward(request, response);
// Jump out of the filter and go to the next page
return;
}
}
// No matches if we made it to here
chain.doFilter(request,response);
}
接著請重新編譯及部署新的程式程式碼,在命令下:切換至Petstore_home srcsappspetstoresrc目錄如:cd D:petstore1.3.1srcwebservicesappspetstoresrc
重新編譯程式
如:build all
=======================
現在讓我們進入主題-Petstore商業邏輯,筆者以使用者基本資料瀏覽流程為例,請啟用cloudscape:
cloudscape –start
圖1 啟用資料庫
接著啟用RI Application Server(應用):
–verbose
圖2 啟用RI
Petstore啟用無誤後,請開啟,輸入
">
圖3 進入Petstore系統
進入系統看到那大大的鸚鵡頭,請點選右上角的”Account”連結,
進入使用者登入流程:
圖4 Petstore首頁
我們會看到登入畫面,直接使用預設的使用者(j2ee)及密碼(j2ee),
點選”Sign In”鈕:
圖5 登入畫面
看到以下顯示個人資訊畫面就表示我們已登入成功啦!
圖6 個人資訊畫面
若此時我們按瀏覽器之”上一頁”鈕返回首頁:
圖7 再返回首頁
再按右上角”Account”連結,會發現畫面直接跳至個人資訊畫面:
圖8 個人資訊畫面
請注意圖4 Petstore首頁畫面左下角出現的
URL:http://localhost:8080/petstore/customer.do,它其實就是圖6個人資訊畫面,但系統並沒有直接從圖4跳至圖6,而先換成圖5登入畫面,要求我們做登入動作,輸入帳號及密碼,驗證成功後才跳至圖6;若是再次從首頁進入個人資訊,系統並不會再次要求登入,在這裡有兩個重點要提:
1.SignOnFilter:若使用者進入的頁面是受到保護的,則系統會先將畫面轉至登入畫面,要求登入。
2.customer.do:它代表的是一個動作加一個畫面的組合,以本例來說,從資料庫讀取個人資訊,組成完整HTML畫面顯示。
SignOnFilter
筆者將使用者進入使用者基本資料瀏覽畫面的流程分為三個階段:
1.使用者欲進入使用者基本資料瀏覽畫面(customer.do),因未登入過,被SignOnFilter攔截,轉至登入畫面(signon.screen)。
2.使用者輸入帳號及密碼按”sumit”後,再度由SignOnFilter攔截,SignOnFilter亦負責帳號、密碼檢核工作,確認無誤後,則將網頁轉導(forward)至第一階段使用者欲進入之使用者基本資料瀏覽畫面(customer.do)。
3.重複第一階段動作,SignOnFilter檢查使用者已登入過,放行轉導至使用者基本資料瀏覽畫面(customer.do)。
第一階段
欲觀察 Filter,先要了解它的影響範圍,請開啟deploytool(注2),滑鼠點選PetstoreWAR,選擇右邊Filter Map頁,會發現此Filter的影響範圍是所有網頁。
圖9 Filter影響範圍
也可在.看到設定,請參考前面敘述,接下來請開啟SignOnFilter.
,它的原始碼位置在
Petstore_homesrccomponentssignonsrccomsunj2eeblueprintssignonwebSignOnFilter.java
。
先看SignOnFilter初始動作,約在87列:
public void init(FilterConfig config) throws ServletException {
this.config = config;
URL protectedResURL = null;
try {
//謮取signon-config.xml
protectedResourcesURL =
config.getServletContext().getResource("/WEB-INF/signon-config.xml");
SignOnDAO dao = new SignOnDAO(protectedResourcesURL);
//讀取登入失敗畫面(signon_error.screen)
signOnErrorPage = dao.getSignOnErrorPage();
//讀取登入畫面(signon.screen)
signOnPage = dao.getSignOnPage();
//讀取所有欲保護畫面,組成HashMap
protectedResources = dao.getProtectedResources();
} catch (java.MalformedURLException ex) {
System.err.println("SignonFilter: malformed URL exception: " + ex);
}
}
它在初始化時會先讀取
Petstore_homesrcappspetstoresrcdocWEB-INFsignon-config.xml
,並組成Data Access (DAO),以方便後續存取(注3),此xml檔案主
要功用記錄登入畫面、登入失敗畫面及所有需登入才能使用的畫面之URL,以下是signon-config.xml片段:
<!-- FoSign On Page(登入畫面)-->
signon.screen
<!-- Error Page When Sign On fails(登入失敗畫面)-->
signon_error.screen
<!-- A Protected Resource-->
<!-- A Protected Resource(本例之保護畫面)-->
接著請看SignOnFilter實際運作的主要函式doFilter(),約在107列:
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
HttpServletRequest hreq = (HttpServletRequest)request;
String currentURI = hreq.getRequestURL().toString();
String currentURL = hreq.getRequestURI();
// get everything after the context root
int firstSlash = currentURL.indexOf("/",1); // jump past the starting slash
String targetURL = null;
//取得使用者欲前往之URL,以本例來說,即是customer.do
if (firstSlash != -1) targetURL = currentURL.substring(firstSlash + 1,
currentURL.length());
//判斷使用者從登入畫面(signon.screen)進行驗證工作
if ((targetURL != null) && targetURL.equals(FORM_SIGNON_URL)) {
validateSignOn(request, response, chain);
// jump out of this method
return;
}
// check if the user is signed on
//檢查使用者是否登入過,從Session取出登入標記,作為判斷之用
boolean signedOn = false;
if (hreq.getSession().getAttribute(SIGNED_ON_USER) != null) {
signedOn
=((Boolean)hreq.getSession().getAttribute(SIGNED_ON_USER)).booleanValue();
} 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) {
chain.doFilter(request,response);
return;
}
// find out if the patterns match the target URL
//將使用者欲前往之URL與所有保護畫面URL做比對,若符合則匯入登入畫面
(signon.screen)
Iterator it = protectedResources.keySet().iterator();
while (it.hasNext()) {
String protectedName = (String)it.next();
ProtectedResource resource =
(ProtectedResource)protectedResources.get(protectedName);
String urlPattern = resource.getURLPattern();
// now check agains the targetURL
//若符合則將目的URL存入Session,並轉導至登入畫面,結束Filter工作
if (urlPattern.equals(targetURL)) {
// put the orginal url in the session so others can access
hreq.getSession().setAttribute(ORIGINAL_URL, targetURL);
config.getServletContext().getRequestDispatcher("/" +
signOnPage).forward(request, response);
// Jump out of the filter and go to the next page
return;
}
}
// No matches if we made it to here
chain.doFilter(request,response);
}
SignOnFilter先取得使用者的目的URL(customer.do),判斷使用者並未登入,開始比對目的URL是否在保護畫面中,發現customer.do為保護畫面,將customer.do此目的URL存入Session,將request轉導至登入畫面(signon.screen),要求使用者進行登入動作。
第一階段驗證
口說無憑,我們可加入偵察程式程式碼來驗證程式是否如筆者所述般執行,
請在SignOnFilter.init()加入兩行程式:
public void init(FilterConfig config) throws ServletException {
this.config = config;
URL protectedResourcesURL = null;
try {
//謮取signon-config.xml
protectedResourcesURL =
config.getServletContext().getResource("/WEB-INF/signon-config.xml");
SignOnDAO dao = new SignOnDAO(protectedResourcesURL);
//讀取登入失敗畫面(signon_error.screen)
signOnErrorPage = dao.getSignOnErrorPage();
//讀取登入畫面(signon.screen)
signOnPage = dao.getSignOnPage();
//請加入偵察程式程式碼
System.out.println("signOnPage="+signOnPage);
System.out.println("signErrorPage="+signOnErrorPage);
//讀取所有欲保護畫面,組成HashMap
protectedResources = dao.getProtectedResources();
} catch (java.net.MalformedURLException ex) {
System.err.println("SignonFilter: malformed URL exception: " + ex);
}
}
doFilter()亦加入偵察程式程式碼:
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
HttpServletRequest hreq = (HttpServletRequest)request;
String currentURI = hreq.getRequestURL().toString();
String currentURL = hreq.getRequestURI();
// get everything after the context root
int firstSlash = currentURL.indexOf("/",1); // jump past the starting slash
String targetURL = null;
//取得使用者欲前往之URL,以本例來說,即是customer.do
if (firstSlash != -1) targetURL = currentURL.substring(firstSlash + 1,
currentURL.length());
//請加入偵察程式程式碼
System.out.println("targetURL="+targetURL);
//判斷使用者從登入畫面(signon.screen)進行驗證工作
if ((targetURL != null) && targetURL.equals(FORM_SIGNON_URL)) {
validateSignOn(request, response, chain);
// jump out of this method
return;
}
// check if the user is signed on
//檢查使用者是否登入過,從Session取出登入標記,作為判斷之用
boolean signedOn = false;
if (hreq.getSession().getAttribute(SIGNED_ON_USER) != null) {
signedOn
=((Boolean)hreq.getSession().getAttribute(SIGNED_ON_USER)).booleanValue();
} 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) {
chain.doFilter(request,response);
return;
}
// find out if the patterns match the target URL
//將使用者欲前往之URL與所有保護畫面URL做比對,若符合則匯入登入畫面
(signon.screen)
Iterator it = protectedResources.keySet().iterator();
while (it.hasNext()) {
String protectedName = (String)it.next();
ProtectedResource resource =
(ProtectedResource)protectedResources.get(protectedName);
String urlPattern = resource.getURLPattern();
// now check agains the targetURL
//若符合則將目的URL存入Session,並轉導至登入畫面,結束Filter工作
if (urlPattern.equals(targetURL)) {
//請加入偵察程式程式碼
System.out.println("URL Matched! urlPattern="+urlPattern);
// put the orginal url in the session so others can access
hreq.getSession().setAttribute(ORIGINAL_URL, targetURL);
config.getServletContext().getRequestDispatcher("/" +
signOnPage).forward(request, response);
// Jump out of the filter and go to the next page
return;
}
}
// No matches if we made it to here
chain.doFilter(request,response);
}
接著請重新編譯及部署新的程式程式碼,在命令下:切換至Petstore_home srcsappspetstoresrc目錄如:cd D:petstore1.3.1srcwebservicesappspetstoresrc
重新編譯程式
如:build all
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/10752043/viewspace-993965/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- Petstore原始碼追蹤記(3)-商業邏輯處理(一) (轉)原始碼
- 傳奇原始碼分析-客戶端(遊戲邏輯處理源分析二)原始碼客戶端遊戲
- vscode原始碼分析【三】程式的啟動邏輯,效能問題的追蹤VSCode原始碼
- external-attacher原始碼分析(2)-核心處理邏輯分析原始碼
- kube-scheduler原始碼分析(2)-核心處理邏輯分析原始碼
- 追蹤解析 Disruptor 原始碼原始碼
- Nginx(二): worker 程式處理邏輯-流程框架Nginx框架
- 【筆記】jQuery原始碼(文件處理3)筆記jQuery原始碼
- 追蹤解析 ThreadPoolExecutor 原始碼thread原始碼
- 追蹤原始碼的方式歸納原始碼
- druid查詢原始碼追蹤UI原始碼
- 追蹤解析 Netty IntObjectHashMap 原始碼NettyObjectHashMap原始碼
- MySQL邏輯查詢處理MySql
- Windows邏輯備份-EXPDP(保留5天內邏輯備份)批處理指令碼Windows指令碼
- 程式碼追蹤
- JavaScript 錯誤處理和堆疊追蹤淺析JavaScript
- vscode原始碼分析【二】程式的啟動邏輯VSCode原始碼
- SAP gateway處理multiple key的邏輯Gateway
- 淺談zip格式處理邏輯漏洞
- 查詢處理的邏輯順序
- 追蹤解析Spring ioc啟動原始碼(2)Spring原始碼
- 前端業務程式碼配置化處理條件判斷邏輯前端
- 程式碼重構之 —— 一堆if、esle 邏輯的處理
- Golang原始碼學習:排程邏輯(二)main goroutine的建立Golang原始碼AI
- Spring MVC的請求處理邏輯SpringMVC
- WM-QM未清TR處理邏輯
- Android 介面顯示與邏輯處理Android
- 如何追蹤laravel動態<二>Laravel
- Spring Cloud Stream消費失敗後的處理策略(二):自定義錯誤處理邏輯SpringCloud
- 創業黑箱:理解產品和商業的邏輯創業
- SQL追蹤和事件追蹤SQL事件
- Vue2原始碼分析-邏輯梳理Vue原始碼
- 讓玩家“白嫖遊戲”下的商業邏輯遊戲
- [原始碼解析] TensorFlow 分散式環境(3)--- Worker 靜態邏輯原始碼分散式
- 【DTM】HUAWEI Ads與DTM網頁轉化追蹤(二)網頁
- 物理DG與邏輯DG的區別與邏輯DG同步異常處理方法
- 機器學習筆記(3):多類邏輯迴歸機器學習筆記邏輯迴歸
- 11g 邏輯備庫簡單故障處理