简体   繁体   English

Java Spring MVC无状态到有状态切换

[英]Java Spring MVC stateless-to-stateful handover

Although I have tagged this as a java/spring question it can be easily asked of any mvc framework with stateless controllers. 尽管我已将此问题标记为java / spring问题,但可以很容易地询问具有无状态控制器的任何mvc框架。 I know rails uses simple stateless controllers for instance so perhaps you guys know how to best solve this problem. 我知道Rails例如使用简单的无状态控制器,所以也许你们知道如何最好地解决这个问题。 I can best describe the problem with java/spring mvc which is the implementation - forgive the java jargon. 我可以用实现最好的方式来描述java / spring mvc的问题-原谅Java行话。

The issue 问题

We are having trouble coming up with a satisfactory way of performing stateless-to-stateful handover in spring mvc. 我们很难想出在Spring MVC中执行无状态到有状态切换的令人满意的方法。 In essence given a structure like: 本质上给定的结构如下:

Model: Unit With the states: withdrawn, available, unavailable And the operations: getOutline() and getHelp() 模型: Unit状态:撤回,可用,不可用操作: getOutline()getHelp()

Controller: UnitController with operations: displayOutline() and displayHelp() 控制器: UnitController ,操作: displayOutline()displayHelp()

We need a way to check the state of the unit before we execute the operation displayOutline() (because the unit itself may be withdrawn and so the user should be forwarded to a withdrawn page). 在执行操作displayOutline()之前,我们需要一种检查单元状态的方法(因为单元本身可能已撤出,因此用户应转发到撤回的页面)。

We have tried to do this a number of ways including: 我们尝试了多种方法来做到这一点,包括:

The dead simple way (any language) 简单的死法(任何语言)

All methods in the controller that require an 'available' state unit call a method isAvailable() in the first line of its implementation. 控制器中所有需要“可用”状态单元的方法都在其实现的第一行中调用方法isAvailable()。 Obviously there lots of replication here, it reeks. 显然这里有很多复制。

The AOP way (Java specific) AOP方式(特定于Java)

An @Around advice can be created called UnitAccess which does the check and reroutes the control flow (ie instead of calling proceed() which would invoke the underlying method it calls another method on the controller). 可以创建一个名为UnitAccess的@Around通知,该建议进行检查并重新路由控制流(即,不是调用proced(),后者会调用其在控制器上调用另一个方法的基础方法)。 This seems like a hack and not really what AOP if for, it does remove the replication but adds complexity and reduces transparency. 这看起来像是黑客,而不是真正的AOP,它确实删除了复制,但增加了复杂性并降低了透明度。

An Interceptor (Provided by servlet architecture but probably doable in other frameworks) 拦截器(由Servlet体系结构提供,但可能在其他框架中可行)

Which checks the unit state and essentially changes the actual URL call. 它检查单元状态并从本质上更改实际的URL调用。 Again this does not seem right. 同样,这似乎不正确。 We don't like the idea of invoking model logic before getting to a controller. 我们不喜欢在进入控制器之前调用模型逻辑的想法。

We have thought about 我们已经考虑过

Command Pattern 命令模式

Creating a command pattern structure which (with the use of inheritance) can return a withdrawn view or valid displayOutline view. 创建一个命令模式结构(使用继承)可以返回撤回的视图或有效的displayOutline视图。 As the execute method will perform the checks in a super() call and the specific logic inside the concrete commands. 由于execute方法将在super()调用中以及具体命令中的特定逻辑中执行检查。 Ie creating a object structure like 即创建一个像这样的对象结构

DisplayOutlineCommand extends UnitCommand

    public void execute(){
        super();
        // must be ok, perform getOutline()
    }

And finally, using a custom Exception 最后,使用自定义异常

Calling getAvailableUnit() on a service level object which will do the checks for availability, etc before returning the unit. 在服务级别对象上调用getAvailableUnit() ,该对象将在返回单元之前进行可用性检查等。 If the unit is withdrawn then it will throw a UnitWithdrawnException which could be caught by the servlet and handled by returning an appropriate view. 如果撤回了该单元,则它将引发UnitWithdrawnException,该异常可能会被servlet捕获并通过返回适当的视图进行处理。 Were still not convinced. 仍然没有被说服。 We are also not hot on the idea of using an exception for normal flow control. 我们也不热衷于使用异常进行常规流控制。

Are we missing something? 我们错过了什么吗? Is there an easy way to do this under spring/another stateless controller framework? 在spring /另一个无状态控制器框架下有没有简单的方法可以做到这一点?

Maybe I'm missing the point, but why should a user come to the controller if the Unit is withdrawn? 也许我错过了要点,但是如果撤回部队,为什么用户应该来找控制器?

I would argue it is best to ensure that normally pages don't link to a controller that require the Unit to be 'OK', if that Unit is not 'OK'. 我认为最好是确保正常页面不会链接到要求Unit为“ OK”的控制器,如果该Unit不是“ OK”的话。 If the state of the Unit changes between the time the referring page is rendered and the actual call comes in to the controller (it is not longer 'OK'), then the use of an exception to handle that event seems perfectly fine to me (like having an exception when an optimistic locking error occurs). 如果单元的状态在呈现引用页面与实际调用之间发生更改(不再是“ OK”),那么使用异常来处理该事件对我来说似乎完全正常(例如发生乐观锁定错误时出现异常)。

Perhaps you haven't described the whole problem, but why not put the check in displayOutline() itself? 也许您没有描述整个问题,但是为什么不将检查放在displayOutline()本身呢? perhaps route to a displayOutlineOrHelp() method, which looks essentially like 也许路由到displayOutlineOrHelp()方法,该方法本质上类似于

ModelAndView displayOutlineOrHelp(...)  {
    Unit unit = ... //code to get the unit the request refers to

    return unit.isAvailable() ? displayOutline(...) : displayHelp(...);   
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM