代码放哪?
因为xwiki允许你把代码放在wiki页面或者放在java,你可能会问,应该把代码放哪。下面是一些一般原则:
- 不要把"业务逻辑"代码放在wiki页面,应该放在Java。因为放Java可以通过IDE方便地调试代码,并可以编写单元测试用来自动测试。一般来说它更容易维护。
- 一般来说,尽量少在wiki页面写一些脚本,因为这会让他们难以维护。
- 只有"表现层逻辑"脚本适合放在wiki页面(而不是在Java代码!),即脚本负责呈现通过Java/REST API检索到的数据。
换句话说,你应该使用MVC模式来把你的View (我们称之为“表现层逻辑”)分离出你的Model (我们称之为“业务逻辑”)。
XWiki应用程序组织
- XWiki开发团队的最佳实践
- XWiki应用程序组织的最佳实践 (Ludovic Dubost建议)
在Class Sheet文档检查对象是否存在
Class sheet文档应当写入以下结构(以下例子是检查文档是否包含XWiki.XWikiUsers对象):
#set($obj = $doc.getObject("XWiki.XWikiUsers"))
#if(!$obj)
1 User Sheet
This stylesheet must be applied on a document containing a XWiki.XWikiUsers object.
#else
1 $msg.get("userProfile", [$xwiki.getUserName($doc.fullName, false)])
...
#end
'if'判断为不存在,XWiki可以提取1 User Sheet为标题,当访问sheet页面时,这是适当的标题,而不是直接显示一些错误信息。
当对non-Javascript UI界面使用xredirect处理错误
当使用Javascript编写一个UI界面时,AJAX负责转发你的action到后台服务来响应成功或者失败,然后在同一页面展示结果。
当没有使用JavaScript时,我们通常使用xredirect查询参数来指定当前页面(及状态),这是我们想要通过执行一个action(通过按下一个按钮,链接,提交一个表单等)后返回。
一个常见的问题,当按这种不通过JavaScript编写一个UI界面是一种错误的处理方式。换句话说,当你使用这种方式来执行你的action导致服务抛出一个错误时,你如何处理这种情况?
一个简单的代码用于后台服务处理错误:
#handleRequest($success)
#if ($success)
#if ($request.action == 'get' || $request.xpage == 'plain')
## JavaScript call here.
Action was successful.
#elseif ("$!request.xredirect" != '')
## No-JavaScript here. Redirect.
$response.sendRedirect($request.xredirect)
#end
#else
#if ($request.action == 'get' || $request.xpage== 'plain')
## JavaScript call here.
Action was NOT successful.
$response.setStatus(403)
#elseif ("$!request.xredirect" != '')
## No-JavaScript here. What now!? Redirect?
#handleErrorHere($request.xredirect)
#end
#end
这个想法是,你要传递错误信息给UI界面,但你没有一个明确的方式来做这件事,就像你对AJAX调用(响应代码和响应文本)。一个解决方案是使用session会话来传递错误信息。你可以服务中设置错误,并在用户界面中,你可以读取并删除它,以便它只显示一次。
对于后台服务,将其转换为:
...
#elseif ("$!request.xredirect" != '')
## No-JavaScript here. Redirect and forward error message.
#set ($errorMessageKeyPrefix = "myModule.error.")
$request.session.setAttribute("${errorMessageKeyPrefix}${request.xredirect}", 'Action was NOT successful')
$response.sendRedirect($request.xredirect)
#end
...
在UI界面端:
...
#set ($xredirect = $doc.getURL($context.action, $!{request.queryString}))
#set ($errorMessageKeyPrefix = "myModule.error.")
#set ($errorMessage = $request.session.getAttribute("${errorMessageKeyPrefix}${xredirect}"))
#if ("$!errorMessage" != '')
## Clean the error and display the message.
#set ($discard = $request.session.removeAttribute("${errorMessageKeyPrefix}${xredirect}"))
{{error}}$errorMessage{{/error}}
#end
...
注意,使用xredirect的值作为session key(加前缀或者不加)是一个很好的主意,这是因为:
- 它已经存在于用户界面(发送它作为参数)和后台服务(接收作为参数)
- 它就像一个命名空间,确保错误只显示当前页面或者请求。
使用一个如上面例子的前缀允许在同个页面有多个组件(wiki宏, 小工具等)而不相互冲突。
这种方法可以重定向当前页面(以便用户可以刷新页面而不重新发送action或重新提交表单),确保在第一次显示之后,在刷新时,错误会消失。