一个小的调用本地EJB的作业,不难,接口什么的非常好写,但是由于网上的jndi千奇百怪,而且这个东西太老了,我上课也没听,导致只能搞个远程的,本地的概念什么的都不是很清楚,所以弄了很久。(环境:JDK7+eclipse+JBOSS7.1)
一会有空总结一下,主要参考老师的PPT(慕课网站 http://mooc1.chaoxing.com/course/203574850.html)和这两篇博客。
- https://blog.csdn.net/u010924834/article/details/51114428
- https://blog.csdn.net/u010924834/article/details/51123010
非常感谢(之前的文章编辑完不能保存和发布,只好重新发一个)
一、调用远程接口
①新建一个EJB 项目,创建无状态会话Bean远程接口及其实现类,然后Run on server(这时可以在控制台上看到JBOSS的信息,最后应该有Deploy "XXX.jar"),这是前提
此处仅仅放一下Reomote接口的代码,示意一下,因为这个包名很长,怕后面大家有点乱
package javaee.ejb.stateless;
import javax.ejb.Remote;
@Remote
public interface HelloBeanRemote {
public String sayHello(String name);
}
注意远程接口的含义是客户端和服务器不在一个JVM上等,反正就是不在一起。所以我们使用一个普通的JavaApplication进行测试。
新建一个Java Project,新建一个带有main函数的public class。
main函数里面调用EJB的过程将使用JNDI和EJB API实现,见下方。
1.使用EJB CLIENT API调用(推荐)
先在此谈一下最重要的配置动作:
(1) 把jboss-client.jar加入到项目(右键工程-Build Path –Configure Build Path-ADD external JARS ),这个在JBOSS安装目录/bin/client下
(2)把远程接口类的.java文件按照原样拷贝到src中,即直接报EJB项目中remote接口的文件所在的包一起拷贝过来,然后删掉没有用的文件(这步的作用和链接1中的导入jar包是一样的)
(3)在src下新建jndi.properties文件,内容如下:
endpoint.name=client-endpoint
remote.connectionprovider.create.options.org.xnio.Options.SSL_ENABLED=false
remote.connections=default
remote.connection.default.host=localhost
remote.connection.default.port=4447
remote.connection.default.connect.options.org.xnio.Options.SASL_POLICY_NOANONYMOUS=false
remote.connection.default.username=admin
remote.connection.default.password=123456
注意username和password换成你自己的
(4)main函数所在类的代码(具体含义可以参考注释和链接1,链接1中讲得更好)
package statelessClient;
import java.util.Hashtable;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javaee.ejb.stateless.HelloBeanRemote;//远程接口
public class HelloWorldClient {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
Hashtable<String, String> jndiProperties = new Hashtable<String, String>();
jndiProperties.put(Context.URL_PKG_PREFIXES, "org.jboss.ejb.client.naming");
try {
Context context = new InitialContext(jndiProperties);
final String appName = "";
final String moduleName = "SessionEJB";//EJB项目名字
final String distinctName = "";
System.out.println("ejb:" + appName + "/" + moduleName + "/" + distinctName + "/HelloBean!javaee.ejb.stateless.HelloBeanRemote");
Object obj = context.lookup("ejb:" + appName + "/" + moduleName + "/" + distinctName + "/HelloBean!javaee.ejb.stateless.HelloBeanRemote");
//此处!后是带包名的remote接口,/和!之间的remote会话bean
HelloBeanRemote hwr =
(HelloBeanRemote)obj;
String say = hwr.sayHello("Jilin University");
System.out.println(say);
} catch (NamingException e) {
e.printStackTrace();
}
}
}
2.使用通用JNDI (配置动作和上面基本一样,需要buildpath、拷贝remote接口类的完整路径、jndi.proporties)
main函数:
package statelessClient;
import java.util.Properties;
import javaee.ejb.stateless.HelloBeanRemote;
import javax.naming.Context;
import javax.naming.InitialContext;
public class HelloWorldClient2 {
public static void main(String[] args) {
// TODO Auto-generated method stub
Properties prop = new Properties();
//服务器的命名和目录管理地址
prop.put(Context.PROVIDER_URL, "remote://localhost:4447");
//初始化上下文环境工厂
prop.put(Context.INITIAL_CONTEXT_FACTORY, org.jboss.naming.remote.client.InitialContextFactory.class.getName());
//用户验证
prop.put(Context.SECURITY_PRINCIPAL,System.getProperty("username","test"));
prop.put(Context.SECURITY_CREDENTIALS,System.getProperty("password","123456"));
try{
Context ctx = new InitialContext(prop);
Object obj = ctx.lookup("SessionEJB/HelloBean!javaee.ejb.stateless.HelloBeanRemote");
/*实际访问的是java:jboss/exported/SessionEJB/HelloBean!javaee.ejb.stateless.HelloBeanRemote
*/
HelloBeanRemote hwr = (HelloBeanRemote)obj;
String say = hwr.sayHello("Jilin University");
System.out.println(say);
} catch (Exception e) {
e.printStackTrace();
}
}
}
远程接口的就到此结束,下面我们说一下怎么调用本地接口,同样是两种方法,一种是JNDI,一种是依赖注入(推荐)
同样首先要创建一个EJB项目,实现local接口,run on server。
此时我们要在WEB项目上测试,保证可以直接调用local接口
1、依赖注入方式(使用servlet作为示例)
相关配置动作:在新建的web project中,将local接口的完整路径拷贝过来,这个动作与上面的远程调用动作相同。注意只需要这个就可以了
然后新建一个Servlet,代码如下:(本地接口里的方法是获取当前时间,所以运行之后可以看到当前时间)
package EJBServletTest;
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;
/**
* Servlet implementation class TestServlet
*/
@WebServlet("/TestServlet")
public class TestServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
@EJB javaee.ejb.stateless.TimeBeanLocal tb;
/**
* @see HttpServlet#HttpServlet()
*/
public TestServlet() {
super();
// TODO Auto-generated constructor stub
}
/**
* @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
*/
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
this.doPost(request, response);
}
/**
* @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
*/
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
PrintWriter out=null;
try{
response.setContentType("text/html;charset=UTF-8");
out = response.getWriter();
out.println("<html>");
out.println("<head>");
out.println("<title>依赖注入无状态会话Bean本地接口</title>");
out.println("</head>");
out.println("<body>");
String str=tb.printTime();
out.print("<br>通过依赖注入调用本地接口EJB<br>"+str+"<br>");
}catch(Exception e){
e.printStackTrace();
out.print("<br>本地接口调用失败!");
}finally{
out.println("</body>");
out.println("</HTML>");
out.flush();
out.close();
}
}
}
这个Servlet的代码完成之后,直接右键该文件-run on server即可
2、通过JNDI方式
我们以一个index.jsp文件为例。
相关配置动作:右键已经创建好的local接口EJB项目-export-EJB JAR FILE,起名字选择一个位置保存,然后将这个JAR包拷贝到当前web项目的WEBCONTENT-WEB INF-lib目录下。
jsp文件的代码:
<%@ page language="java" import="javax.naming.*, javaee.ejb.stateless.*,java.util.*" pageEncoding="gb2312"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=gb2312">
<title>JNDI无状态会话Bean本地接口</title>
</head>
<body>
<!-- 通过接口调用类 -->
<%
System.out.println("1111");
try{
InitialContext ctx = new InitialContext();
final String appName = "";
final String moduleName = "homework2_client";
final String distinctName = "";
//实现类名
final String beanName = "TimeBean";
//out.println(beanName);
//接口类名
final String viewClassName = TimeBeanLocal.class.getName();
//out.println(viewClassName);
String jndi = "java:app/"+moduleName+"/" + beanName + "!" + viewClassName;
// String jndi = "java:module/" + beanName + "!" + viewClassName;
//out.println(jndi);
TimeBeanLocal tb = (TimeBeanLocal)ctx.lookup(jndi);
//TimeBeanLocal tb = (TimeBeanLocal)ctx.lookup("java:module/TimeBean!javaee.ejb.stateless.TimeBeanLocal");
String str=tb.printTime();
out.print("<br>通过JNDI调用本地接口EJB<br>"+str+"<br>");
}catch(Exception e){
System.out.println(e.getMessage());
out.print("<br>本地接口调用失败!");
}
%>
</body>
</html>
程序里面的JNDI的路径可以是多种形式,如java:/app java:/module等。完成之后右键run on server 即可。此处的路径参考了
链接2,有不懂的地方仔细看看即可
这篇到这里,非常感谢那些有帮助的博客,thankyou。
对了,我室友的jsp在执行到context时会出现加载模块(module)失败,无法初始化上下文工厂,这个网上很少有这个错误,但是重写了EJB项目和web项目就可以正常使用了,不是代码的原因