Web开发中框架类的子类化与功能扩展
发布时间: 2025-08-17 00:51:48 订阅数: 5 

# Web开发中框架类的子类化与功能扩展
## 1. 子类化基础与注意事项
在Web开发里,子类化框架类是增强功能、适配特定需求的有效手段。当进行子类化时,需要对常量定义进行正确处理。例如,若要子类化`Response`类,头文件应如下编写:
```plaintext
* WCONNECT_OVERRIDE.H
* Application-specific overrides to WC framework constants.
*
* Subclass the Response class:
#UNDEF WWC_RESPONSE
#DEFINE WWC_RESPONSE MyResponse
*
* more subclassing as required..
```
这里使用`#UNDEF`编译器指令,其作用是在替换常量定义前,先移除之前的定义。若遗漏这一行,编译时会出现“Constant is already created with #DEFINE”的警告。
若管理多个应用程序,这种方法依然可行。若每个应用程序需要不同的子类定义,可将`WCONNECT_OVERRIDE.H`文件移至特定应用程序的路径。
不过,在处理多个Web连接应用程序且子类化框架类时,存在一个潜在问题。从命令窗口测试应用程序时,若在切换应用程序后直接运行主程序文件,框架类可能使用了不同应用程序的覆盖定义进行编译,这可能导致难以诊断和调试的问题。但运行编译后的EXE文件则不会有此问题。为避免该问题,切换到不同应用程序时,可先重新编译所有类,这样就能在Visual FoxPro中成功测试。
## 2. 适合子类化的框架类分析
### 2.1 wwServer类
`wwServer`类是运行应用程序的主要服务器对象的基础。在每个Web连接应用程序的主程序中,都会创建该类的新子类。为特定应用程序扩展此对象功能很简单,只需在主程序的类实现中添加代码。此外,还可创建`wwServer`的子类,让所有应用程序的服务器类都继承它,适用于要为多个应用程序添加额外服务器对象功能的情况。
从完整性角度看,扩展`wwServer`类的必要性不大,因为它已具备响应WC.DLL请求和调用自定义处理类的所有功能。但有一个原因可能促使扩展,即持久性。与每次请求都会实例化和销毁的`Request`、`Response`、`Process`和`Session`对象不同,`Server`对象会一直存在,直到EXE终止。因此,服务器可用于执行各种任务,如打开文件和设置环境。不过,更建议设计单独的工作类,并从`Server`对象实例化它们,以避免增加服务器类的复杂性。添加此类代码的最佳位置是`SetServerProperties()`方法,该方法会在处理第一个请求前被Web连接框架调用。
### 2.2 wwRequest类
`wwRequest`类用于封装每个Web请求的传入请求。多数情况下无需子类化,因为它已包含读取传入请求信息的基本功能。但以下情况可能需要子类化:
- 安装第三方ISAPI过滤器改变WC.DLL接收的信息时,可能需要一个或多个方法来解析这些额外信息。
- 若开发人员熟悉Active Server Page (ASP)技术,可能希望修改Web连接中的`Form`方法,使其能像ASP一样处理多选弹出框。
- 应用程序包含文件上传控件的表单时,`wwRequest`类缺少两个方法,无法灵活处理此类表单。例如,对于同一表单上的多选弹出框,Web连接没有读取弹出框值的方法,也没有验证表单变量是否存在的方法。以下是包含所需方法的子类:
```foxpro
DEFINE CLASS WebRadRequest AS wwRequest
* Sub-class of Web Connection wwRequest.
* --------------------------------------------------------- *
FUNCTION GetMultipartFormMultiple(taVars,tcVarName)
* Adapted by Randy Pearson from other methods in wwRequest class.
*
* This method retrieves multipart, multiselect HTML form variables
* from the request buffer into an array.
*
* Multipart form variables are submitted on the client side by
* specifiying an encoding type of "multipart/form-data":
* <form METHOD="POST" ENCTYPE="multipart/form-data">
* Parameters:
* @taVars
* An array that will receive the form variables. Pass by reference!!
* tcVarname
* The name of the form variable to retrieve.
* Returns:
* Numeric - count variables retrieved into the array.
* Example:
* DIMENSION laVars[1]
* lnVars=Request.GetMultipartFormMultiple(@laVars,"LastName")
* --------------------------------------------------------- *
LOCAL xx, lcValue, lnAt, lcFind, lcPointer
xx=0
lcPointer = THIS.cFormVars
lcFind = [NAME="] + m.tcVarName + ["]
lnAt = ATC(m.lcFind, m.lcPointer)
IF m.lnAt = 0
RETURN 0
ENDIF
* Following is required as of WC 3.20, which adds new handling of
* multi-part borders:
IF EMPTY(THIS.cMultiPartBorder)
THIS.GetMultiPartBorder()
ENDIF
DO WHILE m.lnAt > 0
lcValue = Extract( @lcPointer, ;
tcVarName + ["] + CHR(13) + CHR(10) + CHR(13) + CHR(10), ;
CHR(13) + CHR(10) + "--" + THIS.cMultipartBorder)
* Before WC 3.20, was: ** CHR(13)+CHR(10)+"---------"
xx = m.xx + 1
DIMENSION taVars[ m.xx]
taVars[ m.xx] = m.lcValue
lcPointer = SUBSTR( m.lcPointer, m.lnAt + LEN( m.lcFind))
lnAt = ATC( m.lcFind, m.lcPointer)
ENDDO
RETURN m.xx
ENDFUNC && GetMultipartFormMultiple
* --------------------------------------------------------- *
FUNCTION IsMultipartFormvar()
* Created by Harold Chattaway.
* Determines whether a form variable name was part of
* the current request submittal.
LPARAMETER lckey
LOCAL lcMultiPart, lnLoc
lcMultiPart = THIS.cFormVars
lnLoc = ATC([NAME='] + m.lckey + ['], m.lcMultiPart)
IF m.lnLoc=0
RETURN .F.
ELSE
RETURN .T.
ENDIF
ENDFUNC && IsMultipartFormvar
* --------------------------------------------------------- *
ENDDEFINE && WebRadRequest
```
### 2.3 wwResponse类
`wwResponse`类适合子类化,许多Web连接开发人员会这么做。它是轻量级类,性能良好。若为其添加过多属性和方法来自动化HTML的各个方面,性能会受影响;但添加额外方法可提高开发效率。建议先在最初几个项目中使用默认的Web连接类,确定有提高效率的需求后再进行子类化。也可创建辅助类,在需要时再实例化,如Web连接提供的`wwShowCursor`和`wwDbfPopup`类。
### 2.4 wwProcess类
`wwProcess`类是应用程序的核心。开发多个应用程序时,必然会找到扩展该类以满足自身风格和需求的方法,扩展可能性几乎无限。
### 2.5 wwSession类
`wwSession`类为Web连接应用程序管理状态提供了便利工具。虽然该类可子类化,但并不简单,尤其是要使用`wwSessionSQL`类将会话数据迁移到SQL Server时。而且,子类化的潜在原因相对较少。
最常见的原因是,在大多数或所有处理方法中都需要引用某个会话变量。会话变量的名称和值以XML格式存储在`wwSession.DBF`的`Vars`备注字段中,读取值时需解析该字段。此时,可在数据结构中添加特定于该会话变量的字段,直接读取其值,而非解析`Vars`字段,以提高会话对象的性能。但要使用此技术,还需创建存储和读取该字段数据的方法,且不会自动实现。查看这些类的源代码会发现,实现此类更改并不容易,因为有几个整体方法嵌入了整个数据结构,为添加一两个额外字段,可能需将整个方法复制粘贴到子类中,这会使每次Web连接发布新版本时都处于危险境地。
### 2.6 wwHtmlHeader类
`wwHtmlHeader`类是一个可选类,可轻松封装创建HTML响应详细`<head>`部分的手动过程。它已有添加JavaScript、级联样式表 (CSS) 链接等常用功能的便捷方法,但并非涵盖所有需求。虽可通过内置的`AddMetaTag()`方法或直接操作`cHeadSection`属性来满足其他需求,但这要求了解HTML文档此部分的复杂语法。而且,`AddMetaTag()`方法仅涵盖`<meta>`标签中`name`属性的使用,有时还需使用`http-equiv`属性(如添加内容评级信息)。因此,该类很适合子类化。
以下是添加了一些额外功能的简单子类:
```foxpro
#INCLUDE WCONNECT.H
DEFINE CLASS MyHtmlHeader AS wwHtmlHeader
* --------------------------------------------------------- *
FUNCTION AddMetaEquivTag
* Adds a META tag
```
0
0
相关推荐










