Petstore原始碼追蹤記(3)-商業邏輯處理(一) (轉)
作者:歐宣修
並茂版請參考
two/JavaPaper/Petstore-3_business_logic.pdf">
前言
透過前面的介紹,我們能夠了解Petstore中Model、Controller、View是如何相互合作,現在讓筆者來說明Petstore商業邏輯(Business Logic)的處理方式,首先讓我們先了解為什麼要將商業邏輯與資料展現(Presentation)分開,如此做有下列的好處:
1.減少變動的衝擊:商業邏輯及資料展現彼此獨立,不因商業邏輯改變而影響資料展現的程式程式碼,反之亦然。
2.易於維護:將商業邏輯集中管理,一旦日後有修改,僅須修改一個地方。
3.重複使用:商業邏輯若與資料展現層程式混在一起,如此商業邏輯只能服務一種使用者介面(Client),若將兩者分離,我們可以很容易擴充第二種使用者介面。
4.各司其職:資料展現的設計人員與商業邏輯的設計人員通常是不一樣的,彼此獨立讓術業有專攻,品質及皆能提升。
隱形角色
在追縱Petstore商業邏輯處理方式前,我們先來看看Petstore中的隱形角色,這些隱形角色在(RI)啟用時即默默準備好,待適當時機為Petstore中商業邏輯處理服務,所以筆者須先介紹它們。
請開啟
Petstore_home(注一)srcappspetstoresrcdoc-INFweb.,
我們可以看到:
<!-- Encoding Filter Declaration Start -->
<!-- Encoding Filter Declaration End -->
<!-- Signon Filter Declaration Start -->
<!-- Signon Filter Declaration End -->
<!-- Encoding Filter Map Start-->
<!-- Encoding Filter Mapping End -->
<!-- Signon Filter Mapping Start-->
<!-- Signon Filter Mapping End -->
<!-- ComponentManager Listener -->
<!-- SignOn Attribute Listener -->
Filter與Listener是2.3增加的功能,Filter可以在接受使用者的Request之後,做一些檢查處理,若沒問題則把使用者要求的Response丟回給使用者,反之則丟回預設的處理畫面,最常使用的情況就是登入,在網頁應用系統中有些功能是必須登入才能使用,過去的做法我們會將登入檢查寫在這些個別功能上,如此會造成登入檢查若要修正,則必須逐支修改,造成時間浪費,運用Filter,我們可將登入檢查程式與其它程式獨立,日後容易維護。Listener則是增加對Context,Session生命週期的控制,例如我們能夠在Session初始化時,將所需使用的資料一起產生,並將Reference存入Session,Seesion關閉時可順便將相關資源移除,如此資源集中控管,容易維護。
Encoding Filter
它的程式程式碼位置在
Petstore_homesrccomponentsencodingfiltersrccomsunj2eeblueprintsencodingfilterwebEncodingFilter.java
,它會再讀取web.xml(位置在Petstore_homesrcappspetstoresrcdocrootWEB-INFweb.xml)中的引數,決定編碼方式再將其設入Request中:
web.xml
<!-- Encoding Filter Declaration Start -->
EncodingFilter.java
public class EncodingFilter implements Filter {
private FilterConfig config = null;
// default to ASCII
private String targetEncoding = "ASCII";
//初始化時讀取引數
public void init(FilterConfig config) throws ServletException {
this.config = config;
this.targetEncoding = config.getInitParameter("encoding");
}
public void destroy() {
config = null;
targetEncoding = null;
}
//將編碼方式引數存入reqeust,結束此Filter
public void doFilter(ServletRequest srequest, ServletResponse sresponse,
FilterChain chain)
throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest)srequest;
request.setCharacterEncoding(targetEncoding);
// move on to the next
chain.doFilter(srequest,sresponse);
}
}
筆者覺得這個Filter滿有用的,可以單獨運用在傳統+JavaBeans的Web Application,在3.2.x,預設編碼是UTF-8,所以我們處理中文時,必須自行在程式中處理,在存入前須將中文字編碼由Unicode轉成Big5;到了Tomcat3.3.x,Tomcat會從OS取得預設編碼方式,所以我們不必再自行處理;到了Tomcat4.0.x之後,情況又回到與Tomcat3.2.x一樣,筆者開發Web Application就碰到這個情況,歷經三個版本的Tomcat,程式改過來改過去的,盡做些白工,後來筆者改運用這個Filter,就不需在存入資料庫前須將中文字編碼由Unicode轉成Big5。
ComponentManager Listener
第二個Filter主要掌管登入,與本次主題有密切關係,為使流程順暢,所以稍後再說明。我們來看第一個Listener,它的主要功能是作為服務連結提供者,當使用者進入本系統時,應用伺服器(Application Sever)會在Session產生時會建置儲存服務連結容器,並將其置入Session,待後續程式服務產生後使用。
DefaultComponentManager.java,原始碼在
Petstore_homesrcwafsrccontrollercomsunj2eeblueprintswafcontrollerweb
public void sessionCreated(HttpSessionEvent se) {
HttpSession session = se.getSession();
//產生服務連結容器
sl = ServiceLocator.getInstance();
//將本Listener存入Session
session.setAttribute(WebKeys.COMPONENT_MANAGER, this);
}
ServiceLacator.java,原始碼在
Petstore_homesrccomponentsservicelocatorsrccomsunj2eeblueprintsservicelocatorweb
,此類別寫法滿特別的,大家又可多學一種技巧,追縱前輩原始碼,除了能夠了解各種功能如何設計之外,程式程式碼分解(Refactor)、撰寫風格、設計技巧,對我們來說都是很重要的收穫!ServiceLacator基本上它是一個及資源連結服務提供者,且它的服務不因使用者不同而有所改變,所以它使用static寫法來達到這個效果。
public class ServiceLocator {
private InitialContext ic;
private Map cache; //used to hold references to EJBHomes/JMS Res for
//re-use
private static ServiceLocator me;
//初次宣告此時會初始化動作
static {
try {
me = new ServiceLocator();
} catch(ServiceLocatorException se) {
System.err.println(se);
se.printStackTrace(System.err);
}
}
//建構子,產生JNDI連結及同步化HashMap容器
private ServiceLocator() throws ServiceLocatorException {
try {
ic = new InitialContext();
cache = Collections.synchronizedMap(new HashMap());
} catch (NamingException ne) {
throw new ServiceLocatorException(ne);
} catch (Exception e) {
throw new ServiceLocatorException(e);
}
}
//將本物件參考傳出
static public ServiceLocator getInstance() {
return me;
}
以下略過…
}
上述ServiceLocator建構子中運用Collections的Static Method(靜態函式)synchronizedMap()來產生HashMap容器,依J2SDK 說法,透過此函式可產生出具同步化及執行緒的HashMap容器。
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/10752043/viewspace-993964/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- Petstore原始碼追蹤記(3)-商業邏輯處理(二) (轉)原始碼
- vscode原始碼分析【三】程式的啟動邏輯,效能問題的追蹤VSCode原始碼
- external-attacher原始碼分析(2)-核心處理邏輯分析原始碼
- kube-scheduler原始碼分析(2)-核心處理邏輯分析原始碼
- 追蹤解析 Disruptor 原始碼原始碼
- 【筆記】jQuery原始碼(文件處理3)筆記jQuery原始碼
- 追蹤解析 ThreadPoolExecutor 原始碼thread原始碼
- 傳奇原始碼分析-客戶端(遊戲邏輯處理源分析二)原始碼客戶端遊戲
- 追蹤原始碼的方式歸納原始碼
- druid查詢原始碼追蹤UI原始碼
- 追蹤解析 Netty IntObjectHashMap 原始碼NettyObjectHashMap原始碼
- 程式碼重構之 —— 一堆if、esle 邏輯的處理
- MySQL邏輯查詢處理MySql
- Windows邏輯備份-EXPDP(保留5天內邏輯備份)批處理指令碼Windows指令碼
- 程式碼追蹤
- JavaScript 錯誤處理和堆疊追蹤淺析JavaScript
- SAP gateway處理multiple key的邏輯Gateway
- 淺談zip格式處理邏輯漏洞
- 查詢處理的邏輯順序
- 追蹤解析Spring ioc啟動原始碼(2)Spring原始碼
- 前端業務程式碼配置化處理條件判斷邏輯前端
- Nginx(二): worker 程式處理邏輯-流程框架Nginx框架
- Spring MVC的請求處理邏輯SpringMVC
- WM-QM未清TR處理邏輯
- Android 介面顯示與邏輯處理Android
- 創業黑箱:理解產品和商業的邏輯創業
- SQL追蹤和事件追蹤SQL事件
- Vue2原始碼分析-邏輯梳理Vue原始碼
- Golang原始碼學習:排程邏輯(一)初始化Golang原始碼
- 讓玩家“白嫖遊戲”下的商業邏輯遊戲
- [原始碼解析] TensorFlow 分散式環境(3)--- Worker 靜態邏輯原始碼分散式
- 物理DG與邏輯DG的區別與邏輯DG同步異常處理方法
- 機器學習筆記(3):多類邏輯迴歸機器學習筆記邏輯迴歸
- 11g 邏輯備庫簡單故障處理
- 微軟官方:SELECT語句邏輯處理順序微軟
- SQL邏輯查詢處理順序特別提醒SQL
- AR事務處理GL_DATE獲得邏輯
- golang 程式記憶體追蹤、分析Golang記憶體