treefrog 之控制器
来源:互联网 发布:unity3d百度地图映射 编辑:程序博客网 时间:2024/06/04 22:12
控制器
控制器是网页应用程序的关键类.它接收浏览器的请求, 从模型(model)的角度调用业务逻辑, 在基本的结果上生成视图(view)的HTML, 返回请求响应.
定义操作(Actions)
操作(action)是基于请求URL的一种叫法, 它决定了调用控制器(controller)定义的何种方法.让我们给已经生成的骨架上增加一些操作(Action).首先, 在头文件声明的’pulic slots’部分的操作(action).请注意,如果你希望增加操作(action)的参数时, 这些参数应该声明成QString类型.当你声明任何其类型时,它们将不被识别(通过正常的方法).最多可以定义10个参数.
class T_CONTROLLER_EXPORT FooController : public ApplicationController{ Q_OBJECT :public slots: // 动作(action)定义在这里 void bar(); void baz(const QString &str); :
完成后, 按照往常一样实现这些操作(actions).
操作(action)的选择判断
当一个URL字符串被请求时, 需要决定哪个操作(action)被调用才是正确的.默认情况下,将使用下面的规则.
/controller-name/action-name/argument1/argument2/ ...
这些参数将被当成”操作(Action)参数”.如果使用了超过10个参数, 只有10个参数有效.如果你希望使用11个或者更多参数,请按照下面的方法使用Post或者URL数据参数.这里有一些具体的例子.BlogContrller类的操作(actions)被每个用例调用.
/blog/show -> show();/blog/show/2 -> show(QString("2"));/blog/show/foo/5 -> show(QString("foo"), QString("5"));
如果省略操作(Action),默认情况下会调用index操作.这个看起来像这样:
/blog -> index();
如果请求的URL对应的操作(action)没有定义, 将返回状态码500(内部服务器错误)给浏览器.在大多数情况下,每个调用的操作(action)都会进行以下处理过程:
- 请求的审查
- 访问cookies和会话
- 访问上传的文件
- 调用模型(业务逻辑)
- 传递变量到视图(view)
- 请求建立HTML反馈
这些对于编程者来说,通常意味着许多的工作和大量的代码编写.因此, 导致的结果就是一些人编写了一些庞大而且复杂的控制器(controller).为了防止这种情况, 请仅在模型(model)实现业务逻辑.你应该一直保存控制器尽可能的简单.一旦你明白了操作(action)如何调用的机制, 还能够通过URL客户化操作(action).更多信息请参见URL 路由.
获取请求
一个HTTP请求由THttpRequest类表示.在控制器(controller)中, 你可以用httpRequest()方法获得ThttpRequest对象.
const THttpRequest & TActionController::httpRequest () const;
你可以在这里获得各自数据.
接收请求数据
从浏览器发送的HTTP请求包含方法(method), 头(header), 主体(body).到达服务器的数据,可以通过以下方式:
- post数据 - 使用POST方式从表单提交的数据
- URL参数(查询参数) - 附加在URL上在”?”后的参数,(格式为Key=value&…)*Action参数 - 在Action后的参数(“blog/edit/3”的第三部分) <-见上面的内容.
接下来的例子说明了如何在控制器中获取post数据.我们假设视图中已经有了一个input标签.
<input type="text" name="title" />
在服务器端要获取浏览器发送给控制器的值, 使用下面的代码:
QString val = httpRequest().formItemValue("title")
同时, 如果你希望将值转变为int整形, 可以使用Qt的toInt()方法.如果有大量的数据项发送,一个一个的获取显得有点麻烦.这里有另外的一种方法一次性获取所有数据.例如, 你可以将标签写成这样:
<input type="text" name="blog[title]" /><input type="text" name="blog[body]" />
在控制器内, 可以这样获得数据:
QVariantMap blog = httpRequest().formItems("blog");QVariant t = blog["title"];QVariant b = blog["body"]; :
请求的数据可以表现为hash格式.如何获取URL参数(查询参数)?这里有个例子:
http://example.com/blog/index?mode=normal
你可以使用下面的方法获得blog控制器(controller)的Index操作(action)的mode的值.
QString val = httpRequest().queryItemValue("mode"); //val ="narmal"
同时, 如果你想获得不是URL参数和post数据的数据, 你可以使用allParameters()和methods().为了在应用服务器端检查请求的数据是否是要求的形式, 还提供了验证器功能.更多信息请参见验证器章节.
传递变量到视图(view)
要传递变量到视图(view), 使用texport(variable)或者T_EXPORT(variable)宏.你可以指定的参数类型为QVariant,int,QString, QList, 或者 QHash. 当然你也可以指定一个自定义的模型(model)这儿是它的用法:
QString foo = "Hello world";texport(foo);// 或者int bar;bar = ...texport(bar);
说明:texport的参数必须指定为变量.你不能直接指定一个字符串(“Hello world”)或者数字(例如100).在视图(view)内要使用变量, 你必须首先用tfetch(Type,variable)声明变量.更多详细内容请参见视图(view)章节.
简单地说: 使用tfetch()传递一个对象到视图(view).
** 用户自定义的类的情况**当你需要传递一个新的类(自定义的类)到视图(view), 请件下面的宏增加到头文件的尾部.更多详细的信息请参见 “新建原始模型(original model)”节.
Q_DECLARE_METATYPE(ClassName) // 请更换类名
Qt Q_DECLARE_METATYE已经提供的类不需要再声明.但是,如果需要传递一个模版类,声明还是需要的,如QHash和QList在这个列子中, 请在helpers/applicationhelper.h尾部添加下面的内容
:Q_DECLARE_METATYPE(QList<float>)
Q_DECLARE_METATYPE 宏的参数是一个类名. 但是,如果你包含了一个逗号(如 QHash <Foo, Bar>), 将会产生编译错误.在这种情况下, 名字应该使用typedef QHash <Foo, Bar>来声明.
typedef QHash<Foo, Bar> BarHash;Q_DECLARE_METATYPE(BarHash)
导出对象
我们视导出对象到视图(view)(在texport()方法设置的对象)为”导出对象”.
请求建立反馈内容
在处理完业务逻辑后,处理的结果作为HTML反馈将会返回.如果BlogController show 操作(action)被执行, 在views/blog/show.xxx中的反馈内容被模版名(扩展名基于模版系统)生成.要请求反馈内容, 你可以使用render()方法.
bool render(const QString &action = QString(), const QString &layout = QString());
如果你想反馈一个不同的模版,指定操作(action)名为参数即可.布局(layout)文件名可以被指定为布局参数.方法render()表示”请求 view/template 建立反馈内容”.这也称之为”绘图(drawing)”.
简单地说:要渲染模版,使用 render() 方法.
布局(Layout)
当年创建一个网站的是, 网页页眉,网页页脚还有一些其他的部分通常所有的页面中是通用的, 只是网页的内容不同而已.术语布局(layout)是给这些通用的部分使用的, 模版基于这些通用的部分.布局(layout)文件应该放在views/layouts文件夹内.
关于模版系统
TreeFrog目前为止采用了两种模版系统:Otama和ERB.在ERB内,代码通过<%…%>嵌入.在Treefrog内,Otama系统有不同的处理方式, 因为它完全分离了逻辑(.tom) 和界面模版(.html).
- ERB 使用文件扩展名: xxx.erb
- Otama 使用文件扩展名: xxx.otm和xxx.html
(xxx指操作(action)的名称)
定向到渲染一个字符串
要直接渲染一个字符串,使用 renderText()方法.
// "Hello world" 渲染这个字符串renderText("Hello world");
默认情况下, 是不使用布局(layout)的.如果想要使用布局, 你需要指定第二个参数为true.
// 渲染字符串 "Hello world" 同时使用布局(layout)renderText("Hello world", true);
关于布局(layout)的更多详细的信息请参见 视图(view) 章节.
重定向
要重定向浏览器到另外的URL, 可以使用redirect()方法.第一个参数, 指定一个QUrl类的实例.
// 重定向到 www.example.orgredirect(QUrl("www.example.org"));
你可以重定向到同一台主机的其他操作(action)上.
/ 重定向到Blog控制器的index操作redirect( url("blog", "index") );
下面是另外一个有用的url方法.它在你传递控制器名和操作名时返回相应的QUrl实例.要重定向到同一个控制器内的其他操作,可以忽略控制名.
// 重定向到同一个控制器的show操作redirect( urla("show") );
使用 urla()方法是非常重要的.
在重定向目标页显示信息
重定向指向了另外一个URL.这是因为, 从服务器的视角看, URL接收到了一个新的目标页,这样产生了调用另外一个控制器的操作的效果.Treefrog框架 有一种机制(通过变量)可以实现传递信息到重定向的控制器上.见下面的例子使用tflash()或T_FLASH()方法传递变量.
// foo - 瞬时对象(flash object)QString foo = "successfully";tflash( foo );
传递的对象在这里叫做”瞬时对象(flash object)”.瞬时对象(flash object)转换成重定向后的视图(view)的输出对象.正因为如此, 它能够被echo()或者eh()方法输出显示信息.
使用瞬时对象(flash object)的好处
事实上, 你可以创建一个完全没有瞬时对象(flash object)的网页应用.然而, 在遇到合适的情况下, 如果你使用它, 代码变得非常容易理解(一旦你开始用它).我个人认为保持每个操作(action)完全对立,减少各个操作(action)之间的依赖是比较好的也比更容易理解.我建议不要在单个请求上调用超过一个以上的操作(action).尽可能的保存一个请求一个操作(action)的关系.使用瞬时对象(flash object)时, 如果为几乎相同的内容建立独立分离的显示, 代码可以变得简单些.blogapp (教程)使用create 和show 操作(action)的方式就是一个好的例子.虽然这些操作(action)的处理是不一样的,但都是仅仅显示一条blog的处理结果.在create操作, 成功完成录入后, 这个结果将显示在重定向的show操作上.同时,这个信息”Created successfully.”通过使用瞬时对象(flash object)显示.事实上, 一个应用不会都是这么简单的, 因为不是经常需要获取和使用瞬时对象(flash object).因此, 适度地使用它好了.综上所述, 在实践中大部分的操作(action)都归结于使用redirect()或者render()方法.
顺便说一下
按照上面所说的方式, 但一个重定向发生时,一旦访问到达服务器时处理就被中断了(服务器返回新URL,客户端按新URL再次发出请求).鉴于瞬时对象(flash object)是通过会话的方式实现的, 存活下来的对象可以在其他操作(action)环境下使用.
staticInitialize() 方法
当启动后, 程序只有一个进程.你可能希望提前从数据库读取一些初始化信息.这种情况下, 将处理过程写在ApplicationController#staticInitialize()内.
void ApplicationController::staticInitialize(){// 处理过程..}
当服务器进程启动后, staticInitialize()方法只会调用一次.然而,当你选择在MPM)中描述的PreFork 后,你必须要关注它, 不要让每次进程启动时建立太多的加载功能.
控制器(controller)实例的生命周期
控制器(controller)的实例在被调用前创建, 当操作(action)执行完后被销毁.这意味着控制器的创建和销毁是基于每个HTTP请求的.
这样规定后, 控制器(controller) 通常没有实例变量.请按同样的方式实现ApplicationController.
- treefrog 之控制器
- TreeFrog 之生成器
- treefrog 之模型
- treefrog 之测试
- treefrog 之发布
- treefrog之视图 ERB
- TreeFrog Framework 开发入门之HelloWorld
- treefrog之视图 Otama模版系统
- C++网站开发MVC框架TreeFrog Framework教程——5.控制器
- TreeFrog (C++ Web Framework)开发之源码分析
- TreeFrog (C++ Web Framework)开发入门之使用Qt编译
- TreeFrog (C++ Web Framework)开发之http文件服务器
- TreeFrog (C++ Web Framework)开发之源码分析
- Treefrog应用程序
- TreeFrog折腾记(1)
- TreeFrog折腾记(2)
- 微程序控制器之微程序控制器构成
- msp430之DMA控制器
- hadoop学习笔记
- 剑指offer-输入两棵二叉树A,B,判断B是不是A的子结构(ps:我们约定空树不是任意一个树的子结构)
- 上传app Store时Error : This action could not be completed(-22421)
- 关于单实例多线程的servlet的线程安全问题的探讨
- java导出word带图片png格式的
- treefrog 之控制器
- ubuntu安装交叉编译器
- vue2手机APP项目中,加入开屏广告或者闪屏广告
- 欢迎使用CSDN-markdown编辑器
- 编程小技巧之mysql数据库自我复制
- day14
- Java反射机制的学习
- 【转】kalman滤波介绍
- treefrog 之模型