查看following tutorial上的列表#1,
JAX-RS资源类可以定义为@Stateless或@Singleton。
我的应用程序中有以下代码:
@Stateless
public class VisitDaoImpl implements VisitDao {
@PersistenceContext(name = "MysqlPU")
private EntityManager em;
@Override
public void persist(Visit vist) {
em.persist(vist);
}
}
@ApplicationPath("rest")
public class ApplicationConfig extends Application {
@Override
public Set<Class<?>> getClasses() {
Set<Class<?>> resources = new java.util.HashSet<>();
resources.add(WelcomeResource.class);
return resources;
}
}
//@Singleton
@Stateless
@Path("/Welcome")
public class WelcomeResource {
@EJB
private VisitDao visitDao;
@GET
@Produces(MediaType.TEXT_PLAIN)
public String wellcomeMessage() {
visitDao.persist(new Visit())
return "Welcome";
}
}
正如您所看到的,除了Dao bean之外,我的资源类中没有状态。
我的问题是:
谢谢。
答案 0 :(得分:3)
我认为@Stateless如果要对数据库或其他影响状态的方法执行写操作。
多个线程(客户端)必须等待单例变为可用,因为默认锁定是在singleton-ejbs中写入。
使用@Lock注释单例类指定所有 单例的业务方法和任何超时方法都将使用 指定锁类型,除非他们用a显式设置锁类型 方法级@Lock注释。如果没有@Lock注释 应用单例类,默认锁类型@Lock(WRITE) 所有业务和超时方法。
在示例中,@ Path-ejb和数据库之间有一个ejb-dao。这表明您可以更改为@Singleton并在商务方法上使用@Lock(READ)(不知道为什么有人想尝试)。
但我不认为这是安全的,因为相同的ejb-dao-instance将用于客户端完成的所有并发调用,DAO持有的EntityManager不是线程安全的:
应用程序需要时使用应用程序管理的实体管理器 访问未使用JTA传播的持久性上下文 特定持久性中跨EntityManager实例的事务 单元。在这种情况下,每个EntityManager创建一个新的,隔离的 持久化上下文。 EntityManager及其关联的持久性 应用程序显式创建和销毁上下文。 他们 也可以在直接注入EntityManager实例时使用 完成,因为EntityManager实例不是线程安全的。 EntityManagerFactory实例是线程安全的。
答案 1 :(得分:1)
在Spring中,无状态对象的推荐方法是Singleton,请查看此question和Spring current guide。 因此,根据spring,你应该使用Singleton,因为你的Rest Service是无状态的。
5.5.2原型范围
非单例,bean部署的原型范围导致了 每次请求特定时,都会创建一个新的bean实例 豆是制作的。也就是说,bean被注入另一个bean或你 通过对容器的getBean()方法调用来请求它。作为一个 规则,使用所有有状态bean和单例的原型范围 无状态豆的范围。
但根据Enterprise Beans Java Tutorial,您可以使用无状态bean或单例,因为它们明确声明&#34; Bean实现了Web服务。&#34;对于无国籍和单身人士。但由于singleton pitfalls,无状态bean可能是更好的选择。最后,在Spring中使用singleton,在JavaEE中使用无状态bean。
答案 2 :(得分:1)
首先关闭:在您的情况下,我认为答案应该是&#34;不是&#34;。您的JAX-RS类也没有理由也是EJB。您仍然可以将EJB注入其中(JAX-RS支持此功能),因此在注入的EJB(例如您的VisitDao
)中执行所有EJB-ey内容(如数据库事务)并使REST类保持简洁 - 记住:single responsibility principle。
@Stateless
或@Singleton
我发现人们倾向于使用@Stateless
。就像在其他答案中解释的那样,这导致EJB池,因为EJB默认假设您的类不是线程安全的,因此它永远不会允许多个线程同时进入单个实例。池的大小由您的应用服务器配置控制。如果更多线程想要访问会话bean而不是池中的可用实例(并且池最大大小不允许创建更多),则线程需要等待。
由于在高流量情况下运行时存在线程争用的风险,而且如果您正确编写会话bean,他们实际上 将是线程安全的,我已经开始转向我将我的EJB注释为@Startup @Singleton ConcurrencyManagement(ConcurrencyManagementType.BEAN)
的模式。这意味着:
顺便说一下,这是Spring中bean的默认设置,我觉得它很好(我有一个Spring背景,所以我可能不会完全不偏不倚)。