一、javaweb的設計模式
1.jsp模式介紹
SUN公司推出JSP技術後,同時也推薦了兩種web應用程序的開發模式,一種是JSP+JavaBean模式(model1模式),一種是Servlet+JSP+JavaBean模式(model2模式)。
1)Model1模式介紹
model1模式各部分功能分析
JSP+JavaBean模式適合開發業務邏輯不太複雜的web應用程序,這種模式下,JavaBean用於封裝業務數據,JSP即負責處理用戶請求,又顯示數據。
model1模式的優缺點
優點:簡單快捷,對開發人員要求不高。
缺點:所有的操作都在jsp頁面中,其中訪問數據庫的API是在jsp頁面中完成的,難以維護,不適合做比較複雜應用 ,它只適合中小型項目。
2)Model2模式介紹
model2模式各部分功能分析
Servlet+JSP+JavaBean(MVC)模式適合開發複雜的web應用,在這種模式下,servlet負責處理用戶請求,jsp負責數據顯示,javabean負責封裝數據。 Servlet+JSP、JavaBean模式程序各個模塊之間層次清晰,web開發推薦採用此種模式。
model2模式的優缺點
優點:維護方便,開發人員各司其職,互不干涉,有利於開發中的分工,有利於組件的重用。比較適合做比較複雜應用,它適合做中大型項目。
缺點:項目開發難度增大,對開發人員的要求也隨之提高。
2.javaBean介紹
JavaBean 是一種JAVA語言寫成的可重用組件。爲寫成JavaBean,類必須是具體的和公共的,並且具有無參數的構造器。JavaBean 通過提供符合一致性設計模式的公共方法將內部域暴露成員屬性。衆所周知,屬性名稱符合這種模式,其他Java 類可以通過自身機制發現和操作這些JavaBean 的屬性。
JavaBean可分爲兩種:一種是有用戶界面(UI,User Interface)的JavaBean;還有一種是沒有用戶界面,主要負責處理事務(如數據運算,操縱數據庫)的JavaBean。JSP通常訪問的是後一種JavaBean。而我們在javaweb開發中使用JavaBean主要是用於進行數據的運算(數據的封裝)。
1)javaBean在model1模式下的使用
jsp:useBean
jsp:setProperty
jsp:getProperty
例如:
username:<input type="text" name="username"><br>
password:<input type="password" name="password"><br>
jsp中使用bean標籤來封裝數據
<jsp:useBean id="u" class="com.itheima.domain.User"></jsp:useBean><!--相當於 User u=new User()-->
<jsp:setProperty property="name" name="u"/><!--相當於 u.setName(...)-->
<jsp:setProperty property="password" name="u"/>
當某個網頁將數據傳輸到該jsp界面時,上面的代碼就可以自動封裝這些數據,並通過下面的代碼進行獲取屬性值。
<jsp:getProperty property="name" name="u"/>
要求:頁面上組件的名稱必須與javaBean的bean屬性名稱一致。bean屬性是get/set 後面的名稱。
2)javaBean在model2模式下的使用(BeanUtils工具使用)
在model1模式下我們使用jsp提供的標籤來將數據封裝到javaBean中,那麼我們在model2模式下,因爲jsp已經不在進行功能的處理,只是用於顯示數據,這時怎樣將數據封裝到JavaBean中?如果我們通過手動封裝是可以的,但是如果參數過多,那麼代碼量很大,這時我們可以通過反射機制來完成請求參數的封裝。
1.得到所有請求參數 request.getParameterMap();
2.得到javaBean類的Class對象,得到這個類中所有方法 getDeclaredMethods();
3.判斷methods中是否具有setXxx方法,從map集合的key中獲取;
4.如果查找到這個方法,通過這個方法的invoke進行調用method.invoke()方法;
1.獲取class對象
方式1:Class clazz=Class.forName("全限定名")
方式2:Class clazz=類名.class;
方式3:Class clazz=對象.getClass;
2.可以獲取對應類的構造方法(瞭解)
Constructor con = clazz.getConstructor(Class .. paramClass);
Person p = (Person) con.newInstance(參數);
例如:
Constructor con = clazz.getConstructor(String.class,String.class);
Person p = (Person) con.newInstance("tom","123");
3.可以通過clazz創建一個對象(瞭解)
clazz.newInstance();//相當於調用的無參構造器
4.可以通過clazz獲取所有的字段 getFiled()(瞭解中的瞭解)
5.可以通過clazz獲取所有的方法
Method m = clazz.getMethod("sleep");//獲取公共的方法
Method m = clazz.getDeclaredMethod("sleep");//獲取任意的方法
注意:若是私有的方法 必須讓該方法可以訪問
m.setAccessible(true);
6.Method對象的invoke方法是有返回值,他的返回值就是目標方法執行的返回值
上述代碼我們自己完成會很複雜,在開發中,我們可以使用BeanUtils工具來完成它的底層實現就是通過java中的內省機制(最底層就是反射)來完成的。
3)BeanUtils工具介紹
Apache組織開發了一套用於操作JavaBean的API,這套API考慮到了很多實際開發中的應用場景,因此在實際開發中很多程序員使用這套API操作JavaBean,以簡化程序代碼的編寫。BeanUtils工具的使用步驟:
1.導入jar包:commons-logging-1.1.1.jar、commons-beanutils-1.8.3.jar
2.使用:BeanUtils.populate(javaBean對象, request.getParameterMap());
4)BeanUtils工具類型轉換
在使用BeanUtils工具對數據進行封裝時,它是如何做到將請求參數(字符串)封裝到javaBean的不同類型的屬性上的呢?
BeanUtils默認類型轉換介紹:在BeanUtils工具中,有默認的類型轉換,我們可以在org.apache.commons.beanutils.converters包下查看到它們提供的默認的類型轉換器。
BeanUtils自定義類型轉換器:在開發中,有很多情況下,數據類型的轉換使用BeanUtils工具可能不完全夠用,這時我們就可以通過自定義類型轉換器來完成操作。步驟如下:
1.創建一個類,實現這個接口org.apache.commons.beanutils.Converter,該接口是BeanUtils中所有類型轉換器的根接口。
2.重寫方法public Object convert(Class type, Object value)
在這個方法中完成類型轉換,這個方法的返回值就是賦值給javaBean中對應的屬性
type:要轉換成的類型
value:表單傳遞過來的屬性值
3.註冊類型轉換器
ConvertUtils.register(javaBean對象,要轉換成的類型.class);
二、MVC
MVC全名是Model View Controller,是模型(model)-視圖(view)-控制器(controller)的縮寫,是一種軟件設計典範,用一種業務邏輯、數據、界面顯示分離的方法組織代碼,將業務邏輯聚集到一個部件裏面,在改進和個性化定製界面及用戶交互的同時,不需要重新編寫業務邏輯。MVC被獨特的發展起來用於映射傳統的輸入、處理和輸出功能在一個邏輯的圖形化用戶界面的結構中。MVC模式最早被Trygve Reenskaug提出,成爲施樂帕羅奧多研究中心(Xerox PARC)的Smalltalk語言發明的一種軟件設計模式。MVC可對程序的後期維護和擴展提供了方便,並且使程序某些部分的重用提供了方便。而且MVC也使程序簡化,更加直觀。
M:model模型:主要是封裝數據,封裝對數據的訪問
V:view視圖:主要是用來展示數據,一般是jsp擔任的
C:ctrl控制:接受請求,找到相應的javabean完成業務邏輯
1.javaweb三層架構介紹
所謂的三層架構是由web層,業務層及數據層組成的,它們分別完成各自的工作,如下所示:
Web層:包含jsp和Servlet等與web相關的內容;
業務層:也稱Service層,業務層中不包含JavaWeb的API,它只關心業務邏輯;
數據層:有時候也稱爲是持久層,其功能主要是負責數據庫的訪問,簡單的說法就是實現對數據表的Select,Insert,Update,Delete的操作。
其中,web層是與web相關的內容,包括jsp和servlet,以及request、response、session、ServletContext等,這些對象只能出現在web層,不能出現在業務層;同樣,業務層只關心業務邏輯,例如登錄,註冊功能,其中註冊就是向數據庫中插入一條數據,這樣在數據層就對應一個方法,因此業務層依賴於數據層,可以這樣理解:業務層的一個功能是由數據層的若干個對數據庫的操作組成的。而web層將用戶輸入的數據傳遞給業務層,業務層處理之後將結果返回給web層,由web層再展示給用戶。也就是說web層依賴於業務層。由於業務層和數據層沒有出現javaweb的API,因此業務層和數據層是可重用的,甚至可以應用在非web環境中。
2.javaweb三層架構與MVC的區別分析
三層架構是一個分層式的軟件體系架構設計,它可適用於任何一個項目。MVC是一個設計模式,它是根據項目的具體需求來決定是否適用於該項目。
那麼架構跟設計模式有什麼區別呢?
我們從接手一個項目開始,首先,我們需要進行架構設計,一般我們採用的就是分層式的架構設計,即我們的三層架構。然後,在確定了架構以後,我們再根據項目的具體需求去考慮是否需要應用一些設計模式,比如是否應用我們的MVC模式,抽象工廠模式等等。
三、事務
事務,一般是指要做的或所做的事情。在計算機術語中是指訪問並可能更新數據庫中各種數據項的一個程序執行單元。這些單元要麼全都成功,要麼全都不成功。
1.mysql中的事務
mysql中事務默認是自動提交,一條sql語句就是一個事務。
show variables like '%autocommit%'
開啓手動事務方式
方式1:關閉自動事務(瞭解)
set autocommit = off;
方式2:手動開啓一個事務.(理解)
start transaction;-- 開啓一個事務
commit;-- 事務提交
rollback;-- 事務回滾
擴展:oracle中事務默認是手動的,必須手動提交纔可以。
2.java中的事務
Connection接口的api:
setAutoCommit(false);//手動開啓事務
commit():事務提交
rollback():事務回滾
擴展:瞭解 Savepoint還原點
void rollback(Savepoint savepoint) :還原到那個還原點
Savepoint setSavepoint() :設置還原點
爲了保證所有的操作在一個事務中,必須保證使用的是同一個連接。在service層我們獲取了連接,開啓了事務。如何dao層使用此連接?
方法1:向下傳遞參數。注意連接應該在service釋放
方法2:可以將connection對象綁定當前線程上,jdk中有一個ThreadLocal類,ThreadLocal 實例通常是類中的 private static 字段,它們希望將狀態與某一個線程(例如,用戶 ID 或事務 ID)相關聯。
ThreadLocal的方法:
構造:new ThreadLocal()
set(Object value):將內容和當前線程綁定
Object get():獲取和當前線程綁定的內容
remove():將當前線程和內容解綁
內部維護了map集合
map.put(當前線程,內容);
map.get(當前線程)
map.remove(當前線程)
3.事務的特性
簡稱ACID(Atomicity Consistency Isolation Durability),分別是:
原子性:原子性對應的英文是Atomicity,即表示事務中所有操作是不可再分割的原子單位。事務中所有操作要麼全部執行成功,要麼全部執行失敗;
一致性:一致性對應的英文是Consistency,事務執行後,數據庫狀態與其它業務規則保持一致。例如轉賬業務,無論事務執行成功與否,參與轉賬的兩個賬號餘額之和應該是不變的;
隔離性:隔離性對應的英文是Isolation,是指在併發操作中,不同事務之間應該隔離開來,使每個併發中的事務不會相互干擾;
持久性:持久性對應的英文是Durability,指的是一旦事務提交成功,事務中所有的數據操作都必須被持久化到數據庫中,即使提交事務後,數據庫馬上崩潰,在數據庫重啓時,也必須能保證通過某種機制恢復數據。
不同的事務,其一致性的表現形式是不同的,事務的其他三大特性其實都是爲了事務的一致性服務的。
不考慮隔離性會出現的讀問題
髒讀:在一個事務中讀取到另一個事務沒有提交的數據
不可重複讀:在一個事務中,兩次查詢的結果不一致(針對的update操作)
虛讀(幻讀):在一個事務中,兩次查詢的結果不一致(針對的insert操作)
通過設置數據庫的隔離級別來避免上面的問題(理解)
read uncommitted 讀未提交 上面的三個問題都會出現
read committed 讀已提交 可以避免髒讀的發生
repeatable read 可重複讀 可以避免髒讀和不可重複讀的發生
serializable 串行化 可以避免所有的問題
演示髒讀的發生:
將數據庫的隔離級別設置成:讀未提交
set session transaction isolation level read uncommitted;
查看數據庫的隔離級別
select @@tx_isolation;
避免髒讀的發生,將隔離級別設置成:讀已提交
set session transaction isolation level read committed;
不可避免不可重複讀的發生。
避免不可重複讀的發生,隔離級別設置成:可重複讀
set session transaction isolation level repeatable read;
演示串行化,可以避免所有的問題
set session transaction isolation level serializable;
四種隔離級別的效率
read uncommitted>read committed>repeatable read>serializable
四種隔離級別的安全性
read uncommitted<read committed<repeatable read<serializable
開發中絕對不允許髒讀發生
mysql中默認級別:repeatable read
oracle中默認級別:read committed
mysql中設置
數據庫默認有事務的隔離級別,mysql 中查看與修改事務的隔離級別
set session transaction isolation level 隔離級別;設置事務隔離級別
select @@tx_isolation; 查詢當前事務隔離級別
jdbc中設置事務隔離級別
在java.sql.Connection接口中提供:setTransactionIsolation(int level) ;
參數可以取 Connection 常量之一:
Connection.TRANSACTION_READ_UNCOMMITTED、
Connection.TRANSACTION_READ_COMMITTED、
Connection.TRANSACTION_REPEATABLE_READ
Connection.TRANSACTION_SERIALIZABLE。
(注意,不能使用 Connection.TRANSACTION_NONE,因爲它指定了不受支持的事務。)
DBUtils中事務控制
QueryRunner:
構造:
new QueryRunner(Datasource ds)//自動事務,調用方法的不需要傳入connection,資源不用我們釋放。
new QueryRunner()//手動事務,調用方法的必須傳入connection,需要手動提交事務或者回滾事務。必須手動的釋放資源。