源代碼放在的郵箱的收件箱裡
用戶名:sharesource
密碼:javafans
希望保留給有用的人
謝謝
取這樣一個標題太大
吸引眼球嘛@_@
事實是最近讀《J
EE設計模式》講述表達層模式的那幾章
書中有一個前端控制器+command模式的workflow例子
就琢磨著可以很簡單地擴展成一個MVC框架
花了一個下午改寫了下
對書中所述的理解更為深入
我想這也許對於學習和理解設計模式
以及初次接觸struts等MVC框架的人可能有點幫助
因為整個模型類似於struts
我把它取名叫strutslet^_^
學習性質
切勿認真
(一)完整的類圖如下
前端控制器(FrontController):前端控制器提供了一個統一的位置來封裝公共請求處理
它的任務相當簡單
執行公共的任務
然後把請求轉交給相應的控制器
在strutslet中
前端控制器主要作用也在於此
它初始化並解析配置文件
接受每個請求
並簡單地把請求委托給調度器(Dispatcher)
由調度器執行相應的動作(Action)
調度器把action返回的url返回給FrontController
FrontController負責轉發
Action接口
command模式很好的例子
它是一個命令接口
每一個實現了此接口的action都封裝了某一個請求
新增一條數據記錄並更新model
或者把某個文件寫入磁盤
命令解耦了發送者和接受者之間聯系
發送者調用一個操作
接受者接受請求執行相應的動作
因為使用Command模式解耦
發送者無需知道接受者任何接口
Dispatcher
調度器
負責流程的轉發
負責調用action去執行業務邏輯
由調度器選擇頁面和action
它去除了應用行為和前端控制器間的耦合
調度器服務於前端控制器
它把model的更新委托給action
又提供頁面選擇給FrontController
ActionForward
封裝了轉向操作所需要信息的一個模型
包括name和轉向url
ActionModel
解析配置文件後
將每一個Action封裝成一個ActionModel對象
所有ActionModel構成一個map
並存儲在ServletContext中
供整個框架使用
(二)源代碼簡單分析
Action接口
只有一個execute方法
任何一個action都只要實現此接口
並實現相應的業務邏輯
最後返回一個ActionForward
提供給Dispacher調用
public interface Action {
public ActionForward execute(HttpServletRequest requestServletContext context);
}
比如
我們要實現一個登陸系統(demo的例子)
LoginAction驗證用戶名和密碼
如果正確
返回success頁面
如果登陸失敗
返回fail頁面
public class LoginAction implements Action {
private String name=;
public ActionForward execute(HttpServletRequest request
ServletContext context) {
String userName=requestgetParameter(userName);
String password=requestgetParameter(password);
if(userNameequals(dennis)&&passwordequals()){
requestsetAttribute(name name);
return ActionForwardSUCCESS; //登陸成功返回success
}else
return ActionForwardFAIL; //否則返回fail
}
還是先來看下兩個模型ActionForward和ActionModel沒什麼東西屬性以及相應的gettersetter方法
/**
* 類說明:轉向模型
* @author dennis
*
* */
public class ActionForward {
private String name; //forward的name
private String viewUrl; //forward的url
public static final ActionForward SUCCESS=new ActionForward(success);
public static final ActionForward FAIL=new ActionForward(fail);
public ActionForward(String name){
thisname=name;
}
public ActionForward(String name String viewUrl) {
super();
thisname = name;
thisviewUrl = viewUrl;
}
//name和viewUrl的getter和setter方法
}
我們看到ActionForward預先封裝了SUCCESS和FAIL對象
public class ActionModel {
private String path; // action的path
private String className; // action的class
private Map<String ActionForward> forwards; // action的forward
public ActionModel(){}
public ActionModel(String path String className
Map<String ActionForward> forwards) {
super();
thispath = path;
thisclassName = className;
thisforwards = forwards;
}
//相應的getter和setter方法
}
知道了兩個模型是什麼樣
也應該可以猜到我們的配置文件大概是什麼樣的了
與struts的配置文件格式類似
<?xml version= encoding=UTF?>
<actions>
<action path=/login
class=comstrutsletdemoLoginAction>
<forward name=success url=hellojsp/>
<forward name=fail url=failjsp/>
</action>
</actions>
path是在應用中將被調用的路徑
class指定了調用的哪個action
forward元素指定了轉向
比如我們這裡如果是success就轉向hello
jsp
失敗的話轉向fail
jsp
這裡配置了demo用到的LoginAction
Dispacher接口
主要是getNextPage方法
此方法負責獲得下一個頁面將導向哪裡
提供給前端控制器轉發
public interface Dispatcher {
public void setServletContext(ServletContext context);
public String getNextPage(HttpServletRequest requestServletContext context);
}
原先書中實現了一個WorkFlow的Dispatcher
按照順序調用action
實現工作流調用
而我們所需要的是根據請求的path調用相應的action
執行action的execute方法返回一個ActionForward
然後得到ActionForward的viewUrl
將此viewUrl提供給前端控制器轉發
看看它的getNextPage方法
public String getNextPage(HttpServletRequest request ServletContext context) {
setServletContext(context);
Map<String ActionModel> actions = (Map<String ActionModel>) context
getAttribute(ConstantACTIONS_ATTR); //從ServletContext得到所有action信息
String reqPath = (String) requestgetAttribute(ConstantREQUEST_ATTR);//發起請求的path
ActionModel actionModel = actionsget(reqPath); //根據path得到相應的action
String forward_name = ;
ActionForward actionForward;
try {
Class c = ClassforName(actionModelgetClassName()); //每個請求對應一個action實例
Action action = (Action) cnewInstance();
actionForward = actionexecute(request context); //執行action的execute方法
forward_name = actionForwardgetName();
} catch (Exception e) {
logerror(can not find action +actionModelgetClassName());
eprintStackTrace();
}
actionForward = actionModelgetForwards()get(forward_name);
if (actionForward == null) {
logerror(can not find page for forward +forward_name);
return null;
} else
return actionForwardgetViewUrl(); //返回ActionForward的viewUrl
}
前端控制器(FrontController)它的任務我們已經很清楚初始化配置文件存儲所有action到ServletContext供整個框架使用得到發起請求的path提供給Dispachter查找相應的action調用Dispatcher執行getNextPage方法得到下一個頁面的url並轉發
public void init() throws ServletException {
//初始化配置文件
ServletContext context=getServletContext();
String config_file =getServletConfig()getInitParameter(config);
String dispatcher_name=getServletConfig()getInitParameter(dispatcher);
if (config_file == null || config_fileequals())
config_file = /WEBINF/strutsletconfigxml; //默認是/WEBINF/下面的strutsletconfig
if(dispatcher_name==null||dispatcher_nameequals())
dispatcher_name=ConstantDEFAULT_DISPATCHER;
try {
Map<String ActionModel> resources = ConfigUtilnewInstance() //工具類解析配置文件
parse(config_file context);
contextsetAttribute(ConstantACTIONS_ATTR resources); //存儲在ServletContext中
(初始化strutslet配置文件成功);
} catch (Exception e) {
logerror(初始化strutslet配置文件失敗);
eprintStackTrace();
}
//實例化Dispacher
try{
Class c = ClassforName(dispatcher_name);
Dispatcher dispatcher = (Dispatcher) cnewInstance();
contextsetAttribute(ConstantDISPATCHER_ATTR dispatcher); //放在ServletContext
(初始化Dispatcher成功);
}catch(Exception e) {
logerror(初始化Dispatcher失敗);
eprintStackTrace();
}
doGet()和doPost方法我們都讓它調用process方法
protected void process(HttpServletRequest request
HttpServletResponse response) throws ServletException IOException {
ServletContext context = getServletContext();
//獲取action的path
String reqURI = requestgetRequestURI();
int i=reqURIlastIndexOf();
String contextPath=requestgetContextPath();
String path=reqURIsubstring(contextPathlength()i);
requestsetAttribute(ConstantREQUEST_ATTR path);
Dispatcher dispatcher = (Dispatcher) contextgetAttribute(ConstantDISPATCHER_ATTR);
// make sure we dont cache dynamic data
responsesetHeader(CacheControl nocache);
responsesetHeader(Pragma nocache);
// use the dispatcher to find the next page
String nextPage = dispatchergetNextPage(request context);//調用Dispatcher的getNextPage
// forward control to the view
RequestDispatcher forwarder = requestgetRequestDispatcher(/
+ nextPage);
forwarderforward(request response); //轉發頁面
}
最後
web
xml的配置就非常簡單了
配置前端控制器
提供啟動參數(配置文件所在位置
為空就查找/WEB
INF/下面的strutslet
config
xml文件)
我們把所有以action結尾的請求都交給FrontController處理
<servlet>
<servletname>StrutsletController</servletname>
<servletclass>reFrontController</servletclass>
<!
<initparam>
<paramname>config</paramname>
<paramvalue>/WEBINFstrutsletconfigxml</paramvalue>
</initparam>
>
<loadonstartup></loadonstartup>
</servlet>
<servletmapping>
<servletname>StrutsletController</servletname>
<urlpattern>*action</urlpattern>
</servletmapping>
最後
讓我們看看整個框架圖
From:http://tw.wingwit.com/Article/program/Java/gj/201311/27610.html