Composite模式:
Junit中的TestCase和TestSuite就是組合模式,
Test接口派生出TestCase、TestSuite、TestDecorator
TestSuite有一個add方法,裏面傳入的是Test接口引用,這樣它
就又可以添加TestCase,也可以添加TestSuite了。
java.awt中也用到了這種設計模式。
計算機主板上可以插入CPU和顯卡,顯卡和CPU上還可以再插風扇,風扇又可以
直接插到主板上。
組件上不能再添加新的組件的模式是安全式模式
還有一個透明式的組合模式。
-----------------------------------------------------------------------------------
decorator模式:在不修改類的前提下,改變類的方法和行爲。
比如在不修改ArrayList的情況下,改變ArrayList的add方法,使得
它在每次執行前打印出一段日誌,並能夠將對象添加到集合裏面去,而
其他的方法不受到任何的影響。
//裝飾類
public class ListDecorator extends ArrayList
{
private ArrayList list ;
public ListDecorator(ArrayList list)
{
this.list = list ;
}
public boolean add(Object arg0)
{
System.out.println("In add method");
return list.add(arg0)
}
}
IO中的很多類都用到了Decorator,如BufferedReader等。
----------------------------------------------------------------------------------
Facade模式:
子系統十分複雜,包含很多類和接口,如何讓用戶不用完全瞭解所有的接口和類,就可以順利
使用子系統呢?
如何對子系統進行整理
一個保安系統由是個錄像機Camera、20個電燈Light、5個遙感器Sensor、和一個警報器Alarm組成,
定義這個系統,並在客戶端操作這個系統。
----------------------------------------------------------------------------------
Flyweight模式:
文本編輯器中,一個字可能要在文章中出現幾十次,那麼採用面向對象的編程是否要爲每個創建一個
實例對象呢?
如果創建,存儲空間浪費太大,因爲它們都是對的同一個字,具有相同特徵。,如果不創建,又如何
去標識這個對象的存在呢?
文本編輯器必須爲每個字幕創建一個對象,如何實現?
有點像僞單例模式
在TextEditor裏面創建一個對象的集合,裏面裝的是字體對象實例。
比如使用Map
---------------------------------------------------------------------------------
代理模式:
Hibernate和Spring裏面都用到了。
在實現上和裝飾模式一樣,但是二者的目的不一樣
java.lang.reflect.Proxy
java.lang.reflect.InvocationHandler
===============================================================================
行爲模式:
chain of responsibility模式:
如果存在不同種類消息,它們分別由一個特定的對象處理,如何實現?
使用switch case嗎?
使用switch case的問題在於當新類型的消息類型出現時,必須要修改
switch case代碼,增加處理新消息類型的內容
寫一段代碼,當一個異常傳給這段代碼可以根據代碼的類型不同而生成不同的友好信息,
要保證異常全面並可擴展。
把所有處理異常的方法做成一個鏈,每一個節點只處理一種異常
public abstract class ExceptionHandler
{
protected ExceptionHandler nextHandler
public void setNextHandler(ExceptionHandler n)
{
nextHandler = n ;
}
public abstract String handleException(Exception e);
}
public class SqlExceptionHandler extends ExceptionHandler
{
public String handleException(Exception e)
{
if(e instanceof SQLException)
{
return "發生了數據庫異常" ;
}
else
{
if(nextHandler!=null)
{
return nextHandler.handleException(e);
}
}
return "無法識別的異常" ;
}
}
public class NullpointerExceptionHandler extends ExceptionHandler
{
public String handleException(Exception e)
{
if(e instanceof NullPointerException)
{
return "發生了空指針異常" ;
}
else
{
if(nextHandler!=null)
{
return nextHandler.handleException(e);
}
}
return "無法識別的異常" ;
}
}
public static void main(String[] args)
{
ExceptionHandler sql = new SqlExceptionHandler();
ExceptionHandler np = new NullpointerExceptionHandler();
sql.setNextHandler(np);//構造成鏈
System.out.println(sql.handleException(new NullPointerException()));
}
特徵描述
主要是所有的處理者都要實現同一個方法,並將它們構造成鏈,當自身無法處理時,將請求傳給下一個處理者。
職責鏈模式的最大好處是迴避了switch case的使用。
應用場景
有多個的對象可以處理一個請求,哪個對象處理該請求運行時刻自動確定。
你想在不明確指定接收者的情況下,向多個對象中的一個提交一個請求。
可處理一個請求的對象集合應被動態指定。
------------------------------------------------------------------------------
Command模式
問題描述:
在常見的文本編輯器中,撤消與重做是兩個經常要用到的操作,如何實現?
問題難點:
同一個命令要對各種不同的操作做撤消或重做工作,程序不僅要記住都進行了哪些操作,
還必須記住每個操作的撤消操作或重做操作是什麼,如果不使用好的模式,根本無法實現。
各種操作的對象也可能不同,比如同樣是設置大小,可能是針對文字,
也可能是針對圖片;即使都是針對文字,也必須記錄是哪一個或哪些文字。
房間內有一盞燈和一臺電風扇,燈可以打開、熄滅,風扇可以打開、關閉、加速、減速。
用戶進入房間後,可以以任意順序對燈和風扇進行操作。設計程序,要求可以對用戶操作
做撤消和重做。
public abstract class Command
{
public abstract void redo() ; //重做
public abstract void undo() ; //撤銷
}
public class Light
{
public void on()
{
System.out.println("開燈了!");
}
public void off()
{
System.out.println("熄燈了!");
}
}
public class Fan
{
public void rotate()
{
System.out.println("電風扇轉動了!");
}
public void stop()
{
System.out.println("電風扇停止轉動!");
}
public void speedUp()
{
System.out.println("風扇加速轉動!");
}
public void slowDown()
{
System.out.println("風扇減速轉動!");
}
}
public class LightOnCommand extends Command
{
private Light light ;
public LightOnCommand(Light light)
{
this.light = light ;
}
public void redo()
{
light.on();
}
public void undo()
{
light.off();
}
}
public class LightOffCommand extends Command
{
private Light light ;
public LightOffCommand(Light light )
{
this.light = light ;
}
public void redo()
{
light.off();
}
public void undo()
{
light.on();
}
}
//同理、FanStopCommand、FanSpeedUpCommand、FanSlowDownCommand
//類也可以像下面一樣定義
public class FanRotateCommand extends Command
{
private Fan fan ;
public FanRotateCommand(Fan fan)
{
this.fan = fan ;
}
public void redo()
{
fan.rotate();
}
public void undo()
{
fan.stop();
}
}
public class FanStopCommand extends Command
{
private Fan fan ;
public FanStopCommand(Fan fan)
{
this.fan = fan ;
}
public void redo()
{
fan.stop();
}
public void undo()
{
fan.rotate();
}
}
//房間類就相當於界面了……
public class House
{
private Vector redoList = new Vector() ;
private Vector undoList = new Vector() ;
public void executeCommand(Command c)
{
c.redo() ;
undoList.add(c) ;
}
public void undo()
{
//取出最後一次加入的那個命令
Command c = (Command)undoList.lastElement();
c.undo();
redoList.add(c) ;//加入到重做的集合中去
undoList.remove(c) ;
}
public void redo()
{
Command c = (Command)redoList.lastElement() ;
c.redo() ;
undoList.add(c) ;
redoList.remove(c) ;
}
}
public static void main(String[] args)
{
House n = new House() ;
Command on = new LightOnCommand(new Light()) ;
Command rotate = new FanRotateCommand(new Fan()) ;
n.executeCommand(on) ;
n.executeCommand(rotate) ;
n.undo() ;
n.redo() ;
n.undo() ;
n.undo() ;
}
//上述命令模式的結構很清晰,而且這種設計真的很牛逼……
命令獨立於對象存在,比如TestCase就是典型的命令模式,本來
是你寫的類去運行,結果運行的反倒是TestCase,讓TestCase
去調用你的類中的方法。
特徵描述
將命令獨立出來,而在內部包含真正的執行者。命令可以單獨處理,也可以拿到任何其它的
地方再次運行,這就保證了回退的可能。
應用場景
抽象出待執行的動作以參數化某對象,Command 模式是回調機制的一個面向對象的替代品。
在不同的時刻指定、排列和執行請求,可將負責該請求的命令對象傳送給另一個不同的進程並
在那兒實現該請求。
支持取消操作。
支持修改日誌,這樣當系統崩潰時,這些修改可以被重做一遍。
用構建在原語操作上的高層操作構造一個系統。
----------------------------------------------------------------------
Interpreter模式
當有一個語言需要解釋執行, 並且你可將該語言中的句子表示爲一個抽象語法樹時,
可使用解釋器模式。而當存在以下情況時該模式效果最好:
該文法簡單對於複雜的文法, 文法的類層次變得龐大而無法管理。此時語法分析程序生成器
這樣的工具是更好的選擇。它們無需構建抽象語法樹即可解釋表達式, 這樣可以節省空間而
且還可能節省時間。
效率不是一個關鍵問題最高效的解釋器通常不是通過直接解釋語法分析樹實現的, 而是首先
將它們轉換成另一種形式。例如,正則表達式通常被轉換成狀態機。但即使在這種情況下,
轉換器仍可用解釋器模式實現, 該模式仍是有用的。
------------------------------------------------------------------
Iterator模式:
問題描述
對於一種存儲結構,如何能夠在不暴露其存儲結構細節的情況下,實現對其內部元素的順序訪問?
問題難點
不暴露內部存儲結構基於兩方面考慮
不希望存儲結構被不正確的使用
便於程序員訪問元素,而無需瞭解其內部實現細節
給ArrayList設計一個Iterator,使它能夠按順序返回集合中的對象
Iterator裏面肯定也是個對象組合的思想,ArrayList的Iterator肯定包含一個ArrayList,
然後Iterator中的next或是hasNext要通過ArrayList的方法來間接的實現。
特徵描述
一般會在迭代器中包含集合的引用,在迭代方法中通過訪問集合的相應方法實現對集體的迭代
應用場景
訪問一個聚合對象的內容而無需暴露它的內部表示。
支持對聚合對象的多種遍歷。
爲遍歷不同的聚合結構提供一個統一的接口(即, 支持多態迭代)。
這種模式可以不暴露具體集合的結構
------------------------------------------------------------------------
Mediator模式
問題描述
如果多個對象間需要相互協作,每個對象都必須知道所有的其它對象,這將使對象間的關係變得十分複雜。
如何簡化這種關係?
問題難點
主要的難點在於多個對象協作時,一個對象的變化可以會直接影響到另一個對象,甚至所有對象。
如果將所有對象變化引起的連帶變化都定義出來,這將會使系統變得混亂
法人(Corporation)實體間會發生一些關係,比如,一個公司(Company)需要和工商(ICAdmin)、
稅務(TaxAdmin)等機構打交道,其中任何一方發生變化時,其它兩方都要進行調整,試寫一程序
模擬這種變化。
//法人
public abstract class Corporation
{
public abstract void change() ;
public abstract void acceptChanges() ;
}
public class ICAdmin extends Corporation
{
private Mediator mediator ;
public ICAdmin(Mediator mediator)
{
this.mediator = mediator ;
mediator.register(this) ;
}
public void acceptChanges()
{
System.out.println("工商部門接受到了變化!");
}
public void change()
{
mediator.corporationChanged(this) ;
}
}
public class Company extends Corporation
{
private Mediator mediator ;
public Company(Mediator mediator)
{
this.mediator = mediator ;
mediator.register(this) ;
}
public void acceptChanges()
{
System.out.println("公司接受到了變化!");
}
public void change()
{
mediator.corporationChanged(this) ;
}
}
public class TaxAdmin extends Corporation
{
private Mediator mediator ;
public TaxAdmin(Mediator mediator)
{
this.mediator = mediator ;
mediator.register(this) ;
}
public void acceptChanges()
{
System.out.println("稅務接受到了變化!");
}
public void change()
{
mediator.corporationChanged(this) ;
}
}
public class Mediator
{
private ICAdmin ic ;
private TaxAdmin tax ;
private Company c ;
public void register(Corporation c)
{
if(c instanceof Company)
{
this.c = (Company)c ;
}
else if(c instanceof ICAdmin)
{
this.ic = (ICAdmin)c ;
}
else
{
this.tax = (TaxAdmin)c ;
}
}
//以下最好使用職責鏈來實現
public void corporationChanged(Corporation c)
{
if(c instanceof Company)
{
ic.acceptChanges() ;
tax.acceptChanges() ;
}
else if(ic instanceof ICAdmin)
{
this.c.acceptChanges() ;
tax.acceptChanges() ;
}
else
{
this.c.acceptChanges() ;
ic.acceptChanges();
}
}
}
public static void main(String[] args)
{
Mediator m = new Mediator() ;
Company c = new Company(m) ;
ICAdmin ic = new ICAdmin(m) ;
TaxAdmin tax = new TaxAdmin(m) ;
c.change() ;
ic.change() ;
}
特徵描述
同事間互不相實,由中介者完成同事間交互
同事不知道任何其它同事,只知道中介者,也即具有一箇中介者屬性
應用場景
一組對象以定義良好但是複雜的方式進行通信。產生的相互依賴關係結構混亂且難以理解。
一個對象引用其他很多對象並且直接與這些對象通信,導致難以複用該對象。
想定製一個分佈在多個類中的行爲,而又不想生成太多的子類。
典型應用
界面元素內的相互約束關係
廣義上說,MVC中的controller是M、V的中介者,例如Spring中的DispatcherServlet
即爲HandlerMapping、Controller、ViewResolver、View之間的中介者。這些對象不
直接打交道,而是通過DispatcherServlet完成交互
-----------------------------------------------------------------------
Memento模式(備忘錄)
問題描述
如何記住系統的某一刻狀態,以便可以恢復到這個狀態上
問題難點
在記住系統狀態的同時,又不能暴露系統的內部結構
一個三角形,具有三邊長、顏色等特性,當修改了它的這些屬性後,如何能夠讓它恢復到
前一次的狀態中?
public class Triangle
{
private int a ;
private int b ;
private int c ;
private String color ;
//getter、setter方法略
public Triangle(int a ,int b , int c , String color)
{
this.a = a ;
this.b = b ;
this.c = c ;
this.color = color ;
}
public TriangleMemento createMemento()
{
TriangleMemento memento = new TriMemento() ;
memento.setA(a) ;
memento.setB(b) ;
memento.setC(c) ;
memento.setColor(color) ;
return memento ;
}
public void restore(TriangleMemento memento)
{
a = memento.getA() ;
b = memento.getB() ;
c = memento.getC() ;
color = memento.getColor() ;
}
public String toString()
{
return "a = " + a
+ ", b = "+b+" , c = "+c+", color = "+color ;
}
}
public class TriangleMemento
{
private int a ;
private int b ;
private int c ;
private String color ;
//getter、setter方法。
}
public static void main(String[] args)
{
Triangle t = new Triangle(1,2,3,"red") ;
TriangleMemento memento = t.createMemento() ;
System.out.println(t) ;
t.setA(3) ;
t.setB(4) ;
System.out.println(t);
t.restore(memento);
System.out.println(t) ;
}
特徵描述
重點是將對象具備的狀態提出到備忘錄中,以使不暴露原有對象的結構信息。
應用場景
必須保存一個對象在某一個時刻的(部分)狀態, 這樣以後需要時它才能恢復到先前的狀態。
如果一個用接口來讓其它對象直接得到這些狀態,將會暴露對象的實現細節並破壞對象的封裝性。
典型應用
廣義上說,session/cookies都是Memento模式的應用
Struts中,當提交表單的數據出現錯誤時,要返回包含表單的頁面,並恢復其中的數據,
使用了ActionForm也是備忘錄的一種應用
--------------------------------------------------------------------------
Observer模式
問題描述
系統中往往會有這樣的需求,當一對象的狀態發生改變時,必須要通知所有與它相關聯的對象,如何實現?
問題難點
必須保證當有新對象加入進來時,不用修改原有代碼
老師和學生都關心學校發佈的各項消息,當學校有新的制度發佈時,必須要向老師和學生髮布。
如果政府也關心學校發佈的消息,如何能夠在不修改原有代碼的情況下,保證消息也能發到政府那裏?
讓政府也實現一個Observer接口
public class School extends Observable
{
public void publish()
{
System.out.println("學校發佈了一個消息!") ;
setChanged() ; //調用Observable的protected方法
notifyObservers() ;
}
}
public class Student implements Observer
{
public void update(Boservable o , Object arg)
{
System.out.println("學生接收到了一個消息");
}
}
public class Teacher implements Observer
{
public void update(Boservable o , Object arg)
{
System.out.println("老師接收到了一個消息");
}
}
public static void main(String[] args)
{
School s = new School() ;
s.addObserver(new Student()) ;
s.addObserver(new Student()) ;
s.addObserver(new Teacher()) ;
s.addObserver(new Student()) ;
s.publish() ;
}
//現在如果要加入政府的話、和老師學生是一個道理。
特徵描述
觀察者要向被觀察者註冊,當狀態發生變化時,觀察者要迭代向所有觀察者發消息。
應用場景
必須保存一個對象在某一個時刻的(部分)狀態, 這樣以後需要時它才能恢復到先前的狀態。
如果一個用接口來讓其它對象直接得到這些狀態,將會暴露對象的實現細節並破壞對象的封裝性。
比如監聽器。
Java對Observer模式提供了內置支持,參見
java.util.Observer
java.util.Observable :被觀察者
--------------------------------------------------------------------------
State模式:
問題描述
當一個對象在不同狀態下的行爲完全不同時,如何根據狀態影響行爲?
問題難點
想當然的實現是使用switch case或if語句,判斷條件,然後給出行爲。
但當對象增加了新狀態時,這種條件判斷語句就必須更改。
蝴蝶(butterfly)一生要經歷幼蟲(grub)、蛹(pupa)、成蟲(imago)
三種狀態,在不同的狀態下它的行(walk)、飛(fly)、吃(eat)是完全不
同的,如何設計類,能夠使得在加入新的狀態時,不用改變原有代碼,也可改變
以上行爲?
在狀態(幼蟲、蛹、成蟲)中定義行爲(行走、飛、吃),在蝴蝶中持有狀態對象。
public class ButterFly
{
private State state ;
public void setState(State state)
{
this.state = state ;
}
public void walk()
{
state.walk() ;
}
public void fly()
{
state.fly() ;
}
public void eat()
{
state.eat() ;
}
}
public abstract class State
{
public abstract void walk();
public abstract void fly() ;
public abstract void eat() ;
}
public class Grub extends State
{
public abstract void walk()
{
System.out.println("我只能爬");
}
public abstract void fly()
{
System.out.println("我還不能飛");
}
public abstract void eat()
{
System.out.println("我愛吃青菜");
}
}
public class Pupa extends State
{
public abstract void walk()
{
System.out.println("我現在走不動");
}
public abstract void fly()
{
System.out.println("我還不能飛");
}
public abstract void eat()
{
System.out.println("我現在什麼都不吃");
}
}
public class Imago extends State
{
public abstract void walk()
{
System.out.println("我飛,不走");
}
public abstract void fly()
{
System.out.println("我可以飛了");
}
public abstract void eat()
{
System.out.println("我現在採蜜");
}
}
public static void main(String[] args)
{
State grub = new Grub() ;
State pupa = new Pupa() ;
ButterFly bf = new ButterFly() ;
bf.setState(grub) ;
bf.eat();bf.walk();bf.fly() ;
bf.setState(pupa) ;
bf.eat();bf.walk();bf.fly() ;
}
特徵描述
將行爲提取到狀態中,對象行爲通過狀態實現
應用場景
一個對象的行爲取決於它的狀態, 並且它必須在運行時刻根據狀態改變它的行爲。
一個操作中含有龐大的多分支的條件語句,且這些分支依賴於該對象的狀態。這個狀態通常
用一個或多個枚舉常量表示。通常, 有多個操作包含這一相同的條件結構。State模式將每
一個條件分支放入一個獨立的類中。這使得你可以根據對象自身的情況將對象的狀態作爲一
個對象,這一對象可以不依賴於其他對象而獨立變化。
TCP連接:關閉、打開、監聽等狀態,各種不同的狀態對於同一個“打開”命令的響應是絕對
不同的,將狀態獨立出去,分別對不同的行爲進行各自獨立的響應就可以了。
---------------------------------------------------------------------------
Strategy模式
問題描述
一種業務可以通過幾種算法實現,如何實現?
問題難點
想當然的作法依然是使用switch case或if,但當有新算法加入進來時,
如何能夠在不改變原有代碼的基礎上,加入新算法?
網上商城對不同種類的客戶採用不同的折扣計算方法,但折扣計算方法可能
會發生變化或增加新的算法,如何給它們解耦合?
特徵描述
在對象中包含算法對象
應用場景
許多相關的類僅僅是行爲有異。“策略”提供了一種用多個行爲中的一個行爲來配置一個類的方法。
需要使用一個算法的不同變體。例如,你可能會定義一些反映不同的空間/時間權衡的算法。
算法使用客戶不應該知道的數據。可使用策略模式以避免暴露覆雜的、與算法相關的數據結構。
一個類定義了多種行爲, 並且這些行爲在這個類的操作中以多個條件語句的形式出現。將相關的
條件分支移入它們各自的Strategy類中以代替這些條件語句。
典型應用
AWT中的Layout
-----------------------------------------------------------------------------
Template Method模式
問題描述
在許多的應用中,業務流程的骨架是完全相同的,只是其中的某些內容不同,
如何簡化這種開發,使得程序只關心其中變化的部分呢?
特徵描述
模板定義邏輯骨架,由子類給出步驟中的實現
應用場景
一次性實現一個算法的不變的部分,並將可變的行爲留給子類來實現。
各子類中公共的行爲應被提取出來並集中到一個公共父類中以避免代碼重複。
控制子類擴展。
典型應用
Java類庫中大量的應用了模板模式
Spring在數據層的封裝也大量的使用了模板模式
-----------------------------------------------------------------------------
Visitor模式:
問題描述
如果存在一個較複雜的結構,它內部元素的結構已經固定不變,行爲也不變。
如何在不暴露其內部組織結構的情況下,爲結構中的元素增加新的行爲?
應用場景
一個對象結構包含很多類對象,它們有不同的接口,而你想對這些對象實施一些依賴於其具體類的操作。
需要對一個對象結構中的對象進行很多不同的並且不相關的操作,而你想避免讓這些操作“污染”這些對象的類。
當該對象結構被很多應用共享時,用Vi s i t o r模式讓每個應用僅包含需要用到的操作。
定義對象結構的類很少改變,但經常需要在此結構上定義新的操作。改變對象結構類需要重定義對所有訪問者
的接口,這可能需要很大的代價。如果對象結構類經常改變,那麼可能還是在這些類中定義這些操作較好。
public class Visitor
{
public void visitComponentA(ComponentA a)
{
a.setValue(100) ;
}
public void visitComponentB(ComponentB b)
{
b.setValue(100) ;
}
}
public class ComponentA
{
int value ;
//getter和setter方法
}
public class ComponentB
{
int value ;
//getter和setter方法
}
public class ComplexObject
{
List list = new ArrayList() ;
public ComplexObject(ComponentA a, ComponentB b)
{
list.add(a);
list.add(b);
}
public void accept(Visitor visitor)
{
Iterator it = list.iterator() ;
while(it.hasNext())
{
Object obj = it.next() ;
if(obj instanceof ComponentA)
{
visitor.visitComponentA((ComponentA)obj) ;
}
else if(obj instanceof ComponentB)
{
visitor.visitComponentB((ComponentB)obj);
}
}
}
}
以後要擴充行爲的時候只要增加訪問者就可以了,不用更改ComplexObject這個
複雜對象類。
m o s s t v c c i i m
=================================================================
複習:
BS模式分層:表述層、邏輯層、數據層(j2EE規範)
在每一層都使用了什麼樣的技術實現?
表述層:Servlet
邏輯層:EJB(SessionBean、消息驅動的Bean如JMS)
數據層:實體Bean
表述層(Servlet、Filter、Listener)
Listener監聽兩類事件:生命週期和屬性的增刪改,
Session裏面多了個鈍化和激活的問題,所以多了個監聽器。
一共9個。
過濾器、監聽器和Servlet屬於一體系。
get和post請求:參數的封裝位置不同導致get的數據長度有限,post的
參數封裝在體裏面。
jsp裏面相對來說東西多一些:模版(翻譯過程中不會改變)和元素(行爲元素、指令元素、
腳本元素:腳本聲明、腳本表達式、腳本片段)
include指令和include動作一個是編譯前包含、一個是編譯後包含(都可以包含WEB-INF
文件夾裏面的東西)
RequestDispatcher的forward方法和include方法也可以訪問WEB-INF裏面的東西。
pageEncoding影響容器翻譯時候讀時採用的編碼
contentType影響的是瀏覽器
contentType和pageEncoding只設定一個就可以,另外一個會和已經配置的這個保持一致。
exception內置對象:僅僅在isErrorPage爲true的時候纔可以使用。
pageContext通過getOut方法得到的未必是Out對象(JspWriter:進行了緩存)。
response.getWriter得到的是PrintWriter(沒有緩存)
這裏面有個bodyContent、pushBody和popBody的問題!!
EL表達式中的11個內置對象:配置裏面有個isELIgnored,默認爲false
四個作用域(實際上是Map)、param、paramValues、header、headerValues、cookies、
pageContext(可以得到所有的內置對象)
sessionID:Cookie和URL兩種形式生成。
轉發與重定向:是否生成臨時響應、地址欄是否變化、是否處於同一個請求作用域裏面。
請求轉發最多能夠在一個容器範圍的不同Web工程中跳來跳去,但是重定向可以隨便的跳。
jsp的行爲元素:useBean(在service方法內部開放一個腳本變量供表達式使用、將這個腳本
變量存儲到指定的作用域裏面,注意作用域裏面存的是引用!!)
setProperty和getProperty,我們設置的屬性只要有getter和setter方法就可以,不需要有
屬性名,其實就是利用javaBean的自省機制找屬性的getter方法和setter方法。
表達式的點操作符也是用了javaBean的自省機制。
注意jsp的forward和servlet裏面的forward就是差了個return,servlet執行完forward
之後還要執行剩下的代碼,而jsp就忽略forward後面的代碼了。
------------------
自定義標籤:標籤的處理類、tld文件、taglib引入jsp頁面。
標籤分爲兩大類:傳統標籤和簡單標籤(其實還有標籤文件)
傳統標籤和簡單標籤的頂層是JspTag,它擴展出Tag和SimpleTag兩個體系。
Tag:doStartTag、doEndTag
如果不處理體,就把體直接輸出到out內置對象上;如果處理體(返回的必須是EVAL_BODY_BUFFERED)
,先調用pushBody,然後得到的out就不是內置對象了,而是bodyContent!
標籤如果要處理屬性的話……
SimpleTag:doTag
jspFragment的invoke方法,這裏還有個StringWriter的東西(見以前的筆記)
TagFile(標籤文件)
EL表達式中函數的聲明問題、國際化問題、核心標籤庫問題
數據庫表首先支持gbk、然後數據庫驅動也要支持gbk、然後纔是服務器端和客戶端的支持gbk編碼。
------------------------------------------
晚上是王勇講WebServices:
SOAP、WSDL、UDDI等
Simple Object Access Protocal:是輕量級協議,用於在分散型、
分佈式環境中交換結構化信息。SOAP利用XML技術定義一種可以擴展的消息處理框架。
SOAP消息結構:
WebServices 是指由企業發佈的完成其特別商務需求的在線應用服務。
WebServices協議棧:基於傳輸層。
面向商務、消費者、設備、系統
WSDL(Web Service Description Language)是在這種
.com時代需要一種解決方案來描述它所提供的服務
UDDI(Universal Description Discovery and Integration)
它的核心組件是UDDI商業註冊,使用一個XML文檔來描述企業以及其提供的WebService。
商業註冊提供的信息包括黃頁、白頁、綠頁三部分。
白頁:地址、聯繫方法、企業標識
黃頁:基於標準分類法的行業類別。
綠頁:企業提供的WebService的技術信息,可能是一些指向文件或者URL的指針。
基於Apache Axis的開發示例:
客戶端採用java和delphi
服務器採用webservice發佈,主要使用java
環境:java2平臺、Delphi7、Tomcat、Apache Axis
解壓縮Axis安裝包,將webapps下的axis目錄拷貝到tomcat中的webapps
裏面去。
Service代碼:
public class MyMath
{
public int squared(int x)
{
return x * x ;
}
}
保存代碼爲.jws文件(JavaWebService文件)
將這個文件拷貝到axis工程目錄中去(也就是和WEB-INF同級的目錄)
Axis會自動發現該文件並且部署和編譯
http://localhost:8080/axis/MyMath.jws
就可以訪問了
點擊“Click to see the WSDL”後可以看到WSDL文件。
Java2WSDL:該工具用於將java文件轉換爲WSDL文件
WSDL2Java:將WSDL文件轉換成Stub和skeleton相關java文件。
www.ayandy.com: 提供商地址
www.ayandy.com/Service.asmx?WSDL: WSDL描述信息