网络上有很多介绍
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()
业务方法。整个过程结束。