
2014年10月8日
1.JDK和JRE的區(qū)別:
JDK是Java Development Kit。是面向開發(fā)人員使用的SDK,提供了java的開發(fā)環(huán)境以及運行環(huán)境。
JRE是Java Runtime Enviroment。是指java的運行環(huán)境,是面向java程序得使用者,而不是開發(fā)者。
2.序列化的目的:
Java中,一切都是對象,在分布式環(huán)境中經(jīng)常需要將Object從這一端網(wǎng)絡(luò)或設(shè)備傳遞到另一端。這就需要有一種可以在兩端傳輸數(shù)據(jù)的協(xié)議。Java序列化機制就是為了解決這個問題而產(chǎn)生。
以某種存儲形式使自定義對象持久化。
將對象從一個地方傳到另一個地方。
3.equals和==的區(qū)別:
基本數(shù)據(jù)類型應(yīng)該用“==”來比較他們的值。
當(dāng)比較對象時候,如果對象里重寫了equals方法,比如String,Integer,Date這些類,比較對象的內(nèi)存地址應(yīng)該用“==”,比較對象的值用“equals”,如果沒有重寫equals方法,兩者本質(zhì)上是相同的,都是比較值。
4.什么時候使用Comparator and Comparable 接口
當(dāng)需要排序的集合或數(shù)組不是單純的數(shù)字類型的時候,通??梢允褂肅omparator或Comparable,以簡單的方式實現(xiàn)對象排序和自定義排序。
Comparable用在對象本身,說明這個對象是可以被比較的,也就是說可以被排序的。(String和Integer之所以可以比較大小,是因為它們都實現(xiàn)了Comparable接口,并實現(xiàn)了compareTo()方法)。
Compator用在對象外,相當(dāng)于定義了一個排序算法。
5.轉(zhuǎn)發(fā)和重定向的區(qū)別:
轉(zhuǎn)發(fā)時URL不會改變,request請求內(nèi)的對象將可以繼續(xù)使用,重定向時瀏覽器URL會改變,之前的request會丟失,因此request里的數(shù)據(jù)也不會得到。
通常情況下轉(zhuǎn)發(fā)速度更快,而且能保持request內(nèi)的對象,但是轉(zhuǎn)發(fā)之后,瀏覽器的連接還在先前頁面所以可以重載先前頁面。
轉(zhuǎn)發(fā):request.getRequestDispatcher("apage.jsp").forward(request, response);
重定向:response.sendRedirect("apage.jsp");
6.編譯期異常和運行時異常
編譯時異常可以捕捉,比如我們讀寫文件時候會拋出IOException,操作數(shù)據(jù)庫時會有SQLException,運行時異常不可以捕捉,比如數(shù)組下標(biāo)溢出,空指針異常等
7.Struts1原理和Struts2原理以及區(qū)別和聯(lián)系,在什么項目中用過,有什么體會?
struts1原理:客戶端發(fā)送HttpServletRequest請求給ActionServlet,ActionServlet會檢索和用戶請求匹配的ActionMapping實例,如果不存在就返回請求路徑無效的信息,如果存在就會把請求的表單數(shù)據(jù)保存到ActionForm中去,如果ActionForm不存在就會創(chuàng)建一個ActionForm對象,然后再根據(jù)配置信息決定是否需要表單驗證,如果需要驗證就調(diào)用ActionForm的validate()方法,驗證通過后ActionServlet根據(jù)ActionMapping實例包含的映射信息決定將請求轉(zhuǎn)發(fā)給哪個Action,如果相應(yīng)的Action實例不存在就先創(chuàng)建這個Action然后調(diào)用Action的execute()方法。Action的execute()方法返回一個ActionForward對象,ActionServlet再把客戶請求轉(zhuǎn)發(fā)給ActionForward對象指向的jsp組件。
struts2原理:客戶端發(fā)送HttpServletRequest請求,請求被提交到一系列的Filter,首先是ActionContextCleanUp,然后是其他Filter,最后是FilterDispatcher。FilterDispatcher是Struts2的核心,就是MVC的Struts2實現(xiàn)中控制層的核心。FilterDispatcher詢問ActionMapper決定需要調(diào)用哪個Action,F(xiàn)ilterDispatcher會把請求交給ActionProxy,ActionProxy會根據(jù)Struts.xml配置文件找到需要調(diào)用的Action類。ActionProxy創(chuàng)建一個ActionInvocation實例,同時ActionInvocation通過代理模式調(diào)用Action類,調(diào)用之前會加載Action相關(guān)的所有攔截器,一旦Action執(zhí)行完畢,ActionInvocation根據(jù)Struts.xml配置文件返回對應(yīng)的result。
區(qū)別:1.Struts1是通過Servlet啟動的,struts1要求Action繼承一個抽象類,而不是接口,Struts2的Action類可以實現(xiàn)一個Action接口也可以實現(xiàn)其他接口。
2.struts1的Action是單例模式線程是不安全的,struts2是線程安全的,Action為每一個請求都生成了一個實例。
3.struts1是以ActionServlet為核心控制器,struts2是以FilterDispatcher為核心控制器。
執(zhí)行流程:
a)struts1
jsp發(fā)起httprequest請求->servlet捕獲->struts.xml->namespace+ActionName-> Action->填充表單setXxx()->action.execute()->”success”->Result->設(shè)置request屬性->跳轉(zhuǎn)目標(biāo)頁
b) Action(jsp發(fā)起httprequest請求,被過濾器捕獲)->FilterDispatcher->struts.xml->namespace+ActionName->new Action->填充表單setXxx()->action.execute()->”success”->Result->設(shè)置request屬性->跳轉(zhuǎn)目標(biāo)頁
8.spring原理
spring的最大作用ioc/di,將類與類的依賴關(guān)系寫在配置文件中,程序在運行時根據(jù)配置文件動態(tài)加載依賴的類,降低的類與類之間的藕合度。它的原理是在applicationContext.xml加入bean標(biāo)記,在bean標(biāo)記中通過class屬性說明具體類名、通過property標(biāo)簽說明該類的屬性名、通過constructor-args說明構(gòu)造子的參數(shù)。其一切都是反射,當(dāng)通過applicationContext.getBean(“id名稱”)得到一個類實例時,就是以bean標(biāo)簽的類名、屬性名、構(gòu)造子的參數(shù)為準(zhǔn),通過反射實例對象,喚起對象的set方法設(shè)置屬性值、通過構(gòu)造子的newInstance實例化得到對象。正因為spring一切都是反射,反射比直接調(diào)用的處理速度慢,所以這也是spring的一個問題。
spring第二大作用就是aop,其機理來自于代理模式,代理模式有三個角色分別是通用接口、代理、真實對象。代理、真實對象實現(xiàn)的是同一接口,將真實對象作為代理的一個屬性,向客戶端公開的是代理,當(dāng)客戶端調(diào)用代理的方法時,代理找到真實對象,調(diào)用真實對象方法,在調(diào)用之前之后提供相關(guān)的服務(wù),如事務(wù)、安全、日志。其名詞分別是代理、真實對象、裝備、關(guān)切點、連接點。
9.簡要概述一下SpringMVC和StrutsMVC
Spring的MVC框架主要由DispatcherServlet、處理器映射、處理器、視圖解析器、視圖組成。
1)DispatcherServlet接收到請求后,根據(jù)對應(yīng)配置文件中配置的處理器映射,找到對應(yīng)的處理器映射項(HandlerMapping),根據(jù)配置的映射規(guī)則,找到對應(yīng)的處理器(Handler)。
2)調(diào)用相應(yīng)處理器中的處理方法,處理該請求,處理器處理結(jié)束后會將一個ModelAndView類型的數(shù)據(jù)傳給DispatcherServlet,這其中包含了處理結(jié)果的視圖和視圖中要使用的數(shù)據(jù)。
3)DispatcherServlet 根據(jù)得到的ModelAndView中的視圖對象,找到一個合適的ViewResolver(視圖解析器),根據(jù)視圖解析器的配 置,DispatcherServlet將視圖要顯示的數(shù)據(jù)傳給對應(yīng)的視圖,最后給瀏覽器構(gòu)造一個HTTP響應(yīng)。
DispatcherServlet是整個Spring MVC的核心。它負(fù)責(zé)接收HTTP請求組織協(xié)調(diào)Spring MVC的各個組成部分。其主要工作有以下三項:
1)截獲符合特定格式的URL請求。
2)初始化DispatcherServlet上下文對應(yīng)的WebApplicationContext,并將其與業(yè)務(wù)層、持久化層的WebApplicationContext建立關(guān)聯(lián)。
3)初始化Spring MVC的各個組成組件,并裝配到DispatcherServlet中。
StrutsMVC
1.當(dāng)啟動容器時,容器(tomcat、weblogic)實例化ActionServlet,初始化ActionServlet,在初始化
ActionServlet時加載struts-config.xml文件。
2.當(dāng)客戶通過url.do將請求發(fā)給ActionServlet,ActionServlet將處理轉(zhuǎn)發(fā)給助手RequestProcessor,RequestProcess通過struts-config.xml找到對應(yīng)的actionForm及 action,如果有ActionForm用已有的,沒有通過類的反射實例化一個新的ActionForm,放置到作用域?qū)ο?,通過反射
- 將表單域的值填充到actionForm中。如果有Action用已有的,沒有產(chǎn)生一個新的,通過反射調(diào)用action實例的execute方法,在執(zhí)行前將actionForm通過參數(shù)注入到execute方法中。
- 3.execute方法執(zhí)行結(jié)束前通過actionMapping找到actionForward轉(zhuǎn)發(fā)到另一個頁面。
10.Servlet的工作原理、生命周期
Servlet的工作原理:
Servlet 生命周期:Servlet 加載--->實例化--->服務(wù)--->銷毀。 init():在Servlet的生命周期中,僅執(zhí)行一次init()方法。它是在服務(wù)器裝入Servlet時執(zhí)行的,負(fù)責(zé)初始化Servlet 對象。可以配置服務(wù)器,以在啟動服務(wù)器或客戶機首次訪問Servlet時裝入Servlet。無論有多少客戶機訪問Servlet,都不會重復(fù)執(zhí)行 init()。 service():它是Servlet的核心,負(fù)責(zé)響應(yīng)客戶的請求。每當(dāng)一個客戶請求一個HttpServlet對象,該對象的 Service()方法就要調(diào)用,而且傳遞給這個方法一個“請求”(ServletRequest)對象和一個“響應(yīng)” (ServletResponse)對象作為參數(shù)。在HttpServlet中已存在Service()方法。默認(rèn)的服務(wù)功能是調(diào)用與HTTP請求的方法 相應(yīng)的do功能。 destroy(): 僅執(zhí)行一次,在服務(wù)器端停止且卸載Servlet時執(zhí)行該方法。當(dāng)Servlet對象退出生命周期時,負(fù)責(zé)釋放占用的資 源。一個Servlet在運行service()方法時可能會產(chǎn)生其他的線程,因此需要確認(rèn)在調(diào)用destroy()方法時,這些線程已經(jīng)終止或完成。
Servlet工作原理:
1、首先簡單解釋一下Servlet接收和響應(yīng)客戶請求的過程,首先客戶發(fā)送一個請求,Servlet是調(diào)用service()方法對請求進行響應(yīng) 的,通過源代碼可見,service()方法中對請求的方式進行了匹配,選擇調(diào)用doGet,doPost等這些方法,然后再進入對應(yīng)的方法中調(diào)用邏輯層 的方法,實現(xiàn)對客戶的響應(yīng)。在Servlet接口和GenericServlet中是沒有doGet()、doPost()等等這些方法 的,HttpServlet中定義了這些方法,但是都是返回error信息,所以,我們每次定義一個Servlet的時候,都必須實現(xiàn)doGet或 doPost等這些方法。
2、每一個自定義的Servlet都必須實現(xiàn)Servlet的接口,Servlet接口中定義了五個方法,其中比較重要的三個方法涉及到 Servlet的生命周期,分別是上文提到的init(),service(),destroy()方法。GenericServlet是一個通用的,不 特定于任何協(xié)議的Servlet,它實現(xiàn)了Servlet接口。而HttpServlet繼承于GenericServlet,因此 HttpServlet也實現(xiàn)了Servlet接口。所以我們定義Servlet的時候只需要繼承HttpServlet即可。
3、Servlet接口和GenericServlet是不特定于任何協(xié)議的,而HttpServlet是特定于HTTP協(xié)議的類,所以 HttpServlet中實現(xiàn)了service()方法,并將請求ServletRequest、ServletResponse 強轉(zhuǎn)為HttpRequest 和 HttpResponse。
11.OOA、OOD、OOP含義
Object-Oriented Analysis:面向?qū)ο蠓治龇椒?/span>
Object-Oriented Design:面向?qū)ο笤O(shè)計
Object Oriented Programming:面向?qū)ο缶幊?/span>
OOA是對系統(tǒng)業(yè)務(wù)調(diào)查了解之后根據(jù)面向?qū)ο蟮乃枷脒M行系統(tǒng)分析,在OOA分析的基礎(chǔ)上對系統(tǒng)根據(jù)面向?qū)ο蟮乃枷脒M行系統(tǒng)設(shè)計,從而能夠直接進行OOP面向?qū)ο缶幊獭?/span>
12.mysql分頁查詢
對于有大數(shù)據(jù)量的mysql表來說,使用LIMIT分頁存在很嚴(yán)重的性能問題。
查詢從第1000000之后的30條記錄:
SQL代碼1:平均用時6.6秒 SELECT * FROM `cdb_posts` ORDER BY pid LIMIT 1000000 , 30
SQL代碼2:平均用時0.6秒 SELECT * FROM `cdb_posts` WHERE pid >= (SELECT pid FROM `cdb_posts` ORDER BY pid LIMIT 1000000 , 1) LIMIT 30
因為要取出所有字段內(nèi)容,第一種需要跨越大量數(shù)據(jù)塊并取出,而第二種基本通過直接根據(jù)索引字段定位后,才取出相應(yīng)內(nèi)容,效率自然大大提升。
可以看出,越往后分頁,LIMIT語句的偏移量就會越大,兩者速度差距也會越明顯。
實際應(yīng)用中,可以利用類似策略模式的方式去處理分頁,比如判斷如果是一百頁以內(nèi),就使用最基本的分頁方式,大于一百頁,則使用子查詢的分頁方式。
Oracle查詢:SELECT * FROM (SELECT A.*, ROWNUM RN FROM (SELECT * FROM TABLE_NAME) A WHERE ROWNUM <= 40) WHERE RN >= 21
13.單例模式、工廠模式、代理模式
枚舉實現(xiàn)單例模式:
public enum Singleton {
/**
* 定義一個枚舉的元素,它就代表了Singleton的一個實例。
*/
uniqueInstance;
/**
* 單例可以有自己的操作
*/
public void singletonOperation(){
//功能處理
}
}
懶漢同步單例模式:
public class LazySingleton {
private static LazySingleton instance = null;
/**
* 私有默認(rèn)構(gòu)造子
*/
private LazySingleton(){}
/**
* 靜態(tài)工廠方法
*/
public static synchronized LazySingleton getInstance(){
if(instance == null){
instance = new LazySingleton();
}
return instance;
}
}
工廠模式:http://www.cnblogs.com/java-my-life/archive/2012/03/28/2418836.html
代理模式:http://yangguangfu.iteye.com/blog/815787
未完待續(xù)...
posted @
2014-10-08 16:50 小人物_Amor 閱讀(358) |
評論 (0) |
編輯 收藏
- Servlet 生命周期:Servlet 加載--->實例化--->服務(wù)--->銷毀。
- init():在Servlet的生命周期中,僅執(zhí)行一次init()方法。它是在服務(wù)器裝入Servlet時執(zhí)行的,負(fù)責(zé)初始化Servlet 對象。可以配置服務(wù)器,以在啟動服務(wù)器或客戶機首次訪問Servlet時裝入Servlet。無論有多少客戶機訪問Servlet,都不會重復(fù)執(zhí)行 init()。
- service():它是Servlet的核心,負(fù)責(zé)響應(yīng)客戶的請求。每當(dāng)一個客戶請求一個HttpServlet對象,該對象的 Service()方法就要調(diào)用,而且傳遞給這個方法一個“請求”(ServletRequest)對象和一個“響應(yīng)” (ServletResponse)對象作為參數(shù)。在HttpServlet中已存在Service()方法。默認(rèn)的服務(wù)功能是調(diào)用與HTTP請求的方法 相應(yīng)的do功能。
- destroy(): 僅執(zhí)行一次,在服務(wù)器端停止且卸載Servlet時執(zhí)行該方法。當(dāng)Servlet對象退出生命周期時,負(fù)責(zé)釋放占用的資 源。一個Servlet在運行service()方法時可能會產(chǎn)生其他的線程,因此需要確認(rèn)在調(diào)用destroy()方法時,這些線程已經(jīng)終止或完成。
Tomcat 與 Servlet 是如何工作的:

步驟:
- Web Client 向Servlet容器(Tomcat)發(fā)出Http請求
- Servlet容器接收Web Client的請求
- Servlet容器創(chuàng)建一個HttpRequest對象,將Web Client請求的信息封裝到這個對象中。
- Servlet容器創(chuàng)建一個HttpResponse對象
- Servlet容器調(diào)用HttpServlet對象的service方法,把HttpRequest對象與HttpResponse對象作為參數(shù)傳給 HttpServlet 對象。
- HttpServlet調(diào)用HttpRequest對象的有關(guān)方法,獲取Http請求信息。
- HttpServlet調(diào)用HttpResponse對象的有關(guān)方法,生成響應(yīng)數(shù)據(jù)。
- Servlet容器把HttpServlet的響應(yīng)結(jié)果傳給Web Client。
Servlet工作原理:
1、首先簡單解釋一下Servlet接收和響應(yīng)客戶請求的過程,首先客戶發(fā)送一個請求,Servlet是調(diào)用service()方法對請求進行響應(yīng) 的,通過源代碼可見,service()方法中對請求的方式進行了匹配,選擇調(diào)用doGet,doPost等這些方法,然后再進入對應(yīng)的方法中調(diào)用邏輯層 的方法,實現(xiàn)對客戶的響應(yīng)。在Servlet接口和GenericServlet中是沒有doGet()、doPost()等等這些方法 的,HttpServlet中定義了這些方法,但是都是返回error信息,所以,我們每次定義一個Servlet的時候,都必須實現(xiàn)doGet或 doPost等這些方法。
2、每一個自定義的Servlet都必須實現(xiàn)Servlet的接口,Servlet接口中定義了五個方法,其中比較重要的三個方法涉及到 Servlet的生命周期,分別是上文提到的init(),service(),destroy()方法。GenericServlet是一個通用的,不 特定于任何協(xié)議的Servlet,它實現(xiàn)了Servlet接口。而HttpServlet繼承于GenericServlet,因此 HttpServlet也實現(xiàn)了Servlet接口。所以我們定義Servlet的時候只需要繼承HttpServlet即可。
3、Servlet接口和GenericServlet是不特定于任何協(xié)議的,而HttpServlet是特定于HTTP協(xié)議的類,所以 HttpServlet中實現(xiàn)了service()方法,并將請求ServletRequest、ServletResponse 強轉(zhuǎn)為HttpRequest 和 HttpResponse。
創(chuàng)建Servlet對象的時機:
- Servlet容器啟動時:讀取web.xml配置文件中的信息,構(gòu)造指定的Servlet對象,創(chuàng)建ServletConfig對象,同時將ServletConfig對象作為參數(shù)來調(diào)用Servlet對象的init方法。
- 在Servlet容器啟動后:客戶首次向Servlet發(fā)出請求,Servlet容器會判斷內(nèi)存中是否存在指定的Servlet對象,如果沒有則 創(chuàng)建它,然后根據(jù)客戶的請求創(chuàng)建HttpRequest、HttpResponse對象,從而調(diào)用Servlet 對象的service方法。
- Servlet Servlet容器在啟動時自動創(chuàng)建Servlet,這是由在web.xml文件中為Servlet設(shè)置的<load- on-startup>屬性決定的。從中我們也能看到同一個類型的Servlet對象在Servlet容器中以單例的形式存在。
<servlet>
<servlet-name>Init</servlet-name>
<servlet-class>org.xl.servlet.InitServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
posted @
2014-10-08 15:16 小人物_Amor 閱讀(293) |
評論 (0) |
編輯 收藏

2014年9月25日
/**
*
*/
package com.zx.ww.arraysort;
import java.text.Collator;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Comparator;
import java.util.Locale;
/**
* @author xue
* 2014年9月24日
*/
public class QuickSort {
public static void main(String[] args) {
for (int i = 0; i < 10; i++) {
test();
}
}
public static void test() {
int len = 8000000;
int[] array = new int[len];
for (int i = 0; i < len; i++) {
array[i] = (int)(Math.random()*10000);
}
Calendar cal_before = Calendar.getInstance();
double before = cal_before.getTimeInMillis();
System.out.println(cal_before.getTime());
quickSort(array, 0, array.length-1);
Calendar cal_after = Calendar.getInstance();
double after = cal_after.getTimeInMillis();
System.out.println(cal_after.getTime());
double time = after-before;
System.out.println("用時:" + time + "ms");
System.out.println("==================================");
}
public static void quickSort(int[] array, int left, int right) {
if(left < right) {
int privot = getPrivot(array, left, right);
quickSort(array, left, privot-1);
quickSort(array, privot+1, right);
}
}
//將數(shù)組劃分為兩個數(shù)組,左邊的數(shù)組都比中軸privot小,右邊的都比中軸privot大
public static int getPrivot(int[] array, int left, int right) {
int tmp = array[left];
while(left < right) {
while(left < right && array[right] >= tmp) {
right--;
}
array[left] = array[right];
while(left < right && array[left] <= tmp) {
left++;
}
array[right] = array[left];
}
array[left] = tmp;
return left;
}
}
運行十次輸出的結(jié)果:
Thu Sep 25 13:09:40 CST 2014
Thu Sep 25 13:09:41 CST 2014
用時:1613.0ms
==================================
Thu Sep 25 13:09:41 CST 2014
Thu Sep 25 13:09:43 CST 2014
用時:1614.0ms
==================================
Thu Sep 25 13:09:43 CST 2014
Thu Sep 25 13:09:45 CST 2014
用時:1691.0ms
==================================
Thu Sep 25 13:09:45 CST 2014
Thu Sep 25 13:09:47 CST 2014
用時:1622.0ms
==================================
Thu Sep 25 13:09:47 CST 2014
Thu Sep 25 13:09:48 CST 2014
用時:1621.0ms
==================================
Thu Sep 25 13:09:49 CST 2014
Thu Sep 25 13:09:50 CST 2014
用時:1615.0ms
==================================
Thu Sep 25 13:09:50 CST 2014
Thu Sep 25 13:09:52 CST 2014
用時:1614.0ms
==================================
Thu Sep 25 13:09:52 CST 2014
Thu Sep 25 13:09:54 CST 2014
用時:1632.0ms
==================================
Thu Sep 25 13:09:54 CST 2014
Thu Sep 25 13:09:55 CST 2014
用時:1614.0ms
==================================
Thu Sep 25 13:09:56 CST 2014
Thu Sep 25 13:09:57 CST 2014
用時:1614.0ms
==================================
上述是快速排序八百萬條數(shù)據(jù)用時基本在1.6s左右。
接下來看冒泡排序:
/**
*
*/
package com.zx.ww.arraysort;
import java.text.Collator;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Comparator;
import java.util.Locale;
/**
* @author wuwei
* 2014年9月24日
*/
public class BubbleSort {
public static void main(String[] args) {
for (int i = 0; i < 5; i++) {
test();
}
}
public static void test() {
int len = 80000;
int[] array = new int[len];
for (int i = 0; i < array.length; i++) {
array[i] = (int)(Math.random()*10000);
}
Calendar calBefore = Calendar.getInstance();
System.out.println(calBefore.getTime());
bubbleSort(array);
Calendar calAfter = Calendar.getInstance();
System.out.println(calAfter.getTime());
System.out.println("總共用時" + (calAfter.getTimeInMillis()-calBefore.getTimeInMillis()) + "ms");
System.out.println("==========================");
}
public static void bubbleSort(int[] array) {
int tmp;
for (int i = 0; i < array.length; i++) {
for (int j = 0; j < array.length-i-1; j++) {
if(array[j] > array[j+1]) {
tmp = array[j+1];
array[j+1] = array[j];
array[j] = tmp;
}
}
}
}
}
運行五次輸出如下結(jié)果:
Thu Sep 25 14:44:14 CST 2014
Thu Sep 25 14:44:23 CST 2014
總共用時8822ms
==========================
Thu Sep 25 14:44:23 CST 2014
Thu Sep 25 14:44:32 CST 2014
總共用時8829ms
==========================
Thu Sep 25 14:44:32 CST 2014
Thu Sep 25 14:44:41 CST 2014
總共用時8915ms
==========================
Thu Sep 25 14:44:41 CST 2014
Thu Sep 25 14:44:50 CST 2014
總共用時8748ms
==========================
Thu Sep 25 14:44:50 CST 2014
Thu Sep 25 14:44:58 CST 2014
總共用時8529ms
==========================
冒泡排序八萬條數(shù)據(jù)用時接近9s。
需要注意的是快速排序是八百萬條數(shù)據(jù)只用了1.6s左右。
posted @
2014-09-25 13:09 小人物_Amor 閱讀(274) |
評論 (0) |
編輯 收藏

2014年7月29日
因為項目框架hibernate里的hibernate.hbm2ddl.auto屬性設(shè)置為create(為了使得開發(fā)人員只關(guān)注于實體類而不必去關(guān)心數(shù)據(jù)庫設(shè)計。。。),所以我們每次部署項目的時候都會把數(shù)據(jù)庫生成的表全刪除了然后根據(jù)實體類生成數(shù)據(jù)表,這樣就需要在maven項目寫一個測試類來初始化項目需要的一些基礎(chǔ)數(shù)據(jù),如用戶、權(quán)限、資源、字典等。因為maven在構(gòu)建到特定的生命周期階段的時候會通過插件來執(zhí)行JUnit或者TestNG的測試用例,這個插件就是maven-surefire-plugin(這是需要配置的,當(dāng)然也可以禁止去執(zhí)行測試類,甚至禁止編譯測試類),需要了解的請學(xué)習(xí)相關(guān)maven文檔,或者參考http://blog.csdn.net/sin90lzc/article/details/7543262。
考慮到上述因素,那么我就在src/test/java文件夾下新建一個測試類,那么這個測試類就會在clean install時候會執(zhí)行,那么在這個時候執(zhí)行數(shù)據(jù)初始化是合適的。因為初始化數(shù)據(jù)來自于sql腳本,所以我得讀取sql腳本的內(nèi)容并解析成相關(guān)的sql語句通過java的jdbc執(zhí)行sql語句。那就開始做吧。不多說,上代碼:
1 package com.infopatent.juangetljc.core;
2
3 import java.io.BufferedReader;
4 import java.io.FileInputStream;
5 import java.io.InputStream;
6 import java.sql.Connection;
7 import java.sql.DriverManager;
8 import java.sql.SQLException;
9 import java.sql.Statement;
10 import java.util.ArrayList;
11 import java.util.Arrays;
12 import java.util.List;
13
14 import org.junit.Test;
15
16 import junit.framework.TestCase;
17
18 public class InitDataTest extends TestCase {
19
20 private String url = "jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=UTF-8";
21 private String driver = "com.mysql.jdbc.Driver";
22 private String userName = "root";
23 private String password = "";
24 String filePathIn = "F://workspace/juange-tljc/juange-tljc-core/src/test/java/basedata.sql";
25
26 @Test
27 public void test() {
28
29 try {
30 execute(filePathIn);
31 } catch (Exception e) {
32 // TODO Auto-generated catch block
33 e.printStackTrace();
34 }
35 }
36
37 /*
38 * 讀取sql文件,獲取sql語句
39 * 返回所有sql語句的list集合
40 * */
41 private List<String> loadSql(String sqlFile) throws Exception {
42 List<String> sqlList = new ArrayList<String>();
43 /*
44 * 讀取文件的內(nèi)容并寫道StringBuffer中去
45 * */
46 InputStream sqlFileIn = new FileInputStream(sqlFile);
47 StringBuffer sqlSb = new StringBuffer();
48 byte[] buff = new byte[sqlFileIn.available()];
49 int byteRead = 0;
50 while((byteRead = sqlFileIn.read(buff)) != -1) {
51 sqlSb.append(new String(buff, 0, byteRead));
52 }
53 /*
54 * windows下?lián)Q行是/r/n,Linux下是/n,
55 * 此處需要根據(jù)導(dǎo)出的sql文件進行具體的處理,我在處理的時候
56 * 也遇到了很多的問題,如果我這個不行可以在網(wǎng)上找找別的解析方法
57 * */
58 String sqlArr[] = sqlSb.toString().split("(;\\s*\\rr\\n)|(;\\s*\\n)");
59 for(int i = 0; i<sqlArr.length; i++) {
60 String sql = sqlArr[i].replaceAll("--.*", "").trim();
61 if(!"".equals(sql)) {
62 sqlList.add(sql);
63 }
64 }
65 return sqlList;
66
67 }
68
69 /*
70 * 傳入文件執(zhí)行sql語句
71 *
72 * */
73 private void execute(String sqlFile) throws SQLException {
74 Statement stmt = null;
75 List<String> sqlList = new ArrayList<String>();
76 Connection conn = getConnection();
77 try {
78 sqlList = loadSql(sqlFile);
79 conn.setAutoCommit(false);
80 stmt = conn.createStatement();
81 for (String sql : sqlList) {
82 System.out.println(sql);
83 stmt.addBatch(sql);
84 }
85 int[] rows = stmt.executeBatch();
86 System.out.println("Row count:" + Arrays.toString(rows));
87 conn.commit();
88 System.out.println("數(shù)據(jù)更新成功");
89 } catch (Exception e) {
90 e.printStackTrace();
91 conn.rollback();
92 }finally{
93 stmt.close();
94 conn.close();
95 }
96
97 }
98
99 /*
100 * 獲取sql連接
101 * */
102 private Connection getConnection(){
103 Connection conn = null;
104 try {
105 Class.forName(driver);
106 conn = DriverManager.getConnection(url, userName, password);
107 if(!conn.isClosed()) {
108 System.out.println("數(shù)據(jù)庫連接成功!");
109 }
110 } catch (Exception e) {
111 e.printStackTrace();
112 }
113 return conn;
114 }
115 }
116
在這個過程中遇到了很多的問題,曾經(jīng)一度使我陷入迷糊狀態(tài)中,后來好好梳理了一下思路,一個一個的去排查問題終于成功了~
首先在讀取文件的時候,發(fā)現(xiàn)讀取的文件內(nèi)容顯示是正常的不是亂碼,但是插入到數(shù)據(jù)庫中就是亂碼,好吧,我又遇到了這種問題,我依次檢查了我java文件的編碼,數(shù)據(jù)庫的編碼,都設(shè)置為utf-8,url也加上編碼
"jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=UTF-8"。結(jié)果還是亂碼,那就再看看mysql下的my.ini文件中的編碼設(shè)置在[mysqld]節(jié)點下加上default-character-set=utf8(如果沒有就改為utf8),這下終于不是亂碼了。然后我開始maven clean install,去查看數(shù)據(jù)庫發(fā)現(xiàn)又出現(xiàn)了亂碼的問題,真是折磨人啊,我發(fā)現(xiàn)唯一不同的就是之前正常的插入數(shù)據(jù)是我在測試類下run as junit,而現(xiàn)在用的是maven clean install,剛接觸maven完全不知道癥結(jié)所在啊,百度一下,發(fā)現(xiàn)maven構(gòu)建到特定的生命周期時候運行測試用例是依靠maven-surefire-plugin這個插件的,而這個插件也需要指定字符集編碼的,于是我在項目的pom.xml中加入了如下代碼(本來竟然沒有?。?br />
1 <build>
2 <plugins>
3 <plugin>
4 <groupId>org.apache.maven.plugins</groupId>
5 <artifactId>maven-surefire-plugin</artifactId>
6 <version>2.7.2</version>
7 <configuration>
8 <forkMode>once</forkMode>
9 <argLine>-Dfile.encoding=UTF-8</argLine>
10 <systemProperties>
11 <property>
12 <name>net.sourceforge.cobertura.datafile</name>
13 <value>target/cobertura/cobertura.ser</value>
14 </property>
15 </systemProperties>
16 </configuration>
17 </plugin>
18 </plugins>
19 </build>
這個時候再去maven clean install,終于不亂碼了,終于不亂碼了!花了我四個小時,長見識了!此處記錄自己遇到的問題以及如何解決,希望對各位有幫助!
posted @
2014-07-29 15:07 小人物_Amor 閱讀(3339) |
評論 (0) |
編輯 收藏

2014年5月30日
各位如果想找合適的樹形菜單,不放試試dtree,去官網(wǎng)看看www.destroydrop.com/javascript/tree/,下載dtree.zip下來解壓之后有dtree.js,dtree.css,img文件夾,api.html,example01.html這幾個文件,可以看看api.html,里面有參數(shù)和方法說明,實際上在項目應(yīng)用時,我們是需要從數(shù)據(jù)庫里的菜單表里讀取數(shù)據(jù)進行樹形菜單構(gòu)建的,根據(jù)api.html里面的參數(shù)說明可建立一張s_menu的數(shù)據(jù)表:
CREATE TABLE `s_menu` (
`id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主鍵id',
`pid` int(11) DEFAULT NULL COMMENT '父級id',
`name` varchar(45) DEFAULT NULL COMMENT '菜單名稱',
`url` varchar(255) DEFAULT NULL COMMENT '菜單url',
`title` varchar(45) DEFAULT NULL COMMENT '鼠標(biāo)放上去顯示的title',
`target` varchar(45) DEFAULT NULL COMMENT '目標(biāo)iframe',
`icon` varchar(255) DEFAULT NULL COMMENT '菜單折疊時候顯示的圖片',
`iconOpen` varchar(255) DEFAULT NULL COMMENT '菜單打開時候顯示的圖片',
`open` int(1) DEFAULT '0' COMMENT '是否打開',
PRIMARY KEY (`id`)
) ENGINE=MyISAM AUTO_INCREMENT=12 DEFAULT CHARSET=utf8;
并且插入一些測試數(shù)據(jù)來使用:
INSERT INTO `s_menu` VALUES ('1', '-1', '瀏覽器', '#', '瀏覽器', null, null, null, '0');
INSERT INTO `s_menu` VALUES ('2', '1', 'IE', '#', 'IE瀏覽器', null, null, null, '0');
INSERT INTO `s_menu` VALUES ('3', '2', 'IE6', '#', 'IE6', null, null, null, '0');
INSERT INTO `s_menu` VALUES ('4', '2', 'IE7', '#', 'IE7', null, null, null, '0');
INSERT INTO `s_menu` VALUES ('5', '2', 'IE8', '#', 'IE8', null, null, null, '0');
INSERT INTO `s_menu` VALUES ('6', '2', 'IE10', '#', 'IE10', null, null, null, '0');
INSERT INTO `s_menu` VALUES ('7', '1', 'Firefox', '#', 'Firefox', null, null, null, '0');
INSERT INTO `s_menu` VALUES ('8', '7', 'Firefox15.0', '#', 'Firefox15.0', null, null, null, '0');
INSERT INTO `s_menu` VALUES ('9', '7', 'Firefox15.1', '#', 'Firefox15.1', null, null, null, '0');
INSERT INTO `s_menu` VALUES ('10', '1', '360瀏覽器', '#', '360瀏覽器', null, null, null, '0');
INSERT INTO `s_menu` VALUES ('11', '1', '搜狗瀏覽器', '#', '搜狗瀏覽器', null, null, null, '0');
接下來把解壓好的dtree.js以及dtree.css放到項目的對應(yīng)目錄下,并在頁面引入,后臺執(zhí)行方法我就不說了,就是查詢出s_menu里所有的數(shù)據(jù)就可以了,在jsp里面實現(xiàn):
<%@ page contentType="text/html;charset=UTF-8" %>
<%@ include file="/common/taglibs.jsp" %>
<%@ page import="org.springframework.context.ApplicationContext,org.springframework.context.support.ClassPathXmlApplicationContext,com.zx.ww.entity.base.Menu,com.zx.ww.service.base.MenuManager,java.util.List" %>
<%
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
MenuManager menuManager = (MenuManager)context.getBean("menuManager");
List<Menu> menus = menuManager.findAllMenu();
request.setAttribute("menus", menus);
%>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>SSH2</title>
</head>
<body>
<table width="100%" height="100%" border="0" cellspacing="0" cellpadding="0">
<tr>
<td valign="top">
<div id="treearea" style="overflow: scroll;height:100%;width:100%"></div>
</td>
</tr>
</table>
</body>
</html>
<script type="text/javascript">
var dtree = new dTree('dtree', '${ctx}/images/dtree/');
dtree.config.folderLinks = true;
dtree.config.useCookies = true;
<c:forEach items="${menus}" var="menu">
dtree.add(${menu.id},${menu.pid},"${menu.name}","${menu.url}","${menu.title}");
</c:forEach>
document.getElementById('treearea').innerHTML = dtree;
</script>
看效果:

這是從數(shù)據(jù)庫里讀出數(shù)據(jù)的方式,本地的話構(gòu)建這樣的數(shù)據(jù)就行了:
<script type="text/javascript">
<!--
d = new dTree('d');
d.add(0,-1,'My example tree');
d.add(1,0,'Node 1','example01.html');
d.add(2,0,'Node 2','example01.html');
d.add(3,1,'Node 1.1','example01.html');
d.add(4,0,'Node 3','example01.html');
d.add(5,3,'Node 1.1.1','example01.html');
d.add(6,5,'Node 1.1.1.1','example01.html');
d.add(7,0,'Node 4','example01.html');
d.add(8,1,'Node 1.2','example01.html');
d.add(9,0,'My Pictures','example01.html','Pictures I\'ve taken over the years','','','img/imgfolder.gif');
d.add(10,9,'The trip to Iceland','example01.html','Pictures of Gullfoss and Geysir');
d.add(11,9,'Mom\'s birthday','example01.html');
d.add(12,0,'Recycle Bin','example01.html','','','img/trash.gif');
document.write(d);
//-->
</script>
網(wǎng)上有很多關(guān)于dtree的說明,在此看不明白的再去網(wǎng)上找找別的,有說的比較詳細(xì)的PPT,關(guān)于各個參數(shù)以及方法說明都有~
ok,留著以后會有用的!
posted @
2014-05-30 17:46 小人物_Amor 閱讀(1270) |
評論 (0) |
編輯 收藏