Bean的中文含義是“豆子”,顧名思義Java Bean是一段Java小程序。Java Bean實(shí)際上是指一種特殊的Java類,它通常用來實(shí)現(xiàn)一些比較常用的簡單功能,并可以很容易的被重用或者是插入其他應(yīng)用程序中去。所有遵循一定編程原則的Java類都可以被稱作Java Bean。本章將由淺入深介紹Java Bean的設(shè)計(jì)原理及應(yīng)用方式,并重點(diǎn)介紹Java Bean在JSP中的應(yīng)用。
17.1? Java Bean技術(shù)概述
Java Bean是基于Java的組件模型,由屬性、方法和事件3部分組成。在該模型中,Java Bean可以被修改或與其他組件結(jié)合以生成新組件或完整的程序。它是一種Java類,通過封裝成為具有某種功能或者處理某個(gè)業(yè)務(wù)的對象。因此,也可以通過嵌在JSP頁面內(nèi)的Java代碼訪問Bean及其屬性。
Bean的含義是可重復(fù)使用的Java組件。所謂組件就是一個(gè)由可以自行進(jìn)行內(nèi)部管理的一個(gè)或幾個(gè)類所組成、外界不了解其內(nèi)部信息和運(yùn)行方式的群體。使用它的對象只能通過接口來操作。
17.2? Java Bean編寫規(guī)范
Java Bean實(shí)際上是根據(jù)Java Bean技術(shù)標(biāo)準(zhǔn)所指定Bean的命名和設(shè)計(jì)規(guī)范編寫的Java類。這些類遵循一個(gè)接口格式,以便于使函數(shù)命名、底層行為以及繼承或?qū)崿F(xiàn)的行為,其最大的優(yōu)點(diǎn)在于可以實(shí)現(xiàn)代碼的可重用性。Bean并不需要繼承特別的基類(Base Class)或?qū)崿F(xiàn)特定的接口(Interface)。Bean的編寫規(guī)范使Bean的容器(Container)能夠分析一個(gè)Java類文件,并將其方法(Methods)翻譯成屬性(Properties),即把Java類作為一個(gè)Bean類使用。Bean的編寫規(guī)范包括Bean類的構(gòu)造方法、定義屬性和訪問方法編寫規(guī)則。
17.2.1? Bean組件的工作機(jī)制
在JavaBeans Version1.01 A規(guī)范中定義了該組件的5種重要機(jī)制:
內(nèi)省(Introspection):組建可以發(fā)表其支持的操作和屬性,同時(shí)也支持在其他組件中發(fā)現(xiàn)重復(fù)利用的對象庫,如用戶權(quán)限控制和電子郵件自動(dòng)回復(fù)等。
通信(Communication):生成和收集組件的消息事件。
持續(xù)(Persistence):存放組件的狀態(tài)。
屬性 (Properties):支持組件布局的控制,包括組件占用的空間和組件的相對位置。
定制(Customization):開發(fā)者可控制組件所需的改變機(jī)制。
17.2.2? Java Bean的編寫要求
編寫Java Bean必須滿足以下幾點(diǎn)要求:
所有的Java Bean必須放在一個(gè)包(Package)中。
Java Bean必須生成public class類,文件名稱應(yīng)該與類名稱一致。
所有屬性必須封裝,一個(gè)Java Bean類不應(yīng)有公共實(shí)例變量,類變量都為private。
屬性值應(yīng)該通過一組存取方法(getXxx 和 setXxx)來訪問:對于每個(gè)屬性,應(yīng)該有一個(gè)帶匹配公用 getter 和 setter 方法的專用實(shí)例變量。
Java Bean 類必須有一個(gè)空的構(gòu)造函數(shù):類中必須有一個(gè)不帶參數(shù)的公用構(gòu)造器,此構(gòu)造器也應(yīng)該通過調(diào)用各個(gè)屬性的設(shè)置方法來設(shè)置屬性的默認(rèn)值。
17.2.3? Java Bean的命名規(guī)范
Java Bean的命名規(guī)范如下:
包命名:全部字母小寫。
類命名:每個(gè)單詞首字母大寫。
屬性名:第一個(gè)單詞全部小寫,之后每個(gè)單詞首字母大寫。
方法名:與屬性命名方法相同。
常量名:全部字母大寫。
17.2.4? Java Bean的包
包即package在本書前面的章節(jié)中已經(jīng)有過介紹,Java Bean的包和前面章節(jié)中介紹的包含義基本上是一樣的,但是也有區(qū)別,前面介紹的包都是Java本身定義的,而Java Bean的包是用戶自己定義的。
每一個(gè)Java Bean源文件被編譯成.class文件后,都必須存放在相應(yīng)的文件夾下,存放這個(gè).class文件的文件夾就是一個(gè)包。Java Bean的包必須存放在特定的目錄下,在每個(gè)JSP引擎中都規(guī)定了存放Java Bean包的位置,不同的JSP引擎對Java Bean存放的位置有不同的規(guī)定,如在本書第16章介紹的Tomcat軟件中,Java Bean的所有包都存放在WEB-INF/classes文件夾中。如果存在多級目錄,則需要將.class文件所在目錄的所有上級目錄包含到包名稱中,每一級目錄之間用英文標(biāo)點(diǎn)“.”隔開。例如下面代碼:
package jsp.example.mybean;
17.2.5? Java Bean的結(jié)構(gòu)
代碼是一個(gè)典型的Java Bean實(shí)例,我們用它來說明Java Bean的結(jié)構(gòu)。
屬性:即Java Bean類的成員變量,用于描述Java Bean對象的狀態(tài),對象屬性值的改變觸發(fā)事件,屬性本身就是事件源。
方法:在 Java Bean中,函數(shù)和過程統(tǒng)稱為方法,通過方法來改變和獲取屬性的值。方法可以分為構(gòu)造方法、訪問方法和普通方法等。
事件:事件實(shí)際上是一種特殊的Java Bean,屬性值的改變觸發(fā)事件,事件激發(fā)相關(guān)對象作出反應(yīng),通過Java Bean注冊對象事件監(jiān)聽者機(jī)制來接收、處理事件,它實(shí)現(xiàn)了Java Bean之間的通信。
17.3? Java Bean屬性
在上一節(jié)中我們簡單提到了Java Bean的屬性,Java Bean的屬性與一般Java程序中所指的屬性,或者說與所有面向?qū)ο蟮某绦蛟O(shè)計(jì)語言中對象的屬性是一個(gè)概念,在程序中的具體體現(xiàn)就是類中的變量。屬性分為四類,即單值(Simple)、索引(Index)、關(guān)聯(lián)(Bound)和約束(Constrained)屬性。本節(jié)將對這些屬性進(jìn)行詳細(xì)說明。
17.3.1? 單值(Simple)屬性
單值(Simple)屬性是最普通的屬性類型,該類屬性只有一個(gè)單一的數(shù)據(jù)值,該數(shù)據(jù)值的數(shù)據(jù)類型可以是Java中的任意數(shù)據(jù)類型,包括類和接口等類型。
定義了屬性,還需定義對應(yīng)的訪問方法,一般每個(gè)單值屬性都伴隨有一對get/set 方法。屬性名與和該屬性相關(guān)的get/set方法名對應(yīng)。例如如果有一個(gè)名為“xxx”的屬性,則會(huì)有setXxx和getXxx方法。
另外,布爾(Boolean)屬性是一種特殊的單值屬性,它只有兩個(gè)允許值:true和false,如果有一個(gè)名為“xxx”的布爾屬性,則可以通過isX方法訪問。
在上一節(jié)的代碼實(shí)例中所有的屬性都是簡單屬性,get、set和is等方法就是對這些簡單屬性的訪問方法,關(guān)于訪問方法,將在17.4.2小節(jié)中介紹。
17.3.2? 索引(Indexed)屬性
如果需要定義一批同類型的屬性,使用單值屬性就會(huì)顯得非常煩瑣,為解決此問題,Java Bean中提供了索引(Indexed) 屬性,索引屬性是指Java Bean中數(shù)組類型的成員變量。使用與該屬性對應(yīng)的set/get方法可取得數(shù)組的值。索引屬性通過對應(yīng)的訪問方法設(shè)置或取得該屬性中某個(gè)元素的值,也可以一次設(shè)置或取得整個(gè)屬性的值。
17.3.3? 關(guān)聯(lián)(Bound)屬性
關(guān)聯(lián)(Bound)屬性是指當(dāng)該種屬性的值發(fā)生變化時(shí),要通知其他的對象。每次屬性值改變時(shí),這種屬性就觸發(fā)一個(gè)PropertyChange事件(在Java程序中,事件也是一個(gè)對象,事件將在17.5節(jié)詳細(xì)介紹)。事件中封裝了屬性名、屬性的原值、屬性變化后的新值。這種事件傳遞到其他的Beans,至于接收事件的Beans應(yīng)做什么動(dòng)作,由其自己定義。
屬性的改變稱為Java Bean事件。外部與Java Bean這些事件相關(guān)的類對象稱為監(jiān)聽者(Listener)。監(jiān)聽者可能只對Java Bean某一屬性相關(guān)的事件有興趣,也可能對所有屬性相關(guān)的事件有興趣,因此Java Bean提供兩類事件監(jiān)聽者注冊和注銷的方法,即全局事件監(jiān)聽者注冊、注銷的方法和一般事件監(jiān)聽者注冊、注銷的方法。
17.3.4? 約束(Constrained)屬性
Java Bean的屬性如果改變時(shí),相關(guān)的外部類對象首先要檢查這個(gè)屬性改變的合理性再?zèng)Q定是否接受這種改變,這樣的Java Bean屬性叫約束(Constrained)屬性。當(dāng)約束屬性的改變被拒絕時(shí),改變約束屬性的方法產(chǎn)生一個(gè)約束屬性改變異常 (PropertyVetoException),通過這個(gè)異常處理,Java Bean約束屬性還原回原來的值,并為這個(gè)還原操作發(fā)送一個(gè)新的屬性修改通知。
約束屬性的改變可能會(huì)被拒絕,因此它的setXxx與一般其他 Java Bean屬性的setXxx也有所不同。約束屬性的寫方法如下:
public void setXxx(xxxType newXxx) throws PropertyVetoException
17.4? Java Bean方法
在前面17.2.5小節(jié)介紹Java Bean結(jié)構(gòu)時(shí),簡單地介紹了Java Bean方法,我們知道在Java Bean中的函數(shù)和過程統(tǒng)稱為方法,通過方法來改變和獲取17.3節(jié)中介紹的各種屬性值。方法可以分為構(gòu)造方法、訪問方法和普通方法等。本節(jié)將學(xué)習(xí)創(chuàng)建和使用這些方法。
17.4.1? 構(gòu)造方法
Java Bean的構(gòu)造方法與本書第8章介紹的累的構(gòu)造方法意思是一樣的,就是對Java Bean的屬性及其方法進(jìn)行初始化,即對所定義的屬性及方法設(shè)一個(gè)初始值,構(gòu)造方法名要和Java Bean的類名相同。下面的代碼定義的就是一個(gè)Java Bean及其構(gòu)造方法。
17.4.2? 訪問方法
在定義了Bean的屬性,并通過構(gòu)造方法將其初始化后,要讓其他程序訪問Bean的這些屬性,就必須為其創(chuàng)建訪問方法。訪問方法就是對組件中定義的屬性的訪問,包括讀和寫兩種訪問方式。讀就是一種用于取出Bean屬性的值的取值函數(shù),即getter;而寫則是一種用于設(shè)置Bean屬性的賦值函數(shù),即setter。以下列出的就是Bean屬性訪問方法的具體語法格式:
public void setPropertyName(PropertyType value);//給屬性賦值,即寫方法
public PropertyType getPropertyName();//讀取屬性值,即讀方法
17.4.3? 一般方法
除了對屬性的訪問方法外,還可以在Bean創(chuàng)建一般方法來實(shí)現(xiàn)對函數(shù)的調(diào)用,只要將Bean中的一般方法定義成公有的方法,就可以供其他程序調(diào)用。代碼是一個(gè)實(shí)現(xiàn)求階乘函數(shù)的一般方法。
代碼 Multiple.java
1 package jsp.examples.mybean;
2 public class Multiple{
3 public int Multi(int j){
4? int x = 1;
5? for (int i = 1; i <= j; ++i)
6? { x = x * i; }
7? return x;}
8 }
17.5? Java Bean事件
事件處理是JavaBeans體系結(jié)構(gòu)的核心之一。通過事件處理機(jī)制,可讓一些組件作為事件源,發(fā)出可被描述環(huán)境或其他組件接收的事件。這樣,不同的組件就可在構(gòu)造工具內(nèi)組合在一起,組件之間通過事件的傳遞進(jìn)行通信,構(gòu)成一個(gè)應(yīng)用。從概念上講,事件是一種在“源對象”和“監(jiān)聽者對象”之間某種狀態(tài)發(fā)生變化的傳遞機(jī)制。事件有許多不同的用途,例如在Windows系統(tǒng)中常要處理的鼠標(biāo)事件、窗口邊界改變事件、鍵盤事件等。
17.5.1? 事件模型
Java Bean事件模型如圖所示,事件源是一個(gè)JavaBean類對象,它把屬性改變的時(shí)間對象傳遞給事件監(jiān)聽者,事件監(jiān)聽者負(fù)責(zé)事件的處理。事件監(jiān)聽者必須在事件源注冊。
17.5.2? 事件狀態(tài)對象
與事件發(fā)生有關(guān)的狀態(tài)信息一般都封裝在事件狀態(tài)對象 (Event State Object) 中,這種對象是java.util.EventObject的子類。按設(shè)計(jì)習(xí)慣,這種事件狀態(tài)對象類的名應(yīng)以Event結(jié)尾。例如代碼是一個(gè)鼠標(biāo)移動(dòng)事件實(shí)例。
17.5.3? 事件監(jiān)聽者接口與事件監(jiān)聽者
由于Java事件模型是基于方法調(diào)用的,因此需要一個(gè)定義并組織事件操縱方法的方式。 JavaBeans中,事件操縱方法都被定義在繼承了java.util.EventListener類的事件監(jiān)聽者(EventListener)接口中,按規(guī)定,EventListener接口的命名要以Listener結(jié)尾。任何一個(gè)類如果想操縱在EventListener接口中,定義的方法都必須以實(shí)現(xiàn)這個(gè)接口方式進(jìn)行。這個(gè)類就是事件監(jiān)聽者。例如如下代碼。
//先定義了一個(gè)鼠標(biāo)移動(dòng)事件對象
public class MouseMovedExampleEvent extends java.util.EventObject {
// 在此類中包含了與鼠標(biāo)移動(dòng)事件有關(guān)的狀態(tài)信息
...
}
//定義了鼠標(biāo)移動(dòng)事件的監(jiān)聽者接口
interface MouseMovedExampleListener extends java.util.EventListener {
//在這個(gè)接口中定義了鼠標(biāo)移動(dòng)事件監(jiān)聽者所應(yīng)支持的方法
void mouseMoved(MouseMovedExampleEvent mme);
}
17.5.4? 事件監(jiān)聽者注冊與注銷
為了讓各種可能的事件監(jiān)聽者把自己注冊入合適的事件源中,就建立源與事件監(jiān)聽者間的事件流,事件源必須為事件監(jiān)聽者提供注冊和注銷的方法。在前面第17.3節(jié)關(guān)聯(lián)屬性和約束屬性的介紹中,已看到了這種使用過程,在實(shí)際中,事件監(jiān)聽者的注冊和注銷要使用以下標(biāo)準(zhǔn)的設(shè)計(jì)格式:
public void add< ListenerType>(< ListenerType> listener);
public void remove< ListenerType>(< ListenerType> listener);
下面是一個(gè)具體的實(shí)例,首先定義了一個(gè)事件監(jiān)聽者接口:
import java.util.*;
public interface ModelChangedListener extends EventListener
{ void modelChanged(EventObject e);}
17.5.5? 適配類
適配類是Java事件模型中極其重要的一部分。在一些應(yīng)用場合,事件從源到監(jiān)聽者之間的傳遞要通過適配類來“轉(zhuǎn)發(fā)”。例如:當(dāng)事件源發(fā)出一個(gè)事件,而有幾個(gè)事件監(jiān)聽者對象都可接收該事件,但只有指定對象做出反應(yīng)時(shí),就要在事件源與事件監(jiān)聽者之間插入一個(gè)事件適配器類,由適配器類來指定事件應(yīng)該是由哪些監(jiān)聽者來響應(yīng)。適配類成為了事件監(jiān)聽者,事件源實(shí)際是把適配類作為監(jiān)聽者注冊入監(jiān)聽者隊(duì)列中,而真正的事件響應(yīng)者并未在監(jiān)聽者隊(duì)列中,事件響應(yīng)者應(yīng)做的動(dòng)作由適配類決定。目前絕大多數(shù)的開發(fā)工具在生成代碼時(shí),事件處理都是通過適配類來進(jìn)行的。
17.6? Java Bean在JSP中的應(yīng)用
在前面幾節(jié)我們學(xué)習(xí)了Java Bean的編寫,由于Java Bean是為了重復(fù)使用的程序段落,具有“Write once, run anywhere, reuse everywhere”,即“一次性編寫,任何地方執(zhí)行,所有地方可重用”的特點(diǎn),所以可以為JSP平臺(tái)提供一個(gè)簡單的、緊湊的和優(yōu)秀的問題解決方案,能大幅度提高系統(tǒng)的功能上限、加快執(zhí)行速度,而且不需要犧牲系統(tǒng)的性能。同時(shí),采用JavaBean技術(shù)可以使系統(tǒng)更易于維護(hù),因此極大地提高了JSP的應(yīng)用范圍。本節(jié)將詳細(xì)學(xué)習(xí)如何在JSP中應(yīng)用Bean組件。
17.6.1? 調(diào)用Java Bean
在上一章16.6.2節(jié)中介紹了通過JSP標(biāo)記中的<jsp:useBean>動(dòng)作來調(diào)用Java Bean,下面我們在學(xué)習(xí)完Java Bean的編寫之后,再來復(fù)習(xí)一下這個(gè)標(biāo)記:
<jsp:useBean id="beanId" scope="page|request|session|application" class="package.class" />
首先,我們通過標(biāo)記中的id屬性標(biāo)記Bean,以使JSP頁面的其余部分可以正確的識(shí)別該Bean。
其次,使用scope屬性來確定該Bean的使用范圍。scope屬性所決定的使用范圍,可以參考我們在上一章第16.7.10小節(jié)中所作的介紹。
最后,class屬性通知JSP頁面從何處查找Bean,即找到Bean的.class文件。在此我們必須同時(shí)指定 JavaBean的包(package)名和類(class)名,即class="package.class",否則JSP引擎將無法找到相應(yīng)的 Bean。
17.6.2? 鏈接數(shù)據(jù)庫Bean
在第10章中我們學(xué)習(xí)了通過JDBC鏈接數(shù)據(jù)庫以及在數(shù)據(jù)庫中進(jìn)行數(shù)據(jù)的查詢、修改、插入和刪除等操作。在JSP的應(yīng)用中,數(shù)據(jù)庫的運(yùn)用有著十分重要的地位,可以說數(shù)據(jù)庫的運(yùn)用是JSP應(yīng)用的關(guān)鍵之一。在數(shù)據(jù)庫的運(yùn)用中我們可以發(fā)現(xiàn),在數(shù)據(jù)庫相關(guān)程序中,這些操作都有很多相似之處,許多語句都是通用的。在學(xué)習(xí)了Java Bean之后,我們很自然的就想到是否可以將這些語句編寫到一個(gè)Java Bean中,這樣可以為以后編寫的數(shù)據(jù)庫程序提供極大的方便。
17.6.3? 通過Java Bean查詢數(shù)據(jù)庫
在前面的小節(jié)中,我們編寫了一個(gè)典型的鏈接數(shù)據(jù)庫Bean,在這一小節(jié)中,我們通過一個(gè)實(shí)例來學(xué)習(xí)JSP中如何通過這個(gè)Java Bean來訪問數(shù)據(jù)庫。
在此,我們先用Access數(shù)據(jù)庫軟件創(chuàng)建一個(gè)名為 AddressBook.mdb的數(shù)據(jù)庫,這個(gè)數(shù)據(jù)庫中有一個(gè)名為“user”的表。將這個(gè)數(shù)據(jù)庫設(shè)置成名為“JavaBeanTestDB”的系統(tǒng)數(shù)據(jù)源,具體的設(shè)置方法參考本書的第11章11.3.2小節(jié)中的詳細(xì)介紹。
本實(shí)例的目的是對數(shù)據(jù)庫中的user表進(jìn)行查詢、修改、插入和刪除操作。代碼17-11實(shí)現(xiàn)的是將user表中的用戶ID、用戶名以及用戶密碼顯示出來,并通過“添加”、“修改”和“刪除”按鈕分別鏈接到添加、修改和刪除記錄頁面。
17.6.4? 向數(shù)據(jù)庫添加記錄
在單擊圖中的“添加”按鈕后,將跳轉(zhuǎn)到添加記錄頁面,添加記錄頁面的源文件如代碼所示:
17.6.5? 修改數(shù)據(jù)庫記錄
在單擊17.6.3小節(jié)圖中的“修改”按鈕后,將跳轉(zhuǎn)到修改記錄頁面,該頁面實(shí)現(xiàn)對用戶密碼的修改,修改記錄頁面的源文件如代碼所示。
17.6.6? 刪除數(shù)據(jù)庫記錄
刪除數(shù)據(jù)庫記錄首先是建立數(shù)據(jù)庫鏈接,然后通過刪除選定的數(shù)據(jù)庫記錄字句執(zhí)行記錄,如果該記錄不存在則返回,如果存在則刪除該記錄。刪除數(shù)據(jù)庫記錄頁面的源文件如代碼所示。
17.7? 本章習(xí)題
(1)選擇題
說明:本章的選擇題中有單選題也有多選題,用于讀者檢查自己對本章中關(guān)鍵概念的掌握程度。
1.如果要編寫一個(gè)Bean,并將該Bean存放在WEB-INF/classes/jsp/example/mybean目錄下,則包(package)名稱是?
A.package mybean;?? B.package classes.jsp.example.mybean;
C.package jsp.example;? D.package jsp.example.mybean;
2.編寫一個(gè)Bean必須滿足哪幾點(diǎn)要求?
A.必須放在一個(gè)包(Package)中 B.必須生成public class類
C.必須有一個(gè)空的構(gòu)造函數(shù) D.所有屬性必須封裝
E.應(yīng)該通過一組存取方法來訪問
3.Java Bean中的屬性命名的規(guī)范是?
A.全部字母小寫??? B.每個(gè)單詞首字母大寫
C.第一個(gè)單詞全部小寫,之后每個(gè)單詞首字母大寫? D.全部字母大寫
4.在JSP中引用Bean應(yīng)該如何操作?
A.page指令 B.include指令 C.include動(dòng)作 D.useBean動(dòng)作
5.private int[] myInt;語句定義的是?
A.單值屬性 B.索引屬性 C.關(guān)聯(lián)屬性 D.約束屬性
6.在代碼17-10所生成的Bean中,close()方法執(zhí)行了哪些操作?
A.關(guān)閉數(shù)據(jù)集 B.關(guān)閉Statement對象
C.關(guān)閉數(shù)據(jù)鏈接 D.關(guān)閉數(shù)據(jù)庫驅(qū)動(dòng)
7.在useBean動(dòng)作中,應(yīng)該設(shè)置下面那些參數(shù)?
A.Id B.Scope C.Class D.name
8.Java Bean有幾種屬性?
A.4種 B.3種 C.2種 D.1種
9.Java Bean的方法可以分為幾種?
A.4種 B.3 種 C.2種 D.1種
10.在17.6.2小節(jié)的Bean實(shí)例中,如果數(shù)據(jù)源改變,需要設(shè)置哪幾種屬性的值?
A.rs屬性? B.url屬性
C.user屬性? D.password屬性
(2)程序閱讀題
指出下面Java Bean代碼中的錯(cuò)誤(共6處錯(cuò)誤):
package jsp.examples.mybean;
import java.beans.*;
public class Hello {??????? //類名,應(yīng)該與文件名相同
//定義屬性
String myStr;?
public Boolean myBool;
??? public hello() {?????
? myStr = "Hello Java Bean!";
? myBool = true;
??? }
//get方法
private String getMyStr()
{ return this.myStr;}
//set方法
public void setMyStr(String str)
{this.myStr = str;}
public Boolean setMyBool(Boolean bool)
{ this.myBool = bool; }
//is方法
public void isMyBool()
{ return this.myBool; }
}
(3)實(shí)際操作題
編寫一個(gè)用戶登注冊頁面,通過調(diào)用數(shù)據(jù)庫鏈接Bean將用戶輸入的注冊信息寫入數(shù)據(jù)庫,用戶注冊后轉(zhuǎn)到歡迎頁面,并顯示用戶信息。
17.1? Java Bean技術(shù)概述
Java Bean是基于Java的組件模型,由屬性、方法和事件3部分組成。在該模型中,Java Bean可以被修改或與其他組件結(jié)合以生成新組件或完整的程序。它是一種Java類,通過封裝成為具有某種功能或者處理某個(gè)業(yè)務(wù)的對象。因此,也可以通過嵌在JSP頁面內(nèi)的Java代碼訪問Bean及其屬性。
Bean的含義是可重復(fù)使用的Java組件。所謂組件就是一個(gè)由可以自行進(jìn)行內(nèi)部管理的一個(gè)或幾個(gè)類所組成、外界不了解其內(nèi)部信息和運(yùn)行方式的群體。使用它的對象只能通過接口來操作。
17.2? Java Bean編寫規(guī)范
Java Bean實(shí)際上是根據(jù)Java Bean技術(shù)標(biāo)準(zhǔn)所指定Bean的命名和設(shè)計(jì)規(guī)范編寫的Java類。這些類遵循一個(gè)接口格式,以便于使函數(shù)命名、底層行為以及繼承或?qū)崿F(xiàn)的行為,其最大的優(yōu)點(diǎn)在于可以實(shí)現(xiàn)代碼的可重用性。Bean并不需要繼承特別的基類(Base Class)或?qū)崿F(xiàn)特定的接口(Interface)。Bean的編寫規(guī)范使Bean的容器(Container)能夠分析一個(gè)Java類文件,并將其方法(Methods)翻譯成屬性(Properties),即把Java類作為一個(gè)Bean類使用。Bean的編寫規(guī)范包括Bean類的構(gòu)造方法、定義屬性和訪問方法編寫規(guī)則。
17.2.1? Bean組件的工作機(jī)制
在JavaBeans Version1.01 A規(guī)范中定義了該組件的5種重要機(jī)制:
內(nèi)省(Introspection):組建可以發(fā)表其支持的操作和屬性,同時(shí)也支持在其他組件中發(fā)現(xiàn)重復(fù)利用的對象庫,如用戶權(quán)限控制和電子郵件自動(dòng)回復(fù)等。
通信(Communication):生成和收集組件的消息事件。
持續(xù)(Persistence):存放組件的狀態(tài)。
屬性 (Properties):支持組件布局的控制,包括組件占用的空間和組件的相對位置。
定制(Customization):開發(fā)者可控制組件所需的改變機(jī)制。
17.2.2? Java Bean的編寫要求
編寫Java Bean必須滿足以下幾點(diǎn)要求:
所有的Java Bean必須放在一個(gè)包(Package)中。
Java Bean必須生成public class類,文件名稱應(yīng)該與類名稱一致。
所有屬性必須封裝,一個(gè)Java Bean類不應(yīng)有公共實(shí)例變量,類變量都為private。
屬性值應(yīng)該通過一組存取方法(getXxx 和 setXxx)來訪問:對于每個(gè)屬性,應(yīng)該有一個(gè)帶匹配公用 getter 和 setter 方法的專用實(shí)例變量。
Java Bean 類必須有一個(gè)空的構(gòu)造函數(shù):類中必須有一個(gè)不帶參數(shù)的公用構(gòu)造器,此構(gòu)造器也應(yīng)該通過調(diào)用各個(gè)屬性的設(shè)置方法來設(shè)置屬性的默認(rèn)值。
17.2.3? Java Bean的命名規(guī)范
Java Bean的命名規(guī)范如下:
包命名:全部字母小寫。
類命名:每個(gè)單詞首字母大寫。
屬性名:第一個(gè)單詞全部小寫,之后每個(gè)單詞首字母大寫。
方法名:與屬性命名方法相同。
常量名:全部字母大寫。
17.2.4? Java Bean的包
包即package在本書前面的章節(jié)中已經(jīng)有過介紹,Java Bean的包和前面章節(jié)中介紹的包含義基本上是一樣的,但是也有區(qū)別,前面介紹的包都是Java本身定義的,而Java Bean的包是用戶自己定義的。
每一個(gè)Java Bean源文件被編譯成.class文件后,都必須存放在相應(yīng)的文件夾下,存放這個(gè).class文件的文件夾就是一個(gè)包。Java Bean的包必須存放在特定的目錄下,在每個(gè)JSP引擎中都規(guī)定了存放Java Bean包的位置,不同的JSP引擎對Java Bean存放的位置有不同的規(guī)定,如在本書第16章介紹的Tomcat軟件中,Java Bean的所有包都存放在WEB-INF/classes文件夾中。如果存在多級目錄,則需要將.class文件所在目錄的所有上級目錄包含到包名稱中,每一級目錄之間用英文標(biāo)點(diǎn)“.”隔開。例如下面代碼:
package jsp.example.mybean;
17.2.5? Java Bean的結(jié)構(gòu)
代碼是一個(gè)典型的Java Bean實(shí)例,我們用它來說明Java Bean的結(jié)構(gòu)。
屬性:即Java Bean類的成員變量,用于描述Java Bean對象的狀態(tài),對象屬性值的改變觸發(fā)事件,屬性本身就是事件源。
方法:在 Java Bean中,函數(shù)和過程統(tǒng)稱為方法,通過方法來改變和獲取屬性的值。方法可以分為構(gòu)造方法、訪問方法和普通方法等。
事件:事件實(shí)際上是一種特殊的Java Bean,屬性值的改變觸發(fā)事件,事件激發(fā)相關(guān)對象作出反應(yīng),通過Java Bean注冊對象事件監(jiān)聽者機(jī)制來接收、處理事件,它實(shí)現(xiàn)了Java Bean之間的通信。
17.3? Java Bean屬性
在上一節(jié)中我們簡單提到了Java Bean的屬性,Java Bean的屬性與一般Java程序中所指的屬性,或者說與所有面向?qū)ο蟮某绦蛟O(shè)計(jì)語言中對象的屬性是一個(gè)概念,在程序中的具體體現(xiàn)就是類中的變量。屬性分為四類,即單值(Simple)、索引(Index)、關(guān)聯(lián)(Bound)和約束(Constrained)屬性。本節(jié)將對這些屬性進(jìn)行詳細(xì)說明。
17.3.1? 單值(Simple)屬性
單值(Simple)屬性是最普通的屬性類型,該類屬性只有一個(gè)單一的數(shù)據(jù)值,該數(shù)據(jù)值的數(shù)據(jù)類型可以是Java中的任意數(shù)據(jù)類型,包括類和接口等類型。
定義了屬性,還需定義對應(yīng)的訪問方法,一般每個(gè)單值屬性都伴隨有一對get/set 方法。屬性名與和該屬性相關(guān)的get/set方法名對應(yīng)。例如如果有一個(gè)名為“xxx”的屬性,則會(huì)有setXxx和getXxx方法。
另外,布爾(Boolean)屬性是一種特殊的單值屬性,它只有兩個(gè)允許值:true和false,如果有一個(gè)名為“xxx”的布爾屬性,則可以通過isX方法訪問。
在上一節(jié)的代碼實(shí)例中所有的屬性都是簡單屬性,get、set和is等方法就是對這些簡單屬性的訪問方法,關(guān)于訪問方法,將在17.4.2小節(jié)中介紹。
17.3.2? 索引(Indexed)屬性
如果需要定義一批同類型的屬性,使用單值屬性就會(huì)顯得非常煩瑣,為解決此問題,Java Bean中提供了索引(Indexed) 屬性,索引屬性是指Java Bean中數(shù)組類型的成員變量。使用與該屬性對應(yīng)的set/get方法可取得數(shù)組的值。索引屬性通過對應(yīng)的訪問方法設(shè)置或取得該屬性中某個(gè)元素的值,也可以一次設(shè)置或取得整個(gè)屬性的值。
17.3.3? 關(guān)聯(lián)(Bound)屬性
關(guān)聯(lián)(Bound)屬性是指當(dāng)該種屬性的值發(fā)生變化時(shí),要通知其他的對象。每次屬性值改變時(shí),這種屬性就觸發(fā)一個(gè)PropertyChange事件(在Java程序中,事件也是一個(gè)對象,事件將在17.5節(jié)詳細(xì)介紹)。事件中封裝了屬性名、屬性的原值、屬性變化后的新值。這種事件傳遞到其他的Beans,至于接收事件的Beans應(yīng)做什么動(dòng)作,由其自己定義。
屬性的改變稱為Java Bean事件。外部與Java Bean這些事件相關(guān)的類對象稱為監(jiān)聽者(Listener)。監(jiān)聽者可能只對Java Bean某一屬性相關(guān)的事件有興趣,也可能對所有屬性相關(guān)的事件有興趣,因此Java Bean提供兩類事件監(jiān)聽者注冊和注銷的方法,即全局事件監(jiān)聽者注冊、注銷的方法和一般事件監(jiān)聽者注冊、注銷的方法。
17.3.4? 約束(Constrained)屬性
Java Bean的屬性如果改變時(shí),相關(guān)的外部類對象首先要檢查這個(gè)屬性改變的合理性再?zèng)Q定是否接受這種改變,這樣的Java Bean屬性叫約束(Constrained)屬性。當(dāng)約束屬性的改變被拒絕時(shí),改變約束屬性的方法產(chǎn)生一個(gè)約束屬性改變異常 (PropertyVetoException),通過這個(gè)異常處理,Java Bean約束屬性還原回原來的值,并為這個(gè)還原操作發(fā)送一個(gè)新的屬性修改通知。
約束屬性的改變可能會(huì)被拒絕,因此它的setXxx與一般其他 Java Bean屬性的setXxx也有所不同。約束屬性的寫方法如下:
public void setXxx(xxxType newXxx) throws PropertyVetoException
17.4? Java Bean方法
在前面17.2.5小節(jié)介紹Java Bean結(jié)構(gòu)時(shí),簡單地介紹了Java Bean方法,我們知道在Java Bean中的函數(shù)和過程統(tǒng)稱為方法,通過方法來改變和獲取17.3節(jié)中介紹的各種屬性值。方法可以分為構(gòu)造方法、訪問方法和普通方法等。本節(jié)將學(xué)習(xí)創(chuàng)建和使用這些方法。
17.4.1? 構(gòu)造方法
Java Bean的構(gòu)造方法與本書第8章介紹的累的構(gòu)造方法意思是一樣的,就是對Java Bean的屬性及其方法進(jìn)行初始化,即對所定義的屬性及方法設(shè)一個(gè)初始值,構(gòu)造方法名要和Java Bean的類名相同。下面的代碼定義的就是一個(gè)Java Bean及其構(gòu)造方法。
17.4.2? 訪問方法
在定義了Bean的屬性,并通過構(gòu)造方法將其初始化后,要讓其他程序訪問Bean的這些屬性,就必須為其創(chuàng)建訪問方法。訪問方法就是對組件中定義的屬性的訪問,包括讀和寫兩種訪問方式。讀就是一種用于取出Bean屬性的值的取值函數(shù),即getter;而寫則是一種用于設(shè)置Bean屬性的賦值函數(shù),即setter。以下列出的就是Bean屬性訪問方法的具體語法格式:
public void setPropertyName(PropertyType value);//給屬性賦值,即寫方法
public PropertyType getPropertyName();//讀取屬性值,即讀方法
17.4.3? 一般方法
除了對屬性的訪問方法外,還可以在Bean創(chuàng)建一般方法來實(shí)現(xiàn)對函數(shù)的調(diào)用,只要將Bean中的一般方法定義成公有的方法,就可以供其他程序調(diào)用。代碼是一個(gè)實(shí)現(xiàn)求階乘函數(shù)的一般方法。
代碼 Multiple.java
1 package jsp.examples.mybean;
2 public class Multiple{
3 public int Multi(int j){
4? int x = 1;
5? for (int i = 1; i <= j; ++i)
6? { x = x * i; }
7? return x;}
8 }
17.5? Java Bean事件
事件處理是JavaBeans體系結(jié)構(gòu)的核心之一。通過事件處理機(jī)制,可讓一些組件作為事件源,發(fā)出可被描述環(huán)境或其他組件接收的事件。這樣,不同的組件就可在構(gòu)造工具內(nèi)組合在一起,組件之間通過事件的傳遞進(jìn)行通信,構(gòu)成一個(gè)應(yīng)用。從概念上講,事件是一種在“源對象”和“監(jiān)聽者對象”之間某種狀態(tài)發(fā)生變化的傳遞機(jī)制。事件有許多不同的用途,例如在Windows系統(tǒng)中常要處理的鼠標(biāo)事件、窗口邊界改變事件、鍵盤事件等。
17.5.1? 事件模型
Java Bean事件模型如圖所示,事件源是一個(gè)JavaBean類對象,它把屬性改變的時(shí)間對象傳遞給事件監(jiān)聽者,事件監(jiān)聽者負(fù)責(zé)事件的處理。事件監(jiān)聽者必須在事件源注冊。
17.5.2? 事件狀態(tài)對象
與事件發(fā)生有關(guān)的狀態(tài)信息一般都封裝在事件狀態(tài)對象 (Event State Object) 中,這種對象是java.util.EventObject的子類。按設(shè)計(jì)習(xí)慣,這種事件狀態(tài)對象類的名應(yīng)以Event結(jié)尾。例如代碼是一個(gè)鼠標(biāo)移動(dòng)事件實(shí)例。
17.5.3? 事件監(jiān)聽者接口與事件監(jiān)聽者
由于Java事件模型是基于方法調(diào)用的,因此需要一個(gè)定義并組織事件操縱方法的方式。 JavaBeans中,事件操縱方法都被定義在繼承了java.util.EventListener類的事件監(jiān)聽者(EventListener)接口中,按規(guī)定,EventListener接口的命名要以Listener結(jié)尾。任何一個(gè)類如果想操縱在EventListener接口中,定義的方法都必須以實(shí)現(xiàn)這個(gè)接口方式進(jìn)行。這個(gè)類就是事件監(jiān)聽者。例如如下代碼。
//先定義了一個(gè)鼠標(biāo)移動(dòng)事件對象
public class MouseMovedExampleEvent extends java.util.EventObject {
// 在此類中包含了與鼠標(biāo)移動(dòng)事件有關(guān)的狀態(tài)信息
...
}
//定義了鼠標(biāo)移動(dòng)事件的監(jiān)聽者接口
interface MouseMovedExampleListener extends java.util.EventListener {
//在這個(gè)接口中定義了鼠標(biāo)移動(dòng)事件監(jiān)聽者所應(yīng)支持的方法
void mouseMoved(MouseMovedExampleEvent mme);
}
17.5.4? 事件監(jiān)聽者注冊與注銷
為了讓各種可能的事件監(jiān)聽者把自己注冊入合適的事件源中,就建立源與事件監(jiān)聽者間的事件流,事件源必須為事件監(jiān)聽者提供注冊和注銷的方法。在前面第17.3節(jié)關(guān)聯(lián)屬性和約束屬性的介紹中,已看到了這種使用過程,在實(shí)際中,事件監(jiān)聽者的注冊和注銷要使用以下標(biāo)準(zhǔn)的設(shè)計(jì)格式:
public void add< ListenerType>(< ListenerType> listener);
public void remove< ListenerType>(< ListenerType> listener);
下面是一個(gè)具體的實(shí)例,首先定義了一個(gè)事件監(jiān)聽者接口:
import java.util.*;
public interface ModelChangedListener extends EventListener
{ void modelChanged(EventObject e);}
17.5.5? 適配類
適配類是Java事件模型中極其重要的一部分。在一些應(yīng)用場合,事件從源到監(jiān)聽者之間的傳遞要通過適配類來“轉(zhuǎn)發(fā)”。例如:當(dāng)事件源發(fā)出一個(gè)事件,而有幾個(gè)事件監(jiān)聽者對象都可接收該事件,但只有指定對象做出反應(yīng)時(shí),就要在事件源與事件監(jiān)聽者之間插入一個(gè)事件適配器類,由適配器類來指定事件應(yīng)該是由哪些監(jiān)聽者來響應(yīng)。適配類成為了事件監(jiān)聽者,事件源實(shí)際是把適配類作為監(jiān)聽者注冊入監(jiān)聽者隊(duì)列中,而真正的事件響應(yīng)者并未在監(jiān)聽者隊(duì)列中,事件響應(yīng)者應(yīng)做的動(dòng)作由適配類決定。目前絕大多數(shù)的開發(fā)工具在生成代碼時(shí),事件處理都是通過適配類來進(jìn)行的。
17.6? Java Bean在JSP中的應(yīng)用
在前面幾節(jié)我們學(xué)習(xí)了Java Bean的編寫,由于Java Bean是為了重復(fù)使用的程序段落,具有“Write once, run anywhere, reuse everywhere”,即“一次性編寫,任何地方執(zhí)行,所有地方可重用”的特點(diǎn),所以可以為JSP平臺(tái)提供一個(gè)簡單的、緊湊的和優(yōu)秀的問題解決方案,能大幅度提高系統(tǒng)的功能上限、加快執(zhí)行速度,而且不需要犧牲系統(tǒng)的性能。同時(shí),采用JavaBean技術(shù)可以使系統(tǒng)更易于維護(hù),因此極大地提高了JSP的應(yīng)用范圍。本節(jié)將詳細(xì)學(xué)習(xí)如何在JSP中應(yīng)用Bean組件。
17.6.1? 調(diào)用Java Bean
在上一章16.6.2節(jié)中介紹了通過JSP標(biāo)記中的<jsp:useBean>動(dòng)作來調(diào)用Java Bean,下面我們在學(xué)習(xí)完Java Bean的編寫之后,再來復(fù)習(xí)一下這個(gè)標(biāo)記:
<jsp:useBean id="beanId" scope="page|request|session|application" class="package.class" />
首先,我們通過標(biāo)記中的id屬性標(biāo)記Bean,以使JSP頁面的其余部分可以正確的識(shí)別該Bean。
其次,使用scope屬性來確定該Bean的使用范圍。scope屬性所決定的使用范圍,可以參考我們在上一章第16.7.10小節(jié)中所作的介紹。
最后,class屬性通知JSP頁面從何處查找Bean,即找到Bean的.class文件。在此我們必須同時(shí)指定 JavaBean的包(package)名和類(class)名,即class="package.class",否則JSP引擎將無法找到相應(yīng)的 Bean。
17.6.2? 鏈接數(shù)據(jù)庫Bean
在第10章中我們學(xué)習(xí)了通過JDBC鏈接數(shù)據(jù)庫以及在數(shù)據(jù)庫中進(jìn)行數(shù)據(jù)的查詢、修改、插入和刪除等操作。在JSP的應(yīng)用中,數(shù)據(jù)庫的運(yùn)用有著十分重要的地位,可以說數(shù)據(jù)庫的運(yùn)用是JSP應(yīng)用的關(guān)鍵之一。在數(shù)據(jù)庫的運(yùn)用中我們可以發(fā)現(xiàn),在數(shù)據(jù)庫相關(guān)程序中,這些操作都有很多相似之處,許多語句都是通用的。在學(xué)習(xí)了Java Bean之后,我們很自然的就想到是否可以將這些語句編寫到一個(gè)Java Bean中,這樣可以為以后編寫的數(shù)據(jù)庫程序提供極大的方便。
17.6.3? 通過Java Bean查詢數(shù)據(jù)庫
在前面的小節(jié)中,我們編寫了一個(gè)典型的鏈接數(shù)據(jù)庫Bean,在這一小節(jié)中,我們通過一個(gè)實(shí)例來學(xué)習(xí)JSP中如何通過這個(gè)Java Bean來訪問數(shù)據(jù)庫。
在此,我們先用Access數(shù)據(jù)庫軟件創(chuàng)建一個(gè)名為 AddressBook.mdb的數(shù)據(jù)庫,這個(gè)數(shù)據(jù)庫中有一個(gè)名為“user”的表。將這個(gè)數(shù)據(jù)庫設(shè)置成名為“JavaBeanTestDB”的系統(tǒng)數(shù)據(jù)源,具體的設(shè)置方法參考本書的第11章11.3.2小節(jié)中的詳細(xì)介紹。
本實(shí)例的目的是對數(shù)據(jù)庫中的user表進(jìn)行查詢、修改、插入和刪除操作。代碼17-11實(shí)現(xiàn)的是將user表中的用戶ID、用戶名以及用戶密碼顯示出來,并通過“添加”、“修改”和“刪除”按鈕分別鏈接到添加、修改和刪除記錄頁面。
17.6.4? 向數(shù)據(jù)庫添加記錄
在單擊圖中的“添加”按鈕后,將跳轉(zhuǎn)到添加記錄頁面,添加記錄頁面的源文件如代碼所示:
17.6.5? 修改數(shù)據(jù)庫記錄
在單擊17.6.3小節(jié)圖中的“修改”按鈕后,將跳轉(zhuǎn)到修改記錄頁面,該頁面實(shí)現(xiàn)對用戶密碼的修改,修改記錄頁面的源文件如代碼所示。
17.6.6? 刪除數(shù)據(jù)庫記錄
刪除數(shù)據(jù)庫記錄首先是建立數(shù)據(jù)庫鏈接,然后通過刪除選定的數(shù)據(jù)庫記錄字句執(zhí)行記錄,如果該記錄不存在則返回,如果存在則刪除該記錄。刪除數(shù)據(jù)庫記錄頁面的源文件如代碼所示。
17.7? 本章習(xí)題
(1)選擇題
說明:本章的選擇題中有單選題也有多選題,用于讀者檢查自己對本章中關(guān)鍵概念的掌握程度。
1.如果要編寫一個(gè)Bean,并將該Bean存放在WEB-INF/classes/jsp/example/mybean目錄下,則包(package)名稱是?
A.package mybean;?? B.package classes.jsp.example.mybean;
C.package jsp.example;? D.package jsp.example.mybean;
2.編寫一個(gè)Bean必須滿足哪幾點(diǎn)要求?
A.必須放在一個(gè)包(Package)中 B.必須生成public class類
C.必須有一個(gè)空的構(gòu)造函數(shù) D.所有屬性必須封裝
E.應(yīng)該通過一組存取方法來訪問
3.Java Bean中的屬性命名的規(guī)范是?
A.全部字母小寫??? B.每個(gè)單詞首字母大寫
C.第一個(gè)單詞全部小寫,之后每個(gè)單詞首字母大寫? D.全部字母大寫
4.在JSP中引用Bean應(yīng)該如何操作?
A.page指令 B.include指令 C.include動(dòng)作 D.useBean動(dòng)作
5.private int[] myInt;語句定義的是?
A.單值屬性 B.索引屬性 C.關(guān)聯(lián)屬性 D.約束屬性
6.在代碼17-10所生成的Bean中,close()方法執(zhí)行了哪些操作?
A.關(guān)閉數(shù)據(jù)集 B.關(guān)閉Statement對象
C.關(guān)閉數(shù)據(jù)鏈接 D.關(guān)閉數(shù)據(jù)庫驅(qū)動(dòng)
7.在useBean動(dòng)作中,應(yīng)該設(shè)置下面那些參數(shù)?
A.Id B.Scope C.Class D.name
8.Java Bean有幾種屬性?
A.4種 B.3種 C.2種 D.1種
9.Java Bean的方法可以分為幾種?
A.4種 B.3 種 C.2種 D.1種
10.在17.6.2小節(jié)的Bean實(shí)例中,如果數(shù)據(jù)源改變,需要設(shè)置哪幾種屬性的值?
A.rs屬性? B.url屬性
C.user屬性? D.password屬性
(2)程序閱讀題
指出下面Java Bean代碼中的錯(cuò)誤(共6處錯(cuò)誤):
package jsp.examples.mybean;
import java.beans.*;
public class Hello {??????? //類名,應(yīng)該與文件名相同
//定義屬性
String myStr;?
public Boolean myBool;
??? public hello() {?????
? myStr = "Hello Java Bean!";
? myBool = true;
??? }
//get方法
private String getMyStr()
{ return this.myStr;}
//set方法
public void setMyStr(String str)
{this.myStr = str;}
public Boolean setMyBool(Boolean bool)
{ this.myBool = bool; }
//is方法
public void isMyBool()
{ return this.myBool; }
}
(3)實(shí)際操作題
編寫一個(gè)用戶登注冊頁面,通過調(diào)用數(shù)據(jù)庫鏈接Bean將用戶輸入的注冊信息寫入數(shù)據(jù)庫,用戶注冊后轉(zhuǎn)到歡迎頁面,并顯示用戶信息。
更多文章、技術(shù)交流、商務(wù)合作、聯(lián)系博主
微信掃碼或搜索:z360901061

微信掃一掃加我為好友
QQ號聯(lián)系: 360901061
您的支持是博主寫作最大的動(dòng)力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點(diǎn)擊下面給點(diǎn)支持吧,站長非常感激您!手機(jī)微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點(diǎn)擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對您有幫助就好】元
