#
摘要: 如何使用struts2攔截器,或者自定義攔截器。特別注意,在使用攔截器的時候,在Action里面必須最后一定要引用struts2自帶的攔截器缺省堆棧defaultStack,如下(這里我是引用了struts2自帶的checkbox攔截器): 源碼復制打印?<interceptor-ref name="checkbox"> <...
閱讀全文
1.Struts 2的基本流程 Struts 2框架由3個部分組成:核心控制器FilterDispatcher、業務控制器和用戶實現的業務邏輯組件。在這3個部分里,Struts 2框架提供了核心控制器FilterDispatcher,而用戶需要實現業務控制器和業務邏輯組件。 2.核心控制器:FilterDispatcher FilterDispatcher是Struts 2框架的核心控制器,該控制器作為一個Filter運行在Web應用中,它負責攔截所有的用戶請求,當用戶請求到達時,該Filter會過濾用戶請求。如果用戶請求以action結尾,該請求將被轉入Struts 2框架處理。 Struts 2框架獲得了*.action請求后,將根據*.action請求的前面部分決定調用哪個業務邏輯組件,例如,對于login.action請求,Struts 2調用名為login的Action來處理該請求。 Struts 2應用中的Action都被定義在struts.xml文件中,在該文件中定義Action時,定義了該Action的name屬性和class屬性,其中name屬性決定了該Action處理哪個用戶請求,而class屬性決定了該Action的實現類。 Struts 2用于處理用戶請求的Action實例,并不是用戶實現的業務控制器,而是Action代理——因為用戶實現的業務控制器并沒有與Servlet API耦合,顯然無法處理用戶請求。而Struts 2框架提供了系列攔截器,該系列攔截器負責將HttpServletRequest請求中的請求參數解析出來,傳入到Action中,并回調Action 的execute方法來處理用戶請求。 顯然,上面的處理過程是典型的AOP(面向切面編程)處理方式。圖3.19顯示了這種處理模型。 圖3.19 Struts 2的攔截器和Action 從圖3.19中可以看出,用戶實現的Action類僅僅是Struts 2的Action代理的代理目標。用戶實現的業務控制器(Action)則包含了對用戶請求的處理。用戶的請求數據包含在 HttpServletRequest對象里,而用戶的Action類無需訪問HttpServletRequest對象。攔截器負責將 HttpServletRequest里的請求數據解析出來,并傳給業務邏輯組件Action實例。 3.業務控制器 正如從圖3.19所看到的,業務控制器組件就是用戶實現Action類的實例,Action類里通常包含了一個execute方法,該方法返回一個字符串——該字符串就是一個邏輯視圖名,當業務控制器處理完用戶請求后,根據處理結果不同,execute方法返回不同字符串 ——每個字符串對應一個視圖名。 程序員開發出系統所需要的業務控制器后,還需要配置Struts 2的Action,即需要配置Action的如下三個部分定義: — Action所處理的URL。 — Action組件所對應的實現類。 — Action里包含的邏輯視圖和物理資源之間的對應關系。 每個Action都要處理一個用戶請求,而用戶請求總是包含了指定URL。當Filter Dispatcher攔截到用戶請求后,根據請求的URL和Action處理URL之間的對應關系來處理轉發。 4.Struts 2的模型組件 實際上,模型組件已經超出了MVC框架的覆蓋范圍。對于Struts 2框架而言,通常沒有為模型組件的實現提供太多的幫助。 文本框: 圖3.20 控制器調用模型組件Java EE應用里的模型組件,通常指系統的業務邏輯組件。而隱藏在系統的業務邏輯組件下面的,可能還包含了DAO、領域對象等組件。 通常,MVC框架里的業務控制器會調用模型組件的方法來處理用戶請求。也就是說,業務邏輯控制器不會對用戶請求進行任何實際處理,用戶請求最終由模型組件負責處理。業務控制器只是中間負責調度的調度器,這也是稱Action為控制器的原因。 圖3.20顯示了這種處理流程。 提示 在圖3.20中看到Action調用業務邏輯組件的方法。當控制器需要獲得業務邏輯組件實例時,通常并不會直接獲取業務邏輯組件實例,而是通過工廠模式來獲得業務邏輯組件的實例;或者利用其他IoC容器(如Spring容器)來管理業務邏輯組件的實例。 5.Struts 2的視圖組件 Struts 2已經改變了Struts 1只能使用JSP作為視圖技術的現狀,Struts 2允許使用其他的模板技術,如FreeMarker、Velocity作為視圖技術。 當Struts 2的控制器返回邏輯視圖名時,邏輯視圖并未與任何的視圖技術關聯,僅僅是返回一個字符串,該字符串作為邏輯視圖名。 當我們在struts.xml文件中配置 Action時,不僅需要指定Action的name屬性和class屬性,還要為Action元素指定系列result子元素,每個result子元素定義一個邏輯視圖和物理視圖之間的映射。前面所介紹的應用都使用了JSP技術作為視圖,故配置result子元素時沒有指定type屬性,默認使用JSP 作為視圖資源。 如果需要在Struts 2中使用其他視圖技術,則可以在配置result子元素時,指定相應的type屬性即可。例如,如果需要使用FreeMarker,則為result指定值為freemarker的type屬性;如果想使用Velocity模板技術作為視圖資源,則為result指定值為velocity的type屬性…… 6.Struts 2的運行流程 經過上面介紹,我們發現Struts 2框架的運行流程非常類似于WebWork框架的流程。 提示 在Struts 2的官方站點,我們可以找到如下說法:Essentially,Struts 2.0 is the technical equivalent of WebWork 2.3。Aside from the package and property renaming,it isn't much different than,say,migrating from WebWork 2.1 to 2.2——意思是說:Struts 2.0技術等同于WebWork 2.3框架,除了包和屬性被改名外。從WebWork 2.2遷移到Struts 2不會比從WebWork 2.1遷移到WebWork 2.2更復雜。 這里我們可以看到,Struts 2其實就是WebWork 2.2的升級版,這也就不難理解:為什么WebWork和Struts 2如此相似! 因此,Struts 2的運行流程與WebWork的運行流程完全相同,讀者可以參看圖1.8來了解Struts 2的運行流程。
摘要: struts2 的基石--攔截器(Interceptor)(轉載自http://www.tkk7.com/max/archive/2006/12/06/85925.html) 許多朋友可能對于Struts 2.0與WebWork關系還搞不清楚。下面是Apache的Struts官網中的一段話: Apache Struts 2 was originally known as...
閱讀全文
我們知道通常情況下,Struts2是通過struts.xml配置的。但是隨著系統規模的加大我們需要配置的文件會比較大,雖然我們可以根據不同的系統功能將不同模塊的配置文件單獨書寫,然后通過<include>節點將不同的配置文件引入到最終的struts.xml文件中,但是畢竟還是要維護和管理這些文件,因此也會給維護工作帶來很大的困擾。為了解決這個問題,可以考慮使用struts2的注解。實際上struts2中最主要的概念就是package、action以及Interceptor等等概念,所以只要明白這些注解就可以了。
如果希望使用struts2的注解功能,必須使用一個包struts2-convention-plugin-2.1.8.1.jar,我使用的環境是struts2.1.8.1。如果你使用了不同的版本,找名字就行。
在以上所述的jar文件中定義了一系列的注解,其中比較主要的是:
實際上,struts2中的主要注解就是這些,當然了,還有上面提到的@interceptorRef和@exceptionMapping;基本上,掌握了這些注解就可以了。
但是如果想讓這些注解真正工作,必須在配置文件增加幾個常量的定義:
- struts.convention.default.parent.package:這個常量表示缺省的包名是什么,因為在實際應用中,我們常常定義一個缺省的包,這個包中定義了一大堆的攔截器等等,然后其他的包繼承自這個包。這個常量可以配也可以不配;
- struts.convention.package.locators:這個常量表示你的action類的java包的包名的后綴是啥:比如action。這個常量也可以不配;
- struts.convention.package.locators.basePackage:這個常量表示你的action類的java包package的名字是啥;這個常量也可以不配;
以上三個常量都是輔助作用的,為了讓注解真正的工作,必須在配置文件中增加<package>節點的配置,至少是<package name="myPackage" extends="struts-default" />,這樣注解就可以使用了。
摘要: 在Java編碼中,我們容易犯一些錯誤,也容易疏忽一些問題,因此筆者對日常編碼中曾遇到的一些經典情形歸納整理成文,以共同探討。 0. 糾結的同名 現象 很多類的命名相同(例如:常見于異常、常量、日志等類),導致在import時,有時候張冠李戴,這種錯誤有時候很隱蔽。因為往往同名的類功能也類似,所以IDE不會提示warn。 解決 寫完代碼時,掃視下im...
閱讀全文
摘要:調試不僅可以查找到應用程序缺陷所在,還可以解決缺陷。對于Java程序員來說,他們不僅要學會如何在Eclipse里面開發像樣的程序,更需要學會如何調試程序。本文介紹了Java程序員必知的10個調試技巧,保證讓你受益匪淺! 調試可以幫助識別和解決應用程序缺陷,在本文中,作者將使用大家常用的的開發工具Eclipse來調試Java應用程序。但這里介紹的調試方法基本都是通用的,也適用于NetBeans IDE,我們會把重點放在運行時上面。 在開始之前,推薦大家去看看Eclipse shortcuts這篇文章,它將會給你帶來很多方便。在本文中使用的是Eclipse Juno版(Eclipse 4.2),在開始前給大家提3點建議! 1.不要使用System.out.println作為調試工具 2.把所有涉及到的組件日志級別激活并使用 3.使用日志分析器來讀取日志 0.條件斷點 如果你不知道如何添加斷點,只需點擊左邊面板(行號前面)斷點即被創建。在調試界面中,“斷點”視圖會把所有被創建的斷點列出來。我們可以給它加一個布爾條件,也就是說,該斷點會被激活并且如果布爾條件為真,就會執行該斷點,否則將會跳過往下執行。
1.異常斷點 在斷點視圖中,有一個J!標記按鈕!我們可以使用該按鈕來添加一個Java異常斷點。例如,我們想讓程序在遇到空指針異常(NullPointerException)時,仍然能繼續調試,那么我們可以使用該按鈕來添加一個異常斷點!
2.監視點 這是一個非常好的功能,當選定的屬性訪問或修改程序時,程序會停止執行并允許進行調試。在Outline視圖中選擇一個類變量并從上下文菜單中選擇切換監視點,屬性監視點將會被創建,在斷點(Breakpoints)視圖中會把所有監視點用列表的形式顯示出來。
3.評估/檢查 按Ctrl+Shift+D或者Ctrl+Shift+I來顯示選定變量或者表達式的值。我們也可以給一個變量或表達式添加永久觀察點,當程序在調試時,這些觀察點就會在表達式視圖(Expression view)中顯示出來。
4.修改變量值 在調試過程中,我們可以修改變量值。先選好一個變量然后進入變量視圖(Variables view),根據變量類型在其對應的Value列里輸入值即可。
5.在Main函數里面停止執行 在運行/調試設置中,編輯配置對話框中有“Main”這個選項卡,我們可以勾選“Stop in main”這個復選框。如果選中,那么在調試一個基于main方法的Java程序時,程序會在main方法第一行位置便停止執行。
6.環境變量 并不是在系統屬性中添加環境變量,我們可以在編輯配置對話框中很方便地進行添加。
7.Drop to Frame 這也是我最喜歡的一個功能。調試期間,可以重新跳到調用堆棧框架的開始處執行,并且變量值也會回到最初。根據回檔調整堆棧的深度,這個功能的主要用途是所有變量狀態可以快速回到方法開始執行時候的樣子,然后你可以重新進行一遍一遍執行,這樣就可以在你關注的地方進行多次調試,但是在執行過程中也會產生一些副作用,比如插入到數據庫里面的數據是無法刪除的!
8.分布過濾 當我們進入(F5)方法的時候,我們還可以訪問其外部庫(比如java.*),我們可能不需要這個庫,就可以在Perference選項卡頁面添加一個過濾器來排除這個包。
9.進入、跳出和返回 我把這個放在最后一點,在調試過程中,這些是必須要了解(最好掌握)的東西: F5——進入:移動到下一個步驟,如果當前行有一個方法調用,該控件將會跳轉到被調用方法的第一行執行。 F6——跳出:移動到下一行。如果在當前行有方法調用,那么會直接移動到下一行執行。不會進入被調用方法體里面。 F7——返回:從當前方法中跳出,繼續往下執行。 F8——移動到下一個斷點處執行。
摘要: 接 ibatis 開發指南 2 Cache 在特定硬件基礎上(同時假設系統不存在設計上的缺漏和糟糕低效的 SQL 語句) Cache往往是提升系統性能的最關鍵因素)。 相對 Hibernate 等封裝較為嚴密的 ORM 實現而言(因為對數據對象的操作實現 了較為嚴密的封裝,可以保證其作用范圍內的緩存同步,而 ibatis 提供的是半封閉 ...
閱讀全文
Java做的系統給人的印象是什么?占內存!說道這句話就會有N多人站出來為java辯護,并舉出一堆的性能測試報告來證明這一點。 其實從理論上來講java做的系統并不比其他語言開發出來的系統更占用內存,那么為什么卻有這么N多理由來證明它確實占內存呢?兩個字,陋習。 (1)別用new Boolean()。 在很多場景中Boolean類型是必須的,比如JDBC中boolean類型的set與get都是通過Boolean封裝傳遞的,大部分ORM也是用Boolean來封裝boolean類型的,比如: ps.setBoolean("isClosed",new Boolean(true)); ps.setBoolean("isClosed",new Boolean(isClosed)); ps.setBoolean("isClosed",new Boolean(i==3)); 通常這些系統中構造的Boolean實例的個數是相當多的,所以系統中充滿了大量Boolean實例小對象,這是相當消耗內存的。Boolean類實際上只要兩個實例就夠了,一個true的實例,一個false的實例。 Boolean類提供兩了個靜態變量: public static final Boolean TRUE = new Boolean(true); public static final Boolean FALSE = new Boolean(false); 需要的時候只要取這兩個變量就可以了, 比如: ps.setBoolean("isClosed",Boolean.TRUE); 那么象2、3句那樣要根據一個boolean變量來創建一個Boolean怎么辦呢?可以使用Boolean提供的靜態方法: Boolean.valueOf() 比如: ps.setBoolean("isClosed",Boolean.valueOf(isClosed)); ps.setBoolean("isClosed",Boolean.valueOf(i==3)); 因為valueOf的內部實現是:return (b ? TRUE : FALSE); 所以可以節省大量內存。相信如果Java規范直接把Boolean的構造函數規定成private,就再也不會出現這種情況了。 (2)別用new Integer. 和Boolean類似,java開發中使用Integer封裝int的場合也非常多,并且通常用int表示的數值通常都非常小。SUN SDK中對Integer的實例化進行了優化,Integer類緩存了-128到127這256個狀態的Integer,如果使用Integer.valueOf(int i),傳入的int范圍正好在此內,就返回靜態實例。這樣如果我們使用Integer.valueOf代替new Integer的話也將大大降低內存的占用。如果您的系統要在不同的SDK(比如IBM SDK)中使用的話,那么可以自己做了工具類封裝一下,比如IntegerUtils.valueOf(),這樣就可以在任何SDK中都可以使用這種特性。 (3)用StringBuffer代替字符串相加。 這個我就不多講了,因為已經被人講過N次了。我只想將一個不是笑話的笑話,我在看國內某“著名”java開發的WEB系統的源碼中,竟然發現其中大量的使用字符串相加,一個拼裝SQL語句的方法中竟然最多構造了將近100個string實例。無語中! (4)過濫使用哈希表 有一定開發經驗的開發人員經常會使用hash表(hash表在JDK中的一個實現就是HashMap)來緩存一些數據,從而提高系統的運行速度。比如使用HashMap緩存一些物料信息、人員信息等基礎資料,這在提高系統速度的同時也加大了系統的內存占用,特別是當緩存的資料比較多的時候。其實我們可以使用 操作系統中的緩存的概念來解決這個問題,也就是給被緩存的分配一個一定大小的緩存容器,按照一定的算法淘汰不需要繼續緩存的對象,這樣一方面會因為進行了對象緩存而提高了系統的運行效率,同時由于緩存容器不是無限制擴大,從而也減少了系統的內存占用。現在有很多開源的緩存實現項目,比如ehcache、oscache等,這些項目都實現了FIFO、MRU等常見的緩存算法。 (5)避免過深的類層次結構和過深的方法調用。 因為這兩者都是非常占用內存的(特別是方法調用更是堆棧空間的消耗大戶。 (6)變量只有在用到它的時候才定義和實例化。 (7)盡量避免使用static變量,類內私有常量可以用final來代替。
ibatis的調試相對困難,出錯的時候主要依據是log4生成的log文件和.net的出錯提示,這方面要能比較熟練的看懂. 下面這個配置基本上包含了最復雜的功能:分頁\搜索\排序\緩存\傳值Hash表\返回hash表\動態sql 如果對下面這段配置能信手粘來的話,那開發速度將會大大的提升. <statement id="XinxiTable_SelectAll" listClass="ArrayList" >resultMap="SimpleXinxi" parameterClass="Hashtable" cacheModel="xinxi-cache" > SELECT <dynamic prepend="top"> <isNotEqual prepend="top" property="TopNum" compareValue = "0"> $TopNum$ </isNotEqual> </dynamic> * FROM (select a.[iXinxiID],a.[sXinxiTitle],a.[iXinxiClassId],b.[sClassName], a.[dXinxiDate],a.[dXinxiYxq],a.[iXinxiHits],a.[sXinxiUser],a.[sRedirectUrl], ROW_NUMBER() OVER( <dynamic prepend="order by"> <isEqual prepend="order by" property="Sort" compareValue = "0"> a.iXinxiID desc </isEqual> <isEqual prepend="order by" property="Sort" compareValue = "1"> a.iXinxiID asc </isEqual> <isEqual prepend="order by" property="Sort" compareValue = "2"> a.iXinxiHits desc </isEqual> <isEqual prepend="order by" property="Sort" compareValue = "3"> a.iXinxiHits asc </isEqual> </dynamic> ) as row FROM [dbo].[XinxiTable] as a,[dbo].[XinxiClass] as b <dynamic prepend="where"> <isParameterPresent> <isNotEmpty prepend="and" property="XinxiType" > a.[iXinxiState]= $XinxiType$ </isNotEmpty> <isNotEqual prepend="and" property="XinxiClass" compareValue = "0"> a.[iXinxiClassID]= $XinxiClass$ </isNotEqual> <isEqual prepend="and" property="SearchType" compareValue = "1"> a.[sXinxiTitle] LIKE '%$Keyword$%' </isEqual> <isEqual prepend="and" property="SearchType" compareValue = "2"> (a.[sXinxiTitle] LIKE '%$Keyword$%' or a.[sXinxiContent] LIKE '%$Keyword$%') </isEqual> </isParameterPresent> </dynamic> and a.iXinxiClassId=b.iClassId )a <dynamic prepend="where"> <isParameterPresent> <isEqual prepend="and" property="IsPage" compareValue = "1"> row between $PageLower$ and $PageUpper$ </isEqual> </isParameterPresent> </dynamic> </statement>
摘要: iBatis中的動態查詢還是比較好用的 如果想深入學習,可以參考 Manning.iBATIS.in.Action.Jan.2007 下面給出幾個例子和dtd定義: <select id="selectDispatchedKey" parameterClass="KeyAndKeyFlowInfo" resultMap="KeyAndKeyFlowResult"...
閱讀全文