我从未使用过JavaEE 6的@Singleton新功能,我想试一试。
我在考虑创建一个单例,只是持有一个密码,将允许应用程序管理员(知道密码的人),访问应用程序的一些内容。
我试图在本教程中实现它,但它不起作用。我是这样做的:
我创建了单例bean:
@Singleton
@Startup
@TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
public class AdminAcountEJB implements IAdminAcountEJB {
private String password;
@PostConstruct
public void init() {
password = "password";
}
@Lock(LockType.READ)
public String getPassword() {
return password;
}
}
我提取了一个接口
public interface IAdminAcountEJB {
public abstract String getPassword();
}
然后我尝试使用@EJB在托管bean中注入单例
@Named("managementBB")
@SessionScoped
public class ManagementBB implements Serializable{
@EJB
private IAdminAcountEJB managementEJB;
private String input;
private boolean authorized;
public String seeWhatsUp() {
if(input.equals(managementEJB.getPassword())) {
authorized = true;
return "manage?faces-redirect=true;";
}
return "index?faces-redirect=true;";
}
//Get set methods...
}
我做的最后一件事是创建一些标记,在输入正确的密码时显示:
<h:form rendered="#{managementBB.authorized == false}">
<h:inputSecret value="#{managementEJB.input}"/>
<h:commandButton value="..." action="#{managementEJB.seeWhatsUp}"/>
</h:form>
<h:form rendered="#{managementBB.authorized}">
CORRECT PASSWORD!!
</h:form>
这一切似乎对我来说都很好,但是当我访问页面时,控制台说:
javax.naming.NameNotFoundException:ejbinterfaces.IAdminAcountEJB # ejbinterfaces。IAdminAcountEJB未找到
我不明白为什么它不工作,这就是我如何注入其他EJB的不是Singletones,但与@Singleton不工作。
-我怎么能解决它?
-我也很想知道你是怎么想的,使用一个单例用于这个目的,你认为是一个好的和安全的想法?
我想问题是,既然你在视图中的EL表达式中引用你的单例,它必须用@Named
注释。如果您只在其他人内部使用您的bean,则没有必要这样做。
关于你的设计,我的两个便士是:
- 由于您使用的是Java EE 6,因此不需要为它指定接口。如果你想要/需要它,不要叫它iso(除非你在苹果工作;-),而是给它一个域名相关的名称。
- 使用允许并发读访问的单例对于核心数据是可以的。只是,我不会将密码放在代码中,而是放入数据库表中,最好是散列,并使用singleton作为启动时读取表的提供者。 单例模式通常会给应用程序带来瓶颈,因为根据定义,单例模式是不可伸缩的。因此,对于您的用例,这是可以的,因为我们可以假设访问速率非常低。另一个可能引入的问题是竞争条件(也不是在你的情况下),如果我们有数据变化,因为我们只有一个实例被并行调用。