【问题标题】:Thread safety in JSFJSF 中的线程安全
【发布时间】:2009-12-24 11:40:35
【问题描述】:

假设我们有 singleton 范围的 Spring bean UserController。

我所有进一步的推理都是基于我的假设,即“单例”范围几乎类似于应用程序范围,即我们只有一个适用于所有用户的实例。如果这是错误的假设,请告诉我。

所以,我们有一个包含多个字段的网络表单。两个用户同时填写此表格。他们都同时按下提交按钮。我们的 UserController 是该表单的支持 bean。

我的问题:是否有可能 UserController 中的部分字段将包含来自第一个用户的值,而其余字段将包含来自第二个用户的值?

【问题讨论】:

    标签: java multithreading spring jsf concurrency


    【解决方案1】:

    在 MVC 范例中,您可以在应用程序范围内完美地拥有一个控制器(例如默认情况下已经是 Servlet),代表类只应该包含与请求范围相关联的字段变量。您应该在方法块中声明它们。

    因此不是例子

    public class Controller {
        private SomeObject field; // Not threadsafe as this will be shared among all requests!
    
        public void control(Request request, Response response) {
            this.field = request.getSomething();
        }
    }
    

    但更是如此

    public class Controller {
        public void control(Request request, Response response) {
            SomeObject field = request.getSomething(); // Threadsafe.
        }
    }
    

    View 和关联的Action 应该在线程本地处理,即在方法块中声明。例如

    public class Controller {
        public void control(Request request, Response response) {
            View view = new View(request, response);
            Action action = ActionFactory.getAction(request);
            action.execute(view);
            view.navigate();
        }
    }
    

    Model 将在 Action 类中处理,也在线程本地范围内。

    public class SomeAction implements Action {
        public void execute(View view) {
            Model model = new Model();
            // ...
        }
    }
    

    在 JSF 上下文中,您实际上只有 Model 类,它在本质上只不过是一个 支持 beanControllerView 部分已经由 JSF 在 FacesServlet 控制请求/响应/生命周期/动作和 UIViewRoot 的帮助下处理,后者是从 JSF 页面构建的。因此,对于请求范围的数据,您的 JSF bean 应该是请求范围的。

    【讨论】:

    • 看起来很明智。在所描述的项目中,我看到的情况与您的第一个代码块一样。
    【解决方案2】:
    1. singleton = application 是对的。 Spring 的WebApplicationContext 存储在ServletContext 中,因此每个应用程序一个。

    2. 您的控制器不应属于singleton 范围。它们应该是requestsession 作用域。您的服务层应包含singletons

    3. 如果你的控制器是singleton,那么很确定整个事情都会搞砸;)

    【讨论】:

    • 感谢您的回答。也许你也知道一些描述这些事情的文章?附言它不是“我的控制器”,我只是在调查现有项目。
    • 这里有一个很棒的 spring+jsf+hibernate 操作方法thelabdude.blogspot.com/2009/04/…
    • 不错的文章,有很多有用的东西。
    【解决方案3】:

    您不应该使用单例/应用程序范围的 bean 来处理每个请求/用户的输入。

    您可能想要一个可以将表单参数绑定到的请求范围 bean,然后如果您需要单例 bean 中的某些内容(比如 EntityManager),则可能会将单例 bean 注入该请求 bean。

    【讨论】:

      猜你喜欢
      • 2011-11-16
      • 1970-01-01
      • 2010-12-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多