[Delphi] YxdIOCP 之 MVC 简介

原文地址: http://www.cnblogs.com/yangyxd/articles/5993764.html

YxdIocp:  https://github.com/yangyxd/YxdIOCP

 

最近为 YxdIocp 开源库增加了这个轻量级的 MVC 支持。其实说是 MVC ,但由于现在还没有配套的视图模版引擎,所以在V上面很虚弱。不过本着做数据服务为主的思想,现在已经基本够用了。下面来简单介绍一下它吧。

要使用 MVC 功能非常简单, 引用 iocp.Http.MVC 单元,或者在窗体上放入一个 TIocpHttpMvcServer 组件即可。然后就是编写业务代码 (可参考开源库中 demo\IcopHttpSvrMVC 中的代码)。iocp.Http.MVC 引入了多个属性标注,它是 MVC 的灵魂,要用好 MVC, 必须了解这些属性标注的功能和意义。MVC引擎会使用扫描器根据这些标注自动扫描注入,响应客户请求。

在此之前,我们需要注意一点,在 Delphi 中, 属性标注定义的名称尾部如果是 “Attribute”,  在使用时可以直接省略后面的 “Attribute” ,比如定义了“ServiceAttribute”标注,使用时可以只输入 “[Service]” 即可。下面讲到的属性标注,都是省略掉了 “Attribute” 。

 

一、属性标注说明

[Service]

业务层标识性标注,为指定类添加此标注后,此类才会被MVC引擎识别,从而具备业务请求处理能力。

 

在上面的示例代码中,由于加入了 [Service] 标识,会被 MVC 扫描器发现该类,并自动创建一个单例用于响应业务请求。

 

[Controller]

控制层标注。增加此标注后,指定类才具备处理业务请求的能力。此标注和 [Service] 功能一样,只是方便在一些情况下区分业务类别。

 

[Autowired]

自动装配标注。为一个类中的变量增加此标注后,MVC 引擎会在实例化此类时,为这个成员变量自动注入适当的值。(目前由于暂无IOC实现,只能自动注入TIocpWebSocketServer、Ser ver)

 

程序运行后,会自动将 FServer 初始化为 HttpMVC.Server 。

[RequestMapping]

请求地址映射标注。此标注可用于类级别,也可用于类中的函数或方法上。

此标注有如下几个属性:

  • Value:  指定请求的实际地址。
  • Method: 指定请求的method类型, 它是 TIocpHttpMethod 类型的枚举值,可以是 GET、POST、PUT、DELETE 等。
  • Consumes: 指定处理请求的提交内容类型(Content-Type),例如application/json, text/html。
  • Produces: 指定返回的内容类型,仅当request请求头中的(Accept)类型中包含该指定类型才返回。
  • Params: 指定request中必须包含某些参数值时,才让该方法处理。
  • Headers: 指定request中必须包含某些指定的header值,才能让该方法处理请求。

注意: 在类级别使用此标注时, Params 属性无效。类级别主要用于设置URL的基址,以及一些默认值。比如在类级别指定 Method 为 Post,那么类中的函数或方法映射时,如果未指定 Method, 那么默认就是 Post。另外,在函数或方法被触发时,以下类型的参数会被自动注入:

  • TIocpHttpRequest: 自动注入为当前Request对象。
  • TIocpHttpResponse: 自动注入会当前Response对象。
  • TIocpHttpServer: 自动注入会当前Server对象。
  • TIocpWebSocketServer: 启用 WebSocket 时,自动注入当前 Server 对象。
  • TIocpHttpWriter: 自动注入 Response.GetOutWriter 对象,用于直接输出返回数据。
  • TIocpHttpConnectionTIocpClientContext:自动注入当前连接对象(Request.Connection)。
  • TMemoryStream 或基于 TStream: 自动注入当前请求的数据流对象(Request.Data)。

另外,如果参数名是 “RequestData”, 且为字符串类型时,自动注入 Request.DataString 。

 

示例

 

如果服务器Host是: http://127.0.0.1:8080,

那么,

 

URL: http://127.0.0.1:8080/view1

HTTP: 不限(GET, POST, PUT…)

触发: THelloMvc.View1

 

URL: http://127.0.0.1:8080/view2

HTTP: GET

触发: THelloMvc.View2

 

URL: http://127.0.0.1:8080/view3/aaa?uid=123

HTTP: GET

触发: THelloMvc.View3

 

URL: http://127.0.0.1:8080/view3/aaa?uid=789

HTTP: GET

触发: 无,返回405错误

 

URL: http://127.0.0.1:8080/view3

HTTP: GET

触发: 无,返回404错误

 

URL: http://127.0.0.1:8080/view4?uid=123

HTTP: GET

触发: 无,返回405错误

原因: 没有在Http Header 的”Content-Type”属性中添加 “application/JSON”,需要使用类似下面的请求头才可以正常访问:

使用上面的请求头,会触发 THelloMvc.View4 。

 

[Download]

标识请求返回页面采用下载方式。加入此标注后,会在Http响应头中加入文件下载标识,浏览会以文件下载的方式读取数据,一般会提示用户保存文件。

[WebSocket]

WebSocket 请求处理标注。当类中的一个函数或方法要用来处理 WebSocket 请求时,需要添加此标注。此标注不能与 [RequestMapping] 混用。

此标注有如下几个属性:

  • Data: 指定仅当Data为指定内容的文本消息时才响应。

[PathVariable]

这是一个参数级的属性标注,用来获得请求url中的动态参数,并绑定到处理函数中指定参数上。如果参数类型与实际传入的内容不符,会产生 500 错误。

此标注有如下几个属性:

  • Name: 当方法参数名称和需要绑定的uri template中变量名称不一致时, 用于指定uri template的名称。如果一致,可以省略。

URL中的动态参数,需要以 “{}” 包围起来。

 

示例中,{uid}、{uname} 都是url级的动态参数。通过 PathVariable 标注将它们分别绑定到了处理函数 ViewTest1 的参数 UID 和 UName 上。在触发 ViewTest1 时,UID 的值就是 {uid} , UName 就是 {uname} 。

 

[RequestParam]

这是一个参数级的属性标注。用于将请求参数区数据映射到功能处理方法的参数上。如果实际URL中参数不存在时,会将参数置为空(如数字型会是0,字符串会是空串)。如果参数类型与实际传入的内容不符,会产生 500 错误。

此标注有如下几个属性:

  • Name: 参数名称。

示例中,当 url 是 http://host/demo/view4?uid=123456 时, 触发 ViewTest4 时,参数 UID 的值会是 123456。

 

[RequestBody]

这是一个函数(方法)级的属性标注。它的作用如下:

1. 读取Request请求的body部分数据,使用系统默认配置的Converter(转换器)进行解析,然后把相应的数据绑定到要返回的对象上;

2. 再把Converter返回的对象数据绑定到controller中方法的参数上。

示例:

在触发 RegUser 函数时, 转换器会将请求的数据注入 Data 中。在编写转换器时,GET请求一般需要单独处理。

转换器示例:

设置 HttpMvc.OnDeSerializeData 事件,在事件中进行处理:

在上面的反序列化操作中, Dest 实际上就是标注了 RequestBody 的响应函数中的正要注入的参数,在示例中就是 Data: TUserData。

如果有这样的一个Post请求:

在触发 RegUser 时, 参数 Data 的值会是:

Name    Value
Data    (666, 30, ‘yangyxd’, ‘喵喵’)

 

[ResponseBody]

这是一个函数(方法)级的属性标注。它的作用如下:

将Controller的方法返回的对象,通过适当的Converter的Adapter转换对象, 将内容转换为指定格式后,写入到Response对象的body数据区。

在触发 Porfile 函数时, 返回值 TPerson 会被转换器转换序列化为指定格式,然后写入 Response 对象, 返回给客户端。

设置 HttpMvc.OnSerializeData 事件,在事件中进行处理:

如果在 Porfile 中的返回内容是:

通过使用上面的转换器, 在触发 Porfile 函数后,浏览器收到的数据会是:

 

二、映射函数返回值

普通WEB请求:

无返回值时, 会返回客户端 200 状态。

返回字符串时, 会返回一个  Prefix + 返回值 + Suffix 的文件。如果文件不存在,则返回 404 错误。

返回整数时, 认为是错误代码。比如返回 404, 则浏览器会收到 404 错误。

返回对象(Class) 或记录(Record)时,如果标注了ResponseBody,会使用转换器转换后输出给客户端。如果没有标注 ResponseBody, 则直接返回 200 状态。如果返回的是对象,会自动释放对象。

 

WebSocket 请求:

无返回值时, 服务器不作任何响应。

返回字符串时,会直接将字符串发送给客户端。

返回数据时,会将数据转为字符串后发送给客户端。

返回对象(Class) 或记录(Record)时,如果标注了ResponseBody,会使用转换器转换后输出给客户端。如果没有标注 ResponseBody, 服务器不作任何响应。

三、 MVC 服务器配置

在窗口上放置 TIocpHttpMvcServer 组件时, 通过组件属性面板进行设置。

不使用 TIocpHttpMvcServer 组件时, 引用 iocp.Http.Mvc , 会自动开启 MVC 服务。此时会自动加载配置文件 “http_mvc_setting.xml“。

配置文件应当放于服务程序相同目录中,文件名为 “http_mvc_setting.xml”

配置文件示例:

 

配置文件说明:

ListenPort: 服务器监听端口

Active: 是否在程序运行后自动开始服务

Charset: 默认字符集

UseWebSocket: 是否使用WebSocket服务

ContentLanguage: 默认内容语言

WebPath: WEB服务文件根目录

Prefix: 返回视图的前缀名称,默认为空

Suffix: 返回视图的后缀名称,默认为空

UriCaseSensitive: URI是否大小写敏感

BindAddr: 服务器端口绑定地址,默认为“0.0.0.0”

GzipFileTypes: 自动使用gzip压缩数据的文件类型

AutoDecodePostParams: 自动解析Post方式传入的参数

UploadMaxDataSize: 上传文件的最大大小(字节)。

AccessControlAllow: WEB请求跨域控制选项。

Enabled: 是否启用跨域控制

Origin: 允许哪些url可以跨域请求到本域

Methods: 允许的请求方法

Headers: 允许哪些请求头可以跨域

 

分享到:

0 条评论

沙发空缺中,还不快抢~