我正在关注一本来自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有一点熟悉,但这已经很老了。
(这个答案与我上面的评论有关。)
在容器不自动管理的对象中,可以通过获取对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
您可以创建一个接口并添加@Remote annotation:
@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、jaxr/jaxws工件),请使用@EJB(可能需要添加mappedName)
- 如果客户端在ejb容器(即:独立的java应用程序)之外进行调用,则可以使用JNDI查找
- 如果通过网络,您可以像web服务(@WebService/@Path)一样公开ejb并使用它……好吧,如果您喜欢的话