【发布时间】:2010-11-27 09:47:31
【问题描述】:
虽然我已将此标记为 java/spring 问题,但可以轻松地询问任何具有无状态控制器的 mvc 框架。我知道 Rails 使用简单的无状态控制器,所以也许你们知道如何最好地解决这个问题。我可以最好地描述 java/spring mvc 的问题,它是实现 - 请原谅 java 行话。
问题
我们很难想出一种令人满意的方式来在 spring mvc 中执行无状态到有状态的切换。 本质上给出了这样的结构:
型号:Unit
状态:撤回、可用、不可用
以及操作:getOutline() 和 getHelp()
控制器:UnitController
带有操作:displayOutline() 和 displayHelp()
在执行displayOutline()操作之前,我们需要一种方法来检查单元的状态(因为单元本身可能会被撤回,因此用户应该被转发到撤回的页面)。
我们尝试了多种方式来做到这一点,包括:
最简单的方法(任何语言)
控制器中所有需要“可用”状态单元的方法在其实现的第一行调用方法 isAvailable()。显然这里有很多复制,很臭。
AOP 方式(Java 特有)
可以创建一个名为 UnitAccess 的 @Around 通知,它会检查并重新路由控制流(即,不是调用会调用底层方法的proceed(),而是调用控制器上的另一个方法)。这似乎是一种 hack,而不是真正的 AOP,它确实消除了复制,但增加了复杂性并降低了透明度。
拦截器(由 servlet 架构提供,但可能在其他框架中可行)
它检查单元状态并从根本上改变实际的 URL 调用。这似乎也不对。我们不喜欢在到达控制器之前调用模型逻辑的想法。
我们考虑过
命令模式
创建一个命令模式结构,它(使用继承)可以返回一个撤回的视图或有效的 displayOutline 视图。由于 execute 方法将在 super()call 中执行检查以及具体命令中的特定逻辑。即创建一个对象结构,如
DisplayOutlineCommand extends UnitCommand
public void execute(){
super();
// must be ok, perform getOutline()
}
最后,使用自定义异常
在服务级别对象上调用getAvailableUnit(),它将在返回单元之前检查可用性等。如果该单元被撤回,那么它将抛出一个 UnitWithdrawnException,该异常可以被 servlet 捕获并通过返回适当的视图来处理。还是不服气。我们也不热衷于使用异常进行正常流控制的想法。
我们错过了什么吗?在 spring/另一个无状态控制器框架下有没有简单的方法来做到这一点?
【问题讨论】:
-
对使用 AOP 的反思:我们认为这不是它的正确位置,因为我们通常认为横切关注点不应该“摆弄”它所使用的类/方法的主要功能。 “日志”或“事务管理”是 AOP 的重要用途,因为它们本质上是在不改变上下文的情况下进行装饰。控制器的主要功能是控制流程,使用 AOP 来处理控制器内部的流程似乎并不正确。
标签: java model-view-controller oop spring