繁体   English   中英

如何远程访问@Stateless @LocalBean

[英]how to access a @Stateless @LocalBean remotely

我正在跟踪来自packt的EJB食谱 ,其中包含以下代码:

package packt;

import javax.ejb.Stateless;
import javax.ejb.LocalBean;

//@Stateless
@LocalBean
@Stateless(mappedName="salutationBean")
public class Salutation {
    public String getFormalSalutation(String name) {
        return "Dear " + name;
    }
    public String getInformalSalutation(String name) {
        return "Hi " + name;
    }
}

如何从不扩展HttpServlet的类访问此bean? servlet本身运行良好:

package servlet;

import java.io.IOException;
import java.io.PrintWriter;
import javax.ejb.EJB;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import packt.Salutation;

@WebServlet(urlPatterns = {"/SalutationServlet"})
public class SalutationServlet extends HttpServlet {

    @EJB
    private Salutation salutation;

    protected void processRequest(HttpServletRequest request,
            HttpServletResponse response)
            throws ServletException, IOException {
        response.setContentType("text/html;charset=UTF-8");
        PrintWriter out = response.getWriter();
        try {
            out.println("<html>");
            out.println("<head>");
            out.println("<title>Servlet SalutationServlet</title>");
            out.println("</head>");
            out.println("<body>");
            out.println("<h1>"
                    + salutation.getFormalSalutation("Sherlock Holmes")
                    + "</h1>");
            out.println("</body>");
            out.println("</html>");
        } finally {
            out.flush();
            out.close();
        }
    }

    @Override
    protected void doGet(HttpServletRequest request,
            HttpServletResponse response)
            throws ServletException, IOException {
        processRequest(request, response);
    }

    @Override
    protected void doPost(HttpServletRequest request,
            HttpServletResponse response)
            throws ServletException, IOException {
        processRequest(request, response);
    }
}

并可以从指定的URL查看:

thufir@dur:~$ 
thufir@dur:~$ lynx http://localhost:8080/SalutationApplication-war/SalutationServlet -dump
                              Dear Sherlock Holmes


thufir@dur:~$ 

当前结构:

thufir@dur:~/NetBeansProjects$ 
thufir@dur:~/NetBeansProjects$ tree SalutationApplication/
SalutationApplication/
├── build.xml
├── nbproject
│   ├── ant-deploy.xml
│   ├── build-impl.xml
│   ├── genfiles.properties
│   ├── private
│   │   └── private.properties
│   ├── project.properties
│   └── project.xml
├── SalutationApplication-ejb
│   ├── build.xml
│   ├── nbproject
│   │   ├── ant-deploy.xml
│   │   ├── build-impl.xml
│   │   ├── genfiles.properties
│   │   ├── private
│   │   │   └── private.properties
│   │   ├── project.properties
│   │   └── project.xml
│   └── src
│       ├── conf
│       │   └── MANIFEST.MF
│       └── java
│           └── packt
│               └── Salutation.java
├── SalutationApplication-war
│   ├── build.xml
│   ├── nbproject
│   │   ├── ant-deploy.xml
│   │   ├── build-impl.xml
│   │   ├── genfiles.properties
│   │   ├── private
│   │   │   └── private.properties
│   │   ├── project.properties
│   │   └── project.xml
│   ├── src
│   │   ├── conf
│   │   │   └── MANIFEST.MF
│   │   └── java
│   │       └── servlet
│   │           └── SalutationServlet.java
│   └── web
│       ├── index.html
│       └── WEB-INF
└── src
    └── conf
        └── MANIFEST.MF

20 directories, 27 files
thufir@dur:~/NetBeansProjects$ 

现在,它只是一个本地bean很好,但是最终我希望Salutation.java bean可以远程访问。 我对Head First EJB的EJB已有一定的了解,但这已经很老了。

您可以创建一个界面并添加@Remote批注:

@Remote
public interface MyRemoteInterface {
    void myRemoteMethod();    
}

之后,您可以在EJB中实现此接口:

@LocalBean
@Stateless(mappedName="salutationBean")
public class Salutation implements MyRemoteInterface {
    public String getFormalSalutation(String name) {
        return "Dear " + name;
    }

    public String getInformalSalutation(String name) {
        return "Hi " + name;
    }

    @Override
    public void myRemoteMethod(){
        // only this method will be visible in a remote interaction
    }
}

显然,您需要像这样将其注入客户端

@EJB
MyRemoteInterface remote;

提示:不要让远程客户端访问不需要的内容。


编辑:取决于在哪里客户端:

  • 如果您的客户端使用的是Java组件(cdi对象,其他EJB,servlet,jaxrs / jaxws工件),则使用@EJB(可能需要添加mapdName)
  • 如果您的客户在ejb容器之外调用(即,独立的Java应用程序),则可以使用JNDI查找
  • 如果跨网络,则可以像网络服务(@ WebService / @ Path)一样公开ejb并使用它……如果愿意的话。

(此答案与我的上述评论相关。)

在容器不自动管理的对象中,您可以通过获取对BeanManager的引用来初始化手动注入,并让CDI容器为您完成所有工作。 这适用于您还可以注入到托管bean中的所有内容,但是您不必执行复杂的JNDI查找。

public class CDIUtils {

    public static BeanManager beanManager() {
        try {
            return (BeanManager) new InitialContext().lookup("java:comp/BeanManager");
        } catch (NamingException e) {
            throw new IllegalStateException("Unable to obtain CDI BeanManager", e);
        }
    }

    public static void makeManagedStatic(Object obj) {
        BeanManager bm = beanManager();
        makeManaged(obj, bm);
    }

    public static void makeManaged(Object obj, BeanManager beanManager) {
        Class objClass = (Class) obj.getClass();
        AnnotatedType annotatedType = beanManager.createAnnotatedType(objClass);
        InjectionTarget injectionTarget = beanManager.createInjectionTarget(annotatedType);
        CreationalContext context = beanManager.createCreationalContext(null);
        injectionTarget.inject(obj, context);
    }

}

假设这是您的客户:

public class MyClient {
    @EJB private MyEJB myEJB;
    public void run() {
        if (myEJB == null)
            CDIUtils.makeManagedStatic(this);
        myEJB.someMethod();
    }
}

您也可以简单地在创建时对其进行管理,这将测试省去了null

MyClient client = new MyClient();
CDIUtils.makeManagedStatic(client);
client.run(); // etc

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM