十三天學(xué)會(huì)java第十三天-網(wǎng)絡(luò)編程與設(shè)計(jì)模式_第1頁(yè)
十三天學(xué)會(huì)java第十三天-網(wǎng)絡(luò)編程與設(shè)計(jì)模式_第2頁(yè)
十三天學(xué)會(huì)java第十三天-網(wǎng)絡(luò)編程與設(shè)計(jì)模式_第3頁(yè)
十三天學(xué)會(huì)java第十三天-網(wǎng)絡(luò)編程與設(shè)計(jì)模式_第4頁(yè)
十三天學(xué)會(huì)java第十三天-網(wǎng)絡(luò)編程與設(shè)計(jì)模式_第5頁(yè)
已閱讀5頁(yè),還剩48頁(yè)未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說(shuō)明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡(jiǎn)介

十三天學(xué)會(huì)java第十三天-網(wǎng)絡(luò)編程與設(shè)計(jì)模式分類:

十三天java2013-05-1823:33

53人閱讀

評(píng)論(0)

\o"收藏"收藏

\o"舉報(bào)"舉報(bào)行業(yè)數(shù)據(jù)服務(wù)器Java目錄\o"系統(tǒng)根據(jù)文章中H1到H6標(biāo)簽自動(dòng)生成文章目錄"(?)\o"展開"[+]聲明:此java系列筆記編輯整理于魔樂網(wǎng),原網(wǎng)頁(yè)有視頻同步(如果還有的話)./3.1、網(wǎng)絡(luò)編程(了解)

網(wǎng)絡(luò)編程指的就是通過(guò)網(wǎng)絡(luò)進(jìn)行程序數(shù)據(jù)操作,既然是網(wǎng)絡(luò)開發(fā),那么一定就分為用戶和服務(wù)兩端,而這兩個(gè)端的開發(fā)實(shí)際上就有以下的兩種不同的架構(gòu)(面試題:請(qǐng)解釋C/S和B/S的區(qū)別?):·

C/S(Client/Server):要開發(fā)兩套程序,一套是服務(wù)器端,另外一套是與之對(duì)應(yīng)的客戶端,但是這種程序在日后進(jìn)行維護(hù)的時(shí)候,是需要維護(hù)兩套程序,而且客戶端的程序更新也必須及時(shí),此類程序安全;·

B/S(Browser/Server):要開發(fā)一套程序,只開發(fā)服務(wù)器端的,客戶端使用瀏覽器進(jìn)行訪問(wèn),這種程序在日后進(jìn)行程序維護(hù)的時(shí)候只需要維護(hù)服務(wù)器端即可,客戶端不需要做任何的修改,此類程序使用公共端口,包括公共協(xié)議,所以安全性很差。

如果從網(wǎng)絡(luò)的開發(fā)而言,大的分類是以上的兩類,可是從現(xiàn)在的開發(fā)來(lái)講,更多的情況是針對(duì)于B/S程序進(jìn)行的開發(fā),或者可以這么理解:B/S程序的開發(fā)屬于網(wǎng)絡(luò)時(shí)代,而C/S程序的開發(fā)屬于單機(jī)時(shí)代。而對(duì)于WebService的開發(fā),實(shí)話而言,也屬于B/S結(jié)構(gòu)的程序(跨平臺(tái))。

而在日后學(xué)習(xí)Android開發(fā)的時(shí)候,如果要考慮安全性使用Socket,如果要考慮方便性,還是基于WEB的開發(fā)方便使用。而對(duì)于網(wǎng)絡(luò)的開發(fā)在Java中也分為兩種:TCP(傳輸控制協(xié)議,可靠的傳輸)、UDP(數(shù)據(jù)報(bào)協(xié)議),對(duì)于網(wǎng)絡(luò)開發(fā),本次只專注于TCP程序的實(shí)現(xiàn)。3.2、網(wǎng)絡(luò)程序的基本實(shí)現(xiàn)(了解)

如果要進(jìn)行網(wǎng)絡(luò)程序的開發(fā),那么首先應(yīng)該開發(fā)出的就是服務(wù)器端,本次的操作使用服務(wù)器端向客戶端輸出一個(gè)“HelloWorld.”的字符串信息,而如果要想完成服務(wù)器端的開發(fā),則需要包中的兩個(gè)類:

·

ServerSocket類:是一個(gè)封裝支持TCP協(xié)議的操作類,主要工作在服務(wù)器端,用于接收客戶端請(qǐng)求;

·

Socket類:也是一個(gè)封裝了TCP協(xié)議的操作類,每一個(gè)Socket對(duì)象都表示一個(gè)客戶端。

而現(xiàn)在必須觀察這兩個(gè)類之中的操作方法:

·

ServerSocket類的方法:No.方法名稱類型描述1publicServerSocket(intport)throwsIOException構(gòu)造開辟一個(gè)指定的端口監(jiān)聽,一般使用5000以上2publicSocketaccept()throwsIOException普通服務(wù)器端接收客戶端請(qǐng)求,通過(guò)Socket返回3publicvoidclose()throwsIOException普通關(guān)閉服務(wù)器端

·

Socket類的方法:No.方法名稱類型描述1publicSocket(Stringhost,intport)throwsUnknownHostException,IOException構(gòu)造指定要連接的主機(jī)(IP地址)和端口2publicOutputStreamgetOutputStream()throwsIOException普通取得指定客戶端的輸出對(duì)象,使用的時(shí)候肯定使用PrintStream裝飾操作3publicInputStreamgetInputStream()throwsIOException普通從指定的客戶端讀取數(shù)據(jù),使用Scanner操作范例:完成一個(gè)服務(wù)器端程序代碼package

demo;import

java.io.PrintStream;import

.ServerSocket;import

.Socket;public

class

HelloServer{

public

static

void

main(String[]args)

throws

Exception{

ServerSocketserver=

new

ServerSocket(9999);

//

在9999端口監(jiān)聽

System.out.println("服務(wù)開始啟動(dòng)...");

Socketclient=server.accept();

//

接收客戶端連接,進(jìn)入到阻塞狀態(tài)

PrintStreamout=

new

PrintStream(client.getOutputStream());

out.println("HelloWorld.");

//

向客戶端輸出

out.close();

//

輸出流的關(guān)閉

client.close();

//

關(guān)閉客戶端

server.close();

//

關(guān)閉服務(wù)器端

System.out.println("服務(wù)器已關(guān)閉...");

}}

現(xiàn)在服務(wù)器端已經(jīng)開發(fā)完成了,而現(xiàn)在的服務(wù)器端雖然是通過(guò)Java編寫的,但是使用的是TCP協(xié)議,所以可以利用系統(tǒng)命令的telnet進(jìn)行訪問(wèn)。

·

使用運(yùn)行方式輸入:telnet;

·

連接服務(wù)器:openip地址

端口,openlocalhost9999;

但是現(xiàn)在是利用了系統(tǒng)的工具完成的,那么在開發(fā)之中是不可能使用這工具,應(yīng)該自己去編寫客戶端。范例:編寫一個(gè)客戶端package

demo;import

.Socket;import

java.util.Scanner;public

class

HelloClient{

public

static

void

main(String[]args)

throws

Exception{

Socketclient=

new

Socket("localhost",9999);

Scannerscan=

new

Scanner(client.getInputStream());

scan.useDelimiter("\n");

if

(scan.hasNext()){

//

有數(shù)據(jù)

System.out.println("服務(wù)器的回應(yīng)數(shù)據(jù):"

+scan.next());

}

scan.close();

client.close();

}}

整個(gè)的操作就是一個(gè)輸出和輸入的過(guò)程,只是現(xiàn)在的輸出和輸入的來(lái)源在于網(wǎng)絡(luò),而不是像之前那樣是通過(guò)文件操作了。3.3、網(wǎng)絡(luò)開發(fā)的經(jīng)典模型

——

ECHO程序

這種開發(fā)模型的典型模式指的是客戶端要輸入信息,而后服務(wù)器端接收這端信息之后,前面增加一個(gè)“ECHO:”的信息再返回給客戶端,也就是說(shuō)現(xiàn)在的服務(wù)器端需要輸入和輸出數(shù)據(jù)。范例:編寫一個(gè)程序的基本模型package

demo;import

java.io.PrintStream;import

.ServerSocket;import

.Socket;import

java.util.Scanner;public

class

EchoServer{

public

static

void

main(String[]args)

throws

Exception{

ServerSocketserver=

new

ServerSocket(9999);

boolean

flag=

true;

System.out.println("服務(wù)器運(yùn)行...");

Socketclient=server.accept();

//

接收客戶端請(qǐng)求

Scanner

scan

=

new

Scanner(client.getInputStream());

PrintStreamout=

new

PrintStream(client.getOutputStream());

while

(flag){

if

(scan.hasNext()){

//

有內(nèi)容

Stringstr=scan.next();

if

("byebye".equalsIgnoreCase(str.trim())){

//

程序結(jié)束

out.println("ByeBye...");

flag=

false;

//

退出循環(huán)

}

out.println("ECHO:"

+str.trim());

//

回應(yīng)數(shù)據(jù)

}

}

System.out.println("服務(wù)器停止運(yùn)行...");

server.close();

}}

這個(gè)時(shí)候程序?qū)嶋H上是一種單線程的運(yùn)行狀態(tài),這樣的程序運(yùn)行起來(lái)只能夠?yàn)橐粋€(gè)用戶進(jìn)行服務(wù),所以如果希望一個(gè)服務(wù)器可以同時(shí)處理多個(gè)客戶的操作,那么就必須為其實(shí)現(xiàn)多線程的處理機(jī)制,讓每一個(gè)客戶端表示一個(gè)獨(dú)立的線程對(duì)象,每個(gè)線程對(duì)象有自己獨(dú)立的輸入輸出操作。范例:為服務(wù)器端增加多線程機(jī)制,使用匿名內(nèi)部類package

demo;import

java.io.IOException;import

java.io.PrintStream;import

.ServerSocket;import

.Socket;import

java.util.Scanner;public

class

EchoServer{

public

static

void

main(String[]args)

throws

Exception{

ServerSocketserver=

new

ServerSocket(9999);

boolean

flag=

true;

System.out.println("服務(wù)器運(yùn)行...");

while

(flag){

final

Socketclient=server.accept();

//

接收客戶端請(qǐng)求

new

Thread(new

Runnable(){

@Override

public

void

run(){

boolean

runFlag=

true;

try

{

Scanner

scan

=

new

Scanner(client.getInputStream());

PrintStreamout=

new

PrintStream(client.getOutputStream());

while

(runFlag){

if

(scan.hasNext()){

//

有內(nèi)容

Stringstr=scan.next();

if

("byebye".equalsIgnoreCase(str.trim())){

//

程序結(jié)束

out.println("ByeBye...");

runFlag=

false;

//

退出循環(huán)

}

out.println("ECHO:"

+str.trim());

//

回應(yīng)數(shù)據(jù)

}

}

}

catch

(IOExceptione){

e.printStackTrace();

}

try

{

client.close();

}

catch

(IOExceptione){

e.printStackTrace();

}

}

}).start();

}

System.out.println("服務(wù)器停止運(yùn)行...");

server.close();

}}

但是,在這個(gè)時(shí)候?qū)τ诰€程的控制也需要處理好,如果處理不好,可能就出現(xiàn)死鎖問(wèn)題了。4、總結(jié)

知道什么叫網(wǎng)絡(luò)編程就行了,暫時(shí)用不到。3、具體內(nèi)容

之前的所有內(nèi)容都在本處進(jìn)行總結(jié),而且對(duì)于之前的一些概念不清楚的東西(代碼會(huì)寫)那么都可以不用去看了,把本次程序弄會(huì)了,一切就都會(huì)了,后面也就都會(huì)了。3.1、程序分層(理解)

在一個(gè)完整的項(xiàng)目之中,對(duì)程序進(jìn)行合理的分層,可以讓開發(fā)變得更加的方便,也更加的具備層次感,每一層有每一層的開發(fā)人員,例如:可以簡(jiǎn)單的理解為美工

+

程序相分離。而實(shí)際上的分層操作,可以這樣參考:

如果按照含金量來(lái)講,首先把握住業(yè)務(wù)層是整個(gè)程序的實(shí)現(xiàn)關(guān)鍵,但是對(duì)于前臺(tái)顯示更加的重要。今天的主要任務(wù)是觀察業(yè)務(wù)層和數(shù)據(jù)層的開發(fā),而到了JavaWEB之后,才開始實(shí)現(xiàn)顯示層和控制層的開發(fā)。

在項(xiàng)目之中后臺(tái)的建立直接有著重要的地位,但是不同層之間最為重要的連接組成部分就是接口,所以整個(gè)代碼開發(fā)之中,對(duì)于后臺(tái)代碼就一定要有兩個(gè)組成接口(業(yè)務(wù)層接口,給以后的控制層使用、數(shù)據(jù)層接口,給以后的業(yè)務(wù)層使用)。

·

數(shù)據(jù)層(數(shù)據(jù)訪問(wèn)層,DataAccessObject):指的是執(zhí)行數(shù)據(jù)的具體操作,而現(xiàn)在的開發(fā)之中,大多數(shù)都是針對(duì)于數(shù)據(jù)庫(kù)的開發(fā),所以在數(shù)據(jù)層之中的主要任務(wù)是負(fù)責(zé)完成數(shù)據(jù)的CRUD,而在java之中,如果要想進(jìn)行數(shù)據(jù)的CRUD實(shí)現(xiàn),肯定使用java.sql.PreparedStatement接口;

·

業(yè)務(wù)層(業(yè)務(wù)對(duì)象,BusinessObject,BO,又或者將其稱為Service,服務(wù)層),服務(wù)層的主要目的是根據(jù)業(yè)務(wù)需求進(jìn)行數(shù)據(jù)層的操作,一個(gè)業(yè)務(wù)層要包含多個(gè)數(shù)據(jù)層的操作。

清楚了基本概念之后,那么新的問(wèn)題就該出現(xiàn)了,如何去區(qū)分業(yè)務(wù)層或者是數(shù)據(jù)層?下面以玉史先生吃飯為例,說(shuō)明一下。

如果說(shuō)現(xiàn)在某一個(gè)項(xiàng)目業(yè)務(wù)非常復(fù)雜,可能分為若干個(gè)子業(yè)務(wù),那么就還需要一個(gè)總的業(yè)務(wù)層操作。3.2、實(shí)例分析(重點(diǎn))

下面以emp數(shù)據(jù)表(empno、ename、job、hiredate、sal、comm,都是基本字段)為例分析一個(gè)操作,客戶要求可以實(shí)現(xiàn)如下的幾個(gè)功能:

·

【業(yè)務(wù)層】增加一個(gè)新雇員信息;

|-

〖數(shù)據(jù)層〗要根據(jù)增加的雇員編號(hào)查看此雇員是否存在;

|-

〖數(shù)據(jù)層〗如果雇員不存在則執(zhí)行插入操作,如果存在則不插入;

·

【業(yè)務(wù)層】修改一個(gè)雇員的信息;

|-

〖數(shù)據(jù)層〗直接傳入新的數(shù)據(jù)即可,如果沒有修改返回的更新行數(shù)是0;

·

【業(yè)務(wù)層】刪除一個(gè)雇員的信息;

|-

〖數(shù)據(jù)層〗直接傳入要?jiǎng)h除的雇員編號(hào)即可,如果沒有此雇員信息返回的是0;

·

【業(yè)務(wù)層】根據(jù)編號(hào)查詢一個(gè)雇員的信息;

|-

〖數(shù)據(jù)層〗返回一個(gè)雇員的完整信息;·

【業(yè)務(wù)層】取得全部雇員的信息,要求可以實(shí)現(xiàn)模糊查詢和分頁(yè)顯示,查詢結(jié)果除了返回?cái)?shù)據(jù)之外,還要求知道模糊或全部查詢時(shí)所返回的全部數(shù)據(jù)量:

|-

〖數(shù)據(jù)層〗模糊或查詢?nèi)繚M足條件的雇員數(shù)據(jù),多個(gè)數(shù)據(jù);

|-

〖數(shù)據(jù)層〗使用COUNT()進(jìn)行滿足條件的數(shù)據(jù)統(tǒng)計(jì)。

3.3、準(zhǔn)備階段(重點(diǎn))3.3.1

、VO類:負(fù)責(zé)數(shù)據(jù)的傳輸與包裝

但是現(xiàn)在有一個(gè)最為嚴(yán)重的問(wèn)題出現(xiàn)了,不同層之間(這些層除了數(shù)據(jù)層要操作SQL之外,那么其他層操作的數(shù)據(jù)都應(yīng)該是對(duì)象),所以應(yīng)該有一個(gè)負(fù)責(zé)傳輸?shù)臄?shù)據(jù)對(duì)象,這個(gè)對(duì)象可以稱為ValueObject(VO,POJO、TO、PO)。

但是,現(xiàn)在對(duì)于簡(jiǎn)單Java類的開發(fā)原則也發(fā)生了一些變化:

·

類名稱要和表名稱保持一致;

·

為了日后類的操作方便,所有的簡(jiǎn)單Java類必須實(shí)現(xiàn)java.io.Serializable接口;

·

類中不允許出現(xiàn)任何的基本數(shù)據(jù)類型,只能使用包裝類;

·

類之中的所有屬性都必須封裝,必須都編寫setter、getter;

·

類之中一定要提供有無(wú)參構(gòu)造方法。

在DAO的開發(fā)之中,所有的名稱都有嚴(yán)格規(guī)定,假設(shè)現(xiàn)在的項(xiàng)目的總包名稱為:cn.mldn.oracle,那么現(xiàn)在這個(gè)VO類的保存包名稱就應(yīng)該是cn.mldn.oracle.vo。范例:定義cn.mldn.oracle.vo.Emp類package

cn.mldn.oracle.vo;import

java.io.Serializable;import

java.util.Date;@SuppressWarnings("serial")public

class

Emp

implements

Serializable{

private

Integer

empno

;

private

String

ename

;

private

String

job

;

private

Date

hiredate

;

private

Double

sal

;

private

Double

comm

;

//setter、getter略,自己補(bǔ)充}3.3.2

、DatabaseConnection類:負(fù)責(zé)數(shù)據(jù)庫(kù)連接

既然現(xiàn)在要完成數(shù)據(jù)層的開發(fā),那么就一定需要數(shù)據(jù)庫(kù)的連接與關(guān)閉操作,可是如果將數(shù)據(jù)庫(kù)的連接和關(guān)閉都寫在每一個(gè)數(shù)據(jù)層之中,這樣代碼過(guò)于重復(fù),而且也不方便維護(hù),那么為了方便起見,現(xiàn)在定義一個(gè)DatabaseConnection的類,這個(gè)類專門負(fù)責(zé)取得和關(guān)閉數(shù)據(jù)庫(kù)連接。而這個(gè)類定義在cn.mldn.oracle.dbc包之中。范例:定義cn.mldn.oracle.dbc.DatabaseConnectionpackage

cn.mldn.oracle.dbc;import

java.sql.Connection;import

java.sql.DriverManager;import

java.sql.SQLException;/**

*

本類的主要功能是負(fù)責(zé)數(shù)據(jù)庫(kù)的連接與關(guān)閉的

*

@author

MLDN

*/public

class

DatabaseConnection{

private

static

final

String

DBDRIVER

=

"oracle.jdbc.driver.OracleDriver"

;

private

static

final

String

DBURL

=

"jdbc:oracle:thin:@localhost:1521:MLDN"

;

private

static

final

String

DBUSER

=

"scott"

;

private

static

final

String

PASSWORD

=

"tiger"

;

private

Connection

conn

=

null

;

//

保存連接對(duì)象

/**

*

構(gòu)造方法的主要目的是進(jìn)行數(shù)據(jù)庫(kù)連接,只要在程序之中實(shí)例化了DatabaseConnection對(duì)象

*

那么就表示要進(jìn)行數(shù)據(jù)庫(kù)的連接操作了,所以在構(gòu)造方法之中連接數(shù)據(jù)庫(kù)

*

在本構(gòu)造方法之中,如果出現(xiàn)了異常,將直接輸出異常信息,因?yàn)槿绻麛?shù)據(jù)庫(kù)連接都沒有了,根本就無(wú)法操作

*/

public

DatabaseConnection(){

try

{

Class.forName(DBDRIVER);

this.conn

=DriverManager.getConnection(DBURL,

DBUSER,

PASSWORD);

}

catch

(Exceptione){

e.printStackTrace();

}

}

/**

*

取得一個(gè)數(shù)據(jù)庫(kù)連接對(duì)象,這個(gè)對(duì)象在構(gòu)造方法中取得

*

@return

Connection接口對(duì)象

*/

public

ConnectiongetConnection(){

return

this.conn

;

}

/**

*

關(guān)閉連接,不管是否連接上,執(zhí)行此操作都不會(huì)出錯(cuò)

*/

public

void

close(){

if

(this.conn

!=

null){

//

取得了連接

try

{

//

關(guān)閉連接

this.conn.close();

}

catch

(SQLExceptione){

e.printStackTrace();

}

}

}}

如果在實(shí)際的工作之中,按照DAO最早提出的標(biāo)準(zhǔn),對(duì)于數(shù)據(jù)層的實(shí)現(xiàn)類還需要實(shí)現(xiàn)數(shù)據(jù)庫(kù)的移植操作。即:對(duì)于數(shù)據(jù)庫(kù)連接類應(yīng)該變?yōu)橐粋€(gè)專門負(fù)責(zé)連接的接口,就好象以下的形式一樣:public

interface

DatabaseConnection{

public

ConnectiongetConnection();

public

void

close();}

而后如果一個(gè)項(xiàng)目可能在Oracle或DB2下運(yùn)行,那么針對(duì)于這兩種數(shù)據(jù)庫(kù)分別定義一個(gè)接口實(shí)現(xiàn)類,以對(duì)應(yīng)兩個(gè)不同的數(shù)據(jù)庫(kù)連接。但是這種開發(fā)已經(jīng)和現(xiàn)在的模式有些出入了,而且特別的麻煩,所以在本次為了和日后的開發(fā)可以更好的聯(lián)系在一起,只是定義了一個(gè)類而已。3.4、開發(fā)數(shù)據(jù)層(重點(diǎn))3.4.1

、定義IEmpDAO接口:數(shù)據(jù)層開發(fā)標(biāo)準(zhǔn)

不同層之間的操作依靠的是接口,所以數(shù)據(jù)層的開發(fā)首先要定義出來(lái)的就是標(biāo)準(zhǔn)。那么既然是標(biāo)準(zhǔn)就需要定義的是一個(gè)接口,現(xiàn)在很明顯針對(duì)的是emp表,所以這個(gè)接口的名稱就應(yīng)該為“表名稱DAO”,即:EmpDAO,但是這里有一個(gè)問(wèn)題了,接口和類的命名要求是一致的,所以為了從名稱上區(qū)分出接口或者是類,則建議在接口名稱前增加一個(gè)字母“I”,表示Interface的含義,即:emp這張實(shí)體表的操作標(biāo)準(zhǔn)的接口名稱為:IEmpDAO,而且這個(gè)接口應(yīng)該保存在cn.mldn.oracle.dao包之中。

那么對(duì)于這個(gè)接口的開發(fā)主要是針對(duì)于數(shù)據(jù)的兩種操作(更新、查詢),所以從開發(fā)標(biāo)準(zhǔn)上對(duì)于命名也有著嚴(yán)格的要求,而且必須遵守,基本標(biāo)準(zhǔn)如下:

·

更新操作:以“doXxx()”的方式命名,例如:doCreate()、doUpdate()、doRemvoe();

·

查詢操作,因?yàn)椴樵儾僮鞣譃閮深悾?/p>

|-

數(shù)據(jù)查詢:以“findXxx()”或“findByXxx()”為主,例如:findAll()、findById()、findByJob();

|-

統(tǒng)計(jì)查詢:以“getXxx()”或“getByXxx()”為主,例如:getAllCount()、getByJobCount()。范例:編寫IEmpDAO接口的操作標(biāo)準(zhǔn)package

cn.mldn.oracle.dao;import

java.util.List;import

cn.mldn.oracle.vo.Emp;public

interface

IEmpDAO{

/**

*

執(zhí)行數(shù)據(jù)的增加操作

*

@param

vo

包含所要增加的數(shù)據(jù)的VO對(duì)象

*

@return

如果增加數(shù)據(jù)成功返回true,否則返回false

*

@throws

Exception

操作之中出現(xiàn)了異常,返回給被調(diào)用處執(zhí)行處理

*/

public

boolean

doCreate(Empvo)

throws

Exception;

/**

*

執(zhí)行數(shù)據(jù)的更新操作

*

@param

vo

包含了新數(shù)據(jù)的VO對(duì)象

*

@return

如果修改成功返回true,否則返回false

*

@throws

Exception

操作之中出現(xiàn)了異常,返回給被調(diào)用處執(zhí)行處理

*/

public

boolean

doUpdate(Empvo)

throws

Exception;

/**

*

刪除一個(gè)雇員的信息

*

@param

id

要?jiǎng)h除的雇員編號(hào)

*

@return

如果刪除成功返回true,否則返回false

*

@throws

Exception

操作之中出現(xiàn)了異常,返回給被調(diào)用處執(zhí)行處理

*/

public

boolean

doRemove(int

id)

throws

Exception;

/**

*

根據(jù)雇員編號(hào)查詢一個(gè)雇員的完整信息

*

@param

id

要查詢的雇員編號(hào)

*

@return

如果沒有指定的雇員編號(hào),返回值為null,<br>

*

如果有指定的雇員信息,則將所有的雇員信息包裝到Emp實(shí)例化對(duì)象之中返回。

*

@throws

Exception

操作之中出現(xiàn)了異常,返回給被調(diào)用處執(zhí)行處理

*/

public

EmpfindById(int

id)

throws

Exception;

/**

*

查詢?nèi)康墓蛦T信息

*

@return

多個(gè)雇員信息使用List返回,如果List集合的size()長(zhǎng)度為0,則表示沒有數(shù)據(jù)返回

*

@throws

Exception

操作之中出現(xiàn)了異常,返回給被調(diào)用處執(zhí)行處理

*/

public

List<Emp>findAll()

throws

Exception;

/**

*

分頁(yè)顯示所有雇員的信息,同時(shí)可以完成模糊查詢

*

@param

column

要模糊查詢的字段名稱

*

@param

keyWord

要模糊查詢的數(shù)據(jù),如果為空字符串(isEmpty()判斷為true,表示空字符串),則表示查詢?nèi)?/p>

*

@param

currentPage

當(dāng)前所在的頁(yè)

*

@param

lineSize

沒頁(yè)顯示的記錄長(zhǎng)度

*

@return

多個(gè)雇員信息使用List返回,如果List集合的size()長(zhǎng)度為0,則表示沒有數(shù)據(jù)返回

*

@throws

Exception

操作之中出現(xiàn)了異常,返回給被調(diào)用處執(zhí)行處理

*/

public

List<Emp>findAll(Stringcolumn,StringkeyWord,

int

currentPage,

int

lineSize)

throws

Exception;

/**

*

統(tǒng)計(jì)模糊查詢的數(shù)據(jù)結(jié)果,使用COUNT()函數(shù)進(jìn)行統(tǒng)計(jì)

*

@param

column

要模糊查詢的字段名稱

*

@param

keyWord

要模糊查詢的數(shù)據(jù),如果為空字符串(isEmpty()判斷為true,表示空字符串),則表示查詢?nèi)?/p>

*

@return

會(huì)根據(jù)數(shù)據(jù)量的多少返回?cái)?shù)據(jù)的長(zhǎng)度,如果沒有數(shù)據(jù)返回0

*

@throws

Exception

操作之中出現(xiàn)了異常,返回給被調(diào)用處執(zhí)行處理

*/

public

int

getAllCount(Stringcolumn,StringkeyWord)

throws

Exception;}

現(xiàn)在開發(fā)的標(biāo)準(zhǔn)只是滿足于程序需求的提出需要。3.4.2

、定義IEmpDAO接口的實(shí)現(xiàn)類

既然在接口中已經(jīng)定義了數(shù)據(jù)層的操作標(biāo)準(zhǔn),那么對(duì)于實(shí)現(xiàn)類只需要遵循數(shù)據(jù)層的CRUD操作即可,但是對(duì)于DAO接口的實(shí)現(xiàn)類需要有明確的定義,要求將其定義在:cn.mldn.oracle.dao.impl包之中。

范例:定義EmpDAOImpl子類

·

現(xiàn)在有如下一種的子類實(shí)現(xiàn)接口方式:

@Override

public

boolean

doCreate(Empvo)

throws

Exception{

DatabaseConnectiondbc=

new

DatabaseConnection();

Stringsql=

"INSERTINTOemp(empno,ename,job,hiredate,sal,comm)VALUES(?,?,?,?,?,?)";

PreparedStatementpstmt=dbc.getConnection().prepareStatement(sql);

pstmt.setInt(1,vo.getEmpno());

pstmt.setString(2,vo.getEname());

pstmt.setString(3,vo.getJob());

pstmt.setDate(4,

new

java.sql.Date(vo.getHiredate().getTime()));

pstmt.setDouble(5,vo.getSal());

pstmt.setDouble(6,vo.getComm());

if

(pstmt.executeUpdate()>0){

return

true

;

}

dbc.close();

return

false;

}

如果真的按照這種方式實(shí)現(xiàn)的程序,有兩個(gè)重要問(wèn)題:·

對(duì)于數(shù)據(jù)層之中給出的若干方法,由服務(wù)層調(diào)用,一個(gè)服務(wù)層要執(zhí)行N個(gè)數(shù)據(jù)層,那么每次執(zhí)行的時(shí)候打開一次關(guān)閉一次數(shù)據(jù)庫(kù)?·

按照異常的處理機(jī)制,如果現(xiàn)在執(zhí)行的過(guò)程之中出現(xiàn)了錯(cuò)誤,那么順著throws就結(jié)束調(diào)用了,數(shù)據(jù)庫(kù)就再也無(wú)法關(guān)閉了。

按照之前的分析,一個(gè)業(yè)務(wù)要進(jìn)行多個(gè)數(shù)據(jù)層操作,所以數(shù)據(jù)庫(kù)連接與關(guān)閉交給業(yè)務(wù)層做最合適,而數(shù)據(jù)層只需要有一個(gè)Connection對(duì)象就可以操作了,它不需要關(guān)心這個(gè)對(duì)象是從那里來(lái)的,怎么來(lái)的,只關(guān)心能不能使用。package

cn.mldn.oracle.dao.impl;import

java.sql.Connection;import

java.sql.PreparedStatement;import

java.sql.ResultSet;import

java.util.ArrayList;import

java.util.List;import

cn.mldn.oracle.dao.IEmpDAO;import

cn.mldn.oracle.vo.Emp;public

class

EmpDAOImpl

implements

IEmpDAO{

private

Connection

conn;

private

PreparedStatement

pstmt;

public

EmpDAOImpl(Connectionconn){

this.conn

=conn;

}

@Override

public

boolean

doCreate(Empvo)

throws

Exception{

Stringsql=

"INSERTINTOemp(empno,ename,job,hiredate,sal,comm)VALUES(?,?,?,?,?,?)";

this.pstmt

=

this.conn.prepareStatement(sql);

this.pstmt.setInt(1,vo.getEmpno());

this.pstmt.setString(2,vo.getEname());

this.pstmt.setString(3,vo.getJob());

this.pstmt.setDate(4,

new

java.sql.Date(vo.getHiredate().getTime()));

this.pstmt.setDouble(5,vo.getSal());

this.pstmt.setDouble(6,vo.getComm());

if

(this.pstmt.executeUpdate()>0){

return

true;

}

return

false;

}

@Override

public

boolean

doUpdate(Empvo)

throws

Exception{

Stringsql=

"UPDATEempSETename=?,job=?,hiredate=?,sal=?,comm=?WHEREempno=?";

this.pstmt

=

this.conn.prepareStatement(sql);

this.pstmt.setString(1,vo.getEname());

this.pstmt.setString(2,vo.getJob());

this.pstmt.setDate(3,

new

java.sql.Date(vo.getHiredate().getTime()));

this.pstmt.setDouble(4,vo.getSal());

this.pstmt.setDouble(5,vo.getComm());

this.pstmt.setInt(6,vo.getEmpno());

if

(this.pstmt.executeUpdate()>0){

return

true;

}

return

false;

}

@Override

public

boolean

doRemove(int

id)

throws

Exception{

Stringsql=

"DELETEFROMempWHEREempno=?";

this.pstmt

=

this.conn.prepareStatement(sql);

this.pstmt.setInt(1,id);

if

(this.pstmt.executeUpdate()>0){

return

true;

}

return

false;

}

@Override

public

EmpfindById(int

id)

throws

Exception{

Empemp=

null;

Stringsql=

"SELECTempno,ename,job,hiredate,sal,commFROMempWHEREempno=?";

this.pstmt

=

this.conn.prepareStatement(sql);

this.pstmt.setInt(1,id);

ResultSetrs=

this.pstmt.executeQuery();

if

(rs.next()){

emp=

new

Emp();

emp.setEmpno(rs.getInt(1));

emp.setEname(rs.getString(2));

emp.setJob(rs.getString(3));

emp.setHiredate(rs.getDate(4));

emp.setSal(rs.getDouble(5));

emp.setComm(rs.getDouble(6));

}

return

emp;

}

@Override

public

List<Emp>findAll()

throws

Exception{

List<Emp>all=

new

ArrayList<Emp>();

Stringsql=

"SELECTempno,ename,job,hiredate,sal,commFROMemp";

this.pstmt

=

this.conn.prepareStatement(sql);

ResultSetrs=

this.pstmt.executeQuery();

while

(rs.next()){

Empemp=

new

Emp();

emp.setEmpno(rs.getInt(1));

emp.setEname(rs.getString(2));

emp.setJob(rs.getString(3));

emp.setHiredate(rs.getDate(4));

emp.setSal(rs.getDouble(5));

emp.setComm(rs.getDouble(6));

all.add(emp);

}

return

all;

}

@Override

public

List<Emp>findAll(Stringcolumn,StringkeyWord,

int

currentPage,

int

lineSize)

throws

Exception{

List<Emp>all=

new

ArrayList<Emp>();

Stringsql=

"SELECT*FROM("

+

"SELECTempno,ename,job,hiredate,sal,comm,ROWNUMrnFROMempWHERE"

+column+

"LIKE?ANDROWNUM<=?)temp"

+

"WHEREtemp.rn>?";

this.pstmt

=

this.conn.prepareStatement(sql);

this.pstmt.setString(1,

"%"

+keyWord+

"%");

this.pstmt.setInt(2,currentPage*lineSize);

this.pstmt.setInt(3,(current1)*lineSize);

ResultSetrs=

this.pstmt.executeQuery();

while

(rs.next()){

Empemp=

new

Emp();

emp.setEmpno(rs.getInt(1));

emp.setEname(rs.getString(2));

emp.setJob(rs.getString(3));

emp.setHiredate(rs.getDate(4));

emp.setSal(rs.getDouble(5));

emp.setComm(rs.getDouble(6));

all.add(emp);

}

return

all;

}

@Override

public

int

getAllCount(Stringcolumn,StringkeyWord)

throws

Exception{

Stringsql=

"SELECTCOUNT(empno)FROMempWHERE"

+column+

"LIKE?";

this.pstmt

=

this.conn.prepareStatement(sql);

this.pstmt.setString(1,

"%"

+keyWord+

"%");

ResultSetrs=

this.pstmt.executeQuery();

if

(rs.next()){

return

rs.getInt(1);

}

return

0;

}}3.4.3

、定義DAO工廠類

由于不同層之間只能依靠接口取得對(duì)象,所以就一定需要定義工廠操作類,工廠類定義在cn.mldn.oracle.factory包之中,名稱為DAOFactory。范例:定義工廠類package

cn.mldn.oracle.factory;import

java.sql.Connection;import

cn.mldn.oracle.dao.IEmpDAO;import

cn.mldn.oracle.dao.impl.EmpDAOImpl;public

class

DAOFactory{

public

static

IEmpDAOgetIEmpDAOInstance(Connectionconn){

return

new

EmpDAOImpl(conn);

}}3.5、開發(fā)業(yè)務(wù)層(重點(diǎn))3.5.1

、開發(fā)業(yè)務(wù)層標(biāo)準(zhǔn)

業(yè)務(wù)層以后也是需要留給其他層進(jìn)行調(diào)用的,所以業(yè)務(wù)層定義的時(shí)候也需要首先定義出操作標(biāo)準(zhǔn),而這個(gè)標(biāo)準(zhǔn)也依然使用接口完成,對(duì)于業(yè)務(wù)層,接口命名要求:表名稱

+Service,例如:IEmpService,表示操作Emp表的業(yè)務(wù)。范例:在cn.mldn.oracle.service包中定義IEmpService接口package

cn.mldn.oracle.service;import

java.util.Map;import

cn.mldn.oracle.vo.Emp;public

interface

IEmpService{

/**

*

調(diào)用數(shù)據(jù)庫(kù)的增加操作,操作流程如下:<br>

*

<li>首先要使用IEmpDAO接口中的findById()方法,根據(jù)要增加的id查看指定的雇員信息是否存在;

*

<li>如果要增加的雇員信息不存在,則執(zhí)行IEmpDAO接口的doCreate()方法,并將結(jié)果返回;

*

@param

vo

包裝數(shù)據(jù)的對(duì)象

*

@return

如果增加成功,返回true,如果雇員編號(hào)存在或者是增加失敗,返回false

*

@throws

Exception

有異常交給被調(diào)用處處理

*/

public

boolean

insert(Empvo)

throws

Exception;

/**

*

執(zhí)行數(shù)據(jù)的更新操作,操作的時(shí)候直接調(diào)用IEmpDAO接口的doUpdate()方法,并將更新結(jié)果返回

*

@param

vo

包裝數(shù)據(jù)的對(duì)象

*

@return

如果修改成功,返回true,如果數(shù)據(jù)不存在或修改失敗,返回false

*

@throws

Exception

有異常交給被調(diào)用處處理

*/

public

boolean

update(Empvo)

throws

Exception;

/**

*

執(zhí)行數(shù)據(jù)的刪除操作,刪除操作的時(shí)候調(diào)用IEmpDAO接口的doRemove()方法

*

@param

id

要?jiǎng)h除雇員的id

*

@return

如果刪除成功,返回true,如果數(shù)據(jù)不存在或刪除失敗,則返回false

*

@throws

Exception

有異常交給被調(diào)用處處理

*/

public

boolean

delete(int

id)

throws

Exception;

/**

*

根據(jù)雇員的編號(hào)取得全部的信息

*

@param

id

雇員編號(hào)

*

@return

如果雇員存在則將數(shù)據(jù)包裝為Emp對(duì)象返回,如果數(shù)據(jù)不存在則返回null

*

@throws

Exception

有異常交給被調(diào)用處處理

*/

public

Empget(int

id)

throws

Exception;

/**

*

查詢?nèi)炕蛘呤悄:樵內(nèi)繑?shù)據(jù),查詢的同時(shí)可以返回滿足此查詢的數(shù)據(jù)量,在調(diào)用的時(shí)候需要執(zhí)行以下操作:<br>

*

<li>查詢?nèi)康墓蛦T信息:需要IEmpDAO接口的findAll()方法;

*

<li>查詢滿足條件的雇員數(shù)量:使用IEmpDAO接口的getAllCount()方法操作;

*

@param

column

模糊查詢的字段

*

@param

keyWord

模糊查詢的關(guān)鍵字

*

@param

currentPage

當(dāng)前所在頁(yè)

*

@param

lineSize

每頁(yè)顯示的數(shù)據(jù)長(zhǎng)度

*

@return

由于在進(jìn)行數(shù)據(jù)返回的時(shí)候,此方法要返回兩類數(shù)據(jù):List<Emp>、int,使用Map返回:<br>

*

<li>返回值1:key=allEmps,value=findAll();

*

<li>返回值2:key=empCount,value=getAllCount();

*

@throws

Exception

有異常交給被調(diào)用處處理

*/

public

Map<String,Object>list(Stringcolumn,StringkeyWord,

int

currentPage,

int

lineSize)

throws

Exception;}3.5.2

、定義業(yè)務(wù)層標(biāo)準(zhǔn)的實(shí)現(xiàn)類

如果現(xiàn)在要想實(shí)現(xiàn)業(yè)務(wù)層的標(biāo)準(zhǔn),必須有一個(gè)原則先把握?。阂粋€(gè)業(yè)務(wù)層的方法操作要調(diào)用多個(gè)數(shù)據(jù)層,同時(shí)每個(gè)業(yè)務(wù)要處理數(shù)據(jù)庫(kù)的打開和關(guān)閉。范例:定義標(biāo)準(zhǔn)實(shí)現(xiàn)類

——

cn.mldn.oracle.service.impl.EmpServiceImplpackage

cn.mldn.oracle.service.impl;import

java.sql.Connection;import

java.util.HashMap;import

java.util.Map;import

cn.mldn.oracle.dao.IEmpDAO;import

cn.mldn.oracle.dbc.DatabaseConnection;import

cn.mldn.oracle.factory.DAOFactory;import

cn.mldn.oracle.service.IEmpService;import

cn.mldn.oracle.vo.Emp;public

class

EmpServiceImpl

implements

IEmpService{

private

DatabaseConnection

dbc

=

new

DatabaseConnection();

@Override

public

boolean

insert(Empvo)

throws

Exception{

try

{

Connectionconn=

this.dbc.getConnection();

//

取得連接

IEmpDAOdao=DAOFactory.getIEmpDAOInstance(conn);

//

取得DAO接口對(duì)象

if

(dao.findById(vo.getEmpno())==

null){

//

沒有要查詢的雇員信息

return

dao.doCreate(vo);

//

返回DAO的結(jié)果

}

return

false;

//

數(shù)據(jù)存在,直接返回false

}

catch

(Exceptione){

throw

e;

}

finally

{

this.dbc.close();

}

}

@Override

public

boolean

update(Empvo)

throws

Exception{

try

{

return

DAOFactory.getIEmpDAOInstance(this.dbc.getConnection())

.doUpdate(vo);

}

catch

(Exceptione){

throw

e;

}

finally

{

this.dbc.close();

}

}

@Override

public

boolean

delete(int

id)

throws

Exception{

try

{

return

DAOFactory.getIEmpDAOInstance(this.dbc.getConnection())

.doRemove(id);

}

catch

(Exceptione){

throw

e;

}

finally

{

this.dbc.close();

}

}

@Override

public

Empget(int

id)

throws

Exception{

try

{

return

DAOFactory.getIEmpDAOInstance(this.dbc.getConnection())

.findById(id);

}

catch

(Exceptione){

throw

e;

}

finally

{

this.dbc.close();

}

}

@Override

public

Map<String,Object>list(Stringcolumn,StringkeyWord,

int

currentPage,

int

lineSize)

throws

Exception{

try

{

Map<String,Object>map=

new

HashMap<String,Object>();

map.put("allEmps",

DAOFactory.getIEmpDAOInstance(this.dbc.getConnection())

.findAll(column,keyWord,currentPage,lineSize));

map.put("empCount",

DAOFactory.getIEmpDAOInstance(this.dbc.getConnection())

.getAllCount(column,keyWord));

return

map;

}

catch

(Exceptione){

throw

e;

}

finally

{

this.dbc.close();

}

}}3.5.3

、定義Service工廠類

如果要取得IEmpService接口對(duì)象,一定也需要使用工廠類,避免耦合問(wèn)題。范例:定義cn.mldn.oracle.factory.ServiceFactory工廠類package

cn.mldn.oracle.factory;import

cn.mldn.oracle.service.IEmpService;import

cn.mldn.oracle.service.impl.EmpServiceImpl;public

class

ServiceFactory{

public

static

IEmpServicegetIEmpServiceInstance(){

return

new

EmpServiceImpl();

}}3.6、定義測(cè)試類

一切的程序完成之后,下面就需要編寫測(cè)試程序,對(duì)于測(cè)試程序現(xiàn)在有兩種方法完成:

·

方式一:可以直接編寫主方法,自己根據(jù)它的返回值結(jié)果進(jìn)行判斷是否成功;

·

方式二:利用JUNIT完成,這樣的做法標(biāo)準(zhǔn),而且也方便日后調(diào)試。

如果要使用JUNIT則就需要建立一個(gè)個(gè)的TestCase(測(cè)試用例),而且現(xiàn)在再進(jìn)行測(cè)試的時(shí)候,應(yīng)該首先選擇的是服務(wù)層接口,因?yàn)檫x擇不是針對(duì)于接口測(cè)試,而是針對(duì)于方法測(cè)試,方法就可以不用自己去編寫了。范例:編寫測(cè)試程序類package

cn.mldn.oracle.test;import

java.util.Date;import

java.util.Iterator;import

java.util.List;import

java.util.Map;import

junit.framework.TestCase;import

org.junit.Test;import

cn.mldn.oracle.factory.ServiceFactory;import

cn.mldn.oracle.vo.Emp;public

class

IEmpServiceTest{

@Test

public

void

testInsert(){

Empvo=

new

Emp();

vo.setEmpno(9988);

vo.setEname("張三");

vo.setJob("清潔工");

vo.setSal(300.0);

vo.setComm(200.0);

vo.setHiredate(new

Date());

try

{

TestCase.assertTrue(ServiceFactory.getIEmpServiceInstance().insert(

vo));

}

catch

(Exceptione){

e.printStackTrace();

}

}

@Test

public

void

testUpdate(){

Empvo=

new

Emp();

vo.setEmpno(8888);

vo.setEname("張三");

vo.setJob("清潔工");

vo.setSal(1000.0);

vo.setComm(600.0);

vo.setHiredate(new

Date());

try

{

TestCase.assertTrue(ServiceFactory.getIEmpServiceInstance().update(

vo));

}

catch

(Exceptione){

e.printStackTrace();

}

}

@Test

public

void

testDelete(){

try

{

TestCase.assertTrue(ServiceFactory.getIEmpServiceInstance()

.delete(8888));

}

catch

(Exceptione){

e.printStackTrace();

}

}

@Test

public

void

testGet(){

try

{

Empvo=ServiceFactory.getIEmpServiceInstance().get(7369);

TestCase.assertNotNull(vo);

System.out.println(vo.getEname());

}

catch

(Exceptione){

e.printStackTrace();

}

}

@Test

public

void

testList(){

try

{

Map<String,Object>map=ServiceFactory.getIEmpServiceInstance()

.list("ename",

"",1,5);

TestCase.assertNotNull(map);

System.out.println("總記錄數(shù):"

+map.get("empCount"));

@SuppressWarnings("unchecked")

List<Emp>all=(List<Emp>)map.get("allEmps");

Iterator<Emp>iter=all.iterator();

while

(iter.hasNext()){

Empemp=iter.next();

System.out.println(emp.getEname()+

","

+emp.getJob());

}

}

catch

(Exceptione){

溫馨提示

  • 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。

最新文檔

評(píng)論

0/150

提交評(píng)論