【问题标题】:EJBs and Storing Objects in a Data Structure (Map, List, etc)EJB 和在数据结构(映射、列表等)中存储对象
【发布时间】:2009-03-23 21:52:35
【问题描述】:

是否可以在应用服务器正常运行期间将对象存储在数据结构中?基本上我想要一个与此数据结构接口的 EJB,但不需要完整的数据库解决方案。

作为一个例子,我制作了这个虚拟动物对象:

package com.test.entities;

public class Animal implements java.io.Serializable {

    private static final long serialVersionUID = 3621626745694501710L;
    private Integer id;
    private String animalName;

    public Integer getId() {
        // TODO Auto-generated method stub
        return id;
    }   
    public void setId(Integer id){
        this.id=id;
    }
    public String getAnimalName(){
        return animalName;

    }
    public void setAnimalName(String animalName){
        this.animalName=animalName;
    }
}

所以这里是 EJB Remote 接口:

package com.test.beans;

import java.util.Map;

import javax.ejb.Remote;

import com.test.entities.Animal;

@Remote
public interface MapBeanRemote {

    public void addAnimal(Animal a);

    public void removaAnimal(Integer id);

    public Animal getAnimalById(Integer id);

    Map<Integer, Animal> getAllAnimals();

}

这是会话 Bean:

package com.test.beans;

import java.util.ConcurrentHashMap;
import java.util.Map;

import javax.annotation.PostConstruct;
import javax.ejb.Stateless;

import com.test.entities.Animal;

@Stateless(mappedName="ejb/MapBean")
public class MapBean implements MapBeanRemote{

    Map<Integer, Animal> animalStore;

    @PostConstruct
    public void initialize(){
        animalStore = new ConcurrentHashMap<Integer,Animal>();
    }

    @Override
    public void addAnimal(Animal a) {
        if(a.getId()!=null){
            animalStore.put(a.getId(), a);
        }
    }

    @Override
    public Animal getAnimalById(Integer id) {
        return animalStore.get(id);
    }

    @Override
    public void removaAnimal(Integer id) {
        animalStore.remove(id);

    }

    @Override
    public Map<Integer, Animal> getAllAnimals() {
        return animalStore;
    }

}

所以基本上我希望任何想要操作 Animal Map 的客户端都通过这个 EJB 并让每个客户端访问相同的对象 Map。

这个例子不够好。过了一会儿,所有的动物都被删除了(我假设当 EJB 从 bean 池中被替换时)这会以某种方式作为资源注入吗?

【问题讨论】:

    标签: java jboss jakarta-ee ejb-3.0 ejb


    【解决方案1】:

    这可以通过将 Map 放入 Singleton 并从 bean 访问此单例来完成。这样,所有 EJB 实例都有一个实例(因为它们共享相同的类加载器)。不同 EAR 中的不同 Session bean 将不起作用,因为它们每个都有自己的类加载器,但这似乎不是您的方案。

    您现有的 ConcurrentHashMap 用法足以处理您的大多数情况,但您仍然需要围绕 addAnimal 方法进行同步,因为您需要地图在两个方法调用之间保持一致。

    【讨论】:

      【解决方案2】:

      新的 EJB 3.1 规范提供了新类型的 bean - 单例 bean - 这正是您所需要的。我知道的唯一部分支持 EJB 3.1 的实现是 Apache OpenEJB 3.1。它包括 Singleton bean,但我还没有使用它们。

      【讨论】:

        【解决方案3】:

        这是一个无状态会话 bean。顾名思义,您不应该在这样的 bean 中持有任何类型的状态。 EJB 容器可以与 bean 的多个实例一起工作以满足并发请求。如何同步所有实例的 Lists 数据?我觉得没有办法做到这一点。

        在我看来,将这样的 List 维护到提供业务逻辑的会话 bean 中,甚至违反了业务层的概念。您必须自己处理事务和并发写入。

        为什么不在客户端保存动物列表?我认为这将是更好的方法。

        【讨论】:

        • 我同意违反业务层的概念。这就是为什么,理想情况下,我可以将 Map 作为某种资源注入。我需要在服务器端拥有 Map 的能力,因为我将 Java SE 应用程序硬塞到 Java EE 上下文中。
        • 一个邪恶的想法:使用一个静态类和一个所有会话 bean 都使用的静态 Map,并希望 Map 的同步能够很好地实现,并且不会影响容器的工作。
        【解决方案4】:

        我认为最好的办法是将数据结构完全移出 EJB 并将其存储为静态数据结构。您可能是正确的,因为 EJB 正在池中,所以您的对象正在被擦除。

        请注意,根据您实现对数据结构的访问方式,您需要同步访问以确保线程安全。

        如果您想在 EJB 中维护状态,请考虑查看有状态会话 bean。此外,如果您确实想查看 bean 何时被销毁,您可以覆盖 ejbremove 方法,我忘记了 Java 5 的注释。

        卡尔

        【讨论】:

        • 谢谢。有状态会话 bean 仅用于(据我了解)维护特定客户端的状态,而不是用于整个应用服务器。
        猜你喜欢
        • 1970-01-01
        • 2019-03-14
        • 2018-09-03
        • 2010-12-19
        • 2020-09-27
        • 1970-01-01
        • 1970-01-01
        • 2023-01-14
        • 2021-11-17
        相关资源
        最近更新 更多