Struts2中的拦截器线程是否为UNsafe?

我知道Struts2 Action类是线程安全的,因为操作放在Value Stack中。 值栈依次是Action Context的一部分。 由于Action Context是线程本地的,因此存储在Action Context(包括值栈)中的值对于每个线程都是唯一的。 因此,Actions是线程安全的。

但考虑一下拦截器:它们非常有用,它们为程序员完成所有繁琐的小工作……比如validation,获取参数值等等。但需要考虑的是:拦截器可以在多个请求之间共享。 那么这会使拦截器线程不安全吗?

考虑到这个问题,我试图在网上浏览一些与此问题相关的好文章。 我发现了一篇非常好的文章,他们已经清楚地提到了一个例子拦截器如何不是线程安全的。

该网页是: http : //www.bullraider.com/java/struts2/tutorials/interceptors-and-thread-safety

我从这篇文章中得知,拦截器线程不安全的主要原因是拦截器只创建了一次。 即每个拦截器只有一个对象。 因此,当线程之间共享Interceptor的相同实例时,实例字段不安全。

在文章的最后,提到有些情况,甚至拦截器都是线程安全的。 但他们没有提到任何此类案件。 我在网上冲浪找到答案……但徒劳无功:(

任何人都可以告诉我或给我一个链接,在那里我可以找到如何使拦截器线程安全(或拦截器线程安全时的情况是什么)?

任何不使用实例字段或其他共享状态的Interceptor都是线程安全的:

例如,查看解析HTTP请求参数和cookie,执行日志记录,访问检查,exception处理的所有内置拦截器 :它们不使用实例字段用于可变状态(*),而只是对它们获取的ActionInvocation实例进行操作参数。

(*)有些配置参数的实例字段是在Struts启动时(在单个线程中)设置的,如ExceptionMappingInterceptor ,或者是线程安全的实例字段,如LoggingInterceptorLogger

如果您打算编写自己的Interceptor ,只需使用您传入的ActionInvocation参数以及intercept()方法中的局部变量。 避免让你的拦截方法synchronized或将事物放入synchronized{}块的诱惑 – 这将成为Struts对拦截器的单实例方法的瓶颈。

要回答评论中的问题:

(1)为每个线程创建一个动作实例如何不影响性能?或者它是什么?

使用现代JVM,创建对象的成本可以忽略不计。 如果通过避免昂贵的初始化来保持您的行动轻量化,例如不在操作中创建数据库连接但使用连接池,则应该对性能没有明显影响。

(2)你是否建议不要使用默认的拦截器堆栈,并始终使用自定义拦截器堆栈(其中所有使用实例变量的未使用的拦截器都被删除),以便它是线程安全的?

我不认为使用Struts 2发布和配置的任何默认拦截器都不是线程安全的; 即使他们使用实例字段(因为它们既可以用于配置,也可以用于像Logger一样的线程安全)。

根据我的个人经验,如果你有充分的理由,你应该只触摸/更改拦截器堆栈(内置拦截器的线程安全性不是一个)。 如果你改变堆栈,许多事情会以意想不到的方式表现/破坏 – 运行其中一个内置堆栈,如“default”或“paramPrepareParam”,从长远来看可以节省很多挫败感。 添加自己的自定义拦截器通常比从现有堆栈中删除/重新排列拦截器更具破坏性。

可能相关的是,ScopeInterceptor.java类可能存在线程安全问题: Struts ScopeInterceptor类中的Java线程安全问题?