下面开始我的EJB之旅
学习任何一门技术之前,都必须简单的了解一下该技术的用途的优缺点。所以首先我们来看一下摘自百度百科上面对EJB的定义和说明
==========================================================================
EJB是sun的服务器端组件模型,最大的用处是部署分布式应用程序当然,还有许多方式可以实现分布式应用,类似微软的.net技术。凭借java跨平台的优势,用EJB技术部署的分布式系统可以不限于特定的平台。EJB (Enterprise JavaBean)是J2EE的一部分,定义了一个用于开发基于组件的企业多重应用程序的标准。其特点包括网络服务支持和核心开发工具(SDK)。 在J2EE里,Enterprise Java Beans(EJB)称为Java 企业Bean,是Java的核心代码,分别是会话Bean(Session Bean),实体Bean(Entity Bean)和消息驱动Bean(MessageDriven Bean)。
一个技术规范:EJB 从技术上而言不是一种"产品" ,EJB 是一种标准描述了构建应用组件要解决的:
可扩展 (Scalable)
分布式 (Distributed)
事务处理 (Transactional)
数据存储 (Persistent)
安全性 (Secure)
===========================================================================
里面说得很多,其实我理解和关注的却并不多。首先EJB是一个服务器端的组件模型,可以部署分布式应用程序。我主要比较关注部署分布式应用程序。说实话,什么是分布式应用程序,我也是似懂非懂的,所以希望通过学习EJB更深入的了解一下。然后就是关注EJB要解决的问题了:可扩展、分布式、事务处理、数据存储和安全性。我相信,学习完后能够把这几个部分搞懂就差不多了
说起分布式组件,我相信大家会想到微软的DCOM技术,它们的区别在哪呢?跨平台问题?其他?不懂!
远程调用,和webservice有什么区别呢?摸索中
还有一点,相信很多人和我有共同的疑问。都说EJB是重量级的复杂的,然后又有很多声音说spring将会替代它(当然我们这里学习的EJB3.0以上版本的,对于老版本我们这里就不关注了),我不知道这是怎么回事。
带着这么多疑问,我们开始EJB吧
隔了这么久,总觉得难以下手。哈哈,其实也不是那么复杂。下面我们就开发部署一个无状态的提供本地接口和远程接口的Session Bean吧。
首先开发服务端,服务端必须依赖Ejb的API,首先定义本地接口ILocalCalculator.java
package stateless.ejb;
public interface ILocalCalculator {
double add(double x,double y);
double minus(double x,double y);
double mutilply(double x,double y);
double devide(double x,double y);
}
package stateless.ejb;
public interface IRemoteCalculator extends ILocalCalculator {
double power(double x,int n);
}
实现一个无状态的Session Bean,CalculatorBean.java
package stateless.ejb;
import javax.ejb.Local;
import javax.ejb.Remote;
import javax.ejb.Stateless;
@Stateless
@Remote({IRemoteCalculator.class})
@Local({ILocalCalculator.class})
public class CalculatorBean implements IRemoteCalculator {
@Override
public double add(double x, double y) {
return x+y;
}
@Override
public double devide(double x, double y) {
if(y==0)
{
return 0;
}
return x/y;
}
@Override
public double minus(double x, double y) {
return x-y;
}
@Override
public double mutilply(double x, double y) {
return x*y;
}
@Override
public double power(double x,int n) {
double result=1;
for(int i=1;i<=n;i++)
{
result*=x;
}
return result;
}
}
接下来就是客户端调用了,开发EjbBean.java
package bean;
import java.util.Properties;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import stateless.ejb.ILocalCalculator;
import stateless.ejb.IRemoteCalculator;
public class EjbBean {
/**
* 通过调用ejb服务计算结果
* @param x
* @param y
* @param operator
* @param type 1-local,2-remote
* @return
*/
public double Calc(double x,double y,String operator,int type)
{
Properties props = new Properties();
props.setProperty("java.naming.factory.initial", "org.jnp.interfaces.NamingContextFactory");
props.setProperty("java.naming.provider.url", "localhost:1099");
InitialContext ctx =null;
try {
ctx = new InitialContext(props);
if(type==1)
{
ILocalCalculator calculator=(ILocalCalculator)ctx.lookup("CalculatorBean/local");
if(operator.equals("+"))
{
return calculator.add(x, y);
}
else if(operator.equals("-"))
{
return calculator.minus(x, y);
}
else if(operator.equals("*"))
{
return calculator.mutilply(x, y);
}
else if(operator.equals("/"))
{
return calculator.devide(x, y);
}
}
else if(type==2)
{
IRemoteCalculator calculator=(IRemoteCalculator)ctx.lookup("CalculatorBean/remote");
if(operator.equals("+"))
{
return calculator.add(x, y);
}
else if(operator.equals("-"))
{
return calculator.minus(x, y);
}
else if(operator.equals("*"))
{
return calculator.mutilply(x, y);
}
else if(operator.equals("/"))
{
return calculator.devide(x, y);
}
else if(operator.equals("power"))
{
return calculator.power(x, (int)y);
}
}
} catch (NamingException e) {
e.printStackTrace();
}
return 0.0001;
}
}
然后就是开发service,EjbService.java
package service;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Vector;
import javax.mail.MessagingException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import bean.EjbBean;
import bean.EmailBean;
import entity.Email;
public class EjbService {
private HttpServletRequest req;
private HttpServletResponse res;
public HttpServletRequest getReq() {
return req;
}
public void setReq(HttpServletRequest req) {
this.req = req;
}
public HttpServletResponse getRes() {
return res;
}
public void setRes(HttpServletResponse res) {
this.res = res;
}
public EjbService()
{
}
public EjbService(HttpServletRequest req,HttpServletResponse res)
{
this.req=req;
this.res=res;
}
public void calc(double x,double y,String operator,int type)
{
EjbBean bean=new EjbBean();
double result = bean.Calc(x, y, operator, type);
try {
PrintWriter out =this.res.getWriter();
out.print(result);
} catch (IOException e) {
e.printStackTrace();
}
}
}
package servlet;
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import service.EjbService;
import service.EmailService;
public class EjbServlet extends HttpServlet {
private EjbService service;
/**
* Constructor of the object.
*/
public EjbServlet() {
super();
}
/**
* Destruction of the servlet.
*/
public void destroy() {
super.destroy(); // Just puts "destroy" string in log
// Put your code here
}
/**
* The doGet method of the servlet.
*
* This method is called when a form has its tag value method equals to get.
*
* @param request the request send by the client to the server
* @param response the response send by the server to the client
* @throws ServletException if an error occurred
* @throws IOException if an error occurred
*/
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("text/html");
response.setCharacterEncoding("UTF-8");
request.setCharacterEncoding("UTF-8");
service=new EjbService(request,response);
String action="";
action=request.getParameter("action");
if(action==null || action.equals(""))
{
return;
}
//集中处理请求类型
if(action.toUpperCase().equals("CALCRESULT"))
{
double x=Double.parseDouble(request.getParameter("x_value"));
double y=Double.parseDouble(request.getParameter("y_value"));
String operator=request.getParameter("operator");
String method=request.getParameter("method");
int type=1;
if(method.equals("remote"))
{
type=2;
}
service.calc(x, y, operator, type);
}
}
/**
* The doPost method of the servlet.
*
* This method is called when a form has its tag value method equals to post.
*
* @param request the request send by the client to the server
* @param response the response send by the server to the client
* @throws ServletException if an error occurred
* @throws IOException if an error occurred
*/
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request,response);
}
/**
* Initialization of the servlet.
*
* @throws ServletException if an error occurs
*/
public void init() throws ServletException {
// Put your code here
}
}
EJB客户端
function calc()
{
var x=$("#x").val();
var y=$("#y").val();
//必须引入支持select标签的jquery扩展 jquery.select.js
var oper=$("#operator").getSelectedValue();
var type="local";
if(oper=="power")
{
type="remote";
}
$.get("EjbServlet",{action:"CALCRESULT",x_value:x,y_value:y,operator:oper,method:type},function(data)
{
$("#calc_result").val(data);
});
}
总结:
1、在开发中遇到一个问题,报错信息为
msg:javax.naming.NameAlreadyBoundException: remote
仔细琢磨了一下,发现在导出jar文件给客户端使用时,不能包含实现进去,只能包含提供的接口。在现实开发部署中也正是这样,提供给客户端使用的肯定只有接口,不然EJB就失去了它的意义。而且根据这个错误提示,应该是服务器和客户端在同一台电脑上部署执行才会出现这个错误。猜想是这样的,不知道是否正确
2、这里开发的无状态的Session Bean。那有状态的Session Bean和这个有什么区别呢。
其实有状态的就是会记录用户的状态。举个例子。比如说服务端EJB中有一个成员变量total,实现的功能是每次登陆时加1操作,无状态的就是每个用户登陆一次都会对这个数据进行加1,而有状态的是会分别记录每个用户登陆的次数,而不是所有用户的总登陆次数,现在理解的它们的区别就在这里。其它的待挖掘。如果你有什么更好的理解,请不吝赐教。