已经转移到
好·色之徒--我的博客、我的生活先来说说如何搭建MVC中最重要组成部分C
其实就是一个Servlet,当然我们主要是基于http的web应用,所以这里需要讲述的是关于HttpServlet的。
我们通过继承HttpServlet,创建一个控制器,这里暂且命名为:UctServlet。
HttpServlet主要有三个方法:init,service,destroy,这三个需要我们在UctServlet中详细实现它,先看一段代码
public void init(ServletConfig config) {
try {
super.init(config);
poSCtxt = getServletContext(); //定义了私有成员变量poSCtxt,以获取ServletContext
UctProperties.setServCtxt(poSCtxt); //UctProperties类(共通类),存放一些基础资源,比如数据库信息
DBA = new UctDBIO(); //定义了私有成员变量DBA,UctDBIO类(共通类),关于数据库操作的
psConn = DBA.connect(); //定义了私有成员变量psConn,初始化取得数据库的连接
} catch (Exception e) {
logger.error("UctServlet_init error", e);
}
}
这是在容器启动的时候触发的方法,在init方法中,初始化了一些固有的资源,比如ServletContext、数据库的相关操作,
这是非常必要的,因为这些资源对整个web系统来说一直需要使用,在init中加以初始化,为整个应用节省了很多不必要的开支,
也是系统提升性能的关键措施之一。
public void destroy() {
logger.info("UctServlet destroy.IN & DisConnect Conn = " + psConn);
try {
DBA.disconnect(); // 数据库连接解除
} catch (Exception e) {
logger.error("UctServlet destroy.Error, UctServlet disconnect-Error");
}
}
这是在容器停止的时候触发的方法,用于清除一些资源,比如说数据库资源。
上面两个方法一看就明白,比较简洁,最关键的方法,也是实现C功能的方法是service方法。
这里先探讨一下接收页面请求,实现控制资源分配、页面流转的要素有哪些?
一种方式是:所有的请求都交由service来实现,包括数据分析、数据装配,最后到forward到某一个资源,
当然可能需要一些辅助的help类,这样实现的,service方法会变的很庞大,而且请求的变数很大,
系统从功能上来说很单一,一旦有所变化,那么service方法需要大的改动。这是不可取的。
第二种方法:对请求首先进行一定的限制设计,比如:有两个参数Window(某一画面)和Action(某一动作),
分别表示画面和动作,然后在数据库或是xml文件中来设置你的相关配置,举例如下:(在数据库中)
alink atype window_id action_id
HAAap BEAN WIN_HGA HAA ----年度计划画面 初始的一种状态
HAAap BEAN WIN_HGA SRDT ----SRDT表示年度计划画面上的检索功能
HAAap BEAN WIN_HGA DTIL ----DTIL表示年度计划画面上的详细画面功能
HBAap JSP WIN_HGA HBA ----执行计划画面 初始的一种状态
。。。
类似这样的设计
对这几个字段说明一下:
window_id、action_id是对应画面传过来的两个参数,一个代表具体某一画面,一个是该画面上所有可能需要触发的动作,
比如:初始态、检索、增加、删除等等。
alink是这个体系中M的部分(bean的概念),是针对比如年度计划画面所有的操作,这个很关键。
具体的业务逻辑处理都在其中实现,而且可以看到命名也是很刻意的HAAap--HAA,HBAap--HBA,这样很容易区分是属于哪个画面的。
最后atype,这里设计了三种形态:BEAN、JSP、HTML,怎么来理解呢?BEAN就是刚刚提到的HAAap、HBAap这类的有业务逻辑在里面的,
JSP是直接用到了数据bean,而不需要关联的业务逻辑,而HTML则直接到页面资源,不需要辅助的bean。
这是第二种方法,把核心业务都交由bean去处理,service方法主要关注分发这些业务,
具有更好的扩展性、稳定性,方法也变得简洁明了,容易维护,推荐使用这样的方法来实现MVC模式,具体的做法下面给我一些代码片断:
String sbsWindow = req.getParameterValues("Window"); //获取Window画面参数
String sbsAction = req.getParameterValues("Action"); //获取该画面的动作参数
//在数据库中获取相关处理资源(alink atype)
if (!sUser.getFuriwake(DBA, sbsWindow, sbsAction)) {
errPage(req, res, "UctSevlet AP-CALL.IN", "数据库中没有定义处理动作");
return;
}
String sType = sUser.getApName(); //(BEAN/JSP/HTML)三种类型 atype字段
String sWindow = sUser.getApType(); //画面处理具体的类 alink字段
下面是处理的核心部分:
switch (iType) {
case 1: // ** APP Bean Call **
try {
String wAppId = sPktName + "." + sWindow; //sPktName是包的名字
Class genClass = Class.forName(wAppId); // APPBean的获取
// APPBean实例的取得
appBean = genClass.newInstance();
Class prmClass[] = {
javax.servlet.http.HttpServletRequest.class,
javax.servlet.http.HttpServletResponse.class,
javax.servlet.http.HttpSession.class };
Method mthd = genClass.getMethod("apexec", prmClass); // APPBean的起动方法
Object param[] = { req, res, appSession }; // APPBeann的起动方法的参数的设定
mthd.invoke(appBean, param); // APPBean起动
} catch (ClassNotFoundException e) {
略。。。
}
break;
case 2: // ** JSP 直接调用 (通过DB自动生成bean后) **
try {
Class genClass = Class.forName(sWindow + "Bean"); // JSP用Bean名取得+生成
appBean = genClass.newInstance(); // JSP用Bean的生成
req.setAttribute(sWindow + "Bean", appBean);
} catch (ClassNotFoundException e) {
略。。。
}
this.fCallPage(req, res, sWindow + ".jsp"); //触发JSP资源
break;
case 3: // ** HTML 直接调用 **
boolean wSts = this.fCallPage(req, res, sWindow + ".jsp");
if (wSts == false) {
errPage(req, res, sWindow + ".jsp/.html",
"File_Not_Defined!!");
return;
}
break;
default: // ** 如果没有定义三种类型之一 **
//错误画面
errPage(req, res, sWindow + ".jsp/.html",
"Furiwake_DefinE Not_Defined!!");
}
这是MVC中C的部分(UctServlet类)的介绍,相应的代码作为修改,为了理解学习之用
不借助任何web框架结构,构建自己的MVC应用程序(1) 有个论坛