網絡上有很多介紹
MVC
的理論知識(至于理論知識,我們不多做介紹),我也看到了一些其他人員開發的基于
MVC
的框架。對此我也有些自己的見解。通過使用
fa?ade,template,factory pattern
搭建了一個簡易的
MVC
框架。
?
OK
,我們先來個類圖。
介紹下各自類的用途,
FacadeServlet
主要應用為分發類,而
AbstractLogic
應用了
template pattern
,它是一個抽象類,包括一個抽象方法
doBusiLogic(HttpServletRequest request, HttpServletResponse response)
方法。像
struts
一樣,若新增一個
controller
,需新增一個實現
Action execute()
方法的類。在
struts-config.xml
中配置,通過頁面
url
確定執行哪個類的。在本實例中執行
doBusiLogic(HttpServletRequest request, HttpServletResponse response)
方法(注:
struts
中根據配置執行方法不一樣)。有點糊涂,別急,來個時序圖,詳細說明。
首先通過
URL
訪問
FacadeServlet
,
FacadeServlet
在全局應用中只存在一個。取得具體配置實現類(有點像
struts
應用。通過
java
反射機制實例化配置類。調用
execute()
方法分發。代碼如下(含注釋):
package
?com.qujingbo;

import
?javax.servlet.http.HttpServlet;
import
?javax.servlet.http.HttpServletRequest;
import
?javax.servlet.http.HttpServletResponse;
import
?javax.servlet.ServletException;
import
?java.io.IOException;

/**?*/
/**
?*?<p/>?Title:
?*?</p>
?*?<p/>?Description:
?*?</p>
?*?<p/>?Date:2004-9-7?14:50:25
?*?</p>
?*?
?*?
@author
?EOMS?曲靜波
?*?
@version
?1.0
?
*/
public
?
class
?FacadeServlet?
extends
?HttpServlet?

{
???
public
?
void
?doPost(HttpServletRequest?request,?HttpServletResponse?response)?
throws
?ServletException,?IOException?

???
{
?????????
//
在web.xml中配置
?????????
//
<servlet>
???????
//
<servlet-name>FacadeServlet</servlet-name>
???????
//
<servlet-class>FacadeServlet</servlet-class>?
??????
//
<init-param>
????????
//
<param-name>100</param-name>
??????
//
<param-value>com.qujingbo.InsertDB</param-value>
??????
//
</init-param>
??????
//
<init-param>
????????
//
<param-name>101</param-name>
??????
//
<param-value>com.qujingbo.LoginCheckBusiLogic</param-value>
??????
//
</init-param>
??????
//
</servlet>
??????
//
通過頁面傳過來的action,以該實例為準,若jsp傳過來的action=100。這時String?action="com.qujingbo.InsertDB"
??????
//
web.xml中配置的內容可以寫入像struts那種struts-config.xml那種做為配置文件,定義規范,容器管理。
??????String?action?
=
?request.getParameter(
"
action
"
);
??????
if
(action?
==
?
null
?
||
?
""
.equals(action))?

??????
{
?????????System.out.println(
"
no?action
"
);
?????????
return
;
??????}
??????
try
?

??????
{
???????????
//
通過java反射機制實例化com.qujingbo.InsertDB
?????????String?strClassName?
=
?
this
.getInitParameter(action);
?????????Class?cls?
=
?Class.forName(strClassName);
?????????AbstractLogic?_AbstractLogic?
=
?(AbstractLogic)cls.newInstance();
?????????
//
調用execute方法,execute方法調用com.qujingbo.LoginUser類的doBusiLogic()方法?????????
?????????_AbstractLogic.execute(request,?response);
??????}
??????
catch
(java.lang.Exception?cfe)?

??????
{
?????????cfe.printStackTrace();
??????}
???}
???
public
?
void
?doGet(HttpServletRequest?request,?HttpServletResponse?response)?
throws
?ServletException,?IOException?

???
{
??????doPost(request,?response);
???}
}
給出它的
web.xml
<?xml?version="1.0"??>
<!DOCTYPE?web-app?PUBLIC?"-//Sun?Microsystems,?Inc.//DTD?Web?Application?2.3//EN"?"http://java.sun.com/dtd/web-app_2_3.dtd">
<web-app>
??<welcome-file-list>
????<welcome-file>index.jsp</welcome-file>
??</welcome-file-list>

??<servlet>
?????<servlet-name>FacadeServlet</servlet-name>
?????<servlet-class>FacadeServlet</servlet-class>?
????<init-param>
??????<param-name>100</param-name>
????<param-value>com.qujingbo.LoginUser</param-value>
????</init-param>
</servlet>
????<servlet-mapping>
????????<servlet-name>FacadeServlet</servlet-name>
????????<url-pattern>FacadeServlet</url-pattern>
????</servlet-mapping>

</web-app>

下一步介紹AbstractLogic這個抽象類。該類包含兩個方法。execute()方法調用抽象方法doBusiLogic()(其實是按配置具體實現類的doBusiLogic()方法)。有人會有疑惑為什么要用execute()調用doBusiLogic()方法呢?直接調用doBusiLogic方法不行嗎?其實這里有個小技巧。就像filter一樣,我們如果需要過濾些信息,只要寫在execute()方法最開始就OK,這樣,執行任意一個doBusiLogic()方法時,都會調用execute()方法。結束也一樣。注釋有說明。
package?com.qujingbo;

import?javax.servlet.http.HttpServletRequest;
import?javax.servlet.http.HttpServletResponse;

/**?*//**
?*?<p/>?Title:
?*?</p>
?*?<p/>?Description:
?*?</p>
?*?<p/>?Date:2004-9-7?14:50:25
?*?</p>
?*?
?*?@author?EOMS?曲靜波
?*?@version?1.0
?*/
public?abstract?class?AbstractLogic?


{
???//模板模式,實現類需要實現doBusiLogic方法,在該方法中寫業務邏輯
???public?abstract?void?doBusiLogic(HttpServletRequest?request,?HttpServletResponse?response)?throws?Exception?;
???public?void?execute(HttpServletRequest?request,?HttpServletResponse?response)?throws?Exception?

???
{
?????????//若想在業務邏輯前執行某方法,寫在這里
??????//System.out.println?("pre?call");
??????doBusiLogic(request,?response);
??????//若想在業務邏輯后執行某方法,寫在這里
?????????//System.out.println?("post?call");
???}
}

最后介紹要具體實現執行業務類LoginUser。LoginUser繼承AbstractLogic抽象類,實現doBusiLogic()方法。我們只需在doBusiLogic()方法內實現我們的業務邏輯就OK。LogicUer中的doBusiLogic()方法模擬了一個登陸過程。
package?com.qujingbo;

import?javax.servlet.http.HttpServletRequest;
import?javax.servlet.http.HttpServletResponse;
import?javax.naming.Context;
import?javax.naming.InitialContext;
import?javax.sql.DataSource;
import?java.sql.Connection;
import?java.sql.ResultSet;
import?java.sql.Statement;
import?javax.rmi.PortableRemoteObject;
import?loginEjbPac.LoginHome;
import?loginEjbPac.Login;

/**?*//**
?*?<p/>?Title:
?*?</p>
?*?<p/>?Description:
?*?</p>
?*?<p/>?Date:2004-9-7?14:50:25
?*?</p>
?*?
?*?@author?EOMS?曲靜波
?*?@version?1.0
?*/
public?class?LoginUser?extends?AbstractLogic?


{
???//實現登陸功能
???public?void?doBusiLogic(HttpServletRequest?request,?HttpServletResponse?response)?throws?Exception?

???
{
??????System.out.println("LoginUser");
??????Context?ctxt?=?null;
??????ctxt?=?new?InitialContext();
??????DataSource?ds?=?(DataSource)ctxt.lookup("jbPoolJndi");
??????Connection?con?=?ds.getConnection();
??????Statement?stmt?=?con.createStatement();
??????ResultSet?rs?=?stmt.executeQuery("select?*?from?test");
??????//模擬登陸
??????if(rs.next())?
?????????System.out.println(rs.getString("name"));
??????System.out.println("LoginEJB");
??????LoginHome?home?=?(LoginHome)PortableRemoteObject.narrow(ctxt.lookup("LoginEJBRemote"),?LoginHome.class);
??????Login?remote?=?home.create();
??????if(remote.checkLoginUser("aa"))?
?????????System.out.println("EJB?success");
??????remote.remove();
???}
}

OK
,全部結束,我們重新理下順序。首選通過
web.xml
配置
servlet
(
FacadeServlet
),通過
url
訪問
FacadeServlet
,以本實例為例,
url
地址為
http://yourip:yourport/yourservlet?action=100
,通過獲取
action=100
,在
web.xml
中取得對應的包名,類名。實例化它,由
FacadeServlet
調用
execute()
方法,
execute
方法調用的是具體實例化類的
doBusiLogic()
業務方法。整個過程結束。